From 5fb2fd349879acf13e571139aee605c46b4a8e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 14 Jan 2024 20:32:12 +0800 Subject: [PATCH] Replace `Share URL` with `Share URL as QR Code` --- .../Views/Profile/EditProfileView.swift | 13 ++--- .../Views/Profile/ProfileView.swift | 53 +++++++++++++++++++ sing-box.xcodeproj/project.pbxproj | 41 +++++++++----- .../xcshareddata/swiftpm/Package.resolved | 27 ++++++++++ 4 files changed, 112 insertions(+), 22 deletions(-) diff --git a/ApplicationLibrary/Views/Profile/EditProfileView.swift b/ApplicationLibrary/Views/Profile/EditProfileView.swift index b411c38..d9f9ae3 100644 --- a/ApplicationLibrary/Views/Profile/EditProfileView.swift +++ b/ApplicationLibrary/Views/Profile/EditProfileView.swift @@ -1,3 +1,4 @@ +import Libbox import Library import SwiftUI @@ -14,6 +15,8 @@ public struct EditProfileView: View { @State private var isLoading = false @State private var isChanged = false @State private var alert: Alert? + @State private var shareLinkPresented = false + @State private var shareLinkText: String? public init() {} public var body: some View { @@ -72,16 +75,6 @@ public struct EditProfileView: View { } label: { Text("View Content").foregroundColor(.accentColor) } - ProfileShareButton($alert, profile) { - Text("Share") - } - #endif - #if os(iOS) || os(macOS) - ShareButtonCompat($alert) { - Text("Share URL") - } itemURL: { - profile.shareLink - } #endif Button("Update") { isLoading = true diff --git a/ApplicationLibrary/Views/Profile/ProfileView.swift b/ApplicationLibrary/Views/Profile/ProfileView.swift index a70b42e..ab70c44 100644 --- a/ApplicationLibrary/Views/Profile/ProfileView.swift +++ b/ApplicationLibrary/Views/Profile/ProfileView.swift @@ -2,6 +2,7 @@ import Foundation import Libbox import Library import Network +import QRCode import SwiftUI @MainActor @@ -287,6 +288,8 @@ public struct ProfileView: View { public struct ProfileItem: View { private let parent: ProfileView @State private var profile: ProfilePreview + @State private var shareLinkPresented = false + public init(_ parent: ProfileView, _ profile: ProfilePreview) { self.parent = parent _profile = State(initialValue: profile) @@ -313,11 +316,20 @@ public struct ProfileView: View { } label: { Text(profile.name) } + .sheet(isPresented: $shareLinkPresented) { + shareLinkView.padding() + } .contextMenu { ProfileShareButton(parent.$alert, profile.origin) { Label("Share", systemImage: "square.and.arrow.up.fill") } + if profile.type == .remote { + Button { + shareLinkPresented = true + } label: { + Label("Share URL as QR Code", systemImage: "qrcode") + } Button { parent.isUpdating = true Task { @@ -356,6 +368,14 @@ public struct ProfileView: View { } label: { Image(systemName: "arrow.clockwise") } + Button { + shareLinkPresented = true + } label: { + Image(systemName: "qrcode") + } + .popover(isPresented: $shareLinkPresented, arrowEdge: .bottom) { + shareLinkView + } } ProfileShareButton(parent.$alert, profile.origin) { Image(systemName: "square.and.arrow.up.fill") @@ -380,5 +400,38 @@ public struct ProfileView: View { #endif } } + + private var shareLinkView: some View { + #if os(iOS) + viewBuilder { + if #available(iOS 16.0, *) { + shareLinkView0 + .presentationDetents([.medium]) + .presentationDragIndicator(.visible) + } else { + shareLinkView0 + } + } + #else + shareLinkView0 + #endif + } + + private var foregroundColor: CGColor { + #if canImport(UIKit) + return UIColor.label.cgColor + #elseif canImport(AppKit) + return NSColor.labelColor.cgColor + #endif + } + + private var shareLinkView0: some View { + QRCodeViewUI( + content: LibboxGenerateRemoteProfileImportLink(profile.name, profile.remoteURL!), + errorCorrection: .low, + foregroundColor: foregroundColor, + backgroundColor: CGColor(gray: 1.0, alpha: 0.0) + ) + } } } diff --git a/sing-box.xcodeproj/project.pbxproj b/sing-box.xcodeproj/project.pbxproj index b6f841f..048f428 100644 --- a/sing-box.xcodeproj/project.pbxproj +++ b/sing-box.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 3A3AA7FF2A4EFDB3002F78AB /* Library.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC211D2A459B4700A63465 /* Library.framework */; }; 3A3DEBEB2A4FFE2D00373BF4 /* AppIntents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A3DEBE62A4FFA6000373BF4 /* AppIntents.framework */; }; 3A44BB822A4DC28700E4C9F8 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A44BB812A4DC28700E4C9F8 /* MainView.swift */; }; + 3A4A020D2B53E3DC004EFB87 /* QRCode in Frameworks */ = {isa = PBXBuildFile; productRef = 3A4A020C2B53E3DC004EFB87 /* QRCode */; }; 3A4EAD1B2A4FEB02005435B3 /* Library.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC211D2A459B4700A63465 /* Library.framework */; }; 3A4EAD212A4FEB3C005435B3 /* ApplicationLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A4EAD202A4FEB3C005435B3 /* ApplicationLibrary.swift */; }; 3A4EAD222A4FEB54005435B3 /* NavigationPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEC21742A45B0B800A63465 /* NavigationPage.swift */; }; @@ -569,6 +570,7 @@ files = ( 3A4EAD1B2A4FEB02005435B3 /* Library.framework in Frameworks */, 3A6CA5A02A71317A0027933B /* MarkdownUI in Frameworks */, + 3A4A020D2B53E3DC004EFB87 /* QRCode in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1060,6 +1062,7 @@ name = ApplicationLibrary; packageProductDependencies = ( 3A6CA59F2A71317A0027933B /* MarkdownUI */, + 3A4A020C2B53E3DC004EFB87 /* QRCode */, ); productName = ApplicationLibrary; productReference = 3A4EAD102A4FEAE6005435B3 /* ApplicationLibrary.framework */; @@ -1327,6 +1330,7 @@ 3A017F902A4AB2E4009149FA /* XCRemoteSwiftPackageReference "GRDB" */, 3A57DF3A2A4D705000690BC5 /* XCRemoteSwiftPackageReference "MacControlCenterUI" */, 3ADB2D832A71266E00A6517D /* XCRemoteSwiftPackageReference "swift-markdown-ui" */, + 3A4A020B2B53E3DC004EFB87 /* XCRemoteSwiftPackageReference "qrcode" */, ); productRefGroup = 3AEC20C72A45991900A63465 /* Products */; projectDirPath = ""; @@ -1970,7 +1974,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.8.0; + MARKETING_VERSION = 1.8.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa; PRODUCT_NAME = "sing-box"; SDKROOT = appletvos; @@ -2004,7 +2008,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.8.0; + MARKETING_VERSION = 1.8.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa; PRODUCT_NAME = "sing-box"; SDKROOT = appletvos; @@ -2242,7 +2246,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.8.0; + MARKETING_VERSION = 1.8.2; OTHER_CODE_SIGN_FLAGS = "--deep"; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa; PRODUCT_NAME = "sing-box"; @@ -2282,7 +2286,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.8.0; + MARKETING_VERSION = 1.8.2; OTHER_CODE_SIGN_FLAGS = "--deep"; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa; PRODUCT_NAME = "sing-box"; @@ -2305,7 +2309,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 136; + CURRENT_PROJECT_VERSION = 188; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = Z56Z6NYZN2; ENABLE_HARDENED_RUNTIME = YES; @@ -2321,7 +2325,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.8.0; + MARKETING_VERSION = 1.8.2; OTHER_CODE_SIGN_FLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa; PRODUCT_NAME = "sing-box"; @@ -2343,7 +2347,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 136; + CURRENT_PROJECT_VERSION = 188; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = Z56Z6NYZN2; ENABLE_HARDENED_RUNTIME = YES; @@ -2359,7 +2363,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.8.0; + MARKETING_VERSION = 1.8.2; OTHER_CODE_SIGN_FLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa; PRODUCT_NAME = "sing-box"; @@ -2501,7 +2505,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.8.0-alpha.17; + MARKETING_VERSION = 1.8.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.system; PRODUCT_NAME = "$(inherited)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2537,7 +2541,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.8.0-alpha.17; + MARKETING_VERSION = 1.8.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.system; PRODUCT_NAME = "$(inherited)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2577,7 +2581,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.8.0-alpha.17; + MARKETING_VERSION = 1.8.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.independent; PRODUCT_NAME = SFM; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2616,7 +2620,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.8.0-alpha.17; + MARKETING_VERSION = 1.8.2; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.independent; PRODUCT_NAME = SFM; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2829,6 +2833,14 @@ minimumVersion = 6.15.1; }; }; + 3A4A020B2B53E3DC004EFB87 /* XCRemoteSwiftPackageReference "qrcode" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/dagronf/qrcode.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 17.0.0; + }; + }; 3A57DF3A2A4D705000690BC5 /* XCRemoteSwiftPackageReference "MacControlCenterUI" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/orchetect/MacControlCenterUI"; @@ -2861,6 +2873,11 @@ package = 3A017F902A4AB2E4009149FA /* XCRemoteSwiftPackageReference "GRDB" */; productName = GRDB; }; + 3A4A020C2B53E3DC004EFB87 /* QRCode */ = { + isa = XCSwiftPackageProductDependency; + package = 3A4A020B2B53E3DC004EFB87 /* XCRemoteSwiftPackageReference "qrcode" */; + productName = QRCode; + }; 3A6CA59F2A71317A0027933B /* MarkdownUI */ = { isa = XCSwiftPackageProductDependency; package = 3ADB2D832A71266E00A6517D /* XCRemoteSwiftPackageReference "swift-markdown-ui" */; diff --git a/sing-box.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/sing-box.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 19f1da3..029a589 100644 --- a/sing-box.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/sing-box.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -36,6 +36,15 @@ "version" : "1.0.4" } }, + { + "identity" : "qrcode", + "kind" : "remoteSourceControl", + "location" : "https://github.com/dagronf/qrcode.git", + "state" : { + "revision" : "13c605cfa866e257ac9d4ac8a47320a0e11fb6e0", + "version" : "17.0.0" + } + }, { "identity" : "swift-markdown-ui", "kind" : "remoteSourceControl", @@ -44,6 +53,24 @@ "revision" : "12b351a75201a8124c2f2e1f9fc6ef5cd812c0b9", "version" : "2.1.0" } + }, + { + "identity" : "swift-qrcode-generator", + "kind" : "remoteSourceControl", + "location" : "https://github.com/dagronf/swift-qrcode-generator", + "state" : { + "revision" : "2b1980b825f08a81ccc762b0c4d17fcde9d5e953", + "version" : "2.0.2" + } + }, + { + "identity" : "swiftimagereadwrite", + "kind" : "remoteSourceControl", + "location" : "https://github.com/dagronf/SwiftImageReadWrite", + "state" : { + "revision" : "02c141026a0c5d74635a457d2d0964c4cb8935b3", + "version" : "1.4.1" + } } ], "version" : 2