Skip to content

Commit f43ea11

Browse files
committed
refactor(examples): consolidate dialog semantics and remove LoginDialog
1 parent c0445d5 commit f43ea11

12 files changed

Lines changed: 151 additions & 115 deletions

File tree

examples/demo/android/app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
}
77

88
android {
9-
namespace = "com.onesignal.example.demo"
9+
namespace = "com.onesignal.example"
1010
compileSdk = flutter.compileSdkVersion
1111
ndkVersion = flutter.ndkVersion
1212

@@ -21,7 +21,7 @@ android {
2121

2222
defaultConfig {
2323
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
24-
applicationId = "com.onesignal.example.demo"
24+
applicationId = "com.onesignal.example"
2525
// You can update the following values to match your application needs.
2626
// For more information, see: https://flutter.dev/to/review-gradle-config.
2727
minSdk = flutter.minSdkVersion

examples/demo/android/app/src/main/kotlin/com/onesignal/example/demo/MainActivity.kt renamed to examples/demo/android/app/src/main/kotlin/com/onesignal/example/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.onesignal.example.demo
1+
package com.onesignal.example
22

33
import io.flutter.embedding.android.FlutterActivity
44

examples/demo/lib/viewmodels/app_viewmodel.dart

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,20 @@ import '../models/notification_type.dart';
66
import '../repositories/onesignal_repository.dart';
77
import '../services/preferences_service.dart';
88

9+
List<MapEntry<String, String>> _mergePairs(
10+
List<MapEntry<String, String>> prev,
11+
Map<String, String> next,
12+
) {
13+
final merged = <String, String>{
14+
for (final e in prev) e.key: e.value,
15+
...next,
16+
};
17+
return merged.entries.toList();
18+
}
19+
20+
List<T> _mergeUnique<T>(List<T> prev, List<T> next) =>
21+
{...prev, ...next}.toList();
22+
923
class AppViewModel extends ChangeNotifier {
1024
final OneSignalRepository _repository;
1125
final PreferencesService _prefs;
@@ -184,10 +198,10 @@ class AppViewModel extends ChangeNotifier {
184198

185199
if (_fetchSequence != requestId) return;
186200

187-
_aliasesList = userData.aliases.entries.toList();
188-
_tagsList = userData.tags.entries.toList();
189-
_emailsList = List.from(userData.emails);
190-
_smsNumbersList = List.from(userData.smsNumbers);
201+
_aliasesList = _mergePairs(_aliasesList, userData.aliases);
202+
_tagsList = _mergePairs(_tagsList, userData.tags);
203+
_emailsList = _mergeUnique(_emailsList, userData.emails);
204+
_smsNumbersList = _mergeUnique(_smsNumbersList, userData.smsNumbers);
191205

192206
if (userData.externalId != null) {
193207
_externalUserId = userData.externalId;

examples/demo/lib/widgets/dialogs.dart

Lines changed: 54 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,16 @@ class _SingleInputDialogState extends State<SingleInputDialog> {
5959
onPressed: () => Navigator.pop(context),
6060
child: const Text('Cancel'),
6161
),
62-
TextButton(
63-
onPressed: _controller.text.isEmpty
64-
? null
65-
: () => Navigator.pop(context, _controller.text),
66-
child: Text(widget.confirmLabel),
62+
Semantics(
63+
identifier: 'singleinput_confirm_button',
64+
container: true,
65+
button: true,
66+
child: TextButton(
67+
onPressed: _controller.text.isEmpty
68+
? null
69+
: () => Navigator.pop(context, _controller.text),
70+
child: Text(widget.confirmLabel),
71+
),
6772
),
6873
],
6974
);
@@ -77,7 +82,6 @@ class PairInputDialog extends StatefulWidget {
7782
final String valueLabel;
7883
final String? keySemanticsLabel;
7984
final String? valueSemanticsLabel;
80-
final String? confirmSemanticsLabel;
8185

8286
const PairInputDialog({
8387
super.key,
@@ -86,7 +90,6 @@ class PairInputDialog extends StatefulWidget {
8690
this.valueLabel = 'Value',
8791
this.keySemanticsLabel,
8892
this.valueSemanticsLabel,
89-
this.confirmSemanticsLabel,
9093
});
9194

9295
@override
@@ -148,8 +151,9 @@ class _PairInputDialogState extends State<PairInputDialog> {
148151
child: const Text('Cancel'),
149152
),
150153
Semantics(
151-
identifier: widget.confirmSemanticsLabel ?? 'confirm_button',
154+
identifier: 'singlepair_confirm_button',
152155
container: true,
156+
button: true,
153157
child: TextButton(
154158
onPressed: _isValid
155159
? () => Navigator.pop(
@@ -283,6 +287,7 @@ class _MultiPairInputDialogState extends State<MultiPairInputDialog> {
283287
],
284288
Semantics(
285289
identifier: 'multipair_add_row_button',
290+
container: true,
286291
button: true,
287292
child: TextButton.icon(
288293
onPressed: _addRow,
@@ -301,6 +306,7 @@ class _MultiPairInputDialogState extends State<MultiPairInputDialog> {
301306
),
302307
Semantics(
303308
identifier: 'multipair_confirm_button',
309+
container: true,
304310
button: true,
305311
child: TextButton(
306312
onPressed: _allValid
@@ -374,69 +380,20 @@ class _MultiSelectRemoveDialogState extends State<MultiSelectRemoveDialog> {
374380
),
375381
),
376382
),
377-
actions: [
378-
TextButton(
379-
onPressed: () => Navigator.pop(context),
380-
child: const Text('Cancel'),
381-
),
382-
TextButton(
383-
onPressed: _selected.isEmpty
384-
? null
385-
: () => Navigator.pop(context, _selected.toList()),
386-
child: Text('Remove (${_selected.length})'),
387-
),
388-
],
389-
);
390-
}
391-
}
392-
393-
// Login dialog
394-
class LoginDialog extends StatefulWidget {
395-
const LoginDialog({super.key});
396-
397-
@override
398-
State<LoginDialog> createState() => _LoginDialogState();
399-
}
400-
401-
class _LoginDialogState extends State<LoginDialog> {
402-
final _controller = TextEditingController();
403-
404-
@override
405-
void dispose() {
406-
_controller.dispose();
407-
super.dispose();
408-
}
409-
410-
@override
411-
Widget build(BuildContext context) {
412-
return AlertDialog(
413-
insetPadding: const EdgeInsets.symmetric(horizontal: 16),
414-
title: const Text('Login User'),
415-
content: SizedBox(
416-
width: double.maxFinite,
417-
child: Semantics(
418-
identifier: 'login_user_id_input',
419-
container: true,
420-
child: AppTextField(
421-
controller: _controller,
422-
decoration: const InputDecoration(labelText: 'External User Id'),
423-
onChanged: (_) => setState(() {}),
424-
),
425-
),
426-
),
427383
actions: [
428384
TextButton(
429385
onPressed: () => Navigator.pop(context),
430386
child: const Text('Cancel'),
431387
),
432388
Semantics(
433-
identifier: 'login_confirm_button',
389+
identifier: 'multiselect_confirm_button',
434390
container: true,
391+
button: true,
435392
child: TextButton(
436-
onPressed: _controller.text.isEmpty
393+
onPressed: _selected.isEmpty
437394
? null
438-
: () => Navigator.pop(context, _controller.text),
439-
child: const Text('Login'),
395+
: () => Navigator.pop(context, _selected.toList()),
396+
child: Text('Remove (${_selected.length})'),
440397
),
441398
),
442399
],
@@ -490,20 +447,35 @@ class _OutcomeDialogState extends State<OutcomeDialog> {
490447
onChanged: (v) => setState(() { if (v != null) _type = v; }),
491448
child: Column(
492449
children: [
493-
RadioListTile<OutcomeType>(
494-
title: const Text('Normal Outcome'),
495-
value: OutcomeType.normal,
496-
contentPadding: EdgeInsets.zero,
450+
Semantics(
451+
identifier: 'outcome_type_normal_radio',
452+
container: true,
453+
button: true,
454+
child: RadioListTile<OutcomeType>(
455+
title: const Text('Normal Outcome'),
456+
value: OutcomeType.normal,
457+
contentPadding: EdgeInsets.zero,
458+
),
497459
),
498-
RadioListTile<OutcomeType>(
499-
title: const Text('Unique Outcome'),
500-
value: OutcomeType.unique,
501-
contentPadding: EdgeInsets.zero,
460+
Semantics(
461+
identifier: 'outcome_type_unique_radio',
462+
container: true,
463+
button: true,
464+
child: RadioListTile<OutcomeType>(
465+
title: const Text('Unique Outcome'),
466+
value: OutcomeType.unique,
467+
contentPadding: EdgeInsets.zero,
468+
),
502469
),
503-
RadioListTile<OutcomeType>(
504-
title: const Text('Outcome with Value'),
505-
value: OutcomeType.withValue,
506-
contentPadding: EdgeInsets.zero,
470+
Semantics(
471+
identifier: 'outcome_type_value_radio',
472+
container: true,
473+
button: true,
474+
child: RadioListTile<OutcomeType>(
475+
title: const Text('Outcome with Value'),
476+
value: OutcomeType.withValue,
477+
contentPadding: EdgeInsets.zero,
478+
),
507479
),
508480
],
509481
),
@@ -795,9 +767,14 @@ class TooltipDialog extends StatelessWidget {
795767
),
796768
),
797769
actions: [
798-
TextButton(
799-
onPressed: () => Navigator.pop(context),
800-
child: const Text('OK'),
770+
Semantics(
771+
identifier: 'tooltip_ok_button',
772+
container: true,
773+
button: true,
774+
child: TextButton(
775+
onPressed: () => Navigator.pop(context),
776+
child: const Text('OK'),
777+
),
801778
),
802779
],
803780
);

examples/demo/lib/widgets/list_widgets.dart

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ class SingleItem extends StatelessWidget {
8181
child: Row(
8282
children: [
8383
Expanded(
84-
child: Text(text, style: Theme.of(context).textTheme.bodyMedium),
84+
child: Semantics(
85+
identifier: '${sectionKey}_value_$text',
86+
container: true,
87+
child: Text(text, style: Theme.of(context).textTheme.bodyMedium),
88+
),
8589
),
8690
if (onDelete != null)
8791
Semantics(
@@ -100,20 +104,28 @@ class SingleItem extends StatelessWidget {
100104

101105
class EmptyState extends StatelessWidget {
102106
final String text;
107+
final String? sectionKey;
103108

104-
const EmptyState({super.key, required this.text});
109+
const EmptyState({super.key, required this.text, this.sectionKey});
105110

106111
@override
107112
Widget build(BuildContext context) {
113+
final label = Text(
114+
text,
115+
style: Theme.of(
116+
context,
117+
).textTheme.bodyMedium?.copyWith(color: AppColors.osGrey600),
118+
);
108119
return Padding(
109120
padding: const EdgeInsets.symmetric(vertical: 12),
110121
child: Center(
111-
child: Text(
112-
text,
113-
style: Theme.of(
114-
context,
115-
).textTheme.bodyMedium?.copyWith(color: AppColors.osGrey600),
116-
),
122+
child: sectionKey == null
123+
? label
124+
: Semantics(
125+
identifier: '${sectionKey}_empty',
126+
container: true,
127+
child: label,
128+
),
117129
),
118130
);
119131
}
@@ -171,7 +183,7 @@ class PairList extends StatelessWidget {
171183
if (items.isEmpty) {
172184
return loading
173185
? LoadingState(sectionKey: sectionKey)
174-
: EmptyState(text: emptyText);
186+
: EmptyState(text: emptyText, sectionKey: sectionKey);
175187
}
176188

177189
return Column(
@@ -221,7 +233,7 @@ class _CollapsibleListState extends State<CollapsibleList> {
221233
if (widget.items.isEmpty) {
222234
return widget.loading
223235
? LoadingState(sectionKey: widget.sectionKey)
224-
: EmptyState(text: widget.emptyText);
236+
: EmptyState(text: widget.emptyText, sectionKey: widget.sectionKey);
225237
}
226238

227239
final showAll = _expanded || widget.items.length <= widget.maxVisible;

examples/demo/lib/widgets/sections/aliases_section.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ class AliasesSection extends StatelessWidget {
4949
valueLabel: 'ID',
5050
keySemanticsLabel: 'alias_label_input',
5151
valueSemanticsLabel: 'alias_id_input',
52-
confirmSemanticsLabel: 'alias_confirm_button',
5352
),
5453
);
5554
if (result != null) {

examples/demo/lib/widgets/sections/tags_section.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ class TagsSection extends StatelessWidget {
4848
title: 'Add Tag',
4949
keySemanticsLabel: 'tag_key_input',
5050
valueSemanticsLabel: 'tag_value_input',
51-
confirmSemanticsLabel: 'tag_confirm_button',
5251
),
5352
);
5453
if (result != null) {

examples/demo/lib/widgets/sections/triggers_section.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ class TriggersSection extends StatelessWidget {
4646
title: 'Add Trigger',
4747
keySemanticsLabel: 'trigger_key_input',
4848
valueSemanticsLabel: 'trigger_value_input',
49-
confirmSemanticsLabel: 'trigger_confirm_button',
5049
),
5150
);
5251
if (result != null) {

examples/demo/lib/widgets/sections/user_section.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,12 @@ class UserSection extends StatelessWidget {
7979
onPressed: () async {
8080
final result = await showDialog<String>(
8181
context: context,
82-
builder: (_) => const LoginDialog(),
82+
builder: (_) => const SingleInputDialog(
83+
title: 'Login User',
84+
fieldLabel: 'External User Id',
85+
confirmLabel: 'Login',
86+
semanticsLabel: 'login_user_id_input',
87+
),
8388
);
8489
if (result != null && context.mounted) {
8590
await vm.loginUser(result);

0 commit comments

Comments
 (0)