Action_items
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- app/android/app/src/main/AndroidManifest.xml +1 -1
- app/ios/.gitignore +0 -34
- app/ios/Flutter/AppFrameworkInfo.plist +0 -24
- app/ios/Flutter/Debug.xcconfig +0 -1
- app/ios/Flutter/Release.xcconfig +0 -1
- app/ios/Runner.xcodeproj/project.pbxproj +0 -623
- app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +0 -8
- app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +0 -101
- app/ios/Runner.xcworkspace/contents.xcworkspacedata +0 -7
- app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +0 -8
- app/ios/Runner/AppDelegate.swift +0 -16
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -122
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png +0 -0
- app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png +0 -0
- app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +0 -23
- app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
- app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
- app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
- app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +0 -5
- app/ios/Runner/Base.lproj/LaunchScreen.storyboard +0 -37
- app/ios/Runner/Base.lproj/Main.storyboard +0 -26
- app/ios/Runner/Info.plist +0 -72
- app/ios/Runner/Runner-Bridging-Header.h +0 -1
- app/ios/Runner/SceneDelegate.swift +0 -6
- app/ios/RunnerTests/RunnerTests.swift +0 -12
- app/lib/data/repositories/card_repository.dart +9 -16
- app/lib/data/services/api_client.dart +13 -42
- app/lib/domain/models/card.dart +47 -1
- app/lib/domain/models/collection.dart +0 -51
- app/lib/ui/core/home_shell.dart +7 -7
- app/lib/ui/features/actions/view_models/actions_view_model.dart +111 -0
- app/lib/ui/features/actions/views/actions_screen.dart +290 -0
- app/lib/ui/features/collections/view_models/collections_view_model.dart +0 -65
- 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 |
-
|
| 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 |
|
| 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 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|