From 12a6cc2a52397bc6b5b3b6a2a111b402d7ecdca3 Mon Sep 17 00:00:00 2001 From: jess Date: Mon, 6 Apr 2026 15:33:51 -0700 Subject: [PATCH] sidebar: single-click opens note, delete key works, space previews --- src/SidebarView.swift | 57 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/src/SidebarView.swift b/src/SidebarView.swift index 75c29f5..4a83d61 100644 --- a/src/SidebarView.swift +++ b/src/SidebarView.swift @@ -3,6 +3,8 @@ import SwiftUI struct SidebarView: View { @ObservedObject var state: AppState @State private var lastClickedID: UUID? + @State private var previewNote: NoteInfo? + @FocusState private var sidebarFocused: Bool private let dateFormatter: DateFormatter = { let f = DateFormatter() @@ -49,9 +51,6 @@ struct SidebarView: View { dateFormatter: dateFormatter ) .contentShape(Rectangle()) - .onTapGesture(count: 2) { - state.openNote(note.id) - } .onTapGesture(count: 1) { handleClick(note: note, index: index) } @@ -68,11 +67,29 @@ struct SidebarView: View { } } } + .focusable() + .focused($sidebarFocused) .onDeleteCommand { guard !state.selectedNoteIDs.isEmpty else { return } state.deleteNotes(state.selectedNoteIDs) lastClickedID = nil } + .onKeyPress(.space) { + guard let id = state.selectedNoteIDs.first, + state.selectedNoteIDs.count == 1, + let note = state.noteList.first(where: { $0.id == id }) else { + return .ignored + } + if previewNote?.id == note.id { + previewNote = nil + } else { + previewNote = note + } + return .handled + } + .popover(item: $previewNote, arrowEdge: .trailing) { note in + NotePreviewView(note: note, state: state) + } } } .background(Color(ns: Theme.current.base)) @@ -80,6 +97,7 @@ struct SidebarView: View { } private func handleClick(note: NoteInfo, index: Int) { + sidebarFocused = true let flags = NSEvent.modifierFlags if flags.contains(.command) { state.selectNote(note.id, extend: true) @@ -95,11 +113,44 @@ struct SidebarView: View { } } else { state.selectNote(note.id) + state.openNote(note.id) lastClickedID = note.id } } } +struct NotePreviewView: View { + let note: NoteInfo + @ObservedObject var state: AppState + + var body: some View { + VStack(alignment: .leading, spacing: 8) { + Text(note.title) + .font(.headline) + .foregroundColor(Color(ns: Theme.current.text)) + Divider() + ScrollView { + Text(previewText) + .font(.body) + .foregroundColor(Color(ns: Theme.current.subtext0)) + .frame(maxWidth: .infinity, alignment: .leading) + } + } + .padding() + .frame(width: 320, height: 240) + .background(Color(ns: Theme.current.base)) + } + + private var previewText: String { + let bridge = RustBridge.shared + if bridge.cacheLoad(note.id) { + let text = bridge.getText(note.id) + return String(text.prefix(2000)) + } + return "(unable to load preview)" + } +} + struct NoteRow: View { let note: NoteInfo let isSelected: Bool