Refactor QRCodeParser and CreateQRCodeView to support new URL schemes for Instagram, Facebook, WhatsApp, and Viber; enhance input handling and user guidance in SocialInputView and InputComponentFactory for improved clarity and functionality.

main
v504 2 months ago
parent 988d36cd52
commit dc0a1e2356

@ -193,7 +193,7 @@ class QRCodeParser {
} }
// Viber // Viber
if trimmedContent.hasPrefix("viber://") { if trimmedContent.hasPrefix("viber://add?number=") {
return parseViber(trimmedContent) return parseViber(trimmedContent)
} }
@ -574,7 +574,7 @@ class QRCodeParser {
// MARK: - Viber // MARK: - Viber
private static func parseViber(_ content: String) -> ParsedQRData { private static func parseViber(_ content: String) -> ParsedQRData {
let phone = content.replacingOccurrences(of: "viber://contact?number=", with: "") let phone = content.replacingOccurrences(of: "viber://add?number=", with: "")
return ParsedQRData( return ParsedQRData(
type: .viber, type: .viber,

@ -280,7 +280,7 @@ struct InputComponentFactory {
case .instagram: case .instagram:
return "输入Instagram用户名..." return "输入Instagram用户名..."
case .facebook: case .facebook:
return "输入Facebook用户ID..." return "输入Facebook用户ID或链接..."
case .spotify: case .spotify:
return "输入Spotify信息..." return "输入Spotify信息..."
case .twitter: case .twitter:
@ -288,7 +288,7 @@ struct InputComponentFactory {
case .whatsapp: case .whatsapp:
return "输入WhatsApp电话号码+1234567890..." return "输入WhatsApp电话号码+1234567890..."
case .viber: case .viber:
return "输入Viber信息..." return "输入Viber电话号码(如:+1234567890..."
case .snapchat: case .snapchat:
return "输入Snapchat信息..." return "输入Snapchat信息..."
case .tiktok: case .tiktok:

@ -52,7 +52,7 @@ struct SocialInputView: View {
case .tiktok: return "用户名或链接" case .tiktok: return "用户名或链接"
case .snapchat: return "用户名" case .snapchat: return "用户名"
case .whatsapp: return "输入WhatsApp电话号码" case .whatsapp: return "输入WhatsApp电话号码"
case .viber: return "消息内容" case .viber: return "电话号码"
case .spotify: return "歌曲或播放列表链接" case .spotify: return "歌曲或播放列表链接"
} }
} }
@ -60,12 +60,12 @@ struct SocialInputView: View {
var hint: String { var hint: String {
switch self { switch self {
case .instagram: return "输入Instagram用户名" case .instagram: return "输入Instagram用户名"
case .facebook: return "输入Facebook用户ID" case .facebook: return "输入Facebook用户ID或链接"
case .twitter: return "输入Twitter用户名或完整链接" case .twitter: return "输入Twitter用户名或完整链接"
case .tiktok: return "输入TikTok用户名或完整链接" case .tiktok: return "输入TikTok用户名或完整链接"
case .snapchat: return "输入Snapchat用户名" case .snapchat: return "输入Snapchat用户名"
case .whatsapp: return "输入WhatsApp消息内容" case .whatsapp: return "输入WhatsApp消息内容"
case .viber: return "输入Viber消息内容" case .viber: return "输入Viber电话号码"
case .spotify: return "输入Spotify歌曲或播放列表链接" case .spotify: return "输入Spotify歌曲或播放列表链接"
} }
} }
@ -106,7 +106,7 @@ struct SocialInputView: View {
// / () // / ()
VStack(alignment: .leading, spacing: 8) { VStack(alignment: .leading, spacing: 8) {
HStack { HStack {
Text(platform == .whatsapp ? "电话号码" : (platform == .viber ? "消息内容" : "用户名/链接")) Text(platform == .whatsapp || platform == .viber ? "电话号码" : "用户名/链接")
.font(.subheadline) .font(.subheadline)
.foregroundColor(.primary) .foregroundColor(.primary)
Text("*") Text("*")
@ -120,21 +120,7 @@ struct SocialInputView: View {
.focused($focusedField, equals: .username) .focused($focusedField, equals: .username)
} }
// (Viber)
if platform == .viber {
VStack(alignment: .leading, spacing: 8) {
HStack {
Text("消息内容")
.font(.subheadline)
.foregroundColor(.primary)
Spacer()
}
TextField("输入消息内容", text: $message)
.textFieldStyle(RoundedBorderTextFieldStyle())
.focused($focusedField, equals: .message)
}
}
// //
VStack(alignment: .leading, spacing: 8) { VStack(alignment: .leading, spacing: 8) {
@ -180,7 +166,7 @@ struct SocialInputView: View {
if platform == .instagram { if platform == .instagram {
return "• 输入Instagram用户名\n• 将生成instagram://user?username=用户名格式" return "• 输入Instagram用户名\n• 将生成instagram://user?username=用户名格式"
} else if platform == .facebook { } else if platform == .facebook {
return "• 输入Facebook用户ID\n• 将生成fb://profile/用户ID格式" return "• 输入Facebook用户ID或完整链接\n• 将自动提取用户名并生成fb://profile/格式\n• 支持username 或 https://facebook.com/username"
} else { } else {
return "• 可以输入用户名username\n• 或输入完整链接https://twitter.com/username" return "• 可以输入用户名username\n• 或输入完整链接https://twitter.com/username"
} }
@ -189,7 +175,7 @@ struct SocialInputView: View {
case .whatsapp: case .whatsapp:
return "• 输入WhatsApp电话号码+1234567890\n• 将生成whatsapp://send?phone=电话号码格式\n• 用户扫描后可直接打开WhatsApp聊天" return "• 输入WhatsApp电话号码+1234567890\n• 将生成whatsapp://send?phone=电话号码格式\n• 用户扫描后可直接打开WhatsApp聊天"
case .viber: case .viber:
return "• 输入Viber消息内容\n• 将生成可分享的链接" return "• 输入Viber电话号码(如:+1234567890\n• 将生成viber://add?number=格式\n• 用户扫描后可直接添加Viber联系人"
case .spotify: case .spotify:
return "• 输入歌曲或播放列表链接\n• 或输入Spotify ID" return "• 输入歌曲或播放列表链接\n• 或输入Spotify ID"
} }

@ -513,7 +513,9 @@ struct CreateQRCodeView: View {
case .instagram: case .instagram:
return "instagram://user?username=\(socialUsername)" return "instagram://user?username=\(socialUsername)"
case .facebook: case .facebook:
return "fb://profile/\(socialUsername)" // Facebook/ID
let facebookId = extractFacebookId(from: socialUsername)
return "fb://profile/\(facebookId)"
case .spotify: case .spotify:
return socialUsername.hasPrefix("http") ? socialUsername : "https://open.spotify.com/track/\(socialUsername)" return socialUsername.hasPrefix("http") ? socialUsername : "https://open.spotify.com/track/\(socialUsername)"
case .twitter: case .twitter:
@ -521,8 +523,7 @@ struct CreateQRCodeView: View {
case .whatsapp: case .whatsapp:
return "whatsapp://send?phone=\(socialUsername)" return "whatsapp://send?phone=\(socialUsername)"
case .viber: case .viber:
let message = socialMessage.isEmpty ? "Hello" : socialMessage return "viber://add?number=\(socialUsername)"
return "viber://chat?number=\(socialUsername)&text=\(message.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? message)"
case .snapchat: case .snapchat:
return "https://snapchat.com/add/\(socialUsername)" return "https://snapchat.com/add/\(socialUsername)"
case .tiktok: case .tiktok:
@ -610,6 +611,41 @@ struct CreateQRCodeView: View {
showingAlert = true showingAlert = true
} }
} }
// MARK: - Facebook ID
private func extractFacebookId(from input: String) -> String {
// Facebook/ID
if input.hasPrefix("http") {
// Facebook
let patterns = [
"https://www.facebook.com/",
"https://facebook.com/",
"http://www.facebook.com/",
"http://facebook.com/"
]
var cleanedInput = input
for pattern in patterns {
if cleanedInput.hasPrefix(pattern) {
cleanedInput = String(cleanedInput.dropFirst(pattern.count))
break
}
}
//
if let questionMarkIndex = cleanedInput.firstIndex(of: "?") {
cleanedInput = String(cleanedInput[..<questionMarkIndex])
}
if let slashIndex = cleanedInput.firstIndex(of: "/") {
cleanedInput = String(cleanedInput[..<slashIndex])
}
return cleanedInput.isEmpty ? "unknown" : cleanedInput
}
// ID
return input
}
} }
#Preview { #Preview {

@ -362,6 +362,12 @@ struct ShareSheet: UIViewControllerRepresentable {
return NavigationView { QRCodeDetailView(historyItem: item) } return NavigationView { QRCodeDetailView(historyItem: item) }
} }
#Preview("Viber") {
let ctx = PreviewData.context
let item = PreviewData.viberSample(in: ctx)
return NavigationView { QRCodeDetailView(historyItem: item) }
}
#Preview("Text") { #Preview("Text") {
let ctx = PreviewData.context let ctx = PreviewData.context
let item = PreviewData.textSample(in: ctx) let item = PreviewData.textSample(in: ctx)
@ -448,4 +454,9 @@ private enum PreviewData {
let content = "MECARD:N:Doe,John;NICKNAME:Johnny;TEL:+1234567890;EMAIL:john.doe@example.com;ORG:Example Company;ADR:123 Main St,Anytown,CA,12345,USA;URL:https://example.com;BDAY:19820908;NOTE:Software Engineer;;" let content = "MECARD:N:Doe,John;NICKNAME:Johnny;TEL:+1234567890;EMAIL:john.doe@example.com;ORG:Example Company;ADR:123 Main St,Anytown,CA,12345,USA;URL:https://example.com;BDAY:19820908;NOTE:Software Engineer;;"
return makeBaseItem(in: context, content: content, qrType: .mecard) return makeBaseItem(in: context, content: content, qrType: .mecard)
} }
static func viberSample(in context: NSManagedObjectContext) -> HistoryItem {
let content = "viber://add?number=+1234567890"
return makeBaseItem(in: context, content: content, qrType: .viber)
}
} }

@ -95,7 +95,7 @@ Facebook: fb://profile/<用户ID>
Spotify: spotify:track:<曲目ID> Spotify: spotify:track:<曲目ID>
Twitter: https://twitter.com/<用户名> Twitter: https://twitter.com/<用户名>
WhatsApp: whatsapp://send?phone=<电话号码> WhatsApp: whatsapp://send?phone=<电话号码>
Viber: viber://contact?number=<电话号码> Viber: viber://add?number=<电话号码>
Snapchat: snapchat://<用户名> Snapchat: snapchat://<用户名>
TikTok: https://www.tiktok.com/@<用户名> TikTok: https://www.tiktok.com/@<用户名>
``` ```

Loading…
Cancel
Save