Improve URL Scheme consistency #280

This commit is contained in:
Alex Mazanov 2022-02-12 07:01:46 -08:00
parent f25db9dfee
commit 56bf483170
No known key found for this signature in database
GPG Key ID: FD35C3C7C1D34AB4
3 changed files with 31 additions and 38 deletions

View File

@ -265,13 +265,15 @@ You can mark a plugin as streamable with a special metadata property `<swiftbar.
| Endpoint | Parameter | Description | Example | | Endpoint | Parameter | Description | Example |
| ------------- | ------------- |------------- | ------------- | | ------------- | ------------- |------------- | ------------- |
| refreshallplugins | none | Force refresh all loaded plugins | `swiftbar://refreshallplugins` | | refreshallplugins | none | Force refresh all loaded plugins | `swiftbar://refreshallplugins` |
| refreshplugin | `name` plugin [name](#plugin-naming) | Force refresh plugin by name | `swiftbar://refreshplugin?name=myplugin` | | refreshplugin | `name` or `plugin` plugin [name](#plugin-naming) | Force refresh plugin by name | `swiftbar://refreshplugin?name=myplugin` |
| refreshplugin | `index` plugin index in menubar, starting from `0` | Force refresh plugin by its position in menubar | `swiftbar://refreshplugin?index=1` | | refreshplugin | `index` plugin index in menubar, starting from `0` | Force refresh plugin by its position in menubar | `swiftbar://refreshplugin?index=1` |
| enableplugin | `name` plugin [name](#plugin-naming) | Enable plugin by name | `swiftbar://enableplugin?name=myplugin` | | enableplugin | `name` or `plugin` plugin [name](#plugin-naming) | Enable plugin by name | `swiftbar://enableplugin?name=myplugin` |
| disableplugin | `name` plugin [name](#plugin-naming) | Disable plugin by name | `swiftbar://disableplugin?name=myplugin` | | disableplugin | `name` or `plugin` plugin [name](#plugin-naming) | Disable plugin by name | `swiftbar://disableplugin?name=myplugin` |
| toggleplugin | `name` plugin [name](#plugin-naming) | Toggle(enable\disable) plugin by name | `swiftbar://toggleplugin?name=myplugin` | | toggleplugin | `name` or `plugin` plugin [name](#plugin-naming) | Toggle(enable\disable) plugin by name | `swiftbar://toggleplugin?name=myplugin` |
| addplugin | `src` source URL to plugin file | Add plugin to Swiftbar from URL | `swiftbar://addplugin?src=https://coolplugin` | | addplugin | `src` source URL to plugin file | Add plugin to Swiftbar from URL | `swiftbar://addplugin?src=https://coolplugin` |
| notify | `plugin` plugin [name](#plugin-naming). Notification fields: `title`, `subtitle`, `body`. `href` to open an URL on click (including custom URL schemes). `silent=true` to disable sound | Show notification | `swiftbar://notify?plugin=MyPlugin&title=title&subtitle=subtitle&body=body&silent=true` | | notify | `name` or `plugin` plugin [name](#plugin-naming). Notification fields: `title`, `subtitle`, `body`. `href` to open an URL on click (including custom URL schemes). `silent=true` to disable sound | Show notification | `swiftbar://notify?plugin=MyPlugin&title=title&subtitle=subtitle&body=body&silent=true` |
LTP: instead of plugin [name](#plugin-naming) you can(and probably should) use plugin file name, this considered a unique plugin ID where name can be the same between multiple plugins. If your plugin's filepath is `~/Documents/SwiftBar/myplugin.1m.sh` then name is `myplugin` and ID `myplugin.1m.sh`
## Preferences aka 'defaults' ## Preferences aka 'defaults'

View File

@ -103,14 +103,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, SPUStandardUserDriverDelegat
pluginManager.terminateAllPlugins() pluginManager.terminateAllPlugins()
} }
func getPluginFromURL(url: URL) -> Plugin? {
guard let identifier = url.queryParameters?["plugin"] ?? url.queryParameters?["name"] else { return nil }
return pluginManager.getPluginByNameOrID(identifier: identifier)
}
func application(_: NSApplication, open urls: [URL]) { func application(_: NSApplication, open urls: [URL]) {
for url in urls { for url in urls {
switch url.host?.lowercased() { switch url.host?.lowercased() {
case "refreshallplugins": case "refreshallplugins":
pluginManager.refreshAllPlugins() pluginManager.refreshAllPlugins()
case "refreshplugin": case "refreshplugin":
if let name = url.queryParameters?["name"] { if let plugin = getPluginFromURL(url: url) {
pluginManager.refreshPlugin(named: name) plugin.refresh()
return return
} }
if let indexStr = url.queryParameters?["index"], let index = Int(indexStr) { if let indexStr = url.queryParameters?["index"], let index = Int(indexStr) {
@ -118,25 +123,25 @@ class AppDelegate: NSObject, NSApplicationDelegate, SPUStandardUserDriverDelegat
return return
} }
case "disableplugin": case "disableplugin":
if let name = url.queryParameters?["name"] { if let plugin = getPluginFromURL(url: url) {
pluginManager.disablePlugin(named: name) pluginManager.disablePlugin(plugin: plugin)
} }
case "enableplugin": case "enableplugin":
if let name = url.queryParameters?["name"] { if let plugin = getPluginFromURL(url: url) {
pluginManager.enablePlugin(named: name) pluginManager.enablePlugin(plugin: plugin)
} }
case "toggleplugin": case "toggleplugin":
if let name = url.queryParameters?["name"] { if let plugin = getPluginFromURL(url: url) {
pluginManager.togglePlugin(named: name) pluginManager.togglePlugin(plugin: plugin)
} }
case "addplugin": case "addplugin":
if let src = url.queryParameters?["src"], let url = URL(string: src) { if let src = url.queryParameters?["src"], let url = URL(string: src) {
pluginManager.importPlugin(from: url) pluginManager.importPlugin(from: url)
} }
case "notify": case "notify":
guard let pluginID = url.queryParameters?["plugin"] else { return } guard let plugin = getPluginFromURL(url: url) else { return }
let paramsString = url.queryParameters?.map { "\($0.key)=\($0.value.escaped())" }.joined(separator: " ") ?? "" let paramsString = url.queryParameters?.map { "\($0.key)=\($0.value.escaped())" }.joined(separator: " ") ?? ""
pluginManager.showNotification(pluginID: pluginID, pluginManager.showNotification(plugin: plugin,
title: url.queryParameters?["title"], title: url.queryParameters?["title"],
subtitle: url.queryParameters?["subtitle"], subtitle: url.queryParameters?["subtitle"],
body: url.queryParameters?["body"], body: url.queryParameters?["body"],

View File

@ -75,28 +75,22 @@ class PluginManager: ObservableObject {
enabledPlugins.isEmpty && !prefs.stealthMode ? barItem.show() : barItem.hide() enabledPlugins.isEmpty && !prefs.stealthMode ? barItem.show() : barItem.hide()
} }
func getPluginByNameOrID(identifier: String) -> Plugin? {
plugins.first(where: { $0.id.lowercased() == identifier.lowercased() }) ??
plugins.first(where: { $0.name.lowercased() == identifier.lowercased() })
}
func disablePlugin(plugin: Plugin) { func disablePlugin(plugin: Plugin) {
os_log("Disabling plugin \n%{public}@", log: Log.plugin, plugin.description) os_log("Disabling plugin \n%{public}@", log: Log.plugin, plugin.description)
plugin.disable() plugin.disable()
} }
func disablePlugin(named name: String) {
guard let plugin = plugins.first(where: { $0.name.lowercased() == name.lowercased() }) else { return }
disablePlugin(plugin: plugin)
}
func enablePlugin(plugin: Plugin) { func enablePlugin(plugin: Plugin) {
os_log("Enabling plugin \n%{public}@", log: Log.plugin, plugin.description) os_log("Enabling plugin \n%{public}@", log: Log.plugin, plugin.description)
plugin.enable() plugin.enable()
} }
func enablePlugin(named name: String) { func togglePlugin(plugin: Plugin) {
guard let plugin = plugins.first(where: { $0.name.lowercased() == name.lowercased() }) else { return }
enablePlugin(plugin: plugin)
}
func togglePlugin(named name: String) {
guard let plugin = plugins.first(where: { $0.name.lowercased() == name.lowercased() }) else { return }
plugin.enabled ? disablePlugin(plugin: plugin) : enablePlugin(plugin: plugin) plugin.enabled ? disablePlugin(plugin: plugin) : enablePlugin(plugin: plugin)
} }
@ -209,11 +203,6 @@ class PluginManager: ObservableObject {
menuBarItems.values.forEach { $0.updateMenu(content: $0.plugin?.content) } menuBarItems.values.forEach { $0.updateMenu(content: $0.plugin?.content) }
} }
func refreshPlugin(named name: String) {
guard let plugin = plugins.first(where: { $0.name.lowercased() == name.lowercased() }) else { return }
plugin.refresh()
}
func refreshPlugin(with index: Int) { func refreshPlugin(with index: Int) {
guard plugins.indices.contains(index) else { return } guard plugins.indices.contains(index) else { return }
plugins[index].refresh() plugins[index].refresh()
@ -262,18 +251,15 @@ class PluginManager: ObservableObject {
} }
extension PluginManager { extension PluginManager {
func showNotification(pluginID: PluginID, title: String?, subtitle: String?, body: String?, href: String?, commandParams: String?, silent: Bool = false) { func showNotification(plugin: Plugin, title: String?, subtitle: String?, body: String?, href: String?, commandParams: String?, silent: Bool = false) {
guard let plugin = plugins.first(where: { $0.id == pluginID }),
plugin.enabled else { return }
let content = UNMutableNotificationContent() let content = UNMutableNotificationContent()
content.title = title ?? "" content.title = title ?? ""
content.subtitle = subtitle ?? "" content.subtitle = subtitle ?? ""
content.body = body ?? "" content.body = body ?? ""
content.sound = silent ? nil : .default content.sound = silent ? nil : .default
content.threadIdentifier = pluginID content.threadIdentifier = plugin.id
content.userInfo[SystemNotificationName.pluginID] = pluginID content.userInfo[SystemNotificationName.pluginID] = plugin.id
if let urlString = href, if let urlString = href,
let url = URL(string: urlString), url.host != nil, url.scheme != nil let url = URL(string: urlString), url.host != nil, url.scheme != nil