// // IntroViewModel.swift // AcaMate // // Created by TAnine on 3/20/25. // import SwiftUI import Combine class IntroViewModel: ObservableObject { private let appVM: AppViewModel private var cancellables = Set() @UserDefault(key: "header", defaultValue: "headerValue") var headerValue init(_ appVM: AppViewModel) { self.appVM = appVM } func appStart() { subscribeAlertAction() searchHeader() .flatMap { success -> Future in return self.loadVersion() } .sink { [weak self] completion in guard let self = self else {return} switch completion { case .failure(let error): // 만약 여기서 에러가 난다면 서버에 문제가 있다는 것 printLog(error) self.appVM.alertData = SetAlertData().setServerError(action: appVM.alertAction) self.appVM.showAlert.toggle() case .finished: break } } receiveValue: { [weak self] version in guard let self = self else {return} @UserDefault(key:"currentVer", defaultValue: "0.0.0") var currentVer @UserDefault(key:"finalVer", defaultValue: "0.0.0") var finalVer currentVer = currentVersion() finalVer = version.final_ver let compareForce = compareVersion(version.force_ver, currentVer)//currentVersion()) let compareChoice = compareVersion(version.final_ver, currentVer)//currentVersion()) if compareForce == .bigger { appVM.alertData = SetAlertData().setForceUpdate( action: appVM.alertAction ) appVM.showAlert.toggle() } else if compareChoice == .bigger && version.choice_update_yn { appVM.alertData = SetAlertData().setSelectUpdate( action: appVM.alertAction ) appVM.showAlert.toggle() } else { // 정상 동작 넘어감 appVM.naviState.set(act: .RESET, path: .Login) } } .store(in: &cancellables) } func searchHeader() -> Future { return Future { [weak self] promise in guard let self = self else { promise(.failure(ACA_ERROR("Self 전환 오류"))) return } guard let deviceId = UIDevice.current.identifierForVendor?.uuidString, let bundleId = Bundle.main.bundleIdentifier else { promise(.failure(ACA_ERROR("번들/디바이스 아이디 조회 불량"))) return } let request = APIRequest(path: "/api/v1/in/app", parameters: ["type": "I", "specific": deviceId, "project": bundleId], decoding: APIResponse
.self) appVM.apiManager.loadAPIData(request) .sink { completion in switch completion { case .failure(let error): printLog("최종 에러: \(error)") promise(.failure(error)) case .finished: break } } receiveValue: { [weak self] response in guard let self = self else {return} if let data = response.data { self.headerValue = data.header promise(.success(true)) } else { promise(.failure(ACA_ERROR("데이터 없음"))) } } .store(in: &self.cancellables) } // } private func subscribeAlertAction() { appVM.alertAction .compactMap { $0 } .sink { [weak self] action in guard let self = self else {return} if action == "exit" { exit(1) } else if action == "updateNow" { exit(1) //MARK: - TODO (앱스토어 이동 로직 넣을 것) } else { appVM.naviState.set(act: .RESET, path: .Login) } }.store(in: &cancellables) } private func loadVersion() -> Future { return Future { [weak self] promise in guard let self = self else {return} let request = APIRequest(path: "/api/v1/in/app/version", headers: [API_HEADER : self.headerValue], parameters: ["type":"I"], decoding: APIResponse.self) appVM.apiManager.loadAPIData(request) .sink { completion in switch completion { case .failure(let error): printLog("\(error)") promise(.failure(error)) case .finished: break } } receiveValue: { versionData in guard let version = versionData.data else {return} printLog("\(version.toStringDict())") promise(.success(version)) } .store(in: &cancellables) } } private func currentVersion() -> String { guard let currentVer = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else { return "" } return currentVer } private func versionChange(ver: String) -> [Int] { return ver.components(separatedBy: ["."]).map {Int($0) ?? 0} } }