feat(meetingbar): Prioritize accepted events over tentative/pending
Assisted-by: Claude Opus 4.5 via Claude Code
change uuosomopntszqrtzxzlumllruktslyxk
commit c67213889fd714a328ebb5ac5943a036b70de4e0
author Alpha Chen <alpha@kejadlen.dev>
date
parent zwxnmlkn
diff --git a/.config/sketchybar/meetingbar.swift b/.config/sketchybar/meetingbar.swift
index 2eabf6a6..226f100b 100755
--- a/.config/sketchybar/meetingbar.swift
+++ b/.config/sketchybar/meetingbar.swift
@@ -27,6 +27,20 @@ struct MeetingBarError: Error {
     let message: String
 }
 
+// Returns priority for participation status (lower = higher priority)
+func participationPriority(for event: EKEvent) -> Int {
+    guard let attendees = event.attendees else { return 100 }
+    guard let me = attendees.first(where: { $0.isCurrentUser }) else { return 100 }
+
+    switch me.participantStatus {
+    case .accepted: return 0
+    case .tentative: return 1
+    case .pending: return 2
+    case .unknown: return 3
+    default: return 100
+    }
+}
+
 class MeetingBar {
     let calendarTitle: String
     let eventStore: EKEventStore
@@ -95,20 +109,37 @@ class MeetingBar {
         let predicate = eventStore.predicateForEvents(withStart: startDate, end: endDate, calendars: calendars)
         let events = eventStore.events(matching: predicate).filter { !$0.isAllDay }
 
-        let currentMeeting = events.first(where: { currentDate >= $0.startDate && currentDate <= $0.endDate })
+        // Find current meetings, preferring accepted ones
+        let currentMeetings = events.filter { currentDate >= $0.startDate && currentDate <= $0.endDate }
+        let currentMeeting = currentMeetings.min { first, second in
+            let firstPriority = participationPriority(for: first)
+            let secondPriority = participationPriority(for: second)
+            if firstPriority != secondPriority {
+                return firstPriority < secondPriority
+            }
+            // Same status, prefer shorter meeting
+            let firstDuration = first.endDate.timeIntervalSince(first.startDate)
+            let secondDuration = second.endDate.timeIntervalSince(second.startDate)
+            return firstDuration < secondDuration
+        }
 
         // Find all events starting after current time
         let upcomingEvents = events.filter { $0.startDate > currentDate }
-        // If multiple events start at the same time, pick the shortest one
+        // Priority: earliest start > accepted status > shortest duration
         let nextMeeting = upcomingEvents.min { first, second in
-            if first.startDate == second.startDate {
-                // Same start time, compare durations
-                let firstDuration = first.endDate.timeIntervalSince(first.startDate)
-                let secondDuration = second.endDate.timeIntervalSince(second.startDate)
-                return firstDuration < secondDuration
+            if first.startDate != second.startDate {
+                return first.startDate < second.startDate
+            }
+            // Same start time, prefer accepted events
+            let firstPriority = participationPriority(for: first)
+            let secondPriority = participationPriority(for: second)
+            if firstPriority != secondPriority {
+                return firstPriority < secondPriority
             }
-            // Different start times, pick the earlier one
-            return first.startDate < second.startDate
+            // Same status, pick the shortest one
+            let firstDuration = first.endDate.timeIntervalSince(first.startDate)
+            let secondDuration = second.endDate.timeIntervalSince(second.startDate)
+            return firstDuration < secondDuration
         }
 
         // No current meeting, show next meeting if available