Skip to content

Commit

Permalink
Move workflow-specific pane configs to workflow dirs
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-pennyworth committed Jul 11, 2024
1 parent 4102ce7 commit 79062ef
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 22 deletions.
20 changes: 13 additions & 7 deletions AlfredExtraPane/Pane.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@ enum PanePosition: Equatable {
case vertical(placement: VerticalPlacement, height: Int)
}

public struct WorkflowPaneConfig {
let paneConfig: PaneConfig
/// A nil workflowUID means that this pane is a global pane,
/// applicable to all the workflows.
let workflowUID: String?
}

public struct PaneConfig: Codable, Equatable {
let alignment: PanePosition
/// The workflow UID **or ID** that this pane is associated with.
let workflowUID: String
let customUserAgent: String?
}

class Pane {
let workflowUID: String? // nil for global panes
let config: PaneConfig
var alfredFrame: NSRect = .zero
let window: NSWindow = makeWindow()
Expand All @@ -31,19 +37,19 @@ class Pane {
}
}()

init(config: PaneConfig) {
self.config = config
init(workflowPaneConfig: WorkflowPaneConfig) {
self.config = workflowPaneConfig.paneConfig
self.workflowUID = workflowPaneConfig.workflowUID
window.contentView!.addSubview(webView)

Alfred.onHide { self.hide() }
Alfred.onFrameChange { self.alfredFrame = $0 }
}

lazy var isWildcard: Bool = { self.config.workflowUID == "*" }()
lazy var isGlobal: Bool = { self.workflowUID == nil }()

func matchesExactly(item: Alfred.SelectedItem) -> Bool {
item.workflowuid == self.config.workflowUID ||
item.workflowuid == self.workflowIDtoUID[self.config.workflowUID]
item.workflowuid == self.workflowUID
}

func render(_ url: URL) {
Expand Down
31 changes: 24 additions & 7 deletions AlfredExtraPane/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import AppKit
import Foundation
import Sparkle

let globalConfigFilename = "config.json"
let workflowConfigFilename = "extra-pane-config.json"

class AppDelegate: NSObject, NSApplicationDelegate {
let fs = FileManager.default
var panes: [Pane] = []
private let defaultConfig = PaneConfig(
alignment: .horizontal(placement: .right, width: 300, minHeight: 400),
workflowUID: "*",
customUserAgent: nil
)
var statusItem: NSStatusItem?
Expand All @@ -20,15 +22,15 @@ class AppDelegate: NSObject, NSApplicationDelegate {

override init() {
super.init()
let confs: [PaneConfig] =
(try? read(contentsOf: configFile())) ?? [defaultConfig]
panes = confs.map { Pane(config: $0) }
let confs = globalConfigs() + workflowConfigs()
dump(confs)
panes = confs.map { Pane(workflowPaneConfig: $0) }
Alfred.onItemSelect { item in
// First, render panes that have exact match with workflowUID.
// Then, if no exact match is found, render the wildcard panes.
[
self.panes.filter({ $0.matchesExactly(item: item) }),
self.panes.filter({ $0.isWildcard })
self.panes.filter({ $0.isGlobal })
] .first(where: { !$0.isEmpty })?
.forEach({ pane in item.quicklookurl.map { pane.render($0) } })
}
Expand Down Expand Up @@ -63,14 +65,29 @@ class AppDelegate: NSObject, NSApplicationDelegate {
return prefsDir
}

func configFile() throws -> URL {
let conf = try! appPrefsDir().appendingPathComponent("config.json")
func globalConfigFile() throws -> URL {
let conf = try! appPrefsDir().appendingPathComponent(globalConfigFilename)
if !fs.fileExists(atPath: conf.path) {
write([defaultConfig], to: conf)
}
return conf
}

func globalConfigs() -> [WorkflowPaneConfig] {
((try? read(contentsOf: globalConfigFile())) ?? [defaultConfig])
.map { WorkflowPaneConfig(paneConfig: $0, workflowUID: nil) }
}

func workflowConfigs() -> [WorkflowPaneConfig] {
Alfred.workflows().flatMap { wf in
let confPath = wf.dir.appendingPathComponent(workflowConfigFilename)
let confs: [PaneConfig] = read(contentsOf: confPath) ?? []
return confs.map {
WorkflowPaneConfig(paneConfig: $0, workflowUID: wf.uid)
}
}
}

func setupMenubarExtra() {
let appName =
Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String
Expand Down
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,14 @@ Check out the [tutorial](#tutorial) for a quick walk-through.
and dimensions of the pane

## Configuration
The pane(s) can be configured by editing
`{/path/to}/Alfred.alfredpreferences/preferences/mr.pennyworth.AlfredExtraPane/config.json`
The global pane(s) can be configured by editing
`{/path/to}/Alfred.alfredpreferences/preferences/mr.pennyworth.AlfredExtraPane/config.json`.
Similarly, pane(s) for individual workflows can be configured by editing
`{workflow-dir}/extra-pane-config.json`. If there are any workflow-specific
panes, the items produced from that workflow will not be shown in the global
panes.

Configurable parameters are:
- `workflowUID` (required):
`*` or a specific workflow UID (bundle IDs work too)
- `alignment` (required):
- `horizontal`
- `placement`: `left` or `right`
Expand All @@ -81,19 +83,15 @@ Configurable parameters are:
Here's an example with four panes configured:
```json
[{
"workflowUID" : "*",
"alignment" : {
"horizontal" : {"placement" : "right", "width" : 300, "minHeight" : 400}}
}, {
"workflowUID" : "*",
"alignment" : {
"horizontal" : {"placement" : "left", "width" : 300, "minHeight" : 400}}
}, {
"workflowUID" : "*",
"alignment" : {
"vertical" : {"placement" : "top", "height" : 100}}
}, {
"workflowUID" : "*",
"alignment" : {
"vertical" : {"placement" : "bottom", "height" : 200}}
}]
Expand Down

0 comments on commit 79062ef

Please sign in to comment.