From e6318d394832696c15ce67cd05f85cfed81e3bc7 Mon Sep 17 00:00:00 2001 From: hryeong66 Date: Mon, 19 Aug 2024 21:01:25 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=95=B1=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EB=B2=84=ED=8A=BC=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20=EC=95=B1=EC=8A=A4=ED=86=A0=EC=96=B4=20=EC=97=B0=EA=B2=B0=20?= =?UTF-8?q?(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: 앱업데이트 버튼 추가 및 앱스토어 연결 (#68) --- .../Setting/Sources/SettingView.swift | 30 ++++++++- .../Setting/Sources/SettingViewModel.swift | 61 ++++++++++++------- 2 files changed, 66 insertions(+), 25 deletions(-) diff --git a/Projects/Features/Setting/Sources/SettingView.swift b/Projects/Features/Setting/Sources/SettingView.swift index 2ee8c2d..90aee37 100644 --- a/Projects/Features/Setting/Sources/SettingView.swift +++ b/Projects/Features/Setting/Sources/SettingView.swift @@ -40,8 +40,7 @@ public struct SettingView: View { .padding(.top, 50) memeLogoImage - appNameAndVersion - .padding(.bottom, 50) + appDescriptionView Divider() .padding(.horizontal, 10) @@ -69,6 +68,19 @@ public struct SettingView: View { .padding(.top, 50) } + var appDescriptionView: some View { + VStack { + if viewModel.state.needUpdate { + appNameAndVersion + .padding(.bottom, 16) + appUpdateButton + } else { + appNameAndVersion + } + } + .padding(.bottom, 50) + } + var appNameAndVersion: some View { VStack { Text("파밈") @@ -81,6 +93,20 @@ public struct SettingView: View { } } + var appUpdateButton: some View { + Link(destination: viewModel.appStoreUrl) { + Text("앱 업데이트하기") + .font(Font.Body.Large.semiBold) + .foregroundStyle(Color.Text.inverse) + .padding(.vertical, 12) + .padding(.horizontal, 16) + .background { + RoundedCorners(radius: 10, corners: .allCorners) + .foregroundStyle(Color.Background.primary) + } + } + } + var settingListView: some View { ForEach(viewModel.state.settingList) { settingType in SettingListItemView( diff --git a/Projects/Features/Setting/Sources/SettingViewModel.swift b/Projects/Features/Setting/Sources/SettingViewModel.swift index 056f56e..e83796f 100644 --- a/Projects/Features/Setting/Sources/SettingViewModel.swift +++ b/Projects/Features/Setting/Sources/SettingViewModel.swift @@ -17,6 +17,7 @@ final public class SettingViewModel: ViewModelType, ObservableObject { public enum Action { case naviBackButtonTapped + case checkNeedUpdate } public struct State { @@ -28,14 +29,20 @@ final public class SettingViewModel: ViewModelType, ObservableObject { // MARK: - Properties weak var router: SettingRouting? @Published public var state: State + private let appId: String = "6532618484" + var appStoreUrl: URL { + return URL(string: "itms-apps://itunes.apple.com/app/\(appId)")! + } // MARK: - Initializers public init(router: SettingRouting? = nil) { self.router = router self.state = State() - self.state.needUpdate = self.checkNeedUpdate() - self.state.currnetAppVersion = self.getCurrentAppVersion() + + self.state.currnetAppVersion = "v." + self.getCurrentAppVersion() self.initSettingList() + + self.dispatch(type: .checkNeedUpdate) } private func initSettingList() { @@ -50,11 +57,14 @@ final public class SettingViewModel: ViewModelType, ObservableObject { } // MARK: - Methods - @MainActor public func dispatch(type: Action) { - switch type { - case .naviBackButtonTapped: - router?.popView() + Task { @MainActor in + switch type { + case .naviBackButtonTapped: + router?.popView() + case .checkNeedUpdate: + self.state.needUpdate = await checkNeedUpdate() + } } } @@ -63,30 +73,35 @@ final public class SettingViewModel: ViewModelType, ObservableObject { return currentVersion ?? "" } - private func checkNeedUpdate() -> Bool { - guard let appStoreVersion = self.getLatestVersion() else { return false } - let currentVersion = getCurrentAppVersion() - print("Setting | currentVersion = \(currentVersion)") - print("Setting | appStoreVersion = \(appStoreVersion)") - + private func checkNeedUpdate() async -> Bool { + guard let appStoreVersion = await self.getLatestVersion() else { return false } + let currentVersion = self.getCurrentAppVersion() return currentVersion != appStoreVersion } - private func getLatestVersion() -> String? { -// guard -// let bundleIdentifier = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String, -// let url = URL(string: "https://itunes.apple.com/lookup?bundleId=\(bundleIdentifier)"), -// let data = try? Data(contentsOf: url), -// let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], -// let results = json["results"] as? [[String: Any]], !results.isEmpty, -// let appStoreVersion = results[0]["version"] as? String else { -// return nil -// } -// return appStoreVersion + private func getLatestVersion() async -> String? { + guard let bundleIdentifier = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String, + let url = URL(string: "https://itunes.apple.com/lookup?bundleId=\(bundleIdentifier)&country=kr") else { + return nil + } + + do { + let (data, _) = try await URLSession.shared.data(from: url) + if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], + let results = json["results"] as? [[String: Any]], !results.isEmpty, + let appStoreVersion = results[0]["version"] as? String { + return appStoreVersion + } + } catch { + print("Failed to fetch latest version: \(error)") + } + return nil } + } + public struct SettingType: Identifiable { public let id = UUID() public let url: String