From 6a2c8df180a210d0b6ccae7ca2f577cbcdab3774 Mon Sep 17 00:00:00 2001 From: TZGyn Date: Thu, 13 Aug 2026 09:40:51 +0800 Subject: [PATCH] Modernize the result window UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restyles the window with a cleaner layout: icon-based toolbar buttons (Copy/Save/Get All Text, highlighted OCR Selection action), a bottom status bar with progress indicator and contextual hints, monospaced text tab, and a divider separating chrome from content. 💘 Generated with Crush Assisted-by: Crush:deepseek-v4-flash-0731 --- Sources/Kapture/ResultWindow.swift | 138 +++++++++++++++++++---------- build-app.sh | 4 +- 2 files changed, 93 insertions(+), 49 deletions(-) diff --git a/Sources/Kapture/ResultWindow.swift b/Sources/Kapture/ResultWindow.swift index d3c96ed..6d09073 100644 --- a/Sources/Kapture/ResultWindow.swift +++ b/Sources/Kapture/ResultWindow.swift @@ -197,73 +197,117 @@ struct ResultView: View { let onClose: () -> Void var body: some View { - VStack(spacing: 10) { - HStack { + VStack(spacing: 0) { + // Toolbar + HStack(spacing: 10) { Picker("", selection: $model.mode) { Text("Screenshot").tag(CaptureModel.CaptureMode.screenshot) Text("Text").tag(CaptureModel.CaptureMode.text) - if model.isOCRRunning { - Text("…").tag(CaptureModel.CaptureMode.text) - } } .pickerStyle(.segmented) .fixedSize() - Spacer() - Button("Copy Image") { model.copyImage() } - Button("Save PNG…") { model.savePNG() } - if model.hasSelection { - Button("Get Selection Text") { model.runOCRSelection() } - .disabled(model.isOCRRunning) - .help("Recognize text inside the selected region") - } - Button("Get All Text") { model.runOCR() } - .disabled(model.isOCRRunning) - .help("Recognize all text in the screenshot") - Button("Close") { onClose() } - } - .padding(.horizontal, 12) - .padding(.top, 10) + Spacer() + + if model.hasSelection { + Button { + model.runOCRSelection() + } label: { + Label("OCR Selection", systemImage: "text.magnifyingglass") + } + .buttonStyle(.borderedProminent) + .disabled(model.isOCRRunning) + .help("Recognize text inside the selected region") + } + + Button { + model.runOCR() + } label: { + Label("Get All Text", systemImage: "text.viewfinder") + } + .buttonStyle(.bordered) + .disabled(model.isOCRRunning) + .help("Recognize all text in the screenshot") + + Divider().frame(height: 18) + + Button { + model.copyImage() + } label: { + Label("Copy", systemImage: "doc.on.doc") + } + .buttonStyle(.bordered) + .help("Copy image to clipboard") + + Button { + model.savePNG() + } label: { + Label("Save", systemImage: "square.and.arrow.down") + } + .buttonStyle(.bordered) + .help("Save screenshot as PNG"); + + Button { + onClose() + } label: { + Image(systemName: "xmark.circle.fill") + .foregroundStyle(.secondary) + } + .buttonStyle(.plain) + .help("Close") + } + .padding(.horizontal, 14) + .padding(.vertical, 10) + + Divider() + + // Content if model.mode == .screenshot { ScreenshotPane(model: model) - .border(Color.secondary.opacity(0.4)) - .padding(.horizontal, 12) + .padding(12) } else { - ZStack(alignment: .bottomTrailing) { + ZStack { ScrollView { Text(model.displayText) - .font(.system(.body)) + .font(.system(.body, design: .monospaced)) .textSelection(.enabled) .frame(maxWidth: .infinity, alignment: .leading) - .padding(8) + .padding(12) } - .overlay( - RoundedRectangle(cornerRadius: 6) - .stroke(Color.secondary.opacity(0.4)) - ) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + } - HStack(spacing: 8) { - if let msg = model.statusMessage { - Text(msg) - .font(.caption) - .foregroundColor(.secondary) - } - Button("Copy Text") { model.copyText() } + // Status bar + HStack(spacing: 8) { + if model.isOCRRunning { + ProgressView() + .controlSize(.small) + } + Text(model.statusMessage ?? (model.mode == .screenshot + ? (model.hasSelection ? "Region selected — click OCR Selection." : "Drag to select a region, or Get All Text.") + : "Selectable text")) + .font(.caption) + .foregroundStyle(.secondary) + .lineLimit(1) + + Spacer() + + if model.mode == .text, model.extractedText != nil { + Button { + model.copyText() + } label: { + Label("Copy Text", systemImage: "doc.on.doc") } - .padding(8) + .buttonStyle(.bordered) + .controlSize(.small) } } - - if model.statusMessage != nil && model.mode == .screenshot { - Text(model.statusMessage!) - .font(.caption) - .foregroundColor(.secondary) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 12) - } + .padding(.horizontal, 14) + .padding(.vertical, 8) + .background(.bar) } - .padding(.bottom, 10) - .frame(minWidth: 480, minHeight: 380) + .frame(minWidth: 520, minHeight: 420) } } diff --git a/build-app.sh b/build-app.sh index 02777a6..82f12ae 100755 --- a/build-app.sh +++ b/build-app.sh @@ -108,9 +108,9 @@ cat > "$APP/Contents/Info.plist" <<'PLIST' CFBundleIconFile Icon CFBundleShortVersionString - 1.2.0 + 1.2.1 CFBundleVersion - 20 + 21 LSUIElement NSHighResolutionCapable