mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-01-11 17:38:38 +00:00
Added pomodoro timer
This commit is contained in:
parent
86954a7981
commit
9f84b38084
@ -38,6 +38,8 @@
|
|||||||
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */; };
|
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */; };
|
||||||
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B059D62C205F11E8006E6B86 /* DFRFoundation.framework */; };
|
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B059D62C205F11E8006E6B86 /* DFRFoundation.framework */; };
|
||||||
B0679BC1215AE73F000FC6B4 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = B0679BC0215AE73F000FC6B4 /* dsa_pub.pem */; };
|
B0679BC1215AE73F000FC6B4 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = B0679BC0215AE73F000FC6B4 /* dsa_pub.pem */; };
|
||||||
|
B08126EF217BD0B900A98970 /* PomodoroBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B08126EE217BD0B900A98970 /* PomodoroBarItem.swift */; };
|
||||||
|
B08126F1217BE19000A98970 /* WidgetProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B08126F0217BE19000A98970 /* WidgetProtocol.swift */; };
|
||||||
B08173272135F02B005D4908 /* NightShiftBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B08173262135F02B005D4908 /* NightShiftBarItem.swift */; };
|
B08173272135F02B005D4908 /* NightShiftBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B08173262135F02B005D4908 /* NightShiftBarItem.swift */; };
|
||||||
B081732A2135F354005D4908 /* CoreBrightness.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B08173292135F354005D4908 /* CoreBrightness.framework */; };
|
B081732A2135F354005D4908 /* CoreBrightness.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B08173292135F354005D4908 /* CoreBrightness.framework */; };
|
||||||
B081732C213739FE005D4908 /* DnDBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B081732B213739FE005D4908 /* DnDBarItem.swift */; };
|
B081732C213739FE005D4908 /* DnDBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B081732B213739FE005D4908 /* DnDBarItem.swift */; };
|
||||||
@ -110,6 +112,8 @@
|
|||||||
B059D62A205F0E7D006E6B86 /* TouchBarPrivateApi-Bridging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TouchBarPrivateApi-Bridging.h"; sourceTree = "<group>"; };
|
B059D62A205F0E7D006E6B86 /* TouchBarPrivateApi-Bridging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TouchBarPrivateApi-Bridging.h"; sourceTree = "<group>"; };
|
||||||
B059D62C205F11E8006E6B86 /* DFRFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DFRFoundation.framework; path = ../../../../../System/Library/PrivateFrameworks/DFRFoundation.framework; sourceTree = "<group>"; };
|
B059D62C205F11E8006E6B86 /* DFRFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DFRFoundation.framework; path = ../../../../../System/Library/PrivateFrameworks/DFRFoundation.framework; sourceTree = "<group>"; };
|
||||||
B0679BC0215AE73F000FC6B4 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dsa_pub.pem; sourceTree = "<group>"; };
|
B0679BC0215AE73F000FC6B4 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dsa_pub.pem; sourceTree = "<group>"; };
|
||||||
|
B08126EE217BD0B900A98970 /* PomodoroBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PomodoroBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
B08126F0217BE19000A98970 /* WidgetProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetProtocol.swift; sourceTree = "<group>"; };
|
||||||
B08173262135F02B005D4908 /* NightShiftBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightShiftBarItem.swift; sourceTree = "<group>"; };
|
B08173262135F02B005D4908 /* NightShiftBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightShiftBarItem.swift; sourceTree = "<group>"; };
|
||||||
B08173282135F128005D4908 /* CBBlueLightClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CBBlueLightClient.h; sourceTree = "<group>"; };
|
B08173282135F128005D4908 /* CBBlueLightClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CBBlueLightClient.h; sourceTree = "<group>"; };
|
||||||
B08173292135F354005D4908 /* CoreBrightness.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBrightness.framework; path = ../../../../../System/Library/PrivateFrameworks/CoreBrightness.framework; sourceTree = "<group>"; };
|
B08173292135F354005D4908 /* CoreBrightness.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBrightness.framework; path = ../../../../../System/Library/PrivateFrameworks/CoreBrightness.framework; sourceTree = "<group>"; };
|
||||||
@ -284,6 +288,8 @@
|
|||||||
60669B4220AD8FA80074E817 /* GroupBarItem.swift */,
|
60669B4220AD8FA80074E817 /* GroupBarItem.swift */,
|
||||||
B08173262135F02B005D4908 /* NightShiftBarItem.swift */,
|
B08173262135F02B005D4908 /* NightShiftBarItem.swift */,
|
||||||
B081732B213739FE005D4908 /* DnDBarItem.swift */,
|
B081732B213739FE005D4908 /* DnDBarItem.swift */,
|
||||||
|
B08126EE217BD0B900A98970 /* PomodoroBarItem.swift */,
|
||||||
|
B08126F0217BE19000A98970 /* WidgetProtocol.swift */,
|
||||||
);
|
);
|
||||||
path = Widgets;
|
path = Widgets;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -432,9 +438,11 @@
|
|||||||
B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */,
|
B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */,
|
||||||
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */,
|
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */,
|
||||||
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
||||||
|
B08126F1217BE19000A98970 /* WidgetProtocol.swift in Sources */,
|
||||||
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */,
|
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */,
|
||||||
6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */,
|
6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */,
|
||||||
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
||||||
|
B08126EF217BD0B900A98970 /* PomodoroBarItem.swift in Sources */,
|
||||||
B081732C213739FE005D4908 /* DnDBarItem.swift in Sources */,
|
B081732C213739FE005D4908 /* DnDBarItem.swift in Sources */,
|
||||||
60C44AFD20A373A100C0EC91 /* MusicBarItem.swift in Sources */,
|
60C44AFD20A373A100C0EC91 /* MusicBarItem.swift in Sources */,
|
||||||
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
|
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.18.5</string>
|
<string>0.18.5</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>82</string>
|
<string>109</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.utilities</string>
|
<string>public.app-category.utilities</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
|||||||
@ -40,8 +40,14 @@ struct BarItemDefinition: Decodable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typealias ParametersDecoder = (Decoder) throws -> (
|
||||||
|
item: ItemType,
|
||||||
|
action: ActionType,
|
||||||
|
longAction: LongActionType,
|
||||||
|
parameters: [GeneralParameters.CodingKeys: GeneralParameter]
|
||||||
|
)
|
||||||
|
|
||||||
class SupportedTypesHolder {
|
class SupportedTypesHolder {
|
||||||
typealias ParametersDecoder = (Decoder) throws -> (item: ItemType, action: ActionType, longAction: LongActionType, parameters: [GeneralParameters.CodingKeys: GeneralParameter])
|
|
||||||
private var supportedTypes: [String: ParametersDecoder] = [
|
private var supportedTypes: [String: ParametersDecoder] = [
|
||||||
"escape": { _ in (
|
"escape": { _ in (
|
||||||
item: .staticButton(title: "esc"),
|
item: .staticButton(title: "esc"),
|
||||||
@ -304,6 +310,8 @@ class SupportedTypesHolder {
|
|||||||
parameters: [:]
|
parameters: [:]
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
PomodoroBarItem.name: PomodoroBarItem.decoder,
|
||||||
]
|
]
|
||||||
|
|
||||||
static let sharedInstance = SupportedTypesHolder()
|
static let sharedInstance = SupportedTypesHolder()
|
||||||
@ -345,6 +353,7 @@ enum ItemType: Decodable {
|
|||||||
case groupBar(items: [BarItemDefinition])
|
case groupBar(items: [BarItemDefinition])
|
||||||
case nightShift()
|
case nightShift()
|
||||||
case dnd()
|
case dnd()
|
||||||
|
case pomodoro(workTime: Double, restTime: Double)
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case type
|
case type
|
||||||
@ -361,6 +370,8 @@ enum ItemType: Decodable {
|
|||||||
case url
|
case url
|
||||||
case longUrl
|
case longUrl
|
||||||
case items
|
case items
|
||||||
|
case workTime
|
||||||
|
case restTime
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ItemTypeRaw: String, Decodable {
|
enum ItemTypeRaw: String, Decodable {
|
||||||
@ -378,6 +389,7 @@ enum ItemType: Decodable {
|
|||||||
case groupBar
|
case groupBar
|
||||||
case nightShift
|
case nightShift
|
||||||
case dnd
|
case dnd
|
||||||
|
case pomodoro
|
||||||
}
|
}
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
init(from decoder: Decoder) throws {
|
||||||
@ -439,6 +451,11 @@ enum ItemType: Decodable {
|
|||||||
|
|
||||||
case .dnd:
|
case .dnd:
|
||||||
self = .dnd()
|
self = .dnd()
|
||||||
|
|
||||||
|
case .pomodoro:
|
||||||
|
let workTime = try container.decodeIfPresent(Double.self, forKey: .workTime) ?? 1500.0
|
||||||
|
let restTime = try container.decodeIfPresent(Double.self, forKey: .restTime) ?? 600.0
|
||||||
|
self = .pomodoro(workTime: workTime, restTime: restTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,8 @@ extension ItemType {
|
|||||||
return "com.toxblh.mtmr.nightShift."
|
return "com.toxblh.mtmr.nightShift."
|
||||||
case .dnd(items: _):
|
case .dnd(items: _):
|
||||||
return "com.toxblh.mtmr.dnd."
|
return "com.toxblh.mtmr.dnd."
|
||||||
|
case .pomodoro(interval: _):
|
||||||
|
return PomodoroBarItem.identifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,6 +283,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
barItem = NightShiftBarItem(identifier: identifier)
|
barItem = NightShiftBarItem(identifier: identifier)
|
||||||
case .dnd():
|
case .dnd():
|
||||||
barItem = DnDBarItem(identifier: identifier)
|
barItem = DnDBarItem(identifier: identifier)
|
||||||
|
case .pomodoro(workTime: let workTime, restTime: let restTime):
|
||||||
|
barItem = PomodoroBarItem(identifier: identifier, workTime: workTime, restTime: restTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let action = self.action(forItem: item), let item = barItem as? CustomButtonTouchBarItem {
|
if let action = self.action(forItem: item), let item = barItem as? CustomButtonTouchBarItem {
|
||||||
|
|||||||
123
MTMR/Widgets/PomodoroBarItem.swift
Normal file
123
MTMR/Widgets/PomodoroBarItem.swift
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
//
|
||||||
|
// PomodoroBarItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Daniel Apatin on 10.05.2018.
|
||||||
|
// Copyright © 2018 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
class PomodoroBarItem: CustomButtonTouchBarItem, Widget {
|
||||||
|
static let identifier = "com.toxblh.mtmr.pomodoro."
|
||||||
|
static let name = "pomodoro"
|
||||||
|
static let decoder: ParametersDecoder = { decoder in
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case workTime
|
||||||
|
case restTime
|
||||||
|
}
|
||||||
|
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
let workTime = try container.decodeIfPresent(Double.self, forKey: .workTime)
|
||||||
|
let restTime = try container.decodeIfPresent(Double.self, forKey: .restTime)
|
||||||
|
|
||||||
|
return (
|
||||||
|
item: .pomodoro(workTime: workTime ?? 1500.00, restTime: restTime ?? 300),
|
||||||
|
action: .none,
|
||||||
|
longAction: .none,
|
||||||
|
parameters: [:]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum TimeTypes {
|
||||||
|
case work
|
||||||
|
case rest
|
||||||
|
case none
|
||||||
|
}
|
||||||
|
private let defaultTitle = "🍅"
|
||||||
|
private let workTime: TimeInterval
|
||||||
|
private let restTime: TimeInterval
|
||||||
|
private var typeTime: TimeTypes = .none
|
||||||
|
private var timer: DispatchSourceTimer?
|
||||||
|
|
||||||
|
private var timeLeft: Int = 0
|
||||||
|
private var timeLeftString: String {
|
||||||
|
return String(format: "%.2i:%.2i", timeLeft / 60, timeLeft % 60)
|
||||||
|
}
|
||||||
|
|
||||||
|
init(identifier: NSTouchBarItem.Identifier, workTime: TimeInterval, restTime: TimeInterval) {
|
||||||
|
self.workTime = workTime
|
||||||
|
self.restTime = restTime
|
||||||
|
super.init(identifier: identifier, title: defaultTitle)
|
||||||
|
tapClosure = { [weak self] in self?.startStopWork() }
|
||||||
|
longTapClosure = { [weak self] in self?.startStopRest() }
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
timer?.cancel()
|
||||||
|
timer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func startStopWork() {
|
||||||
|
typeTime = .work
|
||||||
|
startStopTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func startStopRest() {
|
||||||
|
typeTime = .rest
|
||||||
|
startStopTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func startStopTimer() {
|
||||||
|
timer == nil ? start() : reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func start() {
|
||||||
|
timeLeft = Int(typeTime == .work ? workTime : restTime)
|
||||||
|
let queue: DispatchQueue = DispatchQueue(label: "Timer")
|
||||||
|
timer = DispatchSource.makeTimerSource(flags: .strict, queue: queue)
|
||||||
|
timer?.schedule(deadline: .now(), repeating: .seconds(1), leeway: .never)
|
||||||
|
timer?.setEventHandler(handler: tick)
|
||||||
|
timer?.resume()
|
||||||
|
|
||||||
|
NSSound.beep()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func finish() {
|
||||||
|
if typeTime != .none {
|
||||||
|
sendNotification()
|
||||||
|
}
|
||||||
|
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func reset() {
|
||||||
|
typeTime = .none
|
||||||
|
timer?.cancel()
|
||||||
|
timer = nil
|
||||||
|
title = defaultTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
private func tick() {
|
||||||
|
timeLeft -= 1
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
if self.timeLeft >= 0 {
|
||||||
|
self.title = self.defaultTitle + " " + self.timeLeftString
|
||||||
|
} else {
|
||||||
|
self.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func sendNotification() {
|
||||||
|
let notification: NSUserNotification = NSUserNotification()
|
||||||
|
notification.title = "Pomodoro"
|
||||||
|
notification.informativeText = typeTime == .work ? "it's time to rest your mind!" : "It's time to work!"
|
||||||
|
notification.soundName = "Submarine"
|
||||||
|
NSUserNotificationCenter.default.deliver(notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
MTMR/Widgets/WidgetProtocol.swift
Normal file
13
MTMR/Widgets/WidgetProtocol.swift
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// WidgetProtocol.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Anton Palgunov on 20/10/2018.
|
||||||
|
// Copyright © 2018 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
protocol Widget {
|
||||||
|
static var name: String { get }
|
||||||
|
static var identifier: String { get }
|
||||||
|
static var decoder: ParametersDecoder { get }
|
||||||
|
}
|
||||||
115
README.md
115
README.md
@ -1,7 +1,4 @@
|
|||||||
|
<p align="center"><img src="Resources/logo.png" width="120"></p>
|
||||||
<p align="center">
|
|
||||||
<img src="Resources/logo.png" width="120">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
# My TouchBar. My rules
|
# My TouchBar. My rules
|
||||||
|
|
||||||
@ -26,48 +23,12 @@
|
|||||||
|
|
||||||
My the idea is to create the program like a platform for plugins for customization TouchBar. I very like BTT and a full custom TouchBar (my [BTT preset](https://github.com/Toxblh/btt-touchbar-preset)). And I want to create it. And it's my the first Swift project for MacOS :)
|
My the idea is to create the program like a platform for plugins for customization TouchBar. I very like BTT and a full custom TouchBar (my [BTT preset](https://github.com/Toxblh/btt-touchbar-preset)). And I want to create it. And it's my the first Swift project for MacOS :)
|
||||||
|
|
||||||
### Roadmap
|
|
||||||
- [x] Create the first prototype with TouchBar in Storyboard
|
|
||||||
- [x] Put in stripe menu on startup the application
|
|
||||||
- [x] Find how to simulate real buttons like brightness, volume, night shift and etc.
|
|
||||||
- [x] Time in touchbar!
|
|
||||||
- [x] First the weather plugin
|
|
||||||
- [x] Find how to open full-screen TouchBar without the cross and stripe menu
|
|
||||||
- [x] Find how to add haptic feedback
|
|
||||||
- [x] Add icon and menu in StatusBar
|
|
||||||
- [x] Hide from Dock
|
|
||||||
- [x] Status menu: "preferences", "quit"
|
|
||||||
- [x] JSON or another approch for save preset, maybe in `~/Library/Application Support/MTMR/`
|
|
||||||
- [x] Custom buttons size, actions by click
|
|
||||||
- [x] Layout: [always left, NSSliderView for center, always right]
|
|
||||||
- [x] System for autoupdate (https://sparkle-project.org/)
|
|
||||||
- [ ] Overwrite default values from item types (e.g. title for brightness)
|
|
||||||
- [ ] Custom settings for paddings and margins for buttons
|
|
||||||
- [ ] XPC Service for scripts
|
|
||||||
- [ ] UI for settings
|
|
||||||
- [ ] Import config from BTT
|
|
||||||
|
|
||||||
Settings:
|
|
||||||
- [ ] Interface for plugins and export like presets
|
|
||||||
- [x] Startup at login
|
|
||||||
- [ ] Show on/off in Dock
|
|
||||||
- [ ] Show on/off in StatusBar
|
|
||||||
- [ ] On/off Haptic Feedback
|
|
||||||
|
|
||||||
Maybe:
|
|
||||||
- [ ] Refactoring the application on packages (AppleScript, JavaScript? and Swift?)
|
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
- Download last [release](https://github.com/Toxblh/MTMR/releases)
|
- Download last [release](https://github.com/Toxblh/MTMR/releases) from github
|
||||||
- Or via Homebrew `brew cask install mtmr`
|
- Or via Homebrew `brew cask install mtmr`
|
||||||
|
|
||||||
## Preset
|
|
||||||
|
|
||||||
File for customize your preset for MTMR: `open ~/Library/Application\ Support/MTMR/items.json`
|
|
||||||
|
|
||||||
## Built-in button types:
|
## Built-in button types:
|
||||||
|
> Buttons
|
||||||
- escape
|
- escape
|
||||||
- exitTouchbar
|
- exitTouchbar
|
||||||
- brightnessUp
|
- brightnessUp
|
||||||
@ -77,9 +38,6 @@ File for customize your preset for MTMR: `open ~/Library/Application\ Support/MT
|
|||||||
- volumeDown
|
- volumeDown
|
||||||
- volumeUp
|
- volumeUp
|
||||||
- mute
|
- mute
|
||||||
- dock (half-long click to open app, full-long click to kill app)
|
|
||||||
- nightShift
|
|
||||||
- dnd (Dont disturb)
|
|
||||||
|
|
||||||
> Native Plugins
|
> Native Plugins
|
||||||
- battery
|
- battery
|
||||||
@ -87,6 +45,10 @@ File for customize your preset for MTMR: `open ~/Library/Application\ Support/MT
|
|||||||
- weather
|
- weather
|
||||||
- inputsource
|
- inputsource
|
||||||
- music (tap for pause, longTap for next)
|
- music (tap for pause, longTap for next)
|
||||||
|
- dock (half-long click to open app, full-long click to kill app)
|
||||||
|
- nightShift
|
||||||
|
- dnd (Don't disturb)
|
||||||
|
- pomodoro
|
||||||
|
|
||||||
> Media Keys
|
> Media Keys
|
||||||
- previous
|
- previous
|
||||||
@ -139,39 +101,50 @@ File for customize your preset for MTMR: `open ~/Library/Application\ Support/MT
|
|||||||
"align": "center",
|
"align": "center",
|
||||||
"bordered": true,
|
"bordered": true,
|
||||||
"title": "stats",
|
"title": "stats",
|
||||||
"items": [{ button }, {button}, ...]
|
"items": [
|
||||||
|
{ "type": "play" }, { "type": "mute" }, ...]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Native plugins
|
## Native plugins
|
||||||
- `weather`
|
#### `weather`
|
||||||
> Provider: https://openweathermap.org Need allowance location service
|
> Provider: https://openweathermap.org Need allowance location service
|
||||||
```js
|
```js
|
||||||
"type": "weather",
|
"type": "weather",
|
||||||
"refreshInterval": 600,
|
"refreshInterval": 600, // in seconds
|
||||||
"units": "metric", // or imperial
|
"units": "metric", // or imperial
|
||||||
"icon_type": "text" // or images
|
"icon_type": "text" // or images
|
||||||
"api_key": "" // you can get the key on openweather
|
"api_key": "" // you can get the key on openweather
|
||||||
```
|
```
|
||||||
|
|
||||||
- `currency`
|
#### `currency`
|
||||||
> Provider: https://coinbase.com
|
> Provider: https://coinbase.com
|
||||||
```js
|
```js
|
||||||
"type": "currency",
|
"type": "currency",
|
||||||
"refreshInterval": 600,
|
"refreshInterval": 600, // in seconds
|
||||||
"align": "right",
|
"align": "right",
|
||||||
"from": "BTC",
|
"from": "BTC",
|
||||||
"to": "USD",
|
"to": "USD",
|
||||||
```
|
```
|
||||||
|
|
||||||
- `music`
|
#### `music`
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
"type": "music",
|
"type": "music",
|
||||||
"align": "center",
|
"align": "center",
|
||||||
"width": 80,
|
"width": 80,
|
||||||
"bordered": false,
|
"bordered": false,
|
||||||
"refreshInterval": 2,
|
"refreshInterval": 2, // in seconds
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `pomodoro`
|
||||||
|
> Pomodoro plugin. One click for start work timer, longclick for start rest timer. Click in progress for reset.
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"type": "pomodoro",
|
||||||
|
"workTime": 1200, // set time work in seconds. Default 1500 (25 min)
|
||||||
|
"restTime": 600, // set time rest in seconds. Default 300 (5 min)
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -235,7 +208,12 @@ This then you want to use longPress for some operations is will the same values
|
|||||||
|
|
||||||
- `align` can stick the item to the side. default is center
|
- `align` can stick the item to the side. default is center
|
||||||
```js
|
```js
|
||||||
"align": "left" //or "right" or "center"
|
"align": "left" // "left", "right" or "center"
|
||||||
|
```
|
||||||
|
|
||||||
|
- `bordered` you can do button without border
|
||||||
|
```js
|
||||||
|
"bordered": "false" // "true" or "false"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Example configuration:
|
## Example configuration:
|
||||||
@ -296,6 +274,37 @@ This then you want to use longPress for some operations is will the same values
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Roadmap
|
||||||
|
- [x] Create the first prototype with TouchBar in Storyboard
|
||||||
|
- [x] Put in stripe menu on startup the application
|
||||||
|
- [x] Find how to simulate real buttons like brightness, volume, night shift and etc.
|
||||||
|
- [x] Time in touchbar!
|
||||||
|
- [x] First the weather plugin
|
||||||
|
- [x] Find how to open full-screen TouchBar without the cross and stripe menu
|
||||||
|
- [x] Find how to add haptic feedback
|
||||||
|
- [x] Add icon and menu in StatusBar
|
||||||
|
- [x] Hide from Dock
|
||||||
|
- [x] Status menu: "preferences", "quit"
|
||||||
|
- [x] JSON or another approch for save preset, maybe in `~/Library/Application Support/MTMR/`
|
||||||
|
- [x] Custom buttons size, actions by click
|
||||||
|
- [x] Layout: [always left, NSSliderView for center, always right]
|
||||||
|
- [x] System for autoupdate (https://sparkle-project.org/)
|
||||||
|
- [ ] Overwrite default values from item types (e.g. title for brightness)
|
||||||
|
- [ ] Custom settings for paddings and margins for buttons
|
||||||
|
- [ ] XPC Service for scripts
|
||||||
|
- [ ] UI for settings
|
||||||
|
- [ ] Import config from BTT
|
||||||
|
|
||||||
|
Settings:
|
||||||
|
- [ ] Interface for plugins and export like presets
|
||||||
|
- [x] Startup at login
|
||||||
|
- [ ] Show on/off in Dock
|
||||||
|
- [ ] Show on/off in StatusBar
|
||||||
|
- [ ] On/off Haptic Feedback
|
||||||
|
|
||||||
|
Maybe:
|
||||||
|
- [ ] Refactoring the application on packages (AppleScript, JavaScript? and Swift?)
|
||||||
|
|
||||||
### Author's presets
|
### Author's presets
|
||||||
|
|
||||||
[@Toxblh preset](Resources/toxblh.json)
|
[@Toxblh preset](Resources/toxblh.json)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user