@shaykec/app-agent 1.0.3 → 1.0.5

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 (248) hide show
  1. package/.claude/skills/ui-tester/SKILL.md +59 -0
  2. package/.cursor/skills/android-customizer/SKILL.md +50 -16
  3. package/.cursor/skills/appconfig-customization/SKILL.md +15 -0
  4. package/.cursor/skills/customization-planner/SKILL.md +17 -1
  5. package/.cursor/skills/ios-customizer/SKILL.md +54 -13
  6. package/.cursor/skills/mock-data-update/SKILL.md +11 -3
  7. package/.cursor/skills/ui-tester/SKILL.md +59 -0
  8. package/dist/cli.d.ts +18 -4
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +134 -14
  11. package/dist/cli.js.map +1 -1
  12. package/dist/github.d.ts +5 -0
  13. package/dist/github.d.ts.map +1 -1
  14. package/dist/github.js +27 -0
  15. package/dist/github.js.map +1 -1
  16. package/dist/index.js +218 -24
  17. package/dist/index.js.map +1 -1
  18. package/dist/preview-generator.d.ts +35 -0
  19. package/dist/preview-generator.d.ts.map +1 -0
  20. package/dist/preview-generator.js +546 -0
  21. package/dist/preview-generator.js.map +1 -0
  22. package/package.json +4 -1
  23. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/AppConfig.kt +9 -0
  24. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/data/DataSourceResolver.kt +23 -0
  25. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/booking/BookingScreen.kt +6 -4
  26. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/bookings/BookingsScreen.kt +7 -5
  27. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/discovery/DiscoveryViewModel.kt +3 -2
  28. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/discovery/ProviderDetailScreen.kt +1 -1
  29. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/discovery/SearchScreen.kt +1 -1
  30. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/features/profile/ProfileScreen.kt +4 -2
  31. package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/mock/MockDataProvider.kt +12 -11
  32. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/AppConfig.kt +9 -0
  33. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/data/DataRepository.kt +23 -0
  34. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/data/DataSourceResolver.kt +23 -0
  35. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/calls/CallsScreen.kt +4 -3
  36. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/contacts/ContactsScreen.kt +3 -2
  37. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/conversations/ChatScreen.kt +11 -10
  38. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/conversations/ConversationsScreen.kt +5 -5
  39. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/navigation/Navigation.kt +4 -2
  40. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/settings/SettingsScreen.kt +6 -4
  41. package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/mock/MockDataProvider.kt +7 -7
  42. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/data/DataRepository.kt +46 -0
  43. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/data/DataSourceResolver.kt +23 -0
  44. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/alerts/AlertsScreen.kt +4 -3
  45. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/dashboard/DashboardScreen.kt +3 -2
  46. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/datasources/DataSourcesScreen.kt +3 -2
  47. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/reports/ReportsScreen.kt +3 -2
  48. package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/mock/MockDataProvider.kt +16 -15
  49. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/AppConfig.kt +9 -0
  50. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/calendar/CalendarScreen.kt +5 -5
  51. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/chores/ChoreBoardScreen.kt +3 -3
  52. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/familyhub/FamilyHubScreen.kt +4 -4
  53. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/gallery/GalleryScreen.kt +3 -3
  54. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/members/MembersListScreen.kt +5 -5
  55. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/rewards/RewardsScreen.kt +5 -5
  56. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/settings/SettingsScreen.kt +3 -3
  57. package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/mock/MockDataProvider.kt +29 -32
  58. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/AppConfig.kt +9 -0
  59. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/data/DataRepository.kt +70 -0
  60. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/data/DataSourceResolver.kt +23 -0
  61. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/budgets/BudgetsScreen.kt +3 -2
  62. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/goals/GoalsScreen.kt +5 -3
  63. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/home/HomeScreen.kt +8 -7
  64. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/settings/SettingsScreen.kt +0 -1
  65. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/features/transactions/TransactionsScreen.kt +9 -4
  66. package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/mock/MockDataProvider.kt +103 -11
  67. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/data/DataRepository.kt +19 -0
  68. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/leaderboard/LeaderboardScreen.kt +2 -1
  69. package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/results/ResultsScreen.kt +3 -2
  70. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/data/DataRepository.kt +46 -0
  71. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/data/DataSourceResolver.kt +23 -0
  72. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/features/dashboard/DashboardScreen.kt +3 -2
  73. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/features/profile/ProfileScreen.kt +3 -2
  74. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/features/workouts/WorkoutListScreen.kt +3 -2
  75. package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/mock/MockDataProvider.kt +13 -13
  76. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/AppConfig.kt +9 -0
  77. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/data/DataRepository.kt +48 -0
  78. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/data/DataSourceResolver.kt +23 -0
  79. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/courses/CourseListScreen.kt +4 -3
  80. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/leaderboard/LeaderboardScreen.kt +3 -2
  81. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/profile/ProfileScreen.kt +3 -2
  82. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/features/progress/ProgressDashboardScreen.kt +3 -2
  83. package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/mock/MockDataProvider.kt +41 -11
  84. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/AppConfig.kt +9 -0
  85. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/data/DataRepository.kt +33 -0
  86. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/data/DataSourceResolver.kt +28 -0
  87. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/di/AppModule.kt +11 -2
  88. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/favorites/FavoritesViewModel.kt +4 -4
  89. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/map/MapViewModel.kt +4 -4
  90. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/place/PlaceDetailViewModel.kt +5 -5
  91. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/place/PlaceListViewModel.kt +4 -4
  92. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/profile/ProfileViewModel.kt +5 -5
  93. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/route/RouteViewModel.kt +3 -3
  94. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/search/SearchViewModel.kt +3 -3
  95. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/features/settings/SettingsViewModel.kt +3 -3
  96. package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/mock/MockDataProvider.kt +54 -41
  97. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/AppConfig.kt +9 -0
  98. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/browse/BrowseScreen.kt +2 -1
  99. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/detail/DetailScreen.kt +3 -1
  100. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/home/HomeScreen.kt +3 -2
  101. package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/mock/MockDataProvider.kt +63 -132
  102. package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/AppConfig.kt +9 -0
  103. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/AppConfig.kt +9 -0
  104. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/data/DataRepository.kt +62 -0
  105. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/data/DataSourceResolver.kt +23 -0
  106. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/features/home/HomeViewModel.kt +2 -1
  107. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/features/products/ProductViewModels.kt +12 -7
  108. package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/mock/MockDataProvider.kt +31 -31
  109. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/AppConfig.kt +9 -0
  110. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/data/DataRepository.kt +30 -0
  111. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/data/DataSourceResolver.kt +23 -0
  112. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/features/create/CreateScreen.kt +3 -2
  113. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/features/detail/DetailScreen.kt +4 -3
  114. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/features/explore/ExploreScreen.kt +7 -6
  115. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/features/favorites/FavoritesScreen.kt +4 -3
  116. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/features/home/HomeScreen.kt +5 -4
  117. package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/mock/MockDataProvider.kt +12 -11
  118. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/AppConfig.kt +9 -0
  119. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/data/DataRepository.kt +37 -0
  120. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/data/DataSourceResolver.kt +23 -0
  121. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/createpost/CreatePostScreen.kt +3 -2
  122. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/feed/CommentsScreen.kt +4 -3
  123. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/feed/FeedScreen.kt +5 -4
  124. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/messages/MessagesScreen.kt +9 -8
  125. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/notifications/NotificationsScreen.kt +3 -2
  126. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/profile/ProfileScreen.kt +6 -5
  127. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/features/search/SearchScreen.kt +4 -3
  128. package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/mock/MockDataProvider.kt +7 -6
  129. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/AppConfig.kt +9 -0
  130. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/data/DataRepository.kt +38 -0
  131. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/data/DataSourceResolver.kt +23 -0
  132. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/calendar/CalendarScreen.kt +0 -1
  133. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/inbox/InboxScreen.kt +4 -2
  134. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/kanban/KanbanBoardScreen.kt +5 -3
  135. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/projects/ProjectDetailScreen.kt +9 -5
  136. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/projects/ProjectListScreen.kt +6 -4
  137. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/search/SearchScreen.kt +1 -1
  138. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/tasks/TaskDetailScreen.kt +0 -1
  139. package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/mock/MockDataProvider.kt +13 -12
  140. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/AppConfig.kt +9 -0
  141. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/data/DataRepository.kt +34 -0
  142. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/data/DataSourceResolver.kt +23 -0
  143. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/achievements/AchievementsViewModel.kt +4 -2
  144. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/dashboard/TodayViewModel.kt +4 -2
  145. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/habits/HabitDetailViewModel.kt +4 -2
  146. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/features/habits/HabitsListViewModel.kt +4 -2
  147. package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/mock/MockDataProvider.kt +13 -11
  148. package/templates/ios/BookTemplate/BookTemplate/App/AppConfig.swift +12 -2
  149. package/templates/ios/BookTemplate/BookTemplate/Data/DataRepository.swift +33 -0
  150. package/templates/ios/BookTemplate/BookTemplate/Data/DataSourceResolver.swift +20 -0
  151. package/templates/ios/BookTemplate/BookTemplate/Features/Booking/BookingView.swift +1 -1
  152. package/templates/ios/BookTemplate/BookTemplate/Features/Discovery/DiscoveryView.swift +3 -3
  153. package/templates/ios/BookTemplate/BookTemplate/Features/Discovery/MapExploreView.swift +1 -1
  154. package/templates/ios/BookTemplate/BookTemplate/Features/Discovery/ProviderDetailView.swift +1 -1
  155. package/templates/ios/BookTemplate/BookTemplate/Features/Discovery/SearchView.swift +2 -2
  156. package/templates/ios/BookTemplate/BookTemplate/MockData/MockDataProvider.swift +18 -1
  157. package/templates/ios/ChatTemplate/ChatTemplate/App/AppConfig.swift +9 -0
  158. package/templates/ios/ChatTemplate/ChatTemplate/Data/DataRepository.swift +43 -0
  159. package/templates/ios/ChatTemplate/ChatTemplate/Data/DataSourceResolver.swift +20 -0
  160. package/templates/ios/DashTemplate/DashTemplate/App/AppConfig.swift +9 -0
  161. package/templates/ios/DashTemplate/DashTemplate/Data/DataRepository.swift +53 -0
  162. package/templates/ios/DashTemplate/DashTemplate/MockData/MockDataProvider.swift +1 -1
  163. package/templates/ios/FamilyTemplate/FamilyTemplate/App/AppConfig.swift +9 -0
  164. package/templates/ios/FamilyTemplate/FamilyTemplate/App/FamilyTemplateApp.swift +4 -2
  165. package/templates/ios/FamilyTemplate/FamilyTemplate/MockData/MockDataProvider.swift +1 -1
  166. package/templates/ios/FinanceTemplate/FinanceTemplate/App/AppConfig.swift +9 -0
  167. package/templates/ios/FinanceTemplate/FinanceTemplate/Data/DataRepository.swift +75 -0
  168. package/templates/ios/FinanceTemplate/FinanceTemplate/Data/DataSourceResolver.swift +20 -0
  169. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Budgets/BudgetsView.swift +3 -1
  170. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Goals/GoalsView.swift +3 -1
  171. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Home/HomeView.swift +13 -6
  172. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Settings/SettingsView.swift +6 -2
  173. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Transactions/AddTransactionView.swift +4 -2
  174. package/templates/ios/FinanceTemplate/FinanceTemplate/Features/Transactions/TransactionsView.swift +3 -1
  175. package/templates/ios/FinanceTemplate/FinanceTemplate/MockData/MockDataProvider.swift +1 -1
  176. package/templates/ios/GameTemplate/GameTemplate/App/AppConfig.swift +9 -0
  177. package/templates/ios/GameTemplate/GameTemplate/Data/DataRepository.swift +30 -0
  178. package/templates/ios/GameTemplate/GameTemplate/Data/DataSourceResolver.swift +20 -0
  179. package/templates/ios/GameTemplate/GameTemplate/MockData/MockDataProvider.swift +1 -1
  180. package/templates/ios/HealthTemplate/HealthTemplate/App/AppConfig.swift +9 -0
  181. package/templates/ios/HealthTemplate/HealthTemplate/Data/DataRepository.swift +60 -0
  182. package/templates/ios/HealthTemplate/HealthTemplate/MockData/MockDataProvider.swift +1 -1
  183. package/templates/ios/LearnTemplate/LearnTemplate/App/AppConfig.swift +9 -0
  184. package/templates/ios/LearnTemplate/LearnTemplate/Features/Courses/CourseDetailView.swift +3 -2
  185. package/templates/ios/LearnTemplate/LearnTemplate/Features/Courses/CourseListView.swift +3 -2
  186. package/templates/ios/LearnTemplate/LearnTemplate/Features/Flashcards/FlashcardView.swift +2 -1
  187. package/templates/ios/LearnTemplate/LearnTemplate/Features/Leaderboard/LeaderboardView.swift +2 -1
  188. package/templates/ios/LearnTemplate/LearnTemplate/Features/Lessons/LessonPlayerView.swift +4 -2
  189. package/templates/ios/LearnTemplate/LearnTemplate/Features/Profile/ProfileView.swift +4 -2
  190. package/templates/ios/LearnTemplate/LearnTemplate/Features/Progress/ProgressDashboardView.swift +3 -2
  191. package/templates/ios/LearnTemplate/LearnTemplate/Features/Quiz/QuizView.swift +2 -1
  192. package/templates/ios/LearnTemplate/LearnTemplate/MockData/MockDataProvider.swift +1 -1
  193. package/templates/ios/MapTemplate/MapTemplate/App/AppConfig.swift +11 -9
  194. package/templates/ios/MapTemplate/MapTemplate/Data/DataSourceResolver.swift +20 -0
  195. package/templates/ios/MapTemplate/MapTemplate/Features/Favorites/FavoritesView.swift +1 -1
  196. package/templates/ios/MapTemplate/MapTemplate/Features/PlaceDetail/PlaceDetailView.swift +2 -2
  197. package/templates/ios/MapTemplate/MapTemplate/Features/Profile/ProfileView.swift +1 -1
  198. package/templates/ios/MapTemplate/MapTemplate/Features/Route/RouteView.swift +1 -1
  199. package/templates/ios/MapTemplate/MapTemplate/Features/Search/SearchView.swift +1 -1
  200. package/templates/ios/MediaTemplate/MediaTemplate/App/AppConfig.swift +9 -0
  201. package/templates/ios/MediaTemplate/MediaTemplate/Data/DataRepository.swift +52 -0
  202. package/templates/ios/MediaTemplate/MediaTemplate/Data/DataSourceResolver.swift +20 -0
  203. package/templates/ios/MediaTemplate/MediaTemplate/MockData/MockDataProvider.swift +1 -1
  204. package/templates/ios/ReferenceTemplate/ReferenceTemplate/App/AppConfig.swift +9 -0
  205. package/templates/ios/ReferenceTemplate/ReferenceTemplate/Data/DataRepository.swift +28 -0
  206. package/templates/ios/ReferenceTemplate/ReferenceTemplate/Data/DataSourceResolver.swift +20 -0
  207. package/templates/ios/ReferenceTemplate/ReferenceTemplate/MockData/MockDataProvider.swift +1 -1
  208. package/templates/ios/ShopTemplate/ShopTemplate/App/AppConfig.swift +9 -0
  209. package/templates/ios/ShopTemplate/ShopTemplate/Data/DataSourceResolver.swift +20 -0
  210. package/templates/ios/ShopTemplate/ShopTemplate/Features/Home/HomeView.swift +9 -7
  211. package/templates/ios/ShopTemplate/ShopTemplate/Features/Orders/OrdersView.swift +7 -3
  212. package/templates/ios/ShopTemplate/ShopTemplate/Features/Products/ProductDetailView.swift +4 -2
  213. package/templates/ios/ShopTemplate/ShopTemplate/Features/Products/ProductListView.swift +6 -3
  214. package/templates/ios/ShopTemplate/ShopTemplate/MockData/MockDataProvider.swift +1 -1
  215. package/templates/ios/Skeleton/Skeleton/App/AppConfig.swift +9 -0
  216. package/templates/ios/Skeleton/Skeleton/Data/DataRepository.swift +30 -0
  217. package/templates/ios/Skeleton/Skeleton/Data/DataSourceResolver.swift +20 -0
  218. package/templates/ios/Skeleton/Skeleton/Features/Explore/ExploreViewModel.swift +7 -6
  219. package/templates/ios/Skeleton/Skeleton/Features/Home/HomeViewModel.swift +8 -7
  220. package/templates/ios/Skeleton/Skeleton/MockData/MockDataProvider.swift +1 -1
  221. package/templates/ios/SocialTemplate/SocialTemplate/App/AppConfig.swift +4 -3
  222. package/templates/ios/SocialTemplate/SocialTemplate/Data/DataRepository.swift +37 -0
  223. package/templates/ios/SocialTemplate/SocialTemplate/Data/DataSourceResolver.swift +20 -0
  224. package/templates/ios/SocialTemplate/SocialTemplate/Data/SyncManager.swift +1 -1
  225. package/templates/ios/SocialTemplate/SocialTemplate/Features/CreatePost/CreatePostView.swift +2 -2
  226. package/templates/ios/SocialTemplate/SocialTemplate/Features/Feed/CommentsView.swift +2 -2
  227. package/templates/ios/SocialTemplate/SocialTemplate/Features/Feed/FeedView.swift +1 -1
  228. package/templates/ios/SocialTemplate/SocialTemplate/Features/Messages/MessagesView.swift +4 -4
  229. package/templates/ios/SocialTemplate/SocialTemplate/Features/Notifications/NotificationsView.swift +1 -1
  230. package/templates/ios/SocialTemplate/SocialTemplate/Features/Profile/ProfileView.swift +1 -1
  231. package/templates/ios/SocialTemplate/SocialTemplate/Features/Search/SearchView.swift +5 -4
  232. package/templates/ios/SocialTemplate/SocialTemplate/MockData/MockDataProvider.swift +1 -1
  233. package/templates/ios/SocialTemplate/SocialTemplate/Models/Models.swift +2 -2
  234. package/templates/ios/TaskTemplate/TaskTemplate/App/AppConfig.swift +9 -0
  235. package/templates/ios/TaskTemplate/TaskTemplate/Data/DataRepository.swift +38 -0
  236. package/templates/ios/TaskTemplate/TaskTemplate/Data/DataSourceResolver.swift +20 -0
  237. package/templates/ios/TaskTemplate/TaskTemplate/Features/Calendar/CalendarView.swift +6 -2
  238. package/templates/ios/TaskTemplate/TaskTemplate/Features/Inbox/InboxView.swift +2 -1
  239. package/templates/ios/TaskTemplate/TaskTemplate/Features/Kanban/KanbanBoardView.swift +9 -3
  240. package/templates/ios/TaskTemplate/TaskTemplate/Features/Projects/ProjectDetailView.swift +3 -1
  241. package/templates/ios/TaskTemplate/TaskTemplate/Features/Projects/ProjectListView.swift +3 -1
  242. package/templates/ios/TaskTemplate/TaskTemplate/Features/Search/SearchView.swift +3 -1
  243. package/templates/ios/TaskTemplate/TaskTemplate/MockData/MockDataProvider.swift +1 -1
  244. package/templates/ios/TrackTemplate/TrackTemplate/App/AppConfig.swift +9 -0
  245. package/templates/ios/TrackTemplate/TrackTemplate/Data/DataRepository.swift +29 -0
  246. package/templates/ios/TrackTemplate/TrackTemplate/Data/DataSourceResolver.swift +20 -0
  247. package/templates/ios/TrackTemplate/TrackTemplate/MockData/MockDataProvider.swift +1 -1
  248. package/templates/ios/TrackTemplate/TrackTemplate/Services/HabitManager.swift +1 -1
@@ -1,13 +1,14 @@
1
1
  package com.appship.learn.mock
2
2
 
3
3
  import com.appship.learn.AppConfig
4
+ import com.appship.learn.data.DataRepository
4
5
  import com.appship.learn.data.models.*
5
6
  import kotlinx.coroutines.flow.MutableStateFlow
6
7
  import kotlinx.coroutines.flow.StateFlow
7
8
  import kotlinx.coroutines.flow.asStateFlow
8
9
 
9
10
  // CUSTOMIZE:API - Replace mock data with real API calls
10
- object MockDataProvider {
11
+ object MockDataProvider : DataRepository {
11
12
 
12
13
  // MARK: - Default Seed Data
13
14
  private val defaultCategories = listOf(
@@ -172,14 +173,14 @@ object MockDataProvider {
172
173
  val userProgress: StateFlow<UserProgress> = _userProgress.asStateFlow()
173
174
 
174
175
  // MARK: - CRUD Functions
175
- fun getCourses(): List<Course> = _courses.value
176
- fun getCourse(id: String): Course? = _courses.value.find { it.id == id }
177
- fun getLessons(courseId: String): List<Lesson> = _courses.value.find { it.id == courseId }?.lessons ?: emptyList()
178
- fun getFlashcardDecks(): List<FlashcardDeck> = _flashcardDecks.value
179
- fun getLeaderboard(): List<LeaderboardEntry> = _leaderboardEntries.value.sortedBy { it.rank }
180
- fun getProgress(): UserProgress = _userProgress.value
181
-
182
- fun markLessonComplete(courseId: String, lessonId: String) {
176
+ override fun getCourses(): List<Course> = _courses.value
177
+ override fun getCourse(id: String): Course? = _courses.value.find { it.id == id }
178
+ override fun getLessons(courseId: String): List<Lesson> = _courses.value.find { it.id == courseId }?.lessons ?: emptyList()
179
+ override fun getFlashcardDecks(): List<FlashcardDeck> = _flashcardDecks.value
180
+ override fun getLeaderboard(): List<LeaderboardEntry> = _leaderboardEntries.value.sortedBy { it.rank }
181
+ override fun getProgress(): UserProgress = _userProgress.value
182
+
183
+ override fun markLessonComplete(courseId: String, lessonId: String) {
183
184
  val courseIndex = _courses.value.indexOfFirst { it.id == courseId }
184
185
  if (courseIndex >= 0) {
185
186
  val course = _courses.value[courseIndex]
@@ -214,7 +215,7 @@ object MockDataProvider {
214
215
  )
215
216
  }
216
217
 
217
- fun updateFlashcard(deckId: String, cardId: String, difficulty: FlashcardDifficulty) {
218
+ override fun updateFlashcard(deckId: String, cardId: String, difficulty: FlashcardDifficulty) {
218
219
  val deckIndex = _flashcardDecks.value.indexOfFirst { it.id == deckId }
219
220
  if (deckIndex >= 0) {
220
221
  val deck = _flashcardDecks.value[deckIndex]
@@ -242,11 +243,40 @@ object MockDataProvider {
242
243
  }
243
244
  }
244
245
 
245
- fun reset() {
246
+ override fun reset() {
246
247
  _courses.value = defaultCourses
247
248
  _flashcardDecks.value = defaultFlashcardDecks
248
249
  _leaderboardEntries.value = defaultLeaderboardEntries
249
250
  _userProgress.value = defaultUserProgress
250
251
  _achievements.value = defaultAchievements
251
252
  }
253
+
254
+ // Additional methods required by DataRepository interface
255
+ override fun getQuiz(lessonId: String): Quiz? {
256
+ // TODO: Implement quiz retrieval
257
+ return null
258
+ }
259
+
260
+ override fun updateProgress(progress: UserProgress) {
261
+ _userProgress.value = progress
262
+ }
263
+
264
+ override fun updateStreak() {
265
+ val progress = _userProgress.value
266
+ val newStreak = progress.currentStreak + 1
267
+ _userProgress.value = progress.copy(
268
+ currentStreak = newStreak,
269
+ longestStreak = maxOf(progress.longestStreak, newStreak),
270
+ totalXP = progress.totalXP + AppConfig.Business.XP_PER_STREAK
271
+ )
272
+ }
273
+
274
+ override fun unlockAchievement(achievementId: String) {
275
+ val achievements = _achievements.value.toMutableList()
276
+ val index = achievements.indexOfFirst { it.id == achievementId }
277
+ if (index >= 0 && !achievements[index].isUnlocked) {
278
+ achievements[index] = achievements[index].copy(isUnlocked = true)
279
+ _achievements.value = achievements
280
+ }
281
+ }
252
282
  }
@@ -75,4 +75,13 @@ object AppConfig {
75
75
  OnboardingSlide("Get Directions", "Navigate easily with turn-by-turn directions", "directions"),
76
76
  OnboardingSlide("Save Favorites", "Keep track of your favorite places", "favorite")
77
77
  )
78
+
79
+ // CUSTOMIZE:DATASOURCE - Data source configuration
80
+ object DataSource {
81
+ enum class SourceType {
82
+ LOCAL_STORAGE, // Room — real local database (DEFAULT)
83
+ MOCK // In-memory seed data — for development/testing only
84
+ }
85
+ val active: SourceType = SourceType.MOCK
86
+ }
78
87
  }
@@ -0,0 +1,33 @@
1
+ package com.appship.map.data
2
+
3
+ /**
4
+ * Abstracts the data layer. Both MockDataProvider and LocalStorageProvider
5
+ * implement this, allowing the app to swap data sources via AppConfig.DataSource.active.
6
+ *
7
+ * Screens and ViewModels depend on this interface rather than on a concrete implementation.
8
+ * Use [DataSourceResolver.repository] to get the active provider.
9
+ */
10
+ interface DataRepository {
11
+ // Observable state
12
+ val places: List<Place>
13
+ val reviews: Map<String, List<Review>>
14
+ val routes: List<Route>
15
+ val currentUser: User
16
+
17
+ // CRUD operations
18
+ fun getPlace(id: String): Place?
19
+ fun getReviews(placeId: String): List<Review>
20
+ fun addReview(review: Review, placeId: String)
21
+ fun toggleFavorite(place: Place)
22
+ fun getFavoritePlaces(): List<Place>
23
+
24
+ // Filtering & Search
25
+ fun filterPlaces(criteria: FilterCriteria): List<Place>
26
+ fun searchPlaces(query: String): List<Place>
27
+
28
+ // Route operations
29
+ fun getRoute(origin: Coordinate, destination: Coordinate): Route?
30
+
31
+ // Reset
32
+ fun reset()
33
+ }
@@ -0,0 +1,28 @@
1
+ package com.appship.map.data
2
+
3
+ import android.content.Context
4
+ import com.appship.map.AppConfig
5
+ import com.appship.map.mock.MockDataProvider
6
+
7
+ /**
8
+ * Resolves the active [DataRepository] implementation based on [AppConfig.DataSource.active].
9
+ * Screens use this to obtain the correct data source without knowing the concrete type.
10
+ *
11
+ * Note: For ViewModels, prefer injecting [DataRepository] via Hilt instead of using this resolver.
12
+ * This resolver is primarily for Views/Screens that don't use dependency injection.
13
+ *
14
+ * Usage:
15
+ * val repository = DataSourceResolver.getRepository(context)
16
+ * val places = repository.places
17
+ */
18
+ object DataSourceResolver {
19
+ fun getRepository(context: Context): DataRepository {
20
+ return when (AppConfig.DataSource.active) {
21
+ AppConfig.DataSource.SourceType.LOCAL_STORAGE -> {
22
+ // TODO: Return LocalStorageProvider.getInstance(context) once implemented
23
+ MockDataProvider.getInstance(com.appship.map.data.LocalPersistence(context))
24
+ }
25
+ AppConfig.DataSource.SourceType.MOCK -> MockDataProvider.getInstance(com.appship.map.data.LocalPersistence(context))
26
+ }
27
+ }
28
+ }
@@ -1,6 +1,7 @@
1
1
  package com.appship.map.di
2
2
 
3
3
  import android.content.Context
4
+ import com.appship.map.data.DataRepository
4
5
  import com.appship.map.data.LocalPersistence
5
6
  import com.appship.map.data.NetworkMonitor
6
7
  import com.appship.map.data.SyncManager
@@ -32,12 +33,20 @@ object AppModule {
32
33
  return NetworkMonitor(context)
33
34
  }
34
35
 
36
+ @Provides
37
+ @Singleton
38
+ fun provideDataRepository(
39
+ mockDataProvider: MockDataProvider
40
+ ): DataRepository {
41
+ return mockDataProvider
42
+ }
43
+
35
44
  @Provides
36
45
  @Singleton
37
46
  fun provideSyncManager(
38
47
  networkMonitor: NetworkMonitor,
39
- mockDataProvider: MockDataProvider
48
+ dataRepository: DataRepository
40
49
  ): SyncManager {
41
- return SyncManager(networkMonitor, mockDataProvider)
50
+ return SyncManager(networkMonitor, dataRepository as MockDataProvider)
42
51
  }
43
52
  }
@@ -2,8 +2,8 @@ package com.appship.map.features.favorites
2
2
 
3
3
  import androidx.lifecycle.ViewModel
4
4
  import androidx.lifecycle.viewModelScope
5
+ import com.appship.map.data.DataRepository
5
6
  import com.appship.map.data.Place
6
- import com.appship.map.mock.MockDataProvider
7
7
  import dagger.hilt.android.lifecycle.HiltViewModel
8
8
  import kotlinx.coroutines.flow.MutableStateFlow
9
9
  import kotlinx.coroutines.flow.StateFlow
@@ -13,7 +13,7 @@ import javax.inject.Inject
13
13
 
14
14
  @HiltViewModel
15
15
  class FavoritesViewModel @Inject constructor(
16
- private val mockDataProvider: MockDataProvider
16
+ private val repository: DataRepository
17
17
  ) : ViewModel() {
18
18
 
19
19
  data class FavoritesUiState(
@@ -32,14 +32,14 @@ class FavoritesViewModel @Inject constructor(
32
32
  kotlinx.coroutines.delay(300)
33
33
 
34
34
  _uiState.value = _uiState.value.copy(
35
- favorites = mockDataProvider.getFavoritePlaces(),
35
+ favorites = repository.getFavoritePlaces(),
36
36
  isLoading = false
37
37
  )
38
38
  }
39
39
  }
40
40
 
41
41
  fun removeFavorite(place: Place) {
42
- mockDataProvider.toggleFavorite(place)
42
+ repository.toggleFavorite(place)
43
43
  loadFavorites() // Refresh
44
44
  }
45
45
  }
@@ -2,8 +2,8 @@ package com.appship.map.features.map
2
2
 
3
3
  import androidx.lifecycle.ViewModel
4
4
  import androidx.lifecycle.viewModelScope
5
+ import com.appship.map.data.DataRepository
5
6
  import com.appship.map.data.Place
6
- import com.appship.map.mock.MockDataProvider
7
7
  import dagger.hilt.android.lifecycle.HiltViewModel
8
8
  import kotlinx.coroutines.flow.MutableStateFlow
9
9
  import kotlinx.coroutines.flow.StateFlow
@@ -13,7 +13,7 @@ import javax.inject.Inject
13
13
 
14
14
  @HiltViewModel
15
15
  class MapViewModel @Inject constructor(
16
- private val mockDataProvider: MockDataProvider
16
+ private val repository: DataRepository
17
17
  ) : ViewModel() {
18
18
 
19
19
  data class MapUiState(
@@ -33,14 +33,14 @@ class MapViewModel @Inject constructor(
33
33
  kotlinx.coroutines.delay(500)
34
34
 
35
35
  _uiState.value = _uiState.value.copy(
36
- places = mockDataProvider.places,
36
+ places = repository.places,
37
37
  isLoading = false
38
38
  )
39
39
  }
40
40
  }
41
41
 
42
42
  fun toggleFavorite(place: Place) {
43
- mockDataProvider.toggleFavorite(place)
43
+ repository.toggleFavorite(place)
44
44
  loadPlaces() // Refresh list
45
45
  }
46
46
  }
@@ -2,9 +2,9 @@ package com.appship.map.features.place
2
2
 
3
3
  import androidx.lifecycle.ViewModel
4
4
  import androidx.lifecycle.viewModelScope
5
+ import com.appship.map.data.DataRepository
5
6
  import com.appship.map.data.Place
6
7
  import com.appship.map.data.Review
7
- import com.appship.map.mock.MockDataProvider
8
8
  import dagger.hilt.android.lifecycle.HiltViewModel
9
9
  import kotlinx.coroutines.flow.MutableStateFlow
10
10
  import kotlinx.coroutines.flow.StateFlow
@@ -14,7 +14,7 @@ import javax.inject.Inject
14
14
 
15
15
  @HiltViewModel
16
16
  class PlaceDetailViewModel @Inject constructor(
17
- private val mockDataProvider: MockDataProvider
17
+ private val repository: DataRepository
18
18
  ) : ViewModel() {
19
19
 
20
20
  data class PlaceDetailUiState(
@@ -34,8 +34,8 @@ class PlaceDetailViewModel @Inject constructor(
34
34
  // CUSTOMIZE:API - Replace with real API call
35
35
  kotlinx.coroutines.delay(300)
36
36
 
37
- val place = mockDataProvider.getPlace(placeId)
38
- val reviews = place?.let { mockDataProvider.getReviews(it.id) } ?: emptyList()
37
+ val place = repository.getPlace(placeId)
38
+ val reviews = place?.let { repository.getReviews(it.id) } ?: emptyList()
39
39
 
40
40
  _uiState.value = _uiState.value.copy(
41
41
  place = place,
@@ -46,7 +46,7 @@ class PlaceDetailViewModel @Inject constructor(
46
46
  }
47
47
 
48
48
  fun toggleFavorite(place: Place) {
49
- mockDataProvider.toggleFavorite(place)
49
+ repository.toggleFavorite(place)
50
50
  loadPlace(place.id) // Refresh
51
51
  }
52
52
  }
@@ -2,8 +2,8 @@ package com.appship.map.features.place
2
2
 
3
3
  import androidx.lifecycle.ViewModel
4
4
  import androidx.lifecycle.viewModelScope
5
+ import com.appship.map.data.DataRepository
5
6
  import com.appship.map.data.Place
6
- import com.appship.map.mock.MockDataProvider
7
7
  import dagger.hilt.android.lifecycle.HiltViewModel
8
8
  import kotlinx.coroutines.flow.MutableStateFlow
9
9
  import kotlinx.coroutines.flow.StateFlow
@@ -13,7 +13,7 @@ import javax.inject.Inject
13
13
 
14
14
  @HiltViewModel
15
15
  class PlaceListViewModel @Inject constructor(
16
- private val mockDataProvider: MockDataProvider
16
+ private val repository: DataRepository
17
17
  ) : ViewModel() {
18
18
 
19
19
  data class PlaceListUiState(
@@ -33,14 +33,14 @@ class PlaceListViewModel @Inject constructor(
33
33
  kotlinx.coroutines.delay(500)
34
34
 
35
35
  _uiState.value = _uiState.value.copy(
36
- places = mockDataProvider.places,
36
+ places = repository.places,
37
37
  isLoading = false
38
38
  )
39
39
  }
40
40
  }
41
41
 
42
42
  fun toggleFavorite(place: Place) {
43
- mockDataProvider.toggleFavorite(place)
43
+ repository.toggleFavorite(place)
44
44
  loadPlaces() // Refresh list
45
45
  }
46
46
  }
@@ -2,8 +2,8 @@ package com.appship.map.features.profile
2
2
 
3
3
  import androidx.lifecycle.ViewModel
4
4
  import androidx.lifecycle.viewModelScope
5
+ import com.appship.map.data.DataRepository
5
6
  import com.appship.map.data.User
6
- import com.appship.map.mock.MockDataProvider
7
7
  import dagger.hilt.android.lifecycle.HiltViewModel
8
8
  import kotlinx.coroutines.flow.MutableStateFlow
9
9
  import kotlinx.coroutines.flow.StateFlow
@@ -13,7 +13,7 @@ import javax.inject.Inject
13
13
 
14
14
  @HiltViewModel
15
15
  class ProfileViewModel @Inject constructor(
16
- private val mockDataProvider: MockDataProvider
16
+ private val repository: DataRepository
17
17
  ) : ViewModel() {
18
18
 
19
19
  data class ProfileUiState(
@@ -28,13 +28,13 @@ class ProfileViewModel @Inject constructor(
28
28
 
29
29
  fun loadProfile() {
30
30
  viewModelScope.launch {
31
- val user = mockDataProvider.currentUser
32
- val favorites = mockDataProvider.getFavoritePlaces()
31
+ val user = repository.currentUser
32
+ val favorites = repository.getFavoritePlaces()
33
33
 
34
34
  _uiState.value = _uiState.value.copy(
35
35
  user = user,
36
36
  favoriteCount = favorites.size,
37
- reviewCount = mockDataProvider.reviews.values.sumOf { it.size }
37
+ reviewCount = repository.reviews.values.sumOf { it.size }
38
38
  )
39
39
  }
40
40
  }
@@ -3,8 +3,8 @@ package com.appship.map.features.route
3
3
  import androidx.lifecycle.ViewModel
4
4
  import androidx.lifecycle.viewModelScope
5
5
  import com.appship.map.data.Coordinate
6
+ import com.appship.map.data.DataRepository
6
7
  import com.appship.map.data.Route
7
- import com.appship.map.mock.MockDataProvider
8
8
  import dagger.hilt.android.lifecycle.HiltViewModel
9
9
  import kotlinx.coroutines.flow.MutableStateFlow
10
10
  import kotlinx.coroutines.flow.StateFlow
@@ -14,7 +14,7 @@ import javax.inject.Inject
14
14
 
15
15
  @HiltViewModel
16
16
  class RouteViewModel @Inject constructor(
17
- private val mockDataProvider: MockDataProvider
17
+ private val repository: DataRepository
18
18
  ) : ViewModel() {
19
19
 
20
20
  data class RouteUiState(
@@ -33,7 +33,7 @@ class RouteViewModel @Inject constructor(
33
33
  // CUSTOMIZE:API - Replace with real API call
34
34
  kotlinx.coroutines.delay(500)
35
35
 
36
- val route = mockDataProvider.getRoute(origin, destination)
36
+ val route = repository.getRoute(origin, destination)
37
37
 
38
38
  _uiState.value = _uiState.value.copy(
39
39
  route = route,
@@ -2,8 +2,8 @@ package com.appship.map.features.search
2
2
 
3
3
  import androidx.lifecycle.ViewModel
4
4
  import androidx.lifecycle.viewModelScope
5
+ import com.appship.map.data.DataRepository
5
6
  import com.appship.map.data.Place
6
- import com.appship.map.mock.MockDataProvider
7
7
  import dagger.hilt.android.lifecycle.HiltViewModel
8
8
  import kotlinx.coroutines.flow.MutableStateFlow
9
9
  import kotlinx.coroutines.flow.StateFlow
@@ -13,7 +13,7 @@ import javax.inject.Inject
13
13
 
14
14
  @HiltViewModel
15
15
  class SearchViewModel @Inject constructor(
16
- private val mockDataProvider: MockDataProvider
16
+ private val repository: DataRepository
17
17
  ) : ViewModel() {
18
18
 
19
19
  data class SearchUiState(
@@ -37,7 +37,7 @@ class SearchViewModel @Inject constructor(
37
37
  // CUSTOMIZE:API - Replace with real API call
38
38
  kotlinx.coroutines.delay(300)
39
39
 
40
- val results = mockDataProvider.searchPlaces(query)
40
+ val results = repository.searchPlaces(query)
41
41
  _uiState.value = _uiState.value.copy(
42
42
  results = results,
43
43
  isLoading = false
@@ -2,7 +2,7 @@ package com.appship.map.features.settings
2
2
 
3
3
  import androidx.lifecycle.ViewModel
4
4
  import androidx.lifecycle.viewModelScope
5
- import com.appship.map.mock.MockDataProvider
5
+ import com.appship.map.data.DataRepository
6
6
  import dagger.hilt.android.lifecycle.HiltViewModel
7
7
  import kotlinx.coroutines.flow.MutableStateFlow
8
8
  import kotlinx.coroutines.flow.StateFlow
@@ -12,7 +12,7 @@ import javax.inject.Inject
12
12
 
13
13
  @HiltViewModel
14
14
  class SettingsViewModel @Inject constructor(
15
- private val mockDataProvider: MockDataProvider
15
+ private val repository: DataRepository
16
16
  ) : ViewModel() {
17
17
 
18
18
  data class SettingsUiState(
@@ -37,7 +37,7 @@ class SettingsViewModel @Inject constructor(
37
37
 
38
38
  fun resetData() {
39
39
  viewModelScope.launch {
40
- mockDataProvider.reset()
40
+ repository.reset()
41
41
  }
42
42
  }
43
43
  }
@@ -2,6 +2,7 @@ package com.appship.map.mock
2
2
 
3
3
  import com.appship.map.AppConfig
4
4
  import com.appship.map.data.*
5
+ import com.appship.map.data.DataRepository
5
6
  import com.appship.map.data.LocalPersistence
6
7
  import java.util.Date
7
8
  import java.util.Random
@@ -11,15 +12,27 @@ import javax.inject.Singleton
11
12
  @Singleton
12
13
  class MockDataProvider @Inject constructor(
13
14
  private val persistence: LocalPersistence
14
- ) {
15
- var places: MutableList<Place> = mutableListOf()
16
- var reviews: MutableMap<String, MutableList<Review>> = mutableMapOf()
17
- var routes: MutableList<Route> = mutableListOf()
18
- var currentUser: User = defaultCurrentUser
15
+ ) : DataRepository {
16
+ override val places: List<Place> get() = _places
17
+ override val reviews: Map<String, List<Review>> get() = _reviews.mapValues { it.value.toList() }
18
+ override val routes: List<Route> get() = _routes
19
+ override var currentUser: User = defaultCurrentUser
20
+
21
+ private var _places: MutableList<Place> = mutableListOf()
22
+ private var _reviews: MutableMap<String, MutableList<Review>> = mutableMapOf()
23
+ private var _routes: MutableList<Route> = mutableListOf()
19
24
 
20
25
  companion object {
26
+ @Volatile
27
+ private var INSTANCE: MockDataProvider? = null
21
28
  private val random = Random()
22
29
 
30
+ fun getInstance(persistence: LocalPersistence): MockDataProvider {
31
+ return INSTANCE ?: synchronized(this) {
32
+ INSTANCE ?: MockDataProvider(persistence).also { INSTANCE = it }
33
+ }
34
+ }
35
+
23
36
  val defaultCurrentUser = User(
24
37
  id = "current",
25
38
  name = "John Doe",
@@ -401,60 +414,60 @@ class MockDataProvider @Inject constructor(
401
414
  // Load persisted places if available, otherwise use defaults
402
415
  val savedPlaces = persistence.load<List<Place>>("mockdata_places")
403
416
  if (savedPlaces != null) {
404
- places = savedPlaces.toMutableList()
417
+ _places = savedPlaces.toMutableList()
405
418
  } else {
406
- places = makeDefaultPlaces().toMutableList()
419
+ _places = makeDefaultPlaces().toMutableList()
407
420
  // Set favorites based on current user
408
421
  for (placeId in currentUser.favoritePlaces) {
409
- places.find { it.id == placeId }?.isFavorite = true
422
+ _places.find { it.id == placeId }?.isFavorite = true
410
423
  }
411
424
  }
412
425
 
413
426
  // Load persisted reviews if available
414
427
  val savedReviews = persistence.load<Map<String, List<Review>>>("mockdata_reviews")
415
428
  if (savedReviews != null) {
416
- reviews = savedReviews.mapValues { it.value.toMutableList() }.toMutableMap()
429
+ _reviews = savedReviews.mapValues { it.value.toMutableList() }.toMutableMap()
417
430
  } else {
418
431
  // Initialize default reviews for each place
419
- for (place in places) {
420
- reviews[place.id] = makeDefaultReviews(place.id).toMutableList()
432
+ for (place in _places) {
433
+ _reviews[place.id] = makeDefaultReviews(place.id).toMutableList()
421
434
  }
422
435
  }
423
436
 
424
437
  // Initialize routes
425
- routes = makeDefaultRoutes().toMutableList()
438
+ _routes = makeDefaultRoutes().toMutableList()
426
439
  }
427
440
 
428
441
  // MARK: - CRUD Operations
429
442
 
430
- fun getPlace(id: String): Place? {
431
- return places.find { it.id == id }
443
+ override fun getPlace(id: String): Place? {
444
+ return _places.find { it.id == id }
432
445
  }
433
446
 
434
- fun getReviews(placeId: String): List<Review> {
435
- return reviews[placeId] ?: emptyList()
447
+ override fun getReviews(placeId: String): List<Review> {
448
+ return _reviews[placeId] ?: emptyList()
436
449
  }
437
450
 
438
- fun addReview(review: Review, placeId: String) {
439
- if (reviews[placeId] == null) {
440
- reviews[placeId] = mutableListOf()
451
+ override fun addReview(review: Review, placeId: String) {
452
+ if (_reviews[placeId] == null) {
453
+ _reviews[placeId] = mutableListOf()
441
454
  }
442
- reviews[placeId]?.add(0, review)
455
+ _reviews[placeId]?.add(0, review)
443
456
 
444
457
  // Update place rating (simplified average)
445
- places.find { it.id == placeId }?.let { place ->
446
- val placeReviews = reviews[placeId] ?: emptyList()
458
+ _places.find { it.id == placeId }?.let { place ->
459
+ val placeReviews = _reviews[placeId] ?: emptyList()
447
460
  val avgRating = placeReviews.map { it.rating }.average()
448
461
  place.rating = avgRating
449
462
  place.reviewCount = placeReviews.size
450
463
  }
451
464
 
452
- persistence.save(reviews, "mockdata_reviews")
453
- persistence.save(places, "mockdata_places")
465
+ persistence.save(_reviews, "mockdata_reviews")
466
+ persistence.save(_places, "mockdata_places")
454
467
  }
455
468
 
456
- fun toggleFavorite(place: Place) {
457
- places.find { it.id == place.id }?.let { foundPlace ->
469
+ override fun toggleFavorite(place: Place) {
470
+ _places.find { it.id == place.id }?.let { foundPlace ->
458
471
  foundPlace.isFavorite = !foundPlace.isFavorite
459
472
 
460
473
  if (foundPlace.isFavorite) {
@@ -465,18 +478,18 @@ class MockDataProvider @Inject constructor(
465
478
  currentUser.favoritePlaces = currentUser.favoritePlaces.filter { it != place.id }
466
479
  }
467
480
 
468
- persistence.save(places, "mockdata_places")
481
+ persistence.save(_places, "mockdata_places")
469
482
  }
470
483
  }
471
484
 
472
- fun getFavoritePlaces(): List<Place> {
473
- return places.filter { it.isFavorite }
485
+ override fun getFavoritePlaces(): List<Place> {
486
+ return _places.filter { it.isFavorite }
474
487
  }
475
488
 
476
489
  // MARK: - Filtering
477
490
 
478
- fun filterPlaces(criteria: FilterCriteria): List<Place> {
479
- var filtered = places.toList()
491
+ override fun filterPlaces(criteria: FilterCriteria): List<Place> {
492
+ var filtered = _places.toList()
480
493
 
481
494
  // Category filter
482
495
  if (criteria.categories.isNotEmpty()) {
@@ -510,11 +523,11 @@ class MockDataProvider @Inject constructor(
510
523
  return filtered
511
524
  }
512
525
 
513
- fun searchPlaces(query: String): List<Place> {
514
- if (query.isEmpty()) return places.toList()
526
+ override fun searchPlaces(query: String): List<Place> {
527
+ if (query.isEmpty()) return _places.toList()
515
528
 
516
529
  val lowercasedQuery = query.lowercase()
517
- return places.filter { place ->
530
+ return _places.filter { place ->
518
531
  place.name.lowercase().contains(lowercasedQuery) ||
519
532
  place.description.lowercase().contains(lowercasedQuery) ||
520
533
  place.category.name.lowercase().contains(lowercasedQuery) ||
@@ -524,7 +537,7 @@ class MockDataProvider @Inject constructor(
524
537
 
525
538
  // MARK: - Route Operations
526
539
 
527
- fun getRoute(origin: Coordinate, destination: Coordinate): Route? {
540
+ override fun getRoute(origin: Coordinate, destination: Coordinate): Route? {
528
541
  // In a real app, this would call a directions API
529
542
  // For now, return a mock route
530
543
  return Route(
@@ -540,13 +553,13 @@ class MockDataProvider @Inject constructor(
540
553
  }
541
554
 
542
555
  // MARK: - Reset
543
- fun reset() {
544
- places = makeDefaultPlaces().toMutableList()
545
- reviews = mutableMapOf()
546
- for (place in places) {
547
- reviews[place.id] = makeDefaultReviews(place.id).toMutableList()
556
+ override fun reset() {
557
+ _places = makeDefaultPlaces().toMutableList()
558
+ _reviews = mutableMapOf()
559
+ for (place in _places) {
560
+ _reviews[place.id] = makeDefaultReviews(place.id).toMutableList()
548
561
  }
549
- routes = makeDefaultRoutes().toMutableList()
562
+ _routes = makeDefaultRoutes().toMutableList()
550
563
  currentUser = defaultCurrentUser
551
564
 
552
565
  // Clear persistence
@@ -74,4 +74,13 @@ object AppConfig {
74
74
  )
75
75
  )
76
76
  }
77
+
78
+ // CUSTOMIZE:DATASOURCE - Data source configuration
79
+ object DataSource {
80
+ enum class SourceType {
81
+ LOCAL_STORAGE, // Room — real local database (DEFAULT)
82
+ MOCK // In-memory seed data — for development/testing only
83
+ }
84
+ val active: SourceType = SourceType.MOCK
85
+ }
77
86
  }