From 0f3b86fe8c6ab99476ab070acaa737c07cb06fbc Mon Sep 17 00:00:00 2001 From: neon443 <69979447+neon443@users.noreply.github.com> Date: Wed, 28 May 2025 14:47:05 +0100 Subject: [PATCH] New: custom alert for merge/replace imported events --- NearFuture.xcodeproj/project.pbxproj | 2 - NearFuture/Views/Settings/ImportView.swift | 122 +++++++++++++++------ Shared/Model/Events.swift | 8 +- 3 files changed, 92 insertions(+), 40 deletions(-) diff --git a/NearFuture.xcodeproj/project.pbxproj b/NearFuture.xcodeproj/project.pbxproj index cc5191b..0f37a27 100644 --- a/NearFuture.xcodeproj/project.pbxproj +++ b/NearFuture.xcodeproj/project.pbxproj @@ -55,7 +55,6 @@ A98C20CE2DE7308E0008D61C /* ArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20CD2DE7308E0008D61C /* ArchiveView.swift */; }; A98C20D02DE731BD0008D61C /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20CF2DE731BD0008D61C /* HomeView.swift */; }; A98C20D42DE7339E0008D61C /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20D32DE7339E0008D61C /* AboutView.swift */; }; - A98C20D52DE7339E0008D61C /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20D32DE7339E0008D61C /* AboutView.swift */; }; A9FC7EEA2D2823920020D75B /* NearFutureWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FC7EE92D28238A0020D75B /* NearFutureWidgets.swift */; }; /* End PBXBuildFile section */ @@ -526,7 +525,6 @@ buildActionMask = 2147483647; files = ( A920C28C2D24011400E4F9B1 /* Events.swift in Sources */, - A98C20D52DE7339E0008D61C /* AboutView.swift in Sources */, A949F84B2DCAABE00064DCA0 /* ArchiveView.swift in Sources */, A914FA4F2DD276D200856265 /* AboutView.swift in Sources */, A949F84C2DCAABE00064DCA0 /* AddEventView.swift in Sources */, diff --git a/NearFuture/Views/Settings/ImportView.swift b/NearFuture/Views/Settings/ImportView.swift index 6694076..f545deb 100644 --- a/NearFuture/Views/Settings/ImportView.swift +++ b/NearFuture/Views/Settings/ImportView.swift @@ -15,47 +15,97 @@ struct ImportView: View { @State private var text: String = "Ready..." @State private var fgColor: Color = .yellow + @State private var showAlert: Bool = false + + @State private var replaceCurrentEvents: Bool = false + var body: some View { - List { - Section("Status") { - Label(text, systemImage: image) - .contentTransition(.numericText()) - .foregroundStyle(fgColor) - } - TextField("", text: $importStr) - Button() { - do throws { - try viewModel.importEvents(importStr) - withAnimation { - image = "checkmark.circle.fill" - text = "Complete" - fgColor = .green - } - } catch importError.invalidB64 { - withAnimation { - image = "xmark.app.fill" - text = "Invalid base64 input." - fgColor = .red - } - } catch { - withAnimation { - image = "xmark.app.fill" - text = error.localizedDescription - fgColor = .red - } + ZStack(alignment: .center) { + List { + Section("Status") { + Label(text, systemImage: image) + .contentTransition(.numericText()) + .foregroundStyle(fgColor) + } + TextField("", text: $importStr) + Button() { + withAnimation { + showAlert.toggle() + } + } label: { + Label("Import", systemImage: "tray.and.arrow.down.fill") + } + .disabled(importStr.isEmpty) + .onAppear() { + importStr = "" + image = "clock.fill" + text = "Ready..." + fgColor = .yellow } - } label: { - Label("Import", systemImage: "tray.and.arrow.down.fill") } - .disabled(importStr.isEmpty) - .onAppear() { - importStr = "" - image = "clock.fill" - text = "Ready..." - fgColor = .yellow + .blur(radius: showAlert ? 2 : 0) + Group { + Rectangle() + .frame(maxWidth: .infinity, maxHeight: .infinity) + .foregroundStyle(replaceCurrentEvents ? .red.opacity(0.3) : .black.opacity(0.2)) + .animation(.default, value: replaceCurrentEvents) + .ignoresSafeArea() + ZStack { + RoundedRectangle(cornerRadius: 30) + .foregroundStyle(.one.opacity(0.8)) + .blur(radius: 1) + VStack(alignment: .center) { + Text("Are you sure?") + .font(.largeTitle) + .bold() + .foregroundStyle(replaceCurrentEvents ? .red : .two) + .animation(.default, value: replaceCurrentEvents) + Text("This will replace your current events!") + .lineLimit(nil) + .multilineTextAlignment(.center) + .opacity(replaceCurrentEvents ? 1 : 0) + .animation(.default, value: replaceCurrentEvents) + .foregroundStyle(.two) + Toggle("Replace Events", isOn: $replaceCurrentEvents) + .foregroundStyle(.two) + Spacer() + Button() { + withAnimation { + showAlert.toggle() + } + do throws { + try viewModel.importEvents(importStr, replace: replaceCurrentEvents) + withAnimation { + image = "checkmark.circle.fill" + text = "Complete" + fgColor = .green + } + } catch importError.invalidB64 { + withAnimation { + image = "xmark.app.fill" + text = "Invalid base64 input." + fgColor = .red + } + } catch { + withAnimation { + image = "xmark.app.fill" + text = error.localizedDescription + fgColor = .red + } + } + } label: { + Text("yes") + .font(.title2) + .bold() + } + .buttonStyle(BorderedProminentButtonStyle()) + } + .padding() + } + .frame(maxWidth: 250, maxHeight: 250) } + .opacity(showAlert ? 1 : 0) } - } } diff --git a/Shared/Model/Events.swift b/Shared/Model/Events.swift index 29a3f28..331c85b 100644 --- a/Shared/Model/Events.swift +++ b/Shared/Model/Events.swift @@ -325,14 +325,18 @@ class EventViewModel: ObservableObject, @unchecked Sendable { return "" } - func importEvents(_ imported: String) throws { + func importEvents(_ imported: String, replace: Bool) throws { guard let data = Data(base64Encoded: imported) else { throw importError.invalidB64 } let decoder = JSONDecoder() do { let decoded = try decoder.decode([Event].self, from: data) - self.events = decoded + if replace { + self.events = decoded + } else { + self.events = self.events + decoded + } saveEvents() } catch { throw error