From 7b98be1d8d7644a8199f3bbbba1406b72d54470e Mon Sep 17 00:00:00 2001 From: kutesir Date: Sun, 7 Jun 2026 12:43:02 +0300 Subject: [PATCH] Event widget: upcoming-queue auto-select + cleaner config & preview MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add "Upcoming queue" toggle to the Event Countdown widget. When on, it auto-tracks the Nth nearest upcoming event (Nearest / 2nd … 5th, new AutoSelectRank enum). When off, track a picked or fully custom event. - parameterSummary now shows only the relevant fields per mode (toggle + auto-select, or event/name/date), so the date input only appears for custom events. - Replace the dense 380-day placeholder with a ~90-day window so the gallery preview shows a legible dot grid. (The interactive task-checkbox widget already exists as "My Tasks".) Co-Authored-By: Claude Opus 4.8 --- KisaniCal.xcodeproj/project.pbxproj | 38 ++++++-- .../UserInterfaceState.xcuserstate | Bin 49106 -> 49686 bytes .../xcshareddata/xcschemes/KisaniCal.xcscheme | 16 +--- KisaniCalWidgets/EventCountdownWidget.swift | 88 +++++++++++++++--- 4 files changed, 109 insertions(+), 33 deletions(-) diff --git a/KisaniCal.xcodeproj/project.pbxproj b/KisaniCal.xcodeproj/project.pbxproj index ca712ce..7be4def 100644 --- a/KisaniCal.xcodeproj/project.pbxproj +++ b/KisaniCal.xcodeproj/project.pbxproj @@ -80,7 +80,7 @@ 0506183945D16EC443A69651 /* LiveActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveActivityManager.swift; sourceTree = ""; }; 0513EB8C7F6B6853B9E93E09 /* TaskLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskLiveActivity.swift; sourceTree = ""; }; 0C96EC00F6B021DBA3CC1A79 /* ProfileSetupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileSetupView.swift; sourceTree = ""; }; - 0D6D6740721F01A74E404EB9 /* KisaniCalWidgets.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = KisaniCalWidgets.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 0D6D6740721F01A74E404EB9 /* KisaniCalWidgets.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = KisaniCalWidgets.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 106EEF572C6F8990408329F0 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = ""; }; 1AA7498EFED7692022F3E7E1 /* KisaniCal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = KisaniCal.entitlements; sourceTree = ""; }; 208F82348DEBD9FF7B0DCF17 /* MyTasksWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyTasksWidget.swift; sourceTree = ""; }; @@ -104,7 +104,7 @@ 9100804DB1E61EA882CC54DA /* FloatingTabState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingTabState.swift; sourceTree = ""; }; 92824ED40ECD41EFD4F78BEC /* ISSUES.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = ISSUES.md; sourceTree = ""; }; 93D045FE3DEB1D22D908A29F /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; - 9BD1F84B4F45B12CB9B9F1B2 /* KisaniCal.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = KisaniCal.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 9BD1F84B4F45B12CB9B9F1B2 /* KisaniCal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KisaniCal.app; sourceTree = BUILT_PRODUCTS_DIR; }; ADF6CCD95A587E26E30F5712 /* CalendarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarView.swift; sourceTree = ""; }; AF905C574F34B4EE51A8D21E /* AppGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppGroup.swift; sourceTree = ""; }; BC5E179A9189B0A8C3F856F6 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -289,7 +289,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1500; + LastUpgradeCheck = 2620; TargetAttributes = { 28B43516AD88946E21D9BFE0 = { DevelopmentTeam = K8BLMMR883; @@ -405,6 +405,7 @@ CODE_SIGN_ENTITLEMENTS = KisaniCal/KisaniCal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 2; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_CFBundleDisplayName = "Kisani Cal"; @@ -416,13 +417,14 @@ INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleDefault; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); + MARKETING_VERSION = 2; PRODUCT_BUNDLE_IDENTIFIER = com.kutesir.KisaniCal; SDKROOT = iphoneos; SWIFT_VERSION = 5.9; @@ -469,6 +471,7 @@ DEVELOPMENT_TEAM = K8BLMMR883; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -483,6 +486,7 @@ MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; @@ -495,10 +499,16 @@ APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_ENTITLEMENTS = KisaniCalWidgets/KisaniCalWidgets.entitlements; CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 2; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = KisaniCalWidgets/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 18.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 2; PRODUCT_BUNDLE_IDENTIFIER = com.kutesir.KisaniCal.KisaniCalWidgets; SDKROOT = iphoneos; SWIFT_VERSION = 5.9; @@ -545,6 +555,7 @@ DEVELOPMENT_TEAM = K8BLMMR883; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -566,6 +577,7 @@ ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -578,10 +590,16 @@ APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_ENTITLEMENTS = KisaniCalWidgets/KisaniCalWidgets.entitlements; CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 2; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = KisaniCalWidgets/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 18.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 2; PRODUCT_BUNDLE_IDENTIFIER = com.kutesir.KisaniCal.KisaniCalWidgets; SDKROOT = iphoneos; SWIFT_VERSION = 5.9; @@ -597,6 +615,7 @@ CODE_SIGN_ENTITLEMENTS = KisaniCal/KisaniCal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 2; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_CFBundleDisplayName = "Kisani Cal"; @@ -608,13 +627,14 @@ INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIStatusBarStyle = UIStatusBarStyleDefault; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); + MARKETING_VERSION = 2; PRODUCT_BUNDLE_IDENTIFIER = com.kutesir.KisaniCal; SDKROOT = iphoneos; SWIFT_VERSION = 5.9; diff --git a/KisaniCal.xcodeproj/project.xcworkspace/xcuserdata/kutesir.xcuserdatad/UserInterfaceState.xcuserstate b/KisaniCal.xcodeproj/project.xcworkspace/xcuserdata/kutesir.xcuserdatad/UserInterfaceState.xcuserstate index 14b2b42cada50b6a5045d230baa260154783087b..beae5f62b92616b4ab67e0d84fdd2982d7309ca9 100644 GIT binary patch delta 24306 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 delta 23800 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 Z<+i$y+{Y6sKOkVjGYcmCpYEh5e*t?qg + LastUpgradeVersion = "2620" + version = "1.3"> + buildImplicitDependencies = "YES"> + shouldUseLaunchSchemeArgsEnv = "YES"> - - - - - - diff --git a/KisaniCalWidgets/EventCountdownWidget.swift b/KisaniCalWidgets/EventCountdownWidget.swift index 45c4fab..71ae09e 100644 --- a/KisaniCalWidgets/EventCountdownWidget.swift +++ b/KisaniCalWidgets/EventCountdownWidget.swift @@ -10,12 +10,32 @@ import AppIntents // persisted per-instance by WidgetKit, the widget is fully self-contained and does // not depend on App Group data sharing. +// Which upcoming event to auto-track when the queue is on. +enum AutoSelectRank: Int, AppEnum { + case first = 1, second, third, fourth, fifth + + static var typeDisplayRepresentation: TypeDisplayRepresentation = "Auto Select" + static var caseDisplayRepresentations: [AutoSelectRank: DisplayRepresentation] = [ + .first: "Nearest to finish", + .second: "2nd nearest to finish", + .third: "3rd nearest to finish", + .fourth: "4th nearest to finish", + .fifth: "5th nearest to finish", + ] +} + struct EventConfigIntent: WidgetConfigurationIntent { static var title: LocalizedStringResource = "Event Countdown" - static var description = IntentDescription("Count down to any upcoming event with a dot grid.") + static var description = IntentDescription("Count down to an event with a dot grid.") + + // When on, the widget auto-tracks one of your upcoming events. When off, you + // track a specific event you pick, or a fully custom name + date. + @Parameter(title: "Upcoming queue", default: true) + var upcomingQueue: Bool + + @Parameter(title: "Auto select", default: .first) + var autoSelect: AutoSelectRank - // Pick one of your existing events (tasks with a due date). When set, it - // overrides the manual name/date fields below. @Parameter(title: "Track event") var event: EventEntity? @@ -27,6 +47,25 @@ struct EventConfigIntent: WidgetConfigurationIntent { @Parameter(title: "Counting from", default: Date.now) var startDate: Date + + // Show only the relevant fields depending on the toggle — like a clean, + // single-purpose config screen instead of every field at once. + static var parameterSummary: some ParameterSummary { + When(\.$upcomingQueue, .equalTo, true) { + Summary("Track upcoming event") { + \.$upcomingQueue + \.$autoSelect + } + } otherwise: { + Summary("Track a custom event") { + \.$upcomingQueue + \.$event + \.$eventName + \.$targetDate + \.$startDate + } + } + } } // MARK: - Event picker (reads your tasks from the App Group) @@ -141,10 +180,11 @@ struct EventEntry: TimelineEntry { struct EventProvider: AppIntentTimelineProvider { func placeholder(in context: Context) -> EventEntry { + // ~90-day window, ~60% elapsed → a clear, legible dot grid in the gallery. EventEntry(date: .now, - eventName: "Mum's Birthday", - start: Date().addingTimeInterval(-86400 * 320), - target: Date().addingTimeInterval(86400 * 60)) + eventName: "IELTS", + start: Date().addingTimeInterval(-86400 * 54), + target: Date().addingTimeInterval(86400 * 36)) } func snapshot(for configuration: EventConfigIntent, in context: Context) async -> EventEntry { @@ -158,19 +198,43 @@ struct EventProvider: AppIntentTimelineProvider { return Timeline(entries: [entry], policy: .after(nextMidnight)) } + /// Upcoming events (incomplete tasks with a future due date), nearest first. + private func upcomingEvents() -> [EventEntity] { + loadWidgetTasks() + .filter { !$0.isComplete && ($0.dueDate ?? .distantPast) > Date() } + .sorted { ($0.dueDate ?? .distantFuture) < ($1.dueDate ?? .distantFuture) } + .map { EventEntity(id: $0.id.uuidString, title: $0.title, dueDate: $0.dueDate) } + } + private func entry(for config: EventConfigIntent) -> EventEntry { - let name: String - let target: Date - if let ev = config.event, let due = ev.dueDate { - // A picked event supplies its own name + date. + var name: String + var target: Date + + if config.upcomingQueue { + // Auto-track the Nth nearest upcoming event. + let upcoming = upcomingEvents() + let idx = max(0, config.autoSelect.rawValue - 1) + if idx < upcoming.count, let due = upcoming[idx].dueDate { + name = upcoming[idx].title + target = due + } else { + name = "No upcoming event" + target = Date().addingTimeInterval(86400) + } + } else if let ev = config.event, let due = ev.dueDate { + // A specifically picked event supplies its own name + date. name = ev.title target = due } else { + // Fully custom event. name = config.eventName.isEmpty ? "My Event" : config.eventName target = config.targetDate } - // Never let the start sit after the target. - let start = min(config.startDate, target) + + // Counting anchor: custom mode honors the picker; auto mode counts from + // "now" so the grid fills toward the event. Never start after the target. + let anchor = config.upcomingQueue ? Date() : config.startDate + let start = min(anchor, target) let mode = UserDefaults.kisani.integer(forKey: countdownUnitKey) return EventEntry(date: .now, eventName: name, start: start, target: target, unitMode: mode) }