hammerspoon
hammerspoon copied to clipboard
hs.chooser enhancements
Would be great if sometime hs.chooser
could get these configuration enhancements:
- Remove/disable search bar
- Ability to disable the choices default image (so no image is shown)
- Ability to show a detail pane right or bottom of the chooser, for showing more information for the selected choice (e.g. for really long text: in text or subtext just the beginning and in the detail pane then the complete text; e.g. show an image associated to a choice
- Ability to register several keyboard events, next to
return
, for triggering different behavour, e.g. via an additional argument tocompletionFn
- Optionally show a help text (below the chooser? Tooltip?) to explain what happens when chooser is dismissed
Yep, I would love to have pretty much all of these. We've struggled a lot to get the hs.chooser UI working even as well as it does now, so I think if I was going to try again to make it even more dynamic, I would want to rewrite the whole thing and probably use SwiftUI. I can't make any promises about when we'll be able to do that though!
There is a long way to go in terms of the behaviours and keyboard navigation, but I have a very barebones SwiftUI Playground up and running that looks kinda like a Chooser:
import SwiftUI
import PlaygroundSupport
struct ChooserResult: Hashable {
var icon: String?
var text: String
var subText: String?
}
struct ContentView: View {
@State private var showQuery = true
@State private var showDetail = true
@State private var queryString: String = ""
@State private var results:[ChooserResult] = []
var body: some View {
let queryBinding = Binding<String>(get: { self.queryString }, set: {
self.queryString = $0
self.results.append(ChooserResult(icon: "app.gift", text: "lol", subText: "asdf"))
self.results.append(ChooserResult(icon: "scribble", text: "otherlol"))
})
VStack {
if (showQuery) {
HStack {
Image(systemName: "magnifyingglass")
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(.gray)
.frame(maxWidth: 30, maxHeight: 30)
.padding([.leading])
TextField("Type query...", text: queryBinding)
.font(.largeTitle)
.padding([.trailing, .top, .bottom])
// .border(.red)
}
}
if (results.count > 0) {
HStack {
List {
ForEach(results, id: \.self) { result in
HStack {
Image(systemName: result.icon ?? "arrow.forward.circle")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: 40, maxHeight: 40)
VStack {
if (result.subText != nil) {
Text(result.text)
.font(.title)
.padding([.leading, .trailing, .top])
Text(result.subText!)
.foregroundColor(.gray)
.padding([.leading, .trailing, .bottom])
} else {
Text(result.text)
.font(.title)
.padding()
}
}
Spacer()
Text("%1")
.font(.title)
.foregroundColor(.gray)
}
.padding([.leading, .trailing])
}
}
.listStyle(.plain)
// .border(.green)
if (showDetail) {
VStack {
Text("Detail here")
.padding()
// .border(.yellow)
Spacer()
// .border(.gray)
}
}
}
}
}
}
}
PlaygroundPage.current.setLiveView(ContentView())