@appiq/flutter-workflow 1.4.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +160 -0
- package/README.md +69 -9
- package/agents/claude/cubit-agent.md +164 -2
- package/agents/claude/data-agent.md +163 -2
- package/agents/claude/domain-agent.md +164 -2
- package/agents/claude/feature-manager.md +361 -22
- package/agents/claude/integration-validator.md +1 -0
- package/agents/claude/po-agent.md +1 -0
- package/agents/claude/security-agent.md +163 -2
- package/agents/claude/test-agent.md +165 -2
- package/agents/claude/ui-agent.md +159 -8
- package/config/agent-coordination.json +335 -0
- package/config/independent-mode-template.md +202 -0
- package/lib/independent-agent-tracker.js +565 -0
- package/lib/setup-independent-mode.js +562 -0
- package/lib/state-manager.js +526 -0
- package/package.json +4 -2
- package/templates/enhanced-task-breakdown-template.md +415 -0
- package/templates/enhanced-task-history-template.md +605 -0
- package/templates/feature-template.md +116 -30
- package/templates/additional_cubit_req.md +0 -357
- package/templates/additional_data_req.md +0 -480
- package/templates/additional_domain_req.md +0 -431
- package/templates/additional_ui_req.md +0 -205
- package/templates/feature-history-template.md +0 -280
- package/templates/platform-adaptive-widget-template.dart +0 -407
- package/templates/pretty-ui-examples.md +0 -597
- package/templates/task-breakdown-template.md +0 -265
- package/templates/task-history-template.md +0 -276
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
# {{FEATURE_NAME}} - Development History
|
|
2
|
-
|
|
3
|
-
**Feature:** {{FEATURE_NAME}}
|
|
4
|
-
**Created:** {{CREATED_DATE}}
|
|
5
|
-
**Status:** {{CURRENT_STATUS}}
|
|
6
|
-
**Last Updated:** {{UPDATED_DATE}}
|
|
7
|
-
|
|
8
|
-
## Development Timeline
|
|
9
|
-
|
|
10
|
-
### Phase 1: Analysis & Planning (PO Agent)
|
|
11
|
-
**Agent:** Phoenix (PO Agent)
|
|
12
|
-
**Status:** {{PO_STATUS}}
|
|
13
|
-
**Start Date:** {{PO_START_DATE}}
|
|
14
|
-
**End Date:** {{PO_END_DATE}}
|
|
15
|
-
|
|
16
|
-
#### Activities Completed:
|
|
17
|
-
- [ ] Feature requirements analysis
|
|
18
|
-
- [ ] User story breakdown
|
|
19
|
-
- [ ] Acceptance criteria definition
|
|
20
|
-
- [ ] Task planning and estimation
|
|
21
|
-
- [ ] Risk assessment
|
|
22
|
-
- [ ] Stakeholder coordination
|
|
23
|
-
|
|
24
|
-
#### Key Decisions:
|
|
25
|
-
- Decision 1: Rationale
|
|
26
|
-
- Decision 2: Rationale
|
|
27
|
-
- Decision 3: Rationale
|
|
28
|
-
|
|
29
|
-
#### Issues & Resolutions:
|
|
30
|
-
- Issue 1: Resolution
|
|
31
|
-
- Issue 2: Resolution
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
### Phase 2: UI/UX Implementation (UI Agent)
|
|
36
|
-
**Agent:** Maya (UI Agent)
|
|
37
|
-
**Status:** {{UI_STATUS}}
|
|
38
|
-
**Start Date:** {{UI_START_DATE}}
|
|
39
|
-
**End Date:** {{UI_END_DATE}}
|
|
40
|
-
|
|
41
|
-
#### Activities Completed:
|
|
42
|
-
- [ ] UI requirements analysis
|
|
43
|
-
- [ ] Widget library review
|
|
44
|
-
- [ ] Responsive design implementation
|
|
45
|
-
- [ ] Accessibility compliance
|
|
46
|
-
- [ ] Localization implementation
|
|
47
|
-
- [ ] Widget testing
|
|
48
|
-
|
|
49
|
-
#### Key Decisions:
|
|
50
|
-
- UI Decision 1: Rationale
|
|
51
|
-
- UI Decision 2: Rationale
|
|
52
|
-
|
|
53
|
-
#### Files Modified/Created:
|
|
54
|
-
- lib/features/{{FEATURE_FOLDER}}/presentation/pages/
|
|
55
|
-
- lib/features/{{FEATURE_FOLDER}}/presentation/widgets/
|
|
56
|
-
- lib/shared/widgets/ (if applicable)
|
|
57
|
-
|
|
58
|
-
#### Issues & Resolutions:
|
|
59
|
-
- UI Issue 1: Resolution
|
|
60
|
-
- UI Issue 2: Resolution
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
### Phase 3: State Management (Cubit Agent)
|
|
65
|
-
**Agent:** Alex (Cubit Agent)
|
|
66
|
-
**Status:** {{CUBIT_STATUS}}
|
|
67
|
-
**Start Date:** {{CUBIT_START_DATE}}
|
|
68
|
-
**End Date:** {{CUBIT_END_DATE}}
|
|
69
|
-
|
|
70
|
-
#### Activities Completed:
|
|
71
|
-
- [ ] State requirements analysis
|
|
72
|
-
- [ ] Cubit architecture design
|
|
73
|
-
- [ ] State classes implementation
|
|
74
|
-
- [ ] Business logic coordination
|
|
75
|
-
- [ ] Error handling implementation
|
|
76
|
-
- [ ] Cubit testing
|
|
77
|
-
|
|
78
|
-
#### Key Decisions:
|
|
79
|
-
- State Decision 1: Rationale
|
|
80
|
-
- State Decision 2: Rationale
|
|
81
|
-
|
|
82
|
-
#### Files Modified/Created:
|
|
83
|
-
- lib/features/{{FEATURE_FOLDER}}/presentation/cubit/
|
|
84
|
-
- lib/core/cubit/ (if applicable)
|
|
85
|
-
|
|
86
|
-
#### Issues & Resolutions:
|
|
87
|
-
- Cubit Issue 1: Resolution
|
|
88
|
-
- Cubit Issue 2: Resolution
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
### Phase 4: Domain Layer (Domain Agent)
|
|
93
|
-
**Agent:** Jordan (Domain Agent)
|
|
94
|
-
**Status:** {{DOMAIN_STATUS}}
|
|
95
|
-
**Start Date:** {{DOMAIN_START_DATE}}
|
|
96
|
-
**End Date:** {{DOMAIN_END_DATE}}
|
|
97
|
-
|
|
98
|
-
#### Activities Completed:
|
|
99
|
-
- [ ] Domain requirements analysis
|
|
100
|
-
- [ ] Entity design and implementation
|
|
101
|
-
- [ ] Use case implementation
|
|
102
|
-
- [ ] Repository interface creation
|
|
103
|
-
- [ ] Business rule validation
|
|
104
|
-
- [ ] Domain testing
|
|
105
|
-
|
|
106
|
-
#### Key Decisions:
|
|
107
|
-
- Domain Decision 1: Rationale
|
|
108
|
-
- Domain Decision 2: Rationale
|
|
109
|
-
|
|
110
|
-
#### Files Modified/Created:
|
|
111
|
-
- lib/features/{{FEATURE_FOLDER}}/domain/entities/
|
|
112
|
-
- lib/features/{{FEATURE_FOLDER}}/domain/usecases/
|
|
113
|
-
- lib/features/{{FEATURE_FOLDER}}/domain/repositories/
|
|
114
|
-
|
|
115
|
-
#### Issues & Resolutions:
|
|
116
|
-
- Domain Issue 1: Resolution
|
|
117
|
-
- Domain Issue 2: Resolution
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
### Phase 5: Data Layer (Data Agent)
|
|
122
|
-
**Agent:** Sam (Data Agent)
|
|
123
|
-
**Status:** {{DATA_STATUS}}
|
|
124
|
-
**Start Date:** {{DATA_START_DATE}}
|
|
125
|
-
**End Date:** {{DATA_END_DATE}}
|
|
126
|
-
|
|
127
|
-
#### Activities Completed:
|
|
128
|
-
- [ ] Data requirements analysis
|
|
129
|
-
- [ ] Repository implementation
|
|
130
|
-
- [ ] Data source creation
|
|
131
|
-
- [ ] API integration
|
|
132
|
-
- [ ] Local storage implementation
|
|
133
|
-
- [ ] Caching strategy
|
|
134
|
-
- [ ] Data testing
|
|
135
|
-
|
|
136
|
-
#### Key Decisions:
|
|
137
|
-
- Data Decision 1: Rationale
|
|
138
|
-
- Data Decision 2: Rationale
|
|
139
|
-
|
|
140
|
-
#### Files Modified/Created:
|
|
141
|
-
- lib/features/{{FEATURE_FOLDER}}/data/repositories/
|
|
142
|
-
- lib/features/{{FEATURE_FOLDER}}/data/datasources/
|
|
143
|
-
- lib/features/{{FEATURE_FOLDER}}/data/models/
|
|
144
|
-
|
|
145
|
-
#### MCP Integrations Used:
|
|
146
|
-
- MCP Service 1: Purpose
|
|
147
|
-
- MCP Service 2: Purpose
|
|
148
|
-
|
|
149
|
-
#### Issues & Resolutions:
|
|
150
|
-
- Data Issue 1: Resolution
|
|
151
|
-
- Data Issue 2: Resolution
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
### Phase 6: Security Implementation (Security Agent)
|
|
156
|
-
**Agent:** Cipher (Security Agent)
|
|
157
|
-
**Status:** {{SECURITY_STATUS}}
|
|
158
|
-
**Start Date:** {{SECURITY_START_DATE}}
|
|
159
|
-
**End Date:** {{SECURITY_END_DATE}}
|
|
160
|
-
|
|
161
|
-
#### Activities Completed:
|
|
162
|
-
- [ ] Security requirements analysis
|
|
163
|
-
- [ ] COPPA compliance validation
|
|
164
|
-
- [ ] Data encryption implementation
|
|
165
|
-
- [ ] Authentication/authorization
|
|
166
|
-
- [ ] Input validation
|
|
167
|
-
- [ ] Security testing
|
|
168
|
-
|
|
169
|
-
#### Key Decisions:
|
|
170
|
-
- Security Decision 1: Rationale
|
|
171
|
-
- Security Decision 2: Rationale
|
|
172
|
-
|
|
173
|
-
#### Security Measures Implemented:
|
|
174
|
-
- Measure 1: Implementation details
|
|
175
|
-
- Measure 2: Implementation details
|
|
176
|
-
|
|
177
|
-
#### Compliance Validations:
|
|
178
|
-
- [ ] COPPA compliance verified
|
|
179
|
-
- [ ] GDPR compliance verified
|
|
180
|
-
- [ ] Data protection measures implemented
|
|
181
|
-
|
|
182
|
-
#### Issues & Resolutions:
|
|
183
|
-
- Security Issue 1: Resolution
|
|
184
|
-
- Security Issue 2: Resolution
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
### Phase 7: Testing & Quality Assurance (Test Agent)
|
|
189
|
-
**Agent:** Trinity (Test Agent)
|
|
190
|
-
**Status:** {{TEST_STATUS}}
|
|
191
|
-
**Start Date:** {{TEST_START_DATE}}
|
|
192
|
-
**End Date:** {{TEST_END_DATE}}
|
|
193
|
-
|
|
194
|
-
#### Activities Completed:
|
|
195
|
-
- [ ] Testing strategy design
|
|
196
|
-
- [ ] Unit tests implementation (70%)
|
|
197
|
-
- [ ] Widget tests implementation (20%)
|
|
198
|
-
- [ ] Integration tests implementation (10%)
|
|
199
|
-
- [ ] Performance testing
|
|
200
|
-
- [ ] Security testing
|
|
201
|
-
- [ ] Accessibility testing
|
|
202
|
-
|
|
203
|
-
#### Test Coverage Results:
|
|
204
|
-
- Overall Coverage: {{TEST_COVERAGE}}%
|
|
205
|
-
- Unit Test Coverage: {{UNIT_COVERAGE}}%
|
|
206
|
-
- Widget Test Coverage: {{WIDGET_COVERAGE}}%
|
|
207
|
-
- Integration Test Coverage: {{INTEGRATION_COVERAGE}}%
|
|
208
|
-
|
|
209
|
-
#### Quality Gates Status:
|
|
210
|
-
- [ ] Minimum 90% test coverage achieved
|
|
211
|
-
- [ ] All tests passing
|
|
212
|
-
- [ ] Performance benchmarks met
|
|
213
|
-
- [ ] Security tests passing
|
|
214
|
-
- [ ] Accessibility compliance verified
|
|
215
|
-
|
|
216
|
-
#### Issues & Resolutions:
|
|
217
|
-
- Test Issue 1: Resolution
|
|
218
|
-
- Test Issue 2: Resolution
|
|
219
|
-
|
|
220
|
-
---
|
|
221
|
-
|
|
222
|
-
## Overall Feature Summary
|
|
223
|
-
|
|
224
|
-
### Total Development Time
|
|
225
|
-
**Start Date:** {{FEATURE_START_DATE}}
|
|
226
|
-
**End Date:** {{FEATURE_END_DATE}}
|
|
227
|
-
**Total Duration:** {{TOTAL_DURATION}}
|
|
228
|
-
|
|
229
|
-
### Final Status Summary
|
|
230
|
-
- **UI:** {{FINAL_UI_STATUS}}
|
|
231
|
-
- **Domain:** {{FINAL_DOMAIN_STATUS}}
|
|
232
|
-
- **Data:** {{FINAL_DATA_STATUS}}
|
|
233
|
-
- **Security:** {{FINAL_SECURITY_STATUS}}
|
|
234
|
-
- **Test:** {{FINAL_TEST_STATUS}}
|
|
235
|
-
- **Overall:** {{FINAL_STATUS}}
|
|
236
|
-
|
|
237
|
-
### Key Achievements
|
|
238
|
-
- Achievement 1
|
|
239
|
-
- Achievement 2
|
|
240
|
-
- Achievement 3
|
|
241
|
-
|
|
242
|
-
### Lessons Learned
|
|
243
|
-
- Lesson 1
|
|
244
|
-
- Lesson 2
|
|
245
|
-
- Lesson 3
|
|
246
|
-
|
|
247
|
-
### Technical Debt Created
|
|
248
|
-
- Debt Item 1: Priority and plan
|
|
249
|
-
- Debt Item 2: Priority and plan
|
|
250
|
-
|
|
251
|
-
### Future Enhancements
|
|
252
|
-
- Enhancement 1: Priority and timeline
|
|
253
|
-
- Enhancement 2: Priority and timeline
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
## Git Commit History
|
|
258
|
-
```
|
|
259
|
-
{{GIT_COMMIT_HASH_1}} - {{COMMIT_MESSAGE_1}} ({{COMMIT_DATE_1}})
|
|
260
|
-
{{GIT_COMMIT_HASH_2}} - {{COMMIT_MESSAGE_2}} ({{COMMIT_DATE_2}})
|
|
261
|
-
{{GIT_COMMIT_HASH_3}} - {{COMMIT_MESSAGE_3}} ({{COMMIT_DATE_3}})
|
|
262
|
-
...
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
## Files Created/Modified
|
|
266
|
-
### New Files
|
|
267
|
-
- File 1: Purpose
|
|
268
|
-
- File 2: Purpose
|
|
269
|
-
|
|
270
|
-
### Modified Files
|
|
271
|
-
- File 1: Changes made
|
|
272
|
-
- File 2: Changes made
|
|
273
|
-
|
|
274
|
-
## Dependencies Added
|
|
275
|
-
- Dependency 1: Version and purpose
|
|
276
|
-
- Dependency 2: Version and purpose
|
|
277
|
-
|
|
278
|
-
---
|
|
279
|
-
|
|
280
|
-
*This history is automatically maintained by the AppIQ Flutter Workflow system.*
|
|
@@ -1,407 +0,0 @@
|
|
|
1
|
-
import 'package:flutter/cupertino.dart';
|
|
2
|
-
import 'package:flutter/material.dart';
|
|
3
|
-
import 'package:flutter/foundation.dart';
|
|
4
|
-
|
|
5
|
-
/// Platform-adaptive widget template for creating native-feeling components
|
|
6
|
-
///
|
|
7
|
-
/// This template demonstrates how to create widgets that automatically
|
|
8
|
-
/// adapt to iOS (Cupertino) and Android (Material) design languages
|
|
9
|
-
///
|
|
10
|
-
/// Usage Example:
|
|
11
|
-
/// ```dart
|
|
12
|
-
/// AdaptiveButton(
|
|
13
|
-
/// onPressed: () => print('Pressed'),
|
|
14
|
-
/// child: Text('Click me'),
|
|
15
|
-
/// )
|
|
16
|
-
/// ```
|
|
17
|
-
class AdaptiveButton extends StatelessWidget {
|
|
18
|
-
const AdaptiveButton({
|
|
19
|
-
super.key,
|
|
20
|
-
required this.onPressed,
|
|
21
|
-
required this.child,
|
|
22
|
-
this.variant = AdaptiveButtonVariant.primary,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
final VoidCallback? onPressed;
|
|
26
|
-
final Widget child;
|
|
27
|
-
final AdaptiveButtonVariant variant;
|
|
28
|
-
|
|
29
|
-
@override
|
|
30
|
-
Widget build(BuildContext context) {
|
|
31
|
-
switch (Theme.of(context).platform) {
|
|
32
|
-
case TargetPlatform.iOS:
|
|
33
|
-
case TargetPlatform.macOS:
|
|
34
|
-
return _buildCupertinoButton(context);
|
|
35
|
-
case TargetPlatform.android:
|
|
36
|
-
case TargetPlatform.fuchsia:
|
|
37
|
-
case TargetPlatform.linux:
|
|
38
|
-
case TargetPlatform.windows:
|
|
39
|
-
default:
|
|
40
|
-
return _buildMaterialButton(context);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
Widget _buildCupertinoButton(BuildContext context) {
|
|
45
|
-
switch (variant) {
|
|
46
|
-
case AdaptiveButtonVariant.primary:
|
|
47
|
-
return CupertinoButton.filled(
|
|
48
|
-
onPressed: onPressed,
|
|
49
|
-
child: child,
|
|
50
|
-
);
|
|
51
|
-
case AdaptiveButtonVariant.secondary:
|
|
52
|
-
return CupertinoButton(
|
|
53
|
-
onPressed: onPressed,
|
|
54
|
-
child: child,
|
|
55
|
-
);
|
|
56
|
-
case AdaptiveButtonVariant.destructive:
|
|
57
|
-
return CupertinoButton.filled(
|
|
58
|
-
onPressed: onPressed,
|
|
59
|
-
child: child,
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
Widget _buildMaterialButton(BuildContext context) {
|
|
65
|
-
switch (variant) {
|
|
66
|
-
case AdaptiveButtonVariant.primary:
|
|
67
|
-
return FilledButton(
|
|
68
|
-
onPressed: onPressed,
|
|
69
|
-
child: child,
|
|
70
|
-
);
|
|
71
|
-
case AdaptiveButtonVariant.secondary:
|
|
72
|
-
return OutlinedButton(
|
|
73
|
-
onPressed: onPressed,
|
|
74
|
-
child: child,
|
|
75
|
-
);
|
|
76
|
-
case AdaptiveButtonVariant.destructive:
|
|
77
|
-
return FilledButton(
|
|
78
|
-
onPressed: onPressed,
|
|
79
|
-
style: FilledButton.styleFrom(
|
|
80
|
-
backgroundColor: Theme.of(context).colorScheme.error,
|
|
81
|
-
foregroundColor: Theme.of(context).colorScheme.onError,
|
|
82
|
-
),
|
|
83
|
-
child: child,
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
enum AdaptiveButtonVariant {
|
|
90
|
-
primary,
|
|
91
|
-
secondary,
|
|
92
|
-
destructive,
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/// Platform-adaptive navigation bar
|
|
96
|
-
class AdaptiveNavigationBar extends StatelessWidget implements PreferredSizeWidget {
|
|
97
|
-
const AdaptiveNavigationBar({
|
|
98
|
-
super.key,
|
|
99
|
-
this.title,
|
|
100
|
-
this.leading,
|
|
101
|
-
this.actions,
|
|
102
|
-
this.backgroundColor,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
final Widget? title;
|
|
106
|
-
final Widget? leading;
|
|
107
|
-
final List<Widget>? actions;
|
|
108
|
-
final Color? backgroundColor;
|
|
109
|
-
|
|
110
|
-
@override
|
|
111
|
-
Widget build(BuildContext context) {
|
|
112
|
-
switch (Theme.of(context).platform) {
|
|
113
|
-
case TargetPlatform.iOS:
|
|
114
|
-
case TargetPlatform.macOS:
|
|
115
|
-
return CupertinoNavigationBar(
|
|
116
|
-
middle: title,
|
|
117
|
-
leading: leading,
|
|
118
|
-
trailing: actions?.isNotEmpty == true
|
|
119
|
-
? Row(
|
|
120
|
-
mainAxisSize: MainAxisSize.min,
|
|
121
|
-
children: actions!,
|
|
122
|
-
)
|
|
123
|
-
: null,
|
|
124
|
-
backgroundColor: backgroundColor,
|
|
125
|
-
);
|
|
126
|
-
case TargetPlatform.android:
|
|
127
|
-
case TargetPlatform.fuchsia:
|
|
128
|
-
case TargetPlatform.linux:
|
|
129
|
-
case TargetPlatform.windows:
|
|
130
|
-
default:
|
|
131
|
-
return AppBar(
|
|
132
|
-
title: title,
|
|
133
|
-
leading: leading,
|
|
134
|
-
actions: actions,
|
|
135
|
-
backgroundColor: backgroundColor,
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
@override
|
|
141
|
-
Size get preferredSize {
|
|
142
|
-
switch (defaultTargetPlatform) {
|
|
143
|
-
case TargetPlatform.iOS:
|
|
144
|
-
case TargetPlatform.macOS:
|
|
145
|
-
return const Size.fromHeight(44.0);
|
|
146
|
-
case TargetPlatform.android:
|
|
147
|
-
case TargetPlatform.fuchsia:
|
|
148
|
-
case TargetPlatform.linux:
|
|
149
|
-
case TargetPlatform.windows:
|
|
150
|
-
default:
|
|
151
|
-
return const Size.fromHeight(56.0);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/// Platform-adaptive loading indicator
|
|
157
|
-
class AdaptiveLoadingIndicator extends StatelessWidget {
|
|
158
|
-
const AdaptiveLoadingIndicator({
|
|
159
|
-
super.key,
|
|
160
|
-
this.size,
|
|
161
|
-
this.color,
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
final double? size;
|
|
165
|
-
final Color? color;
|
|
166
|
-
|
|
167
|
-
@override
|
|
168
|
-
Widget build(BuildContext context) {
|
|
169
|
-
switch (Theme.of(context).platform) {
|
|
170
|
-
case TargetPlatform.iOS:
|
|
171
|
-
case TargetPlatform.macOS:
|
|
172
|
-
return CupertinoActivityIndicator(
|
|
173
|
-
radius: size != null ? size! / 2 : 10.0,
|
|
174
|
-
color: color,
|
|
175
|
-
);
|
|
176
|
-
case TargetPlatform.android:
|
|
177
|
-
case TargetPlatform.fuchsia:
|
|
178
|
-
case TargetPlatform.linux:
|
|
179
|
-
case TargetPlatform.windows:
|
|
180
|
-
default:
|
|
181
|
-
return CircularProgressIndicator(
|
|
182
|
-
strokeWidth: 2.0,
|
|
183
|
-
color: color,
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/// Platform-adaptive switch
|
|
190
|
-
class AdaptiveSwitch extends StatelessWidget {
|
|
191
|
-
const AdaptiveSwitch({
|
|
192
|
-
super.key,
|
|
193
|
-
required this.value,
|
|
194
|
-
required this.onChanged,
|
|
195
|
-
this.activeColor,
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
final bool value;
|
|
199
|
-
final ValueChanged<bool>? onChanged;
|
|
200
|
-
final Color? activeColor;
|
|
201
|
-
|
|
202
|
-
@override
|
|
203
|
-
Widget build(BuildContext context) {
|
|
204
|
-
switch (Theme.of(context).platform) {
|
|
205
|
-
case TargetPlatform.iOS:
|
|
206
|
-
case TargetPlatform.macOS:
|
|
207
|
-
return CupertinoSwitch(
|
|
208
|
-
value: value,
|
|
209
|
-
onChanged: onChanged,
|
|
210
|
-
activeColor: activeColor,
|
|
211
|
-
);
|
|
212
|
-
case TargetPlatform.android:
|
|
213
|
-
case TargetPlatform.fuchsia:
|
|
214
|
-
case TargetPlatform.linux:
|
|
215
|
-
case TargetPlatform.windows:
|
|
216
|
-
default:
|
|
217
|
-
return Switch(
|
|
218
|
-
value: value,
|
|
219
|
-
onChanged: onChanged,
|
|
220
|
-
activeColor: activeColor,
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/// Platform-adaptive dialog
|
|
227
|
-
class AdaptiveDialog {
|
|
228
|
-
static Future<T?> show<T>({
|
|
229
|
-
required BuildContext context,
|
|
230
|
-
required String title,
|
|
231
|
-
required String content,
|
|
232
|
-
String? cancelText,
|
|
233
|
-
String? confirmText,
|
|
234
|
-
VoidCallback? onCancel,
|
|
235
|
-
VoidCallback? onConfirm,
|
|
236
|
-
}) {
|
|
237
|
-
switch (Theme.of(context).platform) {
|
|
238
|
-
case TargetPlatform.iOS:
|
|
239
|
-
case TargetPlatform.macOS:
|
|
240
|
-
return showCupertinoDialog<T>(
|
|
241
|
-
context: context,
|
|
242
|
-
builder: (context) => CupertinoAlertDialog(
|
|
243
|
-
title: Text(title),
|
|
244
|
-
content: Text(content),
|
|
245
|
-
actions: [
|
|
246
|
-
if (cancelText != null)
|
|
247
|
-
CupertinoDialogAction(
|
|
248
|
-
onPressed: () {
|
|
249
|
-
Navigator.of(context).pop();
|
|
250
|
-
onCancel?.call();
|
|
251
|
-
},
|
|
252
|
-
child: Text(cancelText),
|
|
253
|
-
),
|
|
254
|
-
if (confirmText != null)
|
|
255
|
-
CupertinoDialogAction(
|
|
256
|
-
isDestructiveAction: true,
|
|
257
|
-
onPressed: () {
|
|
258
|
-
Navigator.of(context).pop();
|
|
259
|
-
onConfirm?.call();
|
|
260
|
-
},
|
|
261
|
-
child: Text(confirmText),
|
|
262
|
-
),
|
|
263
|
-
],
|
|
264
|
-
),
|
|
265
|
-
);
|
|
266
|
-
case TargetPlatform.android:
|
|
267
|
-
case TargetPlatform.fuchsia:
|
|
268
|
-
case TargetPlatform.linux:
|
|
269
|
-
case TargetPlatform.windows:
|
|
270
|
-
default:
|
|
271
|
-
return showDialog<T>(
|
|
272
|
-
context: context,
|
|
273
|
-
builder: (context) => AlertDialog(
|
|
274
|
-
title: Text(title),
|
|
275
|
-
content: Text(content),
|
|
276
|
-
actions: [
|
|
277
|
-
if (cancelText != null)
|
|
278
|
-
TextButton(
|
|
279
|
-
onPressed: () {
|
|
280
|
-
Navigator.of(context).pop();
|
|
281
|
-
onCancel?.call();
|
|
282
|
-
},
|
|
283
|
-
child: Text(cancelText),
|
|
284
|
-
),
|
|
285
|
-
if (confirmText != null)
|
|
286
|
-
FilledButton(
|
|
287
|
-
onPressed: () {
|
|
288
|
-
Navigator.of(context).pop();
|
|
289
|
-
onConfirm?.call();
|
|
290
|
-
},
|
|
291
|
-
child: Text(confirmText),
|
|
292
|
-
),
|
|
293
|
-
],
|
|
294
|
-
),
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/// Pretty UI Card with modern design
|
|
301
|
-
class PrettyCard extends StatelessWidget {
|
|
302
|
-
const PrettyCard({
|
|
303
|
-
super.key,
|
|
304
|
-
required this.child,
|
|
305
|
-
this.padding,
|
|
306
|
-
this.margin,
|
|
307
|
-
this.borderRadius,
|
|
308
|
-
this.elevation,
|
|
309
|
-
this.shadowColor,
|
|
310
|
-
this.backgroundColor,
|
|
311
|
-
this.onTap,
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
final Widget child;
|
|
315
|
-
final EdgeInsetsGeometry? padding;
|
|
316
|
-
final EdgeInsetsGeometry? margin;
|
|
317
|
-
final BorderRadius? borderRadius;
|
|
318
|
-
final double? elevation;
|
|
319
|
-
final Color? shadowColor;
|
|
320
|
-
final Color? backgroundColor;
|
|
321
|
-
final VoidCallback? onTap;
|
|
322
|
-
|
|
323
|
-
@override
|
|
324
|
-
Widget build(BuildContext context) {
|
|
325
|
-
final theme = Theme.of(context);
|
|
326
|
-
final defaultBorderRadius = BorderRadius.circular(16.0);
|
|
327
|
-
|
|
328
|
-
return Container(
|
|
329
|
-
margin: margin ?? const EdgeInsets.all(8.0),
|
|
330
|
-
child: Material(
|
|
331
|
-
color: backgroundColor ?? theme.colorScheme.surface,
|
|
332
|
-
borderRadius: borderRadius ?? defaultBorderRadius,
|
|
333
|
-
elevation: elevation ?? 2.0,
|
|
334
|
-
shadowColor: shadowColor ?? theme.shadowColor.withOpacity(0.1),
|
|
335
|
-
child: InkWell(
|
|
336
|
-
onTap: onTap,
|
|
337
|
-
borderRadius: borderRadius ?? defaultBorderRadius,
|
|
338
|
-
child: Padding(
|
|
339
|
-
padding: padding ?? const EdgeInsets.all(16.0),
|
|
340
|
-
child: child,
|
|
341
|
-
),
|
|
342
|
-
),
|
|
343
|
-
),
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
/// Modern gradient button with pretty UI design
|
|
349
|
-
class PrettyGradientButton extends StatelessWidget {
|
|
350
|
-
const PrettyGradientButton({
|
|
351
|
-
super.key,
|
|
352
|
-
required this.onPressed,
|
|
353
|
-
required this.child,
|
|
354
|
-
this.gradient,
|
|
355
|
-
this.borderRadius,
|
|
356
|
-
this.elevation,
|
|
357
|
-
this.padding,
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
final VoidCallback? onPressed;
|
|
361
|
-
final Widget child;
|
|
362
|
-
final Gradient? gradient;
|
|
363
|
-
final BorderRadius? borderRadius;
|
|
364
|
-
final double? elevation;
|
|
365
|
-
final EdgeInsetsGeometry? padding;
|
|
366
|
-
|
|
367
|
-
@override
|
|
368
|
-
Widget build(BuildContext context) {
|
|
369
|
-
final theme = Theme.of(context);
|
|
370
|
-
final defaultGradient = LinearGradient(
|
|
371
|
-
colors: [
|
|
372
|
-
theme.colorScheme.primary,
|
|
373
|
-
theme.colorScheme.primary.withOpacity(0.8),
|
|
374
|
-
],
|
|
375
|
-
begin: Alignment.topLeft,
|
|
376
|
-
end: Alignment.bottomRight,
|
|
377
|
-
);
|
|
378
|
-
|
|
379
|
-
return Container(
|
|
380
|
-
decoration: BoxDecoration(
|
|
381
|
-
gradient: gradient ?? defaultGradient,
|
|
382
|
-
borderRadius: borderRadius ?? BorderRadius.circular(12.0),
|
|
383
|
-
boxShadow: [
|
|
384
|
-
BoxShadow(
|
|
385
|
-
color: theme.colorScheme.primary.withOpacity(0.3),
|
|
386
|
-
blurRadius: elevation ?? 8.0,
|
|
387
|
-
offset: const Offset(0, 4),
|
|
388
|
-
),
|
|
389
|
-
],
|
|
390
|
-
),
|
|
391
|
-
child: Material(
|
|
392
|
-
color: Colors.transparent,
|
|
393
|
-
child: InkWell(
|
|
394
|
-
onTap: onPressed,
|
|
395
|
-
borderRadius: borderRadius ?? BorderRadius.circular(12.0),
|
|
396
|
-
child: Padding(
|
|
397
|
-
padding: padding ?? const EdgeInsets.symmetric(
|
|
398
|
-
horizontal: 24.0,
|
|
399
|
-
vertical: 12.0,
|
|
400
|
-
),
|
|
401
|
-
child: child,
|
|
402
|
-
),
|
|
403
|
-
),
|
|
404
|
-
),
|
|
405
|
-
);
|
|
406
|
-
}
|
|
407
|
-
}
|