diff --git a/MTMR.xcodeproj/project.pbxproj b/MTMR.xcodeproj/project.pbxproj index 30c3a1f..4251a02 100644 --- a/MTMR.xcodeproj/project.pbxproj +++ b/MTMR.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B082B252205C7D8000BC04DC /* AppDelegate.swift */; }; B082B257205C7D8000BC04DC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B082B256205C7D8000BC04DC /* Assets.xcassets */; }; B082B25A205C7D8000BC04DC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B082B258205C7D8000BC04DC /* Main.storyboard */; }; + B0846A752220C968000288A7 /* NetworkBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0846A742220C968000288A7 /* NetworkBarItem.swift */; }; B09EB1E4207C082000D5C1E0 /* HapticFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */; }; B09EB1E6207C0F8E00D5C1E0 /* MultitouchSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B09EB1E5207C0F8E00D5C1E0 /* MultitouchSupport.framework */; }; B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0A7E9A9205D6AA400EEF070 /* KeyPress.swift */; }; @@ -126,6 +127,7 @@ B082B25C205C7D8000BC04DC /* MTMR.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MTMR.entitlements; sourceTree = ""; }; B082B261205C7D8000BC04DC /* MTMRTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MTMRTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; B082B267205C7D8000BC04DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B0846A742220C968000288A7 /* NetworkBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkBarItem.swift; sourceTree = ""; }; B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HapticFeedback.swift; sourceTree = ""; }; B09EB1E5207C0F8E00D5C1E0 /* MultitouchSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MultitouchSupport.framework; path = ../../../../../System/Library/PrivateFrameworks/MultitouchSupport.framework; sourceTree = ""; }; B0A7E9A9205D6AA400EEF070 /* KeyPress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPress.swift; sourceTree = ""; }; @@ -276,19 +278,20 @@ B0B88A07208CD12000A2C160 /* Widgets */ = { isa = PBXGroup; children = ( - 36C2ECD6207B6DAE003CDA33 /* TimeTouchBarItem.swift */, - 6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */, - 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */, - B04B7BB62087398C00C835D0 /* BatteryBarItem.swift */, - 607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */, - 607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */, 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */, + B04B7BB62087398C00C835D0 /* BatteryBarItem.swift */, + 6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */, + 607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */, + B081732B213739FE005D4908 /* DnDBarItem.swift */, + 60669B4220AD8FA80074E817 /* GroupBarItem.swift */, 60F7D453208CC31400ABF5D2 /* InputSourceBarItem.swift */, 60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */, - 60669B4220AD8FA80074E817 /* GroupBarItem.swift */, + B0846A742220C968000288A7 /* NetworkBarItem.swift */, B08173262135F02B005D4908 /* NightShiftBarItem.swift */, - B081732B213739FE005D4908 /* DnDBarItem.swift */, B08126EE217BD0B900A98970 /* PomodoroBarItem.swift */, + 36C2ECD6207B6DAE003CDA33 /* TimeTouchBarItem.swift */, + 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */, + 607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */, B08126F0217BE19000A98970 /* WidgetProtocol.swift */, ); path = Widgets; @@ -437,6 +440,7 @@ B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */, B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */, 36C2ECD9207B74B4003CDA33 /* AppleScriptTouchBarItem.swift in Sources */, + B0846A752220C968000288A7 /* NetworkBarItem.swift in Sources */, B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */, B08126F1217BE19000A98970 /* WidgetProtocol.swift in Sources */, B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */, diff --git a/MTMR/Info.plist b/MTMR/Info.plist index 670c410..b137245 100644 --- a/MTMR/Info.plist +++ b/MTMR/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.19.5 + 0.20 CFBundleVersion - 140 + 178 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index c2003db..7ac5c27 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -338,6 +338,7 @@ enum ItemType: Decodable { case nightShift() case dnd() case pomodoro(workTime: Double, restTime: Double) + case network() private enum CodingKeys: String, CodingKey { case type @@ -376,6 +377,7 @@ enum ItemType: Decodable { case nightShift case dnd case pomodoro + case network } init(from decoder: Decoder) throws { @@ -444,6 +446,9 @@ enum ItemType: Decodable { let workTime = try container.decodeIfPresent(Double.self, forKey: .workTime) ?? 1500.0 let restTime = try container.decodeIfPresent(Double.self, forKey: .restTime) ?? 600.0 self = .pomodoro(workTime: workTime, restTime: restTime) + + case .network: + self = .network() } } } diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index bc1e035..a2862ef 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -49,6 +49,8 @@ extension ItemType { return "com.toxblh.mtmr.dnd." case .pomodoro(interval: _): return PomodoroBarItem.identifier + case .network(): + return NetworkBarItem.identifier } } } @@ -279,6 +281,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate { barItem = DnDBarItem(identifier: identifier) case let .pomodoro(workTime: workTime, restTime: restTime): barItem = PomodoroBarItem(identifier: identifier, workTime: workTime, restTime: restTime) + case .network(): + barItem = NetworkBarItem(identifier: identifier) } if let action = self.action(forItem: item), let item = barItem as? CustomButtonTouchBarItem { diff --git a/MTMR/Widgets/NetworkBarItem.swift b/MTMR/Widgets/NetworkBarItem.swift new file mode 100644 index 0000000..cfbec3b --- /dev/null +++ b/MTMR/Widgets/NetworkBarItem.swift @@ -0,0 +1,129 @@ +// +// NetworkBarItem.swift +// MTMR +// +// Created by Anton Palgunov on 23/02/2019. +// Copyright © 2019 Anton Palgunov. All rights reserved. +// + +import Foundation + +class NetworkBarItem: CustomButtonTouchBarItem, Widget { + static var name: String = "network" + static var identifier: String = "com.toxblh.mtmr.network" + + init(identifier: NSTouchBarItem.Identifier) { + super.init(identifier: identifier, title: " ") + startMonitoringProcess() + } + + required init?(coder _: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func startMonitoringProcess() { + var pipe: Pipe + var outputHandle: FileHandle + var bandwidthProcess: Process? + var dSpeed: UInt64? + var uSpeed: UInt64? + var curr: Array? + var dataAvailable: NSObjectProtocol! + + pipe = Pipe() + bandwidthProcess = Process() + bandwidthProcess?.launchPath = "/usr/bin/env" + bandwidthProcess?.arguments = ["netstat", "-w1", "-l", "en0"] + bandwidthProcess?.standardOutput = pipe + + outputHandle = pipe.fileHandleForReading + outputHandle.waitForDataInBackgroundAndNotify(forModes: [RunLoop.Mode.common]) + + dataAvailable = NotificationCenter.default.addObserver( + forName: NSNotification.Name.NSFileHandleDataAvailable, + object: outputHandle, + queue: nil + ) { _ -> Void in + let data = pipe.fileHandleForReading.availableData + if data.count > 0 { + if let str = NSString(data: data, encoding: String.Encoding.utf8.rawValue) { + curr = [""] + curr = str + .replacingOccurrences(of: " ", with: " ") + .split(separator: " ") + if curr == nil || (curr?.count)! < 6 {} else { + if Int64(curr![2]) == nil {} else { + dSpeed = UInt64(curr![2]) + uSpeed = UInt64(curr![5]) + + self.setTitle(up: self.getHumanizeSize(speed: uSpeed!), down: self.getHumanizeSize(speed: dSpeed!)) + } + } + } + outputHandle.waitForDataInBackgroundAndNotify() + } else { + NotificationCenter.default.removeObserver(dataAvailable) + } + } + + var dataReady: NSObjectProtocol! + dataReady = NotificationCenter.default.addObserver( + forName: Process.didTerminateNotification, + object: outputHandle, + queue: nil + ) { _ -> Void in + print("Task terminated!") + NotificationCenter.default.removeObserver(dataReady) + } + + bandwidthProcess?.launch() + } + + func getHumanizeSize(speed: UInt64) -> String { + let humanText: String + + if speed < 1024 { + humanText = String(format: "%.0f", Double(speed)) + " B/s" + } else if speed < (1024 * 1024) { + humanText = String(format: "%.1f", Double(speed) / 1024) + " KB/s" + } else if speed < (1024 * 1024 * 1024) { + humanText = String(format: "%.1f", Double(speed) / (1024 * 1024)) + " MB/s" + } else { + humanText = String(format: "%.2f", Double(speed) / (1024 * 1024 * 1024)) + " GB/s" + } + + return humanText + } + + func setTitle(up: String, down: String) { + let titleFont = NSFont.monospacedDigitSystemFont(ofSize: 12, weight: NSFont.Weight.light) + + let newTitle = NSMutableAttributedString( + string: "↓", + attributes: [ + NSAttributedString.Key.foregroundColor: NSColor.red, + NSAttributedString.Key.font: titleFont, + ]) + + newTitle.append(NSMutableAttributedString( + string: down, + attributes: [ + NSAttributedString.Key.font: titleFont + ])) + + newTitle.append(NSMutableAttributedString( + string: "\n↑", + attributes: [ + NSAttributedString.Key.foregroundColor: NSColor.blue, + NSAttributedString.Key.font: titleFont, + ])) + + newTitle.append(NSMutableAttributedString( + string: up, + attributes: [ + NSAttributedString.Key.font: titleFont, + ])) + + self.attributedTitle = newTitle + } +} diff --git a/MTMR/Widgets/WidgetProtocol.swift b/MTMR/Widgets/WidgetProtocol.swift index 2775c47..469dc57 100644 --- a/MTMR/Widgets/WidgetProtocol.swift +++ b/MTMR/Widgets/WidgetProtocol.swift @@ -9,5 +9,4 @@ protocol Widget { static var name: String { get } static var identifier: String { get } - static var decoder: ParametersDecoder { get } } diff --git a/README.md b/README.md index 0d09a3a..3c70c11 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ My idea is to create a platform for creating plugins to customize the TouchBar. - nightShift - dnd (Don't disturb) - pomodoro +- network > Media Keys - previous @@ -171,6 +172,14 @@ To close a group, use the button: }, ``` +#### `network` +> Network plugin. The plugin to show usage a network +```js +{ + "type": "network", +}, +``` + ## Actions: - `hidKey` > https://github.com/aosm/IOHIDFamily/blob/master/IOHIDSystem/IOKit/hidsystem/ev_keymap.h use only numbers