Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,21 @@ public enum CommandPaletteCatalog {
isSignedIn: Bool,
isTrialing: Bool,
eventHits: [CommandPaletteEventHit],
recentIds: [String]
recentIds: [String],
tipsMuted: Bool,
levelHidden: Bool,
theme: CompassThemeName
) -> [CommandPaletteSection] {
var built: [CommandPaletteSection] = []

if let goToDate = goToDateItem(query: query, now: now) {
built.append(CommandPaletteSection(id: "go-to-date", heading: "", items: [goToDate]))
}

let navigation = navigationItems(view: view)
let navigation = navigationItems(
view: view,
tipsMuted: tipsMuted,
levelHidden: levelHidden)
if !navigation.isEmpty {
built.append(CommandPaletteSection(id: "navigation", heading: "Navigation", items: navigation))
}
Expand All @@ -43,7 +49,7 @@ public enum CommandPaletteCatalog {
}

built.append(contentsOf: eventActionSections())
built.append(contentsOf: moreSections(isTrialing: isTrialing))
built.append(contentsOf: moreSections(isTrialing: isTrialing, theme: theme))

var accountItems = [CommandPaletteItem(
id: "export-data",
Expand Down Expand Up @@ -89,45 +95,86 @@ public enum CommandPaletteCatalog {
}

private static func navigationItems(
view: CalendarGridView
view: CalendarGridView,
tipsMuted: Bool,
levelHidden: Bool
) -> [CommandPaletteItem] {
var items: [CommandPaletteItem] = [
CommandPaletteItem(
id: "today",
label: "Go to Today",
shortcut: "t",
keywords: ["now", "current", "jump"]),
keywords: ["now", "current", "jump"],
systemImage: "arrow.uturn.backward"),
]
if view != .day {
items.append(
CommandPaletteItem(
id: "go-to-day",
label: "Go to Day view",
shortcut: "d",
keywords: ["day view", "daily"]))
keywords: ["day view", "daily"],
systemImage: "calendar"))
}
if view != .week {
items.append(
CommandPaletteItem(
id: "go-to-week",
label: "Go to Week view",
shortcut: "w",
keywords: ["week view", "weekly"]))
keywords: ["week view", "weekly"],
systemImage: "calendar.day.timeline.left"))
}
if view != .life {
items.append(
CommandPaletteItem(
id: "go-to-life",
label: "Go to Life view",
shortcut: "l",
keywords: ["life view", "years"]))
keywords: ["life view", "years"],
systemImage: "hourglass"))
}
items.append(
CommandPaletteItem(
id: "show-shortcuts",
label: "Show shortcuts",
shortcut: "?",
keywords: ["keyboard", "legend", "help"]))
keywords: ["keyboard", "legend", "help"],
systemImage: "keyboard"))
items.append(
CommandPaletteItem(
id: "practice-shortcuts",
label: "Play Block Party (practice shortcuts)",
keywords: [
"onboarding", "tour", "intro", "help", "tutorial", "coach", "sandbox",
"practice", "shortcuts", "game", "play", "block party",
],
systemImage: "safari"))
items.append(
CommandPaletteItem(
id: "show-welcome-guide",
label: "Show welcome guide",
keywords: ["onboarding", "tour", "intro", "help", "faq"],
systemImage: "safari"))
items.append(
CommandPaletteItem(
id: "toggle-shortcut-tips",
label: tipsMuted ? "Show shortcut tips" : "Hide shortcut tips",
keywords: ["sidebar", "hint", "tips", "teaching", "shortcuts", "keyboard"],
systemImage: tipsMuted ? "eye" : "eye.slash"))
items.append(
CommandPaletteItem(
id: "toggle-shortcut-level",
label: levelHidden ? "Show shortcut level" : "Hide shortcut level",
keywords: ["level", "progress", "badge", "shortcuts", "keyboard"],
systemImage: levelHidden ? "eye" : "eye.slash"))
items.append(
CommandPaletteItem(
id: "toggle-sidebar",
label: "Toggle sidebar",
shortcut: "]",
keywords: ["panel", "hide sidebar", "show sidebar"],
systemImage: "sidebar.left"))
return items
}

Expand All @@ -142,7 +189,8 @@ public enum CommandPaletteCatalog {
id: "recent-" + id,
label: item.label,
shortcut: item.shortcut,
keywords: item.keywords)
keywords: item.keywords,
systemImage: item.systemImage)
}
}

Expand All @@ -167,8 +215,10 @@ public enum CommandPaletteCatalog {
}

private static func moreSections(
isTrialing: Bool
isTrialing: Bool,
theme: CompassThemeName
) -> [CommandPaletteSection] {
let isDark = theme == .darkAbyss
var items: [CommandPaletteItem] = [
CommandPaletteItem(
id: "undo",
Expand All @@ -181,25 +231,21 @@ public enum CommandPaletteCatalog {
shortcut: "mod+shift+z",
keywords: ["repeat", "forward"]),
CommandPaletteItem(
id: "show-welcome-guide",
label: "Show welcome guide",
keywords: ["onboarding", "tour", "intro", "help", "faq"]),
CommandPaletteItem(
id: "practice-shortcuts",
label: "Play Block Party (practice shortcuts)",
keywords: [
"onboarding", "tour", "intro", "help", "tutorial", "coach", "sandbox",
"practice", "shortcuts", "game", "play", "block party",
]),
id: "toggle-theme",
label: isDark ? "Switch to light theme" : "Switch to dark theme",
keywords: ["theme", "dark mode", "light mode", "appearance"],
systemImage: isDark ? "sun.max" : "moon.stars"),
CommandPaletteItem(
id: "open-settings",
label: "Settings",
shortcut: ",",
keywords: ["preferences", "account"]),
keywords: ["preferences", "account"],
systemImage: "gearshape"),
CommandPaletteItem(
id: "about",
label: "About Compass",
keywords: ["version", "info"]),
keywords: ["version", "info"],
systemImage: "info.circle"),
]
if isTrialing {
items.insert(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ public struct CommandPaletteItem: Identifiable, Hashable, Sendable {
public let shortcut: String?
public let keywords: [String]
public let subtitle: String?
public let systemImage: String?

public init(
id: String,
label: String,
shortcut: String? = nil,
keywords: [String] = [],
subtitle: String? = nil
subtitle: String? = nil,
systemImage: String? = nil
) {
self.id = id
self.label = label
self.shortcut = shortcut
self.keywords = keywords
self.subtitle = subtitle
self.systemImage = systemImage
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ extension NativeCalendarRootModel {
isSignedIn: isSignedIn,
isTrialing: billingStore.status?.subscriptionStatus == .trialing,
eventHits: mergedHits,
recentIds: commandPaletteStore.recentCommandIds)
recentIds: commandPaletteStore.recentCommandIds,
tipsMuted: levelsStore.tipsMuted,
levelHidden: levelsStore.badgeHidden,
theme: settingsStore.theme)
}

public func filteredPaletteSections() -> [CommandPaletteSection] {
Expand Down Expand Up @@ -114,12 +117,22 @@ extension NativeCalendarRootModel {
handleShortcut(.navLifeView)
case "show-shortcuts":
shortcutsLegendStore.open()
case "toggle-theme":
let next: CompassThemeName =
settingsStore.theme == .darkAbyss ? .lightBeach : .darkAbyss
settingsStore.setTheme(next)
case "open-settings":
handleShortcut(.otherSettings)
case "practice-shortcuts":
blockPartyStore.replayFromPalette()
case "show-welcome-guide":
onboardingStore.openWelcomeGuide()
case "toggle-shortcut-tips":
levelsStore.setTipsMuted(!levelsStore.tipsMuted)
case "toggle-shortcut-level":
levelsStore.setBadgeHidden(!levelsStore.badgeHidden)
case "toggle-sidebar":
handleShortcut(.otherSidebar)
case "sign-up":
authStore.openModal(.signUp)
case "log-in":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public final class NativeCalendarRootModel {

let anchor: Date = {
let today = demoPresentation?.referenceNow ?? now()
return EffectiveTimeZone.calendar.dateInterval(of: .weekOfYear, for: today)?.start ?? today
return CalendarWindowMath.sundayWeekViewStart(containing: today)
}()
viewStore = ViewStore(
view: .week,
Expand Down Expand Up @@ -372,9 +372,7 @@ public final class NativeCalendarRootModel {
contentTrackWidth = CGFloat(ParityCaptureGeometry.contentTrackWidth)
viewStore.setVisibleDayCount(ParityCaptureGeometry.visibleDayCount)
let today = referenceNow
let calendar = EffectiveTimeZone.calendar
let weekStart = calendar.dateInterval(of: .weekOfYear, for: today)?.start ?? today
viewStore.setAnchorDate(weekStart)
viewStore.setAnchorDate(CalendarWindowMath.sundayWeekViewStart(containing: today))
monthPickerMonth = today
pendingScroll = .scrollToNowOrPulse
rebuildPresentation()
Expand Down Expand Up @@ -922,8 +920,7 @@ public final class NativeCalendarRootModel {
if viewStore.visibleDayCount == 1 {
viewStore.setAnchorDate(today)
} else {
let weekStart = calendar.dateInterval(of: .weekOfYear, for: today)?.start ?? today
viewStore.setAnchorDate(weekStart)
viewStore.setAnchorDate(CalendarWindowMath.sundayWeekViewStart(containing: today))
}
monthPickerMonth = today
rebuildPresentation()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public struct LevelUpToastSnapshot: Hashable, Sendable, Identifiable {
public final class LevelsStore {
public private(set) var levelSnapshot: ShortcutLevelSnapshot
public private(set) var badgeHidden: Bool
public private(set) var tipsMuted: Bool
public private(set) var badgePulsing = false
public private(set) var currentTip: ShortcutTipSnapshot?
public private(set) var pendingLevelUpToast: LevelUpToastSnapshot?
Expand All @@ -63,6 +64,7 @@ public final class LevelsStore {
let initialUsedIds = ShortcutUsagePersistence.usedShortcutIds(from: profile)
usedIds = initialUsedIds
badgeHidden = defaults.bool(forKey: ShortcutUsageStorageKeys.levelHidden)
tipsMuted = defaults.bool(forKey: ShortcutUsageStorageKeys.tipsMuted)
tipRotationIndex = defaults.integer(forKey: ShortcutUsageStorageKeys.tipRotationIndex)
levelSnapshot = ShortcutLevelMath.compute(
usedIds: initialUsedIds,
Expand Down Expand Up @@ -104,6 +106,17 @@ public final class LevelsStore {
advanceTipRotation()
}

public func setTipsMuted(_ muted: Bool) {
guard muted != tipsMuted else { return }
tipsMuted = muted
defaults.set(muted, forKey: ShortcutUsageStorageKeys.tipsMuted)
if muted {
currentTip = nil
} else {
refreshTip()
}
}

public func setBadgeHidden(_ hidden: Bool) {
guard hidden != badgeHidden else { return }
badgeHidden = hidden
Expand Down Expand Up @@ -176,7 +189,7 @@ public final class LevelsStore {
}

private func refreshTip() {
guard !badgeHidden else {
guard !tipsMuted, !badgeHidden else {
currentTip = nil
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Foundation
enum ShortcutUsageStorageKeys {
static let personalization = "compass.shortcuts.personalization"
static let levelHidden = "compass.shortcuts.level-hidden"
static let tipsMuted = "compass.shortcuts.tips-muted"
static let levelCelebrated = "compass.shortcuts.level-celebrated"
static let tipRotationIndex = "compass.shortcuts.tip-rotation-index"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ final class CommandPaletteActionsTests: XCTestCase {
let ids = Set(model.filteredPaletteSections().flatMap(\.items).map(\.id))
XCTAssertTrue(ids.contains("undo"))
XCTAssertTrue(ids.contains("redo"))
XCTAssertTrue(ids.contains("toggle-theme"))
}

func testToggleThemeFlipsStoredTheme() async throws {
let model = try await makeModel()
let initial = model.settingsStore.theme
model.runPaletteCommand(id: "toggle-theme")
XCTAssertNotEqual(model.settingsStore.theme, initial)
model.runPaletteCommand(id: "toggle-theme")
XCTAssertEqual(model.settingsStore.theme, initial)
}

func testAboutInvokesNativePresentation() async throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ import Foundation
public enum CalendarWindowMath {
public static let weekDayCount = 7

/// Web Day.js `startOf("week")`: Sunday 00:00 in the effective timezone.
public static func sundayWeekViewStart(containing date: Date) -> Date {
var calendar = EffectiveTimeZone.calendar
calendar.firstWeekday = 1
calendar.minimumDaysInFirstWeek = 1
let startOfDay = calendar.startOfDay(for: date)
let weekday = calendar.component(.weekday, from: startOfDay)
let daysFromSunday = (weekday - calendar.firstWeekday + 7) % 7
return calendar.date(byAdding: .day, value: -daysFromSunday, to: startOfDay) ?? startOfDay
}

/// Seven local days from the anchor's start of day; `end` is exclusive next midnight.
public static func weekEventsQueryWindow(anchor: Date) -> DateRange {
let calendar = EffectiveTimeZone.calendar
Expand Down
Loading
Loading