Update fantastical open cmds

This commit is contained in:
Hariharan Mudaliar 2026-04-06 11:29:23 +05:30
commit ab7d2619d7
No known key found for this signature in database
GPG key ID: 025583EB0BE5640E
4 changed files with 94 additions and 19 deletions

View file

@ -2042,7 +2042,6 @@
},
"±10 Seconds" : {
"comment" : "Display name for the \"±10 Seconds\" music skip behavior option.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -2665,7 +2664,6 @@
},
"Accent" : {
"comment" : "Display name for the caps lock indicator tint mode.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -3143,7 +3141,6 @@
},
"Adaptive gradient" : {
"comment" : "Display name for the timer icon color mode: adaptive gradient.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -5194,7 +5191,6 @@
},
"Apple Music" : {
"comment" : "Media controller type for Apple Music",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -5917,7 +5913,6 @@
},
"Bar" : {
"comment" : "Name of the timer progress style that shows a horizontal bar.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -11787,6 +11782,9 @@
}
}
}
},
"Default View" : {
},
"Default: dynamic.m4a" : {
"localizations" : {
@ -12212,7 +12210,6 @@
},
"Digital" : {
"comment" : "The display name for the \"Digital\" reminder presentation style.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -17300,7 +17297,6 @@
},
"Green" : {
"comment" : "Display name for the green caps lock indicator tint mode.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -25124,7 +25120,6 @@
},
"Now Playing" : {
"comment" : "Name of the media controller type for the \"Now Playing\" option.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -25809,7 +25804,6 @@
},
"Panel" : {
"comment" : "Display name for the clipboard display mode \"Panel\".",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -28661,7 +28655,6 @@
},
"Ring" : {
"comment" : "The name of the timer progress style that shows a ring shape.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -29919,7 +29912,6 @@
},
"Separate Tab" : {
"comment" : "Display name for the clipboard display mode option to open the clipboard in a separate tab.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -31687,7 +31679,6 @@
},
"Shows screen assistant as a dropdown attached to the AI button" : {
"comment" : "Description of the screen assistant display mode option that shows the screen assistant as a dropdown attached to the AI button.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -31700,7 +31691,6 @@
},
"Shows screen assistant in a floating panel near the notch" : {
"comment" : "Description of the screen assistant display mode option that shows the screen assistant in a floating panel near the notch.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -31854,7 +31844,6 @@
},
"Skip forward or backward by ten seconds" : {
"comment" : "Description of a music skip behavior option.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -32517,7 +32506,6 @@
},
"Spotify" : {
"comment" : "Spotify media controller type.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -32706,7 +32694,6 @@
},
"Standard previous/next track controls" : {
"comment" : "Description of the music skip behavior option to use standard previous/next track controls.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -34131,6 +34118,9 @@
}
}
}
},
"Third-party Calendar Integration" : {
},
"This duration powers the \"Custom\" option inside the timer popover for quick access." : {
"comment" : "A footer description for the custom timer settings, explaining their purpose.",
@ -34995,7 +34985,6 @@
},
"Track Skip" : {
"comment" : "Display name for the \"Track Skip\" music skip behavior.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {
@ -35992,6 +35981,9 @@
}
}
}
},
"Use Fantastical" : {
},
"Use MacBook icon when on battery" : {
"localizations" : {
@ -37194,6 +37186,9 @@
}
}
}
},
"When enabled, clicking on calendar events will open Fantastical instead of Apple Calendar. More integrations coming soon." : {
},
"When enabled, Focus appears briefly (on/off) and then collapses instead of staying visible." : {
"comment" : "A help text for the setting that allows the focus indicator to collapse instead of staying visible.",
@ -37763,7 +37758,6 @@
},
"Youtube Music" : {
"comment" : "Spotify music service.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"ru" : {

View file

@ -2752,6 +2752,8 @@ struct CalendarSettings: View {
@Default(.lockScreenCalendarSelectionMode) private var lockScreenCalendarSelectionMode
@Default(.lockScreenSelectedCalendarIDs) private var lockScreenSelectedCalendarIDs
@Default(.lockScreenShowCalendarEventAfterStartEnabled) private var lockScreenShowCalendarEventAfterStartEnabled
@Default(.useFantasticalCalendar) private var useFantasticalCalendar
@Default(.fantasticalDefaultView) private var fantasticalDefaultView
private func highlightID(_ title: String) -> String {
SettingsTab.calendar.highlightID(for: title)
@ -3045,6 +3047,32 @@ struct CalendarSettings: View {
.disabled(!lockScreenShowCalendarEvent)
.settingsHighlight(id: highlightID("Show start time after event begins"))
}
// MARK: - Third-party Calendar Integration
Section {
Defaults.Toggle(key: .useFantasticalCalendar) {
HStack {
Image(systemName: "calendar.badge.clock")
.foregroundColor(.red)
.frame(width: 20, height: 20)
Text("Use Fantastical")
}
}
.settingsHighlight(id: highlightID("Use Fantastical"))
if useFantasticalCalendar {
Picker("Default View", selection: $fantasticalDefaultView) {
ForEach(FantasticalViewStyle.allCases, id: \.self) { style in
Text(style.displayName).tag(style)
}
}
.settingsHighlight(id: highlightID("Fantastical Default View"))
}
} header: {
Text("Third-party Calendar Integration")
} footer: {
Text("When enabled, clicking on calendar events will open Fantastical instead of Apple Calendar. More integrations coming soon.")
}
Section(header: Text("Select Calendars")) {
let grouped = Dictionary(grouping: calendarManager.allCalendars, by: \.accountName)

View file

@ -256,6 +256,18 @@ enum CalendarSelectionState: Codable, Defaults.Serializable {
case selected(Set<String>)
}
enum FantasticalViewStyle: String, CaseIterable, Codable, Defaults.Serializable {
case mini = "mini"
case calendar = "calendar"
var displayName: String {
switch self {
case .mini: return "Mini View"
case .calendar: return "Full Calendar"
}
}
}
enum ClipboardDisplayMode: String, CaseIterable, Codable, Defaults.Serializable {
case popover = "popover" // Traditional popover attached to button
case panel = "panel" // Floating panel near notch
@ -854,6 +866,10 @@ extension Defaults.Keys {
static let lockScreenShowCalendarStartTimeAfterBegins = Key<Bool>("lockScreenShowCalendarStartTimeAfterBegins", default: true)
static let lockScreenWeatherWidgetRowOrder = Key<String>("lockScreenWeatherWidgetRowOrder", default: "weather_calendar_focus")
// MARK: Third-party Calendar Integration
static let useFantasticalCalendar = Key<Bool>("useFantasticalCalendar", default: false)
static let fantasticalDefaultView = Key<FantasticalViewStyle>("fantasticalDefaultView", default: .mini)
// MARK: Battery
static let showPowerStatusNotifications = Key<Bool>("showPowerStatusNotifications", default: true)
static let showBatteryIndicator = Key<Bool>("showBatteryIndicator", default: BatteryActivityManager.shared.hasBattery())

View file

@ -21,6 +21,7 @@
*/
import Foundation
import Defaults
struct EventModel: Equatable, Identifiable {
let id: String
@ -97,7 +98,15 @@ extension EventModel {
var isMeeting: Bool { !participants.isEmpty }
func calendarAppURL() -> URL? {
// Check if Fantastical is enabled
if Defaults[.useFantasticalCalendar] {
return fantasticalURL()
}
return appleCalendarURL()
}
/// Returns URL to open event in Apple Calendar
private func appleCalendarURL() -> URL? {
guard let id = id.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else {
return nil
}
@ -123,6 +132,34 @@ extension EventModel {
}
return URL(string: "ical://ekevent\(date)/\(id)?method=show&options=more")
}
/// Returns URL to open date in Fantastical
private func fantasticalURL() -> URL? {
// Reminders still use Apple's Reminders app
guard !type.isReminder else {
return URL(string: "x-apple-reminderkit://remcdreminder/\(id)")
}
let viewStyle = Defaults[.fantasticalDefaultView]
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateString = dateFormatter.string(from: start)
// x-fantastical3://show/mini/yyyy-MM-dd or x-fantastical3://show/calendar/yyyy-MM-dd
return URL(string: "x-fantastical3://show/\(viewStyle.rawValue)/\(dateString)")
}
/// Returns URL to open Fantastical at current date (for general calendar access)
static func fantasticalShowURL(for date: Date? = nil) -> URL? {
let viewStyle = Defaults[.fantasticalDefaultView]
if let date = date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateString = dateFormatter.string(from: date)
return URL(string: "x-fantastical3://show/\(viewStyle.rawValue)/\(dateString)")
}
return URL(string: "x-fantastical3://show/\(viewStyle.rawValue)")
}
}
struct Participant: Hashable {