Make the composer wrap and grow, and surface Launch at Login
Long prompts hit a single-line field before; the composer is now an NSTextView that wraps and grows up to seven lines, keeps Return as send, and uses Shift+Return for a newline. Launch at Login already existed in the menu bar icon's right-click menu, so it is now also a toggle in the sync panel where it is easier to find.
This commit is contained in:
@@ -7,6 +7,8 @@ struct PanelView: View {
|
||||
@ObservedObject private var sync = SyncService.shared
|
||||
|
||||
@State private var composer = ""
|
||||
@State private var composerFocused = false
|
||||
@State private var composerHeight: CGFloat = ComposerView.oneLineHeight
|
||||
@State private var search = ""
|
||||
@State private var showSearch = false
|
||||
@State private var showSectionSwitcher = false
|
||||
@@ -19,7 +21,7 @@ struct PanelView: View {
|
||||
@State private var copiedID: UUID?
|
||||
@State private var accessibilityGranted = AXIsProcessTrusted()
|
||||
|
||||
private enum Field: Hashable { case composer, search, newWorkspace }
|
||||
private enum Field: Hashable { case search, newWorkspace }
|
||||
@FocusState private var focusedField: Field?
|
||||
|
||||
var body: some View {
|
||||
@@ -47,10 +49,10 @@ struct PanelView: View {
|
||||
.overlay(newWorkspaceModal)
|
||||
.onDrop(of: [UTType.image.identifier, UTType.fileURL.identifier], isTargeted: nil, perform: handleDrop)
|
||||
.onReceive(NotificationCenter.default.publisher(for: .promptPanelDidShow)) { _ in
|
||||
focusedField = .composer
|
||||
composerFocused = true
|
||||
accessibilityGranted = AXIsProcessTrusted()
|
||||
}
|
||||
.onAppear { focusedField = .composer }
|
||||
.onAppear { composerFocused = true }
|
||||
}
|
||||
|
||||
// MARK: - Header
|
||||
@@ -120,7 +122,7 @@ struct PanelView: View {
|
||||
.onExitCommand {
|
||||
search = ""
|
||||
showSearch = false
|
||||
focusedField = .composer
|
||||
composerFocused = true
|
||||
}
|
||||
if !search.isEmpty {
|
||||
Button { search = "" } label: { Image(systemName: "xmark.circle.fill") }
|
||||
@@ -473,6 +475,12 @@ struct PanelView: View {
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
Divider()
|
||||
Toggle("Launch at Login", isOn: Binding(
|
||||
get: { LoginItem.isEnabled },
|
||||
set: { _ in _ = LoginItem.toggle() }
|
||||
))
|
||||
.font(.callout)
|
||||
if let error = sync.lastError {
|
||||
Text(error)
|
||||
.font(.caption)
|
||||
@@ -548,7 +556,7 @@ struct PanelView: View {
|
||||
private func dismissNewWorkspace() {
|
||||
showNewWorkspace = false
|
||||
newWorkspaceName = ""
|
||||
focusedField = .composer
|
||||
composerFocused = true
|
||||
}
|
||||
|
||||
// MARK: - Selection
|
||||
@@ -615,28 +623,32 @@ struct PanelView: View {
|
||||
// MARK: - Composer
|
||||
|
||||
private var composerField: some View {
|
||||
HStack(spacing: 8) {
|
||||
TextField("Add a note or prompt (\(store.activeSection.name))", text: $composer)
|
||||
.textFieldStyle(.plain)
|
||||
.focused($focusedField, equals: .composer)
|
||||
.onSubmit(submit)
|
||||
.onExitCommand {
|
||||
// Esc clears a selection first, and only hides the panel
|
||||
// once there is nothing selected.
|
||||
HStack(alignment: .bottom, spacing: 8) {
|
||||
ComposerView(
|
||||
text: $composer,
|
||||
isFocused: $composerFocused,
|
||||
height: $composerHeight,
|
||||
placeholder: "Add a note or prompt (\(store.activeSection.name))",
|
||||
onSubmit: submit,
|
||||
onEscape: {
|
||||
if selection.isEmpty {
|
||||
PanelController.shared.hide()
|
||||
} else {
|
||||
clearSelection()
|
||||
}
|
||||
}
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: composerHeight)
|
||||
if !composer.isEmpty {
|
||||
Button(action: submit) { Image(systemName: "arrow.up.circle.fill") }
|
||||
.buttonStyle(.plain)
|
||||
.foregroundStyle(Color.accentColor)
|
||||
.help("Add (Return; Shift+Return for a new line)")
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 10)
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
|
||||
private func submit() {
|
||||
@@ -663,7 +675,7 @@ struct PanelView: View {
|
||||
withAnimation(.easeInOut(duration: 0.15)) { showSectionSwitcher.toggle() }
|
||||
}
|
||||
.keyboardShortcut("k", modifiers: .command)
|
||||
Button("") { focusedField = .composer }
|
||||
Button("") { composerFocused = true }
|
||||
.keyboardShortcut("n", modifiers: .command)
|
||||
Button("") {
|
||||
withAnimation(.easeInOut(duration: 0.15)) { showSync.toggle() }
|
||||
@@ -739,7 +751,7 @@ struct PanelView: View {
|
||||
focusedField = .search
|
||||
} else {
|
||||
search = ""
|
||||
focusedField = .composer
|
||||
composerFocused = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user