feat(app): support local screenshot actions
This commit is contained in:
@@ -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"
|
||||
/>
|
||||
|
||||
|
||||
@@ -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 & 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;
|
||||
|
||||
Vendored
+10
@@ -13,6 +13,10 @@ export function ConfirmNativeRegion(arg1:main.CaptureResult):Promise<void>;
|
||||
|
||||
export function ConfirmRegion(arg1:main.CaptureResult):Promise<void>;
|
||||
|
||||
export function CopyNativeRegionImage(arg1:main.CaptureResult):Promise<void>;
|
||||
|
||||
export function CopyRegionImage(arg1:main.CaptureResult):Promise<void>;
|
||||
|
||||
export function GetConfig():Promise<domain.AppConfig>;
|
||||
|
||||
export function QuitApp():Promise<void>;
|
||||
@@ -21,6 +25,12 @@ export function RetryRegisterHotkey():Promise<void>;
|
||||
|
||||
export function SaveConfig(arg1:domain.AppConfig):Promise<void>;
|
||||
|
||||
export function SaveNativeRegionImage(arg1:main.CaptureResult):Promise<main.CaptureActionResult>;
|
||||
|
||||
export function SaveNativeRegionImageToDir(arg1:main.CaptureResult,arg2:string):Promise<main.CaptureActionResult>;
|
||||
|
||||
export function SaveRegionImage(arg1:main.CaptureResult):Promise<main.CaptureActionResult>;
|
||||
|
||||
export function ShowWindow():Promise<void>;
|
||||
|
||||
export function TestConnection(arg1:domain.S3Config):Promise<void>;
|
||||
|
||||
@@ -22,6 +22,14 @@ export function ConfirmRegion(arg1) {
|
||||
return window['go']['main']['App']['ConfirmRegion'](arg1);
|
||||
}
|
||||
|
||||
export function CopyNativeRegionImage(arg1) {
|
||||
return window['go']['main']['App']['CopyNativeRegionImage'](arg1);
|
||||
}
|
||||
|
||||
export function CopyRegionImage(arg1) {
|
||||
return window['go']['main']['App']['CopyRegionImage'](arg1);
|
||||
}
|
||||
|
||||
export function GetConfig() {
|
||||
return window['go']['main']['App']['GetConfig']();
|
||||
}
|
||||
@@ -38,6 +46,18 @@ export function SaveConfig(arg1) {
|
||||
return window['go']['main']['App']['SaveConfig'](arg1);
|
||||
}
|
||||
|
||||
export function SaveNativeRegionImage(arg1) {
|
||||
return window['go']['main']['App']['SaveNativeRegionImage'](arg1);
|
||||
}
|
||||
|
||||
export function SaveNativeRegionImageToDir(arg1, arg2) {
|
||||
return window['go']['main']['App']['SaveNativeRegionImageToDir'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function SaveRegionImage(arg1) {
|
||||
return window['go']['main']['App']['SaveRegionImage'](arg1);
|
||||
}
|
||||
|
||||
export function ShowWindow() {
|
||||
return window['go']['main']['App']['ShowWindow']();
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
export namespace application {
|
||||
|
||||
|
||||
export class Point {
|
||||
x: number;
|
||||
y: number;
|
||||
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new Point(source);
|
||||
}
|
||||
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.x = source["x"];
|
||||
@@ -18,18 +18,18 @@ export namespace application {
|
||||
tool: string;
|
||||
color: string;
|
||||
points: Point[];
|
||||
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new Annotation(source);
|
||||
}
|
||||
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.tool = source["tool"];
|
||||
this.color = source["color"];
|
||||
this.points = this.convertValues(source["points"], Point);
|
||||
}
|
||||
|
||||
|
||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||
if (!a) {
|
||||
return a;
|
||||
@@ -52,7 +52,7 @@ export namespace application {
|
||||
}
|
||||
|
||||
export namespace domain {
|
||||
|
||||
|
||||
export class S3Config {
|
||||
endpoint: string;
|
||||
region: string;
|
||||
@@ -62,11 +62,11 @@ export namespace domain {
|
||||
pathPrefix: string;
|
||||
publicUrlBase: string;
|
||||
usePathStyle: boolean;
|
||||
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new S3Config(source);
|
||||
}
|
||||
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.endpoint = source["endpoint"];
|
||||
@@ -82,17 +82,17 @@ export namespace domain {
|
||||
export class AppConfig {
|
||||
hotkey: string;
|
||||
s3: S3Config;
|
||||
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new AppConfig(source);
|
||||
}
|
||||
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.hotkey = source["hotkey"];
|
||||
this.s3 = this.convertValues(source["s3"], S3Config);
|
||||
}
|
||||
|
||||
|
||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||
if (!a) {
|
||||
return a;
|
||||
@@ -115,17 +115,31 @@ export namespace domain {
|
||||
}
|
||||
|
||||
export namespace main {
|
||||
|
||||
|
||||
export class CaptureActionResult {
|
||||
completed: boolean;
|
||||
path?: string;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new CaptureActionResult(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.completed = source["completed"];
|
||||
this.path = source["path"];
|
||||
}
|
||||
}
|
||||
export class RegionRect {
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new RegionRect(source);
|
||||
}
|
||||
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.x = source["x"];
|
||||
@@ -137,17 +151,17 @@ export namespace main {
|
||||
export class CaptureResult {
|
||||
rect: RegionRect;
|
||||
annotations: application.Annotation[];
|
||||
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new CaptureResult(source);
|
||||
}
|
||||
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.rect = this.convertValues(source["rect"], RegionRect);
|
||||
this.annotations = this.convertValues(source["annotations"], application.Annotation);
|
||||
}
|
||||
|
||||
|
||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||
if (!a) {
|
||||
return a;
|
||||
|
||||
Reference in New Issue
Block a user