damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit 5d90b497f00b3d3562c1debbdbe53ae5ba67e095
parent a06be64894ea7ea369ae59431e71709fc364a4e0
Author: ericholguin <eric.holguinsanchez@gmail.com>
Date:   Tue, 19 Sep 2023 18:15:50 -0600

images: add scan for qr code to image context menu

Closes: https://github.com/damus-io/damus/pull/1566
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mdamus/Components/ImageCarousel.swift | 2+-
Mdamus/Views/Images/ImageContainerView.swift | 9++++-----
Mdamus/Views/Images/ImageContextMenuModifier.swift | 48++++++++++++++++++++++++++++++++++++++++++++++++
Mdamus/Views/Images/ImageView.swift | 6+++---
Mdamus/Views/Images/ProfilePicImageView.swift | 13++++++-------
Mdamus/Views/Profile/ProfileView.swift | 2+-
6 files changed, 63 insertions(+), 17 deletions(-)

diff --git a/damus/Components/ImageCarousel.swift b/damus/Components/ImageCarousel.swift @@ -190,7 +190,7 @@ struct ImageCarousel: View { } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) .fullScreenCover(isPresented: $open_sheet) { - ImageView(video_controller: state.video, urls: urls, disable_animation: state.settings.disable_animation) + ImageView(video_controller: state.video, urls: urls, settings: state.settings) } .frame(height: height) .onChange(of: selectedIndex) { value in diff --git a/damus/Views/Images/ImageContainerView.swift b/damus/Views/Images/ImageContainerView.swift @@ -12,12 +12,11 @@ import Kingfisher struct ImageContainerView: View { let video_controller: VideoController let url: MediaUrl + let settings: UserSettingsStore @State private var image: UIImage? @State private var showShareSheet = false - let disable_animation: Bool - private struct ImageHandler: ImageModifier { @Binding var handler: UIImage? @@ -29,13 +28,13 @@ struct ImageContainerView: View { func Img(url: URL) -> some View { KFAnimatedImage(url) - .imageContext(.note, disable_animation: disable_animation) + .imageContext(.note, disable_animation: settings.disable_animation) .configure { view in view.framePreloadCount = 3 } .imageModifier(ImageHandler(handler: $image)) .clipped() - .modifier(ImageContextMenuModifier(url: url, image: image, showShareSheet: $showShareSheet)) + .modifier(ImageContextMenuModifier(url: url, image: image, settings: settings, showShareSheet: $showShareSheet)) .sheet(isPresented: $showShareSheet) { ShareSheet(activityItems: [url]) } @@ -57,6 +56,6 @@ let test_image_url = URL(string: "https://jb55.com/red-me.jpg")! struct ImageContainerView_Previews: PreviewProvider { static var previews: some View { - ImageContainerView(video_controller: test_damus_state.video, url: .image(test_image_url), disable_animation: false) + ImageContainerView(video_controller: test_damus_state.video, url: .image(test_image_url), settings: test_damus_state.settings) } } diff --git a/damus/Views/Images/ImageContextMenuModifier.swift b/damus/Views/Images/ImageContextMenuModifier.swift @@ -12,8 +12,16 @@ import UIKit struct ImageContextMenuModifier: ViewModifier { let url: URL? let image: UIImage? + let settings: UserSettingsStore + + @State var qrCodeLink: String = "" + @State var open_link_confirm: Bool = false + @State var no_link_found: Bool = false + @Binding var showShareSheet: Bool + @Environment(\.openURL) var openURL + func body(content: Content) -> some View { return content.contextMenu { Button { @@ -32,6 +40,35 @@ struct ImageContextMenuModifier: ViewModifier { } label: { Label(NSLocalizedString("Save Image", comment: "Context menu option to save an image."), image: "download") } + Button { + qrCodeLink = "" + guard let detector:CIDetector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh]) else { + return + } + guard let ciImage = CIImage(image:someImage) else { + return + } + let features = detector.features(in: ciImage) + if let qrfeatures = features as? [CIQRCodeFeature] { + for feature in qrfeatures { + if let msgStr = feature.messageString { + qrCodeLink += msgStr + } + } + } + + if qrCodeLink == "" { + no_link_found.toggle() + } else { + if qrCodeLink.contains("lnurl") { + open_with_wallet(wallet: settings.default_wallet.model, invoice: qrCodeLink) + } else if let _ = URL(string: qrCodeLink) { + open_link_confirm.toggle() + } + } + } label: { + Label(NSLocalizedString("Scan for QR Code", comment: "Context menu option to scan image for a QR Code."), image: "qr-code.fill") + } } Button { showShareSheet = true @@ -39,5 +76,16 @@ struct ImageContextMenuModifier: ViewModifier { Label(NSLocalizedString("Share", comment: "Button to share an image."), image: "upload") } } + .alert(NSLocalizedString("Found \(qrCodeLink).\nOpen link?", comment: "Alert message asking if the user wants to open the link."), isPresented: $open_link_confirm) { + Button(NSLocalizedString("Open", comment: "Button to proceed with opening link."), role: .none) { + if let url = URL(string: qrCodeLink) { + openURL(url) + } + } + Button(NSLocalizedString("Cancel", comment: "Button to cancel the upload."), role: .cancel) {} + } + .alert(NSLocalizedString("Unable to find a QR Code", comment: "Alert message letting user know a link was not found."), isPresented: $no_link_found) { + Button(NSLocalizedString("Dismiss", comment: "Button to dismiss alert"), role: .cancel) {} + } } } diff --git a/damus/Views/Images/ImageView.swift b/damus/Views/Images/ImageView.swift @@ -16,7 +16,7 @@ struct ImageView: View { @State private var selectedIndex = 0 @State var showMenu = true - let disable_animation: Bool + let settings: UserSettingsStore var tabViewIndicator: some View { HStack(spacing: 10) { @@ -42,7 +42,7 @@ struct ImageView: View { TabView(selection: $selectedIndex) { ForEach(urls.indices, id: \.self) { index in ZoomableScrollView { - ImageContainerView(video_controller: video_controller, url: urls[index], disable_animation: disable_animation) + ImageContainerView(video_controller: video_controller, url: urls[index], settings: settings) .aspectRatio(contentMode: .fit) .padding(.top, Theme.safeAreaInsets?.top) .padding(.bottom, Theme.safeAreaInsets?.bottom) @@ -85,6 +85,6 @@ struct ImageView: View { struct ImageView_Previews: PreviewProvider { static var previews: some View { let url: MediaUrl = .image(URL(string: "https://jb55.com/red-me.jpg")!) - ImageView(video_controller: test_damus_state.video, urls: [url], disable_animation: false) + ImageView(video_controller: test_damus_state.video, urls: [url], settings: test_damus_state.settings) } } diff --git a/damus/Views/Images/ProfilePicImageView.swift b/damus/Views/Images/ProfilePicImageView.swift @@ -9,12 +9,11 @@ import Kingfisher struct ProfileImageContainerView: View { let url: URL? + let settings: UserSettingsStore @State private var image: UIImage? @State private var showShareSheet = false - let disable_animation: Bool - private struct ImageHandler: ImageModifier { @Binding var handler: UIImage? @@ -27,13 +26,13 @@ struct ProfileImageContainerView: View { var body: some View { KFAnimatedImage(url) - .imageContext(.pfp, disable_animation: disable_animation) + .imageContext(.pfp, disable_animation: settings.disable_animation) .configure { view in view.framePreloadCount = 3 } .imageModifier(ImageHandler(handler: $image)) .clipShape(Circle()) - .modifier(ImageContextMenuModifier(url: url, image: image, showShareSheet: $showShareSheet)) + .modifier(ImageContextMenuModifier(url: url, image: image, settings: settings, showShareSheet: $showShareSheet)) .sheet(isPresented: $showShareSheet) { ShareSheet(activityItems: [url]) } @@ -64,7 +63,7 @@ struct NavDismissBarView: View { struct ProfilePicImageView: View { let pubkey: Pubkey let profiles: Profiles - let disable_animation: Bool + let settings: UserSettingsStore @Environment(\.presentationMode) var presentationMode @@ -74,7 +73,7 @@ struct ProfilePicImageView: View { .ignoresSafeArea() ZoomableScrollView { - ProfileImageContainerView(url: get_profile_url(picture: nil, pubkey: pubkey, profiles: profiles), disable_animation: disable_animation) + ProfileImageContainerView(url: get_profile_url(picture: nil, pubkey: pubkey, profiles: profiles), settings: settings) .aspectRatio(contentMode: .fit) .padding(.top, Theme.safeAreaInsets?.top) .padding(.bottom, Theme.safeAreaInsets?.bottom) @@ -94,7 +93,7 @@ struct ProfileZoomView_Previews: PreviewProvider { ProfilePicImageView( pubkey: test_pubkey, profiles: make_preview_profiles(test_pubkey), - disable_animation: false + settings: test_damus_state.settings ) } } diff --git a/damus/Views/Profile/ProfileView.swift b/damus/Views/Profile/ProfileView.swift @@ -328,7 +328,7 @@ struct ProfileView: View { is_zoomed.toggle() } .fullScreenCover(isPresented: $is_zoomed) { - ProfilePicImageView(pubkey: profile.pubkey, profiles: damus_state.profiles, disable_animation: damus_state.settings.disable_animation) + ProfilePicImageView(pubkey: profile.pubkey, profiles: damus_state.profiles, settings: damus_state.settings) } Spacer()