mirror of
https://github.com/neon443/NearFuture.git
synced 2026-03-11 06:49:12 +00:00
minor fix
This commit is contained in:
Binary file not shown.
@@ -27,7 +27,7 @@ struct Event: Identifiable, Codable {
|
|||||||
var description: String
|
var description: String
|
||||||
var date: Date
|
var date: Date
|
||||||
var recurrence: RecurrenceType
|
var recurrence: RecurrenceType
|
||||||
|
|
||||||
enum RecurrenceType: String, Codable, CaseIterable {
|
enum RecurrenceType: String, Codable, CaseIterable {
|
||||||
case none, daily, weekly, monthly, yearly
|
case none, daily, weekly, monthly, yearly
|
||||||
}
|
}
|
||||||
@@ -41,16 +41,16 @@ struct ColorCodable: Codable {
|
|||||||
//for the brainrot kids: alpha is the opacity/transparency of the color,
|
//for the brainrot kids: alpha is the opacity/transparency of the color,
|
||||||
//alpha == 0 completely transparent
|
//alpha == 0 completely transparent
|
||||||
//alpha == 1 completely opaque
|
//alpha == 1 completely opaque
|
||||||
|
|
||||||
var color: Color {
|
var color: Color {
|
||||||
Color(red: red, green: green, blue: blue, opacity: alpha)
|
Color(red: red, green: green, blue: blue, opacity: alpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_ color: Color) {
|
init(_ color: Color) {
|
||||||
let uiColor = UIColor(color)
|
let uiColor = UIColor(color)
|
||||||
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
|
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
|
||||||
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
|
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
|
||||||
|
|
||||||
self.red = Double(r)
|
self.red = Double(r)
|
||||||
self.green = Double(g)
|
self.green = Double(g)
|
||||||
self.blue = Double(b)
|
self.blue = Double(b)
|
||||||
@@ -89,22 +89,22 @@ func daysUntilEvent(_ eventDate: Date, short: Bool) -> String {
|
|||||||
class EventViewModel: ObservableObject {
|
class EventViewModel: ObservableObject {
|
||||||
@Published var events: [Event] = []
|
@Published var events: [Event] = []
|
||||||
@Published var icloudData: [Event] = []
|
@Published var icloudData: [Event] = []
|
||||||
|
|
||||||
@Published var lastSync: Date? = nil
|
@Published var lastSync: Date? = nil
|
||||||
@Published var icloudEventCount: Int = 0
|
@Published var icloudEventCount: Int = 0
|
||||||
@Published var localEventCount: Int = 0
|
@Published var localEventCount: Int = 0
|
||||||
@Published var syncStatus: String = "Not Synced"
|
@Published var syncStatus: String = "Not Synced"
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
loadEvents()
|
loadEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
//appgroup or regular userdefaults
|
//appgroup or regular userdefaults
|
||||||
let appGroupUserDefaults = UserDefaults(suiteName: "group.com.neon443.NearFuture") ?? UserDefaults.standard
|
let appGroupUserDefaults = UserDefaults(suiteName: "group.com.neon443.NearFuture") ?? UserDefaults.standard
|
||||||
|
|
||||||
//icloud store
|
//icloud store
|
||||||
let icloudStore = NSUbiquitousKeyValueStore.default
|
let icloudStore = NSUbiquitousKeyValueStore.default
|
||||||
|
|
||||||
// load from icloud or local
|
// load from icloud or local
|
||||||
func loadEvents() {
|
func loadEvents() {
|
||||||
//load icloud 1st
|
//load icloud 1st
|
||||||
@@ -115,7 +115,7 @@ class EventViewModel: ObservableObject {
|
|||||||
self.events = decodedIcEvents
|
self.events = decodedIcEvents
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if events.isEmpty, let savedData = appGroupUserDefaults.data(forKey: "events") {
|
if events.isEmpty, let savedData = appGroupUserDefaults.data(forKey: "events") {
|
||||||
let decoder = JSONDecoder()
|
let decoder = JSONDecoder()
|
||||||
if let decodedEvents = try? decoder.decode([Event].self, from: savedData) {
|
if let decodedEvents = try? decoder.decode([Event].self, from: savedData) {
|
||||||
@@ -124,35 +124,35 @@ class EventViewModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
updateSyncStatus()
|
updateSyncStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
// save to local and icloud
|
// save to local and icloud
|
||||||
func saveEvents() {
|
func saveEvents() {
|
||||||
let encoder = JSONEncoder()
|
let encoder = JSONEncoder()
|
||||||
if let encoded = try? encoder.encode(events) {
|
if let encoded = try? encoder.encode(events) {
|
||||||
appGroupUserDefaults.set(encoded, forKey: "events")
|
appGroupUserDefaults.set(encoded, forKey: "events")
|
||||||
|
|
||||||
//sync
|
//sync
|
||||||
icloudStore.set(encoded, forKey: "events")
|
icloudStore.set(encoded, forKey: "events")
|
||||||
icloudStore.synchronize()
|
icloudStore.synchronize()
|
||||||
|
|
||||||
updateSyncStatus()
|
updateSyncStatus()
|
||||||
loadEvents()
|
loadEvents()
|
||||||
WidgetCenter.shared.reloadAllTimelines()//reload all widgets when saving events
|
WidgetCenter.shared.reloadAllTimelines()//reload all widgets when saving events
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateSyncStatus() {
|
private func updateSyncStatus() {
|
||||||
lastSync = Date()
|
lastSync = Date()
|
||||||
icloudEventCount = icloudData.count
|
icloudEventCount = icloudData.count
|
||||||
localEventCount = events.count
|
localEventCount = events.count
|
||||||
|
|
||||||
if icloudEventCount == localEventCount {
|
if icloudEventCount == localEventCount {
|
||||||
syncStatus = "Successful"
|
syncStatus = "Successful"
|
||||||
} else {
|
} else {
|
||||||
syncStatus = "Pending"
|
syncStatus = "Pending"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addEvent(
|
func addEvent(
|
||||||
name: String,
|
name: String,
|
||||||
symbol: String,
|
symbol: String,
|
||||||
@@ -172,21 +172,21 @@ class EventViewModel: ObservableObject {
|
|||||||
events.append(newEvent)
|
events.append(newEvent)
|
||||||
saveEvents() //sync with icloud
|
saveEvents() //sync with icloud
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeEvent(at index: IndexSet) {
|
func removeEvent(at index: IndexSet) {
|
||||||
events.remove(atOffsets: index)
|
events.remove(atOffsets: index)
|
||||||
saveEvents() //sync local and icl
|
saveEvents() //sync local and icl
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasUbiquitousKeyValueStore() -> Bool {
|
func hasUbiquitousKeyValueStore() -> Bool {
|
||||||
let icloud = NSUbiquitousKeyValueStore.default
|
let icloud = NSUbiquitousKeyValueStore.default
|
||||||
|
|
||||||
let key = "com.neon443.NearFuture.testkey"
|
let key = "com.neon443.NearFuture.testkey"
|
||||||
let value = "testValue"
|
let value = "testValue"
|
||||||
|
|
||||||
icloud.set(value, forKey: key)
|
icloud.set(value, forKey: key)
|
||||||
icloud.synchronize()
|
icloud.synchronize()
|
||||||
|
|
||||||
if icloud.string(forKey: key) != nil {
|
if icloud.string(forKey: key) != nil {
|
||||||
// print("has UbiquitousKeyValueStore")
|
// print("has UbiquitousKeyValueStore")
|
||||||
icloud.removeObject(forKey: key)
|
icloud.removeObject(forKey: key)
|
||||||
@@ -199,36 +199,36 @@ class EventViewModel: ObservableObject {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sync() {
|
func sync() {
|
||||||
NSUbiquitousKeyValueStore.default.synchronize()
|
NSUbiquitousKeyValueStore.default.synchronize()
|
||||||
loadEvents()
|
loadEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
func replaceLocalWithiCloudData() {
|
func replaceLocalWithiCloudData() {
|
||||||
icloudStore.synchronize()
|
icloudStore.synchronize()
|
||||||
self.events = self.icloudData
|
self.events = self.icloudData
|
||||||
saveEvents()
|
saveEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
func replaceiCloudWithLocalData() {
|
func replaceiCloudWithLocalData() {
|
||||||
icloudStore.synchronize()
|
icloudStore.synchronize()
|
||||||
self.icloudData = self.events
|
self.icloudData = self.events
|
||||||
saveEvents()
|
saveEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
func exportEvents() -> String? {
|
func exportEvents() -> String? {
|
||||||
let encoder = JSONEncoder()
|
let encoder = JSONEncoder()
|
||||||
|
|
||||||
// Custom date encoding strategy to handle date formatting
|
// Custom date encoding strategy to handle date formatting
|
||||||
let dateFormatter = DateFormatter()
|
let dateFormatter = DateFormatter()
|
||||||
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
||||||
encoder.dateEncodingStrategy = .formatted(dateFormatter)
|
encoder.dateEncodingStrategy = .formatted(dateFormatter)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Encode the events array to JSON data
|
// Encode the events array to JSON data
|
||||||
let encodedData = try encoder.encode(events)
|
let encodedData = try encoder.encode(events)
|
||||||
|
|
||||||
// Convert the JSON data to a string
|
// Convert the JSON data to a string
|
||||||
if let jsonString = String(data: encodedData, encoding: .utf8) {
|
if let jsonString = String(data: encodedData, encoding: .utf8) {
|
||||||
return jsonString
|
return jsonString
|
||||||
@@ -241,26 +241,26 @@ class EventViewModel: ObservableObject {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func importEvents(_ imp: String) {
|
func importEvents(_ imp: String) {
|
||||||
guard let impData = imp.data(using: .utf8) else {
|
guard let impData = imp.data(using: .utf8) else {
|
||||||
print("Failed to convert string to data")
|
print("Failed to convert string to data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a JSONDecoder
|
// Create a JSONDecoder
|
||||||
let decoder = JSONDecoder()
|
let decoder = JSONDecoder()
|
||||||
|
|
||||||
// Add a custom date formatter for decoding the date string
|
// Add a custom date formatter for decoding the date string
|
||||||
let dateFormatter = DateFormatter()
|
let dateFormatter = DateFormatter()
|
||||||
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" // Adjust this to the date format you're using
|
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" // Adjust this to the date format you're using
|
||||||
decoder.dateDecodingStrategy = .formatted(dateFormatter)
|
decoder.dateDecodingStrategy = .formatted(dateFormatter)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Attempt to decode the events from the provided data
|
// Attempt to decode the events from the provided data
|
||||||
let decoded = try decoder.decode([Event].self, from: impData)
|
let decoded = try decoder.decode([Event].self, from: impData)
|
||||||
print("Successfully decoded events: \(decoded)")
|
print("Successfully decoded events: \(decoded)")
|
||||||
|
|
||||||
// Save and reload after importing events
|
// Save and reload after importing events
|
||||||
self.events = decoded
|
self.events = decoded
|
||||||
saveEvents()
|
saveEvents()
|
||||||
@@ -270,7 +270,7 @@ class EventViewModel: ObservableObject {
|
|||||||
print("Failed to decode events: \(error.localizedDescription)")
|
print("Failed to decode events: \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: Danger Zone
|
//MARK: Danger Zone
|
||||||
func dangerClearLocalData() {
|
func dangerClearLocalData() {
|
||||||
UserDefaults.standard.removeObject(forKey: "events")
|
UserDefaults.standard.removeObject(forKey: "events")
|
||||||
@@ -278,29 +278,29 @@ class EventViewModel: ObservableObject {
|
|||||||
events.removeAll()
|
events.removeAll()
|
||||||
updateSyncStatus()
|
updateSyncStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
func dangerCleariCloudData() {
|
func dangerCleariCloudData() {
|
||||||
icloudStore.removeObject(forKey: "events")
|
icloudStore.removeObject(forKey: "events")
|
||||||
icloudStore.synchronize()
|
icloudStore.synchronize()
|
||||||
icloudData.removeAll()
|
icloudData.removeAll()
|
||||||
updateSyncStatus()
|
updateSyncStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
func dangerResetLocalData() {
|
func dangerResetLocalData() {
|
||||||
let userDFDict = UserDefaults.standard.dictionaryRepresentation()
|
let userDFDict = UserDefaults.standard.dictionaryRepresentation()
|
||||||
for key in userDFDict.keys {
|
for key in userDFDict.keys {
|
||||||
UserDefaults.standard.removeObject(forKey: key)
|
UserDefaults.standard.removeObject(forKey: key)
|
||||||
}
|
}
|
||||||
|
|
||||||
let appGUSDDict = appGroupUserDefaults.dictionaryRepresentation()
|
let appGUSDDict = appGroupUserDefaults.dictionaryRepresentation()
|
||||||
for key in appGUSDDict.keys {
|
for key in appGUSDDict.keys {
|
||||||
appGroupUserDefaults.removeObject(forKey: key)
|
appGroupUserDefaults.removeObject(forKey: key)
|
||||||
}
|
}
|
||||||
|
|
||||||
events.removeAll()
|
events.removeAll()
|
||||||
updateSyncStatus()
|
updateSyncStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
func dangerResetiCloud() {
|
func dangerResetiCloud() {
|
||||||
let icloudDict = icloudStore.dictionaryRepresentation
|
let icloudDict = icloudStore.dictionaryRepresentation
|
||||||
for key in icloudDict.keys {
|
for key in icloudDict.keys {
|
||||||
@@ -315,7 +315,7 @@ class EventViewModel: ObservableObject {
|
|||||||
func describeOccurrence(date: Date, recurrence: Event.RecurrenceType) -> String {
|
func describeOccurrence(date: Date, recurrence: Event.RecurrenceType) -> String {
|
||||||
let dateString = date.formatted(date: .long, time: .omitted)
|
let dateString = date.formatted(date: .long, time: .omitted)
|
||||||
let recurrenceDescription: String
|
let recurrenceDescription: String
|
||||||
|
|
||||||
switch recurrence {
|
switch recurrence {
|
||||||
case .none:
|
case .none:
|
||||||
recurrenceDescription = "Occurs once on"
|
recurrenceDescription = "Occurs once on"
|
||||||
@@ -328,6 +328,6 @@ func describeOccurrence(date: Date, recurrence: Event.RecurrenceType) -> String
|
|||||||
case .yearly:
|
case .yearly:
|
||||||
recurrenceDescription = "Repeats every year from"
|
recurrenceDescription = "Repeats every year from"
|
||||||
}
|
}
|
||||||
|
|
||||||
return "\(recurrenceDescription) \(dateString)"
|
return "\(recurrenceDescription) \(dateString)"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
<array/>
|
<array/>
|
||||||
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
|
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
|
||||||
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
|
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
|
||||||
<false/>
|
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>group.com.neon443.NearFuture</string>
|
<string>group.com.neon443.NearFuture</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user