You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: examples/build.md
+8-9Lines changed: 8 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -66,16 +66,18 @@ Use **Provider** for dependency injection and **ChangeNotifier** for reactive st
66
66
- `ChangeNotifierProvider<AppViewModel>`at the root widget tree in `main.dart`
67
67
- `AppViewModel extends ChangeNotifier`holds all UI state as private fields with public getters
68
68
- Exposes action methods that update state and call `notifyListeners()`
69
-
- Receives `OneSignalRepository` and `PreferencesService` via constructor injection
69
+
- Receives `OneSignalApiService` and `PreferencesService` via constructor injection
70
70
- Initialize OneSignal SDK before `runApp()`
71
71
- Use `Consumer`/`Selector` from Provider to scope rebuilds and minimize re-renders
72
-
- `OneSignalRepository`is a plain Dart class (not a ChangeNotifier)
72
+
- SDK calls (`OneSignal.User.*`, `OneSignal.Notifications.*`, `OneSignal.InAppMessages.*`, etc.) are invoked directly from `AppViewModel`. There is no repository wrapper.
73
+
- `OneSignalApiService`is a plain Dart class that owns the OneSignal REST API calls (send notification, live activity update/end, fetch user). Not a ChangeNotifier.
73
74
74
75
### Persistence
75
76
76
77
- `PreferencesService`wraps `SharedPreferences`
77
78
- In-memory lists use `List<MapEntry<String, String>>` for triggers, aliases, tags
78
79
- Triggers list (`triggersList`) is NOT persisted to `SharedPreferences`
80
+
- After fetching the user from the REST API, merge results into existing in-memory lists (`_mergePairs` for tag/alias maps, `_mergeUnique` for emails/SMS) so locally-added entries that have not yet round-tripped through the API are preserved.
- Call `viewModel.promptPush()` in `initState()` of `HomeScreen`
115
117
116
-
### Loading Overlay
117
-
- `CircularProgressIndicator`centered in a full-screen semi-transparent overlay
118
-
- `Stack`+ `Visibility` based on `isLoading` state
119
-
- Use `await Future.delayed(const Duration(milliseconds: 100))` after setting state for render delay
118
+
### Loading State
119
+
- No global loading overlay; render an inline `CircularProgressIndicator` inside the section that owns the in-flight work (e.g. user section while `isLoading` is true).
120
+
- The viewmodel uses a request-sequence counter (`_fetchSequence`) so stale REST results are dropped when a newer fetch is already in flight.
120
121
121
122
### SnackBar Messages
122
123
- `AppSnackBar`extension on `BuildContext` defined in `theme.dart`
- `TextEditingController`s are properly disposed in `StatefulWidget`s
136
137
- JSON parsing via `jsonDecode` returns `Map<String, dynamic>` for Track Event
138
+
- Single-field input prompts (e.g. login, add email/SMS, add trigger) reuse a single `SingleInputDialog` widget that takes `title`, `fieldLabel`, `confirmLabel`, and `semanticsLabel`. Avoid creating a per-screen dialog widget when one input is needed.
0 commit comments