kasy-cli 1.12.1 → 1.14.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 (249) hide show
  1. package/bin/kasy.js +143 -7
  2. package/lib/commands/add.js +2 -2
  3. package/lib/commands/codemagic.js +11 -4
  4. package/lib/commands/deploy.js +3 -3
  5. package/lib/commands/favicon.js +115 -0
  6. package/lib/commands/icon.js +143 -0
  7. package/lib/commands/ios.js +20 -5
  8. package/lib/commands/new.js +8 -20
  9. package/lib/commands/remove.js +1 -1
  10. package/lib/commands/reset.js +287 -0
  11. package/lib/commands/run.js +24 -17
  12. package/lib/commands/splash.js +219 -0
  13. package/lib/commands/update.js +1 -1
  14. package/lib/scaffold/CHANGELOG.json +9 -0
  15. package/lib/scaffold/backends/api/patch/README.md +1 -1
  16. package/lib/scaffold/backends/api/patch/android/app/src/main/AndroidManifest.xml +1 -1
  17. package/lib/scaffold/backends/api/patch/lib/features/notifications/api/device_api.dart +53 -0
  18. package/lib/scaffold/backends/api/patch/lib/main.dart +29 -10
  19. package/lib/scaffold/backends/api/pubspec.yaml.tpl +11 -1
  20. package/lib/scaffold/backends/firebase/tokens.js +2 -2
  21. package/lib/scaffold/backends/supabase/edge-functions/send-push-notification/index.ts +8 -2
  22. package/lib/scaffold/backends/supabase/migrations/20240101000011_dedupe_device_tokens.sql +34 -0
  23. package/lib/scaffold/backends/supabase/patch/README.md +1 -1
  24. package/lib/scaffold/backends/supabase/patch/android/app/src/main/AndroidManifest.xml +1 -1
  25. package/lib/scaffold/backends/supabase/patch/lib/features/notifications/api/device_api.dart +43 -0
  26. package/lib/scaffold/backends/supabase/patch/lib/main.dart +29 -10
  27. package/lib/scaffold/backends/supabase/pubspec.yaml.tpl +11 -1
  28. package/lib/scaffold/features/README.md +15 -139
  29. package/lib/scaffold/shared/generator-utils.js +16 -15
  30. package/lib/utils/apple-release.js +85 -16
  31. package/lib/utils/checks.js +4 -105
  32. package/lib/utils/flutter-run.js +173 -0
  33. package/lib/utils/i18n.js +413 -0
  34. package/lib/utils/mobile-identity.js +35 -0
  35. package/lib/utils/ui.js +114 -0
  36. package/package.json +2 -3
  37. package/templates/firebase/README.en.md +1 -1
  38. package/templates/firebase/README.es.md +1 -1
  39. package/templates/firebase/README.md +1 -1
  40. package/templates/firebase/android/app/build.gradle.kts +10 -1
  41. package/templates/firebase/android/app/src/main/AndroidManifest.xml +1 -1
  42. package/templates/firebase/android/app/src/main/kotlin/com/aicrus/firebase/kit/MainActivity.kt +25 -1
  43. package/templates/firebase/android/app/src/main/kotlin/com/aicrus/firebase/kit/MyWidget.kt +160 -11
  44. package/templates/firebase/android/app/src/main/res/drawable/widget_add_button.xml +15 -0
  45. package/templates/firebase/android/app/src/main/res/drawable/widget_gradient_bg.xml +9 -0
  46. package/templates/firebase/android/app/src/main/res/drawable/widget_gradient_inner.xml +12 -0
  47. package/templates/firebase/android/app/src/main/res/drawable/widget_plan_pill_bg.xml +5 -0
  48. package/templates/firebase/android/app/src/main/res/drawable/widget_preview_image.xml +17 -0
  49. package/templates/firebase/android/app/src/main/res/drawable/widget_pro_pill_bg.xml +5 -0
  50. package/templates/firebase/android/app/src/main/res/drawable-hdpi/android12splash.png +0 -0
  51. package/templates/firebase/android/app/src/main/res/drawable-hdpi/splash.png +0 -0
  52. package/templates/firebase/android/app/src/main/res/drawable-mdpi/android12splash.png +0 -0
  53. package/templates/firebase/android/app/src/main/res/drawable-mdpi/splash.png +0 -0
  54. package/templates/firebase/android/app/src/main/res/drawable-night/background.png +0 -0
  55. package/templates/firebase/android/app/src/main/res/drawable-night/launch_background.xml +9 -0
  56. package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/android12splash.png +0 -0
  57. package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/splash.png +0 -0
  58. package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/android12splash.png +0 -0
  59. package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/splash.png +0 -0
  60. package/templates/firebase/android/app/src/main/res/drawable-night-v21/background.png +0 -0
  61. package/templates/firebase/android/app/src/main/res/drawable-night-v21/launch_background.xml +9 -0
  62. package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/android12splash.png +0 -0
  63. package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/splash.png +0 -0
  64. package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png +0 -0
  65. package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/splash.png +0 -0
  66. package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png +0 -0
  67. package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/splash.png +0 -0
  68. package/templates/firebase/android/app/src/main/res/drawable-xhdpi/android12splash.png +0 -0
  69. package/templates/firebase/android/app/src/main/res/drawable-xhdpi/splash.png +0 -0
  70. package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/android12splash.png +0 -0
  71. package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/splash.png +0 -0
  72. package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/android12splash.png +0 -0
  73. package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/splash.png +0 -0
  74. package/templates/firebase/android/app/src/main/res/layout/widget_loading.xml +8 -0
  75. package/templates/firebase/android/app/src/main/res/layout/widget_preview.xml +46 -0
  76. package/templates/firebase/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  77. package/templates/firebase/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  78. package/templates/firebase/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  79. package/templates/firebase/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  80. package/templates/firebase/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  81. package/templates/firebase/android/app/src/main/res/values-night-v31/styles.xml +2 -1
  82. package/templates/firebase/android/app/src/main/res/values-v31/styles.xml +1 -0
  83. package/templates/firebase/android/app/src/main/res/xml/mywidget_info.xml +9 -3
  84. package/templates/firebase/assets/images/favicon.png +0 -0
  85. package/templates/firebase/assets/images/icon.png +0 -0
  86. package/templates/firebase/assets/images/splash_logo_dark.png +0 -0
  87. package/templates/firebase/assets/images/splash_logo_light.png +0 -0
  88. package/templates/firebase/firestore.indexes.json +10 -0
  89. package/templates/firebase/functions/src/core/data/entities/user_device_entity.ts +3 -0
  90. package/templates/firebase/functions/src/core/data/repositories/user_device_repository.ts +17 -1
  91. package/templates/firebase/functions/src/index.ts +1 -0
  92. package/templates/firebase/functions/src/notifications/device_triggers.ts +58 -0
  93. package/templates/firebase/ios/HomeWidgetExtension/MyWidget.swift +116 -33
  94. package/templates/firebase/ios/Runner/AppDelegate.swift +17 -1
  95. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png +0 -0
  96. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png +0 -0
  97. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png +0 -0
  98. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png +0 -0
  99. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png +0 -0
  100. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png +0 -0
  101. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png +0 -0
  102. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png +0 -0
  103. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png +0 -0
  104. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png +0 -0
  105. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png +0 -0
  106. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png +0 -0
  107. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png +0 -0
  108. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png +0 -0
  109. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png +0 -0
  110. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png +0 -0
  111. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png +0 -0
  112. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png +0 -0
  113. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png +0 -0
  114. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png +0 -0
  115. package/templates/firebase/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png +0 -0
  116. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json +9 -8
  117. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png +0 -0
  118. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +33 -0
  119. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
  120. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
  121. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
  122. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png +0 -0
  123. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png +0 -0
  124. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png +0 -0
  125. package/templates/firebase/ios/Runner/Base.lproj/LaunchScreen.storyboard +1 -1
  126. package/templates/firebase/ios/Runner/Info.plist +2 -2
  127. package/templates/firebase/ios/Runner/es.lproj/InfoPlist.strings +1 -1
  128. package/templates/firebase/ios/Runner/pt-BR.lproj/InfoPlist.strings +1 -1
  129. package/templates/firebase/ios/Runner/pt.lproj/InfoPlist.strings +1 -1
  130. package/templates/firebase/lib/components/kasy_button.dart +8 -0
  131. package/templates/firebase/lib/core/bottom_menu/kasy_bottom_bar_factory.dart +18 -0
  132. package/templates/firebase/lib/core/home_widgets/home_widget_mywidget_service.dart +67 -19
  133. package/templates/firebase/lib/core/home_widgets/home_widget_service.dart +22 -8
  134. package/templates/firebase/lib/core/shared_preferences/shared_preferences.dart +16 -4
  135. package/templates/firebase/lib/core/states/components/maybeshow_component.dart +4 -8
  136. package/templates/firebase/lib/core/states/user_state_notifier.dart +13 -1
  137. package/templates/firebase/lib/core/theme/providers/theme_provider.dart +48 -24
  138. package/templates/firebase/lib/features/home/home_page.dart +0 -6
  139. package/templates/firebase/lib/features/notifications/api/device_api.dart +57 -0
  140. package/templates/firebase/lib/features/notifications/providers/models/notification.dart +11 -1
  141. package/templates/firebase/lib/features/notifications/repositories/device_repository.dart +9 -0
  142. package/templates/firebase/lib/features/notifications/repositories/notifications_repository.dart +1 -4
  143. package/templates/firebase/lib/features/notifications/shared/att_permission.dart +28 -8
  144. package/templates/firebase/lib/features/notifications/ui/notifications_page.dart +16 -1
  145. package/templates/firebase/lib/features/notifications/ui/widgets/empty_notifications.dart +44 -11
  146. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_features.dart +4 -0
  147. package/templates/firebase/lib/features/onboarding/ui/onboarding_page.dart +1 -0
  148. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_feature.dart +13 -0
  149. package/templates/firebase/lib/features/settings/settings_page.dart +158 -18
  150. package/templates/firebase/lib/features/settings/ui/components/admin/admin_bottom_sheet.dart +31 -29
  151. package/templates/firebase/lib/features/settings/ui/components/language_switcher.dart +21 -5
  152. package/templates/firebase/lib/i18n/en.i18n.json +10 -3
  153. package/templates/firebase/lib/i18n/es.i18n.json +10 -3
  154. package/templates/firebase/lib/i18n/pt.i18n.json +10 -3
  155. package/templates/firebase/lib/main.dart +29 -10
  156. package/templates/firebase/pubspec.yaml +10 -6
  157. package/templates/firebase/test/core/data/repositories/user_repository_test.dart +1 -1
  158. package/templates/firebase/test/features/notifications/data/device_api_fake.dart +9 -0
  159. package/templates/firebase/web/favicon.png +0 -0
  160. package/templates/firebase/web/icons/Icon-192.png +0 -0
  161. package/templates/firebase/web/icons/Icon-512.png +0 -0
  162. package/templates/firebase/web/icons/Icon-maskable-192.png +0 -0
  163. package/templates/firebase/web/icons/Icon-maskable-512.png +0 -0
  164. package/templates/firebase/web/index.html +50 -39
  165. package/templates/firebase/web/manifest.json +3 -3
  166. package/templates/firebase/web/splash/img/dark-1x.png +0 -0
  167. package/templates/firebase/web/splash/img/dark-2x.png +0 -0
  168. package/templates/firebase/web/splash/img/dark-3x.png +0 -0
  169. package/templates/firebase/web/splash/img/dark-4x.png +0 -0
  170. package/templates/firebase/web/splash/img/light-1x.png +0 -0
  171. package/templates/firebase/web/splash/img/light-2x.png +0 -0
  172. package/templates/firebase/web/splash/img/light-3x.png +0 -0
  173. package/templates/firebase/web/splash/img/light-4x.png +0 -0
  174. package/lib/scaffold/features/analytics/lib/core/data/api/analytics_api.dart +0 -124
  175. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.es.md +0 -35
  176. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.md +0 -35
  177. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.pt.md +0 -35
  178. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.es.md +0 -12
  179. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.md +0 -12
  180. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.pt.md +0 -12
  181. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.es.md +0 -17
  182. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  183. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.pt.md +0 -17
  184. package/lib/scaffold/features/ci/.github/dependabot.yml +0 -16
  185. package/lib/scaffold/features/ci/.github/workflows/app.yml +0 -20
  186. package/lib/scaffold/features/ci/.gitlab/templates/deploy.yaml +0 -14
  187. package/lib/scaffold/features/ci/.gitlab/templates/dropbox.yaml +0 -19
  188. package/lib/scaffold/features/ci/.gitlab/templates/flutter.yaml +0 -163
  189. package/lib/scaffold/features/ci/.gitlab/templates/mailgun.yaml +0 -28
  190. package/lib/scaffold/features/ci/.gitlab-ci.yml +0 -37
  191. package/lib/scaffold/features/ci/codemagic.yaml +0 -157
  192. package/lib/scaffold/features/facebook/lib/core/data/api/tracking_api.dart +0 -111
  193. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_request_entity.dart +0 -27
  194. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_vote_entity.dart +0 -27
  195. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_request_api.dart +0 -50
  196. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_vote_api.dart +0 -79
  197. package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feature_requests.dart +0 -48
  198. package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feedback_state.dart +0 -42
  199. package/lib/scaffold/features/feedback/lib/features/feedbacks/providers/feedback_page_notifier.dart +0 -147
  200. package/lib/scaffold/features/feedback/lib/features/feedbacks/repositories/feature_request_repository.dart +0 -95
  201. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/component/add_feature_form.dart +0 -199
  202. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/feedback_page.dart +0 -175
  203. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/add_feature_button.dart +0 -76
  204. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/feature_card.dart +0 -279
  205. package/lib/scaffold/features/ios-release/.kasy/apple.env.example +0 -8
  206. package/lib/scaffold/features/ios-release/.kasy/codemagic.env.example +0 -7
  207. package/lib/scaffold/features/ios-release/docs/codemagic-release.en.md +0 -50
  208. package/lib/scaffold/features/ios-release/docs/codemagic-release.es.md +0 -50
  209. package/lib/scaffold/features/ios-release/docs/codemagic-release.pt.md +0 -50
  210. package/lib/scaffold/features/ios-release/docs/ios-release.en.md +0 -41
  211. package/lib/scaffold/features/ios-release/docs/ios-release.es.md +0 -41
  212. package/lib/scaffold/features/ios-release/docs/ios-release.pt.md +0 -41
  213. package/lib/scaffold/features/ios-release/scripts/bump-ios-version.js +0 -38
  214. package/lib/scaffold/features/ios-release/scripts/release-ios.sh +0 -137
  215. package/lib/scaffold/features/llm_chat/lib/features/llm_chat/llm_chat_page.dart +0 -301
  216. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/providers/reminder_notifier.dart +0 -81
  217. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/repositories/reminder_preferences.dart +0 -76
  218. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/ui/reminder_page.dart +0 -282
  219. package/lib/scaffold/features/onboarding/lib/features/onboarding/api/entities/user_info_entity.dart +0 -24
  220. package/lib/scaffold/features/onboarding/lib/features/onboarding/api/user_infos_api.dart +0 -71
  221. package/lib/scaffold/features/onboarding/lib/features/onboarding/models/user_info.dart +0 -92
  222. package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_model.dart +0 -15
  223. package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_provider.dart +0 -78
  224. package/lib/scaffold/features/onboarding/lib/features/onboarding/repositories/user_infos_repository.dart +0 -29
  225. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/animations/page_transitions.dart +0 -30
  226. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_att_setup.dart +0 -66
  227. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_features.dart +0 -72
  228. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_loader.dart +0 -92
  229. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_notifications_setup.dart +0 -73
  230. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_questions.dart +0 -89
  231. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/onboarding_page.dart +0 -94
  232. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_background.dart +0 -80
  233. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_feature.dart +0 -139
  234. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart +0 -110
  235. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_progress.dart +0 -84
  236. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +0 -173
  237. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_reassurance.dart +0 -45
  238. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_sticky_footer.dart +0 -77
  239. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +0 -392
  240. package/lib/scaffold/features/revenuecat/lib/core/data/api/tracking_api.dart +0 -116
  241. package/lib/scaffold/features/revenuecat/lib/core/data/models/subscription.dart +0 -322
  242. package/lib/scaffold/features/revenuecat/lib/core/home_widgets/home_widget_background_task.dart +0 -41
  243. package/lib/scaffold/features/revenuecat/lib/core/states/user_state_notifier.dart +0 -305
  244. package/templates/firebase/assets/images/app_icon.png +0 -0
  245. package/templates/firebase/assets/images/onboarding/img1.jpg +0 -0
  246. package/templates/firebase/assets/images/onboarding/onboarding.png +0 -0
  247. package/templates/firebase/assets/images/splashscreen.png +0 -0
  248. package/templates/firebase/lib/core/states/components/maybe_ask_biometric_setup.dart +0 -88
  249. package/templates/firebase/lib/features/notifications/shared/notification_permission_bottom_sheet.dart +0 -144
@@ -1,392 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:kasy_kit/core/theme/theme.dart';
3
-
4
- typedef OnSelectRow = void Function(int index, bool selected);
5
-
6
- /// Ex of usage
7
- /// SelectableRowGroup(
8
- /// onSelect: (index, selected) => onSelect(snapshot.data![index]),
9
- /// options: snapshot.data!
10
- /// .map(
11
- /// (e) => SelectableOption(
12
- /// title: e.name,
13
- /// subtitle: "Created on ${e.formattedCreationDate}",
14
- /// ),
15
- /// )
16
- /// .toList(),
17
- /// )
18
- class OnboardingSelectableRowGroup extends StatefulWidget {
19
- final List<Widget> options;
20
- final List<Widget?>? onSelectInfoWidget;
21
- final OnSelectRow? onSelect;
22
- final int? initialSelectedIndex;
23
- final ScrollPhysics? physics;
24
-
25
- const OnboardingSelectableRowGroup({
26
- super.key,
27
- required this.options,
28
- this.onSelect,
29
- this.initialSelectedIndex,
30
- this.onSelectInfoWidget,
31
- this.physics,
32
- });
33
-
34
- @override
35
- State<OnboardingSelectableRowGroup> createState() =>
36
- _OnboardingSelectableRowGroupState();
37
- }
38
-
39
- class _OnboardingSelectableRowGroupState
40
- extends State<OnboardingSelectableRowGroup> {
41
- int? _selectedIndex;
42
-
43
- @override
44
- void initState() {
45
- _selectedIndex = widget.initialSelectedIndex;
46
- super.initState();
47
- }
48
-
49
- @override
50
- Widget build(BuildContext context) {
51
- return ListView.separated(
52
- physics: widget.physics,
53
- shrinkWrap: true,
54
- separatorBuilder: (context, index) => const SizedBox(height: KasySpacing.sm),
55
- itemCount: widget.options.length,
56
- itemBuilder: (context, index) {
57
- final hasOnSelectInfo = widget.onSelectInfoWidget != null &&
58
- widget.onSelectInfoWidget!.length > index &&
59
- widget.onSelectInfoWidget![index] != null;
60
- return Column(
61
- crossAxisAlignment: CrossAxisAlignment.stretch,
62
- children: [
63
- Material(
64
- color: Colors.transparent,
65
- borderRadius: KasyRadius.mdBorderRadius,
66
- child: InkWell(
67
- onTap: () {
68
- if (_selectedIndex == index) {
69
- return;
70
- }
71
- setState(() {
72
- _selectedIndex = index;
73
- });
74
- widget.onSelect?.call(index, true);
75
- },
76
- child: switch (hasOnSelectInfo && _selectedIndex == index) {
77
- false => widget.options[index],
78
- true => widget.options[index],
79
- },
80
- ),
81
- ),
82
- if (hasOnSelectInfo && _selectedIndex == index)
83
- Padding(
84
- padding: const EdgeInsets.only(top: KasySpacing.sm, bottom: KasySpacing.md),
85
- child: widget.onSelectInfoWidget![index],
86
- ),
87
- ],
88
- );
89
- },
90
- );
91
- }
92
- }
93
-
94
- class OnboardingMultiSelectableRowGroup extends StatefulWidget {
95
- final List<SelectableOption> options;
96
- final OnSelectRow? onSelect;
97
- final ScrollPhysics? physics;
98
- // final int? initialSelectedIndex;
99
-
100
- const OnboardingMultiSelectableRowGroup({
101
- super.key,
102
- required this.options,
103
- this.onSelect,
104
- this.physics,
105
- });
106
-
107
- @override
108
- State<OnboardingMultiSelectableRowGroup> createState() =>
109
- _OnboardingMultiSelectableRowGroupState();
110
- }
111
-
112
- class _OnboardingMultiSelectableRowGroupState
113
- extends State<OnboardingMultiSelectableRowGroup> {
114
- final Set<int> _selectedIndex = {};
115
-
116
- @override
117
- void initState() {
118
- super.initState();
119
- }
120
-
121
- @override
122
- Widget build(BuildContext context) {
123
- return Wrap(
124
- spacing: KasySpacing.sm,
125
- runSpacing: KasySpacing.sm,
126
- children: widget.options.map((option) {
127
- final index = widget.options.indexOf(option);
128
- return Material(
129
- color: Colors.transparent,
130
- borderRadius: KasyRadius.mdBorderRadius,
131
- child: InkWell(
132
- splashColor: context.colors.primary.withValues(alpha:.1),
133
- onTap: () {
134
- if (_selectedIndex.contains(index)) {
135
- _selectedIndex.remove(index);
136
- widget.onSelect?.call(index, false);
137
- } else {
138
- _selectedIndex.add(index);
139
- widget.onSelect?.call(index, true);
140
- }
141
- setState(() {});
142
- },
143
- child: SelectableRowTile(
144
- title: option.title,
145
- subtitle: option.subtitle,
146
- selected: _selectedIndex.contains(index),
147
- emoj: option.emoj,
148
- ),
149
- ),
150
- );
151
- }).toList(),
152
- );
153
- }
154
- }
155
-
156
- class SelectableOption {
157
- final String title;
158
- final String? subtitle;
159
- final String? emoj;
160
- final bool selected;
161
-
162
- const SelectableOption({
163
- required this.title,
164
- this.subtitle,
165
- this.selected = false,
166
- this.emoj,
167
- });
168
- }
169
-
170
- /// Single row tile with a selectable radio box
171
- class SelectableRowTile extends StatefulWidget {
172
- final String? title;
173
- final String? subtitle;
174
- final String? emoj;
175
- final bool selected;
176
- final VoidCallback? onTap;
177
-
178
- const SelectableRowTile({
179
- super.key,
180
- this.title,
181
- this.subtitle,
182
- this.selected = false,
183
- this.onTap,
184
- this.emoj,
185
- });
186
-
187
- @override
188
- State<SelectableRowTile> createState() => _SelectableRowTileState();
189
- }
190
-
191
- class _SelectableRowTileState extends State<SelectableRowTile>
192
- with SingleTickerProviderStateMixin {
193
- late final AnimationController _controller;
194
- late final Animation<double> _opacityAnimation;
195
- late final Animation<double> _iconSizeAnimation;
196
-
197
- @override
198
- void initState() {
199
- super.initState();
200
- _controller = AnimationController(
201
- duration: const Duration(milliseconds: 500),
202
- vsync: this,
203
- );
204
- _opacityAnimation = Tween(
205
- begin: 0.0,
206
- end: 1.0,
207
- ).animate(
208
- CurvedAnimation(parent: _controller, curve: Curves.ease),
209
- );
210
- _iconSizeAnimation = Tween(
211
- begin: 0.0,
212
- end: 1.0,
213
- ).animate(
214
- CurvedAnimation(parent: _controller, curve: Curves.elasticOut),
215
- );
216
- if (widget.selected) {
217
- _controller.forward();
218
- }
219
- }
220
-
221
- @override
222
- void dispose() {
223
- _controller.dispose();
224
- super.dispose();
225
- }
226
-
227
- @override
228
- void didChangeDependencies() {
229
- super.didChangeDependencies();
230
- }
231
-
232
- @override
233
- void didUpdateWidget(covariant SelectableRowTile oldWidget) {
234
- super.didUpdateWidget(oldWidget);
235
- if (oldWidget.selected != widget.selected && widget.selected) {
236
- _controller.forward();
237
- } else if (oldWidget.selected != widget.selected && !widget.selected) {
238
- _controller.reverse();
239
- }
240
- }
241
-
242
- @override
243
- Widget build(BuildContext context) {
244
- return Ink(
245
- decoration: BoxDecoration(
246
- border: Border.all(
247
- color: widget.selected //
248
- ? context.colors.primary.withValues(alpha:.6)
249
- : context.colors.primary.withValues(alpha:.1),
250
- width: widget.selected ? 2 : 1,
251
- ),
252
- borderRadius: KasyRadius.mdBorderRadius,
253
- color: widget.selected
254
- ? context.colors.primary.withValues(alpha:.3)
255
- : context.colors.surface,
256
- ),
257
- padding: const EdgeInsets.symmetric(horizontal: KasySpacing.lg, vertical: KasySpacing.md),
258
- child: Row(
259
- children: [
260
- if (widget.emoj != null)
261
- Flexible(
262
- flex: 0,
263
- child: Padding(
264
- padding: const EdgeInsets.only(right: KasySpacing.md),
265
- child: Text(
266
- widget.emoj!,
267
- style: context.textTheme.titleMedium?.copyWith(
268
- fontSize: 28,
269
- ),
270
- ),
271
- ),
272
- ),
273
- Expanded(
274
- child: Column(
275
- crossAxisAlignment: CrossAxisAlignment.start,
276
- children: [
277
- if (widget.title != null)
278
- Text(
279
- widget.title!,
280
- style: context.textTheme.bodyLarge?.copyWith(
281
- fontWeight: FontWeight.w400,
282
- ),
283
- ),
284
- if (widget.subtitle != null)
285
- Padding(
286
- padding: const EdgeInsets.only(top: KasySpacing.xs),
287
- child: Text(
288
- widget.subtitle!,
289
- style: context.textTheme.bodySmall?.copyWith(
290
- color: context.colors.muted,
291
- ),
292
- ),
293
- ),
294
- ],
295
- ),
296
- ),
297
- const SizedBox(width: KasySpacing.sm),
298
- if (!widget.selected)
299
- Flexible(
300
- flex: 0,
301
- child: RoundRadioBox.unselected(context),
302
- ),
303
- if (widget.selected)
304
- Flexible(
305
- flex: 0,
306
- child: AnimatedBuilder(
307
- animation: _controller,
308
- builder: (context, child) {
309
- return RoundRadioBox.selected(
310
- context,
311
- iconOpacity: _opacityAnimation.value,
312
- iconSize: _iconSizeAnimation.value,
313
- );
314
- },
315
- ),
316
- ),
317
- ],
318
- ),
319
- );
320
- }
321
- }
322
-
323
- class RoundRadioBox extends StatelessWidget {
324
- final Color bgColor;
325
- final Color borderColor;
326
- final IconData? icon;
327
- final double iconOpacity;
328
- final double iconSize;
329
-
330
- const RoundRadioBox({
331
- super.key,
332
- required this.bgColor,
333
- required this.borderColor,
334
- this.iconOpacity = 1,
335
- this.iconSize = 1,
336
- this.icon,
337
- });
338
-
339
- factory RoundRadioBox.selected(
340
- BuildContext context, {
341
- double iconOpacity = 1,
342
- double iconSize = 1,
343
- }) {
344
- return RoundRadioBox(
345
- bgColor: context.colors.background.withValues(alpha:.3),
346
- borderColor: context.colors.onPrimary.withValues(alpha:.3),
347
- icon: Icons.check,
348
- iconOpacity: iconOpacity,
349
- iconSize: iconSize,
350
- );
351
- }
352
-
353
- // ignore: avoid_unused_constructor_parameters
354
- factory RoundRadioBox.unselected(BuildContext context) {
355
- return RoundRadioBox(
356
- bgColor: context.colors.outline,
357
- borderColor: context.colors.surface.withValues(alpha:.1),
358
- );
359
- }
360
-
361
- @override
362
- Widget build(BuildContext context) {
363
- return Container(
364
- width: 28,
365
- height: 28,
366
- decoration: BoxDecoration(
367
- color: bgColor,
368
- shape: BoxShape.circle,
369
- border: Border.all(
370
- color: borderColor,
371
- width: 4,
372
- strokeAlign: BorderSide.strokeAlignOutside,
373
- ),
374
- ),
375
- child: Center(
376
- child: icon != null
377
- ? Opacity(
378
- opacity: iconOpacity,
379
- child: Transform.scale(
380
- scale: iconSize,
381
- child: Icon(
382
- icon,
383
- color: context.colors.muted,
384
- size: 21,
385
- ),
386
- ),
387
- )
388
- : const SizedBox.shrink(),
389
- ),
390
- );
391
- }
392
- }
@@ -1,116 +0,0 @@
1
- import 'dart:async';
2
-
3
- import 'package:facebook_app_events/facebook_app_events.dart';
4
- import 'package:flutter/foundation.dart';
5
- import 'package:flutter_riverpod/flutter_riverpod.dart';
6
- import 'package:logger/logger.dart';
7
- import 'package:permission_handler/permission_handler.dart';
8
- import 'package:kasy_kit/core/initializer/onstart_service.dart';
9
- import 'package:kasy_kit/core/states/models/user_state.dart';
10
- import 'package:kasy_kit/core/states/user_state_notifier.dart';
11
- import 'package:kasy_kit/features/notifications/repositories/device_repository.dart';
12
- import 'package:purchases_flutter/purchases_flutter.dart';
13
- import 'package:sentry_flutter/sentry_flutter.dart';
14
-
15
- final facebookEventApiProvider = Provider(
16
- (ref) => FacebookEventApi(
17
- deviceRepository: ref.watch(deviceRepositoryProvider),
18
- userState: ref.watch(userStateNotifierProvider),
19
- ),
20
- );
21
-
22
- class FacebookEventApi implements OnStartService {
23
- final DeviceRepository deviceRepository;
24
- final UserState userState;
25
-
26
- FacebookEventApi({
27
- required this.deviceRepository,
28
- required this.userState,
29
- });
30
-
31
- @override
32
- Future<void> init() async {
33
- if (kIsWeb) {
34
- return;
35
- }
36
- // We must init the facebook app events
37
- final facebookAppEvents = FacebookAppEvents();
38
- // This is required by RevenueCat
39
- await facebookAppEvents.setAutoLogAppEventsEnabled(false);
40
- }
41
-
42
- Future<void> initUser(String userId) async {
43
- if (kIsWeb) {
44
- return;
45
- }
46
- final facebookAppEvents = FacebookAppEvents();
47
- await facebookAppEvents.setUserID(userId);
48
-
49
- if (defaultTargetPlatform != TargetPlatform.iOS) {
50
- return;
51
- }
52
- final isGranted = await Permission.appTrackingTransparency.isGranted;
53
- if (!isGranted) {
54
- return;
55
- }
56
- await facebookAppEvents.setAdvertiserTracking(enabled: true);
57
- }
58
-
59
- Future<void> requestIDFA() async {
60
- if (kIsWeb) {
61
- return;
62
- }
63
- final facebookAppEvents = FacebookAppEvents();
64
- if (defaultTargetPlatform == TargetPlatform.iOS) {
65
- final status = await Permission.appTrackingTransparency.request();
66
-
67
- debugPrint("IDFA status: $status");
68
- if (status.isGranted) {
69
- // collect identifiers for RevenueCat
70
- await Purchases.collectDeviceIdentifiers();
71
- await facebookAppEvents.setAdvertiserTracking(enabled: true);
72
- await _initMetaUser();
73
- unawaited(facebookAppEvents.flush());
74
- await deviceRepository.refreshExtraData();
75
- } else {
76
- await facebookAppEvents.setAdvertiserTracking(enabled: false);
77
- }
78
- } else if (defaultTargetPlatform == TargetPlatform.android) {
79
- await _initMetaUser();
80
- await facebookAppEvents.setAutoLogAppEventsEnabled(true);
81
- }
82
- }
83
-
84
- Future<void> _initMetaUser() async {
85
- final facebookAppEvents = FacebookAppEvents();
86
- final userId = userState.user.idOrNull;
87
- if (userId != null) {
88
- await facebookAppEvents.setUserID(userId);
89
- }
90
- final userAnonId = await facebookAppEvents.getAnonymousId();
91
-
92
- if (userAnonId != null) {
93
- await Purchases.setFBAnonymousID(userAnonId);
94
- }
95
- }
96
-
97
- Future<void> logMetaStartTrial(String orderId, double price, String currency) async {
98
- try {
99
- final facebookAppEvents = FacebookAppEvents();
100
- await facebookAppEvents.logStartTrial(orderId: orderId, price: price, currency: currency);
101
- } catch (e) {
102
- Logger().e("Error logging StartTrial (facebook): $e");
103
- Sentry.captureException(e, stackTrace: StackTrace.current);
104
- }
105
- }
106
-
107
- Future<void> logMetaSubscribe(String orderId, double price, String currency) async {
108
- try {
109
- final facebookAppEvents = FacebookAppEvents();
110
- await facebookAppEvents.logSubscribe(orderId: orderId, price: price, currency: currency);
111
- } catch (e) {
112
- Logger().e("Error logging Subscribe (facebook): $e");
113
- Sentry.captureException(e, stackTrace: StackTrace.current);
114
- }
115
- }
116
- }