From 940306f4621cf3c0455350735ea89049441a0c7a Mon Sep 17 00:00:00 2001 From: hyeyeonie Date: Wed, 20 Nov 2024 00:46:19 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20Add=20Toast=20Component=20-=20Toast?= =?UTF-8?q?View=20=EC=B6=94=EA=B0=80=ED=95=B4=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=EA=B5=AC=ED=98=84=20-=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=ED=95=9C=20=EB=B7=B0?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj | 4 + .../Sources/Views/Components/ToastView.swift | 74 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift diff --git a/FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj b/FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj index 025f9ec..03d2b8f 100644 --- a/FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj +++ b/FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ 24360D532CD9F3AF00E83D2B /* DailyProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24360D522CD9F3AF00E83D2B /* DailyProgressView.swift */; }; 24A2063F2CDB180000964FBB /* CompletionCalendarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A2063E2CDB180000964FBB /* CompletionCalendarView.swift */; }; 24F8A2172CEB290B00A01A76 /* Config.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 24F8A2162CEB290B00A01A76 /* Config.xcconfig */; }; + 24FAF9452CEC5224004FEC3F /* ToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FAF9442CEC5224004FEC3F /* ToastView.swift */; }; 261714D62CDDDA4000A3241D /* BookSettingsManagerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261714D52CDDDA4000A3241D /* BookSettingsManagerView.swift */; }; 2644404E2CD8A39E0031A290 /* CompletionCelebrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2644404D2CD8A39E0031A290 /* CompletionCelebrationView.swift */; }; 264440502CD8A3AC0031A290 /* CompletionReviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2644404F2CD8A3AC0031A290 /* CompletionReviewView.swift */; }; @@ -70,6 +71,7 @@ 24360D522CD9F3AF00E83D2B /* DailyProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyProgressView.swift; sourceTree = ""; }; 24A2063E2CDB180000964FBB /* CompletionCalendarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionCalendarView.swift; sourceTree = ""; }; 24F8A2162CEB290B00A01A76 /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = ""; }; + 24FAF9442CEC5224004FEC3F /* ToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastView.swift; sourceTree = ""; }; 261714D52CDDDA4000A3241D /* BookSettingsManagerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookSettingsManagerView.swift; sourceTree = ""; }; 2644404D2CD8A39E0031A290 /* CompletionCelebrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionCelebrationView.swift; sourceTree = ""; }; 2644404F2CD8A3AC0031A290 /* CompletionReviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionReviewView.swift; sourceTree = ""; }; @@ -290,6 +292,7 @@ 26F19A6B2CDA0A2B00F41D6D /* CompletionListView.swift */, 26F19A6D2CDA74A600F41D6D /* WeeklyPageCalendarView.swift */, 1AA14A772CDDA30D00B763A6 /* TotalCalendarTextBubble.swift */, + 24FAF9442CEC5224004FEC3F /* ToastView.swift */, ); path = Components; sourceTree = ""; @@ -419,6 +422,7 @@ 26F19A682CD9EFD800F41D6D /* MainHomeView.swift in Sources */, 26F19A742CDB271E00F41D6D /* NavigationRootView.swift in Sources */, 1AA14A7A2CDDD96200B763A6 /* NotificationManager.swift in Sources */, + 24FAF9452CEC5224004FEC3F /* ToastView.swift in Sources */, 264440502CD8A3AC0031A290 /* CompletionReviewView.swift in Sources */, 264440502CD8A3AC0031A290 /* CompletionReviewView.swift in Sources */, 26890B952CAE811A008DFF49 /* FiveGuyesApp.swift in Sources */, diff --git a/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift b/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift new file mode 100644 index 0000000..07a0eea --- /dev/null +++ b/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift @@ -0,0 +1,74 @@ +// +// ToastView.swift +// FiveGuyes +// +// Created by 신혜연 on 11/19/24. +// + +import SwiftUI + +struct ToastView: View { + var message: String + var body: some View { + VStack(spacing: 0) { + Spacer() + Text(message) + .font(.system(size: 16, weight: .semibold)) + .padding(.horizontal, 20) + .padding(.vertical, 14) + .foregroundColor(.white) + .background(Color.gray) + .cornerRadius(16) + } + } +} + +class ToastModel: ObservableObject { + @Published var message: String? + @Published var isVisible: Bool = false + private var timer: Timer? + + func showToast(message: String, duration: TimeInterval = 1.0) { + self.message = message + self.isVisible = true + + timer?.invalidate() + + timer = Timer.scheduledTimer(withTimeInterval: duration, repeats: false) { [weak self] _ in + DispatchQueue.main.async { + withAnimation { + self?.isVisible = false + } + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self?.message = nil + } + } + } + } +} + + struct ToastTestView: View { + @StateObject private var toastViewModel = ToastModel() + + var body: some View { + ZStack { + VStack { + Button("Show Toast") { + toastViewModel.showToast(message: "오늘은 완독하는 마지막 날이에요!") + } + } + + if let message = toastViewModel.message { + ToastView(message: message) + .opacity(toastViewModel.isVisible ? 1.0 : 0.0) + .animation(.easeInOut(duration: 0.5), value: toastViewModel.isVisible) + .transition(.opacity) + .zIndex(1) + } + } + } + } + +#Preview { + ToastTestView() +} From c02871de7b70296c544db615d730bd68719a4984 Mon Sep 17 00:00:00 2001 From: hyeyeonie Date: Wed, 20 Nov 2024 17:45:34 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20#86=20Divide=20the=20ToastViewModel?= =?UTF-8?q?=20-=20=EB=B7=B0=EC=99=80=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=B7=B0,=20=EB=AA=A8=EB=8D=B8=EC=9D=84=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj | 4 + .../Sources/Stores/ToastViewModel.swift | 34 ++++++++ .../Sources/Views/Components/ToastView.swift | 77 +++++++------------ 3 files changed, 66 insertions(+), 49 deletions(-) create mode 100644 FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift diff --git a/FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj b/FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj index 03d2b8f..69a0839 100644 --- a/FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj +++ b/FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 1A54142B2CD9FEF400283FBD /* BookSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A54142A2CD9FEF400283FBD /* BookSearchView.swift */; }; 1AA14A782CDDA30D00B763A6 /* TotalCalendarTextBubble.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AA14A772CDDA30D00B763A6 /* TotalCalendarTextBubble.swift */; }; 1AA14A7A2CDDD96200B763A6 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AA14A792CDDD96200B763A6 /* NotificationManager.swift */; }; + 240445B42CED9074005C3623 /* ToastViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 240445B32CED9074005C3623 /* ToastViewModel.swift */; }; 24360D482CD8BAF100E83D2B /* EmptyNotiView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24360D472CD8BAF100E83D2B /* EmptyNotiView.swift */; }; 24360D4A2CD8BE3C00E83D2B /* FinishGoalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24360D492CD8BE3C00E83D2B /* FinishGoalView.swift */; }; 24360D532CD9F3AF00E83D2B /* DailyProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24360D522CD9F3AF00E83D2B /* DailyProgressView.swift */; }; @@ -66,6 +67,7 @@ 1A54142A2CD9FEF400283FBD /* BookSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BookSearchView.swift; path = FiveGuyes/Sources/Views/Screen/BookSetting/BookSearch/BookSearchView.swift; sourceTree = SOURCE_ROOT; }; 1AA14A772CDDA30D00B763A6 /* TotalCalendarTextBubble.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TotalCalendarTextBubble.swift; sourceTree = ""; }; 1AA14A792CDDD96200B763A6 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; + 240445B32CED9074005C3623 /* ToastViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastViewModel.swift; sourceTree = ""; }; 24360D472CD8BAF100E83D2B /* EmptyNotiView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyNotiView.swift; sourceTree = ""; }; 24360D492CD8BE3C00E83D2B /* FinishGoalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FinishGoalView.swift; sourceTree = ""; }; 24360D522CD9F3AF00E83D2B /* DailyProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyProgressView.swift; sourceTree = ""; }; @@ -257,6 +259,7 @@ 264440542CD8E0100031A290 /* KeyboardObserver.swift */, 26F19A712CDB267600F41D6D /* NavigationCoordinator.swift */, 26EBDE252CDE3C6000B3A2BC /* BookSettingInputModel.swift */, + 240445B32CED9074005C3623 /* ToastViewModel.swift */, ); path = Stores; sourceTree = ""; @@ -406,6 +409,7 @@ 1A010EC22CD8DA4300FBE3B3 /* BookPageSettingView.swift in Sources */, 1A010EC02CD8DA3800FBE3B3 /* BookLowView.swift in Sources */, 1A010EAC2CD8A7E500FBE3B3 /* APIBooksModel.swift in Sources */, + 240445B42CED9074005C3623 /* ToastViewModel.swift in Sources */, 26890B972CAE811A008DFF49 /* ContentView.swift in Sources */, 261714D62CDDDA4000A3241D /* BookSettingsManagerView.swift in Sources */, 1AA14A782CDDA30D00B763A6 /* TotalCalendarTextBubble.swift in Sources */, diff --git a/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift b/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift new file mode 100644 index 0000000..d99aee0 --- /dev/null +++ b/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift @@ -0,0 +1,34 @@ +// +// ToastViewModel.swift +// FiveGuyes +// +// Created by 신혜연 on 11/20/24. +// + +import SwiftUI + +class ToastViewModel: ObservableObject { + @Published var message: String? + @Published var isVisible: Bool = false + private var timer: Timer? + + // 타이머 1.5초 + func showToast(message: String, duration: TimeInterval = 1.0) { + self.message = message + self.isVisible = true + + timer?.invalidate() + timer = Timer.scheduledTimer(withTimeInterval: duration, repeats: false) { [weak self] _ in + self?.hideToast() + } + } + + private func hideToast() { + withAnimation { + self.isVisible = false + } + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.message = nil + } + } +} diff --git a/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift b/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift index 07a0eea..4f67cbb 100644 --- a/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift +++ b/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift @@ -8,66 +8,45 @@ import SwiftUI struct ToastView: View { - var message: String - var body: some View { - VStack(spacing: 0) { - Spacer() - Text(message) - .font(.system(size: 16, weight: .semibold)) - .padding(.horizontal, 20) - .padding(.vertical, 14) - .foregroundColor(.white) - .background(Color.gray) - .cornerRadius(16) - } - } -} - -class ToastModel: ObservableObject { - @Published var message: String? - @Published var isVisible: Bool = false - private var timer: Timer? + @ObservedObject var viewModel: ToastViewModel - func showToast(message: String, duration: TimeInterval = 1.0) { - self.message = message - self.isVisible = true - - timer?.invalidate() - - timer = Timer.scheduledTimer(withTimeInterval: duration, repeats: false) { [weak self] _ in - DispatchQueue.main.async { - withAnimation { - self?.isVisible = false - } - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - self?.message = nil + var body: some View { + ZStack { + VStack { + Spacer() + if let message = viewModel.message, viewModel.isVisible { + Text(message) + .font(.system(size: 16, weight: .semibold)) + .padding(.horizontal, 20) + .padding(.vertical, 14) + .foregroundColor(.white) + .background(Color.gray) + .cornerRadius(16) + .transition(.opacity) + .animation(.easeInOut(duration: 0.5), value: viewModel.isVisible) + .zIndex(1) } } } } } - struct ToastTestView: View { - @StateObject private var toastViewModel = ToastModel() - - var body: some View { - ZStack { - VStack { - Button("Show Toast") { - toastViewModel.showToast(message: "오늘은 완독하는 마지막 날이에요!") - } - } - - if let message = toastViewModel.message { - ToastView(message: message) - .opacity(toastViewModel.isVisible ? 1.0 : 0.0) - .animation(.easeInOut(duration: 0.5), value: toastViewModel.isVisible) - .transition(.opacity) - .zIndex(1) +struct ToastTestView: View { + @StateObject private var toastViewModel = ToastViewModel() + + var body: some View { + ZStack { + VStack(spacing: 20) { + Button { + toastViewModel.showToast(message: "오늘은 완독하는 마지막날이에요!") + } label: { + Text("Show Toast") } } + ToastView(viewModel: toastViewModel) } } +} #Preview { ToastTestView() From 5e5cd691dc2d180536f2158288b431d659367094 Mon Sep 17 00:00:00 2001 From: hyeyeonie Date: Thu, 21 Nov 2024 01:16:56 +0900 Subject: [PATCH 3/4] =?UTF-8?q?fix:=20#86=20Change=20Optional=20Type=20-?= =?UTF-8?q?=20nil=20=EB=8C=80=EC=8B=A0=20=EA=B8=B0=EB=B3=B8=EA=B0=92?= =?UTF-8?q?=EC=9D=84=20=EB=B9=88=20=EB=AC=B8=EC=9E=90=EC=97=B4=EB=A1=9C=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift | 8 ++++---- .../FiveGuyes/Sources/Views/Components/ToastView.swift | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift b/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift index d99aee0..ac62f16 100644 --- a/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift +++ b/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift @@ -8,7 +8,7 @@ import SwiftUI class ToastViewModel: ObservableObject { - @Published var message: String? + @Published var message: String = "" @Published var isVisible: Bool = false private var timer: Timer? @@ -27,8 +27,8 @@ class ToastViewModel: ObservableObject { withAnimation { self.isVisible = false } - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - self.message = nil - } +// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { +// self.message = nil +// } } } diff --git a/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift b/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift index 4f67cbb..ff56bd0 100644 --- a/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift +++ b/FiveGuyes/FiveGuyes/Sources/Views/Components/ToastView.swift @@ -14,8 +14,8 @@ struct ToastView: View { ZStack { VStack { Spacer() - if let message = viewModel.message, viewModel.isVisible { - Text(message) + if viewModel.isVisible { + Text(viewModel.message) .font(.system(size: 16, weight: .semibold)) .padding(.horizontal, 20) .padding(.vertical, 14) From eb2838dc414eecbe773097b803349f7ae53b2d83 Mon Sep 17 00:00:00 2001 From: hyeyeonie Date: Thu, 21 Nov 2024 14:58:33 +0900 Subject: [PATCH 4/4] fix: #86 Delete Comment --- FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift b/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift index ac62f16..736561d 100644 --- a/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift +++ b/FiveGuyes/FiveGuyes/Sources/Stores/ToastViewModel.swift @@ -27,8 +27,5 @@ class ToastViewModel: ObservableObject { withAnimation { self.isVisible = false } -// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { -// self.message = nil -// } } }