You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
3.5 KiB
104 lines
3.5 KiB
// Copyright © 2015 Abhishek Banthia |
|
|
|
import Cocoa |
|
import CoreLoggerKit |
|
import CoreModelKit |
|
import EventKit |
|
|
|
class MenubarTitleProvider: NSObject { |
|
private let store: DataStore |
|
private let eventCenter: EventCenter |
|
|
|
init(with dataStore: DataStore, eventStore: EventCenter) { |
|
store = dataStore |
|
eventCenter = eventStore |
|
super.init() |
|
} |
|
|
|
func titleForMenubar() -> String? { |
|
let filteredEvents = eventCenter.eventsForDate |
|
let autoupdatingCalendar = eventCenter.autoupdatingCalendar |
|
if let nextEvent = checkForUpcomingEvents(filteredEvents, calendar: autoupdatingCalendar) { |
|
return nextEvent |
|
} |
|
|
|
guard let menubarTitles = store.menubarTimezones() else { |
|
return nil |
|
} |
|
|
|
// If the menubar is in compact mode, we don't need any of the below calculations; exit early |
|
if store.shouldDisplay(.menubarCompactMode) { |
|
return nil |
|
} |
|
|
|
if menubarTitles.isEmpty == false { |
|
let titles = menubarTitles.map { data -> String? in |
|
let timezone = TimezoneData.customObject(from: data) |
|
let operationsObject = TimezoneDataOperations(with: timezone!, store: store) |
|
return "\(operationsObject.menuTitle().trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines))" |
|
} |
|
|
|
let titlesStringified = titles.compactMap { $0 } |
|
return titlesStringified.joined(separator: " ") |
|
} |
|
|
|
return nil |
|
} |
|
|
|
func checkForUpcomingEvents(_ filteredEvents: [Date: [EventInfo]], calendar: Calendar) -> String? { |
|
if store.shouldDisplay(.showMeetingInMenubar) { |
|
guard let events = filteredEvents[calendar.startOfDay(for: Date())] else { |
|
return nil |
|
} |
|
|
|
for eventInfo in events { |
|
let event = eventInfo.event |
|
let acceptableCriteria = event.startDate.timeIntervalSinceNow > -300 |
|
if acceptableCriteria, |
|
!eventInfo.isAllDay, |
|
eventInfo.event.status != EKEventStatus.canceled { |
|
let timeForEventToStart = event.startDate.timeIntervalSinceNow / 60 |
|
|
|
if timeForEventToStart > 30 { |
|
Logger.info("Our next event: \(event.title ?? "Error") starts in \(timeForEventToStart) mins") |
|
continue |
|
} |
|
|
|
return format(event: event) |
|
} |
|
} |
|
} |
|
|
|
return nil |
|
} |
|
|
|
internal func format(event: EKEvent) -> String { |
|
guard let truncateLength = store.retrieve(key: CLTruncateTextLength) as? NSNumber, let eventTitle = event.title, event.title.isEmpty == false else { |
|
return CLEmptyString |
|
} |
|
|
|
let seconds = event.startDate.timeIntervalSinceNow |
|
|
|
var menubarText: String = CLEmptyString |
|
|
|
if eventTitle.count > truncateLength.intValue { |
|
let truncateIndex = eventTitle.index(eventTitle.startIndex, offsetBy: truncateLength.intValue) |
|
let truncatedTitle = String(eventTitle[..<truncateIndex]) |
|
|
|
menubarText.append(truncatedTitle) |
|
menubarText.append("...") |
|
} else { |
|
menubarText.append(eventTitle) |
|
} |
|
|
|
let minutes = seconds / 60 |
|
if minutes >= 1 { |
|
let suffix = String(format: " in %0.fm", minutes) |
|
menubarText.append(suffix) |
|
} else { |
|
menubarText.append(" starts now.") |
|
} |
|
|
|
return menubarText |
|
} |
|
}
|
|
|