From 07d8dd0a3b325d33371951cb3c3b56d0e23e4bc3 Mon Sep 17 00:00:00 2001 From: LEO Yoon-Tsaw Date: Tue, 23 Apr 2024 20:37:55 -0400 Subject: [PATCH] Bug fix and UI improvement * Fix macOS App iCloud sync issue * Improve macOS App list hover highlight effect * Reduce color gap on edge of rings Revert "Bug fix and UI improvement" This reverts commit d694289877d81270df6e429973e8506deb7c9d39. Squashed commit of the following: commit 6a682e69ff4e567f93f608ba897ea9e1becf58f6 Author: LEO Yoon-Tsaw Date: Thu Apr 25 22:48:31 2024 -0400 Revert "Improve watchFace" This reverts commit a7adb53e7db2a7c95d133a66eeef5cbcf7a0dde3. commit 039fb89fac1627ead3558b17ac957ccb001a2000 Author: LEO Yoon-Tsaw Date: Thu Apr 25 22:52:23 2024 -0400 Fix commit c64bd0771b5da4373e83fe5bed77c9335cfa4231 Author: LEO Yoon-Tsaw Date: Tue Apr 23 20:44:01 2024 -0400 Xcode 15.3 commit a8b1bce1e473bab44c4e7fae9596ecccd8ac44f7 Author: LEO Yoon-Tsaw Date: Sun Apr 21 18:04:47 2024 -0400 Fix iCloud syncing problem on macOS commit 005dafda627fc318c080a23406d0d4fa50f2e0da Author: LEO Yoon-Tsaw Date: Wed Apr 17 21:56:47 2024 -0400 fix commit bd2afc6d70f45eee1a7492f07f06301e22cdae21 Author: LEO Yoon-Tsaw Date: Wed Apr 17 21:55:40 2024 -0400 Improve macOS config list commit a7adb53e7db2a7c95d133a66eeef5cbcf7a0dde3 Author: LEO Yoon-Tsaw Date: Wed Apr 17 20:23:08 2024 -0400 Improve watchFace commit 3569aeca216d9036b2b3a5cd4b9da43ac9e7e089 Author: LEO Yoon-Tsaw Date: Tue Apr 16 22:50:38 2024 -0400 Add preview for watchFace commit ae77977e02f0df563e139c3161790efbf5e5c527 Author: LEO Yoon-Tsaw Date: Tue Apr 16 21:13:25 2024 -0400 Disbale deleting current config on watch --- Chinendar.xcodeproj/project.pbxproj | 20 ++++++-- README.md | 2 +- Shared/Localizable.xcstrings | 5 +- Shared/Setting/CalendarConfig.swift | 7 +-- Shared/Setting/ThemesList.swift | 75 +++++++++++++++++++++++------ Shared/Views/WatchFaceView.swift | 10 ++++ Watch/Views/SwitchConfig.swift | 1 + 7 files changed, 94 insertions(+), 26 deletions(-) diff --git a/Chinendar.xcodeproj/project.pbxproj b/Chinendar.xcodeproj/project.pbxproj index b7b5180..534e0b4 100644 --- a/Chinendar.xcodeproj/project.pbxproj +++ b/Chinendar.xcodeproj/project.pbxproj @@ -159,6 +159,7 @@ B3C68B1C2B5DE90800FC08E3 /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3C68B1B2B5DE90800FC08E3 /* Protocols.swift */; }; B3C68B1D2B5DE90800FC08E3 /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3C68B1B2B5DE90800FC08E3 /* Protocols.swift */; }; B3C68B1E2B5DE94300FC08E3 /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3C68B1B2B5DE90800FC08E3 /* Protocols.swift */; }; + B3CB52EB2BD5BD9000A94804 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3CB52EA2BD5BD9000A94804 /* CloudKit.framework */; }; B3CC8B9C2A0B30BB0063DE44 /* iOSWidgetBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3CC8B9B2A0B30BB0063DE44 /* iOSWidgetBundle.swift */; }; B3CC8BA12A0B30BC0063DE44 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B3CC8BA02A0B30BC0063DE44 /* Assets.xcassets */; }; B3CC8BA72A0B30BC0063DE44 /* Chinendar Widget.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = B3CC8B972A0B30BB0063DE44 /* Chinendar Widget.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -370,6 +371,7 @@ B3BFA2562A05E0590018F99E /* WatchConnectivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchConnectivity.swift; sourceTree = ""; }; B3C68B182B5DDC4B00FC08E3 /* Card.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Card.swift; sourceTree = ""; }; B3C68B1B2B5DE90800FC08E3 /* Protocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Protocols.swift; sourceTree = ""; }; + B3CB52EA2BD5BD9000A94804 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; }; B3CC8B972A0B30BB0063DE44 /* Chinendar Widget.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Chinendar Widget.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; B3CC8B9B2A0B30BB0063DE44 /* iOSWidgetBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSWidgetBundle.swift; sourceTree = ""; }; B3CC8BA02A0B30BC0063DE44 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -452,6 +454,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B3CB52EB2BD5BD9000A94804 /* CloudKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -588,6 +591,14 @@ path = Watch; sourceTree = ""; }; + B3CB52E92BD5BD9000A94804 /* Frameworks */ = { + isa = PBXGroup; + children = ( + B3CB52EA2BD5BD9000A94804 /* CloudKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; B3CC8B9A2A0B30BB0063DE44 /* iOSWidget */ = { isa = PBXGroup; children = ( @@ -674,6 +685,7 @@ B3CC8B9A2A0B30BB0063DE44 /* iOSWidget */, B3CC8BF12A0C7E300063DE44 /* WatchWidget */, D2E4E0E326F7C73E002F3716 /* Products */, + B3CB52E92BD5BD9000A94804 /* Frameworks */, ); sourceTree = ""; }; @@ -1685,8 +1697,8 @@ D2E4E0F326F7C73F002F3716 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - APP_BUILD = 131; - APP_VERSION = 5.4; + APP_BUILD = 132; + APP_VERSION = 5.4.1; ASSETCATALOG_COMPILER_APPICON_NAME = ""; ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOL_FRAMEWORKS = SwiftUI; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; @@ -1765,8 +1777,8 @@ D2E4E0F426F7C73F002F3716 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - APP_BUILD = 131; - APP_VERSION = 5.4; + APP_BUILD = 132; + APP_VERSION = 5.4.1; ASSETCATALOG_COMPILER_APPICON_NAME = ""; ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOL_FRAMEWORKS = SwiftUI; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; diff --git a/README.md b/README.md index 422fab9..9a362a4 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ For detailed information about the background, design (screenshots), and feature This app is available on `macOS`, `iOS`, `iPadOS`, `watchOS` and `visionOS`, and includes widgets for all these platforms but visionOS. To build the project from the source, simply download or clone this repo, then build with Xcode. The app does not rely on any third-party dependencies. -Minimum OS requirements: `macOS 14.0`, `iOS/iPadOS 17.0`, `watchOS 10.0`, `visionOS 1.0`. You will need `Xcode 15.2` or later to build from the source. +Minimum OS requirements: `macOS 14.0`, `iOS/iPadOS 17.0`, `watchOS 10.0`, `visionOS 1.0`. You will need `Xcode 15.3` or later to build from the source. ## Contributing diff --git a/Shared/Localizable.xcstrings b/Shared/Localizable.xcstrings index 9143976..73924b7 100644 --- a/Shared/Localizable.xcstrings +++ b/Shared/Localizable.xcstrings @@ -656,6 +656,9 @@ } } } + }, + "你好" : { + }, "僅時" : { "localizations" : { @@ -7385,4 +7388,4 @@ } }, "version" : "1.0" -} \ No newline at end of file +} diff --git a/Shared/Setting/CalendarConfig.swift b/Shared/Setting/CalendarConfig.swift index a4a824e..f06c1fb 100644 --- a/Shared/Setting/CalendarConfig.swift +++ b/Shared/Setting/CalendarConfig.swift @@ -164,7 +164,7 @@ struct ConfigList: View { Label("更名", systemImage: "rectangle.and.pencil.and.ellipsis.rtl") } - Button { + HighlightButton { switchTo(config: config) } label: { HStack { @@ -173,11 +173,6 @@ struct ConfigList: View { dateLabel } } -#if os(macOS) - .buttonStyle(.accessoryBar) -#else - .buttonStyle(.borderless) -#endif .tint(.primary) .labelStyle(.titleAndIcon) .contextMenu { diff --git a/Shared/Setting/ThemesList.swift b/Shared/Setting/ThemesList.swift index c66f54e..e39f4b3 100644 --- a/Shared/Setting/ThemesList.swift +++ b/Shared/Setting/ThemesList.swift @@ -9,6 +9,52 @@ import SwiftUI import SwiftData import UniformTypeIdentifiers +#if os(macOS) +struct DynamicButtonStyle: ButtonStyle { + var prominent: Bool + @Environment(\.isEnabled) var isEnabled + @ScaledMetric(relativeTo: .body) var size: CGFloat = 4 + + func makeBody(configuration: Configuration) -> some View { + let color = isEnabled ? Color.primary : Color.secondary + configuration.label + .padding(size) + .overlay( + RoundedRectangle(cornerRadius: size * 1.5) + .stroke(color.opacity(prominent ? 1 : 0), lineWidth: 1) + .fill(color.opacity(prominent ? 0.1 : 0)) + ) + .scaleEffect(configuration.isPressed && isEnabled ? 0.99 : 1.0) + .animation(.easeInOut(duration: 0.2), value: prominent) + .animation(.easeInOut(duration: 0.1), value: configuration.isPressed) + } +} +#endif + +struct HighlightButton: View { + let action: () -> Void + @ViewBuilder let label: () -> Label + @State var hover = false + + var body: some View { + let button = Button { + action() + } label: { + label() + } + .onHover { over in + hover = over + } +#if os(macOS) + button + .buttonStyle(DynamicButtonStyle(prominent: hover)) +#else + button + .buttonStyle(.borderless) +#endif + } +} + struct TextDocument: FileDocument { init(configuration: ReadConfiguration) throws { if let data = configuration.file.regularFileContents { @@ -295,7 +341,7 @@ struct ThemesList: View { Text("常用") } - Button { + HighlightButton { if theme.name! != AppInfo.defaultName || theme.deviceName! != AppInfo.deviceName { target = theme switchAlert = true @@ -307,11 +353,6 @@ struct ThemesList: View { dateLabel } } -#if os(macOS) - .buttonStyle(.accessoryBar) -#else - .buttonStyle(.borderless) -#endif .tint(.primary) .labelStyle(.titleAndIcon) .contextMenu { @@ -498,12 +539,18 @@ struct ThemesList: View { #endif } -#Preview("Themes") { - let watchLayout = WatchLayout() - let watchSetting = WatchSetting() - watchLayout.loadStatic() - return ThemesList() - .modelContainer(DataSchema.container) - .environment(watchLayout) - .environment(watchSetting) +//#Preview("Themes") { +// let watchLayout = WatchLayout() +// let watchSetting = WatchSetting() +// watchLayout.loadStatic() +// return ThemesList() +// .modelContainer(DataSchema.container) +// .environment(watchLayout) +// .environment(watchSetting) +//} + +#Preview("Button") { + HighlightButton(action: {}) { + Text("你好") + } } diff --git a/Shared/Views/WatchFaceView.swift b/Shared/Views/WatchFaceView.swift index 832a972..4b32919 100644 --- a/Shared/Views/WatchFaceView.swift +++ b/Shared/Views/WatchFaceView.swift @@ -426,3 +426,13 @@ struct TimeWatch: View { } } } + + +#Preview("Watch") { + let chineseCalendar = ChineseCalendar() + let watchLayout = WatchLayout() + watchLayout.loadStatic() + + return Watch(displaySubquarter: true, displaySolarTerms: true, compact: false, watchLayout: watchLayout, markSize: 1.0, chineseCalendar: chineseCalendar, highlightType: .flicker) + .frame(width: watchLayout.watchSize.width, height: watchLayout.watchSize.height) +} diff --git a/Watch/Views/SwitchConfig.swift b/Watch/Views/SwitchConfig.swift index 4a29e20..2874058 100644 --- a/Watch/Views/SwitchConfig.swift +++ b/Watch/Views/SwitchConfig.swift @@ -71,6 +71,7 @@ struct SwitchConfig: View { .frame(maxWidth: .infinity, alignment: .trailing) } } + .deleteDisabled(config.name! == calendarConfigure.name) } } .onDelete { indexSet in