// // 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 @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([])) }