-
Notifications
You must be signed in to change notification settings - Fork 0
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
dev: Add drag and drop, fixes and review are still needed #78
Conversation
Caution Review failedThe pull request is closed. WalkthroughThe pull request introduces a new image mapping functionality across multiple files in the PhotoBook application. The changes primarily focus on adding methods to handle image mapping events, enabling drag-and-drop capabilities, and enhancing the interaction between frontend and backend image representations. The modifications span Swift, Objective-C, and header files, creating a consistent mechanism for tracking and processing images within the application's architecture. Changes
Possibly related PRs
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (8)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. 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: 3
🔭 Outside diff range comments (1)
osx/PhotoBook/PhotoBook/Photobook.h (1)
Line range hint
35-50
: Fix inconsistent method naming conventions.The interface has mixed naming conventions:
- Some methods use PascalCase:
NewProject
,RecallMetadata
- Others use camelCase:
startPhotobook
,generateProjectName
This inconsistency is noted in the TODO comment. Let's fix it by using consistent camelCase as per Objective-C conventions.
- (void) startPhotobook; - (NSString*) generateProjectName; -- (void) NewProject:(PaperSettings*)paperSettings; -- (void) RecallMetadata; +- (void) newProject:(PaperSettings*)paperSettings; +- (void) recallMetadata;
🧹 Nitpick comments (9)
osx/PhotoBook/PhotoBook/PhotobookUIListener.swift (1)
15-15
: Remove trailing semicolon to follow Swift conventions.Swift doesn't require semicolons at the end of statements. Remove it to maintain consistency with Swift idioms.
- func onImageMapped(imageId: String, image: FrontendImage) + func onImageMapped(imageId: String, image: FrontendImage)🧰 Tools
🪛 SwiftLint (0.57.0)
[Warning] 15-15: Lines should not have trailing semicolons
(trailing_semicolon)
osx/PhotoBook/PhotoBook/Wrappers/FrontendImage/FrontendImage.mm (1)
9-9
: Remove unused import.The
UniformTypeIdentifiers
framework import appears to be unused in this file.-#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
osx/PhotoBook/PhotoBook/UPL/UPLIdentifier.swift (2)
15-15
: Remove trailing semicolon to follow Swift conventions.Swift doesn't require semicolons at the end of statements.
- public var row:UInt = 0; + public var row: UInt = 0
11-22
: Add documentation for public API.Since this is a new class implementing drag & drop functionality, please add documentation comments explaining:
- The purpose of the class
- Usage examples
- Parameter descriptions
- Threading considerations
Example:
/// Represents a unique identifier for drag & drop operations in UPL (User Placement Layout). /// This class enables drag & drop functionality by implementing necessary protocols and /// providing serialization support. /// /// Example usage: /// ``` /// let identifier = UPLIdentifier(row: 1, indices: [0, 1]) /// ``` class UPLIdentifier: NSObject, Identifiable, NSItemProviderWriting, Encodable, Decodable { /// Unique identifier for the instance let id = UUID() /// The row number in the layout grid public var row: UInt = 0 /// Indices representing positions within the row public var indices: [UInt] /// Creates a new UPL identifier /// - Parameters: /// - row: The row number in the layout grid /// - indices: Array of indices representing positions within the row init(row: UInt, indices: [UInt]) { self.row = row self.indices = indices } }osx/PhotoBook/PhotoBook/Photobook.h (2)
50-50
: Add documentation for the new image mapping method.The new method
mapImagesToSPL
lacks documentation about its purpose and usage.+/** + * Maps images to the SPL (Service Placement Layout) system. + * + * @param images Dictionary mapping image identifiers to their corresponding FrontendImage objects + */ - (void) mapImagesToSPL:(NSDictionary<NSString*, FrontendImage*>*)images;
24-24
: Add documentation for the image mapping callback.The new listener method
onImageMapped
lacks documentation about when it's called and what the parameters represent.+/** + * Called when an image has been successfully mapped in the system. + * + * @param imageId Unique identifier for the mapped image + * @param image The frontend representation of the mapped image + */ - (void)onImageMapped:(NSString*)imageId image:(FrontendImage*)image;osx/PhotoBook/PhotoBook/UPL/UnstagedPhotoLine.swift (1)
39-41
: Add error handling and visual feedback for drag operation.The drag implementation needs enhancement:
- Add error handling for the index conversion to UInt
- Provide visual feedback during drag operation
.onDrag { - NSItemProvider(object: UPLIdentifier(row:0, indices:[UInt(index)])) + if index >= 0 { + let provider = NSItemProvider(object: UPLIdentifier(row:0, indices:[UInt(index)])) + withAnimation { + // Add visual feedback here + } + return provider + } + return NSItemProvider() }osx/PhotoBook/PhotoBook/Pages/PhotoBookApp.swift (2)
38-42
: Add null check and documentation for the image mapping handler.The new method follows the existing pattern but could be improved:
- Add a null check before accessing the last listener to prevent crashes
- Consider documenting the method's purpose and parameters
- Consider whether other listeners in the array should also receive this event
+ /// Notifies listeners when an image has been mapped to a specific ID + /// - Parameters: + /// - imageId: The unique identifier for the mapped image + /// - image: The frontend representation of the mapped image func onImageMapped(imageId: String, image: FrontendImage) { + guard let listener = photobookUIListener.last else { return } - photobookUIListener.last?.onImageMapped(imageId:imageId, image: image) + listener.onImageMapped(imageId:imageId, image: image) }
Line range hint
9-10
: Consider refactoring the listener implementation pattern.The current implementation using global arrays and push/pop methods has several architectural concerns:
- Global mutable state can lead to thread-safety issues and makes testing difficult
- The stack-based listener pattern might be better implemented using a proper observer pattern
- Consider moving listener management to a dedicated service class
Consider refactoring to a more robust pattern:
// Create a dedicated service class ListenerService { private var listeners = [PhotobookUIListener]() func addListener(_ listener: PhotobookUIListener) { listeners.append(listener) } func removeListener(_ listener: PhotobookUIListener) { if let index = listeners.firstIndex(where: { $0 === listener }) { listeners.remove(at: index) } } func notifyImageMapped(imageId: String, image: FrontendImage) { listeners.forEach { $0.onImageMapped(imageId: imageId, image: image) } } }Also applies to: 122-131
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
osx/PhotoBook/PhotoBook/Pages/DashboardView.swift
(1 hunks)osx/PhotoBook/PhotoBook/Pages/PhotoBookApp.swift
(2 hunks)osx/PhotoBook/PhotoBook/Pages/TableContentView.swift
(4 hunks)osx/PhotoBook/PhotoBook/Photobook.h
(3 hunks)osx/PhotoBook/PhotoBook/Photobook.mm
(3 hunks)osx/PhotoBook/PhotoBook/PhotobookUIListener.swift
(1 hunks)osx/PhotoBook/PhotoBook/UPL/UPLIdentifier.swift
(1 hunks)osx/PhotoBook/PhotoBook/UPL/UnstagedPhotoLine.swift
(2 hunks)osx/PhotoBook/PhotoBook/Wrappers/FrontendImage/FrontendImage.h
(1 hunks)osx/PhotoBook/PhotoBook/Wrappers/FrontendImage/FrontendImage.mm
(2 hunks)osx/PhotoBook/PhotoBook/Wrappers/FrontendImage/FrontendImageExtension.swift
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- osx/PhotoBook/PhotoBook/Wrappers/FrontendImage/FrontendImageExtension.swift
🧰 Additional context used
🪛 SwiftLint (0.57.0)
osx/PhotoBook/PhotoBook/PhotobookUIListener.swift
[Warning] 15-15: Lines should not have trailing semicolons
(trailing_semicolon)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Build and analyze default scheme using xcodebuild command
- GitHub Check: Build and analyze default scheme using xcodebuild command
🔇 Additional comments (8)
osx/PhotoBook/PhotoBook/Wrappers/FrontendImage/FrontendImage.h (1)
30-32
: LGTM, but needs documentation.The
unwrap
method is well-placed and follows the established pattern for C++ interop. However, please add documentation to clarify:
- The method's purpose
- Ownership semantics of the returned pointer
- Any preconditions or side effects
Let's verify the memory management implications:
✅ Verification successful
Documentation needed for unwrap method
The
unwrap
method is memory-safe as it returns ashared_ptr
-managed pointer. Please add documentation to clarify:
- Returns the underlying C++ image object
- Ownership is shared (managed by
shared_ptr
)- No preconditions required
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for memory management patterns in the codebase # Look for ownership transfer patterns rg -A 5 "unwrap.*GenericImagePtr" # Check for potential memory leaks or cleanup ast-grep --pattern 'if \($_ = [$_]unwrap\) { $$$ delete $_; $$$ }'Length of output: 112
Script:
#!/bin/bash # Find and examine the implementation file fd "FrontendImage.mm" --type f --exec cat {} # Look for similar wrapper patterns rg -g "*.h" "GenericImagePtr" -A 3 -B 3 # Look for documentation patterns in wrapper classes rg -g "*.h" "@interface.*Wrapper" -A 10Length of output: 27313
osx/PhotoBook/PhotoBook/Wrappers/FrontendImage/FrontendImage.mm (1)
38-41
: Document memory management expectations for unwrapped pointer.The
unwrap
method exposes the internal C++ pointer. Please add documentation about:
- Memory ownership expectations
- Lifetime guarantees of the returned pointer
- Thread safety considerations
This will help prevent memory-related issues when the pointer is used across language boundaries.
osx/PhotoBook/PhotoBook/UPL/UnstagedPhotoLine.swift (1)
50-50
: LGTM! Border adds clear visual distinction.The border addition improves the UI by clearly delineating the scroll view area.
osx/PhotoBook/PhotoBook/Pages/DashboardView.swift (1)
158-159
: Implement onImageMapped protocol method.The empty implementation needs to be completed to handle image mapping events properly. Consider updating the UI or state when images are mapped.
Would you like me to suggest an implementation based on the protocol requirements?
osx/PhotoBook/PhotoBook/Photobook.mm (1)
84-91
: LGTM! Clean implementation of onImageMapped.The method properly handles:
- UUID to string conversion
- FrontendImage creation from GenericImagePtr
osx/PhotoBook/PhotoBook/Pages/TableContentView.swift (3)
272-298
: LGTM! Well-structured drop implementation with proper error handling.The drop target implementation:
- Properly handles data loading and errors
- Uses unique UUIDs for image mapping
- Has appropriate error logging
322-326
: LGTM! Clean decoder implementation.The decodeData method is concise and follows Swift best practices.
374-377
: Implement onImageMapped to handle mapped images.The empty implementation should be completed to:
- Update UI state when images are mapped
- Handle any errors during mapping
Would you like me to suggest an implementation based on the application's requirements?
func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping @Sendable (Data?, (any Error)?) -> Void) -> Progress? { | ||
do { | ||
let encoder = JSONEncoder() | ||
let dataToReturn = try encoder.encode(self) | ||
completionHandler(dataToReturn, nil) | ||
} catch { | ||
completionHandler(nil, error) | ||
} | ||
return Progress(totalUnitCount: 100) | ||
} |
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.
🛠️ Refactor suggestion
Improve progress reporting and error handling.
The current implementation has several issues:
- The Progress object doesn't reflect actual work done
- No validation of the type identifier
- Error handling could be more specific
Consider this improved implementation:
func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping @Sendable (Data?, (any Error)?) -> Void) -> Progress? {
// Verify type identifier
guard typeIdentifier == UTType.plainText.identifier else {
completionHandler(nil, NSError(domain: "UPLIdentifier", code: 1, userInfo: [
NSLocalizedDescriptionKey: "Unsupported type identifier: \(typeIdentifier)"
]))
return nil
}
let progress = Progress(totalUnitCount: 100)
do {
let encoder = JSONEncoder()
progress.completedUnitCount = 50 // Encoding started
let dataToReturn = try encoder.encode(self)
progress.completedUnitCount = 100 // Encoding completed
completionHandler(dataToReturn, nil)
} catch {
completionHandler(nil, error)
}
return progress
}
- (void) mapImagesToSPL:(NSDictionary<NSString*, FrontendImage*>*)images | ||
{ | ||
auto imageToPaperService = mPhotobook->imageToPaperService(); | ||
|
||
std::unordered_map<PBDev::ImageToPaperId, PB::GenericImagePtr, | ||
boost::hash<PBDev::ImageToPaperId>> | ||
backendMap; | ||
|
||
for (NSString *key in images) { | ||
std::string uuidStr = [key UTF8String]; | ||
try { | ||
boost::uuids::string_generator gen; | ||
boost::uuids::uuid nativeUuid = gen(uuidStr); | ||
|
||
PBDev::ImageToPaperId imageId = PBDev::ImageToPaperId(nativeUuid); | ||
|
||
backendMap[imageId] = [images[key] unwrap]; | ||
|
||
} catch (const std::exception& e) { | ||
} | ||
} | ||
|
||
imageToPaperService->map( | ||
PBDev::ImageToPaperServiceId(PB::RuntimeUUID::newUUID()), backendMap); | ||
} |
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.
Add error handling and validation in mapImagesToSPL.
The implementation has several issues:
- Empty catch block silently ignores UUID parsing errors
- No validation for null images
- No error propagation to Swift layer
- (void) mapImagesToSPL:(NSDictionary<NSString*, FrontendImage*>*)images
{
+ if (!images) {
+ NSLog(@"Error: images dictionary is null");
+ return;
+ }
auto imageToPaperService = mPhotobook->imageToPaperService();
std::unordered_map<PBDev::ImageToPaperId, PB::GenericImagePtr,
boost::hash<PBDev::ImageToPaperId>>
backendMap;
for (NSString *key in images) {
+ if (!images[key]) {
+ NSLog(@"Error: null image for key %@", key);
+ continue;
+ }
std::string uuidStr = [key UTF8String];
try {
boost::uuids::string_generator gen;
boost::uuids::uuid nativeUuid = gen(uuidStr);
PBDev::ImageToPaperId imageId = PBDev::ImageToPaperId(nativeUuid);
backendMap[imageId] = [images[key] unwrap];
} catch (const std::exception& e) {
+ NSLog(@"Error parsing UUID %@: %s", key, e.what());
}
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
- (void) mapImagesToSPL:(NSDictionary<NSString*, FrontendImage*>*)images | |
{ | |
auto imageToPaperService = mPhotobook->imageToPaperService(); | |
std::unordered_map<PBDev::ImageToPaperId, PB::GenericImagePtr, | |
boost::hash<PBDev::ImageToPaperId>> | |
backendMap; | |
for (NSString *key in images) { | |
std::string uuidStr = [key UTF8String]; | |
try { | |
boost::uuids::string_generator gen; | |
boost::uuids::uuid nativeUuid = gen(uuidStr); | |
PBDev::ImageToPaperId imageId = PBDev::ImageToPaperId(nativeUuid); | |
backendMap[imageId] = [images[key] unwrap]; | |
} catch (const std::exception& e) { | |
} | |
} | |
imageToPaperService->map( | |
PBDev::ImageToPaperServiceId(PB::RuntimeUUID::newUUID()), backendMap); | |
} | |
- (void) mapImagesToSPL:(NSDictionary<NSString*, FrontendImage*>*)images | |
{ | |
if (!images) { | |
NSLog(@"Error: images dictionary is null"); | |
return; | |
} | |
auto imageToPaperService = mPhotobook->imageToPaperService(); | |
std::unordered_map<PBDev::ImageToPaperId, PB::GenericImagePtr, | |
boost::hash<PBDev::ImageToPaperId>> | |
backendMap; | |
for (NSString *key in images) { | |
if (!images[key]) { | |
NSLog(@"Error: null image for key %@", key); | |
continue; | |
} | |
std::string uuidStr = [key UTF8String]; | |
try { | |
boost::uuids::string_generator gen; | |
boost::uuids::uuid nativeUuid = gen(uuidStr); | |
PBDev::ImageToPaperId imageId = PBDev::ImageToPaperId(nativeUuid); | |
backendMap[imageId] = [images[key] unwrap]; | |
} catch (const std::exception& e) { | |
NSLog(@"Error parsing UUID %@: %s", key, e.what()); | |
} | |
} | |
imageToPaperService->map( | |
PBDev::ImageToPaperServiceId(PB::RuntimeUUID::newUUID()), backendMap); | |
} |
@@ -107,6 +112,7 @@ struct PhotoBookApp: App, PhotobookUIListener, NoirUIListener { | |||
func onMappingFinished(root: String) {} | |||
func onImageUpdated(root: String, row:UInt, index:UInt){} | |||
func onCollageThumbnailsCreated(){} | |||
func onImageMapped(imageId: String, image: FrontendImage){} |
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.
💡 Codebase verification
Remove duplicate protocol implementation
The empty onImageMapped
implementation at line 115 is redundant as PhotoBookApp
already implements this method at line 39 with proper delegation logic. Having two implementations of the same protocol method within the same type can lead to unexpected behavior.
- Remove the empty implementation at line 115 since the working implementation at line 39 already handles the protocol requirement by delegating to the last listener.
🔗 Analysis chain
Review empty implementation and verify protocol requirements.
The empty implementation raises several concerns:
- The TODO comment above suggests that
PhotobookUIListener
might not be needed in this struct - If the listener is needed, the empty implementation should be documented or handle state updates
Let's verify the protocol usage:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for PhotobookUIListener protocol definition and its usage
ast-grep --pattern 'protocol PhotobookUIListener {
$$$
}'
# Search for other implementations of onImageMapped
rg -p "func onImageMapped.*FrontendImage" -A 5
Length of output: 952
Summary by CodeRabbit
New Features
Improvements
Technical Enhancements