create-flutterinit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/bin/index.ts +3 -0
  2. package/package.json +46 -0
  3. package/templates/base/.cursor/rules/flutter-project.mdc.hbs +132 -0
  4. package/templates/base/AGENTS.md.hbs +137 -0
  5. package/templates/base/DESIGN.md.hbs +149 -0
  6. package/templates/base/README.md.hbs +19 -0
  7. package/templates/base/SETUP.md.hbs +253 -0
  8. package/templates/base/analysis_options.yaml +88 -0
  9. package/templates/base/assets/.keep +1 -0
  10. package/templates/base/assets/icons/apple.svg +1 -0
  11. package/templates/base/assets/icons/facebook.svg +1 -0
  12. package/templates/base/assets/icons/google.svg +1 -0
  13. package/templates/base/assets/images/.gitkeep +0 -0
  14. package/templates/base/flutter_native_splash.yaml.hbs +8 -0
  15. package/templates/base/lib/main.dart.hbs +43 -0
  16. package/templates/base/lib/src/app.dart.hbs +105 -0
  17. package/templates/base/lib/src/config/app_config.dart.hbs +112 -0
  18. package/templates/base/lib/src/extensions/collection_extension.dart.hbs +55 -0
  19. package/templates/base/lib/src/extensions/context_extension.dart.hbs +167 -0
  20. package/templates/base/lib/src/extensions/date_time_extension.dart.hbs +40 -0
  21. package/templates/base/lib/src/extensions/extensions.dart.hbs +6 -0
  22. package/templates/base/lib/src/extensions/num_extension.dart.hbs +14 -0
  23. package/templates/base/lib/src/extensions/string_extension.dart.hbs +91 -0
  24. package/templates/base/lib/src/extensions/widget_extension.dart.hbs +47 -0
  25. package/templates/base/lib/src/imports/core_imports.dart.hbs +50 -0
  26. package/templates/base/lib/src/imports/imports.dart.hbs +2 -0
  27. package/templates/base/lib/src/imports/packages_imports.dart.hbs +110 -0
  28. package/templates/base/lib/src/routing/(isGetX)@app_bindings.dart.hbs +23 -0
  29. package/templates/base/lib/src/routing/app_router.dart.hbs +252 -0
  30. package/templates/base/lib/src/routing/app_routes.dart.hbs +46 -0
  31. package/templates/base/lib/src/routing/global_navigator.dart.hbs +15 -0
  32. package/templates/base/lib/src/services/auth_service.dart.hbs +78 -0
  33. package/templates/base/lib/src/services/copy_service.dart.hbs +16 -0
  34. package/templates/base/lib/src/services/internet_connection_service.dart.hbs +10 -0
  35. package/templates/base/lib/src/services/services.dart.hbs +45 -0
  36. package/templates/base/lib/src/shared/app_assets.dart.hbs +15 -0
  37. package/templates/base/lib/src/shared/enums/app_status.dart.hbs +40 -0
  38. package/templates/base/lib/src/shared/enums/button_enums.dart.hbs +22 -0
  39. package/templates/base/lib/src/shared/enums/enums.dart.hbs +3 -0
  40. package/templates/base/lib/src/shared/enums/snack_bar_type.dart.hbs +22 -0
  41. package/templates/base/lib/src/shared/helpers/format_number.dart.hbs +18 -0
  42. package/templates/base/lib/src/shared/helpers/imports.dart.hbs +3 -0
  43. package/templates/base/lib/src/shared/helpers/show_app_sheet.dart.hbs +42 -0
  44. package/templates/base/lib/src/shared/helpers/show_dialog.dart.hbs +49 -0
  45. package/templates/base/lib/src/shared/helpers/show_toast.dart.hbs +92 -0
  46. package/templates/base/lib/src/shared/hooks/hooks.dart.hbs +13 -0
  47. package/templates/base/lib/src/shared/hooks/use_copy.dart.hbs +41 -0
  48. package/templates/base/lib/src/shared/hooks/use_timer.dart.hbs +158 -0
  49. package/templates/base/lib/src/shared/shared.dart.hbs +12 -0
  50. package/templates/base/lib/src/shared/widgets/app_button.dart.hbs +144 -0
  51. package/templates/base/lib/src/shared/widgets/app_card.dart.hbs +126 -0
  52. package/templates/base/lib/src/shared/widgets/app_divider.dart.hbs +88 -0
  53. package/templates/base/lib/src/shared/widgets/app_empty_state.dart.hbs +73 -0
  54. package/templates/base/lib/src/shared/widgets/app_error_widget.dart.hbs +69 -0
  55. package/templates/base/lib/src/shared/widgets/app_icon.dart.hbs +25 -0
  56. package/templates/base/lib/src/shared/widgets/app_loading.dart.hbs +54 -0
  57. package/templates/base/lib/src/shared/widgets/app_text_field.dart.hbs +89 -0
  58. package/templates/base/lib/src/shared/widgets/app_top_bar.dart.hbs +105 -0
  59. package/templates/base/lib/src/shared/widgets/common_image.dart.hbs +120 -0
  60. package/templates/base/lib/src/shared/widgets/toast/imports.dart.hbs +4 -0
  61. package/templates/base/lib/src/shared/widgets/toast/raw_toast.dart.hbs +109 -0
  62. package/templates/base/lib/src/shared/widgets/toast/toast.dart.hbs +142 -0
  63. package/templates/base/lib/src/shared/widgets/toast/toast_card.dart.hbs +57 -0
  64. package/templates/base/lib/src/shared/widgets/widgets.dart.hbs +14 -0
  65. package/templates/base/lib/src/shared/wrappers/(isRiverpod,isProvider,isBloc,isGetX,isMobX)@state_wrapper.dart.hbs +51 -0
  66. package/templates/base/lib/src/shared/wrappers/(supportsLocalization)@localization_wrapper.dart.hbs +25 -0
  67. package/templates/base/lib/src/shared/wrappers/(usesScreenutil)@screen_util_wrapper.dart.hbs +27 -0
  68. package/templates/base/lib/src/shared/wrappers/(usesSkeletonizer)@skeleton_wrapper.dart.hbs +81 -0
  69. package/templates/base/lib/src/shared/wrappers/session_listener_wrapper.dart.hbs +258 -0
  70. package/templates/base/lib/src/shared/wrappers/wrappers.dart.hbs +15 -0
  71. package/templates/base/lib/src/theme/app_borders.dart.hbs +70 -0
  72. package/templates/base/lib/src/theme/app_curves.dart.hbs +69 -0
  73. package/templates/base/lib/src/theme/app_durations.dart.hbs +48 -0
  74. package/templates/base/lib/src/theme/app_shadows.dart.hbs +73 -0
  75. package/templates/base/lib/src/theme/app_spacing.dart.hbs +80 -0
  76. package/templates/base/lib/src/theme/color_schemes.dart.hbs +126 -0
  77. package/templates/base/lib/src/theme/text_theme.dart.hbs +167 -0
  78. package/templates/base/lib/src/theme/theme.dart.hbs +431 -0
  79. package/templates/base/lib/src/theme/theme_constants.dart.hbs +20 -0
  80. package/templates/base/lib/src/utils/app_utils.dart.hbs +46 -0
  81. package/templates/base/lib/src/utils/debouncer.dart.hbs +31 -0
  82. package/templates/base/lib/src/utils/error_handler.dart.hbs +14 -0
  83. package/templates/base/lib/src/utils/failure.dart.hbs +30 -0
  84. package/templates/base/lib/src/utils/input_formatters.dart.hbs +27 -0
  85. package/templates/base/lib/src/utils/logger.dart.hbs +37 -0
  86. package/templates/base/lib/src/utils/platform_info.dart.hbs +13 -0
  87. package/templates/base/lib/src/utils/task_runner.dart.hbs +42 -0
  88. package/templates/base/lib/src/utils/typedefs.dart.hbs +6 -0
  89. package/templates/base/lib/src/utils/utils.dart.hbs +9 -0
  90. package/templates/base/pubspec.yaml.hbs +256 -0
  91. package/templates/base/test/widget_test.dart.hbs +56 -0
  92. package/templates/overlays/architecture/clean/architecture.md +6 -0
  93. package/templates/overlays/architecture/clean/lib/src/features/auth/data/models/user_model.dart.hbs +1 -0
  94. package/templates/overlays/architecture/clean/lib/src/features/auth/data/repositories/auth_repository_impl.dart.hbs +1 -0
  95. package/templates/overlays/architecture/clean/lib/src/features/auth/domain/entities/user.dart.hbs +1 -0
  96. package/templates/overlays/architecture/clean/lib/src/features/auth/domain/repositories/auth_repository.dart.hbs +1 -0
  97. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/providers/(isBloc)@auth_bloc.dart.hbs +1 -0
  98. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/providers/(isBloc)@session_bloc.dart.hbs +1 -0
  99. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/providers/(isGetX)@auth_controller.dart.hbs +1 -0
  100. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/providers/(isGetX)@session_controller.dart.hbs +1 -0
  101. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/providers/(isMobX)@auth_store.dart.hbs +1 -0
  102. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/providers/(isMobX)@session_store.dart.hbs +1 -0
  103. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/providers/(isNoneState)@session_manager.dart.hbs +1 -0
  104. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/providers/(isProvider,isRiverpod)@auth_provider.dart.hbs +1 -0
  105. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/providers/(isProvider,isRiverpod)@session_provider.dart.hbs +1 -0
  106. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/screens/forgot_password_screen.dart.hbs +1 -0
  107. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/screens/login_screen.dart.hbs +1 -0
  108. package/templates/overlays/architecture/clean/lib/src/features/auth/presentation/screens/signup_screen.dart.hbs +1 -0
  109. package/templates/overlays/architecture/clean/lib/src/features/home/presentation/screens/home_page.dart.hbs +1 -0
  110. package/templates/overlays/architecture/clean/lib/src/features/onboarding/presentation/screens/onboarding_page.dart.hbs +1 -0
  111. package/templates/overlays/architecture/feature-first/architecture.md +5 -0
  112. package/templates/overlays/architecture/feature-first/lib/src/features/auth/data/models/user_model.dart.hbs +1 -0
  113. package/templates/overlays/architecture/feature-first/lib/src/features/auth/data/repositories/auth_repository_impl.dart.hbs +1 -0
  114. package/templates/overlays/architecture/feature-first/lib/src/features/auth/domain/entities/user.dart.hbs +1 -0
  115. package/templates/overlays/architecture/feature-first/lib/src/features/auth/domain/repositories/auth_repository.dart.hbs +1 -0
  116. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/providers/(isBloc)@auth_bloc.dart.hbs +1 -0
  117. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/providers/(isBloc)@session_bloc.dart.hbs +1 -0
  118. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/providers/(isGetX)@auth_controller.dart.hbs +1 -0
  119. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/providers/(isGetX)@session_controller.dart.hbs +1 -0
  120. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/providers/(isMobX)@auth_store.dart.hbs +1 -0
  121. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/providers/(isMobX)@session_store.dart.hbs +1 -0
  122. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/providers/(isNoneState)@session_manager.dart.hbs +1 -0
  123. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/providers/(isProvider,isRiverpod)@auth_provider.dart.hbs +1 -0
  124. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/providers/(isProvider,isRiverpod)@session_provider.dart.hbs +1 -0
  125. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/screens/forgot_password_screen.dart.hbs +1 -0
  126. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/screens/login_screen.dart.hbs +1 -0
  127. package/templates/overlays/architecture/feature-first/lib/src/features/auth/presentation/screens/signup_screen.dart.hbs +1 -0
  128. package/templates/overlays/architecture/feature-first/lib/src/features/home/presentation/screens/home_page.dart.hbs +1 -0
  129. package/templates/overlays/architecture/feature-first/lib/src/features/onboarding/presentation/screens/onboarding_page.dart.hbs +1 -0
  130. package/templates/overlays/architecture/layer-first/architecture.md +6 -0
  131. package/templates/overlays/architecture/layer-first/lib/src/data/datasources/local/.gitkeep +0 -0
  132. package/templates/overlays/architecture/layer-first/lib/src/data/datasources/remote/.gitkeep +0 -0
  133. package/templates/overlays/architecture/layer-first/lib/src/data/models/user_model.dart.hbs +1 -0
  134. package/templates/overlays/architecture/layer-first/lib/src/data/repositories/auth_repository_impl.dart.hbs +1 -0
  135. package/templates/overlays/architecture/layer-first/lib/src/domain/entities/user.dart.hbs +1 -0
  136. package/templates/overlays/architecture/layer-first/lib/src/domain/repositories/auth_repository.dart.hbs +1 -0
  137. package/templates/overlays/architecture/layer-first/lib/src/domain/usecases/auth/.gitkeep +0 -0
  138. package/templates/overlays/architecture/layer-first/lib/src/presentation/providers/(isBloc)@auth_bloc.dart.hbs +1 -0
  139. package/templates/overlays/architecture/layer-first/lib/src/presentation/providers/(isBloc)@session_bloc.dart.hbs +1 -0
  140. package/templates/overlays/architecture/layer-first/lib/src/presentation/providers/(isGetX)@auth_controller.dart.hbs +1 -0
  141. package/templates/overlays/architecture/layer-first/lib/src/presentation/providers/(isGetX)@session_controller.dart.hbs +1 -0
  142. package/templates/overlays/architecture/layer-first/lib/src/presentation/providers/(isMobX)@auth_store.dart.hbs +1 -0
  143. package/templates/overlays/architecture/layer-first/lib/src/presentation/providers/(isMobX)@session_store.dart.hbs +1 -0
  144. package/templates/overlays/architecture/layer-first/lib/src/presentation/providers/(isNoneState)@auth_view_model.dart.hbs +1 -0
  145. package/templates/overlays/architecture/layer-first/lib/src/presentation/providers/(isNoneState)@session_manager.dart.hbs +1 -0
  146. package/templates/overlays/architecture/layer-first/lib/src/presentation/providers/(isProvider,isRiverpod)@auth_provider.dart.hbs +1 -0
  147. package/templates/overlays/architecture/layer-first/lib/src/presentation/providers/(isProvider,isRiverpod)@session_provider.dart.hbs +1 -0
  148. package/templates/overlays/architecture/layer-first/lib/src/presentation/screens/auth/forgot_password_screen.dart.hbs +1 -0
  149. package/templates/overlays/architecture/layer-first/lib/src/presentation/screens/auth/login_screen.dart.hbs +1 -0
  150. package/templates/overlays/architecture/layer-first/lib/src/presentation/screens/auth/signup_screen.dart.hbs +1 -0
  151. package/templates/overlays/architecture/layer-first/lib/src/presentation/screens/home/home_page.dart.hbs +1 -0
  152. package/templates/overlays/architecture/layer-first/lib/src/presentation/screens/onboarding/onboarding_page.dart.hbs +1 -0
  153. package/templates/overlays/architecture/layer-first/lib/src/presentation/widgets/.gitkeep +0 -0
  154. package/templates/overlays/architecture/mvc/architecture.md +5 -0
  155. package/templates/overlays/architecture/mvc/lib/src/controllers/auth/(isBloc)@auth_bloc.dart.hbs +1 -0
  156. package/templates/overlays/architecture/mvc/lib/src/controllers/auth/(isBloc)@session_bloc.dart.hbs +1 -0
  157. package/templates/overlays/architecture/mvc/lib/src/controllers/auth/(isGetX)@auth_controller.dart.hbs +1 -0
  158. package/templates/overlays/architecture/mvc/lib/src/controllers/auth/(isGetX)@session_controller.dart.hbs +1 -0
  159. package/templates/overlays/architecture/mvc/lib/src/controllers/auth/(isMobX)@auth_store.dart.hbs +1 -0
  160. package/templates/overlays/architecture/mvc/lib/src/controllers/auth/(isMobX)@session_store.dart.hbs +1 -0
  161. package/templates/overlays/architecture/mvc/lib/src/controllers/auth/(isNoneState)@session_manager.dart.hbs +1 -0
  162. package/templates/overlays/architecture/mvc/lib/src/controllers/auth/(isProvider,isRiverpod)@auth_provider.dart.hbs +1 -0
  163. package/templates/overlays/architecture/mvc/lib/src/controllers/auth/(isProvider,isRiverpod)@session_provider.dart.hbs +1 -0
  164. package/templates/overlays/architecture/mvc/lib/src/models/user_model.dart.hbs +1 -0
  165. package/templates/overlays/architecture/mvc/lib/src/services/auth_repository.dart.hbs +1 -0
  166. package/templates/overlays/architecture/mvc/lib/src/services/auth_repository_impl.dart.hbs +1 -0
  167. package/templates/overlays/architecture/mvc/lib/src/views/auth/forgot_password_screen.dart.hbs +1 -0
  168. package/templates/overlays/architecture/mvc/lib/src/views/auth/login_screen.dart.hbs +1 -0
  169. package/templates/overlays/architecture/mvc/lib/src/views/auth/signup_screen.dart.hbs +1 -0
  170. package/templates/overlays/architecture/mvc/lib/src/views/home/home_page.dart.hbs +1 -0
  171. package/templates/overlays/architecture/mvc/lib/src/views/onboarding/onboarding_page.dart.hbs +1 -0
  172. package/templates/overlays/architecture/mvvm/architecture.md +6 -0
  173. package/templates/overlays/architecture/mvvm/lib/src/data/models/user_model.dart.hbs +1 -0
  174. package/templates/overlays/architecture/mvvm/lib/src/data/repositories/auth_repository.dart.hbs +1 -0
  175. package/templates/overlays/architecture/mvvm/lib/src/data/repositories/auth_repository_impl.dart.hbs +1 -0
  176. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/(isBloc)@bloc/auth_bloc.dart.hbs +1 -0
  177. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/(isBloc)@bloc/session_bloc.dart.hbs +1 -0
  178. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/(isGetX)@controllers/auth_controller.dart.hbs +1 -0
  179. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/(isGetX)@controllers/session_controller.dart.hbs +1 -0
  180. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/(isMobX)@stores/auth_store.dart.hbs +1 -0
  181. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/(isMobX)@stores/session_store.dart.hbs +1 -0
  182. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/(isNoneState)@view_models/auth_view_model.dart.hbs +1 -0
  183. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/(isNoneState)@view_models/session_manager.dart.hbs +1 -0
  184. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/(isProvider,isRiverpod)@providers/auth_provider.dart.hbs +1 -0
  185. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/(isProvider,isRiverpod)@providers/session_provider.dart.hbs +1 -0
  186. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/forgot_password_screen.dart.hbs +1 -0
  187. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/login_screen.dart.hbs +1 -0
  188. package/templates/overlays/architecture/mvvm/lib/src/ui/auth/signup_screen.dart.hbs +1 -0
  189. package/templates/overlays/architecture/mvvm/lib/src/ui/home/home_page.dart.hbs +1 -0
  190. package/templates/overlays/architecture/mvvm/lib/src/ui/onboarding/onboarding_page.dart.hbs +1 -0
  191. package/templates/overlays/backend/appwrite/lib/src/services/(usesAppwriteAuth)@auth_service.dart.hbs +101 -0
  192. package/templates/overlays/backend/custom/lib/src/services/auth_service.dart.hbs +158 -0
  193. package/templates/overlays/backend/firebase/lib/src/services/(usesFirebaseAuth)@auth_service.dart.hbs +96 -0
  194. package/templates/overlays/backend/supabase/lib/src/services/(usesSupabaseAuth)@auth_service.dart.hbs +97 -0
  195. package/templates/overlays/device/app_version_update/lib/src/services/(usesAppVersionUpdate)@version_update_service.dart.hbs +118 -0
  196. package/templates/overlays/device/device_info/lib/src/services/(usesDeviceInfoPlus)@device_info_service.dart.hbs +54 -0
  197. package/templates/overlays/extras/dotenv/.env.hbs +33 -0
  198. package/templates/overlays/extras/flavors/lib/src/flavors.dart.hbs +15 -0
  199. package/templates/overlays/extras/localization/assets/translations/en.json.hbs +47 -0
  200. package/templates/overlays/media/lib/src/services/(usesImagePicker,usesFilePicker)@media_service.dart.hbs +148 -0
  201. package/templates/overlays/networking/cached_image/lib/src/shared/widgets/app_cached_image.dart.hbs +160 -0
  202. package/templates/overlays/networking/dio/lib/src/services/(usesDio)@dio_service.dart.hbs +50 -0
  203. package/templates/overlays/networking/http/lib/src/services/(usesHttp)@http_service.dart.hbs +82 -0
  204. package/templates/overlays/storage/hive/lib/src/services/(usesHive)@hive_service.dart.hbs +59 -0
  205. package/templates/overlays/storage/secure_storage/lib/src/services/(usesSecureStorage)@secure_storage_service.dart.hbs +39 -0
  206. package/templates/overlays/storage/shared_preferences/lib/src/services/(usesSharedPreferences)@storage_service.dart.hbs +53 -0
  207. package/templates/overlays/utilities/geolocator/lib/src/services/(usesGeolocator)@location_service.dart.hbs +78 -0
  208. package/templates/overlays/utilities/path_provider/lib/src/services/(usesPathProvider)@path_service.dart.hbs +30 -0
  209. package/templates/overlays/utilities/permission_handler/lib/src/services/(usesPermissionHandler)@permission_service.dart.hbs +28 -0
  210. package/templates/overlays/utilities/permission_handler/lib/src/shared/hooks/use_permission.dart.hbs +44 -0
  211. package/templates/overlays/utilities/share_plus/lib/src/services/(usesSharePlus)@share_service.dart.hbs +22 -0
  212. package/templates/overlays/utilities/share_plus/lib/src/shared/hooks/use_share.dart.hbs +26 -0
  213. package/templates/overlays/utilities/url_launcher/lib/src/services/(usesUrlLauncher)@url_launcher_service.dart.hbs +37 -0
  214. package/templates/overlays/utilities/url_launcher/lib/src/shared/hooks/use_launch_url.dart.hbs +52 -0
  215. package/templates/partials/features/auth/auth_logic.hbs +611 -0
  216. package/templates/partials/features/auth/auth_repository.hbs +32 -0
  217. package/templates/partials/features/auth/auth_repository_impl.hbs +116 -0
  218. package/templates/partials/features/auth/forgot_password_screen.hbs +368 -0
  219. package/templates/partials/features/auth/login_screen.hbs +540 -0
  220. package/templates/partials/features/auth/session_provider.hbs +437 -0
  221. package/templates/partials/features/auth/signup_screen.hbs +511 -0
  222. package/templates/partials/features/auth/user_model.hbs +23 -0
  223. package/templates/partials/features/home/home_page.hbs +156 -0
  224. package/templates/partials/features/onboarding/onboarding_page.hbs +264 -0
  225. package/templates/partials/llm/add-feature-workflow.hbs +38 -0
  226. package/templates/partials/llm/architecture-rules.hbs +92 -0
  227. package/templates/partials/llm/backend-rules.hbs +30 -0
  228. package/templates/partials/llm/build-runner-note.hbs +15 -0
  229. package/templates/partials/llm/design-quick-ref.hbs +14 -0
  230. package/templates/partials/llm/design-quick-reference.hbs +14 -0
  231. package/templates/partials/llm/navigation-rules.hbs +27 -0
  232. package/templates/partials/llm/networking-rules.hbs +16 -0
  233. package/templates/partials/llm/packages-list.hbs +26 -0
  234. package/templates/partials/llm/services-conventions.hbs +20 -0
  235. package/templates/partials/llm/stack-summary.hbs +22 -0
  236. package/templates/partials/llm/state-management-rules.hbs +40 -0
  237. package/templates/partials/state_label.hbs +1 -0
@@ -0,0 +1,88 @@
1
+ import '../../imports/imports.dart';
2
+
3
+ /// A themed horizontal divider using [ColorScheme.outlineVariant].
4
+ ///
5
+ /// Prefer this over the raw [Divider] widget to stay consistent with the
6
+ /// app's colour scheme without passing explicit colours everywhere.
7
+ ///
8
+ /// Usage:
9
+ /// ```dart
10
+ /// const AppDivider() // standard 1-pt divider
11
+ /// const AppDivider.thick() // 2-pt emphasis divider
12
+ /// AppDivider(indent: 16) // inset divider (like list separator)
13
+ /// ```
14
+ class AppDivider extends StatelessWidget {
15
+ const AppDivider({
16
+ super.key,
17
+ this.height = 1,
18
+ this.thickness = 1,
19
+ this.indent = 0,
20
+ this.endIndent = 0,
21
+ this.color,
22
+ });
23
+
24
+ /// 2-pt visually prominent divider — use between major content sections.
25
+ const AppDivider.thick({
26
+ super.key,
27
+ this.height = 2,
28
+ this.thickness = 2,
29
+ this.indent = 0,
30
+ this.endIndent = 0,
31
+ this.color,
32
+ });
33
+
34
+ final double height;
35
+ final double thickness;
36
+ final double indent;
37
+ final double endIndent;
38
+ final Color? color;
39
+
40
+ @override
41
+ Widget build(BuildContext context) {
42
+ return Divider(
43
+ height: height,
44
+ thickness: thickness,
45
+ indent: indent,
46
+ endIndent: endIndent,
47
+ color: color ?? context.theme.colorScheme.outlineVariant,
48
+ );
49
+ }
50
+ }
51
+
52
+ /// A themed vertical divider using [ColorScheme.outlineVariant].
53
+ ///
54
+ /// Usage:
55
+ /// ```dart
56
+ /// Row(children: [
57
+ /// Text('Left'),
58
+ /// const AppVerticalDivider(),
59
+ /// Text('Right'),
60
+ /// ])
61
+ /// ```
62
+ class AppVerticalDivider extends StatelessWidget {
63
+ const AppVerticalDivider({
64
+ super.key,
65
+ this.width = 1,
66
+ this.thickness = 1,
67
+ this.indent = 0,
68
+ this.endIndent = 0,
69
+ this.color,
70
+ });
71
+
72
+ final double width;
73
+ final double thickness;
74
+ final double indent;
75
+ final double endIndent;
76
+ final Color? color;
77
+
78
+ @override
79
+ Widget build(BuildContext context) {
80
+ return VerticalDivider(
81
+ width: width,
82
+ thickness: thickness,
83
+ indent: indent,
84
+ endIndent: endIndent,
85
+ color: color ?? context.theme.colorScheme.outlineVariant,
86
+ );
87
+ }
88
+ }
@@ -0,0 +1,73 @@
1
+ import '../../imports/imports.dart';
2
+
3
+ /// Displays an empty state with an icon, title, optional subtitle, and action.
4
+ ///
5
+ /// Usage:
6
+ /// ```dart
7
+ /// AppEmptyState(
8
+ /// icon: Icons.inbox_outlined,
9
+ /// title: 'No messages yet',
10
+ /// subtitle: 'Your inbox will appear here.',
11
+ /// actionLabel: 'Refresh',
12
+ /// onAction: _refresh,
13
+ /// )
14
+ /// ```
15
+ class AppEmptyState extends StatelessWidget {
16
+ const AppEmptyState({
17
+ super.key,
18
+ this.icon = {{#if flags.usesIconsaxPlus}}IconsaxPlusLinear.box{{else if flags.usesFlutterRemix}}FlutterRemix.inbox_line{{else if flags.usesHugeicons}}HugeIcons.strokeRoundedInbox{{else}}Icons.inbox_outlined{{/if}},
19
+ required this.title,
20
+ this.subtitle,
21
+ this.actionLabel,
22
+ this.onAction,
23
+ });
24
+
25
+ final dynamic icon;
26
+ final String title;
27
+ final String? subtitle;
28
+ final String? actionLabel;
29
+ final VoidCallback? onAction;
30
+
31
+ @override
32
+ Widget build(BuildContext context) {
33
+ final cs = context.theme.colorScheme;
34
+ final tt = context.theme.textTheme;
35
+
36
+ return Center(
37
+ child: Padding(
38
+ padding: {{#if flags.usesScreenutil}}EdgeInsets.all(40.w){{else}}const EdgeInsets.all(40){{/if}},
39
+ child: Column(
40
+ mainAxisSize: MainAxisSize.min,
41
+ children: [
42
+ AppIcon(icon: icon, size: {{res 64 'sp' flags.usesScreenutil}}, color: cs.onSurfaceVariant.withValues(alpha: 0.5)),
43
+ {{#if flags.usesScreenutil}}SizedBox(height: 20.h){{else}}const SizedBox(height: 20){{/if}},
44
+ Text(
45
+ title,
46
+ style: tt.titleMedium?.copyWith(
47
+ color: cs.onSurface,
48
+ fontWeight: FontWeight.w600,
49
+ ),
50
+ textAlign: TextAlign.center,
51
+ ),
52
+ if (subtitle != null) ...[
53
+ {{#if flags.usesScreenutil}}SizedBox(height: 8.h){{else}}const SizedBox(height: 8){{/if}},
54
+ Text(
55
+ subtitle!,
56
+ style: tt.bodyMedium?.copyWith(color: cs.onSurfaceVariant),
57
+ textAlign: TextAlign.center,
58
+ ),
59
+ ],
60
+ if (actionLabel != null && onAction != null) ...[
61
+ {{#if flags.usesScreenutil}}SizedBox(height: 28.h){{else}}const SizedBox(height: 28){{/if}},
62
+ AppButton(
63
+ label: actionLabel!,
64
+ onPressed: onAction,
65
+ variant: ButtonVariant.secondary,
66
+ ),
67
+ ],
68
+ ],
69
+ ),
70
+ ),
71
+ );
72
+ }
73
+ }
@@ -0,0 +1,69 @@
1
+ import '../../imports/imports.dart';
2
+
3
+ /// Displays an error state with an icon, title, optional body, and retry button.
4
+ ///
5
+ /// Usage:
6
+ /// ```dart
7
+ /// AppErrorWidget(
8
+ /// title: 'Something went wrong',
9
+ /// message: error.toString(),
10
+ /// onRetry: () => ref.invalidate(myProvider),
11
+ /// )
12
+ /// ```
13
+ class AppErrorWidget extends StatelessWidget {
14
+ const AppErrorWidget({
15
+ super.key,
16
+ this.title = 'Something went wrong',
17
+ this.message,
18
+ this.onRetry,
19
+ this.icon = {{#if flags.usesIconsaxPlus}}IconsaxPlusLinear.danger{{else if flags.usesFlutterRemix}}FlutterRemix.error_warning_line{{else if flags.usesHugeicons}}HugeIcons.strokeRoundedAlertCircle{{else}}Icons.error_outline_rounded{{/if}},
20
+ });
21
+
22
+ final String title;
23
+ final String? message;
24
+ final VoidCallback? onRetry;
25
+ final dynamic icon;
26
+
27
+ @override
28
+ Widget build(BuildContext context) {
29
+ final cs = context.theme.colorScheme;
30
+ final tt = context.theme.textTheme;
31
+
32
+ return Center(
33
+ child: Padding(
34
+ padding: const EdgeInsets.all(32),
35
+ child: Column(
36
+ mainAxisSize: MainAxisSize.min,
37
+ children: [
38
+ AppIcon(icon: icon, size: 56, color: cs.error),
39
+ const SizedBox(height: 16),
40
+ Text(
41
+ title,
42
+ style: tt.titleMedium?.copyWith(
43
+ color: cs.onSurface,
44
+ fontWeight: FontWeight.bold,
45
+ ),
46
+ textAlign: TextAlign.center,
47
+ ),
48
+ if (message != null) ...[
49
+ const SizedBox(height: 8),
50
+ Text(
51
+ message!,
52
+ style: tt.bodySmall?.copyWith(color: cs.onSurfaceVariant),
53
+ textAlign: TextAlign.center,
54
+ ),
55
+ ],
56
+ if (onRetry != null) ...[
57
+ const SizedBox(height: 24),
58
+ AppButton(
59
+ label: 'Try Again',
60
+ onPressed: onRetry,
61
+ variant: ButtonVariant.outline,
62
+ ),
63
+ ],
64
+ ],
65
+ ),
66
+ ),
67
+ );
68
+ }
69
+ }
@@ -0,0 +1,25 @@
1
+ import '../../imports/imports.dart';
2
+
3
+ /// A wrapper widget that handles different icon libraries.
4
+ class AppIcon extends StatelessWidget {
5
+ const AppIcon({
6
+ super.key,
7
+ required this.icon,
8
+ this.size,
9
+ this.color,
10
+ });
11
+
12
+ /// The icon to display.
13
+ final IconData icon;
14
+ final double? size;
15
+ final Color? color;
16
+
17
+ @override
18
+ Widget build(BuildContext context) {
19
+ return Icon(
20
+ icon,
21
+ size: size,
22
+ color: color,
23
+ );
24
+ }
25
+ }
@@ -0,0 +1,54 @@
1
+ import '../../imports/imports.dart';
2
+
3
+ /// Centered loading indicator using the primary colour from the theme.
4
+ ///
5
+ /// Usage:
6
+ /// ```dart
7
+ /// // Simple inline loader
8
+ /// const AppLoading()
9
+ ///
10
+ /// // Full-screen loader with message
11
+ /// AppLoading(message: 'Fetching data...')
12
+ /// ```
13
+ class AppLoading extends StatelessWidget {
14
+ const AppLoading({
15
+ super.key,
16
+ this.message,
17
+ this.size = 28,
18
+ this.strokeWidth = 3,
19
+ });
20
+
21
+ final String? message;
22
+ final double size;
23
+ final double strokeWidth;
24
+
25
+ @override
26
+ Widget build(BuildContext context) {
27
+ final cs = context.theme.colorScheme;
28
+ return Center(
29
+ child: Column(
30
+ mainAxisSize: MainAxisSize.min,
31
+ children: [
32
+ SizedBox(
33
+ width: size,
34
+ height: size,
35
+ child: CircularProgressIndicator(
36
+ strokeWidth: strokeWidth,
37
+ color: cs.primary,
38
+ ),
39
+ ),
40
+ if (message != null) ...[
41
+ {{#if flags.usesScreenutil}}SizedBox(height: 16.h){{else}}const SizedBox(height: 16){{/if}},
42
+ Text(
43
+ message!,
44
+ style: context.theme.textTheme.bodyMedium?.copyWith(
45
+ color: cs.onSurfaceVariant,
46
+ ),
47
+ textAlign: TextAlign.center,
48
+ ),
49
+ ],
50
+ ],
51
+ ),
52
+ );
53
+ }
54
+ }
@@ -0,0 +1,89 @@
1
+ import '../../imports/core_imports.dart';
2
+
3
+
4
+ /// A themed text form field wrapping [TextFormField].
5
+ ///
6
+ /// Usage:
7
+ /// ```dart
8
+ /// AppTextField(
9
+ /// label: 'Email',
10
+ /// hint: 'you@example.com',
11
+ /// controller: _emailController,
12
+ /// keyboardType: TextInputType.emailAddress,
13
+ /// validator: (v) => v!.isEmpty ? 'Required' : null,
14
+ /// )
15
+ /// ```
16
+ class AppTextField extends StatelessWidget {
17
+ const AppTextField({
18
+ super.key,
19
+ this.label,
20
+ this.hint,
21
+ this.controller,
22
+ this.validator,
23
+ this.onChanged,
24
+ this.onFieldSubmitted,
25
+ this.focusNode,
26
+ this.keyboardType,
27
+ this.textInputAction,
28
+ this.obscureText = false,
29
+ this.readOnly = false,
30
+ this.enabled = true,
31
+ this.maxLines = 1,
32
+ this.minLines,
33
+ this.prefixIcon,
34
+ this.suffixIcon,
35
+ this.initialValue,
36
+ this.autofocus = false,
37
+ });
38
+
39
+ final String? label;
40
+ final String? hint;
41
+ final TextEditingController? controller;
42
+ final FormFieldValidator<String>? validator;
43
+ final ValueChanged<String>? onChanged;
44
+ final ValueChanged<String>? onFieldSubmitted;
45
+ final FocusNode? focusNode;
46
+ final TextInputType? keyboardType;
47
+ final TextInputAction? textInputAction;
48
+ final bool obscureText;
49
+ final bool readOnly;
50
+ final bool enabled;
51
+ final int? maxLines;
52
+ final int? minLines;
53
+ final Widget? prefixIcon;
54
+ final Widget? suffixIcon;
55
+ final String? initialValue;
56
+ final bool autofocus;
57
+
58
+ @override
59
+ Widget build(BuildContext context) {
60
+ final cs = context.theme.colorScheme;
61
+ final tt = context.theme.textTheme;
62
+
63
+ return TextFormField(
64
+ controller: controller,
65
+ initialValue: initialValue,
66
+ validator: validator,
67
+ onChanged: onChanged,
68
+ onFieldSubmitted: onFieldSubmitted,
69
+ focusNode: focusNode,
70
+ keyboardType: keyboardType,
71
+ textInputAction: textInputAction,
72
+ obscureText: obscureText,
73
+ readOnly: readOnly,
74
+ enabled: enabled,
75
+ maxLines: obscureText ? 1 : maxLines,
76
+ minLines: minLines,
77
+ autofocus: autofocus,
78
+ style: tt.bodyLarge?.copyWith(color: cs.onSurface),
79
+ cursorColor: cs.primary,
80
+ decoration: InputDecoration(
81
+ isDense: true,
82
+ labelText: label,
83
+ hintText: hint,
84
+ prefixIcon: prefixIcon,
85
+ suffixIcon: suffixIcon,
86
+ ),
87
+ );
88
+ }
89
+ }
@@ -0,0 +1,105 @@
1
+ import '../../imports/imports.dart';
2
+
3
+ class AppTopBar extends StatelessWidget implements PreferredSizeWidget {
4
+ const AppTopBar({
5
+ super.key,
6
+ required this.title,
7
+ this.titleWidget,
8
+ this.actions,
9
+ this.centerTitle = true,
10
+ this.onPressed,
11
+ this.isTransparent = false,
12
+ });
13
+
14
+ final String title;
15
+ final Widget? titleWidget;
16
+ final List<Widget>? actions;
17
+ final VoidCallback? onPressed;
18
+ final bool? centerTitle;
19
+ final bool isTransparent;
20
+
21
+ @override
22
+ Widget build(BuildContext context) {
23
+ final theme = context.theme;
24
+
25
+ // Check if we can pop
26
+ {{#if (eq flags.routerPackage "go_router")}}
27
+ final bool canPop = context.canPop();
28
+ {{else if (eq flags.routerPackage "auto_route")}}
29
+ final bool canPop = context.router.canPop();
30
+ {{else}}
31
+ final bool canPop = Navigator.canPop(context);
32
+ {{/if}}
33
+
34
+ void handleBack() {
35
+ if (onPressed != null) {
36
+ onPressed!();
37
+ } else if (canPop) {
38
+ {{#if (eq flags.routerPackage "go_router")}}
39
+ context.pop();
40
+ {{else if (eq flags.routerPackage "auto_route")}}
41
+ context.router.maybePop();
42
+ {{else}}
43
+ Navigator.maybePop(context);
44
+ {{/if}}
45
+ } else {
46
+ {{#if (eq flags.routerPackage "go_router")}}
47
+ context.go(AppRoutes.home);
48
+ {{else if (eq flags.routerPackage "auto_route")}}
49
+ context.router.replaceAll([const HomeRoute()]);
50
+ {{else}}
51
+ Navigator.pushReplacementNamed(context, AppRoutes.home);
52
+ {{/if}}
53
+ }
54
+ }
55
+
56
+ return AppBar(
57
+ centerTitle: centerTitle,
58
+ elevation: 0,
59
+ backgroundColor: isTransparent ? Colors.transparent : null,
60
+ shadowColor: Colors.transparent,
61
+ title: titleWidget ??
62
+ Text(
63
+ title,
64
+ style: theme.appBarTheme.titleTextStyle?.copyWith(
65
+ fontWeight: FontWeight.w600,
66
+ ) ?? theme.textTheme.titleMedium?.copyWith(
67
+ fontWeight: FontWeight.w600,
68
+ ),
69
+ ),
70
+ leadingWidth: {{res 40 'w' flags.usesScreenutil}},
71
+ leading: GestureDetector(
72
+ onTap: handleBack,
73
+ child: ColoredBox(
74
+ color: Colors.transparent,
75
+ child: {{#if flags.usesHugeicons}}
76
+ HugeIcon(
77
+ icon: HugeIcons.strokeRoundedArrowLeft01,
78
+ size: {{res 24 'sp' flags.usesScreenutil}},
79
+ )
80
+ {{else if flags.usesIconsaxPlus}}
81
+ Icon(
82
+ IconsaxPlusLinear.arrow_left,
83
+ color: theme.appBarTheme.iconTheme?.color ?? theme.colorScheme.onSurface,
84
+ )
85
+ {{else if flags.usesFlutterRemix}}
86
+ Icon(
87
+ FlutterRemix.arrow_left_line,
88
+ color: theme.appBarTheme.iconTheme?.color ?? theme.colorScheme.onSurface,
89
+ )
90
+ {{else}}
91
+ Icon(
92
+ Icons.arrow_back,
93
+ color: theme.appBarTheme.iconTheme?.color ?? theme.colorScheme.onSurface,
94
+ )
95
+ {{/if}},
96
+ ),
97
+ ),
98
+ iconTheme: theme.appBarTheme.iconTheme,
99
+ actions: actions ?? [],
100
+ );
101
+ }
102
+
103
+ @override
104
+ Size get preferredSize => const Size.fromHeight(kToolbarHeight);
105
+ }
@@ -0,0 +1,120 @@
1
+ import '../../imports/imports.dart';
2
+
3
+
4
+ /// A multi-purpose image widget that handles network images, SVGs, and local assets.
5
+ ///
6
+ /// Automatically uses [CachedNetworkImage] if enabled for web images.
7
+ /// Automatically uses [SvgPicture] if enabled for SVG files.
8
+ class CommonImage extends StatelessWidget {
9
+ final String imageUrl;
10
+ final double? width;
11
+ final double? height;
12
+ final BoxFit fit;
13
+ final Color? color;
14
+ final Widget? placeholder;
15
+ final Widget? errorWidget;
16
+ final BorderRadius? borderRadius;
17
+
18
+ const CommonImage({
19
+ super.key,
20
+ required this.imageUrl,
21
+ this.width,
22
+ this.height,
23
+ this.fit = BoxFit.cover,
24
+ this.color,
25
+ this.placeholder,
26
+ this.errorWidget,
27
+ this.borderRadius,
28
+ });
29
+
30
+ @override
31
+ Widget build(BuildContext context) {
32
+ final double? adjustedWidth = {{#if flags.usesScreenutil}}width?.w{{else}}width{{/if}};
33
+ final double? adjustedHeight = {{#if flags.usesScreenutil}}height?.h{{else}}height{{/if}};
34
+
35
+ Widget image;
36
+
37
+ if (imageUrl.startsWith('http')) {
38
+ {{#if flags.usesCachedNetworkImage}}
39
+ image = AppCachedImage(
40
+ imageUrl: imageUrl,
41
+ width: width,
42
+ height: height,
43
+ fit: fit,
44
+ color: color,
45
+ placeholder: placeholder,
46
+ errorWidget: errorWidget,
47
+ borderRadius: borderRadius,
48
+ );
49
+ {{else}}
50
+ image = Image.network(
51
+ imageUrl,
52
+ width: adjustedWidth,
53
+ height: adjustedHeight,
54
+ fit: fit,
55
+ color: color,
56
+ errorBuilder: (context, error, stackTrace) => errorWidget ?? _buildDefaultErrorWidget(),
57
+ );
58
+ {{/if}}
59
+ } else if (imageUrl.endsWith('.svg')) {
60
+ {{#if flags.usesFlutterSvg}}
61
+ image = SvgPicture.asset(
62
+ imageUrl,
63
+ width: adjustedWidth,
64
+ height: adjustedHeight,
65
+ fit: fit,
66
+ colorFilter: color != null ? ColorFilter.mode(color!, BlendMode.srcIn) : null,
67
+ );
68
+ {{else}}
69
+ image = const Icon(Icons.broken_image, color: Colors.grey);
70
+ {{/if}}
71
+ } else {
72
+ image = Image.asset(
73
+ imageUrl,
74
+ width: adjustedWidth,
75
+ height: adjustedHeight,
76
+ fit: fit,
77
+ color: color,
78
+ errorBuilder: (context, error, stackTrace) => errorWidget ?? _buildDefaultErrorWidget(),
79
+ );
80
+ }
81
+
82
+ if (borderRadius != null) {
83
+ return ClipRRect(
84
+ borderRadius: borderRadius!,
85
+ child: image,
86
+ );
87
+ }
88
+
89
+ return image;
90
+ }
91
+
92
+ Widget _buildDefaultErrorWidget() {
93
+ return Container(
94
+ width: width,
95
+ height: height,
96
+ color: Colors.grey[200],
97
+ child: {{#if flags.usesHugeicons}}
98
+ HugeIcon(
99
+ icon: HugeIcons.strokeRoundedImageNotFound02,
100
+ size: {{res 24 'sp' flags.usesScreenutil}},
101
+ )
102
+ {{else if flags.usesIconsaxPlus}}
103
+ const Icon(
104
+ IconsaxPlusBold.image,
105
+ color: Colors.grey,
106
+ )
107
+ {{else if flags.usesFlutterRemix}}
108
+ const Icon(
109
+ FlutterRemix.image_line,
110
+ color: Colors.grey,
111
+ )
112
+ {{else}}
113
+ const Icon(
114
+ Icons.error_outline,
115
+ color: Colors.grey,
116
+ )
117
+ {{/if}},
118
+ );
119
+ }
120
+ }
@@ -0,0 +1,4 @@
1
+ export 'toast.dart';
2
+ export 'toast_card.dart';
3
+ export 'raw_toast.dart';
4
+