taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

commit 7b9ca19b66a4b13af3407161ff8a921e780143ba
parent 3445124be9b76a3d8c158587ac3c7e645eeef2b1
Author: Marc Stibane <marc@taler.net>
Date:   Sat, 31 Oct 2026 18:27:01 +0100

ContactsButton for CopyShare

Diffstat:
MTalerCommon/HelperViews/CopyShare.swift | 114++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
MTalerWallet1/Views/HelperViews/QRCodeDetailView.swift | 3++-
2 files changed, 110 insertions(+), 7 deletions(-)

diff --git a/TalerCommon/HelperViews/CopyShare.swift b/TalerCommon/HelperViews/CopyShare.swift @@ -245,39 +245,141 @@ struct ShareButton: View { } } // MARK: - -struct CopyShare: View { +@MainActor +struct ContactsButton: View { + private let symLog = SymLogV(0) let stack: CallStack + let talerUri: String? + let subject: String? + let title: String + + init(_ stack: CallStack, talerUri: String?, subject: String? = nil, title: String? = nil) { + self.stack = stack + self.talerUri = talerUri + self.title = title ?? String(localized: "Contacts") + self.subject = subject + } + @Environment(\.isEnabled) private var isEnabled: Bool + @EnvironmentObject private var controller: Controller - let textToCopy: String - let image: UIImage? + @State private var scale: CGFloat = 1.0 + @State private var showContacts: Bool = false + + func shareAction() -> Void { + symLog.log(talerUri) + controller.hapticFeedback(.soft) + Task { + // First scale down quickly + withAnimation(.easeIn(duration: 0.1)) { + scale = 0.8 + } + // Then bounce back bigger + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + withAnimation(.easeOut(duration: 0.25)) { + scale = 1.15 + } + showContacts = true + } + // Finally settle to normal + DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) { + withAnimation(.easeInOut(duration: 0.25)) { + scale = 1.0 + } + } + } + } + + var body: some View { + if let talerUri { + let contactDest = ContactsView(stack: stack.push(), talerURI: talerUri, subject: subject) + let actions = Group { + NavLink($showContacts) { contactDest } + } + Button(action: shareAction) { + HStack { + Image(systemName: ICONNAME_ALIAS) // 􀲏 + .accessibility(hidden: true) + Text(title) + } + } + .background(actions) + .tint(WalletColors().primaryAccent) + .talerFont(.body) + .scaleEffect(scale) + .disabled(!isEnabled) + } + } +} +// MARK: - +struct CopyShare: View { + let stack: CallStack + let textToCopy: String // either talerURI, or report + let image: UIImage? // either QRcode of talerURI, or nil (report) + let subject: String? + let talerURI: String? + + @Environment(\.isEnabled) private var isEnabled: Bool init(_ stack: CallStack, _ string: String, image: UIImage? = nil, + subject: String? = nil, talerURI: String? = nil ) { self.stack = stack self.textToCopy = string self.image = image + self.subject = subject +#if GNU_TALER || TALER_NIGHTLY + self.talerURI = talerURI +#else + self.talerURI = nil +#endif } var body: some View { + let withContacts: Bool = talerURI != nil let copyB = CopyButton(textToCopy, vertical: false, image: image) .buttonStyle(TalerButtonStyle(type: .bordered)) let share = ShareButton(textToCopy, image: image) .buttonStyle(TalerButtonStyle(type: .bordered)) + let contacts = ContactsButton(stack.push(), talerUri: talerURI, subject: subject) + .buttonStyle(TalerButtonStyle(type: .bordered)) let vLayout = VStack { copyB share + if withContacts { + contacts + } } if #available(iOS 16.0, *) { let hLayout = HStack(spacing: HSPACING) { copyB share + if withContacts { + contacts + } } - ViewThatFits(in: .horizontal) { - hLayout - vLayout + + if withContacts { + let mLayout = VStack { + HStack(spacing: HSPACING) { + copyB + share + } + contacts + } + + ViewThatFits(in: .horizontal) { + hLayout + mLayout + vLayout + } + } else { + ViewThatFits(in: .horizontal) { + hLayout + vLayout + } } } else { vLayout diff --git a/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift b/TalerWallet1/Views/HelperViews/QRCodeDetailView.swift @@ -99,7 +99,8 @@ struct QRCodeDetailView: View { withAnimation { showQRcode = true } }.buttonStyle(TalerButtonStyle(type: .prominent)) } - CopyShare(stack.push(), talerCopyShare, image: qrImage) + CopyShare(stack.push(), talerCopyShare, image: qrImage, + subject: subject, talerURI: talerURI) .disabled(false) // .padding(.bottom) .listRowSeparator(.hidden)