Vatxzz commited on
Commit
308b8d0
·
1 Parent(s): 700309d

Action_items

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. app/android/app/src/main/AndroidManifest.xml +1 -1
  2. app/ios/.gitignore +0 -34
  3. app/ios/Flutter/AppFrameworkInfo.plist +0 -24
  4. app/ios/Flutter/Debug.xcconfig +0 -1
  5. app/ios/Flutter/Release.xcconfig +0 -1
  6. app/ios/Runner.xcodeproj/project.pbxproj +0 -623
  7. app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  8. app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  9. app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +0 -8
  10. app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +0 -101
  11. app/ios/Runner.xcworkspace/contents.xcworkspacedata +0 -7
  12. app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  13. app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +0 -8
  14. app/ios/Runner/AppDelegate.swift +0 -16
  15. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -122
  16. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png +0 -0
  17. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png +0 -0
  18. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png +0 -0
  19. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png +0 -0
  20. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png +0 -0
  21. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png +0 -0
  22. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png +0 -0
  23. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png +0 -0
  24. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png +0 -0
  25. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png +0 -0
  26. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png +0 -0
  27. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png +0 -0
  28. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png +0 -0
  29. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png +0 -0
  30. app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png +0 -0
  31. app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +0 -23
  32. app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
  33. app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
  34. app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
  35. app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +0 -5
  36. app/ios/Runner/Base.lproj/LaunchScreen.storyboard +0 -37
  37. app/ios/Runner/Base.lproj/Main.storyboard +0 -26
  38. app/ios/Runner/Info.plist +0 -72
  39. app/ios/Runner/Runner-Bridging-Header.h +0 -1
  40. app/ios/Runner/SceneDelegate.swift +0 -6
  41. app/ios/RunnerTests/RunnerTests.swift +0 -12
  42. app/lib/data/repositories/card_repository.dart +9 -16
  43. app/lib/data/services/api_client.dart +13 -42
  44. app/lib/domain/models/card.dart +47 -1
  45. app/lib/domain/models/collection.dart +0 -51
  46. app/lib/ui/core/home_shell.dart +7 -7
  47. app/lib/ui/features/actions/view_models/actions_view_model.dart +111 -0
  48. app/lib/ui/features/actions/views/actions_screen.dart +290 -0
  49. app/lib/ui/features/collections/view_models/collections_view_model.dart +0 -65
  50. app/lib/ui/features/collections/views/collections_screen.dart +0 -292
app/android/app/src/main/AndroidManifest.xml CHANGED
@@ -25,7 +25,7 @@
25
  <category android:name="android.intent.category.LAUNCHER"/>
26
  </intent-filter>
27
  <!-- Share target: receive reel links shared as text from Instagram /
28
- TikTok / YouTube and a browser's share sheet (docs/06). -->
29
  <intent-filter>
30
  <action android:name="android.intent.action.SEND"/>
31
  <category android:name="android.intent.category.DEFAULT"/>
 
25
  <category android:name="android.intent.category.LAUNCHER"/>
26
  </intent-filter>
27
  <!-- Share target: receive reel links shared as text from Instagram /
28
+ YouTube and a browser's share sheet (docs/06). -->
29
  <intent-filter>
30
  <action android:name="android.intent.action.SEND"/>
31
  <category android:name="android.intent.category.DEFAULT"/>
app/ios/.gitignore DELETED
@@ -1,34 +0,0 @@
1
- **/dgph
2
- *.mode1v3
3
- *.mode2v3
4
- *.moved-aside
5
- *.pbxuser
6
- *.perspectivev3
7
- **/*sync/
8
- .sconsign.dblite
9
- .tags*
10
- **/.vagrant/
11
- **/DerivedData/
12
- Icon?
13
- **/Pods/
14
- **/.symlinks/
15
- profile
16
- xcuserdata
17
- **/.generated/
18
- Flutter/App.framework
19
- Flutter/Flutter.framework
20
- Flutter/Flutter.podspec
21
- Flutter/Generated.xcconfig
22
- Flutter/ephemeral/
23
- Flutter/app.flx
24
- Flutter/app.zip
25
- Flutter/flutter_assets/
26
- Flutter/flutter_export_environment.sh
27
- ServiceDefinitions.json
28
- Runner/GeneratedPluginRegistrant.*
29
-
30
- # Exceptions to above rules.
31
- !default.mode1v3
32
- !default.mode2v3
33
- !default.pbxuser
34
- !default.perspectivev3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/ios/Flutter/AppFrameworkInfo.plist DELETED
@@ -1,24 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>CFBundleDevelopmentRegion</key>
6
- <string>en</string>
7
- <key>CFBundleExecutable</key>
8
- <string>App</string>
9
- <key>CFBundleIdentifier</key>
10
- <string>io.flutter.flutter.app</string>
11
- <key>CFBundleInfoDictionaryVersion</key>
12
- <string>6.0</string>
13
- <key>CFBundleName</key>
14
- <string>App</string>
15
- <key>CFBundlePackageType</key>
16
- <string>FMWK</string>
17
- <key>CFBundleShortVersionString</key>
18
- <string>1.0</string>
19
- <key>CFBundleSignature</key>
20
- <string>????</string>
21
- <key>CFBundleVersion</key>
22
- <string>1.0</string>
23
- </dict>
24
- </plist>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/ios/Flutter/Debug.xcconfig DELETED
@@ -1 +0,0 @@
1
- #include "Generated.xcconfig"
 
 
app/ios/Flutter/Release.xcconfig DELETED
@@ -1 +0,0 @@
1
- #include "Generated.xcconfig"
 
 
app/ios/Runner.xcodeproj/project.pbxproj DELETED
@@ -1,623 +0,0 @@
1
- // !$*UTF8*$!
2
- {
3
- archiveVersion = 1;
4
- classes = {
5
- };
6
- objectVersion = 54;
7
- objects = {
8
-
9
- /* Begin PBXBuildFile section */
10
- 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11
- 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
12
- 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
13
- 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
14
- 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; };
15
- 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
16
- 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
17
- 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
18
- /* End PBXBuildFile section */
19
-
20
- /* Begin PBXContainerItemProxy section */
21
- 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
22
- isa = PBXContainerItemProxy;
23
- containerPortal = 97C146E61CF9000F007C117D /* Project object */;
24
- proxyType = 1;
25
- remoteGlobalIDString = 97C146ED1CF9000F007C117D;
26
- remoteInfo = Runner;
27
- };
28
- /* End PBXContainerItemProxy section */
29
-
30
- /* Begin PBXCopyFilesBuildPhase section */
31
- 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
32
- isa = PBXCopyFilesBuildPhase;
33
- buildActionMask = 2147483647;
34
- dstPath = "";
35
- dstSubfolderSpec = 10;
36
- files = (
37
- );
38
- name = "Embed Frameworks";
39
- runOnlyForDeploymentPostprocessing = 0;
40
- };
41
- /* End PBXCopyFilesBuildPhase section */
42
-
43
- /* Begin PBXFileReference section */
44
- 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
45
- 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
46
- 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
47
- 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
48
- 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
49
- 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
50
- 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
51
- 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
52
- 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
53
- 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
54
- 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
55
- 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
56
- 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
57
- 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
58
- 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
59
- 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
60
- /* End PBXFileReference section */
61
-
62
- /* Begin PBXFrameworksBuildPhase section */
63
- 97C146EB1CF9000F007C117D /* Frameworks */ = {
64
- isa = PBXFrameworksBuildPhase;
65
- buildActionMask = 2147483647;
66
- files = (
67
- );
68
- runOnlyForDeploymentPostprocessing = 0;
69
- };
70
- /* End PBXFrameworksBuildPhase section */
71
-
72
- /* Begin PBXGroup section */
73
- 331C8082294A63A400263BE5 /* RunnerTests */ = {
74
- isa = PBXGroup;
75
- children = (
76
- 331C807B294A618700263BE5 /* RunnerTests.swift */,
77
- );
78
- path = RunnerTests;
79
- sourceTree = "<group>";
80
- };
81
- 9740EEB11CF90186004384FC /* Flutter */ = {
82
- isa = PBXGroup;
83
- children = (
84
- 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
85
- 9740EEB21CF90195004384FC /* Debug.xcconfig */,
86
- 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
87
- 9740EEB31CF90195004384FC /* Generated.xcconfig */,
88
- );
89
- name = Flutter;
90
- sourceTree = "<group>";
91
- };
92
- 97C146E51CF9000F007C117D = {
93
- isa = PBXGroup;
94
- children = (
95
- 9740EEB11CF90186004384FC /* Flutter */,
96
- 97C146F01CF9000F007C117D /* Runner */,
97
- 97C146EF1CF9000F007C117D /* Products */,
98
- 331C8082294A63A400263BE5 /* RunnerTests */,
99
- );
100
- sourceTree = "<group>";
101
- };
102
- 97C146EF1CF9000F007C117D /* Products */ = {
103
- isa = PBXGroup;
104
- children = (
105
- 97C146EE1CF9000F007C117D /* Runner.app */,
106
- 331C8081294A63A400263BE5 /* RunnerTests.xctest */,
107
- );
108
- name = Products;
109
- sourceTree = "<group>";
110
- };
111
- 97C146F01CF9000F007C117D /* Runner */ = {
112
- isa = PBXGroup;
113
- children = (
114
- 97C146FA1CF9000F007C117D /* Main.storyboard */,
115
- 97C146FD1CF9000F007C117D /* Assets.xcassets */,
116
- 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
117
- 97C147021CF9000F007C117D /* Info.plist */,
118
- 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
119
- 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
120
- 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
121
- 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */,
122
- 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
123
- );
124
- path = Runner;
125
- sourceTree = "<group>";
126
- };
127
- /* End PBXGroup section */
128
-
129
- /* Begin PBXNativeTarget section */
130
- 331C8080294A63A400263BE5 /* RunnerTests */ = {
131
- isa = PBXNativeTarget;
132
- buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
133
- buildPhases = (
134
- 331C807D294A63A400263BE5 /* Sources */,
135
- 331C807F294A63A400263BE5 /* Resources */,
136
- );
137
- buildRules = (
138
- );
139
- dependencies = (
140
- 331C8086294A63A400263BE5 /* PBXTargetDependency */,
141
- );
142
- name = RunnerTests;
143
- productName = RunnerTests;
144
- productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
145
- productType = "com.apple.product-type.bundle.unit-test";
146
- };
147
- 97C146ED1CF9000F007C117D /* Runner */ = {
148
- isa = PBXNativeTarget;
149
- buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
150
- buildPhases = (
151
- 9740EEB61CF901F6004384FC /* Run Script */,
152
- 97C146EA1CF9000F007C117D /* Sources */,
153
- 97C146EB1CF9000F007C117D /* Frameworks */,
154
- 97C146EC1CF9000F007C117D /* Resources */,
155
- 9705A1C41CF9048500538489 /* Embed Frameworks */,
156
- 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
157
- );
158
- buildRules = (
159
- );
160
- dependencies = (
161
- );
162
- name = Runner;
163
- productName = Runner;
164
- productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
165
- productType = "com.apple.product-type.application";
166
- };
167
- /* End PBXNativeTarget section */
168
-
169
- /* Begin PBXProject section */
170
- 97C146E61CF9000F007C117D /* Project object */ = {
171
- isa = PBXProject;
172
- attributes = {
173
- BuildIndependentTargetsInParallel = YES;
174
- LastUpgradeCheck = 1510;
175
- ORGANIZATIONNAME = "";
176
- TargetAttributes = {
177
- 331C8080294A63A400263BE5 = {
178
- CreatedOnToolsVersion = 14.0;
179
- TestTargetID = 97C146ED1CF9000F007C117D;
180
- };
181
- 97C146ED1CF9000F007C117D = {
182
- CreatedOnToolsVersion = 7.3.1;
183
- LastSwiftMigration = 1100;
184
- };
185
- };
186
- };
187
- buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
188
- compatibilityVersion = "Xcode 9.3";
189
- developmentRegion = en;
190
- hasScannedForEncodings = 0;
191
- knownRegions = (
192
- en,
193
- Base,
194
- );
195
- mainGroup = 97C146E51CF9000F007C117D;
196
- productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
197
- projectDirPath = "";
198
- projectRoot = "";
199
- targets = (
200
- 97C146ED1CF9000F007C117D /* Runner */,
201
- 331C8080294A63A400263BE5 /* RunnerTests */,
202
- );
203
- };
204
- /* End PBXProject section */
205
-
206
- /* Begin PBXResourcesBuildPhase section */
207
- 331C807F294A63A400263BE5 /* Resources */ = {
208
- isa = PBXResourcesBuildPhase;
209
- buildActionMask = 2147483647;
210
- files = (
211
- );
212
- runOnlyForDeploymentPostprocessing = 0;
213
- };
214
- 97C146EC1CF9000F007C117D /* Resources */ = {
215
- isa = PBXResourcesBuildPhase;
216
- buildActionMask = 2147483647;
217
- files = (
218
- 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
219
- 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
220
- 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
221
- 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
222
- );
223
- runOnlyForDeploymentPostprocessing = 0;
224
- };
225
- /* End PBXResourcesBuildPhase section */
226
-
227
- /* Begin PBXShellScriptBuildPhase section */
228
- 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
229
- isa = PBXShellScriptBuildPhase;
230
- alwaysOutOfDate = 1;
231
- buildActionMask = 2147483647;
232
- files = (
233
- );
234
- inputPaths = (
235
- "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
236
- );
237
- name = "Thin Binary";
238
- outputPaths = (
239
- );
240
- runOnlyForDeploymentPostprocessing = 0;
241
- shellPath = /bin/sh;
242
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
243
- };
244
- 9740EEB61CF901F6004384FC /* Run Script */ = {
245
- isa = PBXShellScriptBuildPhase;
246
- alwaysOutOfDate = 1;
247
- buildActionMask = 2147483647;
248
- files = (
249
- );
250
- inputPaths = (
251
- );
252
- name = "Run Script";
253
- outputPaths = (
254
- );
255
- runOnlyForDeploymentPostprocessing = 0;
256
- shellPath = /bin/sh;
257
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
258
- };
259
- /* End PBXShellScriptBuildPhase section */
260
-
261
- /* Begin PBXSourcesBuildPhase section */
262
- 331C807D294A63A400263BE5 /* Sources */ = {
263
- isa = PBXSourcesBuildPhase;
264
- buildActionMask = 2147483647;
265
- files = (
266
- 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
267
- );
268
- runOnlyForDeploymentPostprocessing = 0;
269
- };
270
- 97C146EA1CF9000F007C117D /* Sources */ = {
271
- isa = PBXSourcesBuildPhase;
272
- buildActionMask = 2147483647;
273
- files = (
274
- 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
275
- 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
276
- 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */,
277
- );
278
- runOnlyForDeploymentPostprocessing = 0;
279
- };
280
- /* End PBXSourcesBuildPhase section */
281
-
282
- /* Begin PBXTargetDependency section */
283
- 331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
284
- isa = PBXTargetDependency;
285
- target = 97C146ED1CF9000F007C117D /* Runner */;
286
- targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
287
- };
288
- /* End PBXTargetDependency section */
289
-
290
- /* Begin PBXVariantGroup section */
291
- 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
292
- isa = PBXVariantGroup;
293
- children = (
294
- 97C146FB1CF9000F007C117D /* Base */,
295
- );
296
- name = Main.storyboard;
297
- sourceTree = "<group>";
298
- };
299
- 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
300
- isa = PBXVariantGroup;
301
- children = (
302
- 97C147001CF9000F007C117D /* Base */,
303
- );
304
- name = LaunchScreen.storyboard;
305
- sourceTree = "<group>";
306
- };
307
- /* End PBXVariantGroup section */
308
-
309
- /* Begin XCBuildConfiguration section */
310
- 249021D3217E4FDB00AE95B9 /* Profile */ = {
311
- isa = XCBuildConfiguration;
312
- buildSettings = {
313
- ALWAYS_SEARCH_USER_PATHS = NO;
314
- ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
315
- CLANG_ANALYZER_NONNULL = YES;
316
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
317
- CLANG_CXX_LIBRARY = "libc++";
318
- CLANG_ENABLE_MODULES = YES;
319
- CLANG_ENABLE_OBJC_ARC = YES;
320
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
321
- CLANG_WARN_BOOL_CONVERSION = YES;
322
- CLANG_WARN_COMMA = YES;
323
- CLANG_WARN_CONSTANT_CONVERSION = YES;
324
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
325
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
326
- CLANG_WARN_EMPTY_BODY = YES;
327
- CLANG_WARN_ENUM_CONVERSION = YES;
328
- CLANG_WARN_INFINITE_RECURSION = YES;
329
- CLANG_WARN_INT_CONVERSION = YES;
330
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
331
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
332
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
333
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
334
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
335
- CLANG_WARN_STRICT_PROTOTYPES = YES;
336
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
337
- CLANG_WARN_UNREACHABLE_CODE = YES;
338
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
339
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
340
- COPY_PHASE_STRIP = NO;
341
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
342
- ENABLE_NS_ASSERTIONS = NO;
343
- ENABLE_STRICT_OBJC_MSGSEND = YES;
344
- ENABLE_USER_SCRIPT_SANDBOXING = NO;
345
- GCC_C_LANGUAGE_STANDARD = gnu99;
346
- GCC_NO_COMMON_BLOCKS = YES;
347
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
348
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
349
- GCC_WARN_UNDECLARED_SELECTOR = YES;
350
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
351
- GCC_WARN_UNUSED_FUNCTION = YES;
352
- GCC_WARN_UNUSED_VARIABLE = YES;
353
- IPHONEOS_DEPLOYMENT_TARGET = 13.0;
354
- MTL_ENABLE_DEBUG_INFO = NO;
355
- SDKROOT = iphoneos;
356
- SUPPORTED_PLATFORMS = iphoneos;
357
- TARGETED_DEVICE_FAMILY = "1,2";
358
- VALIDATE_PRODUCT = YES;
359
- };
360
- name = Profile;
361
- };
362
- 249021D4217E4FDB00AE95B9 /* Profile */ = {
363
- isa = XCBuildConfiguration;
364
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
365
- buildSettings = {
366
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
367
- CLANG_ENABLE_MODULES = YES;
368
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
369
- DEVELOPMENT_TEAM = PZA655S72B;
370
- ENABLE_BITCODE = NO;
371
- INFOPLIST_FILE = Runner/Info.plist;
372
- LD_RUNPATH_SEARCH_PATHS = (
373
- "$(inherited)",
374
- "@executable_path/Frameworks",
375
- );
376
- PRODUCT_BUNDLE_IDENTIFIER = com.cachy.cachy;
377
- PRODUCT_NAME = "$(TARGET_NAME)";
378
- SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
379
- SWIFT_VERSION = 5.0;
380
- VERSIONING_SYSTEM = "apple-generic";
381
- };
382
- name = Profile;
383
- };
384
- 331C8088294A63A400263BE5 /* Debug */ = {
385
- isa = XCBuildConfiguration;
386
- buildSettings = {
387
- BUNDLE_LOADER = "$(TEST_HOST)";
388
- CODE_SIGN_STYLE = Automatic;
389
- CURRENT_PROJECT_VERSION = 1;
390
- GENERATE_INFOPLIST_FILE = YES;
391
- MARKETING_VERSION = 1.0;
392
- PRODUCT_BUNDLE_IDENTIFIER = com.cachy.cachy.RunnerTests;
393
- PRODUCT_NAME = "$(TARGET_NAME)";
394
- SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
395
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
396
- SWIFT_VERSION = 5.0;
397
- TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
398
- };
399
- name = Debug;
400
- };
401
- 331C8089294A63A400263BE5 /* Release */ = {
402
- isa = XCBuildConfiguration;
403
- buildSettings = {
404
- BUNDLE_LOADER = "$(TEST_HOST)";
405
- CODE_SIGN_STYLE = Automatic;
406
- CURRENT_PROJECT_VERSION = 1;
407
- GENERATE_INFOPLIST_FILE = YES;
408
- MARKETING_VERSION = 1.0;
409
- PRODUCT_BUNDLE_IDENTIFIER = com.cachy.cachy.RunnerTests;
410
- PRODUCT_NAME = "$(TARGET_NAME)";
411
- SWIFT_VERSION = 5.0;
412
- TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
413
- };
414
- name = Release;
415
- };
416
- 331C808A294A63A400263BE5 /* Profile */ = {
417
- isa = XCBuildConfiguration;
418
- buildSettings = {
419
- BUNDLE_LOADER = "$(TEST_HOST)";
420
- CODE_SIGN_STYLE = Automatic;
421
- CURRENT_PROJECT_VERSION = 1;
422
- GENERATE_INFOPLIST_FILE = YES;
423
- MARKETING_VERSION = 1.0;
424
- PRODUCT_BUNDLE_IDENTIFIER = com.cachy.cachy.RunnerTests;
425
- PRODUCT_NAME = "$(TARGET_NAME)";
426
- SWIFT_VERSION = 5.0;
427
- TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
428
- };
429
- name = Profile;
430
- };
431
- 97C147031CF9000F007C117D /* Debug */ = {
432
- isa = XCBuildConfiguration;
433
- buildSettings = {
434
- ALWAYS_SEARCH_USER_PATHS = NO;
435
- ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
436
- CLANG_ANALYZER_NONNULL = YES;
437
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
438
- CLANG_CXX_LIBRARY = "libc++";
439
- CLANG_ENABLE_MODULES = YES;
440
- CLANG_ENABLE_OBJC_ARC = YES;
441
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
442
- CLANG_WARN_BOOL_CONVERSION = YES;
443
- CLANG_WARN_COMMA = YES;
444
- CLANG_WARN_CONSTANT_CONVERSION = YES;
445
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
446
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
447
- CLANG_WARN_EMPTY_BODY = YES;
448
- CLANG_WARN_ENUM_CONVERSION = YES;
449
- CLANG_WARN_INFINITE_RECURSION = YES;
450
- CLANG_WARN_INT_CONVERSION = YES;
451
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
452
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
453
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
454
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
455
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
456
- CLANG_WARN_STRICT_PROTOTYPES = YES;
457
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
458
- CLANG_WARN_UNREACHABLE_CODE = YES;
459
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
460
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
461
- COPY_PHASE_STRIP = NO;
462
- DEBUG_INFORMATION_FORMAT = dwarf;
463
- ENABLE_STRICT_OBJC_MSGSEND = YES;
464
- ENABLE_TESTABILITY = YES;
465
- ENABLE_USER_SCRIPT_SANDBOXING = NO;
466
- GCC_C_LANGUAGE_STANDARD = gnu99;
467
- GCC_DYNAMIC_NO_PIC = NO;
468
- GCC_NO_COMMON_BLOCKS = YES;
469
- GCC_OPTIMIZATION_LEVEL = 0;
470
- GCC_PREPROCESSOR_DEFINITIONS = (
471
- "DEBUG=1",
472
- "$(inherited)",
473
- );
474
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
475
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
476
- GCC_WARN_UNDECLARED_SELECTOR = YES;
477
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
478
- GCC_WARN_UNUSED_FUNCTION = YES;
479
- GCC_WARN_UNUSED_VARIABLE = YES;
480
- IPHONEOS_DEPLOYMENT_TARGET = 13.0;
481
- MTL_ENABLE_DEBUG_INFO = YES;
482
- ONLY_ACTIVE_ARCH = YES;
483
- SDKROOT = iphoneos;
484
- TARGETED_DEVICE_FAMILY = "1,2";
485
- };
486
- name = Debug;
487
- };
488
- 97C147041CF9000F007C117D /* Release */ = {
489
- isa = XCBuildConfiguration;
490
- buildSettings = {
491
- ALWAYS_SEARCH_USER_PATHS = NO;
492
- ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
493
- CLANG_ANALYZER_NONNULL = YES;
494
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
495
- CLANG_CXX_LIBRARY = "libc++";
496
- CLANG_ENABLE_MODULES = YES;
497
- CLANG_ENABLE_OBJC_ARC = YES;
498
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
499
- CLANG_WARN_BOOL_CONVERSION = YES;
500
- CLANG_WARN_COMMA = YES;
501
- CLANG_WARN_CONSTANT_CONVERSION = YES;
502
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
503
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
504
- CLANG_WARN_EMPTY_BODY = YES;
505
- CLANG_WARN_ENUM_CONVERSION = YES;
506
- CLANG_WARN_INFINITE_RECURSION = YES;
507
- CLANG_WARN_INT_CONVERSION = YES;
508
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
509
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
510
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
511
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
512
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
513
- CLANG_WARN_STRICT_PROTOTYPES = YES;
514
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
515
- CLANG_WARN_UNREACHABLE_CODE = YES;
516
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
517
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
518
- COPY_PHASE_STRIP = NO;
519
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
520
- ENABLE_NS_ASSERTIONS = NO;
521
- ENABLE_STRICT_OBJC_MSGSEND = YES;
522
- ENABLE_USER_SCRIPT_SANDBOXING = NO;
523
- GCC_C_LANGUAGE_STANDARD = gnu99;
524
- GCC_NO_COMMON_BLOCKS = YES;
525
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
526
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
527
- GCC_WARN_UNDECLARED_SELECTOR = YES;
528
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
529
- GCC_WARN_UNUSED_FUNCTION = YES;
530
- GCC_WARN_UNUSED_VARIABLE = YES;
531
- IPHONEOS_DEPLOYMENT_TARGET = 13.0;
532
- MTL_ENABLE_DEBUG_INFO = NO;
533
- SDKROOT = iphoneos;
534
- SUPPORTED_PLATFORMS = iphoneos;
535
- SWIFT_COMPILATION_MODE = wholemodule;
536
- SWIFT_OPTIMIZATION_LEVEL = "-O";
537
- TARGETED_DEVICE_FAMILY = "1,2";
538
- VALIDATE_PRODUCT = YES;
539
- };
540
- name = Release;
541
- };
542
- 97C147061CF9000F007C117D /* Debug */ = {
543
- isa = XCBuildConfiguration;
544
- baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
545
- buildSettings = {
546
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
547
- CLANG_ENABLE_MODULES = YES;
548
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
549
- DEVELOPMENT_TEAM = PZA655S72B;
550
- ENABLE_BITCODE = NO;
551
- INFOPLIST_FILE = Runner/Info.plist;
552
- LD_RUNPATH_SEARCH_PATHS = (
553
- "$(inherited)",
554
- "@executable_path/Frameworks",
555
- );
556
- PRODUCT_BUNDLE_IDENTIFIER = com.cachy.cachy;
557
- PRODUCT_NAME = "$(TARGET_NAME)";
558
- SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
559
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
560
- SWIFT_VERSION = 5.0;
561
- VERSIONING_SYSTEM = "apple-generic";
562
- };
563
- name = Debug;
564
- };
565
- 97C147071CF9000F007C117D /* Release */ = {
566
- isa = XCBuildConfiguration;
567
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
568
- buildSettings = {
569
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
570
- CLANG_ENABLE_MODULES = YES;
571
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
572
- DEVELOPMENT_TEAM = PZA655S72B;
573
- ENABLE_BITCODE = NO;
574
- INFOPLIST_FILE = Runner/Info.plist;
575
- LD_RUNPATH_SEARCH_PATHS = (
576
- "$(inherited)",
577
- "@executable_path/Frameworks",
578
- );
579
- PRODUCT_BUNDLE_IDENTIFIER = com.cachy.cachy;
580
- PRODUCT_NAME = "$(TARGET_NAME)";
581
- SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
582
- SWIFT_VERSION = 5.0;
583
- VERSIONING_SYSTEM = "apple-generic";
584
- };
585
- name = Release;
586
- };
587
- /* End XCBuildConfiguration section */
588
-
589
- /* Begin XCConfigurationList section */
590
- 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
591
- isa = XCConfigurationList;
592
- buildConfigurations = (
593
- 331C8088294A63A400263BE5 /* Debug */,
594
- 331C8089294A63A400263BE5 /* Release */,
595
- 331C808A294A63A400263BE5 /* Profile */,
596
- );
597
- defaultConfigurationIsVisible = 0;
598
- defaultConfigurationName = Release;
599
- };
600
- 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
601
- isa = XCConfigurationList;
602
- buildConfigurations = (
603
- 97C147031CF9000F007C117D /* Debug */,
604
- 97C147041CF9000F007C117D /* Release */,
605
- 249021D3217E4FDB00AE95B9 /* Profile */,
606
- );
607
- defaultConfigurationIsVisible = 0;
608
- defaultConfigurationName = Release;
609
- };
610
- 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
611
- isa = XCConfigurationList;
612
- buildConfigurations = (
613
- 97C147061CF9000F007C117D /* Debug */,
614
- 97C147071CF9000F007C117D /* Release */,
615
- 249021D4217E4FDB00AE95B9 /* Profile */,
616
- );
617
- defaultConfigurationIsVisible = 0;
618
- defaultConfigurationName = Release;
619
- };
620
- /* End XCConfigurationList section */
621
- };
622
- rootObject = 97C146E61CF9000F007C117D /* Project object */;
623
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata DELETED
@@ -1,7 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Workspace
3
- version = "1.0">
4
- <FileRef
5
- location = "self:">
6
- </FileRef>
7
- </Workspace>
 
 
 
 
 
 
 
 
app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>IDEDidComputeMac32BitWarning</key>
6
- <true/>
7
- </dict>
8
- </plist>
 
 
 
 
 
 
 
 
 
app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>PreviewsEnabled</key>
6
- <false/>
7
- </dict>
8
- </plist>
 
 
 
 
 
 
 
 
 
app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme DELETED
@@ -1,101 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Scheme
3
- LastUpgradeVersion = "1510"
4
- version = "1.3">
5
- <BuildAction
6
- parallelizeBuildables = "YES"
7
- buildImplicitDependencies = "YES">
8
- <BuildActionEntries>
9
- <BuildActionEntry
10
- buildForTesting = "YES"
11
- buildForRunning = "YES"
12
- buildForProfiling = "YES"
13
- buildForArchiving = "YES"
14
- buildForAnalyzing = "YES">
15
- <BuildableReference
16
- BuildableIdentifier = "primary"
17
- BlueprintIdentifier = "97C146ED1CF9000F007C117D"
18
- BuildableName = "Runner.app"
19
- BlueprintName = "Runner"
20
- ReferencedContainer = "container:Runner.xcodeproj">
21
- </BuildableReference>
22
- </BuildActionEntry>
23
- </BuildActionEntries>
24
- </BuildAction>
25
- <TestAction
26
- buildConfiguration = "Debug"
27
- selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29
- customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
30
- shouldUseLaunchSchemeArgsEnv = "YES">
31
- <MacroExpansion>
32
- <BuildableReference
33
- BuildableIdentifier = "primary"
34
- BlueprintIdentifier = "97C146ED1CF9000F007C117D"
35
- BuildableName = "Runner.app"
36
- BlueprintName = "Runner"
37
- ReferencedContainer = "container:Runner.xcodeproj">
38
- </BuildableReference>
39
- </MacroExpansion>
40
- <Testables>
41
- <TestableReference
42
- skipped = "NO"
43
- parallelizable = "YES">
44
- <BuildableReference
45
- BuildableIdentifier = "primary"
46
- BlueprintIdentifier = "331C8080294A63A400263BE5"
47
- BuildableName = "RunnerTests.xctest"
48
- BlueprintName = "RunnerTests"
49
- ReferencedContainer = "container:Runner.xcodeproj">
50
- </BuildableReference>
51
- </TestableReference>
52
- </Testables>
53
- </TestAction>
54
- <LaunchAction
55
- buildConfiguration = "Debug"
56
- selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
57
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
58
- customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
59
- launchStyle = "0"
60
- useCustomWorkingDirectory = "NO"
61
- ignoresPersistentStateOnLaunch = "NO"
62
- debugDocumentVersioning = "YES"
63
- debugServiceExtension = "internal"
64
- enableGPUValidationMode = "1"
65
- allowLocationSimulation = "YES">
66
- <BuildableProductRunnable
67
- runnableDebuggingMode = "0">
68
- <BuildableReference
69
- BuildableIdentifier = "primary"
70
- BlueprintIdentifier = "97C146ED1CF9000F007C117D"
71
- BuildableName = "Runner.app"
72
- BlueprintName = "Runner"
73
- ReferencedContainer = "container:Runner.xcodeproj">
74
- </BuildableReference>
75
- </BuildableProductRunnable>
76
- </LaunchAction>
77
- <ProfileAction
78
- buildConfiguration = "Profile"
79
- shouldUseLaunchSchemeArgsEnv = "YES"
80
- savedToolIdentifier = ""
81
- useCustomWorkingDirectory = "NO"
82
- debugDocumentVersioning = "YES">
83
- <BuildableProductRunnable
84
- runnableDebuggingMode = "0">
85
- <BuildableReference
86
- BuildableIdentifier = "primary"
87
- BlueprintIdentifier = "97C146ED1CF9000F007C117D"
88
- BuildableName = "Runner.app"
89
- BlueprintName = "Runner"
90
- ReferencedContainer = "container:Runner.xcodeproj">
91
- </BuildableReference>
92
- </BuildableProductRunnable>
93
- </ProfileAction>
94
- <AnalyzeAction
95
- buildConfiguration = "Debug">
96
- </AnalyzeAction>
97
- <ArchiveAction
98
- buildConfiguration = "Release"
99
- revealArchiveInOrganizer = "YES">
100
- </ArchiveAction>
101
- </Scheme>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/ios/Runner.xcworkspace/contents.xcworkspacedata DELETED
@@ -1,7 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Workspace
3
- version = "1.0">
4
- <FileRef
5
- location = "group:Runner.xcodeproj">
6
- </FileRef>
7
- </Workspace>
 
 
 
 
 
 
 
 
app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>IDEDidComputeMac32BitWarning</key>
6
- <true/>
7
- </dict>
8
- </plist>
 
 
 
 
 
 
 
 
 
app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>PreviewsEnabled</key>
6
- <false/>
7
- </dict>
8
- </plist>
 
 
 
 
 
 
 
 
 
app/ios/Runner/AppDelegate.swift DELETED
@@ -1,16 +0,0 @@
1
- import Flutter
2
- import UIKit
3
-
4
- @main
5
- @objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
6
- override func application(
7
- _ application: UIApplication,
8
- didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9
- ) -> Bool {
10
- return super.application(application, didFinishLaunchingWithOptions: launchOptions)
11
- }
12
-
13
- func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
14
- GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
15
- }
16
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json DELETED
@@ -1,122 +0,0 @@
1
- {
2
- "images" : [
3
- {
4
- "size" : "20x20",
5
- "idiom" : "iphone",
6
- "filename" : "Icon-App-20x20@2x.png",
7
- "scale" : "2x"
8
- },
9
- {
10
- "size" : "20x20",
11
- "idiom" : "iphone",
12
- "filename" : "Icon-App-20x20@3x.png",
13
- "scale" : "3x"
14
- },
15
- {
16
- "size" : "29x29",
17
- "idiom" : "iphone",
18
- "filename" : "Icon-App-29x29@1x.png",
19
- "scale" : "1x"
20
- },
21
- {
22
- "size" : "29x29",
23
- "idiom" : "iphone",
24
- "filename" : "Icon-App-29x29@2x.png",
25
- "scale" : "2x"
26
- },
27
- {
28
- "size" : "29x29",
29
- "idiom" : "iphone",
30
- "filename" : "Icon-App-29x29@3x.png",
31
- "scale" : "3x"
32
- },
33
- {
34
- "size" : "40x40",
35
- "idiom" : "iphone",
36
- "filename" : "Icon-App-40x40@2x.png",
37
- "scale" : "2x"
38
- },
39
- {
40
- "size" : "40x40",
41
- "idiom" : "iphone",
42
- "filename" : "Icon-App-40x40@3x.png",
43
- "scale" : "3x"
44
- },
45
- {
46
- "size" : "60x60",
47
- "idiom" : "iphone",
48
- "filename" : "Icon-App-60x60@2x.png",
49
- "scale" : "2x"
50
- },
51
- {
52
- "size" : "60x60",
53
- "idiom" : "iphone",
54
- "filename" : "Icon-App-60x60@3x.png",
55
- "scale" : "3x"
56
- },
57
- {
58
- "size" : "20x20",
59
- "idiom" : "ipad",
60
- "filename" : "Icon-App-20x20@1x.png",
61
- "scale" : "1x"
62
- },
63
- {
64
- "size" : "20x20",
65
- "idiom" : "ipad",
66
- "filename" : "Icon-App-20x20@2x.png",
67
- "scale" : "2x"
68
- },
69
- {
70
- "size" : "29x29",
71
- "idiom" : "ipad",
72
- "filename" : "Icon-App-29x29@1x.png",
73
- "scale" : "1x"
74
- },
75
- {
76
- "size" : "29x29",
77
- "idiom" : "ipad",
78
- "filename" : "Icon-App-29x29@2x.png",
79
- "scale" : "2x"
80
- },
81
- {
82
- "size" : "40x40",
83
- "idiom" : "ipad",
84
- "filename" : "Icon-App-40x40@1x.png",
85
- "scale" : "1x"
86
- },
87
- {
88
- "size" : "40x40",
89
- "idiom" : "ipad",
90
- "filename" : "Icon-App-40x40@2x.png",
91
- "scale" : "2x"
92
- },
93
- {
94
- "size" : "76x76",
95
- "idiom" : "ipad",
96
- "filename" : "Icon-App-76x76@1x.png",
97
- "scale" : "1x"
98
- },
99
- {
100
- "size" : "76x76",
101
- "idiom" : "ipad",
102
- "filename" : "Icon-App-76x76@2x.png",
103
- "scale" : "2x"
104
- },
105
- {
106
- "size" : "83.5x83.5",
107
- "idiom" : "ipad",
108
- "filename" : "Icon-App-83.5x83.5@2x.png",
109
- "scale" : "2x"
110
- },
111
- {
112
- "size" : "1024x1024",
113
- "idiom" : "ios-marketing",
114
- "filename" : "Icon-App-1024x1024@1x.png",
115
- "scale" : "1x"
116
- }
117
- ],
118
- "info" : {
119
- "version" : 1,
120
- "author" : "xcode"
121
- }
122
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png DELETED
Binary file (10.9 kB)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png DELETED
Binary file (295 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png DELETED
Binary file (406 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png DELETED
Binary file (450 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png DELETED
Binary file (282 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png DELETED
Binary file (462 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png DELETED
Binary file (704 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png DELETED
Binary file (406 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png DELETED
Binary file (586 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png DELETED
Binary file (862 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png DELETED
Binary file (862 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png DELETED
Binary file (1.67 kB)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png DELETED
Binary file (762 Bytes)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png DELETED
Binary file (1.23 kB)
 
app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png DELETED
Binary file (1.42 kB)
 
app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json DELETED
@@ -1,23 +0,0 @@
1
- {
2
- "images" : [
3
- {
4
- "idiom" : "universal",
5
- "filename" : "LaunchImage.png",
6
- "scale" : "1x"
7
- },
8
- {
9
- "idiom" : "universal",
10
- "filename" : "LaunchImage@2x.png",
11
- "scale" : "2x"
12
- },
13
- {
14
- "idiom" : "universal",
15
- "filename" : "LaunchImage@3x.png",
16
- "scale" : "3x"
17
- }
18
- ],
19
- "info" : {
20
- "version" : 1,
21
- "author" : "xcode"
22
- }
23
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png DELETED
Binary file (68 Bytes)
 
app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png DELETED
Binary file (68 Bytes)
 
app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png DELETED
Binary file (68 Bytes)
 
app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md DELETED
@@ -1,5 +0,0 @@
1
- # Launch Screen Assets
2
-
3
- You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4
-
5
- You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
 
 
 
 
 
 
app/ios/Runner/Base.lproj/LaunchScreen.storyboard DELETED
@@ -1,37 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
- <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
3
- <dependencies>
4
- <deployment identifier="iOS"/>
5
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
6
- </dependencies>
7
- <scenes>
8
- <!--View Controller-->
9
- <scene sceneID="EHf-IW-A2E">
10
- <objects>
11
- <viewController id="01J-lp-oVM" sceneMemberID="viewController">
12
- <layoutGuides>
13
- <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
14
- <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
15
- </layoutGuides>
16
- <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
17
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
18
- <subviews>
19
- <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
20
- </imageView>
21
- </subviews>
22
- <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
23
- <constraints>
24
- <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
25
- <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
26
- </constraints>
27
- </view>
28
- </viewController>
29
- <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
30
- </objects>
31
- <point key="canvasLocation" x="53" y="375"/>
32
- </scene>
33
- </scenes>
34
- <resources>
35
- <image name="LaunchImage" width="168" height="185"/>
36
- </resources>
37
- </document>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/ios/Runner/Base.lproj/Main.storyboard DELETED
@@ -1,26 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
- <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
3
- <dependencies>
4
- <deployment identifier="iOS"/>
5
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
6
- </dependencies>
7
- <scenes>
8
- <!--Flutter View Controller-->
9
- <scene sceneID="tne-QT-ifu">
10
- <objects>
11
- <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
12
- <layoutGuides>
13
- <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
14
- <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
15
- </layoutGuides>
16
- <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
17
- <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
18
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19
- <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
20
- </view>
21
- </viewController>
22
- <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
23
- </objects>
24
- </scene>
25
- </scenes>
26
- </document>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/ios/Runner/Info.plist DELETED
@@ -1,72 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>NSCalendarsUsageDescription</key>
6
- <string>Cachy adds reminders and sessions from your cards to your calendar.</string>
7
- <key>CADisableMinimumFrameDurationOnPhone</key>
8
- <true/>
9
- <key>CFBundleDevelopmentRegion</key>
10
- <string>$(DEVELOPMENT_LANGUAGE)</string>
11
- <key>CFBundleDisplayName</key>
12
- <string>Cachy</string>
13
- <key>CFBundleExecutable</key>
14
- <string>$(EXECUTABLE_NAME)</string>
15
- <key>CFBundleIdentifier</key>
16
- <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
17
- <key>CFBundleInfoDictionaryVersion</key>
18
- <string>6.0</string>
19
- <key>CFBundleName</key>
20
- <string>cachy</string>
21
- <key>CFBundlePackageType</key>
22
- <string>APPL</string>
23
- <key>CFBundleShortVersionString</key>
24
- <string>$(FLUTTER_BUILD_NAME)</string>
25
- <key>CFBundleSignature</key>
26
- <string>????</string>
27
- <key>CFBundleVersion</key>
28
- <string>$(FLUTTER_BUILD_NUMBER)</string>
29
- <key>LSRequiresIPhoneOS</key>
30
- <true/>
31
- <key>UIApplicationSceneManifest</key>
32
- <dict>
33
- <key>UIApplicationSupportsMultipleScenes</key>
34
- <false/>
35
- <key>UISceneConfigurations</key>
36
- <dict>
37
- <key>UIWindowSceneSessionRoleApplication</key>
38
- <array>
39
- <dict>
40
- <key>UISceneClassName</key>
41
- <string>UIWindowScene</string>
42
- <key>UISceneConfigurationName</key>
43
- <string>flutter</string>
44
- <key>UISceneDelegateClassName</key>
45
- <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
46
- <key>UISceneStoryboardFile</key>
47
- <string>Main</string>
48
- </dict>
49
- </array>
50
- </dict>
51
- </dict>
52
- <key>UIApplicationSupportsIndirectInputEvents</key>
53
- <true/>
54
- <key>UILaunchStoryboardName</key>
55
- <string>LaunchScreen</string>
56
- <key>UIMainStoryboardFile</key>
57
- <string>Main</string>
58
- <key>UISupportedInterfaceOrientations</key>
59
- <array>
60
- <string>UIInterfaceOrientationPortrait</string>
61
- <string>UIInterfaceOrientationLandscapeLeft</string>
62
- <string>UIInterfaceOrientationLandscapeRight</string>
63
- </array>
64
- <key>UISupportedInterfaceOrientations~ipad</key>
65
- <array>
66
- <string>UIInterfaceOrientationPortrait</string>
67
- <string>UIInterfaceOrientationPortraitUpsideDown</string>
68
- <string>UIInterfaceOrientationLandscapeLeft</string>
69
- <string>UIInterfaceOrientationLandscapeRight</string>
70
- </array>
71
- </dict>
72
- </plist>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/ios/Runner/Runner-Bridging-Header.h DELETED
@@ -1 +0,0 @@
1
- #import "GeneratedPluginRegistrant.h"
 
 
app/ios/Runner/SceneDelegate.swift DELETED
@@ -1,6 +0,0 @@
1
- import Flutter
2
- import UIKit
3
-
4
- class SceneDelegate: FlutterSceneDelegate {
5
-
6
- }
 
 
 
 
 
 
 
app/ios/RunnerTests/RunnerTests.swift DELETED
@@ -1,12 +0,0 @@
1
- import Flutter
2
- import UIKit
3
- import XCTest
4
-
5
- class RunnerTests: XCTestCase {
6
-
7
- func testExample() {
8
- // If you add code to the Runner application, consider adding tests here.
9
- // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10
- }
11
-
12
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
app/lib/data/repositories/card_repository.dart CHANGED
@@ -7,7 +7,6 @@ import 'dart:convert';
7
 
8
  import '../../domain/models/artifact.dart';
9
  import '../../domain/models/card.dart';
10
- import '../../domain/models/collection.dart';
11
  import '../../domain/models/enums.dart';
12
  import '../../domain/models/graph.dart';
13
  import '../../domain/models/pipeline_event.dart';
@@ -97,6 +96,14 @@ class CardRepository {
97
  return card;
98
  }
99
 
 
 
 
 
 
 
 
 
100
  Future<void> delete(String cardId) async {
101
  await _api.deleteCard(cardId);
102
  await _store.removeCard(cardId);
@@ -137,21 +144,6 @@ class CardRepository {
137
  Future<LibraryChatResult> libraryChat(List<Map<String, String>> messages) =>
138
  _api.libraryChat(messages);
139
 
140
- // --- collections (docs/09) — user-created groups of cards --------------- //
141
- Future<List<Collection>> listCollections() => _api.listCollections();
142
-
143
- Future<CollectionDetail> getCollection(String id) => _api.getCollection(id);
144
-
145
- Future<Collection> createCollection(String name) =>
146
- _api.createCollection(name);
147
-
148
- Future<void> deleteCollection(String id) => _api.deleteCollection(id);
149
-
150
- Future<Collection> addCardToCollection(String id, String cardId) =>
151
- _api.addCardToCollection(id, cardId);
152
-
153
- Future<Collection> removeCardFromCollection(String id, String cardId) =>
154
- _api.removeCardFromCollection(id, cardId);
155
 
156
  /// Reconstruct the raw JSON for caching. Uses preserved `rawBlocks` so block
157
  /// state round-trips losslessly.
@@ -180,6 +172,7 @@ class CardRepository {
180
  'label': card.primaryAction.label,
181
  'payload': card.primaryAction.payload,
182
  },
 
183
  'blocks': card.rawBlocks,
184
  'media': {
185
  'thumbnail': card.media.thumbnail,
 
7
 
8
  import '../../domain/models/artifact.dart';
9
  import '../../domain/models/card.dart';
 
10
  import '../../domain/models/enums.dart';
11
  import '../../domain/models/graph.dart';
12
  import '../../domain/models/pipeline_event.dart';
 
96
  return card;
97
  }
98
 
99
+ /// Persist the card's action list (docs/13) — follow toggle + per-item done.
100
+ Future<Card> patchActionItems(
101
+ String cardId, Map<String, dynamic> actionItems) async {
102
+ final card = await _api.patchCardActionItems(cardId, actionItems);
103
+ await _store.cacheCard(cardId, _rawOf(card));
104
+ return card;
105
+ }
106
+
107
  Future<void> delete(String cardId) async {
108
  await _api.deleteCard(cardId);
109
  await _store.removeCard(cardId);
 
144
  Future<LibraryChatResult> libraryChat(List<Map<String, String>> messages) =>
145
  _api.libraryChat(messages);
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
  /// Reconstruct the raw JSON for caching. Uses preserved `rawBlocks` so block
149
  /// state round-trips losslessly.
 
172
  'label': card.primaryAction.label,
173
  'payload': card.primaryAction.payload,
174
  },
175
+ 'action_items': card.actionItems.toJson(),
176
  'blocks': card.rawBlocks,
177
  'media': {
178
  'thumbnail': card.media.thumbnail,
app/lib/data/services/api_client.dart CHANGED
@@ -9,7 +9,6 @@ import 'package:http/http.dart' as http;
9
 
10
  import '../../domain/models/artifact.dart';
11
  import '../../domain/models/card.dart';
12
- import '../../domain/models/collection.dart';
13
  import '../../domain/models/enums.dart';
14
  import '../../domain/models/graph.dart';
15
  import '../../domain/models/pipeline_event.dart';
@@ -126,6 +125,19 @@ class ApiClient {
126
  return Card.fromJson(_decodeMap(resp));
127
  }
128
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  Future<void> deleteCard(String cardId) async {
130
  final resp = await _client.delete(_uri('/cards/$cardId'));
131
  if (resp.statusCode >= 400) {
@@ -230,47 +242,6 @@ class ApiClient {
230
  );
231
  }
232
 
233
- // ------------------------------------------------------------------------- //
234
- // Collections — user-created groups of cards (docs/09)
235
- // ------------------------------------------------------------------------- //
236
-
237
- Future<List<Collection>> listCollections() async {
238
- final resp = await _client.get(_uri('/collections'));
239
- return _decodeList(resp).map(Collection.fromJson).toList();
240
- }
241
-
242
- Future<CollectionDetail> getCollection(String id) async {
243
- final resp = await _client.get(_uri('/collections/$id'));
244
- return CollectionDetail.fromJson(_decodeMap(resp));
245
- }
246
-
247
- Future<Collection> createCollection(String name) async {
248
- final resp = await _client.post(
249
- _uri('/collections'),
250
- headers: const {'content-type': 'application/json'},
251
- body: jsonEncode({'name': name}),
252
- );
253
- return Collection.fromJson(_decodeMap(resp));
254
- }
255
-
256
- Future<void> deleteCollection(String id) async {
257
- final resp = await _client.delete(_uri('/collections/$id'));
258
- if (resp.statusCode >= 400) throw ApiException(resp.statusCode, resp.body);
259
- }
260
-
261
- Future<Collection> addCardToCollection(String id, String cardId) async {
262
- final resp = await _client.post(
263
- _uri('/collections/$id/cards'),
264
- headers: const {'content-type': 'application/json'},
265
- body: jsonEncode({'card_id': cardId}),
266
- );
267
- return Collection.fromJson(_decodeMap(resp));
268
- }
269
-
270
- Future<Collection> removeCardFromCollection(String id, String cardId) async {
271
- final resp = await _client.delete(_uri('/collections/$id/cards/$cardId'));
272
- return Collection.fromJson(_decodeMap(resp));
273
- }
274
 
275
  // ------------------------------------------------------------------------- //
276
  // SSE pipeline stream — GET /cards/{id}/stream
 
9
 
10
  import '../../domain/models/artifact.dart';
11
  import '../../domain/models/card.dart';
 
12
  import '../../domain/models/enums.dart';
13
  import '../../domain/models/graph.dart';
14
  import '../../domain/models/pipeline_event.dart';
 
125
  return Card.fromJson(_decodeMap(resp));
126
  }
127
 
128
+ /// Persist the card's action list (docs/13): follow toggle + per-item done.
129
+ Future<Card> patchCardActionItems(
130
+ String cardId,
131
+ Map<String, dynamic> actionItems,
132
+ ) async {
133
+ final resp = await _client.patch(
134
+ _uri('/cards/$cardId'),
135
+ headers: const {'content-type': 'application/json'},
136
+ body: jsonEncode({'action_items': actionItems}),
137
+ );
138
+ return Card.fromJson(_decodeMap(resp));
139
+ }
140
+
141
  Future<void> deleteCard(String cardId) async {
142
  final resp = await _client.delete(_uri('/cards/$cardId'));
143
  if (resp.statusCode >= 400) {
 
242
  );
243
  }
244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
 
246
  // ------------------------------------------------------------------------- //
247
  // SSE pipeline stream — GET /cards/{id}/stream
app/lib/domain/models/card.dart CHANGED
@@ -17,7 +17,7 @@ class Source {
17
  });
18
 
19
  final String url;
20
- final String? platform; // instagram | tiktok | youtube
21
  final String? creator;
22
  final String caption;
23
  final int? durationSeconds;
@@ -78,6 +78,45 @@ class PrimaryAction {
78
  );
79
  }
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  class Media {
82
  const Media({this.thumbnail, this.keyframes = const []});
83
 
@@ -134,6 +173,7 @@ class Card {
134
  required this.source,
135
  this.base = const Base(),
136
  this.primaryAction = const PrimaryAction(),
 
137
  this.blocks = const [],
138
  this.media = const Media(),
139
  this.meta = const Meta(),
@@ -147,6 +187,7 @@ class Card {
147
  final Source source;
148
  final Base base;
149
  final PrimaryAction primaryAction;
 
150
  final List<Block> blocks;
151
  final Media media;
152
  final Meta meta;
@@ -179,6 +220,9 @@ class Card {
179
  primaryAction: PrimaryAction.fromJson(
180
  (json['primary_action'] as Map<String, dynamic>?) ?? const {},
181
  ),
 
 
 
182
  blocks: rawBlocks.map(Block.fromJson).toList(),
183
  media: Media.fromJson((json['media'] as Map<String, dynamic>?) ?? const {}),
184
  meta: Meta.fromJson((json['meta'] as Map<String, dynamic>?) ?? const {}),
@@ -188,6 +232,7 @@ class Card {
188
 
189
  Card copyWith({
190
  CardState? state,
 
191
  List<Block>? blocks,
192
  List<Map<String, dynamic>>? rawBlocks,
193
  }) =>
@@ -199,6 +244,7 @@ class Card {
199
  source: source,
200
  base: base,
201
  primaryAction: primaryAction,
 
202
  blocks: blocks ?? this.blocks,
203
  media: media,
204
  meta: meta,
 
17
  });
18
 
19
  final String url;
20
+ final String? platform; // instagram | youtube
21
  final String? creator;
22
  final String caption;
23
  final int? durationSeconds;
 
78
  );
79
  }
80
 
81
+ /// One concrete to-do the reel tells the viewer to do (docs/13).
82
+ class ActionItem {
83
+ const ActionItem({required this.id, required this.text, this.done = false});
84
+
85
+ final String id;
86
+ final String text;
87
+ final bool done;
88
+
89
+ factory ActionItem.fromJson(Map<String, dynamic> json) => ActionItem(
90
+ id: (json['id'] as String?) ?? '',
91
+ text: (json['text'] as String?) ?? '',
92
+ done: (json['done'] as bool?) ?? false,
93
+ );
94
+
95
+ Map<String, dynamic> toJson() => {'id': id, 'text': text, 'done': done};
96
+ }
97
+
98
+ /// Per-card action list (docs/13). `followed` flips true when the user opts the
99
+ /// card into the Actions hub; until then the list is inert.
100
+ class ActionItems {
101
+ const ActionItems({this.followed = false, this.items = const []});
102
+
103
+ final bool followed;
104
+ final List<ActionItem> items;
105
+
106
+ bool get isPresent => items.isNotEmpty;
107
+
108
+ factory ActionItems.fromJson(Map<String, dynamic> json) => ActionItems(
109
+ followed: (json['followed'] as bool?) ?? false,
110
+ items: ((json['items'] as List?) ?? const [])
111
+ .whereType<Map<String, dynamic>>()
112
+ .map(ActionItem.fromJson)
113
+ .toList(),
114
+ );
115
+
116
+ Map<String, dynamic> toJson() =>
117
+ {'followed': followed, 'items': items.map((e) => e.toJson()).toList()};
118
+ }
119
+
120
  class Media {
121
  const Media({this.thumbnail, this.keyframes = const []});
122
 
 
173
  required this.source,
174
  this.base = const Base(),
175
  this.primaryAction = const PrimaryAction(),
176
+ this.actionItems = const ActionItems(),
177
  this.blocks = const [],
178
  this.media = const Media(),
179
  this.meta = const Meta(),
 
187
  final Source source;
188
  final Base base;
189
  final PrimaryAction primaryAction;
190
+ final ActionItems actionItems;
191
  final List<Block> blocks;
192
  final Media media;
193
  final Meta meta;
 
220
  primaryAction: PrimaryAction.fromJson(
221
  (json['primary_action'] as Map<String, dynamic>?) ?? const {},
222
  ),
223
+ actionItems: ActionItems.fromJson(
224
+ (json['action_items'] as Map<String, dynamic>?) ?? const {},
225
+ ),
226
  blocks: rawBlocks.map(Block.fromJson).toList(),
227
  media: Media.fromJson((json['media'] as Map<String, dynamic>?) ?? const {}),
228
  meta: Meta.fromJson((json['meta'] as Map<String, dynamic>?) ?? const {}),
 
232
 
233
  Card copyWith({
234
  CardState? state,
235
+ ActionItems? actionItems,
236
  List<Block>? blocks,
237
  List<Map<String, dynamic>>? rawBlocks,
238
  }) =>
 
244
  source: source,
245
  base: base,
246
  primaryAction: primaryAction,
247
+ actionItems: actionItems ?? this.actionItems,
248
  blocks: blocks ?? this.blocks,
249
  media: media,
250
  meta: meta,
app/lib/domain/models/collection.dart DELETED
@@ -1,51 +0,0 @@
1
- /// A user-created collection: a named group of cards (docs/09). Mirrors the
2
- /// backend contract (backend models/collection.py). Membership is by card id;
3
- /// the cards themselves are unchanged, so this needs no block-schema change.
4
- library;
5
-
6
- import 'card.dart';
7
-
8
- class Collection {
9
- const Collection({
10
- required this.id,
11
- required this.name,
12
- this.cardIds = const [],
13
- this.createdAt,
14
- });
15
-
16
- final String id;
17
- final String name;
18
- final List<String> cardIds;
19
- final DateTime? createdAt;
20
-
21
- int get count => cardIds.length;
22
-
23
- factory Collection.fromJson(Map<String, dynamic> json) => Collection(
24
- id: (json['id'] as String?) ?? '',
25
- name: (json['name'] as String?) ?? '',
26
- cardIds: (json['card_ids'] as List?)
27
- ?.map((e) => e.toString())
28
- .toList() ??
29
- const [],
30
- createdAt: DateTime.tryParse((json['created_at'] as String?) ?? ''),
31
- );
32
- }
33
-
34
- /// A collection plus its resolved member cards (the detail endpoint payload).
35
- class CollectionDetail {
36
- const CollectionDetail({required this.collection, this.cards = const []});
37
-
38
- final Collection collection;
39
- final List<Card> cards;
40
-
41
- factory CollectionDetail.fromJson(Map<String, dynamic> json) =>
42
- CollectionDetail(
43
- collection: Collection.fromJson(
44
- (json['collection'] as Map<String, dynamic>?) ?? const {},
45
- ),
46
- cards: ((json['cards'] as List?) ?? const [])
47
- .whereType<Map<String, dynamic>>()
48
- .map(Card.fromJson)
49
- .toList(),
50
- );
51
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/lib/ui/core/home_shell.dart CHANGED
@@ -5,8 +5,8 @@ library;
5
 
6
  import 'package:flutter/material.dart';
7
 
 
8
  import '../features/catalog/views/catalog_screen.dart';
9
- import '../features/collections/views/collections_screen.dart';
10
  import '../features/graph/views/graph_screen.dart';
11
  import '../features/library/views/library_screen.dart';
12
 
@@ -27,8 +27,8 @@ class _HomeShellState extends State<HomeShell> {
27
  index: _index,
28
  children: const [
29
  LibraryScreen(),
 
30
  GraphScreen(),
31
- CollectionsScreen(),
32
  CatalogScreen(),
33
  ],
34
  ),
@@ -41,16 +41,16 @@ class _HomeShellState extends State<HomeShell> {
41
  selectedIcon: Icon(Icons.video_library_rounded),
42
  label: 'Library',
43
  ),
 
 
 
 
 
44
  NavigationDestination(
45
  icon: Icon(Icons.hub_outlined),
46
  selectedIcon: Icon(Icons.hub_rounded),
47
  label: 'Graph',
48
  ),
49
- NavigationDestination(
50
- icon: Icon(Icons.folder_outlined),
51
- selectedIcon: Icon(Icons.folder_rounded),
52
- label: 'Collections',
53
- ),
54
  NavigationDestination(
55
  icon: Icon(Icons.auto_stories_outlined),
56
  selectedIcon: Icon(Icons.auto_stories_rounded),
 
5
 
6
  import 'package:flutter/material.dart';
7
 
8
+ import '../features/actions/views/actions_screen.dart';
9
  import '../features/catalog/views/catalog_screen.dart';
 
10
  import '../features/graph/views/graph_screen.dart';
11
  import '../features/library/views/library_screen.dart';
12
 
 
27
  index: _index,
28
  children: const [
29
  LibraryScreen(),
30
+ ActionsScreen(),
31
  GraphScreen(),
 
32
  CatalogScreen(),
33
  ],
34
  ),
 
41
  selectedIcon: Icon(Icons.video_library_rounded),
42
  label: 'Library',
43
  ),
44
+ NavigationDestination(
45
+ icon: Icon(Icons.checklist_outlined),
46
+ selectedIcon: Icon(Icons.checklist_rounded),
47
+ label: 'Actions',
48
+ ),
49
  NavigationDestination(
50
  icon: Icon(Icons.hub_outlined),
51
  selectedIcon: Icon(Icons.hub_rounded),
52
  label: 'Graph',
53
  ),
 
 
 
 
 
54
  NavigationDestination(
55
  icon: Icon(Icons.auto_stories_outlined),
56
  selectedIcon: Icon(Icons.auto_stories_rounded),
app/lib/ui/features/actions/view_models/actions_view_model.dart ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /// Actions hub state (MVVM, docs/13). Loads every card the user has *followed*
2
+ /// the actions of, flattens their to-dos grouped by source reel, and toggles
3
+ /// done state (optimistic + PATCH). The hub is a read-across-cards view; the
4
+ /// per-card list itself is owned by the card.
5
+ library;
6
+
7
+ import 'package:flutter/foundation.dart';
8
+
9
+ import '../../../../data/repositories/card_repository.dart';
10
+ import '../../../../domain/models/card.dart';
11
+
12
+ enum ActionsStatus { idle, loading, ready, error, empty }
13
+
14
+ /// One reel's followed to-dos, for a sectioned display.
15
+ class ActionGroup {
16
+ const ActionGroup({required this.card, required this.items});
17
+ final Card card;
18
+ final List<ActionItem> items;
19
+
20
+ int get pending => items.where((i) => !i.done).length;
21
+ bool get allDone => items.isNotEmpty && pending == 0;
22
+ }
23
+
24
+ class ActionsViewModel extends ChangeNotifier {
25
+ ActionsViewModel({required CardRepository repository})
26
+ : _repository = repository;
27
+
28
+ final CardRepository _repository;
29
+
30
+ ActionsStatus _status = ActionsStatus.idle;
31
+ ActionsStatus get status => _status;
32
+
33
+ String? _error;
34
+ String? get error => _error;
35
+
36
+ List<ActionGroup> _groups = const [];
37
+ List<ActionGroup> get groups => _groups;
38
+
39
+ /// Total to-dos still open across every followed reel — drives a nav badge.
40
+ int get pendingCount =>
41
+ _groups.fold(0, (sum, g) => sum + g.pending);
42
+
43
+ Future<void> load({bool showSpinner = true}) async {
44
+ if (showSpinner) {
45
+ _status = ActionsStatus.loading;
46
+ notifyListeners();
47
+ }
48
+ try {
49
+ final cards = await _repository.list();
50
+ final groups = <ActionGroup>[
51
+ for (final c in cards)
52
+ if (c.actionItems.followed && c.actionItems.items.isNotEmpty)
53
+ ActionGroup(card: c, items: c.actionItems.items),
54
+ ];
55
+ _groups = groups;
56
+ _status = groups.isEmpty ? ActionsStatus.empty : ActionsStatus.ready;
57
+ _error = null;
58
+ } catch (e) {
59
+ _error = e.toString();
60
+ _status = ActionsStatus.error;
61
+ }
62
+ notifyListeners();
63
+ }
64
+
65
+ /// Tick a to-do off (or back on). Optimistic; reverts the group on failure.
66
+ Future<void> toggle(String cardId, String itemId, bool done) async {
67
+ final idx = _groups.indexWhere((g) => g.card.cardId == cardId);
68
+ if (idx < 0) return;
69
+ final before = _groups[idx];
70
+
71
+ final updatedItems = [
72
+ for (final it in before.items)
73
+ it.id == itemId ? ActionItem(id: it.id, text: it.text, done: done) : it,
74
+ ];
75
+ final updatedActions =
76
+ ActionItems(followed: true, items: updatedItems);
77
+ _groups = [..._groups]
78
+ ..[idx] = ActionGroup(
79
+ card: before.card.copyWith(actionItems: updatedActions),
80
+ items: updatedItems,
81
+ );
82
+ notifyListeners();
83
+
84
+ try {
85
+ await _repository.patchActionItems(cardId, updatedActions.toJson());
86
+ } catch (_) {
87
+ _groups = [..._groups]..[idx] = before; // revert
88
+ notifyListeners();
89
+ }
90
+ }
91
+
92
+ /// Stop following a reel's actions — drops it from the hub.
93
+ Future<void> unfollow(String cardId) async {
94
+ final idx = _groups.indexWhere((g) => g.card.cardId == cardId);
95
+ if (idx < 0) return;
96
+ final before = _groups[idx];
97
+ _groups = [..._groups]..removeAt(idx);
98
+ _status = _groups.isEmpty ? ActionsStatus.empty : ActionsStatus.ready;
99
+ notifyListeners();
100
+ try {
101
+ await _repository.patchActionItems(
102
+ cardId,
103
+ ActionItems(followed: false, items: before.items).toJson(),
104
+ );
105
+ } catch (_) {
106
+ _groups = [..._groups]..insert(idx, before); // revert
107
+ _status = ActionsStatus.ready;
108
+ notifyListeners();
109
+ }
110
+ }
111
+ }
app/lib/ui/features/actions/views/actions_screen.dart ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /// The Actions hub (docs/13): every to-do you've followed off a reel, grouped by
2
+ /// its source card, split into things still to do and things done. Tick items off
3
+ /// here or jump back to the card. Cards you haven't followed never appear.
4
+ library;
5
+
6
+ import 'package:cached_network_image/cached_network_image.dart';
7
+ import 'package:flutter/material.dart';
8
+ import 'package:provider/provider.dart';
9
+
10
+ import '../../../../data/repositories/card_repository.dart';
11
+ import '../../../core/content_accent.dart';
12
+ import '../../../core/theme.dart';
13
+ import '../../reader/views/reader_screen.dart';
14
+ import '../view_models/actions_view_model.dart';
15
+
16
+ class ActionsScreen extends StatelessWidget {
17
+ const ActionsScreen({super.key});
18
+
19
+ @override
20
+ Widget build(BuildContext context) {
21
+ return ChangeNotifierProvider(
22
+ create: (ctx) =>
23
+ ActionsViewModel(repository: ctx.read<CardRepository>())..load(),
24
+ child: const _ActionsView(),
25
+ );
26
+ }
27
+ }
28
+
29
+ class _ActionsView extends StatelessWidget {
30
+ const _ActionsView();
31
+
32
+ @override
33
+ Widget build(BuildContext context) {
34
+ final vm = context.watch<ActionsViewModel>();
35
+ return Scaffold(
36
+ appBar: AppBar(
37
+ title: const Text('Actions'),
38
+ actions: [
39
+ if (vm.pendingCount > 0)
40
+ Padding(
41
+ padding: const EdgeInsets.only(right: 16),
42
+ child: Center(
43
+ child: Text(
44
+ '${vm.pendingCount} to do',
45
+ style: Theme.of(context).textTheme.labelLarge?.copyWith(
46
+ color: Theme.of(context).colorScheme.primary,
47
+ fontWeight: FontWeight.w700,
48
+ ),
49
+ ),
50
+ ),
51
+ ),
52
+ ],
53
+ ),
54
+ body: RefreshIndicator(
55
+ onRefresh: () => vm.load(showSpinner: false),
56
+ child: switch (vm.status) {
57
+ ActionsStatus.loading || ActionsStatus.idle =>
58
+ const Center(child: CircularProgressIndicator()),
59
+ ActionsStatus.error => _Message(
60
+ icon: Icons.error_outline_rounded,
61
+ text: "Couldn't load your actions",
62
+ onRetry: vm.load,
63
+ ),
64
+ ActionsStatus.empty => const _Message(
65
+ icon: Icons.checklist_rounded,
66
+ text: 'No actions yet.\nOpen a card and tap “Follow these actions”.',
67
+ ),
68
+ ActionsStatus.ready => ListView.builder(
69
+ padding: const EdgeInsets.fromLTRB(
70
+ Insets.page, 12, Insets.page, 32),
71
+ itemCount: vm.groups.length,
72
+ itemBuilder: (ctx, i) => _GroupCard(group: vm.groups[i]),
73
+ ),
74
+ },
75
+ ),
76
+ );
77
+ }
78
+ }
79
+
80
+ class _GroupCard extends StatelessWidget {
81
+ const _GroupCard({required this.group});
82
+ final ActionGroup group;
83
+
84
+ @override
85
+ Widget build(BuildContext context) {
86
+ final theme = Theme.of(context);
87
+ final vm = context.read<ActionsViewModel>();
88
+ final card = group.card;
89
+ final accent = ContentAccent.of(card.base.contentType);
90
+ final pending = group.items.where((i) => !i.done).toList();
91
+ final done = group.items.where((i) => i.done).toList();
92
+
93
+ return Container(
94
+ margin: const EdgeInsets.only(bottom: 16),
95
+ decoration: BoxDecoration(
96
+ color: theme.colorScheme.surfaceContainerLow,
97
+ borderRadius: BorderRadius.circular(Insets.radius),
98
+ ),
99
+ clipBehavior: Clip.antiAlias,
100
+ child: Column(
101
+ crossAxisAlignment: CrossAxisAlignment.start,
102
+ children: [
103
+ // Header — tap to open the card.
104
+ InkWell(
105
+ onTap: () => Navigator.of(context).push(
106
+ MaterialPageRoute(
107
+ builder: (_) => ReaderScreen(cardId: card.cardId),
108
+ ),
109
+ ),
110
+ child: Padding(
111
+ padding: const EdgeInsets.all(12),
112
+ child: Row(
113
+ children: [
114
+ _Thumb(url: card.thumbnail, accent: accent),
115
+ const SizedBox(width: 12),
116
+ Expanded(
117
+ child: Column(
118
+ crossAxisAlignment: CrossAxisAlignment.start,
119
+ children: [
120
+ Text(
121
+ card.base.oneLiner.isEmpty
122
+ ? 'Saved card'
123
+ : card.base.oneLiner,
124
+ maxLines: 2,
125
+ overflow: TextOverflow.ellipsis,
126
+ style: theme.textTheme.titleSmall
127
+ ?.copyWith(fontWeight: FontWeight.w700),
128
+ ),
129
+ const SizedBox(height: 2),
130
+ Text(
131
+ group.allDone
132
+ ? 'All done'
133
+ : '${group.pending} to do',
134
+ style: theme.textTheme.bodySmall?.copyWith(
135
+ color: group.allDone
136
+ ? accent.color
137
+ : theme.colorScheme.onSurfaceVariant,
138
+ ),
139
+ ),
140
+ ],
141
+ ),
142
+ ),
143
+ PopupMenuButton<String>(
144
+ onSelected: (_) => vm.unfollow(card.cardId),
145
+ itemBuilder: (_) => const [
146
+ PopupMenuItem(
147
+ value: 'unfollow',
148
+ child: Text('Stop following'),
149
+ ),
150
+ ],
151
+ ),
152
+ ],
153
+ ),
154
+ ),
155
+ ),
156
+ const Divider(height: 1),
157
+ Padding(
158
+ padding: const EdgeInsets.fromLTRB(12, 4, 12, 12),
159
+ child: Column(
160
+ children: [
161
+ for (final item in pending)
162
+ _ActionRow(
163
+ text: item.text,
164
+ done: false,
165
+ accent: accent,
166
+ onToggle: () => vm.toggle(card.cardId, item.id, true),
167
+ ),
168
+ for (final item in done)
169
+ _ActionRow(
170
+ text: item.text,
171
+ done: true,
172
+ accent: accent,
173
+ onToggle: () => vm.toggle(card.cardId, item.id, false),
174
+ ),
175
+ ],
176
+ ),
177
+ ),
178
+ ],
179
+ ),
180
+ );
181
+ }
182
+ }
183
+
184
+ class _ActionRow extends StatelessWidget {
185
+ const _ActionRow({
186
+ required this.text,
187
+ required this.done,
188
+ required this.accent,
189
+ required this.onToggle,
190
+ });
191
+ final String text;
192
+ final bool done;
193
+ final ContentAccent accent;
194
+ final VoidCallback onToggle;
195
+
196
+ @override
197
+ Widget build(BuildContext context) {
198
+ final theme = Theme.of(context);
199
+ return InkWell(
200
+ onTap: onToggle,
201
+ borderRadius: BorderRadius.circular(8),
202
+ child: Padding(
203
+ padding: const EdgeInsets.symmetric(vertical: 6),
204
+ child: Row(
205
+ crossAxisAlignment: CrossAxisAlignment.start,
206
+ children: [
207
+ Icon(
208
+ done
209
+ ? Icons.check_box_rounded
210
+ : Icons.check_box_outline_blank_rounded,
211
+ size: 22,
212
+ color: done ? accent.color : theme.colorScheme.onSurfaceVariant,
213
+ ),
214
+ const SizedBox(width: 10),
215
+ Expanded(
216
+ child: Text(
217
+ text,
218
+ style: theme.textTheme.bodyMedium?.copyWith(
219
+ decoration: done ? TextDecoration.lineThrough : null,
220
+ color: done ? theme.colorScheme.onSurfaceVariant : null,
221
+ ),
222
+ ),
223
+ ),
224
+ ],
225
+ ),
226
+ ),
227
+ );
228
+ }
229
+ }
230
+
231
+ class _Thumb extends StatelessWidget {
232
+ const _Thumb({required this.url, required this.accent});
233
+ final String? url;
234
+ final ContentAccent accent;
235
+
236
+ @override
237
+ Widget build(BuildContext context) {
238
+ final placeholder = Container(
239
+ color: accent.color.withValues(alpha: 0.14),
240
+ child: Icon(accent.icon, color: accent.color, size: 22),
241
+ );
242
+ return ClipRRect(
243
+ borderRadius: BorderRadius.circular(10),
244
+ child: SizedBox(
245
+ width: 52,
246
+ height: 52,
247
+ child: (url == null || url!.isEmpty)
248
+ ? placeholder
249
+ : CachedNetworkImage(
250
+ imageUrl: url!,
251
+ fit: BoxFit.cover,
252
+ placeholder: (c, _) => placeholder,
253
+ errorWidget: (c, _, __) => placeholder,
254
+ ),
255
+ ),
256
+ );
257
+ }
258
+ }
259
+
260
+ class _Message extends StatelessWidget {
261
+ const _Message({required this.icon, required this.text, this.onRetry});
262
+ final IconData icon;
263
+ final String text;
264
+ final VoidCallback? onRetry;
265
+
266
+ @override
267
+ Widget build(BuildContext context) {
268
+ final theme = Theme.of(context);
269
+ // ListView so RefreshIndicator still works on the empty/error states.
270
+ return ListView(
271
+ children: [
272
+ SizedBox(height: MediaQuery.of(context).size.height * 0.28),
273
+ Icon(icon, size: 48, color: theme.colorScheme.onSurfaceVariant),
274
+ const SizedBox(height: 12),
275
+ Text(
276
+ text,
277
+ textAlign: TextAlign.center,
278
+ style: theme.textTheme.bodyLarge
279
+ ?.copyWith(color: theme.colorScheme.onSurfaceVariant),
280
+ ),
281
+ if (onRetry != null) ...[
282
+ const SizedBox(height: 16),
283
+ Center(
284
+ child: FilledButton(onPressed: onRetry, child: const Text('Retry')),
285
+ ),
286
+ ],
287
+ ],
288
+ );
289
+ }
290
+ }
app/lib/ui/features/collections/view_models/collections_view_model.dart DELETED
@@ -1,65 +0,0 @@
1
- /// Collections list state (MVVM, docs/09): the user's named groups of cards.
2
- /// Loads from the repository, supports create + delete. Detail (member cards)
3
- /// is fetched on demand by the detail screen.
4
- library;
5
-
6
- import 'package:flutter/foundation.dart';
7
-
8
- import '../../../../data/repositories/card_repository.dart';
9
- import '../../../../domain/models/collection.dart';
10
-
11
- enum CollectionsStatus { idle, loading, ready, error, empty }
12
-
13
- class CollectionsViewModel extends ChangeNotifier {
14
- CollectionsViewModel({required CardRepository repository})
15
- : _repository = repository;
16
-
17
- final CardRepository _repository;
18
-
19
- CollectionsStatus _status = CollectionsStatus.idle;
20
- CollectionsStatus get status => _status;
21
-
22
- List<Collection> _collections = const [];
23
- List<Collection> get collections => List.unmodifiable(_collections);
24
-
25
- String? _error;
26
- String? get error => _error;
27
-
28
- Future<void> load({bool showSpinner = true}) async {
29
- if (showSpinner) {
30
- _status = CollectionsStatus.loading;
31
- notifyListeners();
32
- }
33
- try {
34
- final list = await _repository.listCollections();
35
- _collections = list;
36
- _status =
37
- list.isEmpty ? CollectionsStatus.empty : CollectionsStatus.ready;
38
- _error = null;
39
- } catch (e) {
40
- _error = '$e';
41
- _status = CollectionsStatus.error;
42
- }
43
- notifyListeners();
44
- }
45
-
46
- Future<void> refresh() => load(showSpinner: false);
47
-
48
- Future<void> create(String name) async {
49
- final trimmed = name.trim();
50
- if (trimmed.isEmpty) return;
51
- await _repository.createCollection(trimmed);
52
- await load(showSpinner: false);
53
- }
54
-
55
- Future<void> delete(String id) async {
56
- _collections = _collections.where((c) => c.id != id).toList();
57
- if (_collections.isEmpty) _status = CollectionsStatus.empty;
58
- notifyListeners();
59
- try {
60
- await _repository.deleteCollection(id);
61
- } catch (_) {
62
- await load(showSpinner: false);
63
- }
64
- }
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/lib/ui/features/collections/views/collections_screen.dart DELETED
@@ -1,292 +0,0 @@
1
- /// Collections: the user's named groups of cards (docs/09). A list of
2
- /// collections; tapping one opens a grid of its member cards. Creating a
3
- /// collection is a single name prompt; cards are added from the reader.
4
- library;
5
-
6
- import 'package:flutter/material.dart';
7
- import 'package:provider/provider.dart';
8
-
9
- import '../../../../data/repositories/card_repository.dart';
10
- import '../../../../domain/models/collection.dart';
11
- import '../../../core/theme.dart';
12
- import '../../library/views/card_tile.dart';
13
- import '../../reader/views/reader_screen.dart';
14
- import '../view_models/collections_view_model.dart';
15
-
16
- class CollectionsScreen extends StatelessWidget {
17
- const CollectionsScreen({super.key});
18
-
19
- @override
20
- Widget build(BuildContext context) {
21
- return ChangeNotifierProvider(
22
- create: (ctx) =>
23
- CollectionsViewModel(repository: ctx.read<CardRepository>())..load(),
24
- child: const _CollectionsView(),
25
- );
26
- }
27
- }
28
-
29
- class _CollectionsView extends StatelessWidget {
30
- const _CollectionsView();
31
-
32
- @override
33
- Widget build(BuildContext context) {
34
- final vm = context.watch<CollectionsViewModel>();
35
- return Scaffold(
36
- appBar: AppBar(title: const Text('Collections')),
37
- floatingActionButton: FloatingActionButton.extended(
38
- onPressed: () => _promptCreate(context, vm),
39
- icon: const Icon(Icons.create_new_folder_outlined),
40
- label: const Text('New'),
41
- ),
42
- body: RefreshIndicator(
43
- onRefresh: vm.refresh,
44
- child: _body(context, vm),
45
- ),
46
- );
47
- }
48
-
49
- Widget _body(BuildContext context, CollectionsViewModel vm) {
50
- switch (vm.status) {
51
- case CollectionsStatus.loading:
52
- return const Center(child: CircularProgressIndicator());
53
- case CollectionsStatus.error:
54
- return _Message(
55
- icon: Icons.wifi_off_rounded,
56
- title: "Can't reach the backend",
57
- subtitle: vm.error ?? '',
58
- action: FilledButton(onPressed: vm.load, child: const Text('Retry')),
59
- );
60
- case CollectionsStatus.empty:
61
- return const _Message(
62
- icon: Icons.folder_open_rounded,
63
- title: 'No collections yet',
64
- subtitle: 'Group related cards — tap New, then add cards from a card.',
65
- );
66
- case CollectionsStatus.idle:
67
- case CollectionsStatus.ready:
68
- final items = vm.collections;
69
- return ListView.separated(
70
- physics: const AlwaysScrollableScrollPhysics(),
71
- padding: const EdgeInsets.fromLTRB(Insets.page, 8, Insets.page, 96),
72
- itemCount: items.length,
73
- separatorBuilder: (_, __) => const Divider(height: 1),
74
- itemBuilder: (ctx, i) => _CollectionRow(collection: items[i], vm: vm),
75
- );
76
- }
77
- }
78
-
79
- Future<void> _promptCreate(
80
- BuildContext context, CollectionsViewModel vm) async {
81
- final controller = TextEditingController();
82
- final name = await showDialog<String>(
83
- context: context,
84
- builder: (ctx) => AlertDialog(
85
- title: const Text('New collection'),
86
- content: TextField(
87
- controller: controller,
88
- autofocus: true,
89
- decoration: const InputDecoration(hintText: 'e.g. Recipes to try'),
90
- onSubmitted: (v) => Navigator.pop(ctx, v),
91
- ),
92
- actions: [
93
- TextButton(
94
- onPressed: () => Navigator.pop(ctx),
95
- child: const Text('Cancel'),
96
- ),
97
- FilledButton(
98
- onPressed: () => Navigator.pop(ctx, controller.text),
99
- child: const Text('Create'),
100
- ),
101
- ],
102
- ),
103
- );
104
- if (name != null && name.trim().isNotEmpty) await vm.create(name);
105
- }
106
- }
107
-
108
- class _CollectionRow extends StatelessWidget {
109
- const _CollectionRow({required this.collection, required this.vm});
110
- final Collection collection;
111
- final CollectionsViewModel vm;
112
-
113
- @override
114
- Widget build(BuildContext context) {
115
- return ListTile(
116
- leading: const Icon(Icons.folder_rounded),
117
- title: Text(collection.name),
118
- subtitle: Text('${collection.count} '
119
- '${collection.count == 1 ? 'card' : 'cards'}'),
120
- trailing: IconButton(
121
- icon: const Icon(Icons.delete_outline_rounded),
122
- onPressed: () => _confirmDelete(context),
123
- ),
124
- onTap: () => Navigator.of(context).push(
125
- MaterialPageRoute(
126
- builder: (_) => CollectionDetailScreen(
127
- collectionId: collection.id,
128
- name: collection.name,
129
- ),
130
- ),
131
- ),
132
- );
133
- }
134
-
135
- Future<void> _confirmDelete(BuildContext context) async {
136
- final ok = await showDialog<bool>(
137
- context: context,
138
- builder: (ctx) => AlertDialog(
139
- title: const Text('Delete collection?'),
140
- content: Text('“${collection.name}” will be removed. '
141
- 'The cards themselves are kept.'),
142
- actions: [
143
- TextButton(
144
- onPressed: () => Navigator.pop(ctx, false),
145
- child: const Text('Cancel'),
146
- ),
147
- FilledButton(
148
- onPressed: () => Navigator.pop(ctx, true),
149
- child: const Text('Delete'),
150
- ),
151
- ],
152
- ),
153
- );
154
- if (ok == true) vm.delete(collection.id);
155
- }
156
- }
157
-
158
- /// A collection's member cards, fetched on open. Reuses the library [CardTile].
159
- class CollectionDetailScreen extends StatefulWidget {
160
- const CollectionDetailScreen({
161
- super.key,
162
- required this.collectionId,
163
- required this.name,
164
- });
165
- final String collectionId;
166
- final String name;
167
-
168
- @override
169
- State<CollectionDetailScreen> createState() => _CollectionDetailScreenState();
170
- }
171
-
172
- class _CollectionDetailScreenState extends State<CollectionDetailScreen> {
173
- CollectionDetail? _detail;
174
- String? _error;
175
-
176
- @override
177
- void initState() {
178
- super.initState();
179
- _load();
180
- }
181
-
182
- Future<void> _load() async {
183
- try {
184
- final detail =
185
- await context.read<CardRepository>().getCollection(widget.collectionId);
186
- if (mounted) setState(() => _detail = detail);
187
- } catch (e) {
188
- if (mounted) setState(() => _error = '$e');
189
- }
190
- }
191
-
192
- Future<void> _remove(String cardId) async {
193
- await context
194
- .read<CardRepository>()
195
- .removeCardFromCollection(widget.collectionId, cardId);
196
- await _load();
197
- }
198
-
199
- @override
200
- Widget build(BuildContext context) {
201
- final api = context.read<CardRepository>().api;
202
- final detail = _detail;
203
- return Scaffold(
204
- appBar: AppBar(title: Text(widget.name)),
205
- body: _error != null
206
- ? Center(child: Text("Couldn't load this collection"))
207
- : detail == null
208
- ? const Center(child: CircularProgressIndicator())
209
- : detail.cards.isEmpty
210
- ? const Center(
211
- child: Padding(
212
- padding: EdgeInsets.all(32),
213
- child: Text(
214
- 'No cards yet. Open a card and use "Add to collection".',
215
- textAlign: TextAlign.center,
216
- ),
217
- ),
218
- )
219
- : GridView.builder(
220
- padding: const EdgeInsets.fromLTRB(
221
- Insets.page, 12, Insets.page, 24),
222
- gridDelegate:
223
- const SliverGridDelegateWithFixedCrossAxisCount(
224
- crossAxisCount: 2,
225
- mainAxisSpacing: 14,
226
- crossAxisSpacing: 14,
227
- childAspectRatio: 0.72,
228
- ),
229
- itemCount: detail.cards.length,
230
- itemBuilder: (ctx, i) {
231
- final card = detail.cards[i];
232
- return CardTile(
233
- card: card,
234
- api: api,
235
- confirmTitle: 'Remove from collection?',
236
- confirmBody:
237
- 'The card stays in your library; it just leaves '
238
- 'this collection.',
239
- confirmAction: 'Remove',
240
- onTap: () => Navigator.of(ctx).push(
241
- MaterialPageRoute(
242
- builder: (_) =>
243
- ReaderScreen(cardId: card.cardId),
244
- ),
245
- ),
246
- onDelete: () => _remove(card.cardId),
247
- );
248
- },
249
- ),
250
- );
251
- }
252
- }
253
-
254
- class _Message extends StatelessWidget {
255
- const _Message({
256
- required this.icon,
257
- required this.title,
258
- required this.subtitle,
259
- this.action,
260
- });
261
- final IconData icon;
262
- final String title;
263
- final String subtitle;
264
- final Widget? action;
265
-
266
- @override
267
- Widget build(BuildContext context) {
268
- final theme = Theme.of(context);
269
- return ListView(
270
- physics: const AlwaysScrollableScrollPhysics(),
271
- children: [
272
- SizedBox(height: MediaQuery.of(context).size.height * 0.22),
273
- Icon(icon, size: 52, color: theme.colorScheme.outline),
274
- const SizedBox(height: 16),
275
- Text(title,
276
- textAlign: TextAlign.center, style: theme.textTheme.titleLarge),
277
- const SizedBox(height: 8),
278
- Padding(
279
- padding: const EdgeInsets.symmetric(horizontal: 48),
280
- child: Text(subtitle,
281
- textAlign: TextAlign.center,
282
- style: theme.textTheme.bodyMedium
283
- ?.copyWith(color: theme.colorScheme.onSurfaceVariant)),
284
- ),
285
- if (action != null) ...[
286
- const SizedBox(height: 20),
287
- Center(child: action!),
288
- ],
289
- ],
290
- );
291
- }
292
- }