maxsim-flutter 1.0.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.
Files changed (281) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/LICENSE +21 -0
  3. package/README.md +445 -0
  4. package/claude-plugin/.claude-plugin/plugin.json +46 -0
  5. package/claude-plugin/agents/flutter-setup-agent.md +54 -0
  6. package/claude-plugin/commands/flutter-add.md +32 -0
  7. package/claude-plugin/commands/flutter-create.md +28 -0
  8. package/claude-plugin/commands/flutter-migrate.md +28 -0
  9. package/claude-plugin/skills/flutter-scaffolding/SKILL.md +109 -0
  10. package/dist/claude-setup/agent-writer.d.ts +21 -0
  11. package/dist/claude-setup/agent-writer.d.ts.map +1 -0
  12. package/dist/claude-setup/agent-writer.js +365 -0
  13. package/dist/claude-setup/agent-writer.js.map +1 -0
  14. package/dist/claude-setup/claude-md-generator.d.ts +7 -0
  15. package/dist/claude-setup/claude-md-generator.d.ts.map +1 -0
  16. package/dist/claude-setup/claude-md-generator.js +428 -0
  17. package/dist/claude-setup/claude-md-generator.js.map +1 -0
  18. package/dist/claude-setup/commands-writer.d.ts +7 -0
  19. package/dist/claude-setup/commands-writer.d.ts.map +1 -0
  20. package/dist/claude-setup/commands-writer.js +303 -0
  21. package/dist/claude-setup/commands-writer.js.map +1 -0
  22. package/dist/claude-setup/hooks-writer.d.ts +3 -0
  23. package/dist/claude-setup/hooks-writer.d.ts.map +1 -0
  24. package/dist/claude-setup/hooks-writer.js +34 -0
  25. package/dist/claude-setup/hooks-writer.js.map +1 -0
  26. package/dist/claude-setup/index.d.ts +10 -0
  27. package/dist/claude-setup/index.d.ts.map +1 -0
  28. package/dist/claude-setup/index.js +9 -0
  29. package/dist/claude-setup/index.js.map +1 -0
  30. package/dist/claude-setup/mcp-config-writer.d.ts +3 -0
  31. package/dist/claude-setup/mcp-config-writer.d.ts.map +1 -0
  32. package/dist/claude-setup/mcp-config-writer.js +42 -0
  33. package/dist/claude-setup/mcp-config-writer.js.map +1 -0
  34. package/dist/claude-setup/plugin-assembler.d.ts +2 -0
  35. package/dist/claude-setup/plugin-assembler.d.ts.map +1 -0
  36. package/dist/claude-setup/plugin-assembler.js +3 -0
  37. package/dist/claude-setup/plugin-assembler.js.map +1 -0
  38. package/dist/claude-setup/prd-generator.d.ts +10 -0
  39. package/dist/claude-setup/prd-generator.d.ts.map +1 -0
  40. package/dist/claude-setup/prd-generator.js +295 -0
  41. package/dist/claude-setup/prd-generator.js.map +1 -0
  42. package/dist/claude-setup/setup-orchestrator.d.ts +11 -0
  43. package/dist/claude-setup/setup-orchestrator.d.ts.map +1 -0
  44. package/dist/claude-setup/setup-orchestrator.js +46 -0
  45. package/dist/claude-setup/setup-orchestrator.js.map +1 -0
  46. package/dist/claude-setup/skill-writer.d.ts +3 -0
  47. package/dist/claude-setup/skill-writer.d.ts.map +1 -0
  48. package/dist/claude-setup/skill-writer.js +256 -0
  49. package/dist/claude-setup/skill-writer.js.map +1 -0
  50. package/dist/cli/commands/add.d.ts +16 -0
  51. package/dist/cli/commands/add.d.ts.map +1 -0
  52. package/dist/cli/commands/add.js +414 -0
  53. package/dist/cli/commands/add.js.map +1 -0
  54. package/dist/cli/commands/create.d.ts +3 -0
  55. package/dist/cli/commands/create.d.ts.map +1 -0
  56. package/dist/cli/commands/create.js +161 -0
  57. package/dist/cli/commands/create.js.map +1 -0
  58. package/dist/cli/commands/list.d.ts +12 -0
  59. package/dist/cli/commands/list.d.ts.map +1 -0
  60. package/dist/cli/commands/list.js +148 -0
  61. package/dist/cli/commands/list.js.map +1 -0
  62. package/dist/cli/commands/migrate.d.ts +3 -0
  63. package/dist/cli/commands/migrate.d.ts.map +1 -0
  64. package/dist/cli/commands/migrate.js +332 -0
  65. package/dist/cli/commands/migrate.js.map +1 -0
  66. package/dist/cli/index.d.ts +3 -0
  67. package/dist/cli/index.d.ts.map +1 -0
  68. package/dist/cli/index.js +34 -0
  69. package/dist/cli/index.js.map +1 -0
  70. package/dist/cli/ui/prompts.d.ts +9 -0
  71. package/dist/cli/ui/prompts.d.ts.map +1 -0
  72. package/dist/cli/ui/prompts.js +74 -0
  73. package/dist/cli/ui/prompts.js.map +1 -0
  74. package/dist/cli/ui/spinner.d.ts +2 -0
  75. package/dist/cli/ui/spinner.d.ts.map +1 -0
  76. package/dist/cli/ui/spinner.js +5 -0
  77. package/dist/cli/ui/spinner.js.map +1 -0
  78. package/dist/cli/version-check.d.ts +7 -0
  79. package/dist/cli/version-check.d.ts.map +1 -0
  80. package/dist/cli/version-check.js +92 -0
  81. package/dist/cli/version-check.js.map +1 -0
  82. package/dist/core/config/defaults.d.ts +3 -0
  83. package/dist/core/config/defaults.d.ts.map +1 -0
  84. package/dist/core/config/defaults.js +21 -0
  85. package/dist/core/config/defaults.js.map +1 -0
  86. package/dist/core/config/loader.d.ts +4 -0
  87. package/dist/core/config/loader.d.ts.map +1 -0
  88. package/dist/core/config/loader.js +38 -0
  89. package/dist/core/config/loader.js.map +1 -0
  90. package/dist/core/config/schema.d.ts +406 -0
  91. package/dist/core/config/schema.d.ts.map +1 -0
  92. package/dist/core/config/schema.js +119 -0
  93. package/dist/core/config/schema.js.map +1 -0
  94. package/dist/core/context.d.ts +57 -0
  95. package/dist/core/context.d.ts.map +1 -0
  96. package/dist/core/context.js +99 -0
  97. package/dist/core/context.js.map +1 -0
  98. package/dist/core/detector.d.ts +28 -0
  99. package/dist/core/detector.d.ts.map +1 -0
  100. package/dist/core/detector.js +200 -0
  101. package/dist/core/detector.js.map +1 -0
  102. package/dist/core/validator.d.ts +7 -0
  103. package/dist/core/validator.d.ts.map +1 -0
  104. package/dist/core/validator.js +35 -0
  105. package/dist/core/validator.js.map +1 -0
  106. package/dist/index.d.ts +21 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/index.js +14 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/modules/composer.d.ts +50 -0
  111. package/dist/modules/composer.d.ts.map +1 -0
  112. package/dist/modules/composer.js +122 -0
  113. package/dist/modules/composer.js.map +1 -0
  114. package/dist/modules/definitions/analytics/module.d.ts +7 -0
  115. package/dist/modules/definitions/analytics/module.d.ts.map +1 -0
  116. package/dist/modules/definitions/analytics/module.js +28 -0
  117. package/dist/modules/definitions/analytics/module.js.map +1 -0
  118. package/dist/modules/definitions/api/module.d.ts +7 -0
  119. package/dist/modules/definitions/api/module.d.ts.map +1 -0
  120. package/dist/modules/definitions/api/module.js +41 -0
  121. package/dist/modules/definitions/api/module.js.map +1 -0
  122. package/dist/modules/definitions/auth/module.d.ts +7 -0
  123. package/dist/modules/definitions/auth/module.d.ts.map +1 -0
  124. package/dist/modules/definitions/auth/module.js +53 -0
  125. package/dist/modules/definitions/auth/module.js.map +1 -0
  126. package/dist/modules/definitions/cicd/module.d.ts +7 -0
  127. package/dist/modules/definitions/cicd/module.d.ts.map +1 -0
  128. package/dist/modules/definitions/cicd/module.js +34 -0
  129. package/dist/modules/definitions/cicd/module.js.map +1 -0
  130. package/dist/modules/definitions/core/module.d.ts +7 -0
  131. package/dist/modules/definitions/core/module.d.ts.map +1 -0
  132. package/dist/modules/definitions/core/module.js +31 -0
  133. package/dist/modules/definitions/core/module.js.map +1 -0
  134. package/dist/modules/definitions/database/module.d.ts +8 -0
  135. package/dist/modules/definitions/database/module.d.ts.map +1 -0
  136. package/dist/modules/definitions/database/module.js +47 -0
  137. package/dist/modules/definitions/database/module.js.map +1 -0
  138. package/dist/modules/definitions/deep-linking/module.d.ts +7 -0
  139. package/dist/modules/definitions/deep-linking/module.d.ts.map +1 -0
  140. package/dist/modules/definitions/deep-linking/module.js +48 -0
  141. package/dist/modules/definitions/deep-linking/module.js.map +1 -0
  142. package/dist/modules/definitions/i18n/module.d.ts +7 -0
  143. package/dist/modules/definitions/i18n/module.d.ts.map +1 -0
  144. package/dist/modules/definitions/i18n/module.js +37 -0
  145. package/dist/modules/definitions/i18n/module.js.map +1 -0
  146. package/dist/modules/definitions/push/module.d.ts +7 -0
  147. package/dist/modules/definitions/push/module.d.ts.map +1 -0
  148. package/dist/modules/definitions/push/module.js +40 -0
  149. package/dist/modules/definitions/push/module.js.map +1 -0
  150. package/dist/modules/definitions/theme/module.d.ts +7 -0
  151. package/dist/modules/definitions/theme/module.d.ts.map +1 -0
  152. package/dist/modules/definitions/theme/module.js +42 -0
  153. package/dist/modules/definitions/theme/module.js.map +1 -0
  154. package/dist/modules/registry.d.ts +50 -0
  155. package/dist/modules/registry.d.ts.map +1 -0
  156. package/dist/modules/registry.js +104 -0
  157. package/dist/modules/registry.js.map +1 -0
  158. package/dist/modules/resolver.d.ts +42 -0
  159. package/dist/modules/resolver.d.ts.map +1 -0
  160. package/dist/modules/resolver.js +140 -0
  161. package/dist/modules/resolver.js.map +1 -0
  162. package/dist/ralph/prd-generator.d.ts +2 -0
  163. package/dist/ralph/prd-generator.d.ts.map +1 -0
  164. package/dist/ralph/prd-generator.js +3 -0
  165. package/dist/ralph/prd-generator.js.map +1 -0
  166. package/dist/ralph/ralph-converter.d.ts +2 -0
  167. package/dist/ralph/ralph-converter.d.ts.map +1 -0
  168. package/dist/ralph/ralph-converter.js +3 -0
  169. package/dist/ralph/ralph-converter.js.map +1 -0
  170. package/dist/ralph/story-sizer.d.ts +2 -0
  171. package/dist/ralph/story-sizer.d.ts.map +1 -0
  172. package/dist/ralph/story-sizer.js +3 -0
  173. package/dist/ralph/story-sizer.js.map +1 -0
  174. package/dist/scaffold/engine.d.ts +40 -0
  175. package/dist/scaffold/engine.d.ts.map +1 -0
  176. package/dist/scaffold/engine.js +233 -0
  177. package/dist/scaffold/engine.js.map +1 -0
  178. package/dist/scaffold/file-writer.d.ts +22 -0
  179. package/dist/scaffold/file-writer.d.ts.map +1 -0
  180. package/dist/scaffold/file-writer.js +68 -0
  181. package/dist/scaffold/file-writer.js.map +1 -0
  182. package/dist/scaffold/post-processors/build-runner.d.ts +2 -0
  183. package/dist/scaffold/post-processors/build-runner.d.ts.map +1 -0
  184. package/dist/scaffold/post-processors/build-runner.js +5 -0
  185. package/dist/scaffold/post-processors/build-runner.js.map +1 -0
  186. package/dist/scaffold/post-processors/dart-format.d.ts +2 -0
  187. package/dist/scaffold/post-processors/dart-format.d.ts.map +1 -0
  188. package/dist/scaffold/post-processors/dart-format.js +5 -0
  189. package/dist/scaffold/post-processors/dart-format.js.map +1 -0
  190. package/dist/scaffold/post-processors/flutter-pub-get.d.ts +2 -0
  191. package/dist/scaffold/post-processors/flutter-pub-get.d.ts.map +1 -0
  192. package/dist/scaffold/post-processors/flutter-pub-get.js +5 -0
  193. package/dist/scaffold/post-processors/flutter-pub-get.js.map +1 -0
  194. package/dist/scaffold/renderer.d.ts +20 -0
  195. package/dist/scaffold/renderer.d.ts.map +1 -0
  196. package/dist/scaffold/renderer.js +75 -0
  197. package/dist/scaffold/renderer.js.map +1 -0
  198. package/dist/scaffold/template-helpers.d.ts +25 -0
  199. package/dist/scaffold/template-helpers.d.ts.map +1 -0
  200. package/dist/scaffold/template-helpers.js +115 -0
  201. package/dist/scaffold/template-helpers.js.map +1 -0
  202. package/dist/types/config.d.ts +4 -0
  203. package/dist/types/config.d.ts.map +1 -0
  204. package/dist/types/config.js +2 -0
  205. package/dist/types/config.js.map +1 -0
  206. package/dist/types/module.d.ts +85 -0
  207. package/dist/types/module.d.ts.map +1 -0
  208. package/dist/types/module.js +2 -0
  209. package/dist/types/module.js.map +1 -0
  210. package/dist/types/project.d.ts +13 -0
  211. package/dist/types/project.d.ts.map +1 -0
  212. package/dist/types/project.js +2 -0
  213. package/dist/types/project.js.map +1 -0
  214. package/package.json +80 -0
  215. package/templates/core/analysis_options.yaml.hbs +21 -0
  216. package/templates/core/lib/app.dart.hbs +20 -0
  217. package/templates/core/lib/core/providers/app_providers.dart.hbs +3 -0
  218. package/templates/core/lib/core/router/app_router.dart.hbs +19 -0
  219. package/templates/core/lib/core/theme/app_theme.dart.hbs +15 -0
  220. package/templates/core/lib/features/home/data/models/.gitkeep +0 -0
  221. package/templates/core/lib/features/home/data/repositories/.gitkeep +0 -0
  222. package/templates/core/lib/features/home/domain/entities/.gitkeep +0 -0
  223. package/templates/core/lib/features/home/domain/repositories/.gitkeep +0 -0
  224. package/templates/core/lib/features/home/presentation/pages/home_page.dart.hbs +18 -0
  225. package/templates/core/lib/features/home/presentation/widgets/.gitkeep +0 -0
  226. package/templates/core/lib/main.dart.hbs +11 -0
  227. package/templates/core/pubspec.yaml.hbs +30 -0
  228. package/templates/core/test/widget_test.dart.hbs +16 -0
  229. package/templates/modules/analytics/lib/features/analytics/data/observers/analytics_route_observer.dart.hbs +53 -0
  230. package/templates/modules/analytics/lib/features/analytics/data/services/firebase_analytics_service.dart.hbs +39 -0
  231. package/templates/modules/analytics/lib/features/analytics/domain/services/analytics_service.dart.hbs +25 -0
  232. package/templates/modules/analytics/lib/features/analytics/presentation/providers/analytics_provider.dart.hbs +17 -0
  233. package/templates/modules/analytics/pubspec.partial.yaml +2 -0
  234. package/templates/modules/api/lib/features/api/data/datasources/api_client.dart.hbs +171 -0
  235. package/templates/modules/api/lib/features/api/data/interceptors/auth_interceptor.dart.hbs +25 -0
  236. package/templates/modules/api/lib/features/api/data/interceptors/retry_interceptor.dart.hbs +42 -0
  237. package/templates/modules/api/lib/features/api/data/repositories/api_repository_impl.dart.hbs +21 -0
  238. package/templates/modules/api/lib/features/api/domain/exceptions/api_exception.dart.hbs +31 -0
  239. package/templates/modules/api/lib/features/api/domain/repositories/api_repository.dart.hbs +8 -0
  240. package/templates/modules/api/lib/features/api/presentation/providers/api_provider.dart.hbs +17 -0
  241. package/templates/modules/api/pubspec.partial.yaml +7 -0
  242. package/templates/modules/auth/lib/features/auth/data/datasources/auth_remote_datasource.dart.hbs +181 -0
  243. package/templates/modules/auth/lib/features/auth/data/models/auth_user_model.dart.hbs +27 -0
  244. package/templates/modules/auth/lib/features/auth/data/repositories/auth_repository_impl.dart.hbs +49 -0
  245. package/templates/modules/auth/lib/features/auth/domain/entities/user_entity.dart.hbs +18 -0
  246. package/templates/modules/auth/lib/features/auth/domain/repositories/auth_repository.dart.hbs +22 -0
  247. package/templates/modules/auth/lib/features/auth/domain/usecases/register_usecase.dart.hbs +20 -0
  248. package/templates/modules/auth/lib/features/auth/domain/usecases/sign_in_usecase.dart.hbs +15 -0
  249. package/templates/modules/auth/lib/features/auth/domain/usecases/sign_out_usecase.dart.hbs +11 -0
  250. package/templates/modules/auth/lib/features/auth/presentation/pages/login_page.dart.hbs +118 -0
  251. package/templates/modules/auth/lib/features/auth/presentation/pages/register_page.dart.hbs +131 -0
  252. package/templates/modules/auth/lib/features/auth/presentation/providers/auth_provider.dart.hbs +31 -0
  253. package/templates/modules/auth/pubspec.partial.yaml +13 -0
  254. package/templates/modules/cicd/.github/workflows/ci.yml.hbs +45 -0
  255. package/templates/modules/cicd/.gitlab-ci.yml.hbs +53 -0
  256. package/templates/modules/cicd/bitbucket-pipelines.yml.hbs +39 -0
  257. package/templates/modules/cicd/pubspec.partial.yaml +1 -0
  258. package/templates/modules/database/lib/features/database/data/datasources/database_datasource.dart.hbs +115 -0
  259. package/templates/modules/database/lib/features/database/data/repositories/database_repository_impl.dart.hbs +73 -0
  260. package/templates/modules/database/lib/features/database/domain/repositories/database_repository.dart.hbs +10 -0
  261. package/templates/modules/database/lib/features/database/presentation/providers/database_provider.dart.hbs +43 -0
  262. package/templates/modules/database/pubspec.partial.yaml +27 -0
  263. package/templates/modules/deep-linking/lib/features/deep_linking/data/datasources/deep_link_datasource.dart.hbs +18 -0
  264. package/templates/modules/deep-linking/lib/features/deep_linking/data/repositories/deep_link_repository_impl.dart.hbs +14 -0
  265. package/templates/modules/deep-linking/lib/features/deep_linking/domain/repositories/deep_link_repository.dart.hbs +7 -0
  266. package/templates/modules/deep-linking/lib/features/deep_linking/presentation/providers/deep_link_provider.dart.hbs +57 -0
  267. package/templates/modules/deep-linking/pubspec.partial.yaml +2 -0
  268. package/templates/modules/i18n/l10n.yaml.hbs +5 -0
  269. package/templates/modules/i18n/lib/core/l10n/l10n_config.dart.hbs +29 -0
  270. package/templates/modules/i18n/lib/core/l10n/l10n_provider.dart.hbs +20 -0
  271. package/templates/modules/i18n/lib/l10n/app_de.arb.hbs +27 -0
  272. package/templates/modules/i18n/lib/l10n/app_en.arb.hbs +27 -0
  273. package/templates/modules/i18n/pubspec.partial.yaml +7 -0
  274. package/templates/modules/push/lib/features/push/data/datasources/push_datasource.dart.hbs +124 -0
  275. package/templates/modules/push/lib/features/push/data/repositories/push_repository_impl.dart.hbs +28 -0
  276. package/templates/modules/push/lib/features/push/domain/repositories/push_repository.dart.hbs +31 -0
  277. package/templates/modules/push/lib/features/push/presentation/providers/push_provider.dart.hbs +34 -0
  278. package/templates/modules/push/pubspec.partial.yaml +8 -0
  279. package/templates/modules/theme/lib/core/theme/app_theme.dart.hbs +74 -0
  280. package/templates/modules/theme/lib/core/theme/theme_provider.dart.hbs +46 -0
  281. package/templates/modules/theme/pubspec.partial.yaml +2 -0
@@ -0,0 +1,7 @@
1
+ dependencies:
2
+ flutter_localizations:
3
+ sdk: flutter
4
+ intl: ^0.19.0
5
+
6
+ flutter:
7
+ generate: true
@@ -0,0 +1,124 @@
1
+ import '../../domain/repositories/push_repository.dart';
2
+ {{#ifEquals modules.push.provider "firebase"}}
3
+ import 'package:firebase_messaging/firebase_messaging.dart';
4
+ {{/ifEquals}}
5
+ {{#ifEquals modules.push.provider "onesignal"}}
6
+ import 'package:onesignal_flutter/onesignal_flutter.dart';
7
+ {{/ifEquals}}
8
+
9
+ abstract class PushDataSource {
10
+ Future<bool> requestPermission();
11
+ Future<String?> getToken();
12
+ Stream<PushMessage> get onMessage;
13
+ Stream<PushMessage> get onMessageOpenedApp;
14
+ Future<void> subscribeToTopic(String topic);
15
+ Future<void> unsubscribeFromTopic(String topic);
16
+ }
17
+ {{#ifEquals modules.push.provider "firebase"}}
18
+
19
+ class FirebasePushDataSource implements PushDataSource {
20
+ final FirebaseMessaging _messaging;
21
+
22
+ FirebasePushDataSource({FirebaseMessaging? messaging})
23
+ : _messaging = messaging ?? FirebaseMessaging.instance;
24
+
25
+ @override
26
+ Future<bool> requestPermission() async {
27
+ final settings = await _messaging.requestPermission(
28
+ alert: true,
29
+ badge: true,
30
+ sound: true,
31
+ );
32
+ return settings.authorizationStatus == AuthorizationStatus.authorized ||
33
+ settings.authorizationStatus == AuthorizationStatus.provisional;
34
+ }
35
+
36
+ @override
37
+ Future<String?> getToken() => _messaging.getToken();
38
+
39
+ @override
40
+ Stream<PushMessage> get onMessage => FirebaseMessaging.onMessage.map(
41
+ (message) => PushMessage(
42
+ title: message.notification?.title,
43
+ body: message.notification?.body,
44
+ data: message.data,
45
+ ),
46
+ );
47
+
48
+ @override
49
+ Stream<PushMessage> get onMessageOpenedApp =>
50
+ FirebaseMessaging.onMessageOpenedApp.map(
51
+ (message) => PushMessage(
52
+ title: message.notification?.title,
53
+ body: message.notification?.body,
54
+ data: message.data,
55
+ ),
56
+ );
57
+
58
+ @override
59
+ Future<void> subscribeToTopic(String topic) =>
60
+ _messaging.subscribeToTopic(topic);
61
+
62
+ @override
63
+ Future<void> unsubscribeFromTopic(String topic) =>
64
+ _messaging.unsubscribeFromTopic(topic);
65
+ }
66
+ {{/ifEquals}}
67
+ {{#ifEquals modules.push.provider "onesignal"}}
68
+
69
+ class OneSignalPushDataSource implements PushDataSource {
70
+ OneSignalPushDataSource() {
71
+ OneSignal.initialize('YOUR_ONESIGNAL_APP_ID');
72
+ }
73
+
74
+ @override
75
+ Future<bool> requestPermission() async {
76
+ return await OneSignal.Notifications.requestPermission(true);
77
+ }
78
+
79
+ @override
80
+ Future<String?> getToken() async {
81
+ return OneSignal.User.pushSubscription.id;
82
+ }
83
+
84
+ @override
85
+ Stream<PushMessage> get onMessage {
86
+ final controller = StreamController<PushMessage>.broadcast();
87
+ OneSignal.Notifications.addForegroundWillDisplayListener((event) {
88
+ final notification = event.notification;
89
+ controller.add(PushMessage(
90
+ title: notification.title,
91
+ body: notification.body,
92
+ data: notification.additionalData ?? {},
93
+ ));
94
+ event.preventDefault();
95
+ });
96
+ return controller.stream;
97
+ }
98
+
99
+ @override
100
+ Stream<PushMessage> get onMessageOpenedApp {
101
+ final controller = StreamController<PushMessage>.broadcast();
102
+ OneSignal.Notifications.addClickListener((event) {
103
+ final notification = event.notification;
104
+ controller.add(PushMessage(
105
+ title: notification.title,
106
+ body: notification.body,
107
+ data: notification.additionalData ?? {},
108
+ ));
109
+ });
110
+ return controller.stream;
111
+ }
112
+
113
+ @override
114
+ Future<void> subscribeToTopic(String topic) async {
115
+ // OneSignal uses tags instead of topics
116
+ OneSignal.User.addTag(topic, 'true');
117
+ }
118
+
119
+ @override
120
+ Future<void> unsubscribeFromTopic(String topic) async {
121
+ OneSignal.User.removeTag(topic);
122
+ }
123
+ }
124
+ {{/ifEquals}}
@@ -0,0 +1,28 @@
1
+ import '../../domain/repositories/push_repository.dart';
2
+ import '../datasources/push_datasource.dart';
3
+
4
+ class PushRepositoryImpl implements PushRepository {
5
+ final PushDataSource _dataSource;
6
+
7
+ PushRepositoryImpl(this._dataSource);
8
+
9
+ @override
10
+ Future<bool> requestPermission() => _dataSource.requestPermission();
11
+
12
+ @override
13
+ Future<String?> getToken() => _dataSource.getToken();
14
+
15
+ @override
16
+ Stream<PushMessage> get onMessage => _dataSource.onMessage;
17
+
18
+ @override
19
+ Stream<PushMessage> get onMessageOpenedApp => _dataSource.onMessageOpenedApp;
20
+
21
+ @override
22
+ Future<void> subscribeToTopic(String topic) =>
23
+ _dataSource.subscribeToTopic(topic);
24
+
25
+ @override
26
+ Future<void> unsubscribeFromTopic(String topic) =>
27
+ _dataSource.unsubscribeFromTopic(topic);
28
+ }
@@ -0,0 +1,31 @@
1
+ abstract class PushRepository {
2
+ /// Request permission to receive push notifications.
3
+ Future<bool> requestPermission();
4
+
5
+ /// Get the FCM/device token for this device.
6
+ Future<String?> getToken();
7
+
8
+ /// Stream of incoming foreground messages.
9
+ Stream<PushMessage> get onMessage;
10
+
11
+ /// Stream of messages that opened the app from background.
12
+ Stream<PushMessage> get onMessageOpenedApp;
13
+
14
+ /// Subscribe to a topic (Firebase only).
15
+ Future<void> subscribeToTopic(String topic);
16
+
17
+ /// Unsubscribe from a topic (Firebase only).
18
+ Future<void> unsubscribeFromTopic(String topic);
19
+ }
20
+
21
+ class PushMessage {
22
+ final String? title;
23
+ final String? body;
24
+ final Map<String, dynamic> data;
25
+
26
+ const PushMessage({
27
+ this.title,
28
+ this.body,
29
+ this.data = const {},
30
+ });
31
+ }
@@ -0,0 +1,34 @@
1
+ import 'package:flutter_riverpod/flutter_riverpod.dart';
2
+ import 'package:riverpod_annotation/riverpod_annotation.dart';
3
+ import '../../data/datasources/push_datasource.dart';
4
+ import '../../data/repositories/push_repository_impl.dart';
5
+ import '../../domain/repositories/push_repository.dart';
6
+
7
+ part 'push_provider.g.dart';
8
+
9
+ @riverpod
10
+ PushDataSource pushDataSource(Ref ref) {
11
+ {{#ifEquals modules.push.provider "firebase"}}
12
+ return FirebasePushDataSource();
13
+ {{/ifEquals}}
14
+ {{#ifEquals modules.push.provider "onesignal"}}
15
+ return OneSignalPushDataSource();
16
+ {{/ifEquals}}
17
+ }
18
+
19
+ @riverpod
20
+ PushRepository pushRepository(Ref ref) {
21
+ return PushRepositoryImpl(ref.watch(pushDataSourceProvider));
22
+ }
23
+
24
+ @riverpod
25
+ Stream<PushMessage> incomingPushMessages(Ref ref) {
26
+ return ref.watch(pushRepositoryProvider).onMessage;
27
+ }
28
+
29
+ @riverpod
30
+ Future<String?> pushToken(Ref ref) async {
31
+ final repo = ref.watch(pushRepositoryProvider);
32
+ await repo.requestPermission();
33
+ return repo.getToken();
34
+ }
@@ -0,0 +1,8 @@
1
+ {{#ifEquals modules.push.provider "firebase"}}
2
+ dependencies:
3
+ firebase_messaging: ^15.1.6
4
+ {{/ifEquals}}
5
+ {{#ifEquals modules.push.provider "onesignal"}}
6
+ dependencies:
7
+ onesignal_flutter: ^5.2.7
8
+ {{/ifEquals}}
@@ -0,0 +1,74 @@
1
+ import 'package:flutter/material.dart';
2
+ import 'package:google_fonts/google_fonts.dart';
3
+
4
+ /// Application theme configuration using Material 3 with ColorScheme.fromSeed.
5
+ abstract final class AppTheme {
6
+ /// Seed color used to generate the color scheme.
7
+ static final Color seedColor = _colorFromHex('{{modules.theme.seedColor}}');
8
+
9
+ /// Light theme with Material 3 seed-based color scheme.
10
+ static ThemeData get light => _buildTheme(Brightness.light);
11
+
12
+ {{#if modules.theme.darkMode}}
13
+ /// Dark theme with Material 3 seed-based color scheme.
14
+ static ThemeData get dark => _buildTheme(Brightness.dark);
15
+ {{/if}}
16
+
17
+ static Color _colorFromHex(String hex) {
18
+ final buffer = StringBuffer();
19
+ if (hex.startsWith('#')) hex = hex.substring(1);
20
+ if (hex.length == 6) buffer.write('FF');
21
+ buffer.write(hex);
22
+ return Color(int.parse(buffer.toString(), radix: 16));
23
+ }
24
+
25
+ static ThemeData _buildTheme(Brightness brightness) {
26
+ final colorScheme = ColorScheme.fromSeed(
27
+ seedColor: seedColor,
28
+ brightness: brightness,
29
+ );
30
+
31
+ final textTheme = GoogleFonts.interTextTheme(
32
+ ThemeData(brightness: brightness).textTheme,
33
+ );
34
+
35
+ return ThemeData(
36
+ useMaterial3: true,
37
+ colorScheme: colorScheme,
38
+ textTheme: textTheme,
39
+ appBarTheme: AppBarTheme(
40
+ centerTitle: true,
41
+ backgroundColor: colorScheme.surface,
42
+ foregroundColor: colorScheme.onSurface,
43
+ elevation: 0,
44
+ ),
45
+ cardTheme: CardTheme(
46
+ elevation: 0,
47
+ shape: RoundedRectangleBorder(
48
+ borderRadius: BorderRadius.circular(12),
49
+ ),
50
+ color: colorScheme.surfaceContainerLow,
51
+ ),
52
+ inputDecorationTheme: InputDecorationTheme(
53
+ filled: true,
54
+ fillColor: colorScheme.surfaceContainerHighest.withValues(alpha: 0.5),
55
+ border: OutlineInputBorder(
56
+ borderRadius: BorderRadius.circular(12),
57
+ borderSide: BorderSide.none,
58
+ ),
59
+ focusedBorder: OutlineInputBorder(
60
+ borderRadius: BorderRadius.circular(12),
61
+ borderSide: BorderSide(color: colorScheme.primary, width: 2),
62
+ ),
63
+ ),
64
+ elevatedButtonTheme: ElevatedButtonThemeData(
65
+ style: ElevatedButton.styleFrom(
66
+ padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
67
+ shape: RoundedRectangleBorder(
68
+ borderRadius: BorderRadius.circular(12),
69
+ ),
70
+ ),
71
+ ),
72
+ );
73
+ }
74
+ }
@@ -0,0 +1,46 @@
1
+ import 'package:flutter/material.dart';
2
+ import 'package:flutter_riverpod/flutter_riverpod.dart';
3
+ import 'package:riverpod_annotation/riverpod_annotation.dart';
4
+ import 'app_theme.dart';
5
+
6
+ part 'theme_provider.g.dart';
7
+
8
+ {{#if modules.theme.darkMode}}
9
+ /// Notifier that manages the current [ThemeMode] (light, dark, or system).
10
+ @riverpod
11
+ class AppThemeMode extends _$AppThemeMode {
12
+ @override
13
+ ThemeMode build() => ThemeMode.system;
14
+
15
+ /// Set the theme mode to light.
16
+ void setLight() => state = ThemeMode.light;
17
+
18
+ /// Set the theme mode to dark.
19
+ void setDark() => state = ThemeMode.dark;
20
+
21
+ /// Set the theme mode to follow the system setting.
22
+ void setSystem() => state = ThemeMode.system;
23
+
24
+ /// Toggle between light and dark mode.
25
+ void toggle() {
26
+ state = state == ThemeMode.dark ? ThemeMode.light : ThemeMode.dark;
27
+ }
28
+ }
29
+ {{else}}
30
+ /// Provides the current theme mode. Dark mode is disabled; always returns light.
31
+ @riverpod
32
+ class AppThemeMode extends _$AppThemeMode {
33
+ @override
34
+ ThemeMode build() => ThemeMode.light;
35
+ }
36
+ {{/if}}
37
+
38
+ /// Provides the light [ThemeData] from [AppTheme].
39
+ @riverpod
40
+ ThemeData lightTheme(Ref ref) => AppTheme.light;
41
+
42
+ {{#if modules.theme.darkMode}}
43
+ /// Provides the dark [ThemeData] from [AppTheme].
44
+ @riverpod
45
+ ThemeData darkTheme(Ref ref) => AppTheme.dark;
46
+ {{/if}}
@@ -0,0 +1,2 @@
1
+ dependencies:
2
+ google_fonts: ^6.2.1