Modernize the result window UI

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
This commit is contained in:
2026-08-13 09:40:51 +08:00
parent c9447d2a8b
commit 6a2c8df180
2 changed files with 93 additions and 49 deletions
+83 -39
View File
@@ -197,73 +197,117 @@ struct ResultView: View {
let onClose: () -> Void let onClose: () -> Void
var body: some View { var body: some View {
VStack(spacing: 10) { VStack(spacing: 0) {
HStack { // Toolbar
HStack(spacing: 10) {
Picker("", selection: $model.mode) { Picker("", selection: $model.mode) {
Text("Screenshot").tag(CaptureModel.CaptureMode.screenshot) Text("Screenshot").tag(CaptureModel.CaptureMode.screenshot)
Text("Text").tag(CaptureModel.CaptureMode.text) Text("Text").tag(CaptureModel.CaptureMode.text)
if model.isOCRRunning {
Text("…").tag(CaptureModel.CaptureMode.text)
}
} }
.pickerStyle(.segmented) .pickerStyle(.segmented)
.fixedSize() .fixedSize()
Spacer() Spacer()
Button("Copy Image") { model.copyImage() }
Button("Save PNG…") { model.savePNG() }
if model.hasSelection { if model.hasSelection {
Button("Get Selection Text") { model.runOCRSelection() } Button {
model.runOCRSelection()
} label: {
Label("OCR Selection", systemImage: "text.magnifyingglass")
}
.buttonStyle(.borderedProminent)
.disabled(model.isOCRRunning) .disabled(model.isOCRRunning)
.help("Recognize text inside the selected region") .help("Recognize text inside the selected region")
} }
Button("Get All Text") { model.runOCR() }
Button {
model.runOCR()
} label: {
Label("Get All Text", systemImage: "text.viewfinder")
}
.buttonStyle(.bordered)
.disabled(model.isOCRRunning) .disabled(model.isOCRRunning)
.help("Recognize all text in the screenshot") .help("Recognize all text in the screenshot")
Button("Close") { onClose() }
}
.padding(.horizontal, 12)
.padding(.top, 10)
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 { if model.mode == .screenshot {
ScreenshotPane(model: model) ScreenshotPane(model: model)
.border(Color.secondary.opacity(0.4)) .padding(12)
.padding(.horizontal, 12)
} else { } else {
ZStack(alignment: .bottomTrailing) { ZStack {
ScrollView { ScrollView {
Text(model.displayText) Text(model.displayText)
.font(.system(.body)) .font(.system(.body, design: .monospaced))
.textSelection(.enabled) .textSelection(.enabled)
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.padding(8) .padding(12)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
} }
.overlay(
RoundedRectangle(cornerRadius: 6)
.stroke(Color.secondary.opacity(0.4))
)
// Status bar
HStack(spacing: 8) { HStack(spacing: 8) {
if let msg = model.statusMessage { if model.isOCRRunning {
Text(msg) 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) .font(.caption)
.foregroundColor(.secondary) .foregroundStyle(.secondary)
} .lineLimit(1)
Button("Copy Text") { model.copyText() }
}
.padding(8)
}
}
if model.statusMessage != nil && model.mode == .screenshot { Spacer()
Text(model.statusMessage!)
.font(.caption) if model.mode == .text, model.extractedText != nil {
.foregroundColor(.secondary) Button {
.frame(maxWidth: .infinity, alignment: .leading) model.copyText()
.padding(.horizontal, 12) } label: {
Label("Copy Text", systemImage: "doc.on.doc")
}
.buttonStyle(.bordered)
.controlSize(.small)
} }
} }
.padding(.bottom, 10) .padding(.horizontal, 14)
.frame(minWidth: 480, minHeight: 380) .padding(.vertical, 8)
.background(.bar)
}
.frame(minWidth: 520, minHeight: 420)
} }
} }
+2 -2
View File
@@ -108,9 +108,9 @@ cat > "$APP/Contents/Info.plist" <<'PLIST'
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>Icon</string> <string>Icon</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.2.0</string> <string>1.2.1</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>20</string> <string>21</string>
<key>LSUIElement</key> <key>LSUIElement</key>
<true/> <true/>
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>