Desktop: every write shows a styled in-app dry-run preview (command, changed rows) before the native confirm dialog; i18n house style fix for the developer id hint

This commit is contained in:
CRTkafa 2026-10-23 09:48:48 +08:00
parent c86b583830
commit 364b8ec0d4
7 changed files with 78 additions and 2 deletions

View file

@ -1,6 +1,7 @@
// App data shared by every screen: app folders, studios, store accounts and the apps they see, the pairing / ignore
// overrides, settings, the sidecar, the portfolio (offline check + the last live read from the cache), app icons, and
// background jobs shown as toasts with progress and cancel.
import { askPreview } from './ui/DryRunPreview';
import { createContext, type ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import {
type Account, type AccountCheck, api, type AppInfo, type AppsListResult, type AppStatus, type CacheEntry, DEFAULT_SETTINGS, errorText, newJob, onDownload,
@ -573,6 +574,10 @@ export function useWrite(projectId: string | null) {
setBusy(key);
const tid = d.toast({ id: job, kind: 'job', title: w.title, detail: t('write.dryRunning'), progress: null, job });
try {
// the in-app preview of the dry run first (readable, styled); the host's native dialog stays the real gate
const dry = await api.call<ToolResult>(w.method, projectId, { args: w.args }, job);
if (!dry.ok) { d.updateToast(tid, { kind: 'bad', title: t('write.dryFailed'), detail: withHint(failureText(dry)), progress: undefined, job: undefined }); return null; }
if (!(await askPreview(w.title, dry))) { d.updateToast(tid, { kind: 'info', title: t('write.notApplied'), detail: t('write.notAppliedDetail'), progress: undefined, job: undefined }); return null; }
const o = await api.writeWithConfirm(w.method, projectId, w.args, job);
if (o.stage === 'dry-run') d.updateToast(tid, { kind: 'bad', title: t('write.dryFailed'), detail: withHint(failureText(o.dryRun)), progress: undefined, job: undefined });
else if (o.stage === 'dialog') d.updateToast(tid, { kind: 'info', title: t('write.notApplied'), detail: t('write.notAppliedDetail'), progress: undefined, job: undefined });