-
Notifications
You must be signed in to change notification settings - Fork 0
SnipSnaps for macOS — native Mac app (Photos + Files) #2
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
Open
NickReisenauer
wants to merge
11
commits into
main
Choose a base branch
from
macos-port-phase-0-1
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
1129e0e
Add macOS port implementation plan (docs)
NickReisenauer 45264df
macOS Phase 0-1: native Mac target, sandbox entitlements, fix UIKit-o…
NickReisenauer 7647f1a
Fix macOS launch crash: use .formStyle(.grouped) in Settings
NickReisenauer fd8ee7b
docs: record macOS Form layout-cycle crash + fix in port plan
NickReisenauer 5259bf4
macOS Phase 2: restore Similar/duplicate scan on macOS (shared CGImag…
NickReisenauer 2a684b7
macOS Phase 4: on-disk Files cleanup surface (macOS-only)
NickReisenauer b902724
Make Files surface cohesive with Photos (shared settings + stats)
NickReisenauer 9f7c826
macOS Phase 4b: Files 'Remember Reviewed' + duplicate detection
NickReisenauer fd76267
docs: update macOS port plan with progress log at pause point
NickReisenauer a933981
macOS: native UI/UX & desktop pass (sidebar, menus, keyboard, Liquid …
NickReisenauer f596961
macOS: review fixes, lower deploy target to 15, a11y + UX polish
NickReisenauer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| #if os(macOS) | ||
| import SwiftUI | ||
| import AppKit | ||
|
|
||
| // Native macOS menu-bar commands. The Help menu is retargeted at SnipSnaps' real | ||
| // support/legal URLs (the default SwiftUI Help menu is empty). The Review menu | ||
| // and Edit ▸ Undo are wired to the active review surface via focused values. | ||
| struct AppCommands: Commands { | ||
| var body: some Commands { | ||
| // Edit ▸ Undo routed to whichever review owns the focus, so ⌘Z works | ||
| // regardless of which control is focused (and on the summary screen). | ||
| CommandGroup(replacing: .undoRedo) { | ||
| FocusedReviewUndoButton() | ||
| } | ||
|
|
||
| // File ▸ Add Folder… for the Files surface. | ||
| CommandGroup(after: .newItem) { | ||
| FocusedAddFolderButton() | ||
| } | ||
|
|
||
| CommandMenu("Review") { | ||
| FocusedReviewActionButtons() | ||
| } | ||
|
|
||
| CommandGroup(replacing: .help) { | ||
| Button("SnipSnaps Support") { Self.open("https://kyter.com/snipsnaps/support/") } | ||
| Button("GitHub Repository") { Self.open("https://github.com/Kyter-com/SnipSnaps") } | ||
| Button("Send Feedback…") { Self.open("mailto:dev@kyter.com?subject=SnipSnaps%20App%20Feedback") } | ||
| Divider() | ||
| Button("Privacy Policy") { Self.open("https://kyter.com/snipsnaps/privacy/") } | ||
| Button("Terms & Conditions") { Self.open("https://kyter.com/snipsnaps/terms/") } | ||
| } | ||
| } | ||
|
|
||
| static func open(_ string: String) { | ||
| if let url = URL(string: string) { | ||
| NSWorkspace.shared.open(url) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // MARK: - Focused review bridge | ||
|
|
||
| // A review screen publishes this so the menu bar can drive Keep / Delete / Undo / | ||
| // Skip on the currently-active review, with items auto-disabling elsewhere. | ||
| struct ReviewActions { | ||
| var keep: (() -> Void)? | ||
| var delete: (() -> Void)? | ||
| var undo: (() -> Void)? | ||
| var skipGroup: (() -> Void)? | ||
| var canUndo: Bool = false | ||
| } | ||
|
|
||
| struct ReviewActionsFocusedValueKey: FocusedValueKey { | ||
| typealias Value = ReviewActions | ||
| } | ||
|
|
||
| // Files surface publishes its "add folder" hook so File ▸ Add Folder… works. | ||
| struct AddFolderFocusedValueKey: FocusedValueKey { | ||
| typealias Value = () -> Void | ||
| } | ||
|
|
||
| extension FocusedValues { | ||
| var reviewActions: ReviewActions? { | ||
| get { self[ReviewActionsFocusedValueKey.self] } | ||
| set { self[ReviewActionsFocusedValueKey.self] = newValue } | ||
| } | ||
|
|
||
| var addFolderAction: (() -> Void)? { | ||
| get { self[AddFolderFocusedValueKey.self] } | ||
| set { self[AddFolderFocusedValueKey.self] = newValue } | ||
| } | ||
| } | ||
|
|
||
| private struct FocusedReviewUndoButton: View { | ||
| @FocusedValue(\.reviewActions) private var actions | ||
|
|
||
| var body: some View { | ||
| Button("Undo") { actions?.undo?() } | ||
| .keyboardShortcut("z", modifiers: .command) | ||
| .disabled(!(actions?.canUndo ?? false)) | ||
| } | ||
| } | ||
|
|
||
| private struct FocusedAddFolderButton: View { | ||
| @FocusedValue(\.addFolderAction) private var addFolder | ||
|
|
||
| var body: some View { | ||
| Button("Add Folder…") { addFolder?() } | ||
| .keyboardShortcut("o", modifiers: [.command, .shift]) | ||
| .disabled(addFolder == nil) | ||
| } | ||
| } | ||
|
|
||
| // Click-only menu items (discoverability + VoiceOver). The matching ←/→/Delete/s | ||
| // keys are owned by in-view buttons on the active review, so these intentionally | ||
| // carry NO keyboardShortcut to avoid a double-owned key equivalent. | ||
| private struct FocusedReviewActionButtons: View { | ||
| @FocusedValue(\.reviewActions) private var actions | ||
|
|
||
| var body: some View { | ||
| Button("Keep →") { actions?.keep?() } | ||
| .disabled(actions?.keep == nil) | ||
| Button("Move to Trash ←") { actions?.delete?() } | ||
| .disabled(actions?.delete == nil) | ||
| Button("Skip Group S") { actions?.skipGroup?() } | ||
| .disabled(actions?.skipGroup == nil) | ||
| } | ||
| } | ||
| #endif |
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
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.