Refactor QR scan and share and add QRS support

This commit is contained in:
世界
2026-01-02 16:27:26 +08:00
parent 313cb5d213
commit 52db9bbb39
23 changed files with 1115 additions and 1411 deletions
@@ -78,6 +78,11 @@ public struct ProfileCard: View {
QRCodeSheet(profileName: profile.name, remoteURL: remoteURL)
}
}
.sheet(isPresented: $viewModel.showQRSShare) {
if let profile = selectedProfile, let data = try? profile.origin.toContent().encode() {
QRSSheet(profileName: profile.name, profileData: data)
}
}
#else
.sheet(isPresented: $viewModel.showNewProfile, onDismiss: {
environments.profileUpdate.send()
@@ -98,6 +103,11 @@ public struct ProfileCard: View {
}
}
#endif
.sheet(isPresented: $viewModel.showQRSShare) {
if let profile = selectedProfile, let data = try? profile.origin.toContent().encode() {
QRSSheet(profileName: profile.name, profileData: data)
}
}
.fileExporter(
isPresented: $viewModel.showProfileExporter,
document: viewModel.profileExportDocument,
@@ -250,20 +260,26 @@ public struct ProfileCard: View {
@ViewBuilder
private func shareMenu(for profile: ProfilePreview) -> some View {
#if os(tvOS)
if profile.type == .remote {
Menu {
Menu {
if profile.type == .remote {
Button {
viewModel.showQRCode = true
} label: {
Label("Share URL as QR Code", systemImage: "qrcode")
}
} label: {
Image(systemName: "square.and.arrow.up")
.font(.system(size: 16))
}
.buttonStyle(.plain)
.actionButtonStyle()
Button {
viewModel.showQRSShare = true
} label: {
Label("Share as QRS Code", systemImage: "barcode")
}
} label: {
Image(systemName: "square.and.arrow.up")
.font(.system(size: 16))
}
.buttonStyle(.plain)
.actionButtonStyle()
#else
Menu {
Button {
@@ -297,9 +313,17 @@ public struct ProfileCard: View {
Label("Share URL as QR Code", systemImage: "qrcode")
}
}
Button {
viewModel.showQRSShare = true
} label: {
Label("Share as QRS Code", systemImage: "barcode")
}
} label: {
Image(systemName: "square.and.arrow.up")
.font(.system(size: 16))
.frame(width: 44, height: 32)
.contentShape(Rectangle())
}
.menuIndicator(.hidden)
.foregroundStyle(.primary)
@@ -351,10 +375,16 @@ public struct ProfileCard: View {
switch type {
case .file:
viewModel.profileExportDocument = try ProfileExportDocument(content: profile.origin.toContent())
viewModel.showProfileExporter = true
case .json:
viewModel.profileJSONExportDocument = ProfileJSONExportDocument(jsonContent: try profile.origin.read(), name: profile.name)
viewModel.showJSONExporter = true
viewModel.profileJSONExportDocument = try ProfileJSONExportDocument(jsonContent: profile.origin.read(), name: profile.name)
}
DispatchQueue.main.async {
switch type {
case .file:
viewModel.showProfileExporter = true
case .json:
viewModel.showJSONExporter = true
}
}
} catch {
viewModel.alert = AlertState(error: error)
@@ -462,6 +492,7 @@ extension ProfileCard {
@Published var showNewProfile = false
@Published var showProfilePicker = false
@Published var showQRCode = false
@Published var showQRSShare = false
@Published var isUpdating = false
@Published var alert: AlertState?
@Published var profileToEdit: Profile?
@@ -531,6 +531,7 @@ private struct ProfilePickerRow: View {
@State private var isUpdating = false
@State private var showQRCode = false
@State private var showQRSShare = false
#if os(macOS)
@State private var shareItemType: ShareItemType?
@State private var exportItemType: ExportItemType?
@@ -569,6 +570,11 @@ private struct ProfilePickerRow: View {
QRCodeSheet(profileName: profile.name, remoteURL: remoteURL)
}
}
.sheet(isPresented: $showQRSShare) {
if let data = try? profile.origin.toContent().encode() {
QRSSheet(profileName: profile.name, profileData: data)
}
}
}
private var tvOSNormalBody: some View {
@@ -615,16 +621,24 @@ private struct ProfilePickerRow: View {
} label: {
Label("Update", systemImage: "arrow.clockwise")
}
}
Menu {
Menu {
if profile.type == .remote {
Button {
showQRCode = true
} label: {
Label("Share URL as QR Code", systemImage: "qrcode")
}
} label: {
Label("Share", systemImage: "square.and.arrow.up")
}
Button {
showQRSShare = true
} label: {
Label("Share as QRS Code", systemImage: "barcode")
}
} label: {
Label("Share", systemImage: "square.and.arrow.up")
}
} label: {
Image(systemName: "ellipsis")
@@ -708,6 +722,11 @@ private struct ProfilePickerRow: View {
QRCodeSheet(profileName: profile.name, remoteURL: remoteURL)
}
}
.sheet(isPresented: $showQRSShare) {
if let data = try? profile.origin.toContent().encode() {
QRSSheet(profileName: profile.name, profileData: data)
}
}
.fileExporter(
isPresented: $showProfileExporter,
document: profileExportDocument,
@@ -753,6 +772,11 @@ private struct ProfilePickerRow: View {
QRCodeSheet(profileName: profile.name, remoteURL: remoteURL)
}
}
.sheet(isPresented: $showQRSShare) {
if let data = try? profile.origin.toContent().encode() {
QRSSheet(profileName: profile.name, profileData: data)
}
}
.fileExporter(
isPresented: $showProfileExporter,
document: profileExportDocument,
@@ -952,6 +976,12 @@ private struct ProfilePickerRow: View {
Label("Share URL as QR Code", systemImage: "qrcode")
}
}
Button {
showQRSShare = true
} label: {
Label("Share as QRS Code", systemImage: "barcode")
}
} label: {
Label("Share", systemImage: "square.and.arrow.up")
}
@@ -962,10 +992,16 @@ private struct ProfilePickerRow: View {
switch type {
case .file:
profileExportDocument = try ProfileExportDocument(content: profile.origin.toContent())
showProfileExporter = true
case .json:
profileJSONExportDocument = ProfileJSONExportDocument(jsonContent: try profile.origin.read(), name: profile.name)
showJSONExporter = true
profileJSONExportDocument = try ProfileJSONExportDocument(jsonContent: profile.origin.read(), name: profile.name)
}
DispatchQueue.main.async {
switch type {
case .file:
showProfileExporter = true
case .json:
showJSONExporter = true
}
}
} catch {
alert = AlertState(error: error)
@@ -1025,7 +1061,7 @@ private struct ProfilePickerRow: View {
profileExportDocument = try ProfileExportDocument(content: profile.origin.toContent())
showProfileExporter = true
case .json:
profileJSONExportDocument = ProfileJSONExportDocument(jsonContent: try profile.origin.read(), name: profile.name)
profileJSONExportDocument = try ProfileJSONExportDocument(jsonContent: profile.origin.read(), name: profile.name)
showJSONExporter = true
}
} catch {
@@ -1136,6 +1172,7 @@ private struct ProfilePickerRow: View {
@State private var isUpdating = false
@State private var showQRCode = false
@State private var showQRSShare = false
@State private var profileExportDocument: ProfileExportDocument?
@State private var showProfileExporter = false
@State private var profileJSONExportDocument: ProfileJSONExportDocument?
@@ -1197,6 +1234,11 @@ private struct ProfilePickerRow: View {
QRCodeSheet(profileName: profile.name, remoteURL: remoteURL)
}
}
.sheet(isPresented: $showQRSShare) {
if let data = try? profile.origin.toContent().encode() {
QRSSheet(profileName: profile.name, profileData: data)
}
}
.fileExporter(
isPresented: $showProfileExporter,
document: profileExportDocument,
@@ -1293,6 +1335,12 @@ private struct ProfilePickerRow: View {
Label("Share URL as QR Code", systemImage: "qrcode")
}
}
Button {
showQRSShare = true
} label: {
Label("Share as QRS Code", systemImage: "barcode")
}
} label: {
Label("Share", systemImage: "square.and.arrow.up")
}
@@ -1303,10 +1351,16 @@ private struct ProfilePickerRow: View {
switch type {
case .file:
profileExportDocument = try ProfileExportDocument(content: profile.origin.toContent())
showProfileExporter = true
case .json:
profileJSONExportDocument = ProfileJSONExportDocument(jsonContent: try profile.origin.read(), name: profile.name)
showJSONExporter = true
profileJSONExportDocument = try ProfileJSONExportDocument(jsonContent: profile.origin.read(), name: profile.name)
}
DispatchQueue.main.async {
switch type {
case .file:
showProfileExporter = true
case .json:
showJSONExporter = true
}
}
} catch {
alert = AlertState(error: error)