From 23f67763f464663832a3ea3e92be142a64864f90 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 28 Aug 2023 17:09:41 +1000 Subject: [PATCH] WIP: toast --- Session/Onboarding/LoadAccountView.swift | 11 +- SessionUIKit/Components/Toast.swift | 101 ++++++++++++------ .../Utilities/SwiftUI+Utilities.swift | 4 + 3 files changed, 78 insertions(+), 38 deletions(-) diff --git a/Session/Onboarding/LoadAccountView.swift b/Session/Onboarding/LoadAccountView.swift index fbf9bff22..51baa0919 100644 --- a/Session/Onboarding/LoadAccountView.swift +++ b/Session/Onboarding/LoadAccountView.swift @@ -48,7 +48,9 @@ struct LoadAccountView: View { private func continueWithSeed(seed: Data, onError: (() -> ())?) { if (seed.count != 16) { errorString = "recovery_password_error_generic".localized() - onError?() + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + onError?() + } return } let (ed25519KeyPair, x25519KeyPair) = try! Identity.generate(from: seed) @@ -272,12 +274,6 @@ struct ScanQRCodeView: View { maxWidth: .infinity, maxHeight: .infinity ) - - if let error: String = error, !error.isEmpty { - withAnimation(.easeIn(duration: 0.5)) { - Toast(error) - } - } } else { VStack( alignment: .center, @@ -305,6 +301,7 @@ struct ScanQRCodeView: View { .padding(.bottom, Values.massiveSpacing) } } + .toastView(message: $error) } private func requestCameraAccess() { diff --git a/SessionUIKit/Components/Toast.swift b/SessionUIKit/Components/Toast.swift index f5b9cb433..b0ba526f2 100644 --- a/SessionUIKit/Components/Toast.swift +++ b/SessionUIKit/Components/Toast.swift @@ -1,11 +1,54 @@ // Copyright © 2023 Rangeproof Pty Ltd. All rights reserved. import SwiftUI +import Combine -public struct Toast: View { - @State var dismiss: Bool = false +public struct ToastModifier: ViewModifier { + @Binding var message: String? + @State private var workItem: DispatchWorkItem? - let message: String + public func body(content: Content) -> some View { + content + .frame(maxWidth: .infinity, maxHeight: .infinity) + .overlay( + ZStack { + mainToastView() + }.animation(.spring(), value: message) + ) + .onReceive(Just(message)) { value in + showToast() + } + } + + @ViewBuilder func mainToastView() -> some View { + if let message: String = message { + ToastView(message) + } + } + + private func showToast() { + workItem?.cancel() + + let task = DispatchWorkItem { + dismissToast() + } + + workItem = task + DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: task) + } + + private func dismissToast() { + withAnimation { + message = nil + } + + workItem?.cancel() + workItem = nil + } +} + +public struct ToastView: View { + var message: String static let width: CGFloat = 320 static let height: CGFloat = 44 @@ -15,40 +58,36 @@ public struct Toast: View { } public var body: some View { - VStack { - Spacer() - - if !dismiss { - ZStack { - Capsule() - .foregroundColor(themeColor: .toast_background) - - Text(message) - .font(.system(size: Values.verySmallFontSize)) - .foregroundColor(themeColor: .textPrimary) - .multilineTextAlignment(.center) - .frame(maxWidth: .infinity) - .padding(.horizontal, Values.mediumSpacing) - } - .frame( - width: Self.width, - height: Self.height - ) - .padding(.bottom, Values.smallSpacing) - } - } - .onAppear { - Timer.scheduledTimerOnMainThread(withTimeInterval: 5) { _ in - withAnimation(.easeOut(duration: 0.5)) { - dismiss.toggle() - } + VStack( + spacing: 0 + ) { + ZStack { + Capsule() + .foregroundColor(themeColor: .toast_background) + + Text(message) + .font(.system(size: Values.verySmallFontSize)) + .foregroundColor(themeColor: .textPrimary) + .multilineTextAlignment(.center) + .frame(maxWidth: .infinity) + .padding(.horizontal, Values.mediumSpacing) } + .frame( + width: Self.width, + height: Self.height + ) } + .frame( + maxWidth: .infinity, + maxHeight: .infinity, + alignment: .bottom + ) + .padding(.bottom, Values.smallSpacing) } } struct Toast_Previews: PreviewProvider { static var previews: some View { - Toast("This QR code does not contain a Recovery Password.") + ToastView("Test message.") } } diff --git a/SessionUIKit/Utilities/SwiftUI+Utilities.swift b/SessionUIKit/Utilities/SwiftUI+Utilities.swift index 0e81f3807..550504629 100644 --- a/SessionUIKit/Utilities/SwiftUI+Utilities.swift +++ b/SessionUIKit/Utilities/SwiftUI+Utilities.swift @@ -84,6 +84,10 @@ extension View { .foregroundColor(themeColor: color) ) } + + public func toastView(message: Binding) -> some View { + self.modifier(ToastModifier(message: message)) + } } extension Binding {