From a7fb44c76628deedb19c1c65c73eae03284fcc33 Mon Sep 17 00:00:00 2001 From: LEO Yoon-Tsaw Date: Wed, 9 Oct 2024 14:33:43 -0400 Subject: [PATCH] bug fix --- Chinendar-Tests/Chinendar_Tests.swift | 12 ++++++++++ Chinendar.xcodeproj/project.pbxproj | 8 +++---- Shared/DataModel/DataClass.swift | 28 ++++++++++++++++++++++ Shared/DataModel/DataModel.swift | 16 ++++++------- Shared/Setting/CalendarConfig.swift | 3 ++- Shared/Setting/Location.swift | 2 +- Shared/Siri/AppEntity.swift | 2 +- Shared/Siri/AppIntent.swift | 2 +- Vision/visionApp.swift | 27 +-------------------- Watch/watchApp.swift | 34 +-------------------------- Widget/Protocols.swift | 4 ++-- iOS/iOSApp.swift | 27 +-------------------- macOS/macApp.swift | 27 +-------------------- 13 files changed, 63 insertions(+), 129 deletions(-) diff --git a/Chinendar-Tests/Chinendar_Tests.swift b/Chinendar-Tests/Chinendar_Tests.swift index 65dddde..d9472ee 100644 --- a/Chinendar-Tests/Chinendar_Tests.swift +++ b/Chinendar-Tests/Chinendar_Tests.swift @@ -99,4 +99,16 @@ struct Chinendar_Tests { let calendar = chineseCalendar.calendar #expect(calendar.isDate(start, equalTo: targetDate, toGranularity: .day)) } + + @Test("Date conversion", arguments: [ + (TimeZone(identifier: "America/New_York")!, GeoLocation(lat: 40, lon: -74), false, "九月八日巳時七刻四"), + (TimeZone(identifier: "Asia/Seoul")!, GeoLocation(lat: 40, lon: 135), false, "九月八日子時二刻五"), + (TimeZone(identifier: "Asia/Shanghai")!, GeoLocation(lat: 40, lon: 116), false, "九月七日亥時七刻四"), + (TimeZone(identifier: "Asia/Shanghai")!, GeoLocation(lat: 34.52, lon: 108.94), true, "九月七日亥時五刻三") + ]) + func dateString(timezone: TimeZone, location: GeoLocation, apparentTime: Bool, targetString: String) async throws { + let testDate = Date.from(year: 2024, month: 10, day: 9, hour: 11, minute: 43, timezone: timeZone)! + let chineseCalendar = ChineseCalendar(time: testDate, timezone: timezone, location: location, globalMonth: true, apparentTime: apparentTime, largeHour: true) + #expect("\(chineseCalendar.dateString)\(chineseCalendar.timeString)" == targetString) + } } diff --git a/Chinendar.xcodeproj/project.pbxproj b/Chinendar.xcodeproj/project.pbxproj index 8595ed5..e27c3d1 100644 --- a/Chinendar.xcodeproj/project.pbxproj +++ b/Chinendar.xcodeproj/project.pbxproj @@ -1874,8 +1874,8 @@ D2E4E0F326F7C73F002F3716 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - APP_BUILD = 152; - APP_VERSION = 6.1.4; + APP_BUILD = 155; + APP_VERSION = 6.1.5; ASSETCATALOG_COMPILER_APPICON_NAME = ""; ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOL_FRAMEWORKS = SwiftUI; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; @@ -1951,8 +1951,8 @@ D2E4E0F426F7C73F002F3716 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - APP_BUILD = 152; - APP_VERSION = 6.1.4; + APP_BUILD = 155; + APP_VERSION = 6.1.5; ASSETCATALOG_COMPILER_APPICON_NAME = ""; ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOL_FRAMEWORKS = SwiftUI; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; diff --git a/Shared/DataModel/DataClass.swift b/Shared/DataModel/DataClass.swift index 7e47ba9..be48cff 100644 --- a/Shared/DataModel/DataClass.swift +++ b/Shared/DataModel/DataClass.swift @@ -501,6 +501,8 @@ protocol ViewModelType: AnyObject, Bindable { var chineseCalendar: ChineseCalendar { get set } var locationManager: LocationManager { get } var location: GeoLocation? { get } + var gpsLocation: GeoLocation? { get set } + var gpsLocationAvailable: Bool { get } var layoutInitialized: Bool { get } var configInitialized: Bool { get } @@ -509,6 +511,7 @@ protocol ViewModelType: AnyObject, Bindable { func updateLayout(from: String, updateSize: Bool) func updateConfig(from: String, newName: String?) func setup() + func clearLocation() } extension ViewModelType { @@ -526,6 +529,31 @@ extension ViewModelType { config.initialized } + var location: GeoLocation? { + Task(priority: .userInitiated) { + let gpsLoc = try await locationManager.getLocation(wait: .seconds(1)) + if gpsLoc != gpsLocation { + gpsLocation = gpsLoc + } + } + if config.locationEnabled { + return gpsLocation ?? config.customLocation + } else { + return config.customLocation + } + } + + var gpsLocationAvailable: Bool { + gpsLocation != nil && config.locationEnabled + } + + func clearLocation() { + gpsLocation = nil + Task(priority: .userInitiated) { + await locationManager.clearLocation() + } + } + func layoutString(includeOffset: Bool = true, includeColor: Bool = true) -> String { watchLayout.encode(includeOffset: includeOffset, includeColor: includeColor) } diff --git a/Shared/DataModel/DataModel.swift b/Shared/DataModel/DataModel.swift index 8ba7b94..df9bf25 100644 --- a/Shared/DataModel/DataModel.swift +++ b/Shared/DataModel/DataModel.swift @@ -164,8 +164,8 @@ extension ThemeData { } } let descriptor = FetchDescriptor(predicate: predicate, sortBy: [SortDescriptor(\.modifiedDate, order: .reverse)]) - var resultTheme: ThemeData? do { + var resultTheme: ThemeData? let themes = try context.fetch(descriptor) for theme in themes { if !theme.isNil && resultTheme == nil { @@ -175,10 +175,11 @@ extension ThemeData { } } try context.save() + return resultTheme } catch { print(error.localizedDescription) + return nil } - return resultTheme } @MainActor static func loadDefault() -> String { @@ -232,8 +233,8 @@ extension ConfigData { data.name == name } let descriptor = FetchDescriptor(predicate: predicate, sortBy: [SortDescriptor(\.modifiedDate, order: .reverse)]) - var resultConfig: ConfigData? do { + var resultConfig: ConfigData? let configs = try context.fetch(descriptor) for config in configs { if !config.isNil && resultConfig == nil { @@ -243,10 +244,11 @@ extension ConfigData { } } try context.save() + return resultConfig } catch { print(error.localizedDescription) + return nil } - return resultConfig } static func load(name: String, context: ModelContext) -> (name: String, code: String)? { @@ -406,13 +408,11 @@ extension LocalData: Identifiable, Hashable { descriptor.fetchLimit = 1 do { let records = try LocalDataModel.shared.modelExecutor.modelContext.fetch(descriptor) - if let record = records.first { - return record - } + return records.first } catch { print("Error fetching local data: \(error.localizedDescription)") + return nil } - return nil } static func update(deviceName: String? = nil, configName: String? = nil) { diff --git a/Shared/Setting/CalendarConfig.swift b/Shared/Setting/CalendarConfig.swift index 2587ebf..8cc660f 100644 --- a/Shared/Setting/CalendarConfig.swift +++ b/Shared/Setting/CalendarConfig.swift @@ -164,9 +164,10 @@ struct ConfigList: View { let chineseDate: String = { var calConfig = CalendarConfigure() calConfig.update(from: config.code!) + let location = calConfig.locationEnabled ? viewModel.gpsLocation ?? calConfig.customLocation : calConfig.customLocation let calendar = ChineseCalendar(time: viewModel.chineseCalendar.time, timezone: calConfig.effectiveTimezone, - location: viewModel.location, + location: location, globalMonth: calConfig.globalMonth, apparentTime: calConfig.apparentTime, largeHour: calConfig.largeHour) var displayText = [String]() diff --git a/Shared/Setting/Location.swift b/Shared/Setting/Location.swift index 4fa0fca..2cc5abd 100644 --- a/Shared/Setting/Location.swift +++ b/Shared/Setting/Location.swift @@ -132,7 +132,7 @@ struct LocationSelection: Equatable { get { LocationSelection.from(value: manualLocation?.lon ?? CGFloat(Calendar.current.timeZone.secondsFromGMT()) / 240) } set { - viewModel?.config.customLocation? = GeoLocation(lat: viewModel?.config.customLocation?.lat ?? 0, lon: newValue.value) + viewModel?.config.customLocation = GeoLocation(lat: viewModel?.config.customLocation?.lat ?? 0, lon: newValue.value) } } diff --git a/Shared/Siri/AppEntity.swift b/Shared/Siri/AppEntity.swift index 964110e..70990db 100644 --- a/Shared/Siri/AppEntity.swift +++ b/Shared/Siri/AppEntity.swift @@ -54,7 +54,7 @@ enum NextEventType: String, AppEnum { .lunarPhases: .init(title: "ET_MP"), .chineseHoliday: .init(title: "ET_HOLIDAY"), .sunriseSet: .init(title: "SUNRISE_SET"), - .moonriseSet: .init(title: "MOONRISE_SET"), + .moonriseSet: .init(title: "MOONRISE_SET") ] } diff --git a/Shared/Siri/AppIntent.swift b/Shared/Siri/AppIntent.swift index 456ffd6..5990672 100644 --- a/Shared/Siri/AppIntent.swift +++ b/Shared/Siri/AppIntent.swift @@ -62,7 +62,7 @@ struct ChinendarDate: AppIntent { } return .result(value: calendarString, dialog: IntentDialog(full: "MONTH\(chineseCalendar.monthStringLocalized)DAY\(chineseCalendar.dayStringLocalized)HOLIDAY\(Locale.translate(chineseCalendar.holidays.first ?? ""))HOUR\(chineseCalendar.hourStringLocalized)QUARTER\(chineseCalendar.quarterStringLocalized)", supporting: "LOOKUP_RESULT_PROMPT", systemImageName: "calendar.badge.clock")) { - Text(calendarString) + Text(String(calendarString.reversed())) .font(.system(size: 21, weight: .bold, design: .rounded)) .foregroundStyle(.primary) .minimumScaleFactor(0.5) diff --git a/Vision/visionApp.swift b/Vision/visionApp.swift index 3a87d70..92ea258 100644 --- a/Vision/visionApp.swift +++ b/Vision/visionApp.swift @@ -112,37 +112,12 @@ struct Chinendar: App { var settings = WatchSetting() var chineseCalendar = ChineseCalendar() @ObservationIgnored let locationManager = LocationManager.shared - private var _location: GeoLocation? + var gpsLocation: GeoLocation? private init() { self.setup() } - var location: GeoLocation? { - Task(priority: .userInitiated) { - let gpsLoc = try await locationManager.getLocation(wait: .seconds(1)) - if gpsLoc != _location { - _location = gpsLoc - } - } - if config.locationEnabled { - return _location ?? config.customLocation - } else { - return config.customLocation - } - } - - var gpsLocationAvailable: Bool { - _location != nil && config.locationEnabled - } - - func clearLocation() { - _location = nil - Task(priority: .userInitiated) { - await locationManager.clearLocation() - } - } - func autoSaveLayout() { withObservationTracking { _ = self.layoutString() diff --git a/Watch/watchApp.swift b/Watch/watchApp.swift index 4ef0c34..77a0b8d 100644 --- a/Watch/watchApp.swift +++ b/Watch/watchApp.swift @@ -44,44 +44,12 @@ struct Chinendar: App { var chineseCalendar = ChineseCalendar(compact: true) @ObservationIgnored lazy var watchConnectivity = WatchConnectivityManager(viewModel: self) @ObservationIgnored let locationManager = LocationManager.shared - private var _location: GeoLocation? + var gpsLocation: GeoLocation? private init() { self.setup() } - var location: GeoLocation? { - Task(priority: .userInitiated) { - let gpsLoc = try await locationManager.getLocation(wait: .seconds(1)) - if gpsLoc != _location { - _location = gpsLoc - } - } - if config.locationEnabled { - return _location ?? config.customLocation - } else { - return config.customLocation - } - } - - func clearLocation() { - _location = nil - Task(priority: .userInitiated) { - await locationManager.clearLocation() - } - } - - func updateGPSLocation(location: GeoLocation?) { - if let location { - _location = location - } else { - _location = nil - Task(priority: .userInitiated) { - await locationManager.clearLocation() - } - } - } - func autoSaveLayout() { withObservationTracking { _ = self.layoutString() diff --git a/Widget/Protocols.swift b/Widget/Protocols.swift index 14a2ee1..220d17a 100644 --- a/Widget/Protocols.swift +++ b/Widget/Protocols.swift @@ -26,13 +26,13 @@ extension ChinendarAppIntentTimelineProvider { } func snapshot(for configuration: Entry.Intent, in context: Context) async -> Entry { - let asyncModel = await AsyncModels(compact: compactCalendar(context: context)) + let asyncModel = await AsyncModels(compact: compactCalendar(context: context), calendarName: configuration.calendarConfig?.name) let entry = Entry(configuration: configuration, chineseCalendar: asyncModel.chineseCalendar, watchLayout: asyncModel.layout) return entry } func timeline(for configuration: Entry.Intent, in context: Context) async -> Timeline { - let asyncModel = await AsyncModels(compact: compactCalendar(context: context)) + let asyncModel = await AsyncModels(compact: compactCalendar(context: context), calendarName: configuration.calendarConfig?.name) let entryDates = nextEntryDates(chineseCalendar: asyncModel.chineseCalendar, config: configuration, context: context) let entries: [Entry] = await generateEntries(baseChineseCalendar: asyncModel.chineseCalendar, timeline: entryDates, watchLayout: asyncModel.layout, calendarConfig: asyncModel.config, configuration: configuration) return Timeline(entries: entries, policy: .atEnd) diff --git a/iOS/iOSApp.swift b/iOS/iOSApp.swift index c0688ca..34d4678 100644 --- a/iOS/iOSApp.swift +++ b/iOS/iOSApp.swift @@ -44,37 +44,12 @@ struct Chinendar: App { var chineseCalendar = ChineseCalendar() @ObservationIgnored lazy var watchConnectivity = WatchConnectivityManager(viewModel: self) @ObservationIgnored let locationManager = LocationManager.shared - private var _location: GeoLocation? + var gpsLocation: GeoLocation? private init() { self.setup() } - var location: GeoLocation? { - Task(priority: .userInitiated) { - let gpsLoc = try await locationManager.getLocation(wait: .seconds(1)) - if gpsLoc != _location { - _location = gpsLoc - } - } - if config.locationEnabled { - return _location ?? config.customLocation - } else { - return config.customLocation - } - } - - var gpsLocationAvailable: Bool { - _location != nil && config.locationEnabled - } - - func clearLocation() { - _location = nil - Task(priority: .userInitiated) { - await locationManager.clearLocation() - } - } - func autoSaveLayout() { withObservationTracking { _ = self.layoutString() diff --git a/macOS/macApp.swift b/macOS/macApp.swift index 30c7222..ab9e5e7 100644 --- a/macOS/macApp.swift +++ b/macOS/macApp.swift @@ -128,37 +128,12 @@ final class AppDelegate: NSObject, NSApplicationDelegate { var settings = WatchSetting() var chineseCalendar = ChineseCalendar() @ObservationIgnored let locationManager = LocationManager.shared - private var _location: GeoLocation? + var gpsLocation: GeoLocation? private init() { self.setup() } - var location: GeoLocation? { - Task(priority: .userInitiated) { - let gpsLoc = try await locationManager.getLocation(wait: .seconds(1)) - if gpsLoc != _location { - _location = gpsLoc - } - } - if config.locationEnabled { - return _location ?? config.customLocation - } else { - return config.customLocation - } - } - - var gpsLocationAvailable: Bool { - _location != nil && config.locationEnabled - } - - func clearLocation() { - _location = nil - Task(priority: .userInitiated) { - await locationManager.clearLocation() - } - } - func autoSaveLayout() { withObservationTracking { _ = self.layoutString()