diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 6b4c0f7..beffb28 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 8.0
+ 10.0
diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig
index 592ceee..ec97fc6 100644
--- a/ios/Flutter/Debug.xcconfig
+++ b/ios/Flutter/Debug.xcconfig
@@ -1 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig
index 592ceee..c4855bf 100644
--- a/ios/Flutter/Release.xcconfig
+++ b/ios/Flutter/Release.xcconfig
@@ -1 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
diff --git a/ios/Podfile b/ios/Podfile
new file mode 100644
index 0000000..9411102
--- /dev/null
+++ b/ios/Podfile
@@ -0,0 +1,41 @@
+# Uncomment this line to define a global platform for your project
+platform :ios, '10.0'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_ios_podfile_setup
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_ios_build_settings(target)
+ end
+end
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index e70649f..547d92c 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -3,22 +3,32 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
- 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
- 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
- 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
- 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
+ C54507543282E1DF271A8F5B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5377A98202E56341E37BFF29 /* Pods_Runner.framework */; };
+ D7A88A05286F45FA00F1E31E /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A88A04286F45FA00F1E31E /* ShareViewController.swift */; };
+ D7A88A08286F45FA00F1E31E /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D7A88A06286F45FA00F1E31E /* MainInterface.storyboard */; };
+ D7A88A0C286F45FA00F1E31E /* Share Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D7A88A02286F45FA00F1E31E /* Share Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */
+/* Begin PBXContainerItemProxy section */
+ D7A88A0A286F45FA00F1E31E /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 97C146E61CF9000F007C117D /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D7A88A01286F45FA00F1E31E;
+ remoteInfo = "Share Extension";
+ };
+/* End PBXContainerItemProxy section */
+
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
@@ -26,30 +36,47 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
- 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
- 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
+ D7A88A0D286F45FA00F1E31E /* Embed App Extensions */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 13;
+ files = (
+ D7A88A0C286F45FA00F1E31E /* Share Extension.appex in Embed App Extensions */,
+ );
+ name = "Embed App Extensions";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
+ 344B6DBED37670E7A1194009 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
- 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
+ 5377A98202E56341E37BFF29 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 6CC20B5D3DC60A419EEDBDC6 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
- 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ D357581AB9B8244FF83749DC /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
+ D7A88A02286F45FA00F1E31E /* Share Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Share Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
+ D7A88A04286F45FA00F1E31E /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; };
+ D7A88A07286F45FA00F1E31E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = ""; };
+ D7A88A09286F45FA00F1E31E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ D7A88A122873463B00F1E31E /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; };
+ D7A88A132873467200F1E31E /* Share Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Share Extension.entitlements"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -57,20 +84,32 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
- 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
+ C54507543282E1DF271A8F5B /* Pods_Runner.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D7A889FF286F45FA00F1E31E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 1862DC44F2C4F7D262ABA150 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 5377A98202E56341E37BFF29 /* Pods_Runner.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
- 3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
- 9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
@@ -83,7 +122,10 @@
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
+ D7A88A03286F45FA00F1E31E /* Share Extension */,
97C146EF1CF9000F007C117D /* Products */,
+ DFDE0D8C3E96E8AF6286EFAC /* Pods */,
+ 1862DC44F2C4F7D262ABA150 /* Frameworks */,
);
sourceTree = "";
};
@@ -91,6 +133,7 @@
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
+ D7A88A02286F45FA00F1E31E /* Share Extension.appex */,
);
name = Products;
sourceTree = "";
@@ -98,6 +141,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
+ D7A88A122873463B00F1E31E /* Runner.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
@@ -118,6 +162,27 @@
name = "Supporting Files";
sourceTree = "";
};
+ D7A88A03286F45FA00F1E31E /* Share Extension */ = {
+ isa = PBXGroup;
+ children = (
+ D7A88A132873467200F1E31E /* Share Extension.entitlements */,
+ D7A88A04286F45FA00F1E31E /* ShareViewController.swift */,
+ D7A88A06286F45FA00F1E31E /* MainInterface.storyboard */,
+ D7A88A09286F45FA00F1E31E /* Info.plist */,
+ );
+ path = "Share Extension";
+ sourceTree = "";
+ };
+ DFDE0D8C3E96E8AF6286EFAC /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ 6CC20B5D3DC60A419EEDBDC6 /* Pods-Runner.debug.xcconfig */,
+ D357581AB9B8244FF83749DC /* Pods-Runner.release.xcconfig */,
+ 344B6DBED37670E7A1194009 /* Pods-Runner.profile.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -125,35 +190,63 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
+ 3DE9C7D0B427213A632FCCD9 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ E559009415DC91CEDB724DCD /* [CP] Embed Pods Frameworks */,
+ D7A88A0D286F45FA00F1E31E /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
+ D7A88A0B286F45FA00F1E31E /* PBXTargetDependency */,
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
+ D7A88A01286F45FA00F1E31E /* Share Extension */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D7A88A11286F45FA00F1E31E /* Build configuration list for PBXNativeTarget "Share Extension" */;
+ buildPhases = (
+ D7A889FE286F45FA00F1E31E /* Sources */,
+ D7A889FF286F45FA00F1E31E /* Frameworks */,
+ D7A88A00286F45FA00F1E31E /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Share Extension";
+ productName = "Share Extension";
+ productReference = D7A88A02286F45FA00F1E31E /* Share Extension.appex */;
+ productType = "com.apple.product-type.app-extension";
+ };
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1020;
+ LastSwiftUpdateCheck = 1340;
+ LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
+ DevelopmentTeam = GNWU6RWA76;
LastSwiftMigration = 1100;
};
+ D7A88A01286F45FA00F1E31E = {
+ CreatedOnToolsVersion = 13.4.1;
+ DevelopmentTeam = GNWU6RWA76;
+ ProvisioningStyle = Automatic;
+ };
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
@@ -170,6 +263,7 @@
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
+ D7A88A01286F45FA00F1E31E /* Share Extension */,
);
};
/* End PBXProject section */
@@ -186,6 +280,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ D7A88A00286F45FA00F1E31E /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7A88A08286F45FA00F1E31E /* MainInterface.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@@ -201,7 +303,29 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
+ };
+ 3DE9C7D0B427213A632FCCD9 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
@@ -215,7 +339,49 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
+ };
+ E559009415DC91CEDB724DCD /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
+ "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
+ "${BUILT_PRODUCTS_DIR}/WeScan/WeScan.framework",
+ "${BUILT_PRODUCTS_DIR}/edge_detection/edge_detection.framework",
+ "${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework",
+ "${BUILT_PRODUCTS_DIR}/open_file/open_file.framework",
+ "${BUILT_PRODUCTS_DIR}/path_provider_ios/path_provider_ios.framework",
+ "${BUILT_PRODUCTS_DIR}/photo_manager/photo_manager.framework",
+ "${BUILT_PRODUCTS_DIR}/receive_sharing_intent/receive_sharing_intent.framework",
+ "${BUILT_PRODUCTS_DIR}/share/share.framework",
+ "${BUILT_PRODUCTS_DIR}/shared_preferences_ios/shared_preferences_ios.framework",
+ "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
+ "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework",
+ "${BUILT_PRODUCTS_DIR}/video_player_avfoundation/video_player_avfoundation.framework",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WeScan.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/edge_detection.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/open_file.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_ios.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/photo_manager.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/receive_sharing_intent.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_ios.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player_avfoundation.framework",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
@@ -229,8 +395,24 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ D7A889FE286F45FA00F1E31E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7A88A05286F45FA00F1E31E /* ShareViewController.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXSourcesBuildPhase section */
+/* Begin PBXTargetDependency section */
+ D7A88A0B286F45FA00F1E31E /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D7A88A01286F45FA00F1E31E /* Share Extension */;
+ targetProxy = D7A88A0A286F45FA00F1E31E /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
@@ -248,12 +430,19 @@
name = LaunchScreen.storyboard;
sourceTree = "";
};
+ D7A88A06286F45FA00F1E31E /* MainInterface.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ D7A88A07286F45FA00F1E31E /* Base */,
+ );
+ name = MainInterface.storyboard;
+ sourceTree = "";
+ };
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
@@ -293,7 +482,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -306,21 +495,25 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = GNWU6RWA76;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.example.paperlessApp;
+ PRODUCT_BUNDLE_IDENTIFIER = com.timmermann.paperless;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@@ -330,7 +523,6 @@
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
@@ -376,7 +568,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -386,7 +578,6 @@
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
@@ -426,7 +617,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -440,21 +631,25 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = GNWU6RWA76;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.example.paperlessApp;
+ PRODUCT_BUNDLE_IDENTIFIER = com.timmermann.paperless;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -467,21 +662,25 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = GNWU6RWA76;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.example.paperlessApp;
+ PRODUCT_BUNDLE_IDENTIFIER = com.timmermann.paperless;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@@ -489,6 +688,104 @@
};
name = Release;
};
+ D7A88A0E286F45FA00F1E31E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = GNWU6RWA76;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "Share Extension/Info.plist";
+ INFOPLIST_KEY_CFBundleDisplayName = "Share Extension";
+ INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 The Chromium Authors. All rights reserved.";
+ IPHONEOS_DEPLOYMENT_TARGET = 15.5;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
+ MARKETING_VERSION = 1.0;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.timmermann.paperless.Share-Extension";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ D7A88A0F286F45FA00F1E31E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = GNWU6RWA76;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "Share Extension/Info.plist";
+ INFOPLIST_KEY_CFBundleDisplayName = "Share Extension";
+ INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 The Chromium Authors. All rights reserved.";
+ IPHONEOS_DEPLOYMENT_TARGET = 15.5;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
+ MARKETING_VERSION = 1.0;
+ MTL_FAST_MATH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.timmermann.paperless.Share-Extension";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ D7A88A10286F45FA00F1E31E /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = GNWU6RWA76;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "Share Extension/Info.plist";
+ INFOPLIST_KEY_CFBundleDisplayName = "Share Extension";
+ INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 The Chromium Authors. All rights reserved.";
+ IPHONEOS_DEPLOYMENT_TARGET = 15.5;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
+ MARKETING_VERSION = 1.0;
+ MTL_FAST_MATH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.timmermann.paperless.Share-Extension";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Profile;
+ };
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -512,6 +809,16 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ D7A88A11286F45FA00F1E31E /* Build configuration list for PBXNativeTarget "Share Extension" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D7A88A0E286F45FA00F1E31E /* Debug */,
+ D7A88A0F286F45FA00F1E31E /* Release */,
+ D7A88A10286F45FA00F1E31E /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index 1d526a1..919434a 100644
--- a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -2,6 +2,6 @@
+ location = "self:">
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index a28140c..f3d88ac 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
-
-
-
-
+
+
-
-
+
+
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 9e78406..e1e8adb 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -2,6 +2,8 @@
+ CADisableMinimumFrameDurationOnPhone
+
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleExecutable
@@ -22,6 +24,24 @@
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLSchemes
+
+ ShareMedia
+
+
+
+
+ NSCameraUsageDescription
+ Camera access is needed to scan documents
+ NSLocalNetworkUsageDescription
+ Network access is need to contact the server
+ NSPhotoLibraryUsageDescription
+ Access photo library to upload photos from library
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements
new file mode 100644
index 0000000..e317444
--- /dev/null
+++ b/ios/Runner/Runner.entitlements
@@ -0,0 +1,10 @@
+
+
+
+
+ com.apple.security.application-groups
+
+ group.com.timmermann.paperless
+
+
+
diff --git a/ios/Share Extension/Base.lproj/MainInterface.storyboard b/ios/Share Extension/Base.lproj/MainInterface.storyboard
new file mode 100644
index 0000000..286a508
--- /dev/null
+++ b/ios/Share Extension/Base.lproj/MainInterface.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ios/Share Extension/Info.plist b/ios/Share Extension/Info.plist
new file mode 100644
index 0000000..81e809f
--- /dev/null
+++ b/ios/Share Extension/Info.plist
@@ -0,0 +1,27 @@
+
+
+
+
+ NSExtension
+
+ NSExtensionAttributes
+
+ PHSupportedMediaTypes
+
+ Image
+
+ NSExtensionActivationRule
+
+ NSExtensionActivationSupportsImageWithMaxCount
+ 20
+ NSExtensionActivationSupportsFileWithMaxCount
+ 20
+
+
+ NSExtensionMainStoryboard
+ MainInterface
+ NSExtensionPointIdentifier
+ com.apple.share-services
+
+
+
diff --git a/ios/Share Extension/Share Extension.entitlements b/ios/Share Extension/Share Extension.entitlements
new file mode 100644
index 0000000..e317444
--- /dev/null
+++ b/ios/Share Extension/Share Extension.entitlements
@@ -0,0 +1,10 @@
+
+
+
+
+ com.apple.security.application-groups
+
+ group.com.timmermann.paperless
+
+
+
diff --git a/ios/Share Extension/ShareViewController.swift b/ios/Share Extension/ShareViewController.swift
new file mode 100644
index 0000000..c55140d
--- /dev/null
+++ b/ios/Share Extension/ShareViewController.swift
@@ -0,0 +1,335 @@
+import UIKit
+import Social
+import MobileCoreServices
+import Photos
+
+class ShareViewController: SLComposeServiceViewController {
+ // TODO: IMPORTANT: This should be your host app bundle identifier
+ let hostAppBundleIdentifier = "com.timmermann.paperless"
+ let sharedKey = "ShareKey"
+ var sharedMedia: [SharedMediaFile] = []
+ var sharedText: [String] = []
+ let imageContentType = kUTTypeImage as String
+ let videoContentType = kUTTypeMovie as String
+ let textContentType = kUTTypeText as String
+ let urlContentType = kUTTypeURL as String
+ let fileURLType = kUTTypeFileURL as String;
+
+ override func isContentValid() -> Bool {
+ return true
+ }
+
+ override func viewDidLoad() {
+ super.viewDidLoad();
+ }
+
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+
+ // This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
+ if let content = extensionContext!.inputItems[0] as? NSExtensionItem {
+ if let contents = content.attachments {
+ for (index, attachment) in (contents).enumerated() {
+ if attachment.hasItemConformingToTypeIdentifier(imageContentType) {
+ handleImages(content: content, attachment: attachment, index: index)
+ } else if attachment.hasItemConformingToTypeIdentifier(textContentType) {
+ handleText(content: content, attachment: attachment, index: index)
+ } else if attachment.hasItemConformingToTypeIdentifier(fileURLType) {
+ handleFiles(content: content, attachment: attachment, index: index)
+ } else if attachment.hasItemConformingToTypeIdentifier(urlContentType) {
+ handleUrl(content: content, attachment: attachment, index: index)
+ } else if attachment.hasItemConformingToTypeIdentifier(videoContentType) {
+ handleVideos(content: content, attachment: attachment, index: index)
+ }
+ }
+ }
+ }
+ }
+
+ override func didSelectPost() {
+ print("didSelectPost");
+ }
+
+ override func configurationItems() -> [Any]! {
+ // To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
+ return []
+ }
+
+ private func handleText (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
+ attachment.loadItem(forTypeIdentifier: textContentType, options: nil) { [weak self] data, error in
+
+ if error == nil, let item = data as? String, let this = self {
+
+ this.sharedText.append(item)
+
+ // If this is the last item, save imagesData in userDefaults and redirect to host app
+ if index == (content.attachments?.count)! - 1 {
+ let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
+ userDefaults?.set(this.sharedText, forKey: this.sharedKey)
+ userDefaults?.synchronize()
+ this.redirectToHostApp(type: .text)
+ }
+
+ } else {
+ self?.dismissWithError()
+ }
+ }
+ }
+
+ private func handleUrl (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
+ attachment.loadItem(forTypeIdentifier: urlContentType, options: nil) { [weak self] data, error in
+
+ if error == nil, let item = data as? URL, let this = self {
+
+ this.sharedText.append(item.absoluteString)
+
+ // If this is the last item, save imagesData in userDefaults and redirect to host app
+ if index == (content.attachments?.count)! - 1 {
+ let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
+ userDefaults?.set(this.sharedText, forKey: this.sharedKey)
+ userDefaults?.synchronize()
+ this.redirectToHostApp(type: .text)
+ }
+
+ } else {
+ self?.dismissWithError()
+ }
+ }
+ }
+
+ private func handleImages (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
+ attachment.loadItem(forTypeIdentifier: imageContentType, options: nil) { [weak self] data, error in
+
+ if error == nil, let url = data as? URL, let this = self {
+
+ // Always copy
+ let fileName = this.getFileName(from: url, type: .image)
+ let newPath = FileManager.default
+ .containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")!
+ .appendingPathComponent(fileName)
+ let copied = this.copyFile(at: url, to: newPath)
+ if(copied) {
+ this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .image))
+ }
+
+ // If this is the last item, save imagesData in userDefaults and redirect to host app
+ if index == (content.attachments?.count)! - 1 {
+ let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
+ userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey)
+ userDefaults?.synchronize()
+ this.redirectToHostApp(type: .media)
+ }
+
+ } else {
+ self?.dismissWithError()
+ }
+ }
+ }
+
+ private func handleVideos (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
+ attachment.loadItem(forTypeIdentifier: videoContentType, options: nil) { [weak self] data, error in
+
+ if error == nil, let url = data as? URL, let this = self {
+
+ // Always copy
+ let fileName = this.getFileName(from: url, type: .video)
+ let newPath = FileManager.default
+ .containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")!
+ .appendingPathComponent(fileName)
+ let copied = this.copyFile(at: url, to: newPath)
+ if(copied) {
+ guard let sharedFile = this.getSharedMediaFile(forVideo: newPath) else {
+ return
+ }
+ this.sharedMedia.append(sharedFile)
+ }
+
+ // If this is the last item, save imagesData in userDefaults and redirect to host app
+ if index == (content.attachments?.count)! - 1 {
+ let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
+ userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey)
+ userDefaults?.synchronize()
+ this.redirectToHostApp(type: .media)
+ }
+
+ } else {
+ self?.dismissWithError()
+ }
+ }
+ }
+
+ private func handleFiles (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
+ attachment.loadItem(forTypeIdentifier: fileURLType, options: nil) { [weak self] data, error in
+
+ if error == nil, let url = data as? URL, let this = self {
+
+ // Always copy
+ let fileName = this.getFileName(from :url, type: .file)
+ let newPath = FileManager.default
+ .containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")!
+ .appendingPathComponent(fileName)
+ let copied = this.copyFile(at: url, to: newPath)
+ if (copied) {
+ this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .file))
+ }
+
+ if index == (content.attachments?.count)! - 1 {
+ let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)")
+ userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey)
+ userDefaults?.synchronize()
+ this.redirectToHostApp(type: .file)
+ }
+
+ } else {
+ self?.dismissWithError()
+ }
+ }
+ }
+
+ private func dismissWithError() {
+ print("[ERROR] Error loading data!")
+ let alert = UIAlertController(title: "Error", message: "Error loading data", preferredStyle: .alert)
+
+ let action = UIAlertAction(title: "Error", style: .cancel) { _ in
+ self.dismiss(animated: true, completion: nil)
+ }
+
+ alert.addAction(action)
+ present(alert, animated: true, completion: nil)
+ extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
+ }
+
+ private func redirectToHostApp(type: RedirectType) {
+ let url = URL(string: "ShareMedia://dataUrl=\(sharedKey)#\(type)")
+ var responder = self as UIResponder?
+ let selectorOpenURL = sel_registerName("openURL:")
+
+ while (responder != nil) {
+ if (responder?.responds(to: selectorOpenURL))! {
+ let _ = responder?.perform(selectorOpenURL, with: url)
+ }
+ responder = responder!.next
+ }
+ extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
+ }
+
+ enum RedirectType {
+ case media
+ case text
+ case file
+ }
+
+ func getExtension(from url: URL, type: SharedMediaType) -> String {
+ let parts = url.lastPathComponent.components(separatedBy: ".")
+ var ex: String? = nil
+ if (parts.count > 1) {
+ ex = parts.last
+ }
+
+ if (ex == nil) {
+ switch type {
+ case .image:
+ ex = "PNG"
+ case .video:
+ ex = "MP4"
+ case .file:
+ ex = "TXT"
+ }
+ }
+ return ex ?? "Unknown"
+ }
+
+ func getFileName(from url: URL, type: SharedMediaType) -> String {
+ var name = url.lastPathComponent
+
+ if (name.isEmpty) {
+ name = UUID().uuidString + "." + getExtension(from: url, type: type)
+ }
+
+ return name
+ }
+
+ func copyFile(at srcURL: URL, to dstURL: URL) -> Bool {
+ do {
+ if FileManager.default.fileExists(atPath: dstURL.path) {
+ try FileManager.default.removeItem(at: dstURL)
+ }
+ try FileManager.default.copyItem(at: srcURL, to: dstURL)
+ } catch (let error) {
+ print("Cannot copy item at \(srcURL) to \(dstURL): \(error)")
+ return false
+ }
+ return true
+ }
+
+ private func getSharedMediaFile(forVideo: URL) -> SharedMediaFile? {
+ let asset = AVAsset(url: forVideo)
+ let duration = (CMTimeGetSeconds(asset.duration) * 1000).rounded()
+ let thumbnailPath = getThumbnailPath(for: forVideo)
+
+ if FileManager.default.fileExists(atPath: thumbnailPath.path) {
+ return SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video)
+ }
+
+ var saved = false
+ let assetImgGenerate = AVAssetImageGenerator(asset: asset)
+ assetImgGenerate.appliesPreferredTrackTransform = true
+ // let scale = UIScreen.main.scale
+ assetImgGenerate.maximumSize = CGSize(width: 360, height: 360)
+ do {
+ let img = try assetImgGenerate.copyCGImage(at: CMTimeMakeWithSeconds(600, preferredTimescale: Int32(1.0)), actualTime: nil)
+ try UIImage.pngData(UIImage(cgImage: img))()?.write(to: thumbnailPath)
+ saved = true
+ } catch {
+ saved = false
+ }
+
+ return saved ? SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video) : nil
+
+ }
+
+ private func getThumbnailPath(for url: URL) -> URL {
+ let fileName = Data(url.lastPathComponent.utf8).base64EncodedString().replacingOccurrences(of: "==", with: "")
+ let path = FileManager.default
+ .containerURL(forSecurityApplicationGroupIdentifier: "group.\(hostAppBundleIdentifier)")!
+ .appendingPathComponent("\(fileName).jpg")
+ return path
+ }
+
+ class SharedMediaFile: Codable {
+ var path: String; // can be image, video or url path. It can also be text content
+ var thumbnail: String?; // video thumbnail
+ var duration: Double?; // video duration in milliseconds
+ var type: SharedMediaType;
+
+
+ init(path: String, thumbnail: String?, duration: Double?, type: SharedMediaType) {
+ self.path = path
+ self.thumbnail = thumbnail
+ self.duration = duration
+ self.type = type
+ }
+
+ // Debug method to print out SharedMediaFile details in the console
+ func toString() {
+ print("[SharedMediaFile] \n\tpath: \(self.path)\n\tthumbnail: \(self.thumbnail)\n\tduration: \(self.duration)\n\ttype: \(self.type)")
+ }
+ }
+
+ enum SharedMediaType: Int, Codable {
+ case image
+ case video
+ case file
+ }
+
+ func toData(data: [SharedMediaFile]) -> Data {
+ let encodedData = try? JSONEncoder().encode(data)
+ return encodedData!
+ }
+}
+
+extension Array {
+ subscript (safe index: UInt) -> Element? {
+ return Int(index) < count ? self[Int(index)] : nil
+ }
+}
diff --git a/lib/routes/documents_route.dart b/lib/routes/documents_route.dart
index eff234d..3682fe6 100644
--- a/lib/routes/documents_route.dart
+++ b/lib/routes/documents_route.dart
@@ -534,7 +534,8 @@ class _DocumentsRouteState extends State {
void uploadSharedDocuments() async {
if (sharedFiles != null && sharedFiles!.isNotEmpty) {
for (var f in sharedFiles!) {
- await API.instance!.uploadFile(f.path);
+ await API.instance!
+ .uploadFile(Uri.decodeFull(f.path).replaceAll('file://', ''));
setState(() {
shareAmount--;
});
diff --git a/lib/scan.dart b/lib/scan.dart
index b2fb972..4c9f8c6 100644
--- a/lib/scan.dart
+++ b/lib/scan.dart
@@ -42,7 +42,7 @@ class ScanHandler {
}
Future scanDocument() async {
- EdgeDetection.useInternalStorage(true);
+ // EdgeDetection.useInternalStorage(true);
String? imagePath = await EdgeDetection.detectEdge;
File(imagePath!).rename(scansDir.path + "/" + imagePath.split("/").last);
handleScans();