Skip to content

feat: quick save image to photos on long press#387

Open
MufanQiu wants to merge 1 commit into
BugenZhao:mainfrom
MufanQiu:feat/quick-save-image
Open

feat: quick save image to photos on long press#387
MufanQiu wants to merge 1 commit into
BugenZhao:mainfrom
MufanQiu:feat/quick-save-image

Conversation

@MufanQiu

@MufanQiu MufanQiu commented Jun 30, 2026

Copy link
Copy Markdown

What

Add an opt-in "Quick Save Image on Long Press" setting. When enabled,
long-pressing an image inside a post shows a quick action menu to save the
image directly to the photo library
(or view it), instead of going through
Select Attachments → tap image → save.

The setting lives under Settings → Appearance → Post and is off by
default
, so existing long-press behavior (the post-level context menu) is
unchanged unless the user opts in.

How

  • ContentImageView gains a saveImageToPhotos() that reuses
    SDWebImageManager's cached data, so the original (non-thumbnail) image is
    saved, and requests add-only Photos permission before writing.
  • The image uses a high-priority LongPressGesture that presents a
    confirmationDialog. This is needed because the image lives inside the
    post-level .contextMenu subtree; without a high-priority gesture the image's
    own actions get swallowed by the post context menu. The gesture's mask is set
    to .none when the setting is off (or outside a real post), so it doesn't
    interfere with the existing context menu at all in the default configuration.

Screenshots

Setting Long-press menu
setting menu

Testing

  • Built and ran on the iOS Simulator and on a physical device.
  • Verified: with the setting on, long-pressing an image shows Save / View and
    saving writes the full-size image to Photos; with the setting off, the normal
    post context menu appears as before.

Add an opt-in setting (off by default) under Post appearance. When enabled,
long-pressing an image in a post shows a quick action menu to save the image
directly to the photo library or view it, reusing SDWebImage's cached data so
the original (non-thumbnail) image is saved. A high-priority long-press gesture
is used so the image's own actions are not swallowed by the post-level context
menu, and the gesture is disabled when the setting is off.
Copilot AI review requested due to automatic review settings June 30, 2026 11:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in preference to enable a long-press “quick actions” menu on in-post images, allowing users to save the full-size image directly to the Photos library (or view it) without changing the default long-press behavior when the setting is off.

Changes:

  • Added a new quickSaveImage preference and exposed it under Settings → Appearance → Post.
  • Implemented a high-priority long-press gesture on ContentImageView to present a confirmation dialog (Save / View).
  • Added zh-Hans localizations for the new UI strings and toasts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
app/Shared/Views/PreferencesView.swift Adds a new toggle in Post appearance settings to enable quick-save behavior.
app/Shared/Views/ContentImageView.swift Adds long-press quick action dialog and implements saving via PHPhotoLibrary using SDWebImage cached data.
app/Shared/Storage/PreferencesStorage.swift Persists the new quickSaveImage setting via @AppStorage.
app/Shared/Localization/zh-Hans.lproj/Localizable.strings Adds translations for the new setting label, actions, and related toast strings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +138 to +141
guard let image else {
ToastModel.showAuto(.error("Save Failed"))
return
}
} completionHandler: { success, _ in
DispatchQueue.main.async {
if success {
ToastModel.showAuto(.success("Saved"))
Comment on lines +151 to +155
let options = PHAssetResourceCreationOptions()
options.originalFilename = url.lastPathComponent
let request = PHAssetCreationRequest.forAsset()
request.addResource(with: .photo, data: data, options: options)
} else {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants