feat(share_extension): integrate share_handler package and implement share functionality with updated permissions and entitlements

This commit is contained in:
cogwheel0
2025-08-28 12:59:48 +05:30
parent fc4b10b1f2
commit 4a524d404e
15 changed files with 676 additions and 26 deletions

View File

@@ -3,7 +3,9 @@
<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"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
<!-- Background streaming permissions --> <!-- Background streaming permissions -->
@@ -44,6 +46,28 @@
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
<!-- Receive shares: text, single/multiple files, images -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</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="*/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity> </activity>
<!-- Background streaming service --> <!-- Background streaming service -->
@@ -61,4 +85,4 @@
</application> </application>
<!-- Queries for speech recognition removed; using server transcription --> <!-- Queries for speech recognition removed; using server transcription -->
</manifest> </manifest>

View File

@@ -1,9 +1,12 @@
# Uncomment this line to define a global platform for your project # Uncomment this line to define a global platform for your project
# platform :ios, '13.0' platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'
# Work around Xcode cycle false-positives by letting CocoaPods not declare IO paths
install! 'cocoapods', :disable_input_output_paths => true
project 'Runner', { project 'Runner', {
'Debug' => :debug, 'Debug' => :debug,
'Profile' => :release, 'Profile' => :release,
@@ -28,9 +31,19 @@ require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelpe
flutter_ios_podfile_setup flutter_ios_podfile_setup
target 'Runner' do target 'Runner' do
use_frameworks! # Prefer static frameworks to avoid Xcode embed-cycles with app extensions
use_frameworks! :linkage => :static
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
# share_handler addition start
target 'ShareExtension' do
inherit! :search_paths
# Only models are needed in extension to avoid app-only APIs
pod "share_handler_ios_models", :path => ".symlinks/plugins/share_handler_ios/ios/Models"
end
# share_handler addition end
target 'RunnerTests' do target 'RunnerTests' do
inherit! :search_paths inherit! :search_paths
end end
@@ -40,4 +53,15 @@ post_install do |installer|
installer.pods_project.targets.each do |target| installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target) flutter_additional_ios_build_settings(target)
end end
# Reduce chances of embed/cycle: don't embed Swift stdlib explicitly
installer.aggregate_targets.each do |aggregate_target|
aggregate_target.user_project.native_targets.each do |native_target|
if ['Runner', 'ShareExtension'].include?(native_target.name)
native_target.build_configurations.each do |config|
config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = 'NO'
end
end
end
end
end end

View File

@@ -50,6 +50,14 @@ PODS:
- SDWebImage (5.21.1): - SDWebImage (5.21.1):
- SDWebImage/Core (= 5.21.1) - SDWebImage/Core (= 5.21.1)
- SDWebImage/Core (5.21.1) - SDWebImage/Core (5.21.1)
- share_handler_ios (0.0.14):
- Flutter
- share_handler_ios/share_handler_ios_models (= 0.0.14)
- share_handler_ios_models
- share_handler_ios/share_handler_ios_models (0.0.14):
- Flutter
- share_handler_ios_models
- share_handler_ios_models (0.0.9)
- share_plus (0.0.1): - share_plus (0.0.1):
- Flutter - Flutter
- shared_preferences_foundation (0.0.1): - shared_preferences_foundation (0.0.1):
@@ -75,6 +83,8 @@ DEPENDENCIES:
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- record_ios (from `.symlinks/plugins/record_ios/ios`) - record_ios (from `.symlinks/plugins/record_ios/ios`)
- share_handler_ios (from `.symlinks/plugins/share_handler_ios/ios`)
- share_handler_ios_models (from `.symlinks/plugins/share_handler_ios/ios/Models`)
- share_plus (from `.symlinks/plugins/share_plus/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
@@ -106,6 +116,10 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/path_provider_foundation/darwin" :path: ".symlinks/plugins/path_provider_foundation/darwin"
record_ios: record_ios:
:path: ".symlinks/plugins/record_ios/ios" :path: ".symlinks/plugins/record_ios/ios"
share_handler_ios:
:path: ".symlinks/plugins/share_handler_ios/ios"
share_handler_ios_models:
:path: ".symlinks/plugins/share_handler_ios/ios/Models"
share_plus: share_plus:
:path: ".symlinks/plugins/share_plus/ios" :path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation: shared_preferences_foundation:
@@ -131,6 +145,8 @@ SPEC CHECKSUMS:
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
record_ios: fee1c924aa4879b882ebca2b4bce6011bcfc3d8b record_ios: fee1c924aa4879b882ebca2b4bce6011bcfc3d8b
SDWebImage: f29024626962457f3470184232766516dee8dfea SDWebImage: f29024626962457f3470184232766516dee8dfea
share_handler_ios: e2244e990f826b2c8eaa291ac3831569438ba0fb
share_handler_ios_models: fc638c9b4330dc7f082586c92aee9dfa0b87b871
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
@@ -139,6 +155,6 @@ SPEC CHECKSUMS:
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556 wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e PODFILE CHECKSUM: df88575cf61e98a1a3edf2f8c887dad2c18c2079
COCOAPODS: 1.16.2 COCOAPODS: 1.16.2

View File

@@ -11,11 +11,13 @@
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 */; };
4A7698E95402502ED3A27D07 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E21C32C282E5A003D094A6E9 /* Pods_RunnerTests.framework */; }; 4A7698E95402502ED3A27D07 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E21C32C282E5A003D094A6E9 /* Pods_RunnerTests.framework */; };
5318C41BD6012F73B0A81F8D /* Pods_ShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15F5EAC162214F437B9D5305 /* Pods_ShareExtension.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
B26D75F4FE6FFABCFAC07E43 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BA04FBA3F37D0A688CFEFA7 /* Pods_Runner.framework */; }; B26D75F4FE6FFABCFAC07E43 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BA04FBA3F37D0A688CFEFA7 /* Pods_Runner.framework */; };
F1DBCF1D2E601A39004C2540 /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = F1DBCF132E601A39004C2540 /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@@ -26,6 +28,13 @@
remoteGlobalIDString = 97C146ED1CF9000F007C117D; remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner; remoteInfo = Runner;
}; };
F1DBCF1B2E601A39004C2540 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = F1DBCF122E601A39004C2540;
remoteInfo = ShareExtension;
};
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
@@ -39,19 +48,34 @@
name = "Embed Frameworks"; name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
F1DBCF1E2E601A39004C2540 /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
F1DBCF1D2E601A39004C2540 /* ShareExtension.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
0BA04FBA3F37D0A688CFEFA7 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 0BA04FBA3F37D0A688CFEFA7 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; };
15F5EAC162214F437B9D5305 /* Pods_ShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1EB0E6D3737F83B935118E8E /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; }; 1EB0E6D3737F83B935118E8E /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
20A55D0FD9E7CFD1B9BBBEED /* 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>"; }; 20A55D0FD9E7CFD1B9BBBEED /* 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>"; };
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; };
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>"; };
69671B6B1959FCF16D21E200 /* 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>"; };
71EEBC62F9F81EB3FD345FA2 /* 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>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
F1DBCF292E602000004C2540 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
837A0EFB28C7ACD7FF14EC67 /* 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>"; }; 837A0EFB28C7ACD7FF14EC67 /* 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>"; };
838ED4921F9222D50ECF498B /* 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>"; }; 838ED4921F9222D50ECF498B /* 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>"; };
@@ -64,9 +88,37 @@
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>"; };
B60F6CBA44A303DE5389649E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; }; B60F6CBA44A303DE5389649E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
B6CA85D4EC683E94C2FB2A88 /* 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>"; }; B6CA85D4EC683E94C2FB2A88 /* 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>"; };
C9F5BA8D70297B37D581AE50 /* 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>"; };
E21C32C282E5A003D094A6E9 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E21C32C282E5A003D094A6E9 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F1DBCF132E601A39004C2540 /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
F1DBCF242E601A7C004C2540 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
F1DBCF222E601A39004C2540 /* Exceptions for "ShareExtension" folder in "ShareExtension" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
);
target = F1DBCF122E601A39004C2540 /* ShareExtension */;
};
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
F1DBCF142E601A39004C2540 /* ShareExtension */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
F1DBCF222E601A39004C2540 /* Exceptions for "ShareExtension" folder in "ShareExtension" target */,
);
explicitFileTypes = {
};
explicitFolders = (
);
path = ShareExtension;
sourceTree = "<group>";
};
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
3F0B71E2AB4D863902C09B3E /* Frameworks */ = { 3F0B71E2AB4D863902C09B3E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
@@ -84,6 +136,14 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
F1DBCF102E601A39004C2540 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5318C41BD6012F73B0A81F8D /* Pods_ShareExtension.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
@@ -100,6 +160,7 @@
children = ( children = (
0BA04FBA3F37D0A688CFEFA7 /* Pods_Runner.framework */, 0BA04FBA3F37D0A688CFEFA7 /* Pods_Runner.framework */,
E21C32C282E5A003D094A6E9 /* Pods_RunnerTests.framework */, E21C32C282E5A003D094A6E9 /* Pods_RunnerTests.framework */,
15F5EAC162214F437B9D5305 /* Pods_ShareExtension.framework */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -113,6 +174,9 @@
B6CA85D4EC683E94C2FB2A88 /* Pods-RunnerTests.debug.xcconfig */, B6CA85D4EC683E94C2FB2A88 /* Pods-RunnerTests.debug.xcconfig */,
837A0EFB28C7ACD7FF14EC67 /* Pods-RunnerTests.release.xcconfig */, 837A0EFB28C7ACD7FF14EC67 /* Pods-RunnerTests.release.xcconfig */,
1EB0E6D3737F83B935118E8E /* Pods-RunnerTests.profile.xcconfig */, 1EB0E6D3737F83B935118E8E /* Pods-RunnerTests.profile.xcconfig */,
71EEBC62F9F81EB3FD345FA2 /* Pods-ShareExtension.debug.xcconfig */,
69671B6B1959FCF16D21E200 /* Pods-ShareExtension.release.xcconfig */,
C9F5BA8D70297B37D581AE50 /* Pods-ShareExtension.profile.xcconfig */,
); );
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -133,6 +197,7 @@
children = ( children = (
9740EEB11CF90186004384FC /* Flutter */, 9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
F1DBCF142E601A39004C2540 /* ShareExtension */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */, 331C8082294A63A400263BE5 /* RunnerTests */,
8C43905FA2E52A883F49D605 /* Pods */, 8C43905FA2E52A883F49D605 /* Pods */,
@@ -145,6 +210,7 @@
children = ( children = (
97C146EE1CF9000F007C117D /* Runner.app */, 97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */, 331C8081294A63A400263BE5 /* RunnerTests.xctest */,
F1DBCF132E601A39004C2540 /* ShareExtension.appex */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -152,6 +218,7 @@
97C146F01CF9000F007C117D /* Runner */ = { 97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F1DBCF242E601A7C004C2540 /* Runner.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
@@ -194,20 +261,43 @@
9740EEB61CF901F6004384FC /* Run Script */, 9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */, 97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */, 97C146EB1CF9000F007C117D /* Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
97C146EC1CF9000F007C117D /* Resources */, 97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */, 9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */, F1DBCF1E2E601A39004C2540 /* Embed Foundation Extensions */,
4F34859EAFDCA9A40F09ECFF /* [CP] Embed Pods Frameworks */, AA915538CD255B5C833E6AB7 /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
dependencies = ( dependencies = (
F1DBCF1C2E601A39004C2540 /* PBXTargetDependency */,
); );
name = Runner; name = Runner;
productName = Runner; productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application"; productType = "com.apple.product-type.application";
}; };
F1DBCF122E601A39004C2540 /* ShareExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = F1DBCF232E601A39004C2540 /* Build configuration list for PBXNativeTarget "ShareExtension" */;
buildPhases = (
5A0A281EDF7C33D1547603FC /* [CP] Check Pods Manifest.lock */,
F1DBCF0F2E601A39004C2540 /* Sources */,
F1DBCF102E601A39004C2540 /* Frameworks */,
F1DBCF112E601A39004C2540 /* Resources */,
);
buildRules = (
);
dependencies = (
);
fileSystemSynchronizedGroups = (
F1DBCF142E601A39004C2540 /* ShareExtension */,
);
name = ShareExtension;
productName = ShareExtension;
productReference = F1DBCF132E601A39004C2540 /* ShareExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */ /* End PBXNativeTarget section */
/* Begin PBXProject section */ /* Begin PBXProject section */
@@ -215,6 +305,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
BuildIndependentTargetsInParallel = YES; BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1640;
LastUpgradeCheck = 1510; LastUpgradeCheck = 1510;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
@@ -226,6 +317,9 @@
CreatedOnToolsVersion = 7.3.1; CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100; LastSwiftMigration = 1100;
}; };
F1DBCF122E601A39004C2540 = {
CreatedOnToolsVersion = 16.4;
};
}; };
}; };
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
@@ -243,6 +337,7 @@
targets = ( targets = (
97C146ED1CF9000F007C117D /* Runner */, 97C146ED1CF9000F007C117D /* Runner */,
331C8080294A63A400263BE5 /* RunnerTests */, 331C8080294A63A400263BE5 /* RunnerTests */,
F1DBCF122E601A39004C2540 /* ShareExtension */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
@@ -260,12 +355,18 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
F1DBCF112E601A39004C2540 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
@@ -276,7 +377,7 @@
files = ( files = (
); );
inputPaths = ( inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
); );
name = "Thin Binary"; name = "Thin Binary";
outputPaths = ( outputPaths = (
@@ -285,21 +386,26 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
}; };
4F34859EAFDCA9A40F09ECFF /* [CP] Embed Pods Frameworks */ = { 5A0A281EDF7C33D1547603FC /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
); );
name = "[CP] Embed Pods Frameworks"; inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", );
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-ShareExtension-checkManifestLockResult.txt",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 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; showEnvVarsInLog = 0;
}; };
9740EEB61CF901F6004384FC /* Run Script */ = { 9740EEB61CF901F6004384FC /* Run Script */ = {
@@ -317,6 +423,21 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
}; };
AA915538CD255B5C833E6AB7 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
B2C308F843502D753F643BC6 /* [CP] Check Pods Manifest.lock */ = { B2C308F843502D753F643BC6 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@@ -381,6 +502,13 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
F1DBCF0F2E601A39004C2540 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */ /* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */ /* Begin PBXTargetDependency section */
@@ -389,6 +517,11 @@
target = 97C146ED1CF9000F007C117D /* Runner */; target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
}; };
F1DBCF1C2E601A39004C2540 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = F1DBCF122E601A39004C2540 /* ShareExtension */;
targetProxy = F1DBCF1B2E601A39004C2540 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */ /* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */ /* Begin PBXVariantGroup section */
@@ -467,8 +600,10 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
@@ -655,8 +790,10 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
@@ -683,8 +820,10 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
@@ -706,6 +845,129 @@
}; };
name = Release; name = Release;
}; };
F1DBCF1F2E601A39004C2540 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 71EEBC62F9F81EB3FD345FA2 /* Pods-ShareExtension.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = X2662V5DT2;
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 = 14.0;
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 = app.cogwheel.conduit.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
F1DBCF202E601A39004C2540 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 69671B6B1959FCF16D21E200 /* Pods-ShareExtension.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = X2662V5DT2;
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 = 14.0;
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 = app.cogwheel.conduit.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
F1DBCF212E601A39004C2540 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C9F5BA8D70297B37D581AE50 /* Pods-ShareExtension.profile.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = X2662V5DT2;
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 = 14.0;
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 = app.cogwheel.conduit.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Profile;
};
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
@@ -739,6 +1001,16 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
F1DBCF232E601A39004C2540 /* Build configuration list for PBXNativeTarget "ShareExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F1DBCF1F2E601A39004C2540 /* Debug */,
F1DBCF202E601A39004C2540 /* Release */,
F1DBCF212E601A39004C2540 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */ /* End XCConfigurationList section */
}; };
rootObject = 97C146E61CF9000F007C117D /* Project object */; rootObject = 97C146E61CF9000F007C117D /* Project object */;

View File

@@ -73,5 +73,18 @@
<true/> <true/>
<key>UIStatusBarHidden</key> <key>UIStatusBarHidden</key>
<false/> <false/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>app.cogwheel.conduit.share</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ShareMedia-app.cogwheel.conduit</string>
</array>
</dict>
</array>
</dict> </dict>
</plist> </plist>

View 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.app.cogwheel.conduit</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,47 @@
<?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>
<!-- Uncomment below lines if you want to use a custom group id rather than the default. Set it in Build Settings -> User-Defined -->
<!-- <key>AppGroupId</key>
<string>$(CUSTOM_GROUP_ID)</string> -->
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<!-- Add supported message intent if you support sharing to a specific conversation - start -->
<key>IntentsSupported</key>
<array>
<string>INSendMessageIntent</string>
</array>
<!-- Add supported message intent if you support sharing to a specific conversation (registered via the recordSentMessage api call) - end -->
<key>NSExtensionActivationRule</key>
<!-- Comment or delete the TRUEPREDICATE NSExtensionActivationRule that only works in development mode -->
<!-- <string>TRUEPREDICATE</string> -->
<!-- Add a new NSExtensionActivationRule. The rule below will allow sharing one or more file of any type, url, or text content, You can modify these rules to your liking for which types of share content, as well as how many your app can handle -->
<dict>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<integer>10</integer>
<key>NSExtensionActivationSupportsMovieWithMaxCount</key>
<integer>10</integer>
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
<integer>10</integer>
<key>NSExtensionActivationSupportsText</key>
<true/>
</dict>
<key>PHSupportedMediaTypes</key>
<array>
<string>Video</string>
<string>Image</string>
</array>
</dict>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).ShareViewController</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
</dict>
</dict>
</plist>

View File

@@ -3,6 +3,8 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.security.application-groups</key> <key>com.apple.security.application-groups</key>
<array/> <array>
<string>group.app.cogwheel.conduit</string>
</array>
</dict> </dict>
</plist> </plist>

View File

@@ -0,0 +1,3 @@
import share_handler_ios_models
class ShareViewController: ShareHandlerIosViewController {}

View File

@@ -0,0 +1,172 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:share_handler/share_handler.dart' as sh;
import '../../features/auth/providers/unified_auth_providers.dart';
import '../../features/chat/providers/chat_providers.dart';
import '../../features/chat/services/file_attachment_service.dart';
import '../../core/providers/app_providers.dart';
/// Lightweight payload for a share event
class SharedPayload {
final String? text;
final List<String> filePaths;
const SharedPayload({this.text, this.filePaths = const []});
bool get hasAnything =>
(text != null && text!.trim().isNotEmpty) || filePaths.isNotEmpty;
}
/// Holds a pending shared payload until the app is ready (e.g., authed + model loaded)
final pendingSharedPayloadProvider = StateProvider<SharedPayload?>((_) => null);
/// Initializes listening to OS share intents and handles them
final shareReceiverInitializerProvider = Provider<void>((ref) {
// Do nothing on web/desktop
if (kIsWeb) return;
final sub = StreamController<SharedPayload>.broadcast();
// Listen for app readiness: authenticated and model available
void maybeProcessPending() {
final navState = ref.read(authNavigationStateProvider);
final model = ref.read(selectedModelProvider);
final pending = ref.read(pendingSharedPayloadProvider);
if (pending != null &&
pending.hasAnything &&
navState == AuthNavigationState.authenticated &&
model != null) {
_processPayload(ref, pending);
ref.read(pendingSharedPayloadProvider.notifier).state = null;
}
}
// React when auth/model changes to process a queued share
ref.listen<AuthNavigationState>(
authNavigationStateProvider,
(_, __) => maybeProcessPending(),
);
ref.listen(selectedModelProvider, (_, __) => maybeProcessPending());
// Hook into share_handler
final handler = sh.ShareHandler.instance;
// Handle initial share when app is cold-started via Share
Future.microtask(() async {
try {
final dynamic media = await handler.getInitialSharedMedia();
final payload = _toPayload(media);
if (payload.hasAnything) {
ref.read(pendingSharedPayloadProvider.notifier).state = payload;
maybeProcessPending();
}
} catch (e) {
debugPrint('ShareReceiver: failed to get initial shared media: $e');
}
});
// Handle subsequent shares while app is alive
final streamSub = handler.sharedMediaStream.listen((dynamic media) {
try {
final payload = _toPayload(media);
if (payload.hasAnything) {
ref.read(pendingSharedPayloadProvider.notifier).state = payload;
maybeProcessPending();
}
} catch (e) {
debugPrint('ShareReceiver: failed to parse shared media: $e');
}
});
// Ensure cleanup
ref.onDispose(() async {
await streamSub.cancel();
await sub.close();
});
});
SharedPayload _toPayload(dynamic media) {
if (media == null) return const SharedPayload();
String? text;
final filePaths = <String>[];
try {
// Common field in share_handler: `content` (String?)
text = (media as dynamic).content as String?;
} catch (_) {
try {
// Some plugins use `text`
text = (media as dynamic).text as String?;
} catch (_) {}
}
try {
final list = (media as dynamic).attachments as List<dynamic>?;
if (list != null) {
for (final att in list) {
try {
final p = (att as dynamic).path as String?;
if (p != null && p.isNotEmpty) filePaths.add(p);
} catch (_) {
// Ignore a malformed entry
}
}
}
} catch (_) {
// Older plugins may call it files
try {
final list = (media as dynamic).files as List<dynamic>?;
if (list != null) {
for (final att in list) {
try {
final p = (att as dynamic).path as String?;
if (p != null && p.isNotEmpty) filePaths.add(p);
} catch (_) {}
}
}
} catch (_) {}
}
return SharedPayload(text: text, filePaths: filePaths);
}
Future<void> _processPayload(Ref ref, SharedPayload payload) async {
try {
// Start a fresh chat context but do NOT auto-send
startNewChat(ref);
// Prefer attaching files to the composer so user can add text before sending
if (payload.filePaths.isNotEmpty) {
final svc = ref.read(fileAttachmentServiceProvider);
if (svc != null) {
// Add files to attachment list and kick off uploads, mirroring UI flow
final files = payload.filePaths.map((p) => File(p)).toList();
if (files.isNotEmpty) {
ref.read(attachedFilesProvider.notifier).addFiles(files);
for (final file in files) {
final uploadStream = svc.uploadFile(file);
uploadStream.listen((state) {
ref
.read(attachedFilesProvider.notifier)
.updateFileState(file.path, state);
}, onError: (_) {});
}
}
}
}
// Prefill text in the composer (do not auto-send)
final text = payload.text?.trim();
if (text != null && text.isNotEmpty) {
ref.read(prefilledInputTextProvider.notifier).state = text;
}
// This allows the user to add a caption before sending
} catch (e) {
debugPrint('ShareReceiver: failed to process payload: $e');
}
}

View File

@@ -21,6 +21,9 @@ final chatMessagesProvider =
// Loading state for conversation (used to show chat skeletons during fetch) // Loading state for conversation (used to show chat skeletons during fetch)
final isLoadingConversationProvider = StateProvider<bool>((ref) => false); final isLoadingConversationProvider = StateProvider<bool>((ref) => false);
// Prefilled input text (e.g., when sharing text from other apps)
final prefilledInputTextProvider = StateProvider<String?>((ref) => null);
class ChatMessagesNotifier extends StateNotifier<List<ChatMessage>> { class ChatMessagesNotifier extends StateNotifier<List<ChatMessage>> {
final Ref _ref; final Ref _ref;
StreamSubscription? _messageStream; StreamSubscription? _messageStream;
@@ -453,6 +456,16 @@ Future<void> sendMessage(
await _sendMessageInternal(ref, message, attachments, toolIds); await _sendMessageInternal(ref, message, attachments, toolIds);
} }
// Service-friendly wrapper (accepts generic Ref)
Future<void> sendMessageFromService(
Ref ref,
String message,
List<String>? attachments, [
List<String>? toolIds,
]) async {
await _sendMessageInternal(ref, message, attachments, toolIds);
}
// Internal send message implementation // Internal send message implementation
Future<void> _sendMessageInternal( Future<void> _sendMessageInternal(
dynamic ref, dynamic ref,

View File

@@ -185,6 +185,20 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
vsync: this, vsync: this,
); );
// Listen for prefilled text updates (e.g., from share intent)
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
final text = ref.read(prefilledInputTextProvider);
if (text != null && text.isNotEmpty) {
_controller.text = text;
_controller.selection = TextSelection.collapsed(offset: text.length);
// Clear after applying so it doesn't re-apply on rebuilds
ref.read(prefilledInputTextProvider.notifier).state = null;
_ensureFocusedIfEnabled();
if (!_isExpanded) _setExpanded(true);
}
});
// Listen for text changes and update only when emptiness flips // Listen for text changes and update only when emptiness flips
_controller.addListener(() { _controller.addListener(() {
final has = _controller.text.trim().isNotEmpty; final has = _controller.text.trim().isNotEmpty;
@@ -878,8 +892,8 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
color: isActive color: isActive
? context.conduitTheme.buttonPrimary ? context.conduitTheme.buttonPrimary
: showBackground : showBackground
? context.conduitTheme.cardBorder ? context.conduitTheme.cardBorder
: Colors.transparent, : Colors.transparent,
width: BorderWidth.regular, width: BorderWidth.regular,
), ),
), ),
@@ -898,8 +912,8 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
color: isActive color: isActive
? context.conduitTheme.buttonPrimary ? context.conduitTheme.buttonPrimary
: showBackground : showBackground
? context.conduitTheme.cardBackground ? context.conduitTheme.cardBackground
: Colors.transparent, : Colors.transparent,
borderRadius: BorderRadius.circular(AppBorderRadius.xl), borderRadius: BorderRadius.circular(AppBorderRadius.xl),
boxShadow: (isActive || showBackground) boxShadow: (isActive || showBackground)
? ConduitShadows.button ? ConduitShadows.button
@@ -910,11 +924,13 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
size: iconSize ?? IconSize.medium, size: iconSize ?? IconSize.medium,
color: widget.enabled color: widget.enabled
? (isActive ? (isActive
? context.conduitTheme.buttonPrimaryText ? context.conduitTheme.buttonPrimaryText
: context.conduitTheme.textPrimary : context.conduitTheme.textPrimary.withValues(
.withValues(alpha: Alpha.strong)) alpha: Alpha.strong,
: context.conduitTheme.textPrimary ))
.withValues(alpha: Alpha.disabled), : context.conduitTheme.textPrimary.withValues(
alpha: Alpha.disabled,
),
), ),
), ),
), ),
@@ -954,8 +970,9 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
decoration: BoxDecoration( decoration: BoxDecoration(
// Subtle primary tint when active for clearer affordance // Subtle primary tint when active for clearer affordance
color: isActive color: isActive
? context.conduitTheme.buttonPrimary ? context.conduitTheme.buttonPrimary.withValues(
.withValues(alpha: Alpha.buttonHover + 0.04) alpha: Alpha.buttonHover + 0.04,
)
: context.conduitTheme.cardBackground, : context.conduitTheme.cardBackground,
borderRadius: BorderRadius.circular(AppBorderRadius.xl), borderRadius: BorderRadius.circular(AppBorderRadius.xl),
// No elevation to match modal chips // No elevation to match modal chips

View File

@@ -18,6 +18,7 @@ import 'features/onboarding/views/onboarding_sheet.dart';
import 'package:conduit/l10n/app_localizations.dart'; import 'package:conduit/l10n/app_localizations.dart';
import 'features/chat/views/chat_page.dart'; import 'features/chat/views/chat_page.dart';
import 'features/navigation/views/splash_launcher_page.dart'; import 'features/navigation/views/splash_launcher_page.dart';
import 'core/services/share_receiver_service.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
@@ -66,6 +67,9 @@ class _ConduitAppState extends ConsumerState<ConduitApp> {
// Ensure API service auth integration is active // Ensure API service auth integration is active
ref.read(authApiIntegrationProvider); ref.read(authApiIntegrationProvider);
// Initialize OS share receiver so users can share text/files to Conduit
ref.read(shareReceiverInitializerProvider);
} }
@override @override

View File

@@ -973,6 +973,38 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.0.1"
share_handler:
dependency: "direct main"
description:
name: share_handler
sha256: "0a6d007f0e44fbee27164adcd159ecbc88238864313f4e5c58161cae2180328d"
url: "https://pub.dev"
source: hosted
version: "0.0.25"
share_handler_android:
dependency: transitive
description:
name: share_handler_android
sha256: caf555b933dc72783aa37fef75688c7b86bd6f7bc17d80fbf585bc42f123cc8d
url: "https://pub.dev"
source: hosted
version: "0.0.11"
share_handler_ios:
dependency: transitive
description:
name: share_handler_ios
sha256: cdc21f88f336a944157a8e9ceb191525cee3b082d6eb6c2082488e4f09dc3ece
url: "https://pub.dev"
source: hosted
version: "0.0.15"
share_handler_platform_interface:
dependency: transitive
description:
name: share_handler_platform_interface
sha256: "7a4df95a87b326b2f07458d937f2281874567c364b7b7ebe4e7d50efaae5f106"
url: "https://pub.dev"
source: hosted
version: "0.0.6"
share_plus: share_plus:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@@ -55,6 +55,7 @@ dependencies:
freezed_annotation: ^3.0.0 freezed_annotation: ^3.0.0
wakelock_plus: ^1.2.10 wakelock_plus: ^1.2.10
share_plus: ^11.1.0 share_plus: ^11.1.0
share_handler: ^0.0.19
# Clipboard functionality is available through flutter/services (part of Flutter SDK) # Clipboard functionality is available through flutter/services (part of Flutter SDK)