Compare commits

..
15 Commits
Author SHA1 Message Date
toxblh 4b569e0631 delete travisCI 2020-02-11 23:42:18 +00:00
toxblh 31a5a7c59c decrease time 2020-02-11 23:41:52 +00:00
toxblh 75d2bdf92c final build test 2020-02-11 23:39:25 +00:00
toxblh b4c4067fd0 upd flows 2020-02-11 23:37:20 +00:00
toxblh e1583e5255 test2 2020-02-11 23:35:54 +00:00
toxblh d4762ab81d del npm build 2020-02-11 23:32:02 +00:00
toxblh a35b77bfe3 expose test artifact 2020-02-11 23:19:42 +00:00
toxblh 281f6d711e publish for master with tag 2020-02-11 23:12:04 +00:00
toxblh d52d84c3d1 set add params 2020-02-11 23:09:14 +00:00
toxblh 3141755da7 Test code sign 2020-02-10 22:57:03 +00:00
toxblh 94c3c141e8 separete test and build 2020-02-10 21:37:12 +00:00
toxblh df3beb90f5 gem install xcpretty 2020-02-10 21:22:13 +00:00
toxblh a8ca5b3713 enable test 2020-02-10 21:17:45 +00:00
toxblh 42101f092b dis test 2020-02-10 21:12:55 +00:00
toxblh a161341bca build xcode 2020-02-10 21:11:26 +00:00
22 changed files with 113 additions and 489 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
name: Build-and-test
name: Swift
on: [push, pull_request]
on: [push]
jobs:
test:
+2 -12
View File
@@ -1,4 +1,4 @@
name: Publish unsign version
name: Swift
on:
push:
@@ -8,7 +8,7 @@ on:
- "v*"
jobs:
Build-and-release:
test:
runs-on: macOS-latest
steps:
@@ -28,14 +28,4 @@ jobs:
- 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
-16
View File
@@ -22,8 +22,6 @@
4CC9FEDC22FDEA65001512EB /* AMR_ANSIEscapeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC9FEDB22FDEA65001512EB /* AMR_ANSIEscapeHelper.m */; };
4CDC6E5022FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.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 */; };
6027D1B92080E52A004FFDC7 /* BrightnessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */; };
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */; };
@@ -69,8 +67,6 @@
B0F3112520C9E35F0076BB88 /* SupportNSTouchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F3112420C9E35F0076BB88 /* SupportNSTouchBar.swift */; };
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */; };
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 */
/* Begin PBXCopyFilesBuildPhase section */
@@ -104,8 +100,6 @@
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>"; };
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>"; };
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>"; };
@@ -161,8 +155,6 @@
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>"; };
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 */
/* Begin PBXFrameworksBuildPhase section */
@@ -238,10 +230,8 @@
36FEF871235A1CFC00A0ABCE /* AppSettings.swift */,
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */,
36C2ECD8207B74B4003CDA33 /* AppleScriptTouchBarItem.swift */,
BAF5AB5824317CAF00B04904 /* SwipeItem.swift */,
4CDC6E4F22FCA93F0069ADD4 /* ShellScriptTouchBarItem.swift */,
B059D621205E03F5006E6B86 /* TouchBarController.swift */,
BAF5AB5624317B4300B04904 /* BasicView.swift */,
36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */,
B0008E542080286C003AD4DD /* SupportHelpers.swift */,
B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */,
@@ -268,8 +258,6 @@
B0B17426207D6AFE0004B740 /* AppleScripts */ = {
isa = PBXGroup;
children = (
5DC6CA01241F92CB005CD5E8 /* Music.next.scpt */,
5DC6CA00241F92CB005CD5E8 /* Music.nowPlaying.scpt */,
B0B1742A207D6B580004B740 /* Battery.scpt */,
B0B17429207D6B580004B740 /* Finder.scpt */,
B0B1742C207D6B590004B740 /* iTunes.next.scpt */,
@@ -419,8 +407,6 @@
B0B1743A207D6B590004B740 /* iTunes.nowPlaying.scpt in Resources */,
B082B257205C7D8000BC04DC /* Assets.xcassets 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 */,
B082B25A205C7D8000BC04DC /* Main.storyboard in Resources */,
B0B17435207D6B590004B740 /* Spotify.next.scpt in Resources */,
@@ -471,13 +457,11 @@
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */,
B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */,
36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */,
BAF5AB5724317B4300B04904 /* BasicView.swift in Sources */,
B0846A752220C968000288A7 /* NetworkBarItem.swift in Sources */,
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
B08126F1217BE19000A98970 /* WidgetProtocol.swift in Sources */,
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */,
6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */,
BAF5AB5924317CAF00B04904 /* SwipeItem.swift in Sources */,
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
B0F54A7A2295AC7D00B4C509 /* DarkModeBarItem.swift in Sources */,
B08126EF217BD0B900A98970 /* PomodoroBarItem.swift in Sources */,
+1 -1
View File
@@ -92,7 +92,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
@objc func toggleMultitouch(_ item: NSMenuItem) {
item.state = item.state == .on ? .off : .on
AppSettings.multitouchGestures = item.state == .on
TouchBarController.shared.basicView?.legacyGesturesEnabled = item.state == .on
TouchBarController.shared.scrollArea?.gesturesEnabled = item.state == .on
}
@objc func openPreset(_: Any?) {
+1 -25
View File
@@ -4,11 +4,9 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
private var script: NSAppleScript!
private let interval: TimeInterval
private var forceHideConstraint: NSLayoutConstraint!
private let alternativeImages: [String: SourceProtocol]
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval, alternativeImages: [String: SourceProtocol]) {
init?(identifier: NSTouchBarItem.Identifier, source: SourceProtocol, interval: TimeInterval) {
self.interval = interval
self.alternativeImages = alternativeImages
super.init(identifier: identifier, title: "⏳")
forceHideConstraint = view.widthAnchor.constraint(equalToConstant: 0)
title = "scheduled"
@@ -59,16 +57,6 @@ 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 {
var error: NSDictionary?
let output = script.executeAndReturnError(&error)
@@ -76,18 +64,6 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
print(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 ?? ""
}
}
-7
View File
@@ -1,7 +0,0 @@
if application "Music" is running then
tell application "Music"
if player state is playing then
next track
end if
end tell
end if
-10
View File
@@ -1,10 +0,0 @@
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 ""
-4
View File
@@ -2,10 +2,6 @@ if application "iTunes" is running then
tell application "iTunes" to playpause
end if
if application "Music" is running then
tell application "Music" to playpause
end if
if application "Spotify" is running then
tell application "Spotify" to playpause
end if
-107
View File
@@ -1,107 +0,0 @@
//
// 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
View File
@@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.26</string>
<string>0.25</string>
<key>CFBundleVersion</key>
<string>401</string>
<string>297</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
+2 -19
View File
@@ -208,7 +208,7 @@ class SupportedTypesHolder {
enum ItemType: Decodable {
case staticButton(title: String)
case appleScriptTitledButton(source: SourceProtocol, refreshInterval: Double, alternativeImages: [String: SourceProtocol])
case appleScriptTitledButton(source: SourceProtocol, refreshInterval: Double)
case shellScriptTitledButton(source: SourceProtocol, refreshInterval: Double)
case timeButton(formatTemplate: String, timeZone: String?, locale: String?)
case battery
@@ -226,7 +226,6 @@ enum ItemType: Decodable {
case pomodoro(workTime: Double, restTime: Double)
case network(flip: Bool)
case darkMode
case swipe(direction: String, fingers: Int, minOffset: Float, sourceApple: SourceProtocol?, sourceBash: SourceProtocol?)
private enum CodingKeys: String, CodingKey {
case type
@@ -252,12 +251,6 @@ enum ItemType: Decodable {
case autoResize
case filter
case disableMarquee
case alternativeImages
case sourceApple
case sourceBash
case direction
case fingers
case minOffset
}
enum ItemTypeRaw: String, Decodable {
@@ -280,7 +273,6 @@ enum ItemType: Decodable {
case pomodoro
case network
case darkMode
case swipe
}
init(from decoder: Decoder) throws {
@@ -290,8 +282,7 @@ enum ItemType: Decodable {
case .appleScriptTitledButton:
let source = try container.decode(Source.self, forKey: .source)
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
let alternativeImages = try container.decodeIfPresent([String: Source].self, forKey: .alternativeImages) ?? [:]
self = .appleScriptTitledButton(source: source, refreshInterval: interval, alternativeImages: alternativeImages)
self = .appleScriptTitledButton(source: source, refreshInterval: interval)
case .shellScriptTitledButton:
let source = try container.decode(Source.self, forKey: .source)
@@ -370,14 +361,6 @@ enum ItemType: Decodable {
case .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)
}
}
}
+65 -1
View File
@@ -1,6 +1,10 @@
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]) {
super.init(identifier: identifier)
@@ -11,10 +15,70 @@ class ScrollViewItem: NSCustomTouchBarItem/*, NSGestureRecognizerDelegate*/ {
let scrollView = NSScrollView(frame: CGRect(origin: .zero, size: stackView.fittingSize))
scrollView.documentView = stackView
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) {
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
}
}
}
-8
View File
@@ -62,19 +62,11 @@ class ShellScriptTouchBarItem: CustomButtonTouchBarItem {
let pipe = 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()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
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) {
output = "error"
}
-66
View File
@@ -1,66 +0,0 @@
//
// 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)")
}
}
}
}
}
+24 -33
View File
@@ -57,8 +57,6 @@ extension ItemType {
return NetworkBarItem.identifier
case .darkMode:
return DarkModeBarItem.identifier
case .swipe(direction: _, fingers: _, minOffset: _, sourceApple: _, sourceBash: _):
return "com.toxblh.mtmr.swipe."
}
}
}
@@ -78,10 +76,10 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
var items: [NSTouchBarItem.Identifier: NSTouchBarItem] = [:]
var leftIdentifiers: [NSTouchBarItem.Identifier] = []
var centerIdentifiers: [NSTouchBarItem.Identifier] = []
var centerItems: [NSTouchBarItem] = []
var rightIdentifiers: [NSTouchBarItem.Identifier] = []
var basicViewIdentifier = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollView.".appending(UUID().uuidString))
var basicView: BasicView?
var swipeItems: [SwipeItem] = []
var scrollArea: ScrollViewItem?
var centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
var blacklistAppIdentifiers: [String] = []
var frontmostApplicationIdentifier: String? {
@@ -116,29 +114,24 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
jsonItems = newJsonItems
itemDefinitions = [:]
items = [:]
leftIdentifiers = []
centerItems = []
rightIdentifiers = []
loadItemDefinitions(jsonItems: jsonItems)
createItems()
let centerItems = centerIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
centerItems = centerIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in
items[identifier]
})
let centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
let scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems)
centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString))
scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems)
scrollArea?.gesturesEnabled = AppSettings.multitouchGestures
touchBar.delegate = self
touchBar.defaultItemIdentifiers = [basicViewIdentifier]
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
touchBar.defaultItemIdentifiers = []
touchBar.defaultItemIdentifiers = leftIdentifiers + [centerScrollArea] + rightIdentifiers
updateActiveApp()
}
@@ -194,12 +187,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
func createItems() {
for (identifier, definition) in itemDefinitions {
let item = createItem(forIdentifier: identifier, definition: definition)
if item is SwipeItem {
swipeItems.append(item as! SwipeItem)
} else {
items[identifier] = item
}
items[identifier] = createItem(forIdentifier: identifier, definition: definition)
}
}
@@ -235,11 +223,16 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
}
func touchBar(_: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
if identifier == basicViewIdentifier {
return basicView
if identifier == centerScrollArea {
return scrollArea
}
return nil
guard let item = self.items[identifier],
let definition = self.itemDefinitions[identifier],
definition.align != .center else {
return nil
}
return item
}
func createItem(forIdentifier identifier: NSTouchBarItem.Identifier, definition item: BarItemDefinition) -> NSTouchBarItem? {
@@ -247,8 +240,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
switch item.type {
case let .staticButton(title: title):
barItem = CustomButtonTouchBarItem(identifier: identifier, title: title)
case let .appleScriptTitledButton(source: source, refreshInterval: interval, alternativeImages: alternativeImages):
barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval, alternativeImages: alternativeImages)
case let .appleScriptTitledButton(source: source, refreshInterval: interval):
barItem = AppleScriptTouchBarItem(identifier: identifier, source: source, interval: interval)
case let .shellScriptTitledButton(source: source, refreshInterval: interval):
barItem = ShellScriptTouchBarItem(identifier: identifier, source: source, interval: interval)
case let .timeButton(formatTemplate: template, timeZone: timeZone, locale: locale):
@@ -299,8 +292,6 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
barItem = NetworkBarItem(identifier: identifier, flip: flip)
case .darkMode:
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 {
+2 -33
View File
@@ -15,9 +15,6 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
private var postfix: String
private var from: String
private var to: String
private var decimal: Int
private var decimalValue: Float32!
private var decimalString: String!
private var oldValue: Float32!
private var full: Bool = false
@@ -35,29 +32,11 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
"IDR": "Rp",
"MXN": "$",
"SGD": "$",
"CHF": "Fr.",
"BTC": "฿",
"LTC": "Ł",
"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) {
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
@@ -78,14 +57,6 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
postfix = to
}
if let decimal = decimals[to] {
self.decimal = decimal
} else {
decimal = 2
}
super.init(identifier: identifier, title: "⏳")
activity.repeats = true
@@ -143,12 +114,10 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
}
oldValue = value
decimalValue = (value * pow(10,Float(decimal))).rounded() / pow(10,Float(decimal))
decimalString = String(decimalValue)
var title = ""
if full {
title = String(format: "%@%@‣%@", prefix, postfix, decimalString)
title = String(format: "%@‣%.2f%@", prefix, value, postfix)
} else {
title = String(format: "%@%.2f", prefix, value)
}
-36
View File
@@ -11,7 +11,6 @@ import ScriptingBridge
class MusicBarItem: CustomButtonTouchBarItem {
private enum Player: String {
case Music = "com.apple.Music"
case iTunes = "com.apple.iTunes"
case Spotify = "com.spotify.client"
case VOX = "com.coppertino.Vox"
@@ -20,7 +19,6 @@ class MusicBarItem: CustomButtonTouchBarItem {
}
private let playerBundleIdentifiers = [
Player.Music,
Player.iTunes,
Player.Spotify,
Player.VOX,
@@ -73,10 +71,6 @@ class MusicBarItem: CustomButtonTouchBarItem {
let mp = (musicPlayer as iTunesApplication)
mp.playpause!()
return
} else if ident == .Music {
let mp = (musicPlayer as MusicApplication)
mp.playpause!()
return
} else if ident == .VOX {
let mp = (musicPlayer as VoxApplication)
mp.playpause!()
@@ -140,11 +134,6 @@ class MusicBarItem: CustomButtonTouchBarItem {
mp.nextTrack!()
updatePlayer()
return
} else if ident == .Music {
let mp = (musicPlayer as MusicApplication)
mp.nextTrack!()
updatePlayer()
return
} else if ident == .VOX {
let mp = (musicPlayer as VoxApplication)
mp.next!()
@@ -199,8 +188,6 @@ class MusicBarItem: CustomButtonTouchBarItem {
tempTitle = (musicPlayer as SpotifyApplication).title
} else if ident == .iTunes {
tempTitle = (musicPlayer as iTunesApplication).title
} else if ident == .Music {
tempTitle = (musicPlayer as MusicApplication).title
} else if ident == .VOX {
tempTitle = (musicPlayer as VoxApplication).title
} else if ident == .Safari {
@@ -334,29 +321,6 @@ 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 optional func playpause()
@objc optional func next()
-20
View File
@@ -28,26 +28,6 @@
}
},
// 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": "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"
}
},
// iTunes
{
"type": "appleScriptTitledButton",
+4 -4
View File
@@ -6,7 +6,7 @@ class AppleScriptDefinitionTests: XCTestCase {
[ { "type": "appleScriptTitledButton", "source": { "inline": "tell everything fine" } } ]
""".data(using: .utf8)!
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()
return
}
@@ -18,7 +18,7 @@ class AppleScriptDefinitionTests: XCTestCase {
[ { "type": "appleScriptTitledButton", "source": { "filePath": "/ololo/pew" } } ]
""".data(using: .utf8)!
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()
return
}
@@ -32,7 +32,7 @@ class AppleScriptDefinitionTests: XCTestCase {
[ { "type": "appleScriptTitledButton", "source": { "filePath": "~/pew" } } ]
""".data(using: .utf8)!
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()
return
}
@@ -58,7 +58,7 @@ class AppleScriptDefinitionTests: XCTestCase {
[ { "type": "appleScriptTitledButton", "source": { "inline": "tell everything fine" }, "refreshInterval": 305} ]
""".data(using: .utf8)!
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()
return
}
+3 -75
View File
@@ -102,31 +102,11 @@ The pre-installed configuration contains less or more than you'll probably want,
- appleScriptTitledButton
- shellScriptTitledButton
## Gestures
## Gestures on central part:
By default you can enable basic gestures from application menu (status bar -> MTMR icon -> Volume/Brightness gestures):
- two finger slide: change you Volume
- 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:
- brightness
@@ -153,35 +133,8 @@ You may create as many `swipe` objects in the preset as you 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",
// or
"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`
@@ -422,31 +375,6 @@ If you want to longPress for some operations, it is similar to the configuration
"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
- [x] Create the first prototype with TouchBar in Storyboard
@@ -475,7 +403,7 @@ Settings:
- [x] Startup at login
- [ ] Show on/off in Dock
- [ ] Show on/off in StatusBar
- [ x] On/off Haptic Feedback
- [ ] On/off Haptic Feedback
Maybe:
+3 -5
View File
@@ -1,18 +1,16 @@
# INSTALL xcpretty: sudo gem install xcpretty
NAME='MTMR'
rm -r Release 2>/dev/null
xcodebuild archive \
-scheme "$NAME" \
-archivePath Release/App.xcarchive | xcpretty -c
-archivePath Release/App.xcarchive
xcodebuild \
-exportArchive \
-archivePath Release/App.xcarchive \
-exportOptionsPlist export-options.plist \
-exportPath Release | xcpretty -c
-exportPath Release
cd Release
rm -r App.xcarchive
@@ -22,7 +20,7 @@ NAME_DMG="${NAME}.app"
echo $NAME_DMG
create-dmg $NAME_DMG
DATE=`LC_ALL=en_US.utf8 date +"%a, %d %b %Y %H:%M:%S %z"`
DATE=`date +"%a, %d %b %Y %H:%M:%S %z"`
BUILD=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" ${NAME}.app/Contents/Info.plist`
VERSION=`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" ${NAME}.app/Contents/Info.plist`
MINIMUM=`/usr/libexec/PlistBuddy -c "Print LSMinimumSystemVersion" ${NAME}.app/Contents/Info.plist`
+2 -3
View File
@@ -1,4 +1,3 @@
# INSTALL xcpretty: sudo gem install xcpretty
NAME='MTMR'
killall $NAME
@@ -12,13 +11,13 @@ rm -r Release 2>/dev/null
xcodebuild archive \
-scheme "$NAME" \
-archivePath Release/App.xcarchive | xcpretty
-archivePath Release/App.xcarchive
xcodebuild \
-exportArchive \
-archivePath Release/App.xcarchive \
-exportOptionsPlist export-options.plist \
-exportPath Release | xcpretty
-exportPath Release
cd Release
rm -r App.xcarchive