Enhance HistoryView navigation by differentiating QR code item handling based on data source. Implement new methods for generating QR code images and extracting style data, improving user experience and functionality in HistoryItemRow.

main
v504 2 months ago
parent 59634d27fb
commit 06fe117f68

@ -0,0 +1,191 @@
import SwiftUI
import CoreImage
import QRCode
// MARK: -
class QRCodeGenerator {
// MARK: - 使Core Image
static func generateBasicQRCode(content: String) -> UIImage {
let data = content.data(using: .utf8)
let qrFilter = CIFilter.qrCodeGenerator()
qrFilter.setValue(data, forKey: "inputMessage")
qrFilter.setValue("H", forKey: "inputCorrectionLevel")
guard let outputImage = qrFilter.outputImage else {
return UIImage(systemName: "qrcode") ?? UIImage()
}
let context = CIContext()
guard let cgImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return UIImage(systemName: "qrcode") ?? UIImage()
}
return UIImage(cgImage: cgImage)
}
// MARK: - 使QRCode
static func generateHighQualityQRCode(
content: String,
styleData: QRCodeStyleData? = nil
) -> UIImage {
do {
let document = try createQRCodeDocument(content: content, styleData: styleData)
let imageData = try document.pngData(dimension: 600)
return UIImage(data: imageData) ?? generateBasicQRCode(content: content)
} catch {
print("生成高质量二维码失败:\(error.localizedDescription)")
return generateBasicQRCode(content: content)
}
}
// MARK: - QRCode
private static func createQRCodeDocument(
content: String,
styleData: QRCodeStyleData?
) throws -> QRCode.Document {
let document = try QRCode.Document(engine: QRCodeEngineExternal())
//
document.utf8String = content
// 使
guard let styleData = styleData else {
// 使
document.design.backgroundColor(CGColor(red: 1, green: 1, blue: 1, alpha: 1)) //
document.design.style.eye = QRCode.FillStyle.Solid(CGColor(red: 0, green: 0, blue: 0, alpha: 1)) //
document.design.style.eyeBackground = CGColor(red: 1, green: 1, blue: 1, alpha: 1) //
document.design.shape.onPixels = QRCode.PixelShape.Square() //
document.design.style.onPixels = QRCode.FillStyle.Solid(CGColor(red: 0, green: 0, blue: 0, alpha: 1)) //
document.design.style.onPixelsBackground = CGColor(red: 1, green: 1, blue: 1, alpha: 1) //
document.design.shape.offPixels = QRCode.PixelShape.Square() //
document.design.style.offPixels = QRCode.FillStyle.Solid(CGColor(red: 1, green: 1, blue: 1, alpha: 1)) //
document.design.style.offPixelsBackground = CGColor(red: 1, green: 1, blue: 1, alpha: 1) //
document.design.shape.eye = QRCode.EyeShape.Square() //
return document
}
//
applyStyleData(styleData, to: document)
return document
}
// MARK: -
private static func applyStyleData(_ styleData: QRCodeStyleData, to document: QRCode.Document) {
//
if let backgroundColor = getColor(from: styleData.backgroundColor) {
document.design.backgroundColor(backgroundColor)
}
//
let foregroundColor = getColor(from: styleData.foregroundColor) ?? CGColor(red: 0, green: 0, blue: 0, alpha: 1)
//
document.design.style.eye = QRCode.FillStyle.Solid(foregroundColor)
document.design.style.eyeBackground = getColor(from: styleData.backgroundColor) ?? CGColor(red: 1, green: 1, blue: 1, alpha: 1)
//
let dotType = getDotType(from: styleData.dotType)
document.design.shape.onPixels = dotType
document.design.style.onPixels = QRCode.FillStyle.Solid(foregroundColor)
document.design.style.onPixelsBackground = getColor(from: styleData.backgroundColor) ?? CGColor(red: 1, green: 1, blue: 1, alpha: 1)
document.design.shape.offPixels = dotType
document.design.style.offPixels = QRCode.FillStyle.Solid(getColor(from: styleData.backgroundColor) ?? CGColor(red: 1, green: 1, blue: 1, alpha: 1))
document.design.style.offPixelsBackground = getColor(from: styleData.backgroundColor) ?? CGColor(red: 1, green: 1, blue: 1, alpha: 1)
//
let eyeType = getEyeType(from: styleData.eyeType)
document.design.shape.eye = eyeType
// Logo
if let logo = styleData.logo {
applyLogo(logo, hasCustomLogo: styleData.hasCustomLogo, customLogoFileName: styleData.customLogoFileName, to: document)
}
}
// MARK: - Logo
private static func applyLogo(
_ logoIdentifier: String,
hasCustomLogo: Bool,
customLogoFileName: String?,
to document: QRCode.Document
) {
if hasCustomLogo, let fileName = customLogoFileName {
// Logo
if let customLogoImage = loadCustomLogoImage(fileName: fileName),
let cgImage = customLogoImage.cgImage {
document.logoTemplate = QRCode.LogoTemplate.CircleCenter(image: cgImage, inset: 0)
}
} else {
// Logo
if let qrCodeLogo = QRCodeLogo(rawValue: logoIdentifier),
let logoImage = qrCodeLogo.image,
let cgImage = logoImage.cgImage {
document.logoTemplate = QRCode.LogoTemplate.CircleCenter(image: cgImage)
}
}
}
// MARK: - Logo
private static func loadCustomLogoImage(fileName: String) -> UIImage? {
guard let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
return nil
}
let customLogosPath = documentsPath.appendingPathComponent("CustomLogos")
let imagePath = customLogosPath.appendingPathComponent(fileName)
return UIImage(contentsOfFile: imagePath.path)
}
// MARK: -
private static func getColor(from colorString: String) -> CGColor? {
switch colorString.lowercased() {
case "black": return CGColor(red: 0, green: 0, blue: 0, alpha: 1)
case "white": return CGColor(red: 1, green: 1, blue: 1, alpha: 1)
case "red": return CGColor(red: 1, green: 0, blue: 0, alpha: 1)
case "blue": return CGColor(red: 0, green: 0, blue: 1, alpha: 1)
case "green": return CGColor(red: 0, green: 1, blue: 0, alpha: 1)
case "yellow": return CGColor(red: 1, green: 1, blue: 0, alpha: 1)
case "purple": return CGColor(red: 0.5, green: 0, blue: 0.5, alpha: 1)
case "orange": return CGColor(red: 1, green: 0.5, blue: 0, alpha: 1)
case "pink": return CGColor(red: 1, green: 0.75, blue: 0.8, alpha: 1)
case "cyan": return CGColor(red: 0, green: 1, blue: 1, alpha: 1)
case "magenta": return CGColor(red: 1, green: 0, blue: 1, alpha: 1)
case "brown": return CGColor(red: 0.6, green: 0.4, blue: 0.2, alpha: 1)
case "gray": return CGColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1)
case "navy": return CGColor(red: 0, green: 0, blue: 0.5, alpha: 1)
case "teal": return CGColor(red: 0, green: 0.5, blue: 0.5, alpha: 1)
case "indigo": return CGColor(red: 0.3, green: 0, blue: 0.7, alpha: 1)
case "lime": return CGColor(red: 0.5, green: 1, blue: 0, alpha: 1)
case "maroon": return CGColor(red: 0.5, green: 0, blue: 0, alpha: 1)
case "olive": return CGColor(red: 0.5, green: 0.5, blue: 0, alpha: 1)
case "silver": return CGColor(red: 0.75, green: 0.75, blue: 0.75, alpha: 1)
default: return nil
}
}
// MARK: -
private static func getDotType(from dotTypeString: String) -> QRCodePixelShapeGenerator {
// QRCodeDotType
if let dotType = QRCodeDotType.allCases.first(where: { $0.rawValue == dotTypeString }) {
return dotType.pixelShape
}
//
return QRCode.PixelShape.Square()
}
// MARK: -
private static func getEyeType(from eyeTypeString: String) -> QRCodeEyeShapeGenerator {
// QRCodeEyeType
if let eyeType = QRCodeEyeType.allCases.first(where: { $0.rawValue == eyeTypeString }) {
return eyeType.eyeShape
}
//
return QRCode.EyeShape.Square()
}
}

@ -647,13 +647,28 @@ struct HistoryItemRow: View {
} }
} }
.background( .background(
// //
Group { Group {
if item.dataType == DataType.qrcode.rawValue { if item.dataType == DataType.qrcode.rawValue {
NavigationLink( if item.dataSource == DataSource.created.rawValue {
destination: QRCodeDetailView(historyItem: item), //
label: { EmptyView() } NavigationLink(
) destination: QRCodeSavedView(
qrCodeImage: generateQRCodeImage(from: item),
qrCodeContent: item.content ?? "",
qrCodeType: getQRCodeType(from: item),
styleData: getStyleData(from: item),
historyItem: item
),
label: { EmptyView() }
)
} else {
//
NavigationLink(
destination: QRCodeDetailView(historyItem: item),
label: { EmptyView() }
)
}
} else if item.dataType == DataType.barcode.rawValue { } else if item.dataType == DataType.barcode.rawValue {
NavigationLink( NavigationLink(
destination: BarcodeDetailView(historyItem: item), destination: BarcodeDetailView(historyItem: item),
@ -670,6 +685,45 @@ struct HistoryItemRow: View {
formatter.timeStyle = .short formatter.timeStyle = .short
return formatter.string(from: date) return formatter.string(from: date)
} }
// MARK: - QRCodeSavedView
private func generateQRCodeImage(from item: HistoryItem) -> UIImage {
//
let content = item.content ?? ""
//
let styleData = getStyleData(from: item)
// 使
return QRCodeGenerator.generateHighQualityQRCode(
content: content,
styleData: styleData
)
}
private func getQRCodeType(from item: HistoryItem) -> QRCodeType {
if let qrCodeTypeString = item.qrCodeType,
let qrCodeType = QRCodeType(rawValue: qrCodeTypeString) {
return qrCodeType
}
return .text //
}
private func getStyleData(from item: HistoryItem) -> QRCodeStyleData? {
//
guard let jsonString = item.qrCodeStyleData,
let jsonData = jsonString.data(using: .utf8) else {
return nil
}
do {
let styleData = try JSONDecoder().decode(QRCodeStyleData.self, from: jsonData)
return styleData
} catch {
print("❌ 样式数据JSON解码失败\(error)")
return nil
}
}
} }
// MARK: - // MARK: -

Loading…
Cancel
Save