-
-
Notifications
You must be signed in to change notification settings - Fork 213
Share image from extension to app #447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are accessibility issues in these changes.
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughThis update implements cross-process image sharing between an iOS Share Extension and its main app container using an app group and a custom URL scheme. It introduces new entitlements, modifies the UI and control flow to load and display shared images, and updates project and configuration files to support secure data transfer and inter-app communication. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ShareExtension
participant AppGroupStorage
participant MainApp
participant AppDelegate
participant MainPage
User->>ShareExtension: Shares an image
ShareExtension->>ShareExtension: ExportImageToMainApp()
ShareExtension->>AppGroupStorage: Save image as "shared_image"
ShareExtension->>MainApp: Open custom URL (mauiapp://openFromShare)
MainApp->>AppDelegate: AppDelegate.OpenUrl(...)
AppDelegate->>AppGroupStorage: Retrieve "shared_image"
AppDelegate->>MainApp: Call LoadImage(byte[] imageData)
MainApp->>MainPage: LoadImage(byte[] imageData)
MainPage->>MainPage: Display image
Estimated code review effort🎯 4 (Complex) | ⏱️ ~35 minutes Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (10)
🚧 Files skipped from review as they are similar to previous changes (8)
🧰 Additional context used🪛 GitHub Check: Codacy Static Code AnalysisiOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs[warning] 39-39: iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs#L39 ⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (6)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
🔭 Outside diff range comments (1)
iOSExtensions/ShareExtension/log.txt (1)
1-48: Remove log file from version control.This log file should not be committed to the repository as it:
- Contains sensitive development environment information (simulator device paths)
- Will continuously change during development, causing unnecessary version control noise
- Can grow large over time
Add this file to
.gitignoreand remove it from the repository:+# Log files +*.log +log.txtConsider implementing structured logging with appropriate log levels instead of verbose console output for production code.
🧹 Nitpick comments (8)
iOSExtensions/ShareExtension/AppContainer/MainPage.xaml (2)
12-16: Improve image rendering for arbitrary sizesSetting
Aspect="AspectFit"prevents distortion when loading screenshots or photos of unknown dimensions.- <Image x:Name="Img" - Source="dotnet_bot.png" - SemanticProperties.Description="Cute dot net bot waving hi to you!" - HeightRequest="200" - HorizontalOptions="Center" /> + <Image x:Name="Img" + Source="dotnet_bot.png" + SemanticProperties.Description="Placeholder image" + HeightRequest="200" + Aspect="AspectFit" + HorizontalOptions="Center" />
18-24: Remove dead commented-out controls to keep XAML cleanIf the label/button are no longer needed, deleting them avoids noise and reduces merge-conflict surface.
- <!-- <Label Text="Click button to open Safari. Then click on Share button" - HorizontalOptions="Center"/> - - <Button - Text="Open Safari" - Clicked="OnClicked" - HorizontalOptions="Center" /> -->iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist (1)
35-45: Consider using a more specific URL scheme for security.The URL scheme
mauiappis fairly generic and could potentially be registered by other apps, leading to URL interception. Consider using a more specific scheme that includes your company or app identifier, such asvladislavantonyuk-mauiapporcom-vladislavantonyuk-container.- <key>CFBundleURLName</key> - <string>com.vladislavantonyuk.container</string> - <key>CFBundleURLSchemes</key> - <array> - <string>mauiapp</string> - </array> + <key>CFBundleURLName</key> + <string>com.vladislavantonyuk.container</string> + <key>CFBundleURLSchemes</key> + <array> + <string>com-vladislavantonyuk-container</string> + </array>iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs (1)
15-18: Remove commented code.The commented-out
OnClickedmethod should be removed rather than left in the codebase. Version control maintains the history if needed.- // private async void OnClicked(object sender, EventArgs e) - // { - // await Launcher.OpenAsync("https://vladislavantonyuk.github.io/"); - // }iOSExtensions/ShareExtension/AppContainer/App.xaml.cs (2)
5-8: Consider following standard naming conventions.While the warning suppression works, consider following standard C# naming conventions where private fields use underscore prefix. The current naming is actually correct for private fields.
You can remove the warning suppression as
_mainPagefollows standard conventions:-#pragma warning disable IDE1006 // Naming Styles private MainPage _mainPage; -#pragma warning restore IDE1006 // Naming Styles
10-12: Remove excessive blank lines.Multiple consecutive blank lines reduce code readability.
- -iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs (2)
29-35: Remove commented-out codeThe commented code adds clutter and appears to be an alternative implementation that's not being used.
69-108: Extension only processes first image attachmentThe loop iterates through all attachments but returns after processing the first image. Consider processing all images or documenting this limitation.
Would you like me to implement support for multiple image attachments?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
MauiSamples.sln(1 hunks)global.json(1 hunks)iOSExtensions/ShareExtension/AppContainer/App.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs(2 hunks)iOSExtensions/ShareExtension/log.txt(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs (3)
iOSExtensions/ShareExtension/AppContainer/MauiProgram.cs (1)
MauiProgram(3-12)iOSExtensions/ShareExtension/AppContainer/App.xaml.cs (3)
App(3-29)App(13-18)LoadImage(25-28)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs (1)
LoadImage(10-13)
iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs (1)
iOSExtensions/ShareExtension/AppContainer/App.xaml.cs (1)
LoadImage(25-28)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (6)
global.json (1)
3-3: Confirm build agents have .NET 9.0.303The patch-level bump is harmless for local dev, but CI images and hosted agents must also have 9.0.303; otherwise the build will fall back to an older SDK and ignore
allowPrerelease, giving surprising results.
Please double-check the pipeline pool or Dev Container definition.iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj (1)
8-10: Only a formatting change – looks fineThe added blank line does not affect MSBuild evaluation. No further action required.
iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist (1)
5-8: App-group entitlement added – verify it matches the provisioning profile
group.com.yourcompany.mauiappmust already exist in the Apple Developer portal and be included in both the app’s and extension’s provisioning profiles. A mismatch will cause runtime failures when accessing the shared container.iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist (1)
5-8: Consistent group ID – good, but ensure portal / profile alignmentThe group ID matches the extension’s plist, which is required. Just make sure the same entitlement is enabled for the main-app App ID and its provisioning profile before TestFlight / App Store submission.
iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs (1)
5-5: LGTM!The UIKit using statement is correctly added and necessary for the iOS-specific types used in the OpenUrl method.
MauiSamples.sln (1)
1-406: LGTM!The solution file properly includes the ShareExtension projects and maintains a well-organized structure with appropriate project nesting.
iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements image sharing functionality from an iOS Share Extension to a main MAUI app. When users share images from the iOS Photos app or screenshot editor, the extension saves the image data to a shared app group and opens the main app via a custom URL scheme. The main app then retrieves and displays the shared image.
- Added iOS Share Extension project with image processing and app group communication
- Implemented custom URL scheme handling in the main app to receive shared images
- Added app group entitlements to both extension and main app for secure data sharing
Reviewed Changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| ShareViewController.cs | Implements core image sharing logic with async processing and URL scheme launching |
| AppDelegate.cs | Handles custom URL scheme and retrieves shared image data from app group |
| MainPage.xaml.cs | Adds method to display shared images in the UI |
| Info.plist | Configures custom URL scheme for the main app |
| Entitlements.plist (both) | Enables app group access for data sharing between extension and app |
| App.xaml.cs | Manages shared MainPage instance for image display |
| log.txt | Debug logging output from extension testing |
| global.json | Updates SDK version |
| MauiSamples.sln | Adds new Visual Studio solution structure |
Comments suppressed due to low confidence (1)
iOSExtensions/ShareExtension/AppContainer/App.xaml.cs:5
- [nitpick] The pragma warning disable suggests a naming convention issue with the _mainPage field. Consider following proper C# naming conventions instead of suppressing the warning.
#pragma warning disable IDE1006 // Naming Styles
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
|
@hflexgrig thank you for the PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (6)
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs (6)
41-49: Avoid async void in override methodsUsing
async voidin an override method can lead to unhandled exceptions and unpredictable behavior.
82-82: Add return statement after setting task result to falseMissing return statement after setting task result, causing execution to continue.
84-85: Extract app group identifier to configurationThe app group identifier is hardcoded and should be configurable.
131-138: Add support for iOS versions below 18The current implementation only works on iOS 18+ and returns false for older versions, breaking the feature for most users.
150-150: Use Array.Empty() for better performanceUse
Array.Empty<NSExtensionItem>()instead ofnew NSExtensionItem[0]for better performance and consistency with modern C# practices.
106-111: Improve error handling in catch blockThe catch block has an empty implementation with just a comment, and the method returns true even when an exception occurs, masking failures from callers.
} - catch (System.Exception) + catch (System.Exception ex) { - //log ex + // Log the exception properly + System.Diagnostics.Debug.WriteLine($"Error in ExportImageToMainApp: {ex}"); + return false; } - - return true; + + return true;
🧹 Nitpick comments (2)
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs (2)
1-1: Remove unused deprecated importThe
MobileCoreServicesframework is deprecated since iOS 14 and appears to be unused in this file. The code already usesUniformTypeIdentifiersfor type checking.-using MobileCoreServices; using Social;
27-32: Remove commented placeholder codeCommented-out code should be removed. If this is intended as documentation for future implementation, consider adding it to the project documentation instead.
- //If you extend from UIViewController, instead of SLComposeServiceViewController, add image loading logic here. - // var flowControl = await ExportImageToMainApp(); - // if (!flowControl) - // { - // return; - // }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
global.json(1 hunks)iOSExtensions/ShareExtension/AppContainer/App.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
- global.json
- iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist
- iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist
- iOSExtensions/ShareExtension/AppContainer/App.xaml.cs
- iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj
- iOSExtensions/ShareExtension/AppContainer/MainPage.xaml
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Codacy Static Code Analysis
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (6)
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs (6)
41-49: Avoid async void in override methods.Using
async voidin an override method can lead to unhandled exceptions and unpredictable behavior. iOS may not wait for the async operation to complete.
70-96: Multiple unaddressed issues in image loading logic.Several previously identified issues remain unaddressed:
- Missing return statement: After
TrySetResult(false), execution continues and may callTrySetResult(true).- Hardcoded app group identifier: Should be extracted to a constant.
- Unsafe null-forgiving operator: Using
data!without proper null checking.Apply these fixes:
+private const string APP_GROUP_IDENTIFIER = "group.com.yourcompany.mauiapp"; if (itemProvider.HasItemConformingTo(UniformTypeIdentifiers.UTTypes.Image.ToString())) { itemProvider.LoadItem(UniformTypeIdentifiers.UTTypes.Image.ToString(), null, (nsObject, error) => { NSData? data = null; if (nsObject is NSUrl url)//from photos { data = NSData.FromUrl(url); } else if (nsObject is UIImage uiImage)//from screenshot editor { data = uiImage.AsPNG(); } - if (data is null) tcs.TrySetResult(false); + if (data is null) + { + tcs.TrySetResult(false); + return; + } - var userDefaults = new NSUserDefaults("group.com.yourcompany.mauiapp", NSUserDefaultsType.SuiteName); + var userDefaults = new NSUserDefaults(APP_GROUP_IDENTIFIER, NSUserDefaultsType.SuiteName); - userDefaults.SetValueForKey(data!, new NSString("shared_image")); + userDefaults.SetValueForKey(data, new NSString("shared_image"));
109-115: Improve error handling - method masks failures.The catch block doesn't properly handle errors and still returns true, which masks failures from callers.
catch (System.Exception) { //log ex + return false; } -return true;
134-141: Add support for iOS versions below 18.The current implementation only works on iOS 18+ and returns false for older versions, effectively breaking the feature for most users.
Implement the fallback:
else { - //TODO: fix for > ios18 versions - // var sel = new Selector("openURL:"); - // var result = application.PerformSelector(sel, url, 0); - // return result != null; - return false; + var sel = new ObjCRuntime.Selector("openURL:"); + var result = application.PerformSelector(sel, url, 0); + CompleteExtension(); + return result != null; }
153-153: Use Array.Empty for better performance.Use
Array.Empty<NSExtensionItem>()instead ofnew NSExtensionItem[0]for better performance and consistency with modern C# practices.-ExtensionContext?.CompleteRequest(new NSExtensionItem[0], null); +ExtensionContext?.CompleteRequest(Array.Empty<NSExtensionItem>(), null);
51-67: Critical: Missing Safari URL sharing and null safety issues.Multiple critical issues need to be addressed:
- Missing Safari URL sharing: Per PR objectives, this breaks existing Safari URL sharing functionality.
- Missing null checks: Code accesses
ExtensionContext?.InputItems[0]without verifying the array exists and has elements.Add Safari URL support and null checks:
private async Task<bool> ExportImageToMainApp() { try { var tcs = new TaskCompletionSource<bool>(); + if (ExtensionContext?.InputItems == null || ExtensionContext.InputItems.Length == 0) + { + CompleteExtension(); + return false; + } var extensionItem = ExtensionContext?.InputItems[0] as NSExtensionItem; var attachments = extensionItem?.Attachments; - if (attachments is null) + if (attachments == null || attachments.Length == 0) + { + CompleteExtension(); return false; + } - foreach (var itemProvider in attachments) + foreach (var itemProvider in attachments) { + // Handle URLs (for Safari sharing) + if (itemProvider.HasItemConformingTo(UTTypes.Url.ToString())) + { + itemProvider.LoadItem(UTTypes.Url.ToString(), null, (nsObject, error) => + { + if (nsObject is NSUrl url) + { + var userDefaults = new NSUserDefaults(APP_GROUP_IDENTIFIER, NSUserDefaultsType.SuiteName); + userDefaults.SetString(url.AbsoluteString, new NSString("shared_url")); + userDefaults.Synchronize(); + tcs.TrySetResult(true); + } + else + { + tcs.TrySetResult(false); + } + }); + continue; + } + if (itemProvider.HasItemConformingTo(UniformTypeIdentifiers.UTTypes.Image.ToString()))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
global.json(1 hunks)iOSExtensions/ShareExtension/AppContainer/App.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
- global.json
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist
- iOSExtensions/ShareExtension/AppContainer/MainPage.xaml
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs
- iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs
- iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj
- iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist
- iOSExtensions/ShareExtension/AppContainer/App.xaml.cs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (1)
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs (1)
26-32: LGTM! Helpful guidance for alternative implementation.The commented code provides clear guidance for developers who might want to extend UIViewController instead of SLComposeServiceViewController.
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Show resolved
Hide resolved
Done! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs (1)
12-12: Consider making app group identifier configurable.While using a constant is better than a magic string, the app group identifier could be made configurable through app settings or build configuration to support different environments (dev, staging, production).
Consider reading from configuration:
private static string AppGroupIdentifier => Microsoft.Maui.Controls.Application.Current?.Resources?["AppGroupIdentifier"]?.ToString() ?? "group.com.yourcompany.mauiapp";
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
global.json(1 hunks)iOSExtensions/ShareExtension/AppContainer/App.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs(2 hunks)
✅ Files skipped from review due to trivial changes (1)
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist
🚧 Files skipped from review as they are similar to previous changes (8)
- global.json
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist
- iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist
- iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs
- iOSExtensions/ShareExtension/AppContainer/MainPage.xaml
- iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj
- iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
- iOSExtensions/ShareExtension/AppContainer/App.xaml.cs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (1)
iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs (1)
10-13: Good implementation of constants!The constants are well-defined and address the previous feedback about avoiding magic strings. This improves maintainability and readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (5)
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs (5)
39-53: Async void override method still not addressed.The past review comment about avoiding
async voidin override methods remains unaddressed. This can lead to unhandled exceptions and unpredictable behavior since iOS may not wait for the async operation to complete.Consider the previously suggested approach using Task.Run or a synchronous method with completion handlers.
55-112: Safari URL sharing functionality still missing.The method only handles image attachments and doesn't support URL attachments, which breaks the Safari URL sharing functionality as mentioned in the PR objectives. This was flagged in a past review comment with specific implementation guidance.
Please implement URL handling alongside image handling to maintain backward compatibility with Safari sharing.
62-63: Missing bounds check for InputItems access.Accessing
ExtensionContext?.InputItems[0]without checking if InputItems has any elements could cause an IndexOutOfRangeException.Add a null and bounds check before accessing the first element.
87-90: Missing return statement after TrySetResult(false).The code continues execution after setting the task result to false, which could lead to unexpected behavior including calling TrySetResult(true) later.
Add a return statement after
tcs.TrySetResult(false);to prevent further execution.
146-149: Consider using Array.Empty() for better performance.The past review comment suggested using
Array.Empty<NSExtensionItem>()instead of[]for better performance and consistency with modern C# practices.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
global.json(1 hunks)iOSExtensions/ShareExtension/AppContainer/App.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs(2 hunks)
✅ Files skipped from review due to trivial changes (1)
- iOSExtensions/ShareExtension/AppContainer/MainPage.xaml
🚧 Files skipped from review as they are similar to previous changes (8)
- global.json
- iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist
- iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist
- iOSExtensions/ShareExtension/AppContainer/App.xaml.cs
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs
- iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist
🔇 Additional comments (2)
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs (2)
1-3: LGTM! UniformTypeIdentifiers using statement added correctly.This addresses the past review comment about the missing using statement for UniformTypeIdentifiers.
9-11: LGTM! Constants properly extracted from hardcoded values.This addresses past review comments about extracting the hardcoded app group identifier and other magic strings into configurable constants.
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (3)
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs (3)
39-53: Improved error handling, but async void remains a concern.The addition of try-catch-finally block with
CompleteExtension()in the finally block significantly improves error handling and ensures the extension context is always completed. However, the method remainsasync void, which can still lead to unhandled exceptions in the iOS runtime.Note: The
async voidissue from previous reviews remains, but the error handling improvements make this much more robust.
87-91: Critical: Missing return statement after TrySetResult(false).After calling
tcs.TrySetResult(false)when data is null, the code continues execution and may callTrySetResult(true)later, causing unexpected behavior.Apply this fix:
if (data is null) { tcs.TrySetResult(false); + return; }
70-100: Missing Safari URL sharing functionality.The method only handles image attachments and ignores URL attachments, breaking the existing Safari URL sharing functionality mentioned in the PR objectives. Both image and URL sharing must be supported.
Add URL handling before the image handling:
foreach (var itemProvider in attachments) { + // Handle URLs (for Safari sharing) + if (itemProvider.HasItemConformingTo(UTTypes.Url.ToString())) + { + itemProvider.LoadItem(UTTypes.Url.ToString(), null, (nsObject, _) => + { + if (nsObject is NSUrl url) + { + var userDefaults = new NSUserDefaults(AppGroupIdentifier, NSUserDefaultsType.SuiteName); + userDefaults.SetString(url.AbsoluteString, new NSString("shared_url")); + userDefaults.Synchronize(); + tcs.TrySetResult(true); + } + else + { + tcs.TrySetResult(false); + } + }); + continue; + } + if (itemProvider.HasItemConformingTo(UTTypes.Image.ToString()))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
global.json(1 hunks)iOSExtensions/ShareExtension/AppContainer/App.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml(1 hunks)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist(1 hunks)iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
- iOSExtensions/ShareExtension/AppContainer/MainPage.xaml
- global.json
- iOSExtensions/ShareExtension/AppContainer/App.xaml.cs
- iOSExtensions/ShareExtension/AppContainerExtension/Entitlements.plist
- iOSExtensions/ShareExtension/AppContainerExtension/AppContainerExtension.csproj
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Entitlements.plist
- iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs
- iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/Info.plist
🧰 Additional context used
🧬 Code Graph Analysis (1)
iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs (3)
iOSExtensions/ShareExtension/AppContainer/MauiProgram.cs (1)
MauiProgram(3-12)iOSExtensions/ShareExtension/AppContainer/App.xaml.cs (3)
App(3-22)App(7-11)LoadImage(18-21)iOSExtensions/ShareExtension/AppContainer/MainPage.xaml.cs (1)
LoadImage(10-13)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (4)
iOSExtensions/ShareExtension/AppContainer/Platforms/iOS/AppDelegate.cs (1)
5-14: LGTM! Constants properly defined.The addition of the UIKit using statement and private constants for URL scheme, host, app group identifier, and shared image key addresses previous feedback about avoiding magic strings. The constant names follow proper naming conventions.
iOSExtensions/ShareExtension/AppContainerExtension/ShareViewController.cs (3)
1-12: LGTM! Using statements and constants properly defined.The addition of the
UniformTypeIdentifiersusing statement and extraction of hardcoded values to constants addresses previous feedback. The constant names follow proper conventions and improve maintainability.
115-147: LGTM! Excellent responder chain traversal and iOS version handling.The implementation properly:
- Traverses the responder chain to find UIApplication
- Handles iOS 18+ with modern API
- Provides fallback for iOS < 18 using selector
- Calls
CompleteExtension()in both code paths- Uses constant for maximum attempts to prevent infinite loops
149-152: LGTM! Clean encapsulation of extension completion.The method properly encapsulates the extension context completion logic and uses the modern empty array literal syntax.
|
@VladislavAntonyuk only one "issue" remains from code analizers, but it not really an issue! |
4dba16f
into
VladislavAntonyuk:main
Uses app group to store image data from extension, opens the main app by custom url scheme, and the main app reads and displays image (from photos or screenshot editor)
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores