iOS: attach arbitrary files via a unified photo/file menu#12
Open
ehs208 wants to merge 8 commits into
Open
Conversation
Adds a unified "+" attach menu (사진 / 파일) to the workspace input bar. The 파일 path opens a document picker (all file types), reads the bytes, and reuses the existing generic file.upload RPC + appendPathToDraft flow — saving to ~/Downloads/cmux-remote/ with a timestamp-prefixed filename and inserting the Mac path into the draft. iOS-only; relay unchanged. Co-Authored-By: Claude Opus 4.8 <[email protected]>
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Pure filename-sanitize / timestamp-prefix / MIME-inference helpers, unit tested. Verified via swift CLI harness (10/10) since the iOS simulator platform is unavailable in this environment; XCTest run deferred to Xcode. Co-Authored-By: Claude Opus 4.8 <[email protected]>
Replace the photo-only button with a '+' menu (사진/파일). The 파일 path opens a document picker (all types), reads bytes, and reuses the existing file.upload RPC + appendPathToDraft flow with a timestamp-prefixed filename. 12 MiB pre-check; existing photo flow unchanged. Updates the smoke UI test's attach-button accessibility id. Co-Authored-By: Claude Opus 4.8 <[email protected]>
`swift build -c release` failed to compile InboxNotification.swift: error: the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions The `body` value was built from a long `??` chain mixing `stringValue(for:)` and `nestedStringValue(...)`. Because `??` is an overloaded operator, a chain that long makes the Swift type-checker explore too many overload combinations and time out. Introduce a `firstStringValue(forAny:)` helper that returns the first non-empty string among a list of keys, and use it to collapse the long `??` chains for workspaceId, title, body, surfaceId, id, subtitle, and threadId. Key ordering (first match wins) is preserved, so behavior is unchanged. Release build and all 37 SharedKitTests pass. Co-Authored-By: Claude Opus 4.8 <[email protected]>
The relay's uniqueFilename was written for the photo flow and mishandled non-image files: - extensionless names (Dockerfile, Makefile) got a bogus ".jpg" appended because fileExtension() defaulted to jpg for any non-png/heic MIME; - an empty client name leaked the relay's cwd via URL(fileURLWithPath:""). Now the relay respects the client filename verbatim (no forced extension), synthesizes "upload.<ext>" (extension derived from MIME via UTType) only when no usable name is given, and sanitizes with NSString.lastPathComponent. iOS drops its now-redundant timestamp prefix (the relay owns the single timestamp) and reads file bytes off the MainActor. Adds relay tests for extensionless / non-image / blank-name cases (4/4). relay: 52 XCTest pass; iOS logic verified via swift CLI (8/8). Co-Authored-By: Claude Opus 4.8 <[email protected]>
Co-Authored-By: Claude Opus 4.8 <[email protected]>
CommandComposer.failSubmit renders errors via String(describing:), which uses CustomStringConvertible.description, not LocalizedError.errorDescription. Conform AttachmentError to CustomStringConvertible so the friendly Korean message shows instead of the raw enum case dump. Also cross-reference the 12 MiB cap constant with the relay's maxBytes. Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
📝 WalkthroughWalkthroughThe PR adds iOS document-file attachments with sanitized naming, MIME detection, size validation, relay upload integration, and updated UI tests. Relay filename generation preserves non-image names. Inbox notifications now extract the first non-empty value from alternative payload keys. ChangesFile Attachment Flow
Inbox Notification Parsing
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant AttachMenuButton
participant WorkspaceView
participant SurfaceStore
participant RelayFileUploadService
User->>AttachMenuButton: Select file
AttachMenuButton->>WorkspaceView: Open fileImporter
WorkspaceView->>WorkspaceView: Validate size and read file
WorkspaceView->>SurfaceStore: Upload data, filename, and MIME type
SurfaceStore->>RelayFileUploadService: Save upload
RelayFileUploadService-->>SurfaceStore: Return uploaded path
SurfaceStore-->>WorkspaceView: Return upload result
WorkspaceView->>WorkspaceView: Append path to command draft
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds an iPhone attachment path for arbitrary files, not just photos. The workspace input bar's photo button becomes a single
+menu (사진 / 파일). The 파일 option opens a document picker (any file type); the picked file is uploaded via the existingfile.uploadRPC, saved on the Mac under~/Downloads/cmux-remote/, and its path is inserted into the command draft — the same flow photos already use. Handy for handing a file (Dockerfile, PDF, log, …) to a terminal agent.Changes
WorkspaceView.swift):PhotoAttachButton→AttachMenuButton(Menu) +.photosPicker(isPresented:)/.fileImporter. NewattachFile(_:)reads bytes off the main actor under a security-scoped resource, pre-checks the 12 MiB cap, and reusesuploadFile+appendPathToDraft. Existing photo flow is untouched.AttachmentNaming.swift, new): pure, unit-tested helpers for basename sanitization (directory-traversal safe) and MIME inference.HostServices.swift):RelayFileUploadServicefilename generation was photo-specific and mishandled arbitrary files — an extensionless name (e.g.Dockerfile) got a bogus.jpgappended, and an empty name leaked the cwd. It now respects the client filename verbatim (no forced extension), synthesizesupload.<ext>(extension viaUTType) only when no usable name is given, and sanitizes withNSString.lastPathComponent. The relay remains the single source of the<yyyyMMdd-HHmmss>-prefix, so the client no longer double-timestamps.Note on the build-fix commit
This branch includes a cherry-pick of the type-checker build fix from #11 (
Sources/SharedKit/InboxNotification.swift) so the relay compiles on top ofmain. It's the identical change, so merging #11 first is conflict-free.Verification
swift test— RelayServerTests 52 + SharedKitTests 37 pass, including newHostServicesTestscases for extensionless / non-image / blank-name / traversal filenames.AttachmentNaming, and the too-large error copy) verified via aswiftCLI harness using the real sources (all passing).+menu opens both pickers, an extensionless file lands correctly named in~/Downloads/cmux-remote/, and the >12 MiB error shows the friendly message.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Documentation