feat(app): support local screenshot actions

This commit is contained in:
2026-06-04 01:05:28 +08:00
parent c45864e44c
commit 1d52d154fd
11 changed files with 662 additions and 108 deletions
+48
View File
@@ -21,6 +21,8 @@ import { EventsOn, EventsOff } from '../wailsjs/runtime/runtime'
import {
RetryRegisterHotkey,
ConfirmRegion,
CopyRegionImage,
SaveRegionImage,
CancelRegion,
} from '../wailsjs/go/main/App'
@@ -85,6 +87,50 @@ async function onOverlayConfirm(rect: {
}
}
async function onOverlayCopy(rect: {
rect: {
x: number
y: number
w: number
h: number
}
annotations: Array<{
tool: string
color: string
points: Array<{ x: number; y: number }>
}>
}) {
mode.value = 'settings'
overlayPayload.value = null
try {
await CopyRegionImage(rect as any)
} catch {
/* Surfaced via upload:failure */
}
}
async function onOverlaySave(rect: {
rect: {
x: number
y: number
w: number
h: number
}
annotations: Array<{
tool: string
color: string
points: Array<{ x: number; y: number }>
}>
}) {
mode.value = 'settings'
overlayPayload.value = null
try {
await SaveRegionImage(rect as any)
} catch {
/* Surfaced via upload:failure */
}
}
async function onOverlayCancel() {
mode.value = 'settings'
overlayPayload.value = null
@@ -143,6 +189,8 @@ onUnmounted(() => {
:width="overlayPayload.cssWidth"
:height="overlayPayload.cssHeight"
@confirm="onOverlayConfirm"
@copy="onOverlayCopy"
@save="onOverlaySave"
@cancel="onOverlayCancel"
/>
+49 -4
View File
@@ -30,6 +30,14 @@ const emit = defineEmits<{
e: 'confirm',
payload: { rect: Rect; annotations: Annotation[] }
): void
(
e: 'copy',
payload: { rect: Rect; annotations: Annotation[] }
): void
(
e: 'save',
payload: { rect: Rect; annotations: Annotation[] }
): void
(e: 'cancel'): void
}>()
@@ -92,7 +100,7 @@ const sizeLabel = computed(() => {
const rightToolbarPos = computed(() => {
if (!rect.value) return null
return placeToolbar(rect.value, 220, 40, 'right')
return placeToolbar(rect.value, 304, 40, 'right')
})
const leftToolbarPos = computed(() => {
@@ -218,6 +226,11 @@ function onSelectionMouseDown(e: MouseEvent) {
if (e.button !== 0 || !rect.value) return
e.stopPropagation()
paletteOpen.value = false
if (e.detail >= 2) {
removeSinglePointAnnotation()
onCopy()
return
}
const p = pointFromEvent(e)
const handle = hitHandle(p)
if (handle) {
@@ -312,11 +325,26 @@ function chooseColor(color: string) {
}
function onConfirm() {
emitAction('confirm')
}
function onCopy() {
emitAction('copy')
}
function onSave() {
emitAction('save')
}
function emitAction(action: 'confirm' | 'copy' | 'save') {
if (!rect.value) return
emit('confirm', {
const payload = {
rect: { ...rect.value },
annotations: annotations.value,
})
}
if (action === 'confirm') emit('confirm', payload)
if (action === 'copy') emit('copy', payload)
if (action === 'save') emit('save', payload)
}
function onCancel() {
@@ -337,6 +365,13 @@ function undoAnnotation() {
annotations.value.pop()
}
function removeSinglePointAnnotation() {
const last = annotations.value[annotations.value.length - 1]
if (last && last.tool === activeTool.value && last.points.length <= 1) {
annotations.value.pop()
}
}
onMounted(() => {
window.addEventListener('keydown', onKeydown)
})
@@ -522,6 +557,9 @@ onUnmounted(() => {
@mousedown.stop
>
<button class="btn cancel" @click="onCancel" title="Esc">Cancel</button>
<button class="btn secondary" @click="onSave" title="Save to folder">
Save
</button>
<button class="btn primary" @click="onConfirm" title="Enter">
Upload &amp; copy
</button>
@@ -612,7 +650,7 @@ onUnmounted(() => {
width: 190px;
}
.action-toolbar {
width: 220px;
width: 304px;
}
.btn,
@@ -636,6 +674,13 @@ onUnmounted(() => {
.btn.cancel:hover {
background: rgba(255, 255, 255, 0.08);
}
.btn.secondary {
background: rgba(255, 255, 255, 0.12);
color: #fff;
}
.btn.secondary:hover {
background: rgba(255, 255, 255, 0.18);
}
.btn.primary {
background: #3b82f6;
color: #fff;