hammerspoon icon indicating copy to clipboard operation
hammerspoon copied to clipboard

hs.chooser enhancements

Open bviefhues opened this issue 2 years ago • 11 comments

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 to completionFn
  • Optionally show a help text (below the chooser? Tooltip?) to explain what happens when chooser is dismissed

bviefhues avatar Aug 15 '22 15:08 bviefhues

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!

cmsj avatar Aug 21 '22 15:08 cmsj

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())

cmsj avatar Aug 22 '22 08:08 cmsj