|
|
@@ -530,6 +530,9 @@ class ViewController: NSViewController {
|
|
|
private var globalSearchResults: [ScheduledMeeting] = []
|
|
|
private var topBarProfileInitial = "H"
|
|
|
private var clockTimer: Timer?
|
|
|
+ private var lastObservedCalendarDayStart: Date = Calendar.current.startOfDay(for: Date())
|
|
|
+ private var calendarDayChangeObservers: [NSObjectProtocol] = []
|
|
|
+ private var workspaceWakeObserver: NSObjectProtocol?
|
|
|
private var meetingsRefreshTimer: Timer?
|
|
|
private var brandLeadingConstraint: NSLayoutConstraint?
|
|
|
private var windowFullScreenObservers: [NSObjectProtocol] = []
|
|
|
@@ -807,6 +810,7 @@ class ViewController: NSViewController {
|
|
|
}
|
|
|
setupUI()
|
|
|
setupWidgetBridge()
|
|
|
+ installCalendarDayChangeObservers()
|
|
|
if let tzId = UserDefaults.standard.string(forKey: Self.zoomAccountTimeZoneDefaultsKey),
|
|
|
let tz = TimeZone(identifier: tzId) {
|
|
|
zoomAccountTimeZone = tz
|
|
|
@@ -840,6 +844,7 @@ class ViewController: NSViewController {
|
|
|
if storeKitCoordinator.hasPremiumAccess {
|
|
|
DesktopWidgetWindowManager.shared.restore()
|
|
|
}
|
|
|
+ refreshHomeForCurrentDayIfNeeded()
|
|
|
}
|
|
|
|
|
|
override func viewDidLayout() {
|
|
|
@@ -9462,6 +9467,15 @@ class ViewController: NSViewController {
|
|
|
NotificationCenter.default.removeObserver(observer)
|
|
|
}
|
|
|
windowFullScreenObservers.removeAll()
|
|
|
+ for observer in calendarDayChangeObservers {
|
|
|
+ NotificationCenter.default.removeObserver(observer)
|
|
|
+ }
|
|
|
+ calendarDayChangeObservers.removeAll()
|
|
|
+ if let workspaceWakeObserver {
|
|
|
+ NSWorkspace.shared.notificationCenter.removeObserver(workspaceWakeObserver)
|
|
|
+ self.workspaceWakeObserver = nil
|
|
|
+ }
|
|
|
+ clockTimer?.invalidate()
|
|
|
}
|
|
|
|
|
|
private func ensureUsageSessionStartDate() {
|
|
|
@@ -9534,15 +9548,86 @@ class ViewController: NSViewController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private func installCalendarDayChangeObservers() {
|
|
|
+ guard calendarDayChangeObservers.isEmpty else { return }
|
|
|
+
|
|
|
+ let center = NotificationCenter.default
|
|
|
+ let dayChangeNames: [Notification.Name] = [.NSCalendarDayChanged, .NSSystemClockDidChange]
|
|
|
+ for name in dayChangeNames {
|
|
|
+ let observer = center.addObserver(forName: name, object: nil, queue: .main) { [weak self] _ in
|
|
|
+ Task { @MainActor [weak self] in
|
|
|
+ self?.refreshHomeForCurrentDayIfNeeded(force: true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ calendarDayChangeObservers.append(observer)
|
|
|
+ }
|
|
|
+
|
|
|
+ workspaceWakeObserver = NSWorkspace.shared.notificationCenter.addObserver(
|
|
|
+ forName: NSWorkspace.didWakeNotification,
|
|
|
+ object: nil,
|
|
|
+ queue: .main
|
|
|
+ ) { [weak self] _ in
|
|
|
+ Task { @MainActor [weak self] in
|
|
|
+ self?.refreshHomeForCurrentDayIfNeeded(force: true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// When the calendar day changes (midnight, wake from sleep, or return to the app), reset the home UI to today and reload meetings.
|
|
|
+ @MainActor
|
|
|
+ private func refreshHomeForCurrentDayIfNeeded(force: Bool = false) {
|
|
|
+ let calendar = Calendar.current
|
|
|
+ let todayStart = calendar.startOfDay(for: Date())
|
|
|
+ let dayChanged = calendar.isDate(todayStart, inSameDayAs: lastObservedCalendarDayStart) == false
|
|
|
+
|
|
|
+ guard dayChanged || force else { return }
|
|
|
+
|
|
|
+ if dayChanged {
|
|
|
+ lastObservedCalendarDayStart = todayStart
|
|
|
+ applyCalendarDayRolloverRefresh()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ updateClock()
|
|
|
+ guard hasBuiltInitialHomeView else { return }
|
|
|
+ updateMeetingsDayUI()
|
|
|
+ applyFilteredMeetings()
|
|
|
+ applyMeetingsPageFilters(resetVisible: false)
|
|
|
+ renderSchedulerCalendarGrid()
|
|
|
+ if isUserLoggedIn(), storeKitCoordinator.hasPremiumAccess {
|
|
|
+ triggerMeetingsRefresh(force: false)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @MainActor
|
|
|
+ private func applyCalendarDayRolloverRefresh() {
|
|
|
+ updateClock()
|
|
|
+ guard hasBuiltInitialHomeView else { return }
|
|
|
+
|
|
|
+ setSelectedMeetingsDayStart(Date())
|
|
|
+ applyMeetingsPageFilters(resetVisible: true)
|
|
|
+ renderAiCompanionList()
|
|
|
+
|
|
|
+ if isUserLoggedIn(), storeKitCoordinator.hasPremiumAccess {
|
|
|
+ triggerMeetingsRefresh(force: true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private func startClock() {
|
|
|
clockTimer?.invalidate()
|
|
|
clockTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
|
|
|
- self?.updateClock()
|
|
|
+ Task { @MainActor [weak self] in
|
|
|
+ self?.updateClock()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Task { @MainActor in
|
|
|
+ updateClock()
|
|
|
}
|
|
|
- updateClock()
|
|
|
}
|
|
|
|
|
|
+ @MainActor
|
|
|
private func updateClock() {
|
|
|
+ refreshHomeForCurrentDayIfNeeded()
|
|
|
let now = Date()
|
|
|
let timeFormatter = DateFormatter()
|
|
|
timeFormatter.dateFormat = "h:mm a"
|