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.
- package/CHANGELOG.md +42 -0
- package/LICENSE +21 -0
- package/README.md +445 -0
- package/claude-plugin/.claude-plugin/plugin.json +46 -0
- package/claude-plugin/agents/flutter-setup-agent.md +54 -0
- package/claude-plugin/commands/flutter-add.md +32 -0
- package/claude-plugin/commands/flutter-create.md +28 -0
- package/claude-plugin/commands/flutter-migrate.md +28 -0
- package/claude-plugin/skills/flutter-scaffolding/SKILL.md +109 -0
- package/dist/claude-setup/agent-writer.d.ts +21 -0
- package/dist/claude-setup/agent-writer.d.ts.map +1 -0
- package/dist/claude-setup/agent-writer.js +365 -0
- package/dist/claude-setup/agent-writer.js.map +1 -0
- package/dist/claude-setup/claude-md-generator.d.ts +7 -0
- package/dist/claude-setup/claude-md-generator.d.ts.map +1 -0
- package/dist/claude-setup/claude-md-generator.js +428 -0
- package/dist/claude-setup/claude-md-generator.js.map +1 -0
- package/dist/claude-setup/commands-writer.d.ts +7 -0
- package/dist/claude-setup/commands-writer.d.ts.map +1 -0
- package/dist/claude-setup/commands-writer.js +303 -0
- package/dist/claude-setup/commands-writer.js.map +1 -0
- package/dist/claude-setup/hooks-writer.d.ts +3 -0
- package/dist/claude-setup/hooks-writer.d.ts.map +1 -0
- package/dist/claude-setup/hooks-writer.js +34 -0
- package/dist/claude-setup/hooks-writer.js.map +1 -0
- package/dist/claude-setup/index.d.ts +10 -0
- package/dist/claude-setup/index.d.ts.map +1 -0
- package/dist/claude-setup/index.js +9 -0
- package/dist/claude-setup/index.js.map +1 -0
- package/dist/claude-setup/mcp-config-writer.d.ts +3 -0
- package/dist/claude-setup/mcp-config-writer.d.ts.map +1 -0
- package/dist/claude-setup/mcp-config-writer.js +42 -0
- package/dist/claude-setup/mcp-config-writer.js.map +1 -0
- package/dist/claude-setup/plugin-assembler.d.ts +2 -0
- package/dist/claude-setup/plugin-assembler.d.ts.map +1 -0
- package/dist/claude-setup/plugin-assembler.js +3 -0
- package/dist/claude-setup/plugin-assembler.js.map +1 -0
- package/dist/claude-setup/prd-generator.d.ts +10 -0
- package/dist/claude-setup/prd-generator.d.ts.map +1 -0
- package/dist/claude-setup/prd-generator.js +295 -0
- package/dist/claude-setup/prd-generator.js.map +1 -0
- package/dist/claude-setup/setup-orchestrator.d.ts +11 -0
- package/dist/claude-setup/setup-orchestrator.d.ts.map +1 -0
- package/dist/claude-setup/setup-orchestrator.js +46 -0
- package/dist/claude-setup/setup-orchestrator.js.map +1 -0
- package/dist/claude-setup/skill-writer.d.ts +3 -0
- package/dist/claude-setup/skill-writer.d.ts.map +1 -0
- package/dist/claude-setup/skill-writer.js +256 -0
- package/dist/claude-setup/skill-writer.js.map +1 -0
- package/dist/cli/commands/add.d.ts +16 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +414 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/create.d.ts +3 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +161 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/list.d.ts +12 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +148 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +3 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +332 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +34 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ui/prompts.d.ts +9 -0
- package/dist/cli/ui/prompts.d.ts.map +1 -0
- package/dist/cli/ui/prompts.js +74 -0
- package/dist/cli/ui/prompts.js.map +1 -0
- package/dist/cli/ui/spinner.d.ts +2 -0
- package/dist/cli/ui/spinner.d.ts.map +1 -0
- package/dist/cli/ui/spinner.js +5 -0
- package/dist/cli/ui/spinner.js.map +1 -0
- package/dist/cli/version-check.d.ts +7 -0
- package/dist/cli/version-check.d.ts.map +1 -0
- package/dist/cli/version-check.js +92 -0
- package/dist/cli/version-check.js.map +1 -0
- package/dist/core/config/defaults.d.ts +3 -0
- package/dist/core/config/defaults.d.ts.map +1 -0
- package/dist/core/config/defaults.js +21 -0
- package/dist/core/config/defaults.js.map +1 -0
- package/dist/core/config/loader.d.ts +4 -0
- package/dist/core/config/loader.d.ts.map +1 -0
- package/dist/core/config/loader.js +38 -0
- package/dist/core/config/loader.js.map +1 -0
- package/dist/core/config/schema.d.ts +406 -0
- package/dist/core/config/schema.d.ts.map +1 -0
- package/dist/core/config/schema.js +119 -0
- package/dist/core/config/schema.js.map +1 -0
- package/dist/core/context.d.ts +57 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +99 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/detector.d.ts +28 -0
- package/dist/core/detector.d.ts.map +1 -0
- package/dist/core/detector.js +200 -0
- package/dist/core/detector.js.map +1 -0
- package/dist/core/validator.d.ts +7 -0
- package/dist/core/validator.d.ts.map +1 -0
- package/dist/core/validator.js +35 -0
- package/dist/core/validator.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/composer.d.ts +50 -0
- package/dist/modules/composer.d.ts.map +1 -0
- package/dist/modules/composer.js +122 -0
- package/dist/modules/composer.js.map +1 -0
- package/dist/modules/definitions/analytics/module.d.ts +7 -0
- package/dist/modules/definitions/analytics/module.d.ts.map +1 -0
- package/dist/modules/definitions/analytics/module.js +28 -0
- package/dist/modules/definitions/analytics/module.js.map +1 -0
- package/dist/modules/definitions/api/module.d.ts +7 -0
- package/dist/modules/definitions/api/module.d.ts.map +1 -0
- package/dist/modules/definitions/api/module.js +41 -0
- package/dist/modules/definitions/api/module.js.map +1 -0
- package/dist/modules/definitions/auth/module.d.ts +7 -0
- package/dist/modules/definitions/auth/module.d.ts.map +1 -0
- package/dist/modules/definitions/auth/module.js +53 -0
- package/dist/modules/definitions/auth/module.js.map +1 -0
- package/dist/modules/definitions/cicd/module.d.ts +7 -0
- package/dist/modules/definitions/cicd/module.d.ts.map +1 -0
- package/dist/modules/definitions/cicd/module.js +34 -0
- package/dist/modules/definitions/cicd/module.js.map +1 -0
- package/dist/modules/definitions/core/module.d.ts +7 -0
- package/dist/modules/definitions/core/module.d.ts.map +1 -0
- package/dist/modules/definitions/core/module.js +31 -0
- package/dist/modules/definitions/core/module.js.map +1 -0
- package/dist/modules/definitions/database/module.d.ts +8 -0
- package/dist/modules/definitions/database/module.d.ts.map +1 -0
- package/dist/modules/definitions/database/module.js +47 -0
- package/dist/modules/definitions/database/module.js.map +1 -0
- package/dist/modules/definitions/deep-linking/module.d.ts +7 -0
- package/dist/modules/definitions/deep-linking/module.d.ts.map +1 -0
- package/dist/modules/definitions/deep-linking/module.js +48 -0
- package/dist/modules/definitions/deep-linking/module.js.map +1 -0
- package/dist/modules/definitions/i18n/module.d.ts +7 -0
- package/dist/modules/definitions/i18n/module.d.ts.map +1 -0
- package/dist/modules/definitions/i18n/module.js +37 -0
- package/dist/modules/definitions/i18n/module.js.map +1 -0
- package/dist/modules/definitions/push/module.d.ts +7 -0
- package/dist/modules/definitions/push/module.d.ts.map +1 -0
- package/dist/modules/definitions/push/module.js +40 -0
- package/dist/modules/definitions/push/module.js.map +1 -0
- package/dist/modules/definitions/theme/module.d.ts +7 -0
- package/dist/modules/definitions/theme/module.d.ts.map +1 -0
- package/dist/modules/definitions/theme/module.js +42 -0
- package/dist/modules/definitions/theme/module.js.map +1 -0
- package/dist/modules/registry.d.ts +50 -0
- package/dist/modules/registry.d.ts.map +1 -0
- package/dist/modules/registry.js +104 -0
- package/dist/modules/registry.js.map +1 -0
- package/dist/modules/resolver.d.ts +42 -0
- package/dist/modules/resolver.d.ts.map +1 -0
- package/dist/modules/resolver.js +140 -0
- package/dist/modules/resolver.js.map +1 -0
- package/dist/ralph/prd-generator.d.ts +2 -0
- package/dist/ralph/prd-generator.d.ts.map +1 -0
- package/dist/ralph/prd-generator.js +3 -0
- package/dist/ralph/prd-generator.js.map +1 -0
- package/dist/ralph/ralph-converter.d.ts +2 -0
- package/dist/ralph/ralph-converter.d.ts.map +1 -0
- package/dist/ralph/ralph-converter.js +3 -0
- package/dist/ralph/ralph-converter.js.map +1 -0
- package/dist/ralph/story-sizer.d.ts +2 -0
- package/dist/ralph/story-sizer.d.ts.map +1 -0
- package/dist/ralph/story-sizer.js +3 -0
- package/dist/ralph/story-sizer.js.map +1 -0
- package/dist/scaffold/engine.d.ts +40 -0
- package/dist/scaffold/engine.d.ts.map +1 -0
- package/dist/scaffold/engine.js +233 -0
- package/dist/scaffold/engine.js.map +1 -0
- package/dist/scaffold/file-writer.d.ts +22 -0
- package/dist/scaffold/file-writer.d.ts.map +1 -0
- package/dist/scaffold/file-writer.js +68 -0
- package/dist/scaffold/file-writer.js.map +1 -0
- package/dist/scaffold/post-processors/build-runner.d.ts +2 -0
- package/dist/scaffold/post-processors/build-runner.d.ts.map +1 -0
- package/dist/scaffold/post-processors/build-runner.js +5 -0
- package/dist/scaffold/post-processors/build-runner.js.map +1 -0
- package/dist/scaffold/post-processors/dart-format.d.ts +2 -0
- package/dist/scaffold/post-processors/dart-format.d.ts.map +1 -0
- package/dist/scaffold/post-processors/dart-format.js +5 -0
- package/dist/scaffold/post-processors/dart-format.js.map +1 -0
- package/dist/scaffold/post-processors/flutter-pub-get.d.ts +2 -0
- package/dist/scaffold/post-processors/flutter-pub-get.d.ts.map +1 -0
- package/dist/scaffold/post-processors/flutter-pub-get.js +5 -0
- package/dist/scaffold/post-processors/flutter-pub-get.js.map +1 -0
- package/dist/scaffold/renderer.d.ts +20 -0
- package/dist/scaffold/renderer.d.ts.map +1 -0
- package/dist/scaffold/renderer.js +75 -0
- package/dist/scaffold/renderer.js.map +1 -0
- package/dist/scaffold/template-helpers.d.ts +25 -0
- package/dist/scaffold/template-helpers.d.ts.map +1 -0
- package/dist/scaffold/template-helpers.js +115 -0
- package/dist/scaffold/template-helpers.js.map +1 -0
- package/dist/types/config.d.ts +4 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/module.d.ts +85 -0
- package/dist/types/module.d.ts.map +1 -0
- package/dist/types/module.js +2 -0
- package/dist/types/module.js.map +1 -0
- package/dist/types/project.d.ts +13 -0
- package/dist/types/project.d.ts.map +1 -0
- package/dist/types/project.js +2 -0
- package/dist/types/project.js.map +1 -0
- package/package.json +80 -0
- package/templates/core/analysis_options.yaml.hbs +21 -0
- package/templates/core/lib/app.dart.hbs +20 -0
- package/templates/core/lib/core/providers/app_providers.dart.hbs +3 -0
- package/templates/core/lib/core/router/app_router.dart.hbs +19 -0
- package/templates/core/lib/core/theme/app_theme.dart.hbs +15 -0
- package/templates/core/lib/features/home/data/models/.gitkeep +0 -0
- package/templates/core/lib/features/home/data/repositories/.gitkeep +0 -0
- package/templates/core/lib/features/home/domain/entities/.gitkeep +0 -0
- package/templates/core/lib/features/home/domain/repositories/.gitkeep +0 -0
- package/templates/core/lib/features/home/presentation/pages/home_page.dart.hbs +18 -0
- package/templates/core/lib/features/home/presentation/widgets/.gitkeep +0 -0
- package/templates/core/lib/main.dart.hbs +11 -0
- package/templates/core/pubspec.yaml.hbs +30 -0
- package/templates/core/test/widget_test.dart.hbs +16 -0
- package/templates/modules/analytics/lib/features/analytics/data/observers/analytics_route_observer.dart.hbs +53 -0
- package/templates/modules/analytics/lib/features/analytics/data/services/firebase_analytics_service.dart.hbs +39 -0
- package/templates/modules/analytics/lib/features/analytics/domain/services/analytics_service.dart.hbs +25 -0
- package/templates/modules/analytics/lib/features/analytics/presentation/providers/analytics_provider.dart.hbs +17 -0
- package/templates/modules/analytics/pubspec.partial.yaml +2 -0
- package/templates/modules/api/lib/features/api/data/datasources/api_client.dart.hbs +171 -0
- package/templates/modules/api/lib/features/api/data/interceptors/auth_interceptor.dart.hbs +25 -0
- package/templates/modules/api/lib/features/api/data/interceptors/retry_interceptor.dart.hbs +42 -0
- package/templates/modules/api/lib/features/api/data/repositories/api_repository_impl.dart.hbs +21 -0
- package/templates/modules/api/lib/features/api/domain/exceptions/api_exception.dart.hbs +31 -0
- package/templates/modules/api/lib/features/api/domain/repositories/api_repository.dart.hbs +8 -0
- package/templates/modules/api/lib/features/api/presentation/providers/api_provider.dart.hbs +17 -0
- package/templates/modules/api/pubspec.partial.yaml +7 -0
- package/templates/modules/auth/lib/features/auth/data/datasources/auth_remote_datasource.dart.hbs +181 -0
- package/templates/modules/auth/lib/features/auth/data/models/auth_user_model.dart.hbs +27 -0
- package/templates/modules/auth/lib/features/auth/data/repositories/auth_repository_impl.dart.hbs +49 -0
- package/templates/modules/auth/lib/features/auth/domain/entities/user_entity.dart.hbs +18 -0
- package/templates/modules/auth/lib/features/auth/domain/repositories/auth_repository.dart.hbs +22 -0
- package/templates/modules/auth/lib/features/auth/domain/usecases/register_usecase.dart.hbs +20 -0
- package/templates/modules/auth/lib/features/auth/domain/usecases/sign_in_usecase.dart.hbs +15 -0
- package/templates/modules/auth/lib/features/auth/domain/usecases/sign_out_usecase.dart.hbs +11 -0
- package/templates/modules/auth/lib/features/auth/presentation/pages/login_page.dart.hbs +118 -0
- package/templates/modules/auth/lib/features/auth/presentation/pages/register_page.dart.hbs +131 -0
- package/templates/modules/auth/lib/features/auth/presentation/providers/auth_provider.dart.hbs +31 -0
- package/templates/modules/auth/pubspec.partial.yaml +13 -0
- package/templates/modules/cicd/.github/workflows/ci.yml.hbs +45 -0
- package/templates/modules/cicd/.gitlab-ci.yml.hbs +53 -0
- package/templates/modules/cicd/bitbucket-pipelines.yml.hbs +39 -0
- package/templates/modules/cicd/pubspec.partial.yaml +1 -0
- package/templates/modules/database/lib/features/database/data/datasources/database_datasource.dart.hbs +115 -0
- package/templates/modules/database/lib/features/database/data/repositories/database_repository_impl.dart.hbs +73 -0
- package/templates/modules/database/lib/features/database/domain/repositories/database_repository.dart.hbs +10 -0
- package/templates/modules/database/lib/features/database/presentation/providers/database_provider.dart.hbs +43 -0
- package/templates/modules/database/pubspec.partial.yaml +27 -0
- package/templates/modules/deep-linking/lib/features/deep_linking/data/datasources/deep_link_datasource.dart.hbs +18 -0
- package/templates/modules/deep-linking/lib/features/deep_linking/data/repositories/deep_link_repository_impl.dart.hbs +14 -0
- package/templates/modules/deep-linking/lib/features/deep_linking/domain/repositories/deep_link_repository.dart.hbs +7 -0
- package/templates/modules/deep-linking/lib/features/deep_linking/presentation/providers/deep_link_provider.dart.hbs +57 -0
- package/templates/modules/deep-linking/pubspec.partial.yaml +2 -0
- package/templates/modules/i18n/l10n.yaml.hbs +5 -0
- package/templates/modules/i18n/lib/core/l10n/l10n_config.dart.hbs +29 -0
- package/templates/modules/i18n/lib/core/l10n/l10n_provider.dart.hbs +20 -0
- package/templates/modules/i18n/lib/l10n/app_de.arb.hbs +27 -0
- package/templates/modules/i18n/lib/l10n/app_en.arb.hbs +27 -0
- package/templates/modules/i18n/pubspec.partial.yaml +7 -0
- package/templates/modules/push/lib/features/push/data/datasources/push_datasource.dart.hbs +124 -0
- package/templates/modules/push/lib/features/push/data/repositories/push_repository_impl.dart.hbs +28 -0
- package/templates/modules/push/lib/features/push/domain/repositories/push_repository.dart.hbs +31 -0
- package/templates/modules/push/lib/features/push/presentation/providers/push_provider.dart.hbs +34 -0
- package/templates/modules/push/pubspec.partial.yaml +8 -0
- package/templates/modules/theme/lib/core/theme/app_theme.dart.hbs +74 -0
- package/templates/modules/theme/lib/core/theme/theme_provider.dart.hbs +46 -0
- package/templates/modules/theme/pubspec.partial.yaml +2 -0
|
@@ -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}}
|
package/templates/modules/push/lib/features/push/data/repositories/push_repository_impl.dart.hbs
ADDED
|
@@ -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
|
+
}
|
package/templates/modules/push/lib/features/push/presentation/providers/push_provider.dart.hbs
ADDED
|
@@ -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,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}}
|