mirror of
https://github.com/neon443/NearFuture.git
synced 2026-03-11 06:49:12 +00:00
Fix import/Export events
rewrote the daysTillEventt()
This commit is contained in:
@@ -16,6 +16,9 @@
|
|||||||
A920C2BE2D24021A00E4F9B1 /* SFSymbolsPicker in Frameworks */ = {isa = PBXBuildFile; productRef = A920C2BD2D24021A00E4F9B1 /* SFSymbolsPicker */; };
|
A920C2BE2D24021A00E4F9B1 /* SFSymbolsPicker in Frameworks */ = {isa = PBXBuildFile; productRef = A920C2BD2D24021A00E4F9B1 /* SFSymbolsPicker */; };
|
||||||
A920C2C12D2403CA00E4F9B1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C2C02D2403CA00E4F9B1 /* ContentView.swift */; };
|
A920C2C12D2403CA00E4F9B1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C2C02D2403CA00E4F9B1 /* ContentView.swift */; };
|
||||||
A93BC0942D2B18A3002E8BBD /* StatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93BC0932D2B18A3002E8BBD /* StatsView.swift */; };
|
A93BC0942D2B18A3002E8BBD /* StatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93BC0932D2B18A3002E8BBD /* StatsView.swift */; };
|
||||||
|
A973B26C2DC551310028F8A2 /* ImportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A973B26B2DC551310028F8A2 /* ImportView.swift */; };
|
||||||
|
A973B2702DC552EB0028F8A2 /* ExportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A973B26F2DC552EB0028F8A2 /* ExportView.swift */; };
|
||||||
|
A973B2712DC553050028F8A2 /* ExportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A973B26F2DC552EB0028F8A2 /* ExportView.swift */; };
|
||||||
A977CC922DBBB48000DED8C0 /* ArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A977CC912DBBB48000DED8C0 /* ArchiveView.swift */; };
|
A977CC922DBBB48000DED8C0 /* ArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A977CC912DBBB48000DED8C0 /* ArchiveView.swift */; };
|
||||||
A977CC9A2DBD74FE00DED8C0 /* HelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A977CC992DBD74FE00DED8C0 /* HelpView.swift */; };
|
A977CC9A2DBD74FE00DED8C0 /* HelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A977CC992DBD74FE00DED8C0 /* HelpView.swift */; };
|
||||||
A979F57F2D26B1300094C0B3 /* EditEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A979F57E2D26B1300094C0B3 /* EditEventView.swift */; };
|
A979F57F2D26B1300094C0B3 /* EditEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A979F57E2D26B1300094C0B3 /* EditEventView.swift */; };
|
||||||
@@ -74,6 +77,8 @@
|
|||||||
A920C2B72D2401A300E4F9B1 /* AddEventView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddEventView.swift; sourceTree = "<group>"; };
|
A920C2B72D2401A300E4F9B1 /* AddEventView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddEventView.swift; sourceTree = "<group>"; };
|
||||||
A920C2C02D2403CA00E4F9B1 /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
A920C2C02D2403CA00E4F9B1 /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
A93BC0932D2B18A3002E8BBD /* StatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsView.swift; sourceTree = "<group>"; };
|
A93BC0932D2B18A3002E8BBD /* StatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsView.swift; sourceTree = "<group>"; };
|
||||||
|
A973B26B2DC551310028F8A2 /* ImportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportView.swift; sourceTree = "<group>"; };
|
||||||
|
A973B26F2DC552EB0028F8A2 /* ExportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExportView.swift; sourceTree = "<group>"; };
|
||||||
A977CC912DBBB48000DED8C0 /* ArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveView.swift; sourceTree = "<group>"; };
|
A977CC912DBBB48000DED8C0 /* ArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveView.swift; sourceTree = "<group>"; };
|
||||||
A977CC992DBD74FE00DED8C0 /* HelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpView.swift; sourceTree = "<group>"; };
|
A977CC992DBD74FE00DED8C0 /* HelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpView.swift; sourceTree = "<group>"; };
|
||||||
A979F57E2D26B1300094C0B3 /* EditEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditEventView.swift; sourceTree = "<group>"; };
|
A979F57E2D26B1300094C0B3 /* EditEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditEventView.swift; sourceTree = "<group>"; };
|
||||||
@@ -165,6 +170,8 @@
|
|||||||
A93BC0932D2B18A3002E8BBD /* StatsView.swift */,
|
A93BC0932D2B18A3002E8BBD /* StatsView.swift */,
|
||||||
A977CC992DBD74FE00DED8C0 /* HelpView.swift */,
|
A977CC992DBD74FE00DED8C0 /* HelpView.swift */,
|
||||||
A920C2B42D2401A100E4F9B1 /* SettingsView.swift */,
|
A920C2B42D2401A100E4F9B1 /* SettingsView.swift */,
|
||||||
|
A973B26B2DC551310028F8A2 /* ImportView.swift */,
|
||||||
|
A973B26F2DC552EB0028F8A2 /* ExportView.swift */,
|
||||||
A985104D2DB256430013D5FF /* iCloudSettingsView.swift */,
|
A985104D2DB256430013D5FF /* iCloudSettingsView.swift */,
|
||||||
A980FC302D920097006A778F /* Info.plist */,
|
A980FC302D920097006A778F /* Info.plist */,
|
||||||
A920C28D2D24011A00E4F9B1 /* Assets.xcassets */,
|
A920C28D2D24011A00E4F9B1 /* Assets.xcassets */,
|
||||||
@@ -361,8 +368,10 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
A920C2BB2D2401A400E4F9B1 /* AddEventView.swift in Sources */,
|
A920C2BB2D2401A400E4F9B1 /* AddEventView.swift in Sources */,
|
||||||
|
A973B26C2DC551310028F8A2 /* ImportView.swift in Sources */,
|
||||||
A98510502DB263F00013D5FF /* EventListView.swift in Sources */,
|
A98510502DB263F00013D5FF /* EventListView.swift in Sources */,
|
||||||
A920C2C12D2403CA00E4F9B1 /* ContentView.swift in Sources */,
|
A920C2C12D2403CA00E4F9B1 /* ContentView.swift in Sources */,
|
||||||
|
A973B2712DC553050028F8A2 /* ExportView.swift in Sources */,
|
||||||
A920C2B82D2401A300E4F9B1 /* SettingsView.swift in Sources */,
|
A920C2B82D2401A300E4F9B1 /* SettingsView.swift in Sources */,
|
||||||
A977CC9A2DBD74FE00DED8C0 /* HelpView.swift in Sources */,
|
A977CC9A2DBD74FE00DED8C0 /* HelpView.swift in Sources */,
|
||||||
A920C28C2D24011400E4F9B1 /* Item.swift in Sources */,
|
A920C28C2D24011400E4F9B1 /* Item.swift in Sources */,
|
||||||
@@ -389,6 +398,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
A973B2702DC552EB0028F8A2 /* ExportView.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -76,7 +76,9 @@ struct EventListView: View {
|
|||||||
.foregroundStyle(.one)
|
.foregroundStyle(.one)
|
||||||
}
|
}
|
||||||
Button() {
|
Button() {
|
||||||
event.complete.toggle()
|
withAnimation {
|
||||||
|
event.complete.toggle()
|
||||||
|
}
|
||||||
let eventToModify = viewModel.events.firstIndex() { currEvent in
|
let eventToModify = viewModel.events.firstIndex() { currEvent in
|
||||||
currEvent.id == event.id
|
currEvent.id == event.id
|
||||||
}
|
}
|
||||||
|
|||||||
27
NearFuture/ExportView.swift
Normal file
27
NearFuture/ExportView.swift
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// ExportView.swift
|
||||||
|
// NearFuture
|
||||||
|
//
|
||||||
|
// Created by neon443 on 02/05/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ExportView: View {
|
||||||
|
@ObservedObject var viewModel: EventViewModel
|
||||||
|
var body: some View {
|
||||||
|
List {
|
||||||
|
Button() {
|
||||||
|
UIPasteboard.general.string = viewModel.exportEvents()
|
||||||
|
} label: {
|
||||||
|
Label("Copy Events", systemImage: "document.on.clipboard")
|
||||||
|
}
|
||||||
|
Text(viewModel.exportEvents())
|
||||||
|
.textSelection(.enabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
ExportView(viewModel: dummyEventViewModel())
|
||||||
|
}
|
||||||
61
NearFuture/ImportView.swift
Normal file
61
NearFuture/ImportView.swift
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
//
|
||||||
|
// ImportView.swift
|
||||||
|
// NearFuture
|
||||||
|
//
|
||||||
|
// Created by neon443 on 02/05/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ImportView: View {
|
||||||
|
@ObservedObject var viewModel: EventViewModel
|
||||||
|
@Binding var importStr: String
|
||||||
|
|
||||||
|
@State private var image: String = "clock.fill"
|
||||||
|
@State private var text: String = "Ready..."
|
||||||
|
@State private var fgColor: Color = .yellow
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
Label("Import", systemImage: "tray.and.arrow.down.fill")
|
||||||
|
}
|
||||||
|
.disabled(importStr.isEmpty)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
ImportView(
|
||||||
|
viewModel: dummyEventViewModel(),
|
||||||
|
importStr: .constant("kljadfskljafdlkj;==")
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -35,7 +35,22 @@ struct Event: Identifiable, Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ColorCodable: Codable {
|
struct ColorCodable: Codable, Equatable {
|
||||||
|
init(_ color: Color) {
|
||||||
|
let uiColor = UIColor(color)
|
||||||
|
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 1.0
|
||||||
|
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
|
||||||
|
|
||||||
|
self.red = Double(r)
|
||||||
|
self.green = Double(g)
|
||||||
|
self.blue = Double(b)
|
||||||
|
}
|
||||||
|
init(red: Double, green: Double, blue: Double) {
|
||||||
|
self.red = red
|
||||||
|
self.green = green
|
||||||
|
self.blue = blue
|
||||||
|
}
|
||||||
|
|
||||||
var red: Double
|
var red: Double
|
||||||
var green: Double
|
var green: Double
|
||||||
var blue: Double
|
var blue: Double
|
||||||
@@ -57,103 +72,34 @@ struct ColorCodable: Codable {
|
|||||||
self.blue = cc.blue
|
self.blue = cc.blue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_ color: Color) {
|
|
||||||
let uiColor = UIColor(color)
|
|
||||||
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 1.0
|
|
||||||
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
|
|
||||||
|
|
||||||
self.red = Double(r)
|
|
||||||
self.green = Double(g)
|
|
||||||
self.blue = Double(b)
|
|
||||||
}
|
|
||||||
init(red: Double, green: Double, blue: Double) {
|
|
||||||
self.red = red
|
|
||||||
self.green = green
|
|
||||||
self.blue = blue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func daysUntilEvent(_ eventDate: Date) -> (short: String, long: String) {
|
func daysUntilEvent(_ eventDate: Date) -> (long: String, short: String) {
|
||||||
let calendar = Calendar.current
|
let calendar = Calendar.current
|
||||||
let currentDate = Date()
|
let now = Date()
|
||||||
let components = calendar.dateComponents([.day, .hour, .minute], from: currentDate, to: eventDate)
|
|
||||||
guard let days = components.day else {
|
|
||||||
return ("N/A", "N/A")
|
|
||||||
}
|
|
||||||
guard let hours = components.hour else {
|
|
||||||
return ("N/A", "N/A")
|
|
||||||
}
|
|
||||||
guard let minutes = components.minute else {
|
|
||||||
return ("N/A", "N/A")
|
|
||||||
}
|
|
||||||
|
|
||||||
enum RetUnit {
|
let isToday = calendar.isDate(now, inSameDayAs: eventDate)
|
||||||
case days
|
let components = calendar.dateComponents([.second, .day], from: now, to: eventDate)
|
||||||
case hours
|
|
||||||
case minutes
|
guard !isToday else { return ("Today", "Today") }
|
||||||
}
|
let secsComponents = eventDate.timeIntervalSinceNow
|
||||||
func ret(days: Int = 0, hours: Int = 0, minutes: Int = 0, unit: RetUnit) -> (String, String) {
|
guard let daysCompontents = components.day else { return ("N/A", "N/A") }
|
||||||
var future: Bool = true
|
let secs = Double(secsComponents)
|
||||||
var days = days
|
var days = 0
|
||||||
var hours = hours
|
var long = ""
|
||||||
var minutes = minutes
|
var short = ""
|
||||||
if days < 0 || hours < 0 || minutes < 0 {
|
if secs < 0 {
|
||||||
future = false
|
|
||||||
days.negate()
|
|
||||||
hours.negate()
|
|
||||||
minutes.negate()
|
|
||||||
} else {
|
|
||||||
future = true
|
|
||||||
}
|
|
||||||
switch unit {
|
|
||||||
case .days:
|
|
||||||
return (
|
|
||||||
"\(future ? "" : "-")\(days)d",
|
|
||||||
"\(days) day\(plu(days)) \(future ? "" : "ago")"
|
|
||||||
)
|
|
||||||
case .hours:
|
|
||||||
return (
|
|
||||||
"\(future ? "" : "-")\(hours)h",
|
|
||||||
"\(hours) hour\(plu(hours)) \(future ? "" : "ago")"
|
|
||||||
)
|
|
||||||
case .minutes:
|
|
||||||
return (
|
|
||||||
"\(future ? "" : "-")\(minutes)m",
|
|
||||||
"\(minutes) min\(plu(minutes)) \(future ? "" : "ago")"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch eventDate > Date() {
|
|
||||||
case true:
|
|
||||||
//future
|
|
||||||
if days == 0 {
|
|
||||||
if hours == 0 {
|
|
||||||
//less than 1h
|
|
||||||
return ret(minutes: minutes, unit: .minutes)
|
|
||||||
} else {
|
|
||||||
//less than 24h
|
|
||||||
return ret(hours: hours, unit: .hours)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//grater than 24h
|
|
||||||
return ret(days: days, unit: .days)
|
|
||||||
}
|
|
||||||
case false:
|
|
||||||
//past
|
//past
|
||||||
if days == 0 {
|
days = Int(floor(secs/86400))
|
||||||
if hours == 0 {
|
long = "\(-days) day\(plu(days)) ago"
|
||||||
//less than 1h
|
short = "\(days)d"
|
||||||
return ret(minutes: minutes, unit: .minutes)
|
} else {
|
||||||
} else {
|
//future
|
||||||
//less than 24h
|
days = Int(ceil(secs/86400))
|
||||||
return ret(hours: hours, unit: .hours)
|
long = "\(days) day\(plu(days))"
|
||||||
}
|
short = "\(days)d"
|
||||||
} else {
|
|
||||||
//grater than 24h
|
|
||||||
return ret(days: days, unit: .days)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return (long, short)
|
||||||
}
|
}
|
||||||
|
|
||||||
class EventViewModel: ObservableObject {
|
class EventViewModel: ObservableObject {
|
||||||
@@ -297,57 +243,25 @@ class EventViewModel: ObservableObject {
|
|||||||
saveEvents()
|
saveEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
func exportEvents() -> String? {
|
func exportEvents() -> String {
|
||||||
let encoder = JSONEncoder()
|
let encoder = JSONEncoder()
|
||||||
|
if let json = try? encoder.encode(self.events) {
|
||||||
// Custom date encoding strategy to handle date formatting
|
return "\(json.base64EncodedString())"
|
||||||
let dateFormatter = DateFormatter()
|
|
||||||
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
|
||||||
encoder.dateEncodingStrategy = .formatted(dateFormatter)
|
|
||||||
|
|
||||||
do {
|
|
||||||
// Encode the events array to JSON data
|
|
||||||
let encodedData = try encoder.encode(events)
|
|
||||||
|
|
||||||
// Convert the JSON data to a string
|
|
||||||
if let jsonString = String(data: encodedData, encoding: .utf8) {
|
|
||||||
return jsonString
|
|
||||||
} else {
|
|
||||||
print("Failed to convert encoded data to string")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
print("Failed to encode events: \(error.localizedDescription)")
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func importEvents(_ imp: String) {
|
func importEvents(_ imported: String) throws {
|
||||||
guard let impData = imp.data(using: .utf8) else {
|
guard let data = Data(base64Encoded: imported) else {
|
||||||
print("Failed to convert string to data")
|
throw importError.invalidB64
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a JSONDecoder
|
|
||||||
let decoder = JSONDecoder()
|
let decoder = JSONDecoder()
|
||||||
|
|
||||||
// Add a custom date formatter for decoding the date string
|
|
||||||
let dateFormatter = DateFormatter()
|
|
||||||
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" // Adjust this to the date format you're using
|
|
||||||
decoder.dateDecodingStrategy = .formatted(dateFormatter)
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Attempt to decode the events from the provided data
|
let decoded = try decoder.decode([Event].self, from: data)
|
||||||
let decoded = try decoder.decode([Event].self, from: impData)
|
|
||||||
print("Successfully decoded events: \(decoded)")
|
|
||||||
|
|
||||||
// Save and reload after importing events
|
|
||||||
self.events = decoded
|
self.events = decoded
|
||||||
saveEvents()
|
saveEvents()
|
||||||
loadEvents()
|
|
||||||
} catch {
|
} catch {
|
||||||
// Print error if decoding fails
|
throw error
|
||||||
print("Failed to decode events: \(error.localizedDescription)")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,3 +358,7 @@ func plu(_ inp: Int) -> String {
|
|||||||
if inp < 0 { input.negate() }
|
if inp < 0 { input.negate() }
|
||||||
return "\(input == 1 ? "" : "s")"
|
return "\(input == 1 ? "" : "s")"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum importError: Error {
|
||||||
|
case invalidB64
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct SettingsView: View {
|
struct SettingsView: View {
|
||||||
@State var viewModel: EventViewModel
|
@ObservedObject var viewModel: EventViewModel
|
||||||
|
|
||||||
@State private var hasUbiquitous: Bool = false
|
@State private var hasUbiquitous: Bool = false
|
||||||
@State private var lastSyncWasSuccessful: Bool = false
|
@State private var lastSyncWasSuccessful: Bool = false
|
||||||
@@ -68,47 +68,17 @@ struct SettingsView: View {
|
|||||||
viewModel.sync()
|
viewModel.sync()
|
||||||
updateStatus()
|
updateStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigationLink() {
|
NavigationLink() {
|
||||||
NavigationStack() {
|
ImportView(viewModel: viewModel, importStr: $importStr)
|
||||||
Button() {
|
|
||||||
UIPasteboard.general.string = "\(viewModel.exportEvents() ?? "")"
|
|
||||||
print(viewModel.exportEvents() as Any)
|
|
||||||
} label: {
|
|
||||||
Text("copy")
|
|
||||||
}
|
|
||||||
Text("\(viewModel.exportEvents() ?? "")")
|
|
||||||
}
|
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "list.bullet.rectangle")
|
Label("Import Events", systemImage: "tray.and.arrow.down.fill")
|
||||||
Text("Export events")
|
.foregroundStyle(.one)
|
||||||
}
|
}
|
||||||
NavigationLink() {
|
NavigationLink() {
|
||||||
NavigationStack() {
|
ExportView(viewModel: viewModel)
|
||||||
VStack {
|
|
||||||
TextEditor(text: $importStr)
|
|
||||||
.foregroundStyle(.foreground, .gray)
|
|
||||||
.background(.gray)
|
|
||||||
.frame(width: 200, height: 400)
|
|
||||||
.shadow(radius: 5)
|
|
||||||
Button() {
|
|
||||||
viewModel.importEvents(importStr)
|
|
||||||
} label: {
|
|
||||||
Text("import events")
|
|
||||||
}
|
|
||||||
.buttonStyle(BorderedProminentButtonStyle())
|
|
||||||
Button() {
|
|
||||||
if let pb = UIPasteboard.general.string {
|
|
||||||
print(pb)
|
|
||||||
}
|
|
||||||
} label: {
|
|
||||||
Text("print pb")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "square.and.arrow.down")
|
Label("Export Events", systemImage: "square.and.arrow.up")
|
||||||
Text("Import events")
|
.foregroundStyle(.one)
|
||||||
}
|
}
|
||||||
|
|
||||||
Section("Tip") {
|
Section("Tip") {
|
||||||
@@ -147,7 +117,3 @@ struct SettingsView: View {
|
|||||||
#Preview {
|
#Preview {
|
||||||
SettingsView(viewModel: dummyEventViewModel())
|
SettingsView(viewModel: dummyEventViewModel())
|
||||||
}
|
}
|
||||||
|
|
||||||
func test() -> Void {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -191,6 +191,6 @@ struct iCloudSettingsView: View {
|
|||||||
lastSyncWasNormalAgo: .constant(true),
|
lastSyncWasNormalAgo: .constant(true),
|
||||||
localCountEqualToiCloud: .constant(true),
|
localCountEqualToiCloud: .constant(true),
|
||||||
icloudCountEqualToLocal: .constant(true),
|
icloudCountEqualToLocal: .constant(true),
|
||||||
updateStatus: test
|
updateStatus: {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user