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

merge external code

This commit is contained in:
Toxblh 2019-11-28 21:48:41 +03:00
parent 85e3deac79
commit a4fee54ae0
9 changed files with 671 additions and 9 deletions

2
.gitignore vendored
View File

@ -54,7 +54,7 @@ playground.xcworkspace
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Checkouts
Carthage/Build

1
Cartfile Normal file
View File

@ -0,0 +1 @@
github "stephencelis/SQLite.swift" ~> 0.12.0

1
Cartfile.resolved Normal file
View File

@ -0,0 +1 @@
github "stephencelis/SQLite.swift" "0.12.2"

View File

@ -32,10 +32,14 @@
607EEA4D2087A8DA009DA5F0 /* CurrencyBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */; };
60C44AFD20A373A100C0EC91 /* MusicBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */; };
60F7D454208CC31400ABF5D2 /* InputSourceBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F7D453208CC31400ABF5D2 /* InputSourceBarItem.swift */; };
8338290C2360CA31008981D7 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8338290B2360CA31008981D7 /* SQLite.framework */; };
8338290D2360CA3F008981D7 /* SQLite.framework in Copy Files */ = {isa = PBXBuildFile; fileRef = 8338290B2360CA31008981D7 /* SQLite.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
839ECD8523600BF500BE2DA5 /* NotificationTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839ECD8423600BF500BE2DA5 /* NotificationTouchBarItem.swift */; };
839ECD882360160100BE2DA5 /* Mail.scpt in Sources */ = {isa = PBXBuildFile; fileRef = 839ECD872360160100BE2DA5 /* Mail.scpt */; };
B0008E552080286C003AD4DD /* SupportHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0008E542080286C003AD4DD /* SupportHelpers.swift */; };
B002E642216C0E38002774BA /* CoreDisplay.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B002E641216C0E38002774BA /* CoreDisplay.framework */; };
B00D181D2152F4A5000806F4 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B00D181C2152F4A5000806F4 /* Sparkle.framework */; };
B00D181F2152F521000806F4 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = B00D181C2152F4A5000806F4 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B00D181F2152F521000806F4 /* Sparkle.framework in Copy Files */ = {isa = PBXBuildFile; fileRef = B00D181C2152F4A5000806F4 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B04B7BB72087398C00C835D0 /* BatteryBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B04B7BB62087398C00C835D0 /* BatteryBarItem.swift */; };
B05600D32083E9BB00EB218D /* CustomSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B05600D22083E9BB00EB218D /* CustomSlider.swift */; };
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; };
@ -70,14 +74,16 @@
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
B00D181E2152F507000806F4 /* CopyFiles */ = {
B00D181E2152F507000806F4 /* Copy Files */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 12;
dstPath = "";
dstSubfolderSpec = 10;
files = (
B00D181F2152F521000806F4 /* Sparkle.framework in CopyFiles */,
B00D181F2152F521000806F4 /* Sparkle.framework in Copy Files */,
8338290D2360CA3F008981D7 /* SQLite.framework in Copy Files */,
);
name = "Copy Files";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
@ -112,6 +118,10 @@
607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyBarItem.swift; sourceTree = "<group>"; };
60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicBarItem.swift; sourceTree = "<group>"; };
60F7D453208CC31400ABF5D2 /* InputSourceBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputSourceBarItem.swift; sourceTree = "<group>"; };
8338290B2360CA31008981D7 /* SQLite.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SQLite.framework; path = Carthage/Build/Mac/SQLite.framework; sourceTree = "<group>"; };
839ECD8423600BF500BE2DA5 /* NotificationTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTouchBarItem.swift; sourceTree = "<group>"; };
839ECD86236015E300BE2DA5 /* Messages.scpt */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = Messages.scpt; sourceTree = "<group>"; };
839ECD872360160100BE2DA5 /* Mail.scpt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Mail.scpt; sourceTree = "<group>"; };
B0008E542080286C003AD4DD /* SupportHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportHelpers.swift; sourceTree = "<group>"; };
B002E641216C0E38002774BA /* CoreDisplay.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreDisplay.framework; path = ../../../../../System/Library/Frameworks/CoreDisplay.framework; sourceTree = "<group>"; };
B00D181C2152F4A5000806F4 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Sparkle.framework; sourceTree = "<group>"; };
@ -164,6 +174,7 @@
files = (
B002E642216C0E38002774BA /* CoreDisplay.framework in Frameworks */,
B081732A2135F354005D4908 /* CoreBrightness.framework in Frameworks */,
8338290C2360CA31008981D7 /* SQLite.framework in Frameworks */,
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */,
B09EB1E6207C0F8E00D5C1E0 /* MultitouchSupport.framework in Frameworks */,
B00D181D2152F4A5000806F4 /* Sparkle.framework in Frameworks */,
@ -183,6 +194,7 @@
B059D62B205F11E8006E6B86 /* Frameworks */ = {
isa = PBXGroup;
children = (
8338290B2360CA31008981D7 /* SQLite.framework */,
B002E641216C0E38002774BA /* CoreDisplay.framework */,
B00D181C2152F4A5000806F4 /* Sparkle.framework */,
B08173292135F354005D4908 /* CoreBrightness.framework */,
@ -268,6 +280,8 @@
B0B1742E207D6B590004B740 /* Vox.next.scpt */,
B0B1742F207D6B590004B740 /* Vox.nowPlaying.scpt */,
B0B17428207D6B580004B740 /* Weather.scpt */,
839ECD86236015E300BE2DA5 /* Messages.scpt */,
839ECD872360160100BE2DA5 /* Mail.scpt */,
);
path = AppleScripts;
sourceTree = "<group>";
@ -310,6 +324,7 @@
4CFF5E5B22E623DD00BFB1EE /* YandexWeatherBarItem.swift */,
B08126F0217BE19000A98970 /* WidgetProtocol.swift */,
B0F54A792295AC7D00B4C509 /* DarkModeBarItem.swift */,
839ECD8423600BF500BE2DA5 /* NotificationTouchBarItem.swift */,
);
path = Widgets;
sourceTree = "<group>";
@ -324,7 +339,7 @@
B082B24B205C7D8000BC04DC /* Sources */,
B082B24C205C7D8000BC04DC /* Frameworks */,
B082B24D205C7D8000BC04DC /* Resources */,
B00D181E2152F507000806F4 /* CopyFiles */,
B00D181E2152F507000806F4 /* Copy Files */,
B0679BBF215AE085000FC6B4 /* ShellScript */,
);
buildRules = (
@ -479,8 +494,10 @@
B08173272135F02B005D4908 /* NightShiftBarItem.swift in Sources */,
36FEF872235A1CFC00A0ABCE /* AppSettings.swift in Sources */,
60F7D454208CC31400ABF5D2 /* InputSourceBarItem.swift in Sources */,
839ECD882360160100BE2DA5 /* Mail.scpt in Sources */,
36A778BE20A6C27100B38714 /* GeneralExtensions.swift in Sources */,
60669B4320AD8FA80074E817 /* GroupBarItem.swift in Sources */,
839ECD8523600BF500BE2DA5 /* NotificationTouchBarItem.swift in Sources */,
36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */,
B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */,
36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */,
@ -637,9 +654,16 @@
"$(inherited)",
"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
"$(PROJECT_DIR)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = MTMR/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.14;
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
"\"SQLite\"",
);
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMR;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -660,9 +684,16 @@
"$(inherited)",
"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
"$(PROJECT_DIR)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = MTMR/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.14;
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
"\"SQLite\"",
);
PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMR;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

View File

@ -0,0 +1,10 @@
if application "Mail" is running then
tell application "Mail"
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 ""

View File

@ -0,0 +1,10 @@
if application "Messages" is running then
tell application "Messages"
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 ""

View File

@ -56,6 +56,13 @@ class SupportedTypesHolder {
parameters: [.align: .align(.left)]
) },
"reply": { _ in (
item: .staticButton(title: "Reply"),
action: .shellScript(executable: "/usr/bin/open", parameters: ["sms://"]),
longAction: .none,
parameters: [.align: .align(.right)]
) },
"delete": { _ in (
item: .staticButton(title: "del"),
action: .keyPress(keycode: 117),
@ -177,6 +184,27 @@ class SupportedTypesHolder {
parameters: [:]
) },
"notification": { decoder in
enum CodingKeys: String, CodingKey { case refreshInterval; case disableMarquee; case image }
let container = try decoder.container(keyedBy: CodingKeys.self)
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval)
let disableMarquee = try container.decodeIfPresent(Bool.self, forKey: .disableMarquee)
if var img = try container.decodeIfPresent(Source.self, forKey: .image) {
return (
item: .notification(interval: interval ?? 5.0, disableMarquee: disableMarquee ?? false),
action: .shellScript(executable: "/usr/bin/open", parameters: ["sms://"]),
longAction: .none,
parameters: [.image: .image(source: img)]
)
} else {
return (
item: .notification(interval: interval ?? 5.0, disableMarquee: disableMarquee ?? false),
action: .shellScript(executable: "/usr/bin/open", parameters: ["sms://"]),
longAction: .none,
parameters: [:]
)
}
},
]
static let sharedInstance = SupportedTypesHolder()
@ -220,6 +248,7 @@ enum ItemType: Decodable {
case currency(interval: Double, from: String, to: String, full: Bool)
case inputsource
case music(interval: Double, disableMarquee: Bool)
case notification(interval: Double, disableMarquee: Bool)
case group(items: [BarItemDefinition])
case nightShift
case dnd
@ -267,6 +296,7 @@ enum ItemType: Decodable {
case currency
case inputsource
case music
case notification
case group
case nightShift
case dnd
@ -283,7 +313,7 @@ enum ItemType: Decodable {
let source = try container.decode(Source.self, forKey: .source)
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
self = .appleScriptTitledButton(source: source, refreshInterval: interval)
case .shellScriptTitledButton:
let source = try container.decode(Source.self, forKey: .source)
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
@ -320,7 +350,7 @@ enum ItemType: Decodable {
let api_key = try container.decodeIfPresent(String.self, forKey: .api_key) ?? "32c4256d09a4c52b38aecddba7a078f6"
let icon_type = try container.decodeIfPresent(String.self, forKey: .icon_type) ?? "text"
self = .weather(interval: interval, units: units, api_key: api_key, icon_type: icon_type)
case .yandexWeather:
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0
self = .yandexWeather(interval: interval)
@ -340,6 +370,11 @@ enum ItemType: Decodable {
let disableMarquee = try container.decodeIfPresent(Bool.self, forKey: .disableMarquee) ?? false
self = .music(interval: interval, disableMarquee: disableMarquee)
case .notification:
let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 5.0
let disableMarquee = try container.decodeIfPresent(Bool.self, forKey: .disableMarquee) ?? false
self = .notification(interval: interval, disableMarquee: disableMarquee)
case .group:
let items = try container.decode([BarItemDefinition].self, forKey: .items)
self = .group(items: items)

View File

@ -45,6 +45,8 @@ extension ItemType {
return "com.toxblh.mtmr.inputsource."
case .music(interval: _):
return "com.toxblh.mtmr.music."
case .notification(interval: _):
return "com.toxblh.mtmr.notification."
case .group(items: _):
return "com.toxblh.mtmr.groupBar."
case .nightShift:
@ -98,7 +100,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
}
blacklistAppIdentifiers = AppSettings.blacklistedAppIds
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(activeApplicationChanged), name: NSWorkspace.didLaunchApplicationNotification, object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(activeApplicationChanged), name: NSWorkspace.didTerminateApplicationNotification, object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(activeApplicationChanged), name: NSWorkspace.didActivateApplicationNotification, object: nil)
@ -258,7 +260,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
} else {
barItem = AppScrubberTouchBarItem(identifier: identifier, autoResize: autoResize)
}
case .volume:
case .volume:
if case let .image(source)? = item.additionalParameters[.image] {
barItem = VolumeViewController(identifier: identifier, image: source.image)
} else {
@ -280,6 +282,12 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
barItem = InputSourceBarItem(identifier: identifier)
case let .music(interval: interval, disableMarquee: disableMarquee):
barItem = MusicBarItem(identifier: identifier, interval: interval, disableMarquee: disableMarquee)
case let .notification(interval: interval, disableMarquee: disableMarquee):
if case let .image(source)? = item.additionalParameters[.image] {
barItem = NotificationBarItem(identifier: identifier, interval: interval, disableMarquee: disableMarquee, image: source.image)
} else {
barItem = NotificationBarItem(identifier: identifier, interval: interval, disableMarquee: disableMarquee)
}
case let .group(items: items):
barItem = GroupBarItem(identifier: identifier, items: items)
case .nightShift:

View File

@ -0,0 +1,566 @@
//
// NotificationsTouchBarItem.swift
// MTMR
//
// Created by Matthew Cox on 10/22/19.
// Copyright © 2019 Anton Palgunov. All rights reserved.
//
import Foundation
import Cocoa
import ScriptingBridge
import SQLite
import Contacts
import UserNotifications
class NotificationBarItem: CustomButtonTouchBarItem {
public enum Message: String {
case Messages = "com.apple.iChat"
case Mail = "com.apple.mail"
}
private let notificationIdentifiers = [
Message.Messages,
Message.Mail,
]
private let interval: TimeInterval
private let disableMarquee: Bool
private var messageText: String?
private var messageFrom: String?
private var timer: Timer?
private let iconSize = NSSize(width: 21, height: 21)
private let activity: NSBackgroundActivityScheduler
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, disableMarquee: Bool, image: NSImage? = nil) {
self.interval = interval
self.disableMarquee = disableMarquee
//tapClosure = { [weak self] in self?.DarkModeToggle() }
if image == nil {
//sliderItem = CustomSlider()
} else {
// sliderItem = CustomSlider(knob: image!)
}
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
activity.interval = interval
super.init(identifier: identifier, title: "")
//var systemBlue: NSColor { set }
isBordered = false
backgroundColor = NSColor.systemRed
//button = item.view as? NSButton else { continue }
//let textRange = NSRange(location: 0, length: button.title.characters.count)
//let titleColor = useCustomColor.state == NSControl.StateValue.on ? NSColor.black : NSColor.white
//let newTitle = NSMutableAttributedString(string: button.title)
//newTitle.addAttribute(NSAttributedStringKey.foregroundColor, value: titleColor, range: textRange)
//newTitle.addAttribute(NSAttributedStringKey.font, value: button.font!, range: textRange)
//newTitle.setAlignment(.center, range: textRange)
//button.attributedTitle = newTitle
//attributedTitle = "test"
//image = NSImage(name: NSUserGroup)
//title = "\(Noti.0)"
// func getDeliveredNotifications(completionHandler: @escaping ([UNNotification]) -> Void) {
// print("")
// }
// let notificationCenter = UNUserNotificationCenter.current()
// notificationCenter.requestAuthorization(options: [.alert, .badge, .provisional]) {}
// UNUserNotificationCenter.current().getDeliveredNotifications { (notifications) in
// print("Noti")
// print(notifications)
// }
/* let center = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .badge, .sound]
center.requestAuthorization(options: options) { (granted, error) in
if granted {
application.registerForRemoteNotifications()
}
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let actionIdentifier = response.actionIdentifier
let content = response.notification.request.content
print("\(content)")
switch actionIdentifier {
case UNNotificationDismissActionIdentifier: // Notification was dismissed by user
// Do something
completionHandler()
case UNNotificationDefaultActionIdentifier: // App was opened from notification
// Do something
completionHandler()
case "com.usernotificationstutorial.reply":
if let textResponse = response as? UNTextInputNotificationResponse {
let reply = textResponse.userText
// Send reply message
completionHandler()
}
case "com.usernotificationstutorial.delete":
// Delete message
completionHandler()
default:
completionHandler()
}
*/
/*let replyAction = UNTextInputNotificationAction(identifier: "com.usernotificationstutorial.reply", title: "Reply", options: [], textInputButtonTitle: "Send", textInputPlaceholder: "Type your message")
let deleteAction = UNNotificationAction(identifier: "com.usernotificationstutorial.delete", title: "Delete", options: [.authenticationRequired, .destructive])
let category = UNNotificationCategory(identifier: "com.usernotificationstutorial.message", actions: [replyAction, deleteAction], intentIdentifiers: [], options: [])
center.setNotificationCategories([category])
}
userNotificationCenter(center: center)
*/
tapClosure = { [weak self] in self?.playPause() }
longTapClosure = { [weak self] in self?.nextTrack() }
refreshAndSchedule()
}
@objc func marquee() {
let str = title
if str.count > 10 {
let indexFirst = str.index(str.startIndex, offsetBy: 0)
let indexSecond = str.index(str.startIndex, offsetBy: 1)
title = String(str.suffix(from: indexSecond)) + String(str[indexFirst])
}
}
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func playPause() {
for ident in notificationIdentifiers {
if let messageApplication = SBApplication(bundleIdentifier: ident.rawValue) {
if messageApplication.isRunning {
if ident == .Messages {
let mp = (messageApplication as MessagesApplication)
mp.playpause!()
return
} else if ident == .Mail {
let mp = (messageApplication as MailApplication)
mp.playpause!()
return
}
break
}
}
}
}
@objc func nextTrack() {
for ident in notificationIdentifiers {
if let messageApplication = SBApplication(bundleIdentifier: ident.rawValue) {
if messageApplication.isRunning {
if ident == .Messages {
let mp = (messageApplication as MessagesApplication)
mp.nextTrack!()
updateNotification()
return
} else if ident == .Mail {
let mp = (messageApplication as MailApplication)
mp.nextTrack!()
updateNotification()
return
}
}
}
}
}
func refreshAndSchedule() {
DispatchQueue.main.async {
self.updateNotification()
DispatchQueue.main.asyncAfter(deadline: .now() + self.interval) { [weak self] in
self?.refreshAndSchedule()
}
}
}
func updateNotification() {
var iconUpdated = false
var titleUpdated = false
var notificationbuilder = ""
let name = ""
let message = ""
let durl = ""
let person = ""
let dbpath = ""
let Noti = NotiBar().getAll(name: name, message: message, durl: durl, person: person, dbpath: dbpath)
//let lastNotificationItem = ""
print("\(Noti.0) \(Noti.1) \(Noti.3)")
//icon \(Noti.0)
//Message \(Noti.1)
//button path \(Noti.2)
//Number \(Noti.3)
let fromBox = String(Noti.3)
let messageBox = String(Noti.1)
if fromBox.isEmpty
{
notificationbuilder = ""
}
else
{
notificationbuilder = "\(fromBox) - \(messageBox)"
}
let lastNotificationItem = "\(notificationbuilder)"
for ident in notificationIdentifiers {
if let messageApplication = SBApplication(bundleIdentifier: ident.rawValue) {
if messageApplication.isRunning {
var tempTitle = ""
if ident == .Messages {
tempTitle = lastNotificationItem
} else if ident == .Mail {
tempTitle = (messageApplication as MailApplication).title
}
if tempTitle == self.messageText {
return
} else {
self.messageText = tempTitle
}
if let messageText = self.messageText?.ifNotEmpty {
self.timer?.invalidate()
self.timer = nil
if (disableMarquee) {
self.title = " " + messageText
} else {
self.title = " " + messageText + " "
self.timer = Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: #selector(self.marquee), userInfo: nil, repeats: true)
}
titleUpdated = true
}
if let _ = tempTitle.ifNotEmpty,
let appPath = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: ident.rawValue) {
let image = NSWorkspace.shared.icon(forFile: appPath)
image.size = self.iconSize
self.image = image
iconUpdated = true
}
break
}
}
}
DispatchQueue.main.async {
if !iconUpdated {
self.image = nil
}
if !titleUpdated {
self.title = ""
}
}
}
}
class NotiRun {
static func shell(launchPath path: String, arguments args: [String]) -> String {
let task = Process()
task.launchPath = path
task.arguments = args
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
task.waitUntilExit()
return(output!)
}
}
class NotiBar
{
func getAll(name:String, message:String, durl: String, person:String, dbpath: String) -> (String, String, String, String, String)
{
let res = NotiRun.shell(launchPath: "/usr/bin/getconf", arguments: ["DARWIN_USER_DIR"])
let trimmedres = res.trimmingCharacters(in: .whitespacesAndNewlines)
let db = try! Connection("\(trimmedres)com.apple.notificationcenter/db2/db")
let record = Table("record")
let app = Table("app")
let presented = Expression<Int?>("presented")
let identifier = Expression<String?>("identifier")
let delivered_date = Expression<Int?>("delivered_date")
let app_id = Expression<Int?>("app_id")
// let app_id = Expression<Int64>("app_id")
let data = Expression<Data>("data")
var name = ""
var message = ""
var durl = ""
var person = ""
var dbpath = ""
let timestamp = Int(NSDate().timeIntervalSinceReferenceDate - 86400)
//var image = ""
//var reply = ""
//var dismiss = ""
//var other = ""
let Messages = String("com.apple.iChat")
let Mail = String("com.apple.mail")
for app in try! db.prepare(app.select(app[*]))
{
if ("\(app[identifier]!)" == Messages)
{
}
if ("\(app[identifier]!)" == Mail)
{
}
// Messages
// Mail
}
// print("\(timestamp)")
//for record in try! db.prepare(record.join(app, on: record[app_id] == app[app_id]).select(record[*]).filter(delivered_date > timestamp) ) {
//app_id == 4 ||
for record in try! db.prepare(record.select(record[*]).filter(delivered_date > timestamp && app_id == 5) ) {
guard let notifierout = try? PropertyListSerialization.propertyList(from: record[data], options: [], format: nil) else {
fatalError("failed to deserialize")
}
if let notiDescAppName = (notifierout as AnyObject)["app"]! as? String
{
if let ret = self.getPath(appNamedNew: "\(notiDescAppName)") {
let retfix = ("\(ret)")
let rettrimmed = retfix.trimmingCharacters(in: .whitespacesAndNewlines)
let notifierbuilder = Bundle(url: URL(fileURLWithPath: "\(rettrimmed)"))?.infoDictionary?["CFBundleDisplayName"] as? String ?? Bundle(url: URL(fileURLWithPath: "\(rettrimmed)"))?.infoDictionary?["CFBundleName"] as? String
if notifierbuilder == nil
{
}
else
{
if (notifierbuilder == "Messages" || notifierbuilder == "Mail")
{
if (notifierbuilder == "Messages")
{
name = "💬"
}
else if notifierbuilder == "Mail"
{
name = "✉️"
}
if let notiDescAppMessageTop = (notifierout as AnyObject)["req"]! as? AnyObject
{
if let notiDescAppMail = (notiDescAppMessageTop as AnyObject)["subt"]! as? String
{
message = notiDescAppMail
}
else if let notiDescAppMessage = (notiDescAppMessageTop as AnyObject)["body"]! as? String
{
message = notiDescAppMessage
}
}
if let notiDescAppURLTop = (notifierout as AnyObject)["req"]! as? AnyObject
{
if let notiDescAppURL = (notiDescAppURLTop as AnyObject)["durl"]! as? String
{
durl = notiDescAppURL
}
}
if let notiDescAppPersonTop = (notifierout as AnyObject)["req"]! as? AnyObject
{
if let notiDescAppPerson = (notiDescAppPersonTop as AnyObject)["titl"]! as? String
{
person = notiDescAppPerson
}
// let imagee = getContactImage(imgu: "\(person)")
}
}
else
{
name = notifierbuilder!
}
}
}
}
dbpath = "\(trimmedres)com.apple.notificationcenter/db2/db"
}
//print("\(name)-\(message)-\(durl)-\(person)-\(dbpath)")
return (name, message, durl, person, dbpath)
}
// static func getImage(image: String) -> String
//{
//}
//static func getOptionReply(reply: String) -> String
//{
//}
//static func getOptionDismiss(dismiss: String) -> String
//{
//}
//static func getOptionOther(otNSView()her: String) -> String
//{
//}
func getPath(appNamedNew: String) -> String? {
if let absopath = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: appNamedNew) {
return "\(absopath)"
} else {
return ""
}
}
func lastModified(path: String) -> NSDate? {
let fileUrl = NSURL(fileURLWithPath: path)
var modified: AnyObject?
do {
try fileUrl.getResourceValue(&modified, forKey: URLResourceKey.contentModificationDateKey)
return modified as? NSDate
} catch let error as NSError {
print("\(#function) Error: \(error)")
return nil
}
}
}
func getContactImage(imgu:String) -> NSImage?
{
let store = CNContactStore()
//let contactStore = CNContactStore()
let keys = [CNContactPhoneNumbersKey, CNContactFamilyNameKey, CNContactGivenNameKey, CNContactNicknameKey, CNContactImageDataKey] as! CNKeyDescriptor
// let request = CNContactFetchRequest(keysToFetch: keys)
// try? contactStore.enumerateContacts(with: request) { (contact, error) in
// Do something with contact
//}
do
{
let contacts = try! store.unifiedContacts(matching: CNContact.predicateForContacts(matchingName: imgu), keysToFetch:[keys])
if contacts.count > 0
{
if let image = contacts[0].imageData
{
return NSImage.init(data: image)
}
}
}
return nil
}
@objc protocol MessagesApplication {
@objc optional var currentTrack: SpotifyTrack { get }
@objc optional func nextTrack()
@objc optional func previousTrack()
@objc optional func playpause()
}
extension SBApplication: MessagesApplication {}
@objc protocol MessagesTrack {
@objc optional var artist: String { get }
@objc optional var name: String { get }
}
extension SBObject: MessagesTrack {}
extension MessagesApplication {
var title: String {
guard let t = currentTrack else { return "" }
return (t.artist ?? "") + "" + (t.name ?? "")
}
}
@objc protocol MailApplication {
@objc optional var currentTrack: MailTrack { get }
@objc optional func playpause()
@objc optional func nextTrack()
@objc optional func previousTrack()
}
extension SBApplication: MailApplication {}
@objc protocol MailTrack {
@objc optional var artist: String { get }
@objc optional var name: String { get }
}
extension SBObject: MailTrack {}
extension MailApplication {
var title: String {
guard let t = currentTrack else { return "" }
return (t.artist ?? "") + "" + (t.name ?? "")
}
}