1
0
mirror of https://github.com/Toxblh/MTMR.git synced 2026-01-10 00:58:37 +00:00

WIP Implementation of up next widget

This commit is contained in:
connorgmeehan 2020-07-24 23:22:25 +10:00
parent 14282b86a9
commit 8b5c2f10b7
5 changed files with 188 additions and 0 deletions

View File

@ -71,6 +71,7 @@
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */; };
BAF5AB5724317B4300B04904 /* BasicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF5AB5624317B4300B04904 /* BasicView.swift */; };
BAF5AB5924317CAF00B04904 /* SwipeItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF5AB5824317CAF00B04904 /* SwipeItem.swift */; };
F29F6A2524BC7148004FF8E4 /* UpNextBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F29F6A2424BC7148004FF8E4 /* UpNextBarItem.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -163,6 +164,7 @@
B0F8771B207AC92700D6E430 /* TouchBarSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarSupport.h; sourceTree = "<group>"; };
BAF5AB5624317B4300B04904 /* BasicView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicView.swift; sourceTree = "<group>"; };
BAF5AB5824317CAF00B04904 /* SwipeItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeItem.swift; sourceTree = "<group>"; };
F29F6A2424BC7148004FF8E4 /* UpNextBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpNextBarItem.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -322,6 +324,7 @@
4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */,
B08126F0217BE19000A98970 /* WidgetProtocol.swift */,
B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */,
F29F6A2424BC7148004FF8E4 /* UpNextBarItem.swift */,
);
path = Widgets;
sourceTree = "<group>";
@ -488,6 +491,7 @@
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */,
4CDC6E5022FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift in Sources */,
607EEA4B2087835F009DA5F0 /* WeatherBarItem.swift in Sources */,
F29F6A2524BC7148004FF8E4 /* UpNextBarItem.swift in Sources */,
B0F3112520C9E35F0076BB88 /* SupportNSTouchBar.swift in Sources */,
4CFF5E5C22E623DD00BFB1EE /* YandexWeatherBarItem.swift in Sources */,
6042B6AA2083E27000C525C8 /* DeprecatedCarbonAPI.c in Sources */,

View File

@ -227,6 +227,7 @@ enum ItemType: Decodable {
case network(flip: Bool)
case darkMode
case swipe(direction: String, fingers: Int, minOffset: Float, sourceApple: SourceProtocol?, sourceBash: SourceProtocol?)
case upnext(from: Double, to: Double, nthEvent: Int)
private enum CodingKeys: String, CodingKey {
case type
@ -258,6 +259,7 @@ enum ItemType: Decodable {
case direction
case fingers
case minOffset
case nthEvent
}
enum ItemTypeRaw: String, Decodable {
@ -281,6 +283,7 @@ enum ItemType: Decodable {
case network
case darkMode
case swipe
case upnext
}
init(from decoder: Decoder) throws {
@ -378,6 +381,12 @@ enum ItemType: Decodable {
let fingers = try container.decode(Int.self, forKey: .fingers)
let minOffset = try container.decodeIfPresent(Float.self, forKey: .minOffset) ?? 0.0
self = .swipe(direction: direction, fingers: fingers, minOffset: minOffset, sourceApple: sourceApple, sourceBash: sourceBash)
case .upnext:
let from = try container.decodeIfPresent(Double.self, forKey: .from) ?? 0 // Lower bounds of period of time in hours to search for events
let to = try container.decodeIfPresent(Double.self, forKey: .to) ?? 1 // Upper bounds of period of time in hours to search for events
let nthEvent = try container.decodeIfPresent(Int.self, forKey: .nthEvent) ?? 1 // 1 indexed array. Get the 1st, 2nd, 3rd event to display multiple notifications
self = .upnext(from: from, to: to, nthEvent: nthEvent)
}
}
}

View File

@ -59,6 +59,8 @@ extension ItemType {
return DarkModeBarItem.identifier
case .swipe(direction: _, fingers: _, minOffset: _, sourceApple: _, sourceBash: _):
return "com.toxblh.mtmr.swipe."
case .upnext:
return "com.connorgmeehan.mtmrupnext."
}
}
}
@ -301,6 +303,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
barItem = DarkModeBarItem(identifier: identifier)
case let .swipe(direction: direction, fingers: fingers, minOffset: minOffset, sourceApple: sourceApple, sourceBash: sourceBash):
barItem = SwipeItem(identifier: identifier, direction: direction, fingers: fingers, minOffset: minOffset, sourceApple: sourceApple, sourceBash: sourceBash)
case let .upnext(from: from, to: to, nthEvent: nthEvent):
barItem = UpNextBarItem(identifier: identifier, interval: 10, from: from, to: to, nthEvent: nthEvent)
}
if let action = self.action(forItem: item), let item = barItem as? CustomButtonTouchBarItem {

View File

@ -0,0 +1,155 @@
//
// UpNextBarItems.swift
// MTMR
//
// Created by Connor Meehan on 13/7/20.
// Copyright © 2020 Anton Palgunov. All rights reserved.
//
//
import Foundation
import EventKit
class UpNextBarItem: CustomButtonTouchBarItem {
private let activity: NSBackgroundActivityScheduler // Update scheduler
private let eventStore = EKEventStore() //
private let df = DateFormatter()
private let buttonTemplate = "🗓 %@ - %@ "
// Settings
private var futureSearchCutoff: Double
private var pastSearchCutoff: Double
private var nthEvent: Int
// State
private var hasPermission: Bool = false
/// <#Description#>
/// - Parameters:
/// - identifier: Unique identifier of widget
/// - interval: Update view interval in seconds
/// - from: Relative to current time, how far back we search for events in hours
/// - to: Relative to current time, how far forward we search for events in hours
/// - nthEvent: Which event to show (1 is first, 2 is second, and so on)
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: Double, to: Double, nthEvent: Int) {
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updateCheck")
activity.interval = interval
self.pastSearchCutoff = from
self.futureSearchCutoff = to
self.nthEvent = nthEvent
self.df.dateFormat = "HH:mm"
if (nthEvent <= 0) {
fatalError("Error on UpNext bar item. nthEvent property must be greater than 0.")
}
super.init(identifier: identifier, title: " ")
let authorizationStatus = EKEventStore.authorizationStatus(for: EKEntityType.event)
switch authorizationStatus {
case .notDetermined:
print("notDetermined")
case .restricted:
print("restricted")
case .denied:
print("denied")
case .authorized:
print("authorizded")
default:
print("Unkown EKEventStore authorization status")
}
eventStore.requestAccess(to: .event){ granted, error in
self.hasPermission = granted;
if(!granted) {
NSLog("Error: MTMR UpNextBarWidget not given calendar access.")
return
}
self.updateView()
}
tapClosure = { [weak self] in self?.gotoAppleCalendar() }
// Start activity to update view
activity.repeats = true
activity.qualityOfService = .utility
activity.schedule { (completion: NSBackgroundActivityScheduler.CompletionHandler) in
self.updateView()
completion(NSBackgroundActivityScheduler.Result.finished)
}
updateView()
}
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateView() {
if (!self.hasPermission) {
self.title = "🗓 No permissions"
return
}
var upcomingEvents = self.getUpcomingEvents()
upcomingEvents.sort(by: {$0.startDate.compare($1.startDate) == .orderedAscending})
for event in upcomingEvents {
print("\(event.title) - \(event.startDate)")
}
if (upcomingEvents.count >= self.nthEvent) {
let event = upcomingEvents[self.nthEvent-1]
let title = event.title
let startDateString = self.df.string(for: event.startDate)
print("TITLE: " + title + " STARTDATE: " + (startDateString ?? "nil"))
DispatchQueue.main.async {
print("SHOW")
self.image = nil
self.title = String(format: self.buttonTemplate, title, startDateString ?? "No time")
self.view.isHidden = false
}
} else {
// Do not display any event
DispatchQueue.main.async {
print("HIDE " + String(upcomingEvents.count) + " " + String(self.nthEvent) + " " + String(upcomingEvents.count > self.nthEvent))
self.image = nil
self.title = ""
self.view.isHidden = true
}
}
}
func getUpcomingEvents() -> [UpNextEventModel] {
var upcomingEvents: [UpNextEventModel] = []
NSLog("Getting calendar events...")
// Calculate the range we're going to search for events in
let dateLowerBounds = Date(timeIntervalSinceNow: self.pastSearchCutoff * 360)
let dateUpperBounds = Date(timeIntervalSinceNow: self.futureSearchCutoff * 360)
let calendars = self.eventStore.calendars(for: .event)
for calendar in calendars {
let predicate = self.eventStore.predicateForEvents(withStart: dateLowerBounds, end: dateUpperBounds, calendars: [calendar])
let events = self.eventStore.events(matching: predicate)
for event in events {
upcomingEvents.append(UpNextEventModel(title: event.title, startDate: event.startDate))
}
}
print("Found " + String(upcomingEvents.count) + " events.")
return upcomingEvents
}
func gotoAppleCalendar() {
print("CLICK")
NSWorkspace.shared.open(URL(fileURLWithPath: "/Applications/Photos.app"))
}}
struct UpNextEventModel {
var title: String
var startDate: Date
}

View File

@ -84,6 +84,7 @@ The pre-installed configuration contains less or more than you'll probably want,
- darkMode
- pomodoro
- network
- upnext (Calendar events)
> Media Keys
@ -343,6 +344,21 @@ To close a group, use the button:
},
```
#### `upnext`
> Calender next event plugin
```js
{
"type": "upnext",
"from": 0, // Lower bound of search range for next event in hours. Default 0 (current time)
"to": 1, // Upper bounds of search range for next event in hours. Default 1 (one hour in the future)
"nthEvent": 1 // Sets this touchbar button to show the nthEvent. Default 1 (the first upcoming event)
},
```
## Actions:
- `hidKey`