mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-10-31 10:28:36 +00:00
Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6721f0274 | ||
|
|
75df82a567 | ||
|
|
a1f64028cc | ||
|
|
3fc75ca8f0 | ||
|
|
6d266394a4 | ||
|
|
52758f947d | ||
|
|
502f989417 | ||
|
|
f61550e510 | ||
|
|
a0fc0b33c5 | ||
|
|
42ce95b72e | ||
|
|
642f0807bb | ||
|
|
dbb2f16222 | ||
|
|
3864591777 | ||
|
|
7e0db70fab | ||
|
|
40c684f528 | ||
|
|
093faa2c02 | ||
|
|
aeee9983d1 | ||
|
|
bdfb7118c9 | ||
|
|
878cd346c1 | ||
|
|
712448f207 | ||
|
|
e9e5a6f739 |
@@ -0,0 +1,22 @@
|
|||||||
|
name: Build-and-test
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: macOS-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: xcodebuild test -project MTMR.xcodeproj -scheme 'UnitTests' | xcpretty -c && exit ${PIPESTATUS[0]}
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: macOS-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: xcodebuild archive -project "MTMR.xcodeproj" -scheme "MTMR" -archivePath Release/App.xcarchive DEVELOPMENT_TEAM="" CODE_SIGN_IDENTITY="" | xcpretty -c && exit ${PIPESTATUS[0]}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
name: Publish unsign version
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Build-and-release:
|
||||||
|
runs-on: macOS-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 12.x
|
||||||
|
|
||||||
|
- name: Install create-dmg
|
||||||
|
run: npm i -g create-dmg
|
||||||
|
|
||||||
|
- name: Build Archive
|
||||||
|
run: xcodebuild archive -project "MTMR.xcodeproj" -scheme "MTMR" -archivePath Release/App.xcarchive DEVELOPMENT_TEAM="" CODE_SIGN_IDENTITY="" | xcpretty -c && exit ${PIPESTATUS[0]}
|
||||||
|
|
||||||
|
- name: Build App
|
||||||
|
run: xcodebuild -project "MTMR.xcodeproj" -exportArchive -archivePath Release/App.xcarchive -exportOptionsPlist export-options.plist -exportPath Release | xcpretty -c && exit ${PIPESTATUS[0]}
|
||||||
|
|
||||||
|
- name: Create DMG
|
||||||
|
run: |
|
||||||
|
cd Release
|
||||||
|
create-dmg MTMR.app || true
|
||||||
|
|
||||||
|
- name: GitHub Release
|
||||||
|
uses: "marvinpinto/action-automatic-releases@latest"
|
||||||
|
with:
|
||||||
|
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
prerelease: false
|
||||||
|
files: Release/MTMR*.dmg
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
language: swift
|
|
||||||
xcode_project: MTMR.xcodeproj
|
|
||||||
xcode_scheme: UnitTests
|
|
||||||
osx_image: xcode11.1
|
|
||||||
install: gem install xcpretty
|
|
||||||
script: "xcodebuild test -project MTMR.xcodeproj -scheme 'UnitTests' | xcpretty -c && exit ${PIPESTATUS[0]}"
|
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
4CC9FEDC22FDEA65001512EB /* AMR_ANSIEscapeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC9FEDB22FDEA65001512EB /* AMR_ANSIEscapeHelper.m */; };
|
4CC9FEDC22FDEA65001512EB /* AMR_ANSIEscapeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC9FEDB22FDEA65001512EB /* AMR_ANSIEscapeHelper.m */; };
|
||||||
4CDC6E5022FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */; };
|
4CDC6E5022FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */; };
|
||||||
4CFF5E5C22E623DD00BFB1EE /* YandexWeatherBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */; };
|
4CFF5E5C22E623DD00BFB1EE /* YandexWeatherBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */; };
|
||||||
|
5DC6CA02241F92CB005CD5E8 /* Music.nowPlaying.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 5DC6CA00241F92CB005CD5E8 /* Music.nowPlaying.scpt */; };
|
||||||
|
5DC6CA03241F92CB005CD5E8 /* Music.next.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 5DC6CA01241F92CB005CD5E8 /* Music.next.scpt */; };
|
||||||
60173D3E20C0031B002C305F /* LaunchAtLoginController.m in Sources */ = {isa = PBXBuildFile; fileRef = 60173D3D20C0031B002C305F /* LaunchAtLoginController.m */; };
|
60173D3E20C0031B002C305F /* LaunchAtLoginController.m in Sources */ = {isa = PBXBuildFile; fileRef = 60173D3D20C0031B002C305F /* LaunchAtLoginController.m */; };
|
||||||
6027D1B92080E52A004FFDC7 /* BrightnessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */; };
|
6027D1B92080E52A004FFDC7 /* BrightnessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */; };
|
||||||
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */; };
|
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */; };
|
||||||
@@ -67,6 +69,8 @@
|
|||||||
B0F3112520C9E35F0076BB88 /* SupportNSTouchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F3112420C9E35F0076BB88 /* SupportNSTouchBar.swift */; };
|
B0F3112520C9E35F0076BB88 /* SupportNSTouchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F3112420C9E35F0076BB88 /* SupportNSTouchBar.swift */; };
|
||||||
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */; };
|
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */; };
|
||||||
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */; };
|
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 */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
@@ -100,6 +104,8 @@
|
|||||||
4CC9FEDB22FDEA65001512EB /* AMR_ANSIEscapeHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMR_ANSIEscapeHelper.m; sourceTree = "<group>"; };
|
4CC9FEDB22FDEA65001512EB /* AMR_ANSIEscapeHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMR_ANSIEscapeHelper.m; sourceTree = "<group>"; };
|
||||||
4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShellScriptTouchBarItem.swift; sourceTree = "<group>"; };
|
4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShellScriptTouchBarItem.swift; sourceTree = "<group>"; };
|
||||||
4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YandexWeatherBarItem.swift; sourceTree = "<group>"; };
|
4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YandexWeatherBarItem.swift; sourceTree = "<group>"; };
|
||||||
|
5DC6CA00241F92CB005CD5E8 /* Music.nowPlaying.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Music.nowPlaying.scpt; sourceTree = "<group>"; };
|
||||||
|
5DC6CA01241F92CB005CD5E8 /* Music.next.scpt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Music.next.scpt; sourceTree = "<group>"; };
|
||||||
60173D3C20C0031B002C305F /* LaunchAtLoginController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LaunchAtLoginController.h; sourceTree = "<group>"; };
|
60173D3C20C0031B002C305F /* LaunchAtLoginController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LaunchAtLoginController.h; sourceTree = "<group>"; };
|
||||||
60173D3D20C0031B002C305F /* LaunchAtLoginController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LaunchAtLoginController.m; sourceTree = "<group>"; };
|
60173D3D20C0031B002C305F /* LaunchAtLoginController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LaunchAtLoginController.m; sourceTree = "<group>"; };
|
||||||
6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrightnessViewController.swift; sourceTree = "<group>"; };
|
6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrightnessViewController.swift; sourceTree = "<group>"; };
|
||||||
@@ -155,6 +161,8 @@
|
|||||||
B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarkModeBarItem.swift; sourceTree = "<group>"; };
|
B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarkModeBarItem.swift; sourceTree = "<group>"; };
|
||||||
B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TouchBarSupport.m; sourceTree = "<group>"; };
|
B0F87719207AC1EA00D6E430 /* TouchBarSupport.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TouchBarSupport.m; sourceTree = "<group>"; };
|
||||||
B0F8771B207AC92700D6E430 /* TouchBarSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarSupport.h; sourceTree = "<group>"; };
|
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>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -230,8 +238,10 @@
|
|||||||
36FEF871235A1CFC00A0ABCE /* AppSettings.swift */,
|
36FEF871235A1CFC00A0ABCE /* AppSettings.swift */,
|
||||||
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */,
|
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */,
|
||||||
36C2ECD8207B74B4003CDA33 /* AppleScriptTouchBarItem.swift */,
|
36C2ECD8207B74B4003CDA33 /* AppleScriptTouchBarItem.swift */,
|
||||||
|
BAF5AB5824317CAF00B04904 /* SwipeItem.swift */,
|
||||||
4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */,
|
4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */,
|
||||||
B059D621205E03F5006E6B86 /* TouchBarController.swift */,
|
B059D621205E03F5006E6B86 /* TouchBarController.swift */,
|
||||||
|
BAF5AB5624317B4300B04904 /* BasicView.swift */,
|
||||||
36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */,
|
36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */,
|
||||||
B0008E542080286C003AD4DD /* SupportHelpers.swift */,
|
B0008E542080286C003AD4DD /* SupportHelpers.swift */,
|
||||||
B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */,
|
B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */,
|
||||||
@@ -258,6 +268,8 @@
|
|||||||
B0B17426207D6AFE0004B740 /* AppleScripts */ = {
|
B0B17426207D6AFE0004B740 /* AppleScripts */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
5DC6CA01241F92CB005CD5E8 /* Music.next.scpt */,
|
||||||
|
5DC6CA00241F92CB005CD5E8 /* Music.nowPlaying.scpt */,
|
||||||
B0B1742A207D6B580004B740 /* Battery.scpt */,
|
B0B1742A207D6B580004B740 /* Battery.scpt */,
|
||||||
B0B17429207D6B580004B740 /* Finder.scpt */,
|
B0B17429207D6B580004B740 /* Finder.scpt */,
|
||||||
B0B1742C207D6B590004B740 /* iTunes.next.scpt */,
|
B0B1742C207D6B590004B740 /* iTunes.next.scpt */,
|
||||||
@@ -407,6 +419,8 @@
|
|||||||
B0B1743A207D6B590004B740 /* iTunes.nowPlaying.scpt in Resources */,
|
B0B1743A207D6B590004B740 /* iTunes.nowPlaying.scpt in Resources */,
|
||||||
B082B257205C7D8000BC04DC /* Assets.xcassets in Resources */,
|
B082B257205C7D8000BC04DC /* Assets.xcassets in Resources */,
|
||||||
B0B17437207D6B590004B740 /* Spotify.nowPlaying.scpt in Resources */,
|
B0B17437207D6B590004B740 /* Spotify.nowPlaying.scpt in Resources */,
|
||||||
|
5DC6CA02241F92CB005CD5E8 /* Music.nowPlaying.scpt in Resources */,
|
||||||
|
5DC6CA03241F92CB005CD5E8 /* Music.next.scpt in Resources */,
|
||||||
B0B17436207D6B590004B740 /* iTunes.next.scpt in Resources */,
|
B0B17436207D6B590004B740 /* iTunes.next.scpt in Resources */,
|
||||||
B082B25A205C7D8000BC04DC /* Main.storyboard in Resources */,
|
B082B25A205C7D8000BC04DC /* Main.storyboard in Resources */,
|
||||||
B0B17435207D6B590004B740 /* Spotify.next.scpt in Resources */,
|
B0B17435207D6B590004B740 /* Spotify.next.scpt in Resources */,
|
||||||
@@ -457,11 +471,13 @@
|
|||||||
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */,
|
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */,
|
||||||
B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */,
|
B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */,
|
||||||
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */,
|
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */,
|
||||||
|
BAF5AB5724317B4300B04904 /* BasicView.swift in Sources */,
|
||||||
B0846A752220C968000288A7 /* NetworkBarItem.swift in Sources */,
|
B0846A752220C968000288A7 /* NetworkBarItem.swift in Sources */,
|
||||||
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
||||||
B08126F1217BE19000A98970 /* WidgetProtocol.swift 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 */,
|
||||||
|
BAF5AB5924317CAF00B04904 /* SwipeItem.swift in Sources */,
|
||||||
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
||||||
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */,
|
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */,
|
||||||
B08126EF217BD0B900A98970 /* PomodoroBarItem.swift in Sources */,
|
B08126EF217BD0B900A98970 /* PomodoroBarItem.swift in Sources */,
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
@objc func toggleMultitouch(_ item: NSMenuItem) {
|
@objc func toggleMultitouch(_ item: NSMenuItem) {
|
||||||
item.state = item.state == .on ? .off : .on
|
item.state = item.state == .on ? .off : .on
|
||||||
AppSettings.multitouchGestures = item.state == .on
|
AppSettings.multitouchGestures = item.state == .on
|
||||||
TouchBarController.shared.scrollArea?.gesturesEnabled = item.state == .on
|
TouchBarController.shared.basicView?.legacyGesturesEnabled = item.state == .on
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func openPreset(_: Any?) {
|
@objc func openPreset(_: Any?) {
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
private var script: NSAppleScript!
|
private var script: NSAppleScript!
|
||||||
private let interval: TimeInterval
|
private let interval: TimeInterval
|
||||||
private var forceHideConstraint: NSLayoutConstraint!
|
private var forceHideConstraint: NSLayoutConstraint!
|
||||||
|
private let alternativeImages: [String: SourceProtocol]
|
||||||
|
|
||||||
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval) {
|
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval, alternativeImages: [String: SourceProtocol]) {
|
||||||
self.interval = interval
|
self.interval = interval
|
||||||
|
self.alternativeImages = alternativeImages
|
||||||
super.init(identifier: identifier, title: "⏳")
|
super.init(identifier: identifier, title: "⏳")
|
||||||
forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0)
|
forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0)
|
||||||
title = "scheduled"
|
title = "scheduled"
|
||||||
@@ -57,6 +59,16 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateIcon(iconLabel: String) {
|
||||||
|
if alternativeImages[iconLabel] != nil {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.image = self.alternativeImages[iconLabel]!.image
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("Cannot find icon with label \"\(iconLabel)\"")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func execute() -> String {
|
func execute() -> String {
|
||||||
var error: NSDictionary?
|
var error: NSDictionary?
|
||||||
let output = script.executeAndReturnError(&error)
|
let output = script.executeAndReturnError(&error)
|
||||||
@@ -64,6 +76,18 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
print(error)
|
print(error)
|
||||||
return "error"
|
return "error"
|
||||||
}
|
}
|
||||||
|
if output.descriptorType == typeAEList {
|
||||||
|
let arr = Array(1...output.numberOfItems).compactMap({ output.atIndex($0)!.stringValue ?? "" })
|
||||||
|
|
||||||
|
if arr.count <= 0 {
|
||||||
|
return ""
|
||||||
|
} else if arr.count == 1 {
|
||||||
|
return arr[0]
|
||||||
|
} else {
|
||||||
|
updateIcon(iconLabel: arr[1])
|
||||||
|
return arr[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
return output.stringValue ?? ""
|
return output.stringValue ?? ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
if application "Music" is running then
|
||||||
|
tell application "Music"
|
||||||
|
if player state is playing then
|
||||||
|
next track
|
||||||
|
end if
|
||||||
|
end tell
|
||||||
|
end if
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
if application "Music" is running then
|
||||||
|
tell application "Music"
|
||||||
|
if player state is playing then
|
||||||
|
return (get artist of current track) & " – " & (get name of current track)
|
||||||
|
else
|
||||||
|
return ""
|
||||||
|
end if
|
||||||
|
end tell
|
||||||
|
end if
|
||||||
|
return ""
|
||||||
@@ -2,6 +2,10 @@ if application "iTunes" is running then
|
|||||||
tell application "iTunes" to playpause
|
tell application "iTunes" to playpause
|
||||||
end if
|
end if
|
||||||
|
|
||||||
|
if application "Music" is running then
|
||||||
|
tell application "Music" to playpause
|
||||||
|
end if
|
||||||
|
|
||||||
if application "Spotify" is running then
|
if application "Spotify" is running then
|
||||||
tell application "Spotify" to playpause
|
tell application "Spotify" to playpause
|
||||||
end if
|
end if
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
//
|
||||||
|
// BasicView.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 3/29/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
class BasicView: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
||||||
|
var twofingers: NSPanGestureRecognizer!
|
||||||
|
var threefingers: NSPanGestureRecognizer!
|
||||||
|
var fourfingers: NSPanGestureRecognizer!
|
||||||
|
var swipeItems: [SwipeItem] = []
|
||||||
|
var prevPositions: [Int: CGFloat] = [2:0, 3:0, 4:0]
|
||||||
|
|
||||||
|
// legacy gesture positions
|
||||||
|
// by legacy I mean gestures to increse/decrease volume/brigtness which can be checked from app menu
|
||||||
|
var legacyPrevPositions: [Int: CGFloat] = [2:0, 3:0, 4:0]
|
||||||
|
var legacyGesturesEnabled = false
|
||||||
|
|
||||||
|
init(identifier: NSTouchBarItem.Identifier, items: [NSTouchBarItem], swipeItems: [SwipeItem]) {
|
||||||
|
super.init(identifier: identifier)
|
||||||
|
self.swipeItems = swipeItems
|
||||||
|
let views = items.compactMap { $0.view }
|
||||||
|
let stackView = NSStackView(views: views)
|
||||||
|
stackView.spacing = 1
|
||||||
|
stackView.orientation = .horizontal
|
||||||
|
view = stackView
|
||||||
|
|
||||||
|
twofingers = NSPanGestureRecognizer(target: self, action: #selector(twofingersHandler(_:)))
|
||||||
|
twofingers.numberOfTouchesRequired = 2
|
||||||
|
twofingers.allowedTouchTypes = .direct
|
||||||
|
view.addGestureRecognizer(twofingers)
|
||||||
|
|
||||||
|
threefingers = NSPanGestureRecognizer(target: self, action: #selector(threefingersHandler(_:)))
|
||||||
|
threefingers.numberOfTouchesRequired = 3
|
||||||
|
threefingers.allowedTouchTypes = .direct
|
||||||
|
view.addGestureRecognizer(threefingers)
|
||||||
|
|
||||||
|
fourfingers = NSPanGestureRecognizer(target: self, action: #selector(fourfingersHandler(_:)))
|
||||||
|
fourfingers.numberOfTouchesRequired = 4
|
||||||
|
fourfingers.allowedTouchTypes = .direct
|
||||||
|
view.addGestureRecognizer(fourfingers)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func gestureHandler(position: CGFloat, fingers: Int, state: NSGestureRecognizer.State) {
|
||||||
|
switch state {
|
||||||
|
case .began:
|
||||||
|
prevPositions[fingers] = position
|
||||||
|
legacyPrevPositions[fingers] = position
|
||||||
|
case .changed:
|
||||||
|
if self.legacyGesturesEnabled {
|
||||||
|
if fingers == 2 {
|
||||||
|
let prevPos = legacyPrevPositions[fingers]!
|
||||||
|
if ((position - prevPos) > 10) || ((prevPos - position) > 10) {
|
||||||
|
if position > prevPos {
|
||||||
|
HIDPostAuxKey(NX_KEYTYPE_SOUND_UP)
|
||||||
|
} else if position < prevPos {
|
||||||
|
HIDPostAuxKey(NX_KEYTYPE_SOUND_DOWN)
|
||||||
|
}
|
||||||
|
legacyPrevPositions[fingers] = position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fingers == 3 {
|
||||||
|
let prevPos = legacyPrevPositions[fingers]!
|
||||||
|
if ((position - prevPos) > 15) || ((prevPos - position) > 15) {
|
||||||
|
if position > prevPos {
|
||||||
|
GenericKeyPress(keyCode: CGKeyCode(144)).send()
|
||||||
|
} else if position < prevPos {
|
||||||
|
GenericKeyPress(keyCode: CGKeyCode(145)).send()
|
||||||
|
}
|
||||||
|
legacyPrevPositions[fingers] = position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .ended:
|
||||||
|
print("gesture ended \(position - prevPositions[fingers]!) \(fingers)")
|
||||||
|
for item in swipeItems {
|
||||||
|
item.processEvent(offset: position - prevPositions[fingers]!, fingers: fingers)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func twofingersHandler(_ sender: NSGestureRecognizer?) {
|
||||||
|
let position = (sender?.location(in: sender?.view).x)!
|
||||||
|
self.gestureHandler(position: position, fingers: 2, state: sender!.state)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func threefingersHandler(_ sender: NSGestureRecognizer?) {
|
||||||
|
let position = (sender?.location(in: sender?.view).x)!
|
||||||
|
self.gestureHandler(position: position, fingers: 3, state: sender!.state)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func fourfingersHandler(_ sender: NSGestureRecognizer?) {
|
||||||
|
let position = (sender?.location(in: sender?.view).x)!
|
||||||
|
self.gestureHandler(position: position, fingers: 4, state: sender!.state)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -19,7 +19,7 @@
|
|||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.25</string>
|
<string>0.25</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>297</string>
|
<string>385</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>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
<key>NSHomeKitUsageDescription</key>
|
<key>NSHomeKitUsageDescription</key>
|
||||||
<string>MTMR needs access to HomeKit for work</string>
|
<string>MTMR needs access to HomeKit for work</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright © 2018 Anton Palgunov. All rights reserved.</string>
|
<string>Copyright © 2018 - 2020 Anton Palgunov. All rights reserved.</string>
|
||||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||||
<string>Weather widget need your location for correct work</string>
|
<string>Weather widget need your location for correct work</string>
|
||||||
<key>NSLocationAlwaysUsageDescription</key>
|
<key>NSLocationAlwaysUsageDescription</key>
|
||||||
|
|||||||
+19
-2
@@ -208,7 +208,7 @@ class SupportedTypesHolder {
|
|||||||
|
|
||||||
enum ItemType: Decodable {
|
enum ItemType: Decodable {
|
||||||
case staticButton(title: String)
|
case staticButton(title: String)
|
||||||
case appleScriptTitledButton(source: SourceProtocol, refreshInterval: Double)
|
case appleScriptTitledButton(source: SourceProtocol, refreshInterval: Double, alternativeImages: [String: SourceProtocol])
|
||||||
case shellScriptTitledButton(source: SourceProtocol, refreshInterval: Double)
|
case shellScriptTitledButton(source: SourceProtocol, refreshInterval: Double)
|
||||||
case timeButton(formatTemplate: String, timeZone: String?, locale: String?)
|
case timeButton(formatTemplate: String, timeZone: String?, locale: String?)
|
||||||
case battery
|
case battery
|
||||||
@@ -226,6 +226,7 @@ enum ItemType: Decodable {
|
|||||||
case pomodoro(workTime: Double, restTime: Double)
|
case pomodoro(workTime: Double, restTime: Double)
|
||||||
case network(flip: Bool)
|
case network(flip: Bool)
|
||||||
case darkMode
|
case darkMode
|
||||||
|
case swipe(direction: String, fingers: Int, minOffset: Float, sourceApple: SourceProtocol?, sourceBash: SourceProtocol?)
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case type
|
case type
|
||||||
@@ -251,6 +252,12 @@ enum ItemType: Decodable {
|
|||||||
case autoResize
|
case autoResize
|
||||||
case filter
|
case filter
|
||||||
case disableMarquee
|
case disableMarquee
|
||||||
|
case alternativeImages
|
||||||
|
case sourceApple
|
||||||
|
case sourceBash
|
||||||
|
case direction
|
||||||
|
case fingers
|
||||||
|
case minOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ItemTypeRaw: String, Decodable {
|
enum ItemTypeRaw: String, Decodable {
|
||||||
@@ -273,6 +280,7 @@ enum ItemType: Decodable {
|
|||||||
case pomodoro
|
case pomodoro
|
||||||
case network
|
case network
|
||||||
case darkMode
|
case darkMode
|
||||||
|
case swipe
|
||||||
}
|
}
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
init(from decoder: Decoder) throws {
|
||||||
@@ -282,7 +290,8 @@ enum ItemType: Decodable {
|
|||||||
case .appleScriptTitledButton:
|
case .appleScriptTitledButton:
|
||||||
let source = try container.decode(Source.self, forKey: .source)
|
let source = try container.decode(Source.self, forKey: .source)
|
||||||
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
|
||||||
self = .appleScriptTitledButton(source: source, refreshInterval: interval)
|
let alternativeImages = try container.decodeIfPresent([String: Source].self, forKey: .alternativeImages) ?? [:]
|
||||||
|
self = .appleScriptTitledButton(source: source, refreshInterval: interval, alternativeImages: alternativeImages)
|
||||||
|
|
||||||
case .shellScriptTitledButton:
|
case .shellScriptTitledButton:
|
||||||
let source = try container.decode(Source.self, forKey: .source)
|
let source = try container.decode(Source.self, forKey: .source)
|
||||||
@@ -361,6 +370,14 @@ enum ItemType: Decodable {
|
|||||||
|
|
||||||
case .darkMode:
|
case .darkMode:
|
||||||
self = .darkMode
|
self = .darkMode
|
||||||
|
|
||||||
|
case .swipe:
|
||||||
|
let sourceApple = try container.decodeIfPresent(Source.self, forKey: .sourceApple)
|
||||||
|
let sourceBash = try container.decodeIfPresent(Source.self, forKey: .sourceBash)
|
||||||
|
let direction = try container.decode(String.self, forKey: .direction)
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class ScrollViewItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
class ScrollViewItem: NSCustomTouchBarItem/*, NSGestureRecognizerDelegate*/ {
|
||||||
var twofingersPrev: CGFloat = 0.0
|
|
||||||
var threefingersPrev: CGFloat = 0.0
|
|
||||||
var twofingers: NSPanGestureRecognizer!
|
|
||||||
var threefingers: NSPanGestureRecognizer!
|
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, items: [NSTouchBarItem]) {
|
init(identifier: NSTouchBarItem.Identifier, items: [NSTouchBarItem]) {
|
||||||
super.init(identifier: identifier)
|
super.init(identifier: identifier)
|
||||||
@@ -15,70 +11,10 @@ class ScrollViewItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
|||||||
let scrollView = NSScrollView(frame: CGRect(origin: .zero, size: stackView.fittingSize))
|
let scrollView = NSScrollView(frame: CGRect(origin: .zero, size: stackView.fittingSize))
|
||||||
scrollView.documentView = stackView
|
scrollView.documentView = stackView
|
||||||
view = scrollView
|
view = scrollView
|
||||||
|
|
||||||
twofingers = NSPanGestureRecognizer(target: self, action: #selector(twofingersHandler(_:)))
|
|
||||||
twofingers.allowedTouchTypes = .direct
|
|
||||||
twofingers.numberOfTouchesRequired = 2
|
|
||||||
view.addGestureRecognizer(twofingers)
|
|
||||||
|
|
||||||
threefingers = NSPanGestureRecognizer(target: self, action: #selector(threefingersHandler(_:)))
|
|
||||||
threefingers.allowedTouchTypes = .direct
|
|
||||||
threefingers.numberOfTouchesRequired = 3
|
|
||||||
view.addGestureRecognizer(threefingers)
|
|
||||||
}
|
|
||||||
|
|
||||||
var gesturesEnabled = true {
|
|
||||||
didSet {
|
|
||||||
twofingers.isEnabled = gesturesEnabled
|
|
||||||
threefingers.isEnabled = gesturesEnabled
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder _: NSCoder) {
|
required init?(coder _: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func twofingersHandler(_ sender: NSGestureRecognizer?) { // Volume
|
|
||||||
let position = (sender?.location(in: sender?.view).x)!
|
|
||||||
|
|
||||||
switch sender!.state {
|
|
||||||
case .began:
|
|
||||||
twofingersPrev = position
|
|
||||||
case .changed:
|
|
||||||
if ((position - twofingersPrev) > 10) || ((twofingersPrev - position) > 10) {
|
|
||||||
if position > twofingersPrev {
|
|
||||||
HIDPostAuxKey(NX_KEYTYPE_SOUND_UP)
|
|
||||||
} else if position < twofingersPrev {
|
|
||||||
HIDPostAuxKey(NX_KEYTYPE_SOUND_DOWN)
|
|
||||||
}
|
|
||||||
twofingersPrev = position
|
|
||||||
}
|
|
||||||
case .ended:
|
|
||||||
twofingersPrev = 0.0
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func threefingersHandler(_ sender: NSGestureRecognizer?) { // Brightness
|
|
||||||
let position = (sender?.location(in: sender?.view).x)!
|
|
||||||
|
|
||||||
switch sender!.state {
|
|
||||||
case .began:
|
|
||||||
threefingersPrev = position
|
|
||||||
case .changed:
|
|
||||||
if ((position - threefingersPrev) > 15) || ((threefingersPrev - position) > 15) {
|
|
||||||
if position > threefingersPrev {
|
|
||||||
GenericKeyPress(keyCode: CGKeyCode(144)).send()
|
|
||||||
} else if position < threefingersPrev {
|
|
||||||
GenericKeyPress(keyCode: CGKeyCode(145)).send()
|
|
||||||
}
|
|
||||||
threefingersPrev = position
|
|
||||||
}
|
|
||||||
case .ended:
|
|
||||||
threefingersPrev = 0.0
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,11 +62,19 @@ class ShellScriptTouchBarItem: CustomButtonTouchBarItem {
|
|||||||
|
|
||||||
let pipe = Pipe()
|
let pipe = Pipe()
|
||||||
task.standardOutput = pipe
|
task.standardOutput = pipe
|
||||||
|
|
||||||
|
// kill process if it is over update interval
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + interval) { [weak task] in
|
||||||
|
task?.terminate()
|
||||||
|
}
|
||||||
|
|
||||||
task.launch()
|
task.launch()
|
||||||
|
|
||||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||||
var output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String? ?? ""
|
var output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String? ?? ""
|
||||||
|
|
||||||
|
//always wait until task end or you can catch "task still running" error while accessing task.terminationStatus variable
|
||||||
|
task.waitUntilExit()
|
||||||
if (output == "" && task.terminationStatus != 0) {
|
if (output == "" && task.terminationStatus != 0) {
|
||||||
output = "error"
|
output = "error"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// SwipeItem.swift
|
||||||
|
// MTMR
|
||||||
|
//
|
||||||
|
// Created by Fedor Zaitsev on 3/29/20.
|
||||||
|
// Copyright © 2020 Anton Palgunov. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class SwipeItem: NSCustomTouchBarItem {
|
||||||
|
private var scriptApple: NSAppleScript?
|
||||||
|
private var scriptBash: String?
|
||||||
|
private var direction: String
|
||||||
|
private var fingers: Int
|
||||||
|
private var minOffset: Float
|
||||||
|
init?(identifier: NSTouchBarItem.Identifier, direction: String, fingers: Int, minOffset: Float, sourceApple: SourceProtocol?, sourceBash: SourceProtocol?) {
|
||||||
|
self.direction = direction
|
||||||
|
self.fingers = fingers
|
||||||
|
self.scriptBash = sourceBash?.string
|
||||||
|
self.scriptApple = sourceApple?.appleScript
|
||||||
|
self.minOffset = minOffset
|
||||||
|
super.init(identifier: identifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func processEvent(offset: CGFloat, fingers: Int) {
|
||||||
|
if direction == "right" && Float(offset) > self.minOffset && self.fingers == fingers {
|
||||||
|
self.execute()
|
||||||
|
}
|
||||||
|
if direction == "left" && Float(offset) < -self.minOffset && self.fingers == fingers {
|
||||||
|
self.execute()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func execute() {
|
||||||
|
if scriptApple != nil {
|
||||||
|
DispatchQueue.appleScriptQueue.async {
|
||||||
|
var error: NSDictionary?
|
||||||
|
self.scriptApple?.executeAndReturnError(&error)
|
||||||
|
if let error = error {
|
||||||
|
print("SwipeItem apple script error: \(error)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if scriptBash != nil {
|
||||||
|
DispatchQueue.shellScriptQueue.async {
|
||||||
|
let task = Process()
|
||||||
|
task.launchPath = "/bin/bash"
|
||||||
|
task.arguments = ["-c", self.scriptBash!]
|
||||||
|
task.launch()
|
||||||
|
task.waitUntilExit()
|
||||||
|
|
||||||
|
|
||||||
|
if (task.terminationStatus != 0) {
|
||||||
|
print("SwipeItem bash script error. Status: \(task.terminationStatus)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,6 +57,8 @@ extension ItemType {
|
|||||||
return NetworkBarItem.identifier
|
return NetworkBarItem.identifier
|
||||||
case .darkMode:
|
case .darkMode:
|
||||||
return DarkModeBarItem.identifier
|
return DarkModeBarItem.identifier
|
||||||
|
case .swipe(direction: _, fingers: _, minOffset: _, sourceApple: _, sourceBash: _):
|
||||||
|
return "com.toxblh.mtmr.swipe."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,10 +78,10 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
var items: [NSTouchBarItem.Identifier: NSTouchBarItem] = [:]
|
var items: [NSTouchBarItem.Identifier: NSTouchBarItem] = [:]
|
||||||
var leftIdentifiers: [NSTouchBarItem.Identifier] = []
|
var leftIdentifiers: [NSTouchBarItem.Identifier] = []
|
||||||
var centerIdentifiers: [NSTouchBarItem.Identifier] = []
|
var centerIdentifiers: [NSTouchBarItem.Identifier] = []
|
||||||
var centerItems: [NSTouchBarItem] = []
|
|
||||||
var rightIdentifiers: [NSTouchBarItem.Identifier] = []
|
var rightIdentifiers: [NSTouchBarItem.Identifier] = []
|
||||||
var scrollArea: ScrollViewItem?
|
var basicViewIdentifier = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollView.".appending(UUID().uuidString))
|
||||||
var centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
|
var basicView: BasicView?
|
||||||
|
var swipeItems: [SwipeItem] = []
|
||||||
|
|
||||||
var blacklistAppIdentifiers: [String] = []
|
var blacklistAppIdentifiers: [String] = []
|
||||||
var frontmostApplicationIdentifier: String? {
|
var frontmostApplicationIdentifier: String? {
|
||||||
@@ -114,24 +116,29 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
jsonItems = newJsonItems
|
jsonItems = newJsonItems
|
||||||
itemDefinitions = [:]
|
itemDefinitions = [:]
|
||||||
items = [:]
|
items = [:]
|
||||||
leftIdentifiers = []
|
|
||||||
centerItems = []
|
|
||||||
rightIdentifiers = []
|
|
||||||
|
|
||||||
loadItemDefinitions(jsonItems: jsonItems)
|
loadItemDefinitions(jsonItems: jsonItems)
|
||||||
createItems()
|
createItems()
|
||||||
|
|
||||||
centerItems = centerIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
|
let centerItems = centerIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
|
||||||
items[identifier]
|
items[identifier]
|
||||||
})
|
})
|
||||||
|
|
||||||
centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
|
let centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
|
||||||
scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems)
|
let scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems)
|
||||||
scrollArea?.gesturesEnabled = AppSettings.multitouchGestures
|
|
||||||
|
|
||||||
touchBar.delegate = self
|
touchBar.delegate = self
|
||||||
touchBar.defaultItemIdentifiers = []
|
touchBar.defaultItemIdentifiers = [basicViewIdentifier]
|
||||||
touchBar.defaultItemIdentifiers = leftIdentifiers + [centerScrollArea] + rightIdentifiers
|
|
||||||
|
let leftItems = leftIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
|
||||||
|
items[identifier]
|
||||||
|
})
|
||||||
|
let rightItems = rightIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
|
||||||
|
items[identifier]
|
||||||
|
})
|
||||||
|
|
||||||
|
basicView = BasicView(identifier: basicViewIdentifier, items:leftItems + [scrollArea] + rightItems, swipeItems: swipeItems)
|
||||||
|
basicView?.legacyGesturesEnabled = AppSettings.multitouchGestures
|
||||||
|
|
||||||
updateActiveApp()
|
updateActiveApp()
|
||||||
}
|
}
|
||||||
@@ -187,7 +194,12 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
|
|
||||||
func createItems() {
|
func createItems() {
|
||||||
for (identifier, definition) in itemDefinitions {
|
for (identifier, definition) in itemDefinitions {
|
||||||
items[identifier] = createItem(forIdentifier: identifier, definition: definition)
|
let item = createItem(forIdentifier: identifier, definition: definition)
|
||||||
|
if item is SwipeItem {
|
||||||
|
swipeItems.append(item as! SwipeItem)
|
||||||
|
} else {
|
||||||
|
items[identifier] = item
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,25 +235,20 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func touchBar(_: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
|
func touchBar(_: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
|
||||||
if identifier == centerScrollArea {
|
if identifier == basicViewIdentifier {
|
||||||
return scrollArea
|
return basicView
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let item = self.items[identifier],
|
|
||||||
let definition = self.itemDefinitions[identifier],
|
|
||||||
definition.align != .center else {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
func createItem(forIdentifier identifier: NSTouchBarItem.Identifier, definition item: BarItemDefinition) -> NSTouchBarItem? {
|
func createItem(forIdentifier identifier: NSTouchBarItem.Identifier, definition item: BarItemDefinition) -> NSTouchBarItem? {
|
||||||
var barItem: NSTouchBarItem!
|
var barItem: NSTouchBarItem!
|
||||||
switch item.type {
|
switch item.type {
|
||||||
case let .staticButton(title: title):
|
case let .staticButton(title: title):
|
||||||
barItem = CustomButtonTouchBarItem(identifier: identifier, title: title)
|
barItem = CustomButtonTouchBarItem(identifier: identifier, title: title)
|
||||||
case let .appleScriptTitledButton(source: source, refreshInterval: interval):
|
case let .appleScriptTitledButton(source: source, refreshInterval: interval, alternativeImages: alternativeImages):
|
||||||
barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval)
|
barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval, alternativeImages: alternativeImages)
|
||||||
case let .shellScriptTitledButton(source: source, refreshInterval: interval):
|
case let .shellScriptTitledButton(source: source, refreshInterval: interval):
|
||||||
barItem = ShellScriptTouchBarItem(identifier: identifier, source: source, interval: interval)
|
barItem = ShellScriptTouchBarItem(identifier: identifier, source: source, interval: interval)
|
||||||
case let .timeButton(formatTemplate: template, timeZone: timeZone, locale: locale):
|
case let .timeButton(formatTemplate: template, timeZone: timeZone, locale: locale):
|
||||||
@@ -292,6 +299,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
barItem = NetworkBarItem(identifier: identifier, flip: flip)
|
barItem = NetworkBarItem(identifier: identifier, flip: flip)
|
||||||
case .darkMode:
|
case .darkMode:
|
||||||
barItem = DarkModeBarItem(identifier: identifier)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let action = self.action(forItem: item), let item = barItem as? CustomButtonTouchBarItem {
|
if let action = self.action(forItem: item), let item = barItem as? CustomButtonTouchBarItem {
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
|||||||
private var postfix: String
|
private var postfix: String
|
||||||
private var from: String
|
private var from: String
|
||||||
private var to: String
|
private var to: String
|
||||||
|
private var decimal: Int
|
||||||
|
private var decimalValue: Float32!
|
||||||
|
private var decimalString: String!
|
||||||
private var oldValue: Float32!
|
private var oldValue: Float32!
|
||||||
private var full: Bool = false
|
private var full: Bool = false
|
||||||
|
|
||||||
@@ -32,11 +35,29 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
|||||||
"IDR": "Rp",
|
"IDR": "Rp",
|
||||||
"MXN": "$",
|
"MXN": "$",
|
||||||
"SGD": "$",
|
"SGD": "$",
|
||||||
"CHF": "Fr.",
|
|
||||||
"BTC": "฿",
|
"BTC": "฿",
|
||||||
"LTC": "Ł",
|
"LTC": "Ł",
|
||||||
"ETH": "Ξ",
|
"ETH": "Ξ",
|
||||||
]
|
]
|
||||||
|
private let decimals = [
|
||||||
|
"USD": 4,
|
||||||
|
"EUR": 4,
|
||||||
|
"RUB": 2,
|
||||||
|
"JPY": 2,
|
||||||
|
"GBP": 4,
|
||||||
|
"CAD": 4,
|
||||||
|
"KRW": 4,
|
||||||
|
"CNY": 4,
|
||||||
|
"AUD": 4,
|
||||||
|
"BRL": 4,
|
||||||
|
"IDR": 1,
|
||||||
|
"MXN": 2,
|
||||||
|
"SGD": 4,
|
||||||
|
"CHF": 4,
|
||||||
|
"BTC": 2,
|
||||||
|
"LTC": 2,
|
||||||
|
"ETH": 2,
|
||||||
|
]
|
||||||
|
|
||||||
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String, full: Bool) {
|
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String, full: Bool) {
|
||||||
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
||||||
@@ -57,6 +78,14 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
|||||||
postfix = to
|
postfix = to
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if let decimal = decimals[to] {
|
||||||
|
self.decimal = decimal
|
||||||
|
} else {
|
||||||
|
decimal = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
super.init(identifier: identifier, title: "⏳")
|
super.init(identifier: identifier, title: "⏳")
|
||||||
|
|
||||||
activity.repeats = true
|
activity.repeats = true
|
||||||
@@ -114,10 +143,12 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oldValue = value
|
oldValue = value
|
||||||
|
decimalValue = (value * pow(10,Float(decimal))).rounded() / pow(10,Float(decimal))
|
||||||
|
decimalString = String(decimalValue)
|
||||||
|
|
||||||
var title = ""
|
var title = ""
|
||||||
if full {
|
if full {
|
||||||
title = String(format: "%@‣%.2f%@", prefix, value, postfix)
|
title = String(format: "%@%@‣%@", prefix, postfix, decimalString)
|
||||||
} else {
|
} else {
|
||||||
title = String(format: "%@%.2f", prefix, value)
|
title = String(format: "%@%.2f", prefix, value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import ScriptingBridge
|
|||||||
|
|
||||||
class MusicBarItem: CustomButtonTouchBarItem {
|
class MusicBarItem: CustomButtonTouchBarItem {
|
||||||
private enum Player: String {
|
private enum Player: String {
|
||||||
|
case Music = "com.apple.Music"
|
||||||
case iTunes = "com.apple.iTunes"
|
case iTunes = "com.apple.iTunes"
|
||||||
case Spotify = "com.spotify.client"
|
case Spotify = "com.spotify.client"
|
||||||
case VOX = "com.coppertino.Vox"
|
case VOX = "com.coppertino.Vox"
|
||||||
@@ -19,6 +20,7 @@ class MusicBarItem: CustomButtonTouchBarItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private let playerBundleIdentifiers = [
|
private let playerBundleIdentifiers = [
|
||||||
|
Player.Music,
|
||||||
Player.iTunes,
|
Player.iTunes,
|
||||||
Player.Spotify,
|
Player.Spotify,
|
||||||
Player.VOX,
|
Player.VOX,
|
||||||
@@ -71,6 +73,10 @@ class MusicBarItem: CustomButtonTouchBarItem {
|
|||||||
let mp = (musicPlayer as iTunesApplication)
|
let mp = (musicPlayer as iTunesApplication)
|
||||||
mp.playpause!()
|
mp.playpause!()
|
||||||
return
|
return
|
||||||
|
} else if ident == .Music {
|
||||||
|
let mp = (musicPlayer as MusicApplication)
|
||||||
|
mp.playpause!()
|
||||||
|
return
|
||||||
} else if ident == .VOX {
|
} else if ident == .VOX {
|
||||||
let mp = (musicPlayer as VoxApplication)
|
let mp = (musicPlayer as VoxApplication)
|
||||||
mp.playpause!()
|
mp.playpause!()
|
||||||
@@ -134,6 +140,11 @@ class MusicBarItem: CustomButtonTouchBarItem {
|
|||||||
mp.nextTrack!()
|
mp.nextTrack!()
|
||||||
updatePlayer()
|
updatePlayer()
|
||||||
return
|
return
|
||||||
|
} else if ident == .Music {
|
||||||
|
let mp = (musicPlayer as MusicApplication)
|
||||||
|
mp.nextTrack!()
|
||||||
|
updatePlayer()
|
||||||
|
return
|
||||||
} else if ident == .VOX {
|
} else if ident == .VOX {
|
||||||
let mp = (musicPlayer as VoxApplication)
|
let mp = (musicPlayer as VoxApplication)
|
||||||
mp.next!()
|
mp.next!()
|
||||||
@@ -188,6 +199,8 @@ class MusicBarItem: CustomButtonTouchBarItem {
|
|||||||
tempTitle = (musicPlayer as SpotifyApplication).title
|
tempTitle = (musicPlayer as SpotifyApplication).title
|
||||||
} else if ident == .iTunes {
|
} else if ident == .iTunes {
|
||||||
tempTitle = (musicPlayer as iTunesApplication).title
|
tempTitle = (musicPlayer as iTunesApplication).title
|
||||||
|
} else if ident == .Music {
|
||||||
|
tempTitle = (musicPlayer as MusicApplication).title
|
||||||
} else if ident == .VOX {
|
} else if ident == .VOX {
|
||||||
tempTitle = (musicPlayer as VoxApplication).title
|
tempTitle = (musicPlayer as VoxApplication).title
|
||||||
} else if ident == .Safari {
|
} else if ident == .Safari {
|
||||||
@@ -321,6 +334,29 @@ extension iTunesApplication {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc protocol MusicApplication {
|
||||||
|
@objc optional var currentTrack: MusicTrack { get }
|
||||||
|
@objc optional func playpause()
|
||||||
|
@objc optional func nextTrack()
|
||||||
|
@objc optional func previousTrack()
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SBApplication: MusicApplication {}
|
||||||
|
|
||||||
|
@objc protocol MusicTrack {
|
||||||
|
@objc optional var artist: String { get }
|
||||||
|
@objc optional var name: String { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SBObject: MusicTrack {}
|
||||||
|
|
||||||
|
extension MusicApplication {
|
||||||
|
var title: String {
|
||||||
|
guard let t = currentTrack else { return "" }
|
||||||
|
return (t.artist ?? "") + " — " + (t.name ?? "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@objc protocol VoxApplication {
|
@objc protocol VoxApplication {
|
||||||
@objc optional func playpause()
|
@objc optional func playpause()
|
||||||
@objc optional func next()
|
@objc optional func next()
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ import CoreLocation
|
|||||||
class YandexWeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate {
|
class YandexWeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate {
|
||||||
private let activity: NSBackgroundActivityScheduler
|
private let activity: NSBackgroundActivityScheduler
|
||||||
private let unitsStr = "°C"
|
private let unitsStr = "°C"
|
||||||
private let iconsSource = ["Ясно": "☀️", "Малооблачно": "🌤", "Облачно с прояснениями": "⛅️", "Пасмурно": "☁️", "Небольшой дождь": "🌦", "Дождь": "🌧", "Ливень": "⛈", "Гроза": "🌩", "Дождь со снегом": "☔️", "Небольшой снег": "❄️", "Снег": "🌨", "Туман": "🌫"]
|
private let iconsSource = [
|
||||||
|
"Ясно": "☀️", "Малооблачно": "🌤", "Облачно с прояснениями": "⛅️", "Пасмурно": "☁️", "Небольшой дождь": "🌦", "Дождь": "🌧", "Ливень": "⛈", "Гроза": "🌩", "Дождь со снегом": "☔️", "Небольшой снег": "❄️", "Снег": "🌨", "Туман": "🌫",
|
||||||
|
"Clear": "☀️", "Mostly clear": "🌤", "Partly cloudy": "⛅️", "Overcast": "☁️", "Light rain": "🌦", "Rain": "🌧", "Heavy rain": "⛈", "Storm": "🌩", "Sleet": "☔️", "Light snow": "❄️", "Snow": "🌨", "Fog": "🌫"
|
||||||
|
]
|
||||||
private var location: CLLocation!
|
private var location: CLLocation!
|
||||||
private var prevLocation: CLLocation!
|
private var prevLocation: CLLocation!
|
||||||
private var manager: CLLocationManager!
|
private var manager: CLLocationManager!
|
||||||
@@ -88,9 +91,9 @@ class YandexWeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate
|
|||||||
|
|
||||||
func getWeatherUrl() -> String {
|
func getWeatherUrl() -> String {
|
||||||
if location != nil {
|
if location != nil {
|
||||||
return "https://yandex.ru/pogoda/?lat=\(location.coordinate.latitude)&lon=\(location.coordinate.longitude)"
|
return "https://yandex.ru/pogoda/?lat=\(location.coordinate.latitude)&lon=\(location.coordinate.longitude)?lang=ru"
|
||||||
} else {
|
} else {
|
||||||
return "https://yandex.ru/pogoda/" // Yandex will try to determine your location by default
|
return "https://yandex.ru/pogoda/?lang=ru" // Yandex will try to determine your location by default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,26 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Music
|
||||||
|
{
|
||||||
|
"type": "appleScriptTitledButton",
|
||||||
|
"source": {
|
||||||
|
"inline": "if application \"Music\" is running then\rtell application \"Music\"\rif player state is playing then\rreturn (get artist of current track) & \" – \" & (get name of current track)\relse\rreturn \"\"\rend if\rend tell\rend if\rreturn \"\"\r"
|
||||||
|
},
|
||||||
|
"action": "appleScript",
|
||||||
|
"actionAppleScript": {
|
||||||
|
"inline": "if application \"Music\" is running then\rtell application \"Music\"\rif player state is playing then\rnext track\rend if\rend tell\rend if\r"
|
||||||
|
},
|
||||||
|
"longAction": "appleScript",
|
||||||
|
"longActionAppleScript": {
|
||||||
|
"inline": "if application \"Music\" is running then\rtell application \"Music\"\rif player state is playing then\rprev track\rend if\rend tell\rend if\r"
|
||||||
|
},
|
||||||
|
"refreshInterval": 2,
|
||||||
|
"image": {
|
||||||
|
"base64": "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAADAUExURUdwTOVVZCzB+3qc0gkDBgEBAgcKEwAAAA4EBP5aVU2V95iJv7V3rtBOvH5W6jaOyclScKZGX3wuQCMuUqZN7+NQYXtDvFd9/sxYni2z6UhBhyhvnIp7sf38/PXz9ePm69/k6fHv8/j29+3q7/v6+ufq7uvu8fTw8+1egOFki/dbboVj/HNy/T+j/dNtnEul81vC8Vmf3OeRqOBVofK4xZfF7sDb7PLe6LxU1KKK79PL6vrW3fh4g5Zi4bi16daa0A3Qc90AAAAddFJOUwD3/v0uOlYNG/z+/v7998OYYztt/Le2/eDqi5jEo2rNTwAABMtJREFUWMPdl1tjqjoQhauC0Hqvta26JVxUQBQFRPBS/f//as8kISBqd/twXs5KjBDyrZkEFfP09D+WoigqFxz+mlbVXncweEZVBoNuD1x+E1vtMVZoURn01J/mob52KRNuj4k5mZjJcRueFotFpfv6EwdVRfy0tSdXSranheN0/zkRSB7x42Q6udExdBy3972Fog4o/kBg4X6bhPJaeX7eTqeT6b0MJtPpdOu6n49XQgX+dOQ8vpWEvYn/2AHiL052PpoROcsOtND17ztQ3rwTuCQz9O/moKiMf6BkG/puKBzurKQ64PmbU2bDzUxk3Uql4lZcl3Vpvt9VbxLoLZwjY7E1WcNZoB0XpbELie/3Sg6KVHG2jGPs1LTCE2UXFfgIgtBgyq8d/E/pehJq1zmZGc7kAPsMX4Ec932T25uX5vUklFcHJlDU1OT4wllkvOtn9lrSbF7dCUggNEtaMOXhQZq4WkpBcksJQBCOnyjvM4P8KqQgFW9BFJka2NMKB1gw+VMxvN9smnwI1EuzpxS+g9FWYySjsTpOtnq+H162iW01m/wyXLUPzT/5HKQoSjQmU8vE6TAElvWggbhuNRpScQa002bVtJmBCz9qNusWBkJmoyHmoHajC4yybVujhR26mJVha7lDo2FrhnA4N0aq+BpE24zjgsMoEsfU0AADaKCwemiIRZA+o6N9oygyMi/EAWk0DMNgFvCmN/5IwqCV3PCGzzIwbINrzgwykVq2iorUalm2UTZotXKWqVYz5uBjzDUoxrxWyzKQWy061LZsNIJ3PAMDIcbVauwdGmxrNblgYNnCgStN54ylBSsYoAxerwwgJsCWTS0sepym0Mdp1gYBw5lmwgDXIDEoaeHLYE36BafzuQWFQ9RASM/XQPpMD5YQ2gA/AwPArQJyZWDsgo64C+/pBRkDG4s31hdmwFNAGz1mBjPukBs8qdSgLDBA1LJm1lw/14IgWAdAQ5nhax4HY/FR7qfpHQMPUChzS0c6eFmv17MZo7HZBP3MQJHTNCnzxPMgOFUteAGtMwMmfRPIijBgc+AmNK6+9zw+9Iw05YsG8aaT/7Kro7eUcoSWw3n/1W57SxgGOZCYxl+VDDabcf6LpNTf3g6IQ4XY7TbiyyUBmhqsViswWK02cE7ITIdmtxnWlcJz6f1tPyMsha+2R4UGyJPdywotwGSHOKHdm+IMYA40BRhtkXOb42DAh8crppjw8CyB4nMBlvFtD/0WSfZebkDHguLNar2JdyTXptqRrx6OmMKZkISQc4Yv9yyDXHiiEx1qXL1OAFdhBJPAAQeRQDEiRZEm+kwnu2p1XHo64yQ8j47bL1kCZ87pDKWxuW4mQJ9O9ba31xE5Y/rnA4VoTCJQwvnyBNgk+pkDi8sSJjlKRPxhX7r3Lytz0LPMi1H1Qv7VuzwuAzh4h1ukKFi/YV9+9E8THZbne2Ezxd/xsNGQ6u+wgoeH4SH9Tl367t+2Ko/acA8Oj/DhWP7X/30Zkvj4WMYlj10MOISXf7DlkPvvH6g43u0oCzDS1U5f/sHWC3d7cn3UAQf4HeHfwxXQY4yu/HTDKNXro3Gngw4vw2FnPKrXJfUXu0fqIdeFZOnXm08FTRSxcf391pW7oNGT8vRf6i9jqljwYzAm6AAAAABJRU5ErkJggg=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// iTunes
|
// iTunes
|
||||||
{
|
{
|
||||||
"type": "appleScriptTitledButton",
|
"type": "appleScriptTitledButton",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class AppleScriptDefinitionTests: XCTestCase {
|
|||||||
[ { "type": "appleScriptTitledButton", "source": { "inline": "tell everything fine" } } ]
|
[ { "type": "appleScriptTitledButton", "source": { "inline": "tell everything fine" } } ]
|
||||||
""".data(using: .utf8)!
|
""".data(using: .utf8)!
|
||||||
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonNoActionFixture)
|
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonNoActionFixture)
|
||||||
guard case .appleScriptTitledButton(let source, _)? = result?.first?.type else {
|
guard case .appleScriptTitledButton(let source, _, _)? = result?.first?.type else {
|
||||||
XCTFail()
|
XCTFail()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ class AppleScriptDefinitionTests: XCTestCase {
|
|||||||
[ { "type": "appleScriptTitledButton", "source": { "filePath": "/ololo/pew" } } ]
|
[ { "type": "appleScriptTitledButton", "source": { "filePath": "/ololo/pew" } } ]
|
||||||
""".data(using: .utf8)!
|
""".data(using: .utf8)!
|
||||||
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonNoActionFixture)
|
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonNoActionFixture)
|
||||||
guard case .appleScriptTitledButton(let source, _)? = result?.first?.type else {
|
guard case .appleScriptTitledButton(let source, _, _)? = result?.first?.type else {
|
||||||
XCTFail()
|
XCTFail()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ class AppleScriptDefinitionTests: XCTestCase {
|
|||||||
[ { "type": "appleScriptTitledButton", "source": { "filePath": "~/pew" } } ]
|
[ { "type": "appleScriptTitledButton", "source": { "filePath": "~/pew" } } ]
|
||||||
""".data(using: .utf8)!
|
""".data(using: .utf8)!
|
||||||
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonNoActionFixture)
|
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonNoActionFixture)
|
||||||
guard case .appleScriptTitledButton(let source, _)? = result?.first?.type else {
|
guard case .appleScriptTitledButton(let source, _, _)? = result?.first?.type else {
|
||||||
XCTFail()
|
XCTFail()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ class AppleScriptDefinitionTests: XCTestCase {
|
|||||||
[ { "type": "appleScriptTitledButton", "source": { "inline": "tell everything fine" }, "refreshInterval": 305} ]
|
[ { "type": "appleScriptTitledButton", "source": { "inline": "tell everything fine" }, "refreshInterval": 305} ]
|
||||||
""".data(using: .utf8)!
|
""".data(using: .utf8)!
|
||||||
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonNoActionFixture)
|
let result = try? JSONDecoder().decode([BarItemDefinition].self, from: buttonNoActionFixture)
|
||||||
guard case .appleScriptTitledButton(_, 305)? = result?.first?.type else {
|
guard case .appleScriptTitledButton(_, 305, _)? = result?.first?.type else {
|
||||||
XCTFail()
|
XCTFail()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,11 +102,31 @@ The pre-installed configuration contains less or more than you'll probably want,
|
|||||||
- appleScriptTitledButton
|
- appleScriptTitledButton
|
||||||
- shellScriptTitledButton
|
- shellScriptTitledButton
|
||||||
|
|
||||||
## Gestures on central part:
|
## Gestures
|
||||||
|
|
||||||
|
By default you can enable basic gestures from application menu (status bar -> MTMR icon -> Volume/Brightness gestures):
|
||||||
- two finger slide: change you Volume
|
- two finger slide: change you Volume
|
||||||
- three finger slide: change you Brightness
|
- three finger slide: change you Brightness
|
||||||
|
|
||||||
|
### Custom gestures
|
||||||
|
|
||||||
|
You can add custom actions for two/three/four finger swipes. To do it, you need to use `swipe` type:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"type": "swipe",
|
||||||
|
"fingers": 2, // number of fingers required (2,3 or 4)
|
||||||
|
"direction": "right", // direction of swipe (right/left)
|
||||||
|
"minOffset" 10, // optional: minimal required offset for gesture to emit event
|
||||||
|
"sourceApple": { // optional: apple script to run
|
||||||
|
"inline": "beep"
|
||||||
|
},
|
||||||
|
"sourceBash": { // optional: bash script to run
|
||||||
|
"inline": "touch /Users/lobster/test"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You may create as many `swipe` objects in the preset as you want.
|
||||||
|
|
||||||
## Built-in slider types:
|
## Built-in slider types:
|
||||||
|
|
||||||
- brightness
|
- brightness
|
||||||
@@ -133,8 +153,35 @@ The pre-installed configuration contains less or more than you'll probably want,
|
|||||||
"inline": "tell application \"Finder\"\rif not (exists window 1) then\rmake new Finder window\rset target of front window to path to home folder as string\rend if\ractivate\rend tell",
|
"inline": "tell application \"Finder\"\rif not (exists window 1) then\rmake new Finder window\rset target of front window to path to home folder as string\rend if\ractivate\rend tell",
|
||||||
// or
|
// or
|
||||||
"base64": "StringInbase64"
|
"base64": "StringInbase64"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Note: appleScriptTitledButton can change its icon. To do it, you need to do the following things:
|
||||||
|
1. Declarate dictionary of icons in `alternativeImages` field
|
||||||
|
2. Make you script return array of two values - `{"TITLE", "IMAGE_LABEL"}`
|
||||||
|
3. Make sure that your `IMAGE_LABEL` is declared in `alternativeImages` field
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"type": "appleScriptTitledButton",
|
||||||
|
"source": {
|
||||||
|
"inline": "if (random number from 1 to 2) = 1 then\n\tset val to {\"title\", \"play\"}\nelse\n\tset val to {\"title\", \"pause\"}\nend if\nreturn val"
|
||||||
|
},
|
||||||
|
"refreshInterval": 1,
|
||||||
|
"image": {
|
||||||
|
"base64": "iVBORw0KGgoAAAANSUhEUgA..."
|
||||||
|
},
|
||||||
|
"alternativeImages": {
|
||||||
|
"play": {
|
||||||
|
"base64": "iVBORw0KGgoAAAANSUhEUgAAAAAA..."
|
||||||
|
},
|
||||||
|
"pause": {
|
||||||
|
"base64": "iVBORw0KGgoAAAANSUhEUgAAAIAA..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `shellScriptTitledButton`
|
#### `shellScriptTitledButton`
|
||||||
@@ -375,6 +422,31 @@ If you want to longPress for some operations, it is similar to the configuration
|
|||||||
"bordered": "false" // "true" or "false"
|
"bordered": "false" // "true" or "false"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `background` allow to specify you button background color
|
||||||
|
|
||||||
|
```js
|
||||||
|
"background": "#FF0000",
|
||||||
|
```
|
||||||
|
by using background with color "#000000" and bordered == false you can create button without gray background but with background when the button is pressed
|
||||||
|
|
||||||
|
- `title` specify button title
|
||||||
|
|
||||||
|
```js
|
||||||
|
"title": "hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
- `image` specify button icon
|
||||||
|
|
||||||
|
```js
|
||||||
|
"image": {
|
||||||
|
//Can be either of those
|
||||||
|
"base64": "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAABGdB...."
|
||||||
|
//or
|
||||||
|
"filePath": "~/img.png"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Roadmap
|
### Roadmap
|
||||||
|
|
||||||
- [x] Create the first prototype with TouchBar in Storyboard
|
- [x] Create the first prototype with TouchBar in Storyboard
|
||||||
@@ -403,7 +475,7 @@ Settings:
|
|||||||
- [x] Startup at login
|
- [x] Startup at login
|
||||||
- [ ] Show on/off in Dock
|
- [ ] Show on/off in Dock
|
||||||
- [ ] Show on/off in StatusBar
|
- [ ] Show on/off in StatusBar
|
||||||
- [ ] On/off Haptic Feedback
|
- [ x] On/off Haptic Feedback
|
||||||
|
|
||||||
Maybe:
|
Maybe:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user