mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 07:48:40 +00:00
fixes #340 and continue with #333
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
This commit is contained in:
parent
0984eaf347
commit
230809290a
18 changed files with 1219 additions and 167 deletions
|
|
@ -33,6 +33,16 @@
|
||||||
<data android:scheme="http" android:host="me.twonly.eu" />
|
<data android:scheme="http" android:host="me.twonly.eu" />
|
||||||
<data android:scheme="https" />
|
<data android:scheme="https" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="image/*" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="video/*" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
|
|
@ -46,19 +56,11 @@
|
||||||
android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.JobInfoSchedulerService"
|
android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.JobInfoSchedulerService"
|
||||||
tools:node="remove">
|
tools:node="remove">
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<!-- <service
|
|
||||||
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
|
|
||||||
android:foregroundServiceType="dataSync|remoteMessaging"
|
|
||||||
android:exported="false" /> -->
|
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="eu.twonly.service.TWONLY_LOGO"
|
android:name="eu.twonly.service.TWONLY_LOGO"
|
||||||
android:resource="@drawable/ic_launcher_foreground" />
|
android:resource="@drawable/ic_launcher_foreground" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||||
<uses-permission android:name="android.permission.CAMERA"/>
|
<uses-permission android:name="android.permission.CAMERA"/>
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 83475a912851acb6a718ea32a6f0f754d64a50d8
|
Subproject commit 7930d9727019344238297d810661bc3e8f724c37
|
||||||
|
|
@ -43,6 +43,13 @@ target 'Runner' do
|
||||||
target 'RunnerTests' do
|
target 'RunnerTests' do
|
||||||
inherit! :search_paths
|
inherit! :search_paths
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Share Extension is name of Extension which you created which is in this case 'Share Extension'
|
||||||
|
target 'ShareExtension' do
|
||||||
|
inherit! :search_paths
|
||||||
|
# flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,8 @@ PODS:
|
||||||
- flutter_secure_storage_darwin (10.0.0):
|
- flutter_secure_storage_darwin (10.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- flutter_sharing_intent (1.0.1):
|
||||||
|
- Flutter
|
||||||
- flutter_volume_controller (0.0.1):
|
- flutter_volume_controller (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- gal (1.0.0):
|
- gal (1.0.0):
|
||||||
|
|
@ -260,7 +262,7 @@ PODS:
|
||||||
- nanopb/encode (= 3.30910.0)
|
- nanopb/encode (= 3.30910.0)
|
||||||
- nanopb/decode (3.30910.0)
|
- nanopb/decode (3.30910.0)
|
||||||
- nanopb/encode (3.30910.0)
|
- nanopb/encode (3.30910.0)
|
||||||
- "no_screenshot (0.0.1+4)":
|
- no_screenshot (0.3.2-beta.3):
|
||||||
- Flutter
|
- Flutter
|
||||||
- ScreenProtectorKit (~> 1.3.1)
|
- ScreenProtectorKit (~> 1.3.1)
|
||||||
- objective_c (0.0.1):
|
- objective_c (0.0.1):
|
||||||
|
|
@ -350,6 +352,7 @@ DEPENDENCIES:
|
||||||
- flutter_keyboard_visibility_temp_fork (from `.symlinks/plugins/flutter_keyboard_visibility_temp_fork/ios`)
|
- flutter_keyboard_visibility_temp_fork (from `.symlinks/plugins/flutter_keyboard_visibility_temp_fork/ios`)
|
||||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||||
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
|
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
|
||||||
|
- flutter_sharing_intent (from `.symlinks/plugins/flutter_sharing_intent/ios`)
|
||||||
- flutter_volume_controller (from `.symlinks/plugins/flutter_volume_controller/ios`)
|
- flutter_volume_controller (from `.symlinks/plugins/flutter_volume_controller/ios`)
|
||||||
- gal (from `.symlinks/plugins/gal/darwin`)
|
- gal (from `.symlinks/plugins/gal/darwin`)
|
||||||
- google_mlkit_barcode_scanning (from `.symlinks/plugins/google_mlkit_barcode_scanning/ios`)
|
- google_mlkit_barcode_scanning (from `.symlinks/plugins/google_mlkit_barcode_scanning/ios`)
|
||||||
|
|
@ -441,6 +444,8 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||||
flutter_secure_storage_darwin:
|
flutter_secure_storage_darwin:
|
||||||
:path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin"
|
:path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin"
|
||||||
|
flutter_sharing_intent:
|
||||||
|
:path: ".symlinks/plugins/flutter_sharing_intent/ios"
|
||||||
flutter_volume_controller:
|
flutter_volume_controller:
|
||||||
:path: ".symlinks/plugins/flutter_volume_controller/ios"
|
:path: ".symlinks/plugins/flutter_volume_controller/ios"
|
||||||
gal:
|
gal:
|
||||||
|
|
@ -507,7 +512,8 @@ SPEC CHECKSUMS:
|
||||||
flutter_image_compress_common: 1697a328fd72bfb335507c6bca1a65fa5ad87df1
|
flutter_image_compress_common: 1697a328fd72bfb335507c6bca1a65fa5ad87df1
|
||||||
flutter_keyboard_visibility_temp_fork: 95b2d534bacf6ac62e7fcbe5c2a9e2c2a17ce06f
|
flutter_keyboard_visibility_temp_fork: 95b2d534bacf6ac62e7fcbe5c2a9e2c2a17ce06f
|
||||||
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
||||||
flutter_secure_storage_darwin: ce237a8775b39723566dc72571190a3769d70468
|
flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23
|
||||||
|
flutter_sharing_intent: 0c1e53949f09fa8df8ac2268505687bde8ff264c
|
||||||
flutter_volume_controller: c2be490cb0487e8b88d0d9fc2b7e1c139a4ebccb
|
flutter_volume_controller: c2be490cb0487e8b88d0d9fc2b7e1c139a4ebccb
|
||||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||||
google_mlkit_barcode_scanning: 8f5987f244a43fe1167689c548342a5174108159
|
google_mlkit_barcode_scanning: 8f5987f244a43fe1167689c548342a5174108159
|
||||||
|
|
@ -529,7 +535,7 @@ SPEC CHECKSUMS:
|
||||||
MLKitCommon: 07c2c33ae5640e5380beaaa6e4b9c249a205542d
|
MLKitCommon: 07c2c33ae5640e5380beaaa6e4b9c249a205542d
|
||||||
MLKitVision: 45e79d68845a2de77e2dd4d7f07947f0ed157b0e
|
MLKitVision: 45e79d68845a2de77e2dd4d7f07947f0ed157b0e
|
||||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||||
no_screenshot: 6d183496405a3ab709a67a54e5cd0f639e94729e
|
no_screenshot: 89e778ede9f1e39cc3fb9404d782a42712f2a0b2
|
||||||
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
|
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
|
||||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||||
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
||||||
|
|
@ -551,6 +557,6 @@ SPEC CHECKSUMS:
|
||||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||||
video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a
|
video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a
|
||||||
|
|
||||||
PODFILE CHECKSUM: c0c524475498435108850efecde62ba98e081c25
|
PODFILE CHECKSUM: ae041999f13ba7b2285ff9ad9bc688ed647bbcb7
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
05CF222065FC24670B05B6D0 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */; };
|
05CF222065FC24670B05B6D0 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */; };
|
||||||
06AA21445BEAF2C45DC9DCDF /* Pods_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */; };
|
06AA21445BEAF2C45DC9DCDF /* Pods_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */; };
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
|
30EBDD0F93DC44E774F3B785 /* Pods_ShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E190E82D9973B318A389650B /* Pods_ShareExtension.framework */; };
|
||||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
|
|
@ -19,6 +20,7 @@
|
||||||
CA4FDF5DD8F229C30DE512AF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */; };
|
CA4FDF5DD8F229C30DE512AF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */; };
|
||||||
D21FCEAB2D9F2B750088701D /* NotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D21FCEA42D9F2B750088701D /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
D21FCEAB2D9F2B750088701D /* NotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D21FCEA42D9F2B750088701D /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
D25D4D1E2EF626E30029F805 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D25D4D1D2EF626E30029F805 /* StoreKit.framework */; };
|
D25D4D1E2EF626E30029F805 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D25D4D1D2EF626E30029F805 /* StoreKit.framework */; };
|
||||||
|
D25D4D7A2EFF41DB0029F805 /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D25D4D702EFF41DB0029F805 /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
F3C66D726A2EB28484DF0B10 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */; };
|
F3C66D726A2EB28484DF0B10 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
|
@ -37,6 +39,13 @@
|
||||||
remoteGlobalIDString = D21FCEA32D9F2B750088701D;
|
remoteGlobalIDString = D21FCEA32D9F2B750088701D;
|
||||||
remoteInfo = NotificationService;
|
remoteInfo = NotificationService;
|
||||||
};
|
};
|
||||||
|
D25D4D782EFF41DB0029F805 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = D25D4D6F2EFF41DB0029F805;
|
||||||
|
remoteInfo = ShareExtension;
|
||||||
|
};
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
|
@ -56,6 +65,7 @@
|
||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 13;
|
dstSubfolderSpec = 13;
|
||||||
files = (
|
files = (
|
||||||
|
D25D4D7A2EFF41DB0029F805 /* ShareExtension.appex in Embed Foundation Extensions */,
|
||||||
D21FCEAB2D9F2B750088701D /* NotificationService.appex in Embed Foundation Extensions */,
|
D21FCEAB2D9F2B750088701D /* NotificationService.appex in Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
name = "Embed Foundation Extensions";
|
name = "Embed Foundation Extensions";
|
||||||
|
|
@ -67,10 +77,12 @@
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
1581CC44342D555EFB889768 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
1581CC44342D555EFB889768 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
15CEF849B61A620CFB2DC5F1 /* Pods-ShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.debug.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
35366FD433E0EFC6EF19A452 /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig"; sourceTree = "<group>"; };
|
35366FD433E0EFC6EF19A452 /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
39FB86A38393489D58A01B0B /* Pods-ShareExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.profile.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
4D78471482626812FE2468E9 /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
4D78471482626812FE2468E9 /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
6EB462F87F0A23758713308F /* 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 = "<group>"; };
|
6EB462F87F0A23758713308F /* 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 = "<group>"; };
|
||||||
|
|
@ -87,11 +99,15 @@
|
||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
A22BD564F16069E5FCB60767 /* Pods-ShareExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.release.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
B3B27B7FBEEA31DB7793A0C2 /* 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 = "<group>"; };
|
B3B27B7FBEEA31DB7793A0C2 /* 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 = "<group>"; };
|
||||||
D21FCEA42D9F2B750088701D /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
D21FCEA42D9F2B750088701D /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D2265DD42D920142000D99BB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
D2265DD42D920142000D99BB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
D25D4D1D2EF626E30029F805 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
|
D25D4D1D2EF626E30029F805 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
|
||||||
|
D25D4D702EFF41DB0029F805 /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
D25D4D802EFF437F0029F805 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = "<group>"; };
|
||||||
DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
E190E82D9973B318A389650B /* Pods_ShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
E96A5ACA32A7118204F050A5 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
E96A5ACA32A7118204F050A5 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
F02F7A1D63544AA9F23A1085 /* Pods-NotificationService.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.profile.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.profile.xcconfig"; sourceTree = "<group>"; };
|
F02F7A1D63544AA9F23A1085 /* Pods-NotificationService.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.profile.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
|
@ -105,6 +121,13 @@
|
||||||
);
|
);
|
||||||
target = D21FCEA32D9F2B750088701D /* NotificationService */;
|
target = D21FCEA32D9F2B750088701D /* NotificationService */;
|
||||||
};
|
};
|
||||||
|
D25D4D7E2EFF41DB0029F805 /* Exceptions for "ShareExtension" folder in "ShareExtension" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Info.plist,
|
||||||
|
);
|
||||||
|
target = D25D4D6F2EFF41DB0029F805 /* ShareExtension */;
|
||||||
|
};
|
||||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
|
@ -116,6 +139,14 @@
|
||||||
path = NotificationService;
|
path = NotificationService;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D25D4D712EFF41DB0029F805 /* ShareExtension */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
D25D4D7E2EFF41DB0029F805 /* Exceptions for "ShareExtension" folder in "ShareExtension" target */,
|
||||||
|
);
|
||||||
|
path = ShareExtension;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXFileSystemSynchronizedRootGroup section */
|
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -144,6 +175,14 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D25D4D6D2EFF41DB0029F805 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
30EBDD0F93DC44E774F3B785 /* Pods_ShareExtension.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
|
@ -172,6 +211,7 @@
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
D21FCEA52D9F2B750088701D /* NotificationService */,
|
D21FCEA52D9F2B750088701D /* NotificationService */,
|
||||||
|
D25D4D712EFF41DB0029F805 /* ShareExtension */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */,
|
16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */,
|
||||||
|
|
@ -186,6 +226,7 @@
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||||
D21FCEA42D9F2B750088701D /* NotificationService.appex */,
|
D21FCEA42D9F2B750088701D /* NotificationService.appex */,
|
||||||
|
D25D4D702EFF41DB0029F805 /* ShareExtension.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -193,6 +234,7 @@
|
||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D25D4D802EFF437F0029F805 /* RunnerDebug.entitlements */,
|
||||||
D2265DD42D920142000D99BB /* Runner.entitlements */,
|
D2265DD42D920142000D99BB /* Runner.entitlements */,
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
|
|
@ -213,6 +255,7 @@
|
||||||
A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */,
|
A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */,
|
||||||
EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */,
|
EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */,
|
||||||
DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */,
|
DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */,
|
||||||
|
E190E82D9973B318A389650B /* Pods_ShareExtension.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -229,6 +272,9 @@
|
||||||
4D78471482626812FE2468E9 /* Pods-NotificationService.debug.xcconfig */,
|
4D78471482626812FE2468E9 /* Pods-NotificationService.debug.xcconfig */,
|
||||||
35366FD433E0EFC6EF19A452 /* Pods-NotificationService.release.xcconfig */,
|
35366FD433E0EFC6EF19A452 /* Pods-NotificationService.release.xcconfig */,
|
||||||
F02F7A1D63544AA9F23A1085 /* Pods-NotificationService.profile.xcconfig */,
|
F02F7A1D63544AA9F23A1085 /* Pods-NotificationService.profile.xcconfig */,
|
||||||
|
15CEF849B61A620CFB2DC5F1 /* Pods-ShareExtension.debug.xcconfig */,
|
||||||
|
A22BD564F16069E5FCB60767 /* Pods-ShareExtension.release.xcconfig */,
|
||||||
|
39FB86A38393489D58A01B0B /* Pods-ShareExtension.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -274,6 +320,7 @@
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
D21FCEAA2D9F2B750088701D /* PBXTargetDependency */,
|
D21FCEAA2D9F2B750088701D /* PBXTargetDependency */,
|
||||||
|
D25D4D792EFF41DB0029F805 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = Runner;
|
name = Runner;
|
||||||
productName = Runner;
|
productName = Runner;
|
||||||
|
|
@ -301,6 +348,27 @@
|
||||||
productReference = D21FCEA42D9F2B750088701D /* NotificationService.appex */;
|
productReference = D21FCEA42D9F2B750088701D /* NotificationService.appex */;
|
||||||
productType = "com.apple.product-type.app-extension";
|
productType = "com.apple.product-type.app-extension";
|
||||||
};
|
};
|
||||||
|
D25D4D6F2EFF41DB0029F805 /* ShareExtension */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = D25D4D7F2EFF41DB0029F805 /* Build configuration list for PBXNativeTarget "ShareExtension" */;
|
||||||
|
buildPhases = (
|
||||||
|
627F39EA1643E08048D23996 /* [CP] Check Pods Manifest.lock */,
|
||||||
|
D25D4D6C2EFF41DB0029F805 /* Sources */,
|
||||||
|
D25D4D6D2EFF41DB0029F805 /* Frameworks */,
|
||||||
|
D25D4D6E2EFF41DB0029F805 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
D25D4D712EFF41DB0029F805 /* ShareExtension */,
|
||||||
|
);
|
||||||
|
name = ShareExtension;
|
||||||
|
productName = ShareExtension;
|
||||||
|
productReference = D25D4D702EFF41DB0029F805 /* ShareExtension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
|
|
@ -308,7 +376,7 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = YES;
|
BuildIndependentTargetsInParallel = YES;
|
||||||
LastSwiftUpdateCheck = 1620;
|
LastSwiftUpdateCheck = 2610;
|
||||||
LastUpgradeCheck = 1510;
|
LastUpgradeCheck = 1510;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
|
@ -323,6 +391,9 @@
|
||||||
D21FCEA32D9F2B750088701D = {
|
D21FCEA32D9F2B750088701D = {
|
||||||
CreatedOnToolsVersion = 16.2;
|
CreatedOnToolsVersion = 16.2;
|
||||||
};
|
};
|
||||||
|
D25D4D6F2EFF41DB0029F805 = {
|
||||||
|
CreatedOnToolsVersion = 26.1.1;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||||
|
|
@ -341,6 +412,7 @@
|
||||||
97C146ED1CF9000F007C117D /* Runner */,
|
97C146ED1CF9000F007C117D /* Runner */,
|
||||||
331C8080294A63A400263BE5 /* RunnerTests */,
|
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||||
D21FCEA32D9F2B750088701D /* NotificationService */,
|
D21FCEA32D9F2B750088701D /* NotificationService */,
|
||||||
|
D25D4D6F2EFF41DB0029F805 /* ShareExtension */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
@ -372,6 +444,13 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D25D4D6E2EFF41DB0029F805 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
|
@ -452,6 +531,28 @@
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
|
||||||
};
|
};
|
||||||
|
627F39EA1643E08048D23996 /* [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-ShareExtension-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 */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
|
|
@ -533,6 +634,13 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D25D4D6C2EFF41DB0029F805 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
|
|
@ -546,6 +654,11 @@
|
||||||
target = D21FCEA32D9F2B750088701D /* NotificationService */;
|
target = D21FCEA32D9F2B750088701D /* NotificationService */;
|
||||||
targetProxy = D21FCEA92D9F2B750088701D /* PBXContainerItemProxy */;
|
targetProxy = D21FCEA92D9F2B750088701D /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
D25D4D792EFF41DB0029F805 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = D25D4D6F2EFF41DB0029F805 /* ShareExtension */;
|
||||||
|
targetProxy = D25D4D782EFF41DB0029F805 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
|
|
@ -631,6 +744,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
DEVELOPMENT_TEAM = CN332ZUGRP;
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|
@ -827,8 +941,9 @@
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
DEVELOPMENT_TEAM = CN332ZUGRP;
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|
@ -863,6 +978,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
DEVELOPMENT_TEAM = CN332ZUGRP;
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|
@ -1004,6 +1120,133 @@
|
||||||
};
|
};
|
||||||
name = Profile;
|
name = Profile;
|
||||||
};
|
};
|
||||||
|
D25D4D7B2EFF41DB0029F805 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 15CEF849B61A620CFB2DC5F1 /* Pods-ShareExtension.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtensionDebug.entitlements;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 26.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = eu.twonly.ShareExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||||
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
D25D4D7C2EFF41DB0029F805 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = A22BD564F16069E5FCB60767 /* Pods-ShareExtension.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 26.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = eu.twonly.ShareExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
D25D4D7D2EFF41DB0029F805 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 39FB86A38393489D58A01B0B /* Pods-ShareExtension.profile.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 26.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = eu.twonly.ShareExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
|
@ -1047,6 +1290,16 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
D25D4D7F2EFF41DB0029F805 /* Build configuration list for PBXNativeTarget "ShareExtension" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
D25D4D7B2EFF41DB0029F805 /* Debug */,
|
||||||
|
D25D4D7C2EFF41DB0029F805 /* Release */,
|
||||||
|
D25D4D7D2EFF41DB0029F805 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
};
|
};
|
||||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import Flutter
|
||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
import UserNotifications
|
import UserNotifications
|
||||||
|
import flutter_sharing_intent
|
||||||
|
|
||||||
@main
|
@main
|
||||||
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
|
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
|
||||||
|
|
@ -14,6 +15,17 @@ import UserNotifications
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
|
||||||
|
|
||||||
|
let sharingIntent = SwiftFlutterSharingIntentPlugin.instance
|
||||||
|
if sharingIntent.hasSameSchemePrefix(url: url) {
|
||||||
|
return sharingIntent.application(app, open: url, options: options)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proceed url handling for other Flutter libraries like app_links
|
||||||
|
return super.application(app, open: url, options:options)
|
||||||
|
}
|
||||||
|
|
||||||
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||||
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,9 +87,21 @@
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
<!--Disable Firebase Telemetry-->
|
|
||||||
<key>firebase_performance_collection_deactivated</key>
|
<key>firebase_performance_collection_deactivated</key>
|
||||||
<true/>
|
<true/>
|
||||||
<!--...-->
|
|
||||||
|
<key>AppGroupId</key>
|
||||||
|
<string>$(CUSTOM_GROUP_ID)</string>
|
||||||
|
<key>CFBundleURLTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>SharingMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
||||||
20
ios/Runner/RunnerDebug.entitlements
Normal file
20
ios/Runner/RunnerDebug.entitlements
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>aps-environment</key>
|
||||||
|
<string>development</string>
|
||||||
|
<key>com.apple.developer.associated-domains</key>
|
||||||
|
<array>
|
||||||
|
<string>applinks:me.twonly.eu</string>
|
||||||
|
</array>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.eu.twonly.shareIntent</string>
|
||||||
|
</array>
|
||||||
|
<key>keychain-access-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>$(AppIdentifierPrefix)eu.twonly.shared</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
24
ios/ShareExtension/Base.lproj/MainInterface.storyboard
Normal file
24
ios/ShareExtension/Base.lproj/MainInterface.storyboard
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Share View Controller-->
|
||||||
|
<scene sceneID="ceB-am-kn3">
|
||||||
|
<objects>
|
||||||
|
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
|
<view key="view" opaque="NO" contentMode="scaleToFill" id="wbc-yd-nQP">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<viewLayoutGuide key="safeArea" id="1Xd-am-t49"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="CEy-Cv-SGf" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
||||||
553
ios/ShareExtension/FSIShareViewController.swift
Normal file
553
ios/ShareExtension/FSIShareViewController.swift
Normal file
|
|
@ -0,0 +1,553 @@
|
||||||
|
// SOURCE: https://github.com/bhagat-techind/flutter_sharing_intent/blob/main/example/ios/Share%20Extension/FSIShareViewController.swift
|
||||||
|
|
||||||
|
// FSIShareViewController.swift
|
||||||
|
// Merged, optimized controller: uses RSI architecture with all FSI features preserved
|
||||||
|
// Uses model name `SharingFile` (same fields as SharedMediaFile) where `value` = path
|
||||||
|
|
||||||
|
import AVFoundation
|
||||||
|
import MobileCoreServices
|
||||||
|
import Social
|
||||||
|
import UIKit
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
|
public let kSchemePrefix = "SharingMedia"
|
||||||
|
public let kUserDefaultsKey = "SharingKey"
|
||||||
|
public let kUserDefaultsMessageKey = "SharingMessageKey"
|
||||||
|
public let kAppGroupIdKey = "AppGroupId"
|
||||||
|
public let kAppChannel = "flutter_sharing_intent"
|
||||||
|
|
||||||
|
@available(swift, introduced: 5.0)
|
||||||
|
open class FSIShareViewController: SLComposeServiceViewController {
|
||||||
|
// MARK: - Config
|
||||||
|
private(set) var hostAppBundleIdentifier: String = ""
|
||||||
|
private(set) var appGroupId: String = ""
|
||||||
|
|
||||||
|
// Results
|
||||||
|
private var sharedMedia: [SharingFile] = []
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
private let debugLogs = false
|
||||||
|
|
||||||
|
// MARK: - Lifecycle
|
||||||
|
open override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
loadIds()
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func isContentValid() -> Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func didSelectPost() {
|
||||||
|
if self.sharedMedia.isEmpty {
|
||||||
|
if let text = self.contentText, !text.isEmpty {
|
||||||
|
self.sharedMedia.append(
|
||||||
|
SharingFile(value: text, thumbnail: nil, duration: nil, type: .text)
|
||||||
|
)
|
||||||
|
self.saveAndRedirect(message: text)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.completeAndExit()
|
||||||
|
} else {
|
||||||
|
self.saveAndRedirect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
// Process attachments automatically on appear like original FSI
|
||||||
|
processAttachments()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Load Ids
|
||||||
|
private func loadIds() {
|
||||||
|
let shareExtId = Bundle.main.bundleIdentifier ?? ""
|
||||||
|
if let idx = shareExtId.lastIndex(of: ".") {
|
||||||
|
hostAppBundleIdentifier = String(shareExtId[..<idx])
|
||||||
|
} else {
|
||||||
|
hostAppBundleIdentifier = shareExtId
|
||||||
|
}
|
||||||
|
let custom = Bundle.main.object(forInfoDictionaryKey: kAppGroupIdKey) as? String
|
||||||
|
appGroupId = custom ?? "group.\(hostAppBundleIdentifier)"
|
||||||
|
log("loaded host=\(hostAppBundleIdentifier) group=\(appGroupId)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Attachment processing (clean RSI style, preserve FSI features)
|
||||||
|
private func processAttachments() {
|
||||||
|
guard let content = extensionContext?.inputItems.first as? NSExtensionItem else {
|
||||||
|
completeAndExit()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let attachments = content.attachments, !attachments.isEmpty else {
|
||||||
|
completeAndExit()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use DispatchGroup to wait for async loads
|
||||||
|
let group = DispatchGroup()
|
||||||
|
for (index, provider) in attachments.enumerated() {
|
||||||
|
group.enter()
|
||||||
|
// Try all SharedMediaType options similar to RSI but preserve explicit FSI order
|
||||||
|
if provider.isImage {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.image, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleImageItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isMovie {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.movie, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleVideoItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isFile {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.fileURL, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleFileItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isURL {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.url, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleUrlItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isText {
|
||||||
|
let id = provider.hasItemConformingToTypeIdentifier(UType.plainText)
|
||||||
|
? UType.plainText
|
||||||
|
: UType.text
|
||||||
|
provider.loadItem(forTypeIdentifier: id, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleTextItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isData {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.data, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleFileItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isItem {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.item, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleFileItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log("Unknown provider type: \(provider.registeredTypeIdentifiers)")
|
||||||
|
|
||||||
|
// Unknown type: just leave
|
||||||
|
group.leave()
|
||||||
|
}
|
||||||
|
|
||||||
|
group.notify(queue: .main) { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
// if we have media -> media, else fallback to complete
|
||||||
|
if !self.sharedMedia.isEmpty {
|
||||||
|
self.saveAndRedirect()
|
||||||
|
} else {
|
||||||
|
print("FSIShare: No shared media → stopping.")
|
||||||
|
self.completeAndExit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Individual handlers (preserve FSI behavior)
|
||||||
|
private func handleTextItem(data: NSSecureCoding?, index: Int, total: Int) {
|
||||||
|
if let s = data as? String {
|
||||||
|
sharedMedia.append(SharingFile(value: s, thumbnail: nil, duration: nil, type: .text))
|
||||||
|
} else if let url = data as? URL {
|
||||||
|
sharedMedia.append(SharingFile(value: url.absoluteString, thumbnail: nil, duration: nil, type: .url))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleUrlItem(data: NSSecureCoding?, index: Int, total: Int) {
|
||||||
|
if let url = data as? URL {
|
||||||
|
sharedMedia.append(SharingFile(value: url.absoluteString, thumbnail: nil, duration: nil, type: .url))
|
||||||
|
} else if let s = data as? String {
|
||||||
|
sharedMedia.append(SharingFile(value: s, thumbnail: nil, duration: nil, type: .text))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleImageItem(data: NSSecureCoding?, index: Int, total: Int) {
|
||||||
|
// data can be URL, UIImage, or Data
|
||||||
|
if let url = data as? URL {
|
||||||
|
let filename = getFileName(from: url, type: .image)
|
||||||
|
if let dst = containerURL()?.appendingPathComponent(filename) {
|
||||||
|
if copyFile(at: url, to: dst) {
|
||||||
|
sharedMedia.append(SharingFile(value: dst.absoluteString, mimeType: url.mimeType(), thumbnail: nil, duration: nil, type: .image))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let img = data as? UIImage {
|
||||||
|
if let saved = writeTempImage(img) {
|
||||||
|
sharedMedia.append(saved)
|
||||||
|
}
|
||||||
|
} else if let raw = data as? Data, let img = UIImage(data: raw) {
|
||||||
|
if let saved = writeTempImage(img) {
|
||||||
|
sharedMedia.append(saved)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleVideoItem(data: NSSecureCoding?, index: Int, total: Int) {
|
||||||
|
if let url = data as? URL {
|
||||||
|
let filename = getFileName(from: url, type: .video)
|
||||||
|
if let dst = containerURL()?.appendingPathComponent(filename) {
|
||||||
|
if copyFile(at: url, to: dst) {
|
||||||
|
if let m = getSharedMediaFile(forVideo: dst) {
|
||||||
|
sharedMedia.append(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleFileItem(data: NSSecureCoding?, index: Int, total: Int) {
|
||||||
|
if let url = data as? URL {
|
||||||
|
let filename = getFileName(from: url, type: .file)
|
||||||
|
if let dst = containerURL()?.appendingPathComponent(filename) {
|
||||||
|
if copyFile(at: url, to: dst) {
|
||||||
|
sharedMedia.append(SharingFile(value: dst.absoluteString, mimeType: url.mimeType(), thumbnail: nil, duration: nil, type: .file))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if let raw = data as? Data {
|
||||||
|
let filename = "File_\(UUID().uuidString)"
|
||||||
|
if let dst = containerURL()?.appendingPathComponent(filename) {
|
||||||
|
do {
|
||||||
|
try raw.write(to: dst)
|
||||||
|
sharedMedia.append(SharingFile(value: dst.absoluteString, mimeType: "application/octet-stream", thumbnail: nil, duration: nil, type: .file))
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Helpers: write temp image
|
||||||
|
private func writeTempImage(_ image: UIImage) -> SharingFile? {
|
||||||
|
guard let container = containerURL() else { return nil }
|
||||||
|
let tempName = "TempImage_\(UUID().uuidString).png"
|
||||||
|
let dst = container.appendingPathComponent(tempName)
|
||||||
|
do {
|
||||||
|
if let d = image.pngData() {
|
||||||
|
try d.write(to: dst)
|
||||||
|
let decoded = dst.absoluteString.removingPercentEncoding ?? dst.absoluteString
|
||||||
|
return SharingFile(value: decoded, mimeType: "image/png", thumbnail: nil, duration: nil, type: .image)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
log("writeTempImage error: \(error)")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func saveAndRedirect(message: String? = nil) {
|
||||||
|
let ud = UserDefaults(suiteName: appGroupId)
|
||||||
|
if !sharedMedia.isEmpty {
|
||||||
|
if let data = try? JSONEncoder().encode(sharedMedia) {
|
||||||
|
ud?.set(data, forKey: kUserDefaultsKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ud?.set(message, forKey: kUserDefaultsMessageKey)
|
||||||
|
ud?.synchronize()
|
||||||
|
redirectToHostApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func redirectToHostApp() {
|
||||||
|
// kept for compatibility (RSI style)
|
||||||
|
loadIds()
|
||||||
|
// let raw = "\(kSchemePrefix)-\(hostAppBundleIdentifier):share"
|
||||||
|
let raw = "\(kSchemePrefix)-\(hostAppBundleIdentifier)://dataUrl=\(kUserDefaultsKey)"
|
||||||
|
guard let url = URL(string: raw.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? raw) else { completeAndExit(); return }
|
||||||
|
|
||||||
|
var responder: UIResponder? = self
|
||||||
|
if #available(iOS 18.0, *) {
|
||||||
|
while responder != nil {
|
||||||
|
if let app = responder as? UIApplication { app.open(url, options: [:], completionHandler: nil) }
|
||||||
|
responder = responder?.next
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let sel = sel_registerName("openURL:")
|
||||||
|
while responder != nil {
|
||||||
|
if responder?.responds(to: sel) ?? false { _ = responder?.perform(sel, with: url) }
|
||||||
|
responder = responder?.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - File / thumbnail / metadata helpers
|
||||||
|
func getExtension(from url: URL, type: SharingFileType) -> 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"
|
||||||
|
case .text: ex = "txt"
|
||||||
|
case .url: ex = "txt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ex ?? "bin"
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFileName(from url: URL, type: SharingFileType) -> 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)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
log("copyFile error: \(error)")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getSharedMediaFile(forVideo: URL) -> SharingFile? {
|
||||||
|
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 SharingFile(value: forVideo.absoluteString, mimeType: forVideo.mimeType(), thumbnail: thumbnailPath.absoluteString, duration: Int(duration), type: .video)
|
||||||
|
}
|
||||||
|
|
||||||
|
let gen = AVAssetImageGenerator(asset: asset)
|
||||||
|
gen.appliesPreferredTrackTransform = true
|
||||||
|
gen.maximumSize = CGSize(width: 360, height: 360)
|
||||||
|
|
||||||
|
// Use first second or zero
|
||||||
|
let time = CMTime(seconds: min(1.0, CMTimeGetSeconds(asset.duration)), preferredTimescale: 600)
|
||||||
|
do {
|
||||||
|
let cg = try gen.copyCGImage(at: time, actualTime: nil)
|
||||||
|
if let data = UIImage(cgImage: cg).jpegData(compressionQuality: 0.8) {
|
||||||
|
try data.write(to: thumbnailPath)
|
||||||
|
return SharingFile(value: forVideo.absoluteString, mimeType: forVideo.mimeType(), thumbnail: thumbnailPath.absoluteString, duration: Int(duration), type: .video)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
log("getSharedMediaFile thumbnail error: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback
|
||||||
|
return SharingFile(value: forVideo.absoluteString, mimeType: forVideo.mimeType(), thumbnail: nil, duration: Int(duration), type: .video)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getThumbnailPath(for url: URL) -> URL {
|
||||||
|
guard let container = containerURL() else { fatalError("App group not configured or missing") }
|
||||||
|
let fileName = Data(url.lastPathComponent.utf8).base64EncodedString().replacingOccurrences(of: "=", with: "")
|
||||||
|
return container.appendingPathComponent("\(fileName).jpg")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func containerURL() -> URL? {
|
||||||
|
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func completeAndExit() {
|
||||||
|
extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func dismissWithError() {
|
||||||
|
log("[ERROR] Error loading data!")
|
||||||
|
let alert = UIAlertController(title: "Error", message: "Error loading data", preferredStyle: .alert)
|
||||||
|
alert.addAction(UIAlertAction(title: "OK", style: .cancel) { _ in self.dismiss(animated: true, completion: nil) })
|
||||||
|
present(alert, animated: true, completion: nil)
|
||||||
|
extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func writeTempFile(_ image: UIImage, to dstURL: URL) -> Bool {
|
||||||
|
do {
|
||||||
|
if FileManager.default.fileExists(atPath: dstURL.path) { try FileManager.default.removeItem(at: dstURL) }
|
||||||
|
let pngData = image.pngData()
|
||||||
|
try pngData?.write(to: dstURL)
|
||||||
|
return true
|
||||||
|
} catch (let error) {
|
||||||
|
log("writeTempFile error: \(error)")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func saveToUserDefaults(data: [SharingFile]) {
|
||||||
|
let ud = UserDefaults(suiteName: appGroupId)
|
||||||
|
if let enc = try? JSONEncoder().encode(data) { ud?.set(enc, forKey: kUserDefaultsKey); ud?.synchronize() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Logging
|
||||||
|
private func log(_ s: String) { if debugLogs { print("[FSIShareVC] \(s)") } }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Extensions
|
||||||
|
extension URL {
|
||||||
|
func mimeType() -> String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
if let ut = UTType(filenameExtension: self.pathExtension), let m = ut.preferredMIMEType { return m }
|
||||||
|
} else {
|
||||||
|
if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, self.pathExtension as NSString, nil)?.takeRetainedValue() {
|
||||||
|
if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() { return mimetype as String }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "application/octet-stream"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension NSItemProvider {
|
||||||
|
var isImage: Bool { return hasItemConformingToTypeIdentifier(UType.image) }
|
||||||
|
var isMovie: Bool { return hasItemConformingToTypeIdentifier(UType.movie) }
|
||||||
|
var isText: Bool {
|
||||||
|
hasItemConformingToTypeIdentifier(UType.plainText) || hasItemConformingToTypeIdentifier(UType.text)
|
||||||
|
}
|
||||||
|
var isURL: Bool { return hasItemConformingToTypeIdentifier(UType.url) }
|
||||||
|
var isFile: Bool { return hasItemConformingToTypeIdentifier(UType.fileURL) }
|
||||||
|
var isData:Bool { return hasItemConformingToTypeIdentifier(UType.data) }
|
||||||
|
var isItem: Bool { hasItemConformingToTypeIdentifier(UType.item) }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Array {
|
||||||
|
subscript(safe index: UInt) -> Element? { return Int(index) < count ? self[Int(index)] : nil }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class SharingFile: Codable {
|
||||||
|
var value: String
|
||||||
|
var mimeType: String?
|
||||||
|
var thumbnail: String?; // video thumbnail
|
||||||
|
var duration: Int?; // video duration in milliseconds
|
||||||
|
var type: SharingFileType;
|
||||||
|
var message: String? // post message
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case value
|
||||||
|
case mimeType
|
||||||
|
case thumbnail
|
||||||
|
case duration
|
||||||
|
case type
|
||||||
|
case message
|
||||||
|
}
|
||||||
|
|
||||||
|
init(value: String, mimeType: String? = nil, thumbnail: String?, duration: Int?,
|
||||||
|
type: SharingFileType, message: String?=nil) {
|
||||||
|
self.value = value
|
||||||
|
self.mimeType = mimeType
|
||||||
|
self.thumbnail = thumbnail
|
||||||
|
self.duration = duration
|
||||||
|
self.type = type
|
||||||
|
self.message = message
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug method to print out SharedMediaFile details in the console
|
||||||
|
func toString() {
|
||||||
|
print("[SharingFile] \n\tvalue: \(self.value)\n\tthumbnail: \(self.thumbnail ?? "--" )\n\tduration: \(self.duration ?? 0)\n\ttype: \(self.type)\n\tmimeType: \(String(describing: self.mimeType))\n\tmessage: \(String(describing: self.message))")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum SharingFileType: Int, Codable {
|
||||||
|
case text
|
||||||
|
case url
|
||||||
|
case image
|
||||||
|
case video
|
||||||
|
case file
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unified UTType → works on iOS 11–18
|
||||||
|
enum UType {
|
||||||
|
static var image: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.image.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeImage as String // old API
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var movie: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.movie.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeMovie as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static var url: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.url.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeURL as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var fileURL: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.fileURL.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeFileURL as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var text: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.text.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeText as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var plainText: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.plainText.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypePlainText as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var data: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.data.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeData as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var item: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.item.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeItem as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
ios/ShareExtension/Info.plist
Normal file
35
ios/ShareExtension/Info.plist
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>AppGroupId</key>
|
||||||
|
<string>$(CUSTOM_GROUP_ID)</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionMainStoryboard</key>
|
||||||
|
<string>MainInterface</string>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.share-services</string>
|
||||||
|
<key>NSExtensionAttributes</key>
|
||||||
|
<dict>
|
||||||
|
<key>PHSupportedMediaTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>Video</string>
|
||||||
|
<string>Image</string>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<key>NSExtensionActivationRule</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>NSExtensionActivationSupportsMovieWithMaxCount</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
10
ios/ShareExtension/ShareExtensionDebug.entitlements
Normal file
10
ios/ShareExtension/ShareExtensionDebug.entitlements
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.eu.twonly.shareIntent</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
3
ios/ShareExtension/ShareViewController.swift
Normal file
3
ios/ShareExtension/ShareViewController.swift
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
class ShareViewController: FSIShareViewController {
|
||||||
|
|
||||||
|
}
|
||||||
180
lib/src/services/intent/links.intent.dart
Normal file
180
lib/src/services/intent/links.intent.dart
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_sharing_intent/model/sharing_file.dart';
|
||||||
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/services/api/mediafiles/upload.service.dart';
|
||||||
|
import 'package:twonly/src/services/signal/session.signal.dart';
|
||||||
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/views/camera/share_image_editor_view.dart';
|
||||||
|
import 'package:twonly/src/views/chats/add_new_user.view.dart';
|
||||||
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
|
import 'package:twonly/src/views/contact/contact.view.dart';
|
||||||
|
import 'package:twonly/src/views/public_profile.view.dart';
|
||||||
|
|
||||||
|
Future<void> handleIntentUrl(BuildContext context, Uri uri) async {
|
||||||
|
if (!uri.scheme.startsWith('http')) return;
|
||||||
|
if (uri.host != 'me.twonly.eu') return;
|
||||||
|
if (uri.hasEmptyPath) return;
|
||||||
|
|
||||||
|
final publicKey = uri.hasFragment ? uri.fragment : null;
|
||||||
|
final userPaths = uri.path.split('/');
|
||||||
|
if (userPaths.length != 2) return;
|
||||||
|
final username = userPaths[1];
|
||||||
|
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
if (username == gUser.username) {
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return const PublicProfileView();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.info(
|
||||||
|
'Opened via deep link!: username = $username public_key = ${uri.fragment}',
|
||||||
|
);
|
||||||
|
final contacts = await twonlyDB.contactsDao.getContactsByUsername(username);
|
||||||
|
if (contacts.isEmpty) {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
Uint8List? publicKeyBytes;
|
||||||
|
if (publicKey != null) {
|
||||||
|
publicKeyBytes = base64Url.decode(publicKey);
|
||||||
|
}
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return AddNewUserView(
|
||||||
|
username: username,
|
||||||
|
publicKey: publicKeyBytes,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (publicKey != null) {
|
||||||
|
try {
|
||||||
|
final contact = contacts.first;
|
||||||
|
final storedPublicKey = await getPublicKeyFromContact(contact.userId);
|
||||||
|
final receivedPublicKey = base64Url.decode(publicKey);
|
||||||
|
if (storedPublicKey == null ||
|
||||||
|
receivedPublicKey.isEmpty ||
|
||||||
|
!context.mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (storedPublicKey.equals(receivedPublicKey)) {
|
||||||
|
if (!contact.verified) {
|
||||||
|
final markAsVerified = await showAlertDialog(
|
||||||
|
context,
|
||||||
|
context.lang.linkFromUsername(contact.username),
|
||||||
|
context.lang.linkFromUsernameLong,
|
||||||
|
customOk: context.lang.gotLinkFromFriend,
|
||||||
|
);
|
||||||
|
if (markAsVerified) {
|
||||||
|
await twonlyDB.contactsDao.updateContact(
|
||||||
|
contact.userId,
|
||||||
|
const ContactsCompanion(
|
||||||
|
verified: Value(true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return ContactView(contact.userId);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await showAlertDialog(
|
||||||
|
context,
|
||||||
|
context.lang.couldNotVerifyUsername(contact.username),
|
||||||
|
context.lang.linkPubkeyDoesNotMatch,
|
||||||
|
customCancel: '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Log.warn(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleIntentMediaFile(
|
||||||
|
BuildContext context,
|
||||||
|
String filePath,
|
||||||
|
MediaType type,
|
||||||
|
) async {
|
||||||
|
final file = File(filePath);
|
||||||
|
if (!file.existsSync()) {
|
||||||
|
Log.error('The shared intent file does not exits.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final newMediaService = await initializeMediaUpload(
|
||||||
|
type,
|
||||||
|
gUser.defaultShowTime,
|
||||||
|
);
|
||||||
|
if (newMediaService == null) {
|
||||||
|
Log.error('Could not create new media file for intent shared file');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.copySync(newMediaService.originalPath.path);
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => ShareImageEditorView(
|
||||||
|
mediaFileService: newMediaService,
|
||||||
|
sharedFromGallery: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleIntentSharedFile(
|
||||||
|
BuildContext context,
|
||||||
|
List<SharedFile> files,
|
||||||
|
) async {
|
||||||
|
for (final file in files) {
|
||||||
|
if (file.value == null) {
|
||||||
|
Log.error(
|
||||||
|
'Got shared media, but value is empty: getMediaStream ${file.mimeType}',
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Log.info('got file via intent ${file.type} ${file.value}');
|
||||||
|
|
||||||
|
switch (file.type) {
|
||||||
|
case SharedMediaType.URL:
|
||||||
|
await handleIntentUrl(context, Uri.parse(file.value!));
|
||||||
|
case SharedMediaType.IMAGE:
|
||||||
|
var type = MediaType.image;
|
||||||
|
if (file.value!.endsWith('.gif')) {
|
||||||
|
type = MediaType.gif;
|
||||||
|
}
|
||||||
|
await handleIntentMediaFile(context, file.value!, type);
|
||||||
|
case SharedMediaType.VIDEO:
|
||||||
|
await handleIntentMediaFile(context, file.value!, MediaType.video);
|
||||||
|
// ignore: no_default_cases
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
break; // only handle one file...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -227,7 +227,8 @@ class MainCameraController {
|
||||||
content: Text(
|
content: Text(
|
||||||
globalRootScaffoldMessengerKey.currentContext?.lang
|
globalRootScaffoldMessengerKey.currentContext?.lang
|
||||||
.verifiedPublicKey(
|
.verifiedPublicKey(
|
||||||
getContactDisplayName(contact)) ??
|
getContactDisplayName(contact),
|
||||||
|
) ??
|
||||||
'',
|
'',
|
||||||
),
|
),
|
||||||
duration: const Duration(seconds: 6),
|
duration: const Duration(seconds: 6),
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,22 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:typed_data';
|
|
||||||
import 'package:app_links/app_links.dart';
|
import 'package:app_links/app_links.dart';
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:drift/drift.dart' show Value;
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
|
import 'package:flutter_sharing_intent/flutter_sharing_intent.dart';
|
||||||
|
import 'package:flutter_sharing_intent/model/sharing_file.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/services/intent/links.intent.dart';
|
||||||
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
||||||
import 'package:twonly/src/services/notifications/setup.notifications.dart';
|
import 'package:twonly/src/services/notifications/setup.notifications.dart';
|
||||||
import 'package:twonly/src/services/signal/session.signal.dart';
|
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview.dart';
|
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview.dart';
|
||||||
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
|
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
|
||||||
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
|
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
|
||||||
import 'package:twonly/src/views/camera/share_image_editor_view.dart';
|
import 'package:twonly/src/views/camera/share_image_editor_view.dart';
|
||||||
import 'package:twonly/src/views/chats/add_new_user.view.dart';
|
|
||||||
import 'package:twonly/src/views/chats/chat_list.view.dart';
|
import 'package:twonly/src/views/chats/chat_list.view.dart';
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
|
||||||
import 'package:twonly/src/views/contact/contact.view.dart';
|
|
||||||
import 'package:twonly/src/views/memories/memories.view.dart';
|
import 'package:twonly/src/views/memories/memories.view.dart';
|
||||||
import 'package:twonly/src/views/public_profile.view.dart';
|
|
||||||
|
|
||||||
void Function(int) globalUpdateOfHomeViewPageIndex = (a) {};
|
void Function(int) globalUpdateOfHomeViewPageIndex = (a) {};
|
||||||
|
|
||||||
|
|
@ -61,6 +54,7 @@ class HomeViewState extends State<HomeView> {
|
||||||
final MainCameraController _mainCameraController = MainCameraController();
|
final MainCameraController _mainCameraController = MainCameraController();
|
||||||
|
|
||||||
final PageController homeViewPageController = PageController(initialPage: 1);
|
final PageController homeViewPageController = PageController(initialPage: 1);
|
||||||
|
late StreamSubscription<List<SharedFile>> _intentStreamSub;
|
||||||
late StreamSubscription<Uri> _deepLinkSub;
|
late StreamSubscription<Uri> _deepLinkSub;
|
||||||
|
|
||||||
double buttonDiameter = 100;
|
double buttonDiameter = 100;
|
||||||
|
|
@ -121,99 +115,21 @@ class HomeViewState extends State<HomeView> {
|
||||||
|
|
||||||
// Subscribe to all events (initial link and further)
|
// Subscribe to all events (initial link and further)
|
||||||
_deepLinkSub = AppLinks().uriLinkStream.listen((uri) async {
|
_deepLinkSub = AppLinks().uriLinkStream.listen((uri) async {
|
||||||
if (!uri.scheme.startsWith('http')) return;
|
if (mounted) await handleIntentUrl(context, uri);
|
||||||
if (uri.host != 'me.twonly.eu') return;
|
});
|
||||||
if (uri.hasEmptyPath) return;
|
|
||||||
|
|
||||||
final publicKey = uri.hasFragment ? uri.fragment : null;
|
_intentStreamSub = FlutterSharingIntent.instance.getMediaStream().listen(
|
||||||
final userPaths = uri.path.split('/');
|
(f) {
|
||||||
if (userPaths.length != 2) return;
|
if (mounted) handleIntentSharedFile(context, f);
|
||||||
final username = userPaths[1];
|
},
|
||||||
|
// ignore: inference_failure_on_untyped_parameter
|
||||||
if (!mounted) return;
|
onError: (err) {
|
||||||
|
Log.error('getIntentDataStream error: $err');
|
||||||
if (username == gUser.username) {
|
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return const PublicProfileView();
|
|
||||||
},
|
},
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.info(
|
FlutterSharingIntent.instance.getInitialSharing().then((f) {
|
||||||
'Opened via deep link!: username = $username public_key = ${uri.fragment}',
|
if (mounted) handleIntentSharedFile(context, f);
|
||||||
);
|
|
||||||
final contacts =
|
|
||||||
await twonlyDB.contactsDao.getContactsByUsername(username);
|
|
||||||
if (contacts.isEmpty) {
|
|
||||||
if (!mounted) return;
|
|
||||||
Uint8List? publicKeyBytes;
|
|
||||||
if (publicKey != null) {
|
|
||||||
publicKeyBytes = base64Url.decode(publicKey);
|
|
||||||
}
|
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return AddNewUserView(
|
|
||||||
username: username,
|
|
||||||
publicKey: publicKeyBytes,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else if (publicKey != null) {
|
|
||||||
try {
|
|
||||||
final contact = contacts.first;
|
|
||||||
final storedPublicKey = await getPublicKeyFromContact(contact.userId);
|
|
||||||
final receivedPublicKey = base64Url.decode(publicKey);
|
|
||||||
if (storedPublicKey == null ||
|
|
||||||
receivedPublicKey.isEmpty ||
|
|
||||||
!mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (storedPublicKey.equals(receivedPublicKey)) {
|
|
||||||
if (!contact.verified) {
|
|
||||||
final markAsVerified = await showAlertDialog(
|
|
||||||
context,
|
|
||||||
context.lang.linkFromUsername(contact.username),
|
|
||||||
context.lang.linkFromUsernameLong,
|
|
||||||
customOk: context.lang.gotLinkFromFriend,
|
|
||||||
);
|
|
||||||
if (markAsVerified) {
|
|
||||||
await twonlyDB.contactsDao.updateContact(
|
|
||||||
contact.userId,
|
|
||||||
const ContactsCompanion(
|
|
||||||
verified: Value(true),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) {
|
|
||||||
return ContactView(contact.userId);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await showAlertDialog(
|
|
||||||
context,
|
|
||||||
context.lang.couldNotVerifyUsername(contact.username),
|
|
||||||
context.lang.linkPubkeyDoesNotMatch,
|
|
||||||
customCancel: '',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
Log.warn(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,6 +138,7 @@ class HomeViewState extends State<HomeView> {
|
||||||
unawaited(selectNotificationStream.close());
|
unawaited(selectNotificationStream.close());
|
||||||
disableCameraTimer?.cancel();
|
disableCameraTimer?.cancel();
|
||||||
_mainCameraController.closeCamera();
|
_mainCameraController.closeCamera();
|
||||||
|
_intentStreamSub.cancel();
|
||||||
_deepLinkSub.cancel();
|
_deepLinkSub.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
52
pubspec.lock
52
pubspec.lock
|
|
@ -742,29 +742,27 @@ packages:
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: flutter_secure_storage
|
name: flutter_secure_storage
|
||||||
ref: a06ead81809c900e7fc421a30db0adf3b5919139
|
sha256: da922f2aab2d733db7e011a6bcc4a825b844892d4edd6df83ff156b09a9b2e40
|
||||||
resolved-ref: a06ead81809c900e7fc421a30db0adf3b5919139
|
url: "https://pub.dev"
|
||||||
url: "https://github.com/juliansteenbakker/flutter_secure_storage.git"
|
source: hosted
|
||||||
source: git
|
version: "10.0.0"
|
||||||
version: "10.0.0-beta.4"
|
|
||||||
flutter_secure_storage_darwin:
|
flutter_secure_storage_darwin:
|
||||||
dependency: "direct overridden"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
path: flutter_secure_storage_darwin
|
name: flutter_secure_storage_darwin
|
||||||
ref: a06ead81809c900e7fc421a30db0adf3b5919139
|
sha256: "8878c25136a79def1668c75985e8e193d9d7d095453ec28730da0315dc69aee3"
|
||||||
resolved-ref: a06ead81809c900e7fc421a30db0adf3b5919139
|
url: "https://pub.dev"
|
||||||
url: "https://github.com/juliansteenbakker/flutter_secure_storage.git"
|
source: hosted
|
||||||
source: git
|
version: "0.2.0"
|
||||||
version: "0.1.0"
|
|
||||||
flutter_secure_storage_linux:
|
flutter_secure_storage_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage_linux
|
name: flutter_secure_storage_linux
|
||||||
sha256: "9b4b73127e857cd3117d43a70fa3dddadb6e0b253be62e6a6ab85caa0742182c"
|
sha256: "2b5c76dce569ab752d55a1cee6a2242bcc11fdba927078fb88c503f150767cda"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "3.0.0"
|
||||||
flutter_secure_storage_platform_interface:
|
flutter_secure_storage_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -777,18 +775,25 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage_web
|
name: flutter_secure_storage_web
|
||||||
sha256: "4c3f233e739545c6cb09286eeec1cc4744138372b985113acc904f7263bef517"
|
sha256: "6a1137df62b84b54261dca582c1c09ea72f4f9a4b2fcee21b025964132d5d0c3"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.1.0"
|
||||||
flutter_secure_storage_windows:
|
flutter_secure_storage_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage_windows
|
name: flutter_secure_storage_windows
|
||||||
sha256: ff32af20f70a8d0e59b2938fc92de35b54a74671041c814275afd80e27df9f21
|
sha256: "3b7c8e068875dfd46719ff57c90d8c459c87f2302ed6b00ff006b3c9fcad1613"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.1.0"
|
||||||
|
flutter_sharing_intent:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "dependencies/flutter_sharing_intent"
|
||||||
|
relative: true
|
||||||
|
source: path
|
||||||
|
version: "2.0.4"
|
||||||
flutter_svg:
|
flutter_svg:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -1243,11 +1248,10 @@ packages:
|
||||||
no_screenshot:
|
no_screenshot:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: no_screenshot
|
path: "dependencies/no_screenshot"
|
||||||
sha256: ec3d86d7ee89a09c3a3939c1003012536ba4b3fcb4f8cbd23d87ada595c99258
|
relative: true
|
||||||
url: "https://pub.dev"
|
source: path
|
||||||
source: hosted
|
version: "0.3.2-beta.3"
|
||||||
version: "0.3.1"
|
|
||||||
objective_c:
|
objective_c:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
61
pubspec.yaml
61
pubspec.yaml
|
|
@ -36,6 +36,7 @@ dependencies:
|
||||||
url_launcher: ^6.3.2
|
url_launcher: ^6.3.2
|
||||||
vector_graphics: ^1.1.19
|
vector_graphics: ^1.1.19
|
||||||
video_player: ^2.10.1
|
video_player: ^2.10.1
|
||||||
|
in_app_purchase: ^3.2.3
|
||||||
|
|
||||||
|
|
||||||
# Trusted publisher fluttercommunity.dev
|
# Trusted publisher fluttercommunity.dev
|
||||||
|
|
@ -54,44 +55,50 @@ dependencies:
|
||||||
scrollable_positioned_list: ^0.3.8 # google.dev
|
scrollable_positioned_list: ^0.3.8 # google.dev
|
||||||
|
|
||||||
|
|
||||||
|
# Flutter Favorite
|
||||||
|
provider: ^6.1.2
|
||||||
|
drift: ^2.25.1
|
||||||
|
drift_flutter: ^0.2.4
|
||||||
|
flutter_local_notifications: ^19.1.0
|
||||||
|
sentry_flutter: ^9.8.0
|
||||||
|
|
||||||
|
|
||||||
|
# With high download
|
||||||
|
app_links: ^7.0.0 # 1.6 mio
|
||||||
|
image: ^4.3.0 # 3.3 mio
|
||||||
|
archive: ^4.0.7 # 6.5 mio
|
||||||
|
file_picker: ^10.3.6 # 2 mio
|
||||||
|
get: ^4.7.2 # 740 k
|
||||||
|
flutter_secure_storage: ^10.0.0 # 1.85 mio
|
||||||
|
permission_handler: ^12.0.0+1 # 2 mio
|
||||||
|
|
||||||
|
|
||||||
# Not yet checked
|
# Not yet checked
|
||||||
archive: ^4.0.7
|
|
||||||
audio_waveforms: ^2.0.0
|
audio_waveforms: ^2.0.0
|
||||||
avatar_maker: ^0.4.0
|
avatar_maker: ^0.4.0
|
||||||
background_downloader: ^9.4.0
|
background_downloader: ^9.4.0
|
||||||
cached_network_image: ^3.4.1
|
cached_network_image: ^3.4.1
|
||||||
cryptography_flutter_plus: ^2.3.4
|
cryptography_flutter_plus: ^2.3.4
|
||||||
cryptography_plus: ^2.7.0
|
cryptography_plus: ^2.7.0
|
||||||
drift: ^2.25.1
|
|
||||||
drift_flutter: ^0.2.4
|
|
||||||
ffmpeg_kit_flutter_new: ^4.1.0
|
ffmpeg_kit_flutter_new: ^4.1.0
|
||||||
file_picker: ^10.3.6
|
|
||||||
flutter_android_volume_keydown: ^1.0.1
|
flutter_android_volume_keydown: ^1.0.1
|
||||||
flutter_image_compress: ^2.4.0
|
flutter_image_compress: ^2.4.0
|
||||||
flutter_local_notifications: ^19.1.0
|
|
||||||
flutter_secure_storage:
|
|
||||||
git:
|
|
||||||
url: https://github.com/juliansteenbakker/flutter_secure_storage.git
|
|
||||||
ref: a06ead81809c900e7fc421a30db0adf3b5919139 # from develop
|
|
||||||
path: flutter_secure_storage/
|
|
||||||
flutter_volume_controller: ^1.3.4
|
flutter_volume_controller: ^1.3.4
|
||||||
gal: ^2.3.1
|
gal: ^2.3.1
|
||||||
get: ^4.7.2
|
|
||||||
google_mlkit_barcode_scanning: ^0.14.1
|
google_mlkit_barcode_scanning: ^0.14.1
|
||||||
image: ^4.3.0
|
|
||||||
no_screenshot: ^0.3.1
|
# flutter_secure_storage:
|
||||||
permission_handler: ^12.0.0+1
|
# git:
|
||||||
provider: ^6.1.2
|
# url: https://github.com/juliansteenbakker/flutter_secure_storage.git
|
||||||
restart_app: ^1.3.2
|
# ref: a06ead81809c900e7fc421a30db0adf3b5919139 # from develop
|
||||||
sentry_flutter: ^9.8.0
|
# path: flutter_secure_storage/
|
||||||
app_links: ^7.0.0
|
|
||||||
in_app_purchase: ^3.2.3
|
|
||||||
|
|
||||||
|
|
||||||
# Overwritten by self-controlled repository
|
# Overwritten by self-controlled repository
|
||||||
emoji_picker_flutter: ^4.3.0
|
emoji_picker_flutter: ^4.3.0
|
||||||
|
|
||||||
# Packages which got overwritten using the twonly-app-dependencies repository
|
# Packages which got overwritten using the twonly-app-dependencies repository
|
||||||
|
restart_app: ^1.3.2
|
||||||
photo_view: ^0.15.0
|
photo_view: ^0.15.0
|
||||||
hashlib: ^2.0.0
|
hashlib: ^2.0.0
|
||||||
libsignal_protocol_dart: ^0.7.4
|
libsignal_protocol_dart: ^0.7.4
|
||||||
|
|
@ -100,6 +107,8 @@ dependencies:
|
||||||
introduction_screen: ^4.0.0
|
introduction_screen: ^4.0.0
|
||||||
qr_flutter: ^4.1.0
|
qr_flutter: ^4.1.0
|
||||||
hand_signature: ^3.0.3
|
hand_signature: ^3.0.3
|
||||||
|
flutter_sharing_intent: ^2.0.4
|
||||||
|
no_screenshot: ^0.3.1
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
dots_indicator:
|
dots_indicator:
|
||||||
|
|
@ -110,6 +119,8 @@ dependency_overrides:
|
||||||
path: ./dependencies/introduction_screen
|
path: ./dependencies/introduction_screen
|
||||||
libsignal_protocol_dart:
|
libsignal_protocol_dart:
|
||||||
path: ./dependencies/libsignal_protocol_dart
|
path: ./dependencies/libsignal_protocol_dart
|
||||||
|
flutter_sharing_intent:
|
||||||
|
path: ./dependencies/flutter_sharing_intent
|
||||||
lottie:
|
lottie:
|
||||||
path: ./dependencies/lottie
|
path: ./dependencies/lottie
|
||||||
mutex:
|
mutex:
|
||||||
|
|
@ -134,6 +145,8 @@ dependency_overrides:
|
||||||
path: ./dependencies/x25519
|
path: ./dependencies/x25519
|
||||||
qr_flutter:
|
qr_flutter:
|
||||||
path: ./dependencies/qr_flutter
|
path: ./dependencies/qr_flutter
|
||||||
|
no_screenshot:
|
||||||
|
path: ./dependencies/no_screenshot
|
||||||
camera_android_camerax:
|
camera_android_camerax:
|
||||||
# path: ../flutter-packages/packages/camera/camera_android_camerax
|
# path: ../flutter-packages/packages/camera/camera_android_camerax
|
||||||
git:
|
git:
|
||||||
|
|
@ -149,11 +162,11 @@ dependency_overrides:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/yenchieh/flutter_android_volume_keydown.git
|
url: https://github.com/yenchieh/flutter_android_volume_keydown.git
|
||||||
branch: fix/lStar-not-found-error
|
branch: fix/lStar-not-found-error
|
||||||
flutter_secure_storage_darwin:
|
# flutter_secure_storage_darwin:
|
||||||
git:
|
# git:
|
||||||
url: https://github.com/juliansteenbakker/flutter_secure_storage.git
|
# url: https://github.com/juliansteenbakker/flutter_secure_storage.git
|
||||||
ref: a06ead81809c900e7fc421a30db0adf3b5919139 # from develop
|
# ref: a06ead81809c900e7fc421a30db0adf3b5919139 # from develop
|
||||||
path: flutter_secure_storage_darwin/
|
# path: flutter_secure_storage_darwin/
|
||||||
# hardcoding the mirror mode of the VideCapture to MIRROR_MODE_ON_FRONT_ONLY
|
# hardcoding the mirror mode of the VideCapture to MIRROR_MODE_ON_FRONT_ONLY
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue