Browse Source

Merge branch 'master' of https://github.com/n0shake/Clocker

pull/101/head
Abhishek 3 years ago
parent
commit
6d2c3bdb4a
  1. 81
      Clocker/Events and Reminders/CalendarHandler.swift
  2. 13
      Clocker/Events and Reminders/EventCenter.swift
  3. 13
      Clocker/Overall App/Themer.swift
  4. 22
      Clocker/Panel/ParentPanelController.swift

81
Clocker/Events and Reminders/CalendarHandler.swift

@ -150,7 +150,7 @@ extension EventCenter {
return menubarText
}
func nextOccuring(_: [EventInfo]) -> EKEvent? {
func nextOccuring(_: [EventInfo]) -> EventInfo? {
if calendarAccessDenied() || calendarAccessNotDetermined() {
return nil
}
@ -162,14 +162,14 @@ extension EventCenter {
}.first
if let firstEvent = filteredEvent {
return firstEvent.event
return firstEvent
}
let filteredAllDayEvent = relevantEvents.filter {
$0.isAllDay
}.first
return filteredAllDayEvent?.event
return filteredAllDayEvent
}
func initializeStoreIfNeccesary() {
@ -201,7 +201,7 @@ extension EventCenter {
for event in events {
if selectedCalendars.contains(event.event.calendar.calendarIdentifier) {
if filteredEvents[date] == nil {
filteredEvents[date] = []
filteredEvents[date] = Array()
}
filteredEvents[date]?.append(event)
@ -332,14 +332,82 @@ extension EventCenter {
let isEndDate = autoupdatingCalendar.isDate(date, inSameDayAs: event.endDate) && (event.startDate.compare(date) == .orderedAscending)
let isAllDay = event.isAllDay || (event.startDate.compare(date) == .orderedAscending && event.endDate.compare(nextDate) == .orderedSame)
let isSingleDay = event.isAllDay && (event.startDate.compare(date) == .orderedSame && event.endDate.compare(nextDate) == .orderedSame)
let meetingURL = retrieveMeetingURL(event)
let eventInfo = EventInfo(event: event,
isStartDate: isStartDate,
isEndDate: isEndDate,
isAllDay: isAllDay,
isSingleDay: isSingleDay)
isSingleDay: isSingleDay,
meetingURL: meetingURL)
return eventInfo
}
static var dataDetector: NSDataDetector?
// Borrowing logic from Ityscal
@discardableResult
private func findAppropriateURLs(_ description: String) -> URL? {
guard let results = EventCenter.dataDetector?.matches(in: description, options: .reportCompletion, range: NSMakeRange(0, description.count)) else {
return nil
}
for result in results {
if result.resultType == .link, var actualLink = result.url?.absoluteString {
// Check for Zoom links
if actualLink.contains("zoom.us/j/") || actualLink.contains("zoom.us/s/") || actualLink.contains("zoom.us/w/") {
// Create a Zoom App link
let workspace = NSWorkspace.shared
if workspace.urlForApplication(toOpen: URL(string: "zoommtg://")!) != nil {
actualLink = actualLink.replacingOccurrences(of: "https://", with: "zoommtg://")
actualLink = actualLink.replacingOccurrences(of: "?", with: "&")
actualLink = actualLink.replacingOccurrences(of: "/j/", with: "/join?confno=")
actualLink = actualLink.replacingOccurrences(of: "/s/", with: "/join?confno=")
actualLink = actualLink.replacingOccurrences(of: "/w/", with: "/join?confno=")
if let appLink = URL(string: actualLink) {
return appLink
}
}
} else if actualLink.contains("zoommtg://")
|| actualLink.contains("meet.google.com/")
|| actualLink.contains("hangouts.google.com/")
|| actualLink.contains("webex.com/")
|| actualLink.contains("gotomeeting.com/join")
|| actualLink.contains("ringcentral.com/j")
|| actualLink.contains("bigbluebutton.org/gl")
|| actualLink.contains("://bigbluebutton.")
|| actualLink.contains("://bbb.")
|| actualLink.contains("indigo.collocall.de")
|| actualLink.contains("public.senfcall.de")
|| actualLink.contains("youcanbook.me/zoom/")
|| actualLink.contains("workplace.com/groupcall") {
if let zoomLink = result.url {
return zoomLink
}
}
}
}
return nil
}
private func retrieveMeetingURL(_ event: EKEvent) -> URL? {
if EventCenter.dataDetector == nil {
// TODO: Handle Try-Catch gracefully
EventCenter.dataDetector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
}
if let location = event.location {
return findAppropriateURLs(location)
}
if let url = event.url {
return findAppropriateURLs(url.absoluteString)
}
if let notes = event.notes {
return findAppropriateURLs(notes)
}
return nil
}
}
struct CalendarInfo {
@ -353,4 +421,5 @@ struct EventInfo {
let isEndDate: Bool
let isAllDay: Bool
let isSingleDay: Bool
let meetingURL: URL?
}

13
Clocker/Events and Reminders/EventCenter.swift

@ -16,6 +16,8 @@ class EventCenter: NSObject {
var eventsForDate: [Date: [EventInfo]] = [:]
var filteredEvents: [Date: [EventInfo]] = [:]
private let fetchQueue = DispatchQueue(label: "com.abhishek.fetch")
@discardableResult class func sharedCenter() -> EventCenter {
return shared
@ -41,11 +43,16 @@ class EventCenter: NSObject {
private func refetchAll() {
Logger.info("\nRefetching events from the store")
eventsForDate = [:]
filteredEvents = [:]
autoreleasepool {
fetchQueue.async {
// We get events for a 120 day period.
// If the user uses a calendar often, this will be called frequently
self.fetchEvents(-40, 80)
}
}
// We get events for a 120 day period.
// If the user uses a calendar often, this will be called frequently
fetchEvents(-40, 80)
}
}

13
Clocker/Overall App/Themer.swift

@ -187,8 +187,8 @@ extension Themer {
return
themeIndex == .light
? NSImage(named: NSImage.Name("Settings"))!
: NSImage(named: NSImage.Name("Settings-White"))!
? NSImage(named: NSImage.Name("Settings"))!
: NSImage(named: NSImage.Name("Settings-White"))!
}
func pinImage() -> NSImage {
@ -442,6 +442,15 @@ extension Themer {
NSColor(deviceRed: 42.0 / 255.0, green: 55.0 / 255.0, blue: 62.0 / 255.0, alpha: 1.0)
}
func videoCallImage() -> NSImage? {
if #available(macOS 11.0, *) {
let symbolConfig = NSImage.SymbolConfiguration(pointSize: 20, weight: .regular)
return symbolImage(for: "video.circle.fill")?.withSymbolConfiguration(symbolConfig)
} else {
return nil
}
}
func symbolImage(for name: String) -> NSImage? {
assert(name.isEmpty == false)

22
Clocker/Panel/ParentPanelController.swift

@ -698,6 +698,16 @@ class ParentPanelController: NSWindowController {
func removeUpcomingEventView() {
OperationQueue.main.addOperation {
let eventCenter = EventCenter.sharedCenter()
let now = Date()
if let events = eventCenter.eventsForDate[NSCalendar.autoupdatingCurrent.startOfDay(for: now)], events.isEmpty == false {
guard let upcomingEvent = eventCenter.nextOccuring(events), let meetingLink = upcomingEvent.meetingURL else {
return
}
NSWorkspace.shared.open(meetingLink)
return
}
if self.stackView.arrangedSubviews.contains(self.upcomingEventView!), self.upcomingEventView?.isHidden == false {
self.upcomingEventView?.isHidden = true
UserDefaults.standard.set("NO", forKey: CLShowUpcomingEventView)
@ -812,9 +822,9 @@ class ParentPanelController: NSWindowController {
return
}
self.calendarColorView.layer?.backgroundColor = upcomingEvent.calendar.color.cgColor
self.nextEventLabel.stringValue = upcomingEvent.title
self.nextEventLabel.toolTip = upcomingEvent.title
self.calendarColorView.layer?.backgroundColor = upcomingEvent.event.calendar.color.cgColor
self.nextEventLabel.stringValue = upcomingEvent.event.title
self.nextEventLabel.toolTip = upcomingEvent.event.title
if upcomingEvent.isAllDay == true {
let title = events.count == 1 ? "All-Day" : "All Day - Total \(events.count) events today"
self.setCalendarButtonTitle(buttonTitle: title)
@ -824,11 +834,15 @@ class ParentPanelController: NSWindowController {
return
}
let timeSince = Date().timeAgo(since: upcomingEvent.startDate)
let timeSince = Date().timeAgo(since: upcomingEvent.event.startDate)
let withoutAn = timeSince.replacingOccurrences(of: "an", with: CLEmptyString)
let withoutAgo = withoutAn.replacingOccurrences(of: "ago", with: CLEmptyString)
self.setCalendarButtonTitle(buttonTitle: "in \(withoutAgo.lowercased())")
if upcomingEvent.meetingURL != nil {
self.whiteRemoveButton.image = Themer.shared().videoCallImage()
}
if #available(OSX 10.14, *) {
PerfLogger.endMarker("Fetch Calendar Events")

Loading…
Cancel
Save