d6aeede2bc
从桌面工程复制而来,作为本仓库的 Xuxucheck/ 子目录。 为控制仓库体积做了两处删减: - 移除 Frameworks/opencv2.xcframework 下的两个 visionOS 切片 (xros-arm64、xros-arm64-simulator,合计约 106 MB),并同步删掉该 xcframework 内 Info.plist 里对应的两条 AvailableLibraries 记录, 只保留 ios-arm64 与 ios-arm64_x86_64-simulator。 - 移除全部 .DS_Store 与 xcuserdata/。 已用 xcodebuild 从本目录完整编译验证:BUILD SUCCEEDED, ProcessXCFramework 以 --platform ios 成功选中框架,产物含 3699 个 cv:: 符号 (OpenCV 确实链入),嵌入 framework 3 个,与移除无用 pod 之后的状态一致。 仓库约 206 MB,其中 OpenCV 203 MB、其余源码与依赖约 3 MB。
231 lines
8.2 KiB
Swift
231 lines
8.2 KiB
Swift
//
|
|
// CameraView.swift
|
|
// XuXuCheck
|
|
//
|
|
// Created by henseycai on 2025/6/25.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct CameraView: View {
|
|
// @Binding var image: CGImage?
|
|
// @Binding var array3D: [[[Double]]]
|
|
|
|
@Environment(CameraViewModel.self) private var cameraViewModel
|
|
@Environment(\.dismiss) private var dissmiss
|
|
|
|
//https://cloverlaun.tistory.com/77
|
|
//https://stackoverflow.com/questions/59438285/disable-swipe-back-for-a-navigationlink-swiftui/65354662
|
|
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
|
|
|
|
@State private var showingNaiveSafariViewFullScreenCover = false
|
|
|
|
@State var isAnimating = false
|
|
|
|
//let grayImage = OpenCVWrapper.toGrayscale(uiImage)
|
|
var body: some View {
|
|
|
|
ZStack (alignment: .top){
|
|
|
|
|
|
|
|
|
|
GeometryReader { geometry in
|
|
|
|
|
|
|
|
|
|
if let image = cameraViewModel.currentFrame {
|
|
|
|
let uiImage = UIImage(cgImage: image)
|
|
let result = OpenCVWrapper.analysisImage(uiImage)
|
|
|
|
let wbArr = result.paperWbValue as! [Double]
|
|
// let descArr = result.paperTypeDesc as! [Int]
|
|
|
|
// let wbArr = result.paperWbValue as! [Int]
|
|
|
|
|
|
if(wbArr[3] == 0){
|
|
|
|
if(cameraViewModel.array3D.count < 16){
|
|
let _ = cameraViewModel.array3D.append(result.paperAnalResults as! [[Double]])
|
|
// let _ = print(cameraViewModel.array3D.count)
|
|
}else{
|
|
|
|
if(cameraViewModel.isDataSent == false){
|
|
|
|
let _ = print(cameraViewModel.array3D)
|
|
|
|
//let _ = cameraViewModel.stopSession()
|
|
|
|
|
|
let _ = cameraViewModel.addRecord(desc: result.paperTypeDesc as! [Int])
|
|
}
|
|
|
|
|
|
//following line works just bcs Image come continuously ,so following triggered. thanks God~
|
|
// if(cameraViewModel.isSuccess == true){
|
|
// let _ = self.presentationMode.wrappedValue.dismiss()
|
|
//
|
|
// XuXuWebView(currentUrl: cameraViewModel.recordDetailUrl())
|
|
// }
|
|
|
|
}
|
|
|
|
//let _ = print(wbArr)
|
|
// let _ = print(descArr)
|
|
}
|
|
|
|
|
|
|
|
Image(uiImage: result.srcImg)
|
|
.resizable()
|
|
.scaledToFit()
|
|
.frame(width: geometry.size.width,
|
|
height: geometry.size.height)
|
|
//.clipped()
|
|
/*clipped() This crucial modifier crops any content of the view that extends beyond its defined frame. When combined with .scaledToFill() and .frame(), it effectively "crops" the image to the specified dimensions.*/
|
|
|
|
|
|
|
|
Image("scanfan").resizable().frame(width: 60,height: 235)
|
|
.offset(x: isAnimating ? geometry.size.width : -50,y:70)
|
|
.animation(.easeInOut(duration: 5).repeatForever(autoreverses: false), value: isAnimating)
|
|
.onAppear{
|
|
isAnimating.toggle()
|
|
}
|
|
|
|
Text("Scan urinal strip in natural light. Put strip on white paper towel.Ensure strip is completely presented in green box.").foregroundStyle(Color.white)
|
|
.font(.title2).frame(maxWidth: .infinity, maxHeight:.infinity,alignment: .topLeading)
|
|
.padding().background(Color.gray)
|
|
.offset(x:0,y:400)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// ContentUnavailableView("Camera feed interrupted", systemImage: "xmark.circle.fill")
|
|
// .frame(width: geometry.size.width,
|
|
// height: geometry.size.height)
|
|
|
|
|
|
|
|
}
|
|
}
|
|
.padding(.top,20)
|
|
.onChange(of: cameraViewModel.isSuccess){oldState,newState in
|
|
if(oldState == false && newState == true){
|
|
|
|
//https://www.hackingwithswift.com/quick-start/swiftui/how-to-run-some-code-when-state-changes-using-onchange
|
|
|
|
//https://developer.apple.com/documentation/swiftui/view/onchange(of:perform:)
|
|
|
|
// showingNaiveSafariViewFullScreenCover = true
|
|
// dissmiss()
|
|
showingNaiveSafariViewFullScreenCover.toggle()
|
|
}
|
|
}
|
|
.onChange(of: cameraViewModel.isNeedPopErr){oldState,newState in
|
|
if(oldState == false && newState == true){
|
|
showTopToast.toggle()
|
|
}
|
|
}
|
|
.fullScreenCover(isPresented: $showingNaiveSafariViewFullScreenCover) {
|
|
XuXuWebView(currentUrl: cameraViewModel.recordDetailUrl())
|
|
}
|
|
.present(isPresented: self.$showTopToast, type: .toast, position: .top, duration: 6.0, onTap: {
|
|
|
|
}, onToastDismiss: {
|
|
dissmiss()
|
|
}) {
|
|
self.createTopToastView()
|
|
}
|
|
|
|
|
|
|
|
HStack {
|
|
|
|
Image(systemName: "arrow.backward")
|
|
.frame(width: 50, height: 50)
|
|
.foregroundColor(.secondary)
|
|
.strokeStyle(cornerRadius: 15)
|
|
.onTapGesture {
|
|
dissmiss()
|
|
}
|
|
|
|
Text("Scanning").font(.headline).frame(maxWidth: .infinity, alignment: .center)
|
|
}.padding(.top,50)
|
|
}
|
|
|
|
// .navigationBarTitleDisplayMode(.inline)
|
|
// .toolbar{
|
|
// ToolbarItem(placement:.principal){
|
|
//
|
|
//
|
|
// Text("Timer").font(.headline)
|
|
// }
|
|
// }
|
|
//
|
|
// .navigationBarItems(
|
|
// leading: Button(action: {
|
|
// dissmiss()
|
|
// }, label: {
|
|
// Image(systemName: "arrow.backward")
|
|
// .foregroundColor(Color(red: 231/255, green: 200/255, blue: 153/255))
|
|
// }), trailing: Button(action: {
|
|
// // 点击按钮时的操作
|
|
// }, label: {
|
|
// Text("明细")
|
|
// .foregroundColor(Color(red: 231/255, green: 200/255, blue: 153/255))
|
|
// }))
|
|
|
|
|
|
}
|
|
|
|
|
|
let topToastColor = Color(hex: "4067CC")
|
|
|
|
@State var showTopToast = false
|
|
|
|
func createTopToastView() -> some View {
|
|
VStack {
|
|
Spacer(minLength: 30)
|
|
HStack() {
|
|
Image("AppIcon")
|
|
.resizable()
|
|
.aspectRatio(contentMode: ContentMode.fill)
|
|
.frame(width: 50, height: 50)
|
|
.cornerRadius(25)
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
HStack {
|
|
Text("Error")
|
|
.font(.system(size: 18))
|
|
.foregroundColor(.white)
|
|
.fontWeight(.bold)
|
|
Spacer()
|
|
Image(systemName: "info")
|
|
.font(.system(size: 12))
|
|
.foregroundColor(.white)
|
|
}
|
|
|
|
Text("\(cameraViewModel.xuxuError?.message)" + "!")
|
|
.lineLimit(2)
|
|
.font(.system(size: 16))
|
|
.foregroundColor(.white)
|
|
}
|
|
}.padding(15)
|
|
}
|
|
.frame(height: 130)
|
|
.background(self.topToastColor)
|
|
}
|
|
|
|
}
|
|
|
|
#Preview {
|
|
CameraView()
|
|
|
|
// CameraView(image: .constant(nil),array3D: .constant([]))
|
|
}
|