Skip to content

Commit a8827c5

Browse files
committed
split up App & User section
1 parent 111eda9 commit a8827c5

File tree

4 files changed

+121
-104
lines changed

4 files changed

+121
-104
lines changed

examples/build.md

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -292,22 +292,23 @@ In AppViewModel (ChangeNotifier), register observers:
292292

293293
### Section Order (top to bottom)
294294

295-
1. **App Section** (App ID, Guidance Banner, Consent Toggle, Logged-in-as display, Login/Logout)
296-
2. **Push Section** (Push ID, Enabled Toggle, Auto-prompts permission on load)
297-
3. **Send Push Notification Section** (Simple, With Image, Custom buttons)
298-
4. **In-App Messaging Section** (Pause toggle)
299-
5. **Send In-App Message Section** (Top Banner, Bottom Banner, Center Modal, Full Screen - with icons)
300-
6. **Aliases Section** (Add/Add Multiple, read-only list)
301-
7. **Emails Section** (Collapsible list >5 items)
302-
8. **SMS Section** (Collapsible list >5 items)
303-
9. **Tags Section** (Add/Add Multiple/Remove Selected)
304-
10. **Outcome Events Section** (Send Outcome dialog with type selection)
305-
11. **Triggers Section** (Add/Add Multiple/Remove Selected/Clear All - IN MEMORY ONLY)
306-
12. **Track Event Section** (Track Event with JSON validation)
307-
13. **Location Section** (Location Shared toggle, Prompt Location button)
308-
14. **Next Page Button**
309-
310-
### Prompt 2.1 - App Section
295+
1. **App Section** (App ID, Guidance Banner, Consent Toggle)
296+
2. **User Section** (Status, External ID, Login/Logout)
297+
3. **Push Section** (Push ID, Enabled Toggle, Auto-prompts permission on load)
298+
4. **Send Push Notification Section** (Simple, With Image, Custom buttons)
299+
5. **In-App Messaging Section** (Pause toggle)
300+
6. **Send In-App Message Section** (Top Banner, Bottom Banner, Center Modal, Full Screen - with icons)
301+
7. **Aliases Section** (Add/Add Multiple, read-only list)
302+
8. **Emails Section** (Collapsible list >5 items)
303+
9. **SMS Section** (Collapsible list >5 items)
304+
10. **Tags Section** (Add/Add Multiple/Remove Selected)
305+
11. **Outcome Events Section** (Send Outcome dialog with type selection)
306+
12. **Triggers Section** (Add/Add Multiple/Remove Selected/Clear All - IN MEMORY ONLY)
307+
13. **Track Event Section** (Track Event with JSON validation)
308+
14. **Location Section** (Location Shared toggle, Prompt Location button)
309+
15. **Next Page Button**
310+
311+
### Prompt 2.1a - App Section
311312

312313
```
313314
App Section layout:
@@ -330,8 +331,14 @@ App Section layout:
330331
- Calls OneSignal.consentGiven(value)
331332
- Separated from the above toggle by a horizontal divider
332333
- NOT a blocking overlay - user can interact with app regardless of state
334+
```
335+
336+
### Prompt 2.1b - User Section
337+
338+
```
339+
User Section layout (separate SectionCard titled "User", placed after App Section):
333340
334-
4. User status card (always visible, ABOVE the login/logout buttons):
341+
1. User status card (always visible, ABOVE the login/logout buttons):
335342
- Card with two rows separated by a divider
336343
- Row 1: "Status" label on the left, value on the right
337344
- Row 2: "External ID" label on the left, value on the right
@@ -342,12 +349,12 @@ App Section layout:
342349
- Status shows "Logged In" with green styling (Color(0xFF2E7D32))
343350
- External ID shows the actual external user ID
344351
345-
5. LOGIN USER button:
352+
2. LOGIN USER button:
346353
- Shows "LOGIN USER" when no user is logged in
347354
- Shows "SWITCH USER" when a user is logged in
348355
- Opens dialog with empty "External User Id" field
349356
350-
6. LOGOUT USER button (only visible when a user is logged in)
357+
3. LOGOUT USER button (only visible when a user is logged in)
351358
```
352359

353360
### Prompt 2.2 - Push Section
@@ -1040,7 +1047,8 @@ examples/demo/
10401047
│ ├── log_view.dart # Collapsible log viewer (Appium-ready)
10411048
│ ├── dialogs.dart # All dialog widgets
10421049
│ └── sections/
1043-
│ ├── app_section.dart # App ID, consent, login/logout
1050+
│ ├── app_section.dart # App ID, guidance banner, consent
1051+
│ ├── user_section.dart # User status, login/logout
10441052
│ ├── push_section.dart # Push subscription controls
10451053
│ ├── send_push_section.dart # Send notification buttons
10461054
│ ├── in_app_section.dart # IAM pause toggle

examples/demo/lib/screens/home_screen.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import '../widgets/loading_overlay.dart';
1010
import '../widgets/log_view.dart';
1111
import '../widgets/sections/aliases_section.dart';
1212
import '../widgets/sections/app_section.dart';
13+
import '../widgets/sections/user_section.dart';
1314
import '../widgets/sections/emails_section.dart';
1415
import '../widgets/sections/in_app_section.dart';
1516
import '../widgets/sections/location_section.dart';
@@ -102,6 +103,9 @@ class _HomeScreenState extends State<HomeScreen> {
102103
AppSection(
103104
onInfoTap: () => _showTooltipDialog(context, 'app'),
104105
),
106+
UserSection(
107+
onInfoTap: () => _showTooltipDialog(context, 'user'),
108+
),
105109
PushSection(
106110
onInfoTap: () => _showTooltipDialog(context, 'push'),
107111
),

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

Lines changed: 0 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import 'package:url_launcher/url_launcher.dart';
44

55
import '../../theme.dart';
66
import '../../viewmodels/app_viewmodel.dart';
7-
import '../dialogs.dart';
8-
import '../action_button.dart';
97
import '../section_card.dart';
108
import '../toggle_row.dart';
119

@@ -110,88 +108,6 @@ class AppSection extends StatelessWidget {
110108
),
111109
),
112110
),
113-
const SizedBox(height: 24),
114-
115-
// USER section header
116-
Padding(
117-
padding: EdgeInsets.only(bottom: AppSpacing.gap),
118-
child: Text(
119-
'USER',
120-
style: Theme.of(context).textTheme.bodySmall?.copyWith(
121-
fontWeight: FontWeight.bold,
122-
color: Colors.grey[700],
123-
letterSpacing: 0.5,
124-
),
125-
),
126-
),
127-
128-
// User status card
129-
Card(
130-
margin: EdgeInsets.zero,
131-
child: Padding(
132-
padding: AppSpacing.cardPadding,
133-
child: Column(
134-
children: [
135-
Row(
136-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
137-
children: [
138-
const Text('Status', style: TextStyle(fontSize: 14)),
139-
Text(
140-
vm.isLoggedIn ? 'Logged In' : 'Anonymous',
141-
style: TextStyle(
142-
fontSize: 14,
143-
fontWeight: FontWeight.w500,
144-
color: vm.isLoggedIn
145-
? AppColors.oneSignalGreen
146-
: Colors.grey[600],
147-
),
148-
),
149-
],
150-
),
151-
const Divider(),
152-
Row(
153-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
154-
children: [
155-
const Text(
156-
'External ID',
157-
style: TextStyle(fontSize: 14),
158-
),
159-
SelectableText(
160-
vm.isLoggedIn
161-
? (vm.externalUserId ?? '')
162-
: '–',
163-
style: const TextStyle(fontSize: 14),
164-
),
165-
],
166-
),
167-
],
168-
),
169-
),
170-
),
171-
AppSpacing.gapBox,
172-
173-
// Login / Switch User button
174-
PrimaryButton(
175-
label: vm.isLoggedIn ? 'SWITCH USER' : 'LOGIN USER',
176-
onPressed: () async {
177-
final result = await showDialog<String>(
178-
context: context,
179-
builder: (_) => const LoginDialog(),
180-
);
181-
if (result != null && context.mounted) {
182-
vm.loginUser(result);
183-
}
184-
},
185-
),
186-
if (vm.isLoggedIn) ...[
187-
AppSpacing.gapBox,
188-
189-
// Logout button
190-
DestructiveButton(
191-
label: 'LOGOUT USER',
192-
onPressed: vm.logoutUser,
193-
),
194-
],
195111
],
196112
),
197113
);
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:provider/provider.dart';
3+
4+
import '../../theme.dart';
5+
import '../../viewmodels/app_viewmodel.dart';
6+
import '../dialogs.dart';
7+
import '../action_button.dart';
8+
import '../section_card.dart';
9+
10+
class UserSection extends StatelessWidget {
11+
final VoidCallback? onInfoTap;
12+
13+
const UserSection({super.key, this.onInfoTap});
14+
15+
@override
16+
Widget build(BuildContext context) {
17+
final vm = context.watch<AppViewModel>();
18+
19+
return SectionCard(
20+
title: 'User',
21+
onInfoTap: onInfoTap,
22+
child: Column(
23+
crossAxisAlignment: CrossAxisAlignment.start,
24+
children: [
25+
Card(
26+
margin: EdgeInsets.zero,
27+
child: Padding(
28+
padding: AppSpacing.cardPadding,
29+
child: Column(
30+
children: [
31+
Row(
32+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
33+
children: [
34+
const Text('Status', style: TextStyle(fontSize: 14)),
35+
Text(
36+
vm.isLoggedIn ? 'Logged In' : 'Anonymous',
37+
style: TextStyle(
38+
fontSize: 14,
39+
fontWeight: FontWeight.w500,
40+
color: vm.isLoggedIn
41+
? AppColors.oneSignalGreen
42+
: Colors.grey[600],
43+
),
44+
),
45+
],
46+
),
47+
const Divider(),
48+
Row(
49+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
50+
children: [
51+
const Text(
52+
'External ID',
53+
style: TextStyle(fontSize: 14),
54+
),
55+
SelectableText(
56+
vm.isLoggedIn ? (vm.externalUserId ?? '') : '–',
57+
style: const TextStyle(fontSize: 14),
58+
),
59+
],
60+
),
61+
],
62+
),
63+
),
64+
),
65+
AppSpacing.gapBox,
66+
PrimaryButton(
67+
label: vm.isLoggedIn ? 'SWITCH USER' : 'LOGIN USER',
68+
onPressed: () async {
69+
final result = await showDialog<String>(
70+
context: context,
71+
builder: (_) => const LoginDialog(),
72+
);
73+
if (result != null && context.mounted) {
74+
vm.loginUser(result);
75+
}
76+
},
77+
),
78+
if (vm.isLoggedIn) ...[
79+
AppSpacing.gapBox,
80+
DestructiveButton(
81+
label: 'LOGOUT USER',
82+
onPressed: vm.logoutUser,
83+
),
84+
],
85+
],
86+
),
87+
);
88+
}
89+
}

0 commit comments

Comments
 (0)