mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
fix: update error\warning flow
This commit is contained in:
@@ -114,6 +114,16 @@
|
|||||||
|
|
||||||
## UI и качество
|
## UI и качество
|
||||||
|
|
||||||
|
- [ ] **обдумать агрегацию предупреждений на тайле** — сейчас разрешено два
|
||||||
|
бейджа рядом (derived `resultNote` + runtime-warnings); после
|
||||||
|
использования решить, нужен ли один сводный бейдж со счётчиком и списком
|
||||||
|
- [ ] **лимит КБ/качество как авто-шаг пайплайна** — вынести size limit/quality
|
||||||
|
из меню Download в автоматический инструмент цепочки, который применяет
|
||||||
|
выбранные настройки (сжатие видно в превью и в цепочке, ошибки
|
||||||
|
недостижимости ложатся на тайл шага). Нужен флоу передачи индикатора из
|
||||||
|
такого шага в кнопку Download (ошибка/предупреждение/итоговый размер).
|
||||||
|
Связано с пунктами про индикацию активного сжатия и превью итогового
|
||||||
|
результата
|
||||||
- [ ] кнопку редактирования названия пайплайна на этой же странице
|
- [ ] кнопку редактирования названия пайплайна на этой же странице
|
||||||
- [ ] при загрузке нескольких файлов, показывает source не той же высоты, как
|
- [ ] при загрузке нескольких файлов, показывает source не той же высоты, как
|
||||||
result
|
result
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
// Runtime warnings (chain/download events): shown as badges next to the
|
// Runtime warnings (chain/download events): shown as badges next to the
|
||||||
// derived result note, but from a different source.
|
// derived result note, but from a different source.
|
||||||
warnings?: string[];
|
warnings?: string[];
|
||||||
|
// Runtime errors: danger badges; detail goes to the native tooltip until
|
||||||
|
// a popover with full text exists.
|
||||||
|
errors?: { label: string; detail?: string }[];
|
||||||
actions?: Snippet;
|
actions?: Snippet;
|
||||||
}
|
}
|
||||||
let {
|
let {
|
||||||
@@ -31,6 +34,7 @@
|
|||||||
note = undefined,
|
note = undefined,
|
||||||
noteTone = "warning",
|
noteTone = "warning",
|
||||||
warnings = [],
|
warnings = [],
|
||||||
|
errors = [],
|
||||||
actions = undefined,
|
actions = undefined,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
@@ -56,6 +60,14 @@
|
|||||||
{#if note}
|
{#if note}
|
||||||
<Badge tone={noteTone} label={note} />
|
<Badge tone={noteTone} label={note} />
|
||||||
{/if}
|
{/if}
|
||||||
|
{#each errors as error (error.label + (error.detail ?? ""))}
|
||||||
|
<Badge
|
||||||
|
tone="danger"
|
||||||
|
label={error.label}
|
||||||
|
title={error.detail}
|
||||||
|
role="alert"
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
{#each warnings as warning (warning)}
|
{#each warnings as warning (warning)}
|
||||||
<Badge tone="warning" label={warning} role="status" />
|
<Badge tone="warning" label={warning} role="status" />
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import DownloadButton from "$lib/components/ui/DownloadButton.svelte";
|
import DownloadButton from "$lib/components/ui/DownloadButton.svelte";
|
||||||
import UploadButton from "$lib/components/ui/UploadButton.svelte";
|
import UploadButton from "$lib/components/ui/UploadButton.svelte";
|
||||||
|
import Badge from "$lib/components/ui/Badge.svelte";
|
||||||
import type { OutputMime } from "$lib/core/io";
|
import type { OutputMime } from "$lib/core/io";
|
||||||
import { outputFormatByMime } from "$lib/output-formats";
|
import { outputFormatByMime } from "$lib/output-formats";
|
||||||
import { t } from "$lib/i18n/t";
|
import { t } from "$lib/i18n/t";
|
||||||
@@ -16,6 +17,9 @@
|
|||||||
quality?: number;
|
quality?: number;
|
||||||
limitKb?: number;
|
limitKb?: number;
|
||||||
alphaLoss?: boolean;
|
alphaLoss?: boolean;
|
||||||
|
// Download-zone feedback: size-limit misses and action failures.
|
||||||
|
warnings?: string[];
|
||||||
|
error?: { label: string; detail?: string } | null;
|
||||||
onupload: (file: File) => void;
|
onupload: (file: File) => void;
|
||||||
ondownload: () => void;
|
ondownload: () => void;
|
||||||
onformat?: (mime: OutputMime) => void;
|
onformat?: (mime: OutputMime) => void;
|
||||||
@@ -31,6 +35,8 @@
|
|||||||
quality = undefined,
|
quality = undefined,
|
||||||
limitKb = undefined,
|
limitKb = undefined,
|
||||||
alphaLoss = false,
|
alphaLoss = false,
|
||||||
|
warnings = [],
|
||||||
|
error = null,
|
||||||
onupload,
|
onupload,
|
||||||
ondownload,
|
ondownload,
|
||||||
onformat,
|
onformat,
|
||||||
@@ -61,6 +67,17 @@
|
|||||||
disabled={running}
|
disabled={running}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#each warnings as warning (warning)}
|
||||||
|
<Badge tone="warning" label={warning} role="status" />
|
||||||
|
{/each}
|
||||||
|
{#if error}
|
||||||
|
<Badge
|
||||||
|
tone="danger"
|
||||||
|
label={error.label}
|
||||||
|
title={error.detail}
|
||||||
|
role="alert"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if canDownload && alphaLoss}
|
{#if canDownload && alphaLoss}
|
||||||
<p class="alpha-warning" role="status">
|
<p class="alpha-warning" role="status">
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
result: PixelImage | null;
|
result: PixelImage | null;
|
||||||
resultNote?: ResultNote | null;
|
resultNote?: ResultNote | null;
|
||||||
warnings?: string[];
|
warnings?: string[];
|
||||||
|
errors?: { label: string; detail?: string }[];
|
||||||
fileResult?: FileResult | null;
|
fileResult?: FileResult | null;
|
||||||
textResult?: string | null;
|
textResult?: string | null;
|
||||||
textVars?: Record<string, string | number>;
|
textVars?: Record<string, string | number>;
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
result,
|
result,
|
||||||
resultNote = null,
|
resultNote = null,
|
||||||
warnings = [],
|
warnings = [],
|
||||||
|
errors = [],
|
||||||
fileResult = null,
|
fileResult = null,
|
||||||
textResult = null,
|
textResult = null,
|
||||||
textVars = undefined,
|
textVars = undefined,
|
||||||
@@ -71,6 +73,7 @@
|
|||||||
note={resultNote ? t(resultNote.key) : undefined}
|
note={resultNote ? t(resultNote.key) : undefined}
|
||||||
noteTone={resultNote?.tone ?? "warning"}
|
noteTone={resultNote?.tone ?? "warning"}
|
||||||
{warnings}
|
{warnings}
|
||||||
|
{errors}
|
||||||
>
|
>
|
||||||
{#snippet actions()}
|
{#snippet actions()}
|
||||||
{#if ontogglemask}
|
{#if ontogglemask}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
textSource?: string;
|
textSource?: string;
|
||||||
running?: boolean;
|
running?: boolean;
|
||||||
fileCount?: number;
|
fileCount?: number;
|
||||||
|
warnings?: string[];
|
||||||
|
errors?: { label: string; detail?: string }[];
|
||||||
ontextinput?: (text: string) => void;
|
ontextinput?: (text: string) => void;
|
||||||
onrendertext?: () => void;
|
onrendertext?: () => void;
|
||||||
onupload?: (file: File) => void;
|
onupload?: (file: File) => void;
|
||||||
@@ -27,6 +29,8 @@
|
|||||||
textSource = "",
|
textSource = "",
|
||||||
running = false,
|
running = false,
|
||||||
fileCount = 0,
|
fileCount = 0,
|
||||||
|
warnings = [],
|
||||||
|
errors = [],
|
||||||
ontextinput,
|
ontextinput,
|
||||||
onrendertext,
|
onrendertext,
|
||||||
onupload,
|
onupload,
|
||||||
@@ -83,7 +87,13 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<PreviewTile label={t("sourceCard.source")} viewMode={mode} dims={sourceDims}>
|
<PreviewTile
|
||||||
|
label={t("sourceCard.source")}
|
||||||
|
viewMode={mode}
|
||||||
|
dims={sourceDims}
|
||||||
|
{warnings}
|
||||||
|
{errors}
|
||||||
|
>
|
||||||
{#if mode === "text"}
|
{#if mode === "text"}
|
||||||
<div class="text-source-wrap">
|
<div class="text-source-wrap">
|
||||||
<SchemaTextSource
|
<SchemaTextSource
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
import { createOutputControls } from "./output-controls.svelte";
|
import { createOutputControls } from "./output-controls.svelte";
|
||||||
import { hasPreviewResult } from "./schema-preview-model";
|
import { hasPreviewResult } from "./schema-preview-model";
|
||||||
import { createSchemaToolRunner } from "./schema-tool-runner.svelte";
|
import { createSchemaToolRunner } from "./schema-tool-runner.svelte";
|
||||||
|
import type { DisplayError } from "./schema-tool-runner.svelte";
|
||||||
import {
|
import {
|
||||||
createSchemaToolState,
|
createSchemaToolState,
|
||||||
toolSchemaOf,
|
toolSchemaOf,
|
||||||
@@ -63,7 +64,7 @@
|
|||||||
setSteps: (v) => (stepState.steps = v),
|
setSteps: (v) => (stepState.steps = v),
|
||||||
touchedFor: (key) => stepState.touchedFor(key),
|
touchedFor: (key) => stepState.touchedFor(key),
|
||||||
reportError: (e) => runner.reportError(e),
|
reportError: (e) => runner.reportError(e),
|
||||||
clearError: () => (runner.displayError = null),
|
clearError: () => runner.clearSourceError(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const stepState = createSchemaToolState({
|
const stepState = createSchemaToolState({
|
||||||
@@ -122,12 +123,36 @@
|
|||||||
const stepResults = $derived(runner.stepResults);
|
const stepResults = $derived(runner.stepResults);
|
||||||
const stepFileSets = $derived(runner.stepFileSets);
|
const stepFileSets = $derived(runner.stepFileSets);
|
||||||
const runWarnings = $derived(runner.runWarnings);
|
const runWarnings = $derived(runner.runWarnings);
|
||||||
const displayError = $derived(runner.displayError);
|
// Feedback zones: source tile / step tiles / download button area.
|
||||||
const warningTexts = $derived(
|
const sourceWarningTexts = $derived(
|
||||||
[...upload.sourceWarnings, ...runWarnings, ...runner.downloadWarnings].map(
|
upload.sourceWarnings.map(chainWarningText),
|
||||||
chainWarningText,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
const warningsByStep = $derived.by(() => {
|
||||||
|
const byStep: string[][] = steps.map(() => []);
|
||||||
|
for (const w of runWarnings) {
|
||||||
|
if ("step" in w && w.step >= 1 && w.step <= byStep.length) {
|
||||||
|
byStep[w.step - 1].push(chainWarningText(w));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return byStep;
|
||||||
|
});
|
||||||
|
const downloadWarningTexts = $derived(
|
||||||
|
runner.downloadWarnings.map(chainWarningText),
|
||||||
|
);
|
||||||
|
const stepError = $derived(runner.stepError);
|
||||||
|
const sourceError = $derived(runner.sourceError);
|
||||||
|
const actionError = $derived(runner.actionError);
|
||||||
|
|
||||||
|
function displayText(e: DisplayError | null): string {
|
||||||
|
if (!e) return "";
|
||||||
|
return e.kind === "i18n" ? t(e.key, e.vars) : e.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorBadge(e: DisplayError | null) {
|
||||||
|
return e
|
||||||
|
? [{ label: t("actions.actionFailed"), detail: displayText(e) }]
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
const masks = createStepMasks({
|
const masks = createStepMasks({
|
||||||
steps: () => steps,
|
steps: () => steps,
|
||||||
@@ -176,14 +201,6 @@
|
|||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
const errorText = $derived.by(() => {
|
|
||||||
const current = displayError;
|
|
||||||
if (!current) return "";
|
|
||||||
return current.kind === "i18n"
|
|
||||||
? t(current.key, current.vars)
|
|
||||||
: current.text;
|
|
||||||
});
|
|
||||||
|
|
||||||
const debouncedRun = debounce(() => run(), 200);
|
const debouncedRun = debounce(() => run(), 200);
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
@@ -288,6 +305,8 @@
|
|||||||
textSource={upload.textSource}
|
textSource={upload.textSource}
|
||||||
running={busy}
|
running={busy}
|
||||||
fileCount={upload.sourceFiles.length}
|
fileCount={upload.sourceFiles.length}
|
||||||
|
warnings={sourceWarningTexts}
|
||||||
|
errors={errorBadge(sourceError)}
|
||||||
ontextinput={(v) => (upload.textSource = v)}
|
ontextinput={(v) => (upload.textSource = v)}
|
||||||
onrendertext={run}
|
onrendertext={run}
|
||||||
onupload={upload.handleFile}
|
onupload={upload.handleFile}
|
||||||
@@ -320,7 +339,10 @@
|
|||||||
resultKind={displayResultKind}
|
resultKind={displayResultKind}
|
||||||
result={out}
|
result={out}
|
||||||
{resultNote}
|
{resultNote}
|
||||||
warnings={warningTexts}
|
warnings={warningsByStep[i] ?? []}
|
||||||
|
errors={stepError && stepError.step === i
|
||||||
|
? [{ label: stepError.label, detail: stepError.detail }]
|
||||||
|
: []}
|
||||||
{fileResult}
|
{fileResult}
|
||||||
{textResult}
|
{textResult}
|
||||||
textVars={verdictVars}
|
textVars={verdictVars}
|
||||||
@@ -341,6 +363,10 @@
|
|||||||
viewMode="image"
|
viewMode="image"
|
||||||
dims={out ? `${out.width} × ${out.height}` : undefined}
|
dims={out ? `${out.width} × ${out.height}` : undefined}
|
||||||
parts={outSet.length > 1 ? outSet.length : undefined}
|
parts={outSet.length > 1 ? outSet.length : undefined}
|
||||||
|
warnings={warningsByStep[i] ?? []}
|
||||||
|
errors={stepError && stepError.step === i
|
||||||
|
? [{ label: stepError.label, detail: stepError.detail }]
|
||||||
|
: []}
|
||||||
>
|
>
|
||||||
{#snippet actions()}
|
{#snippet actions()}
|
||||||
{@render maskChip(i)}
|
{@render maskChip(i)}
|
||||||
@@ -381,6 +407,13 @@
|
|||||||
quality={output.quality}
|
quality={output.quality}
|
||||||
limitKb={output.limitKb}
|
limitKb={output.limitKb}
|
||||||
alphaLoss={output.alphaLoss}
|
alphaLoss={output.alphaLoss}
|
||||||
|
warnings={downloadWarningTexts}
|
||||||
|
error={actionError
|
||||||
|
? {
|
||||||
|
label: t("actions.actionFailed"),
|
||||||
|
detail: displayText(actionError),
|
||||||
|
}
|
||||||
|
: null}
|
||||||
onupload={upload.handleFile}
|
onupload={upload.handleFile}
|
||||||
ondownload={download}
|
ondownload={download}
|
||||||
onformat={(v) => (output.format = v)}
|
onformat={(v) => (output.format = v)}
|
||||||
@@ -442,9 +475,6 @@
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if errorText}
|
|
||||||
<p class="error" role="alert">{errorText}</p>
|
|
||||||
{/if}
|
|
||||||
<StepReorderOverlay {steps} dnd={stepDnd} />
|
<StepReorderOverlay {steps} dnd={stepDnd} />
|
||||||
</DragDropProvider>
|
</DragDropProvider>
|
||||||
</div>
|
</div>
|
||||||
@@ -611,11 +641,6 @@
|
|||||||
border-radius: 0 0 var(--radius-m) var(--radius-m);
|
border-radius: 0 0 var(--radius-m) var(--radius-m);
|
||||||
background: var(--color-panel);
|
background: var(--color-panel);
|
||||||
}
|
}
|
||||||
.error {
|
|
||||||
margin: var(--space-l) 0 0;
|
|
||||||
color: var(--color-danger);
|
|
||||||
font: var(--font-size-s) var(--font-mono);
|
|
||||||
}
|
|
||||||
.empty {
|
.empty {
|
||||||
font: var(--font-size-s) var(--font-mono);
|
font: var(--font-size-s) var(--font-mono);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,12 @@ interface RunnerState {
|
|||||||
runWarnings: ChainWarning[];
|
runWarnings: ChainWarning[];
|
||||||
// Size-limit feedback from the last download (limit unreachable etc.).
|
// Size-limit feedback from the last download (limit unreachable etc.).
|
||||||
downloadWarnings: ChainWarning[];
|
downloadWarnings: ChainWarning[];
|
||||||
displayError: DisplayError | null;
|
// Chain step failure: badge lands on that step's tile (0-based index).
|
||||||
|
stepError: { step: number; label: string; detail: string } | null;
|
||||||
|
// Source decode/upload failures (via reportError): badge on the source tile.
|
||||||
|
sourceError: DisplayError | null;
|
||||||
|
// Download/copy and non-chain run failures: badge near the download button.
|
||||||
|
actionError: DisplayError | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toDisplayError(e: unknown): DisplayError {
|
function toDisplayError(e: unknown): DisplayError {
|
||||||
@@ -101,7 +106,8 @@ async function run(s: RunnerState, ctx: SchemaToolRunnerCtx) {
|
|||||||
const steps = ctx.steps();
|
const steps = ctx.steps();
|
||||||
if (!schema || steps.length === 0) return;
|
if (!schema || steps.length === 0) return;
|
||||||
const gen = ++s.runGen;
|
const gen = ++s.runGen;
|
||||||
s.displayError = null;
|
s.stepError = null;
|
||||||
|
s.actionError = null;
|
||||||
s.running = true;
|
s.running = true;
|
||||||
try {
|
try {
|
||||||
const source = ctx.source();
|
const source = ctx.source();
|
||||||
@@ -125,16 +131,17 @@ async function run(s: RunnerState, ctx: SchemaToolRunnerCtx) {
|
|||||||
if (e instanceof ChainStepError) {
|
if (e instanceof ChainStepError) {
|
||||||
const base = toDisplayError(e.cause);
|
const base = toDisplayError(e.cause);
|
||||||
const msg = base.kind === "i18n" ? t(base.key, base.vars) : base.text;
|
const msg = base.kind === "i18n" ? t(base.key, base.vars) : base.text;
|
||||||
s.displayError = {
|
s.stepError = {
|
||||||
kind: "plain",
|
step: e.stepIndex,
|
||||||
text: t("toolPage.stepError", {
|
label: t("chain.stepFailed", { n: e.stepIndex + 1 }),
|
||||||
|
detail: t("toolPage.stepError", {
|
||||||
n: e.stepIndex + 1,
|
n: e.stepIndex + 1,
|
||||||
title: chainStepTitle(e.toolId),
|
title: chainStepTitle(e.toolId),
|
||||||
msg,
|
msg,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
s.displayError = toDisplayError(e);
|
s.actionError = toDisplayError(e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (gen === s.runGen) s.running = false;
|
if (gen === s.runGen) s.running = false;
|
||||||
@@ -144,7 +151,7 @@ async function run(s: RunnerState, ctx: SchemaToolRunnerCtx) {
|
|||||||
async function download(s: RunnerState, ctx: SchemaToolRunnerCtx) {
|
async function download(s: RunnerState, ctx: SchemaToolRunnerCtx) {
|
||||||
if (!ctx.schema()) return;
|
if (!ctx.schema()) return;
|
||||||
s.downloading = true;
|
s.downloading = true;
|
||||||
s.displayError = null;
|
s.actionError = null;
|
||||||
try {
|
try {
|
||||||
if (s.fileResult) {
|
if (s.fileResult) {
|
||||||
await downloadZip(s.fileResult.files, `${ctx.pageSlug()}.zip`);
|
await downloadZip(s.fileResult.files, `${ctx.pageSlug()}.zip`);
|
||||||
@@ -179,7 +186,7 @@ async function download(s: RunnerState, ctx: SchemaToolRunnerCtx) {
|
|||||||
downloadBlob(blob, `${ctx.pageSlug()}.${out.ext}`);
|
downloadBlob(blob, `${ctx.pageSlug()}.${out.ext}`);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
s.displayError = toDisplayError(e);
|
s.actionError = toDisplayError(e);
|
||||||
} finally {
|
} finally {
|
||||||
s.downloading = false;
|
s.downloading = false;
|
||||||
}
|
}
|
||||||
@@ -195,7 +202,7 @@ async function copyText(s: RunnerState, ctx: SchemaToolRunnerCtx) {
|
|||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(copyValue);
|
await navigator.clipboard.writeText(copyValue);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
s.displayError = toDisplayError(e);
|
s.actionError = toDisplayError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +212,7 @@ async function downloadText(s: RunnerState, ctx: SchemaToolRunnerCtx) {
|
|||||||
const blob = new Blob([s.textResult], { type: "text/plain" });
|
const blob = new Blob([s.textResult], { type: "text/plain" });
|
||||||
downloadBlob(blob, `${ctx.pageSlug()}.txt`);
|
downloadBlob(blob, `${ctx.pageSlug()}.txt`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
s.displayError = toDisplayError(e);
|
s.actionError = toDisplayError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +222,8 @@ function clearResults(s: RunnerState) {
|
|||||||
s.textResult = null;
|
s.textResult = null;
|
||||||
s.verdictVars = undefined;
|
s.verdictVars = undefined;
|
||||||
s.downloadWarnings = [];
|
s.downloadWarnings = [];
|
||||||
s.displayError = null;
|
s.stepError = null;
|
||||||
|
s.actionError = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execution state and actions of SchemaToolView: run/download/clipboard and
|
// Execution state and actions of SchemaToolView: run/download/clipboard and
|
||||||
@@ -234,7 +242,9 @@ export function createSchemaToolRunner(ctx: SchemaToolRunnerCtx) {
|
|||||||
stepFileSets: [],
|
stepFileSets: [],
|
||||||
runWarnings: [],
|
runWarnings: [],
|
||||||
downloadWarnings: [],
|
downloadWarnings: [],
|
||||||
displayError: null,
|
stepError: null,
|
||||||
|
sourceError: null,
|
||||||
|
actionError: null,
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
get running() {
|
get running() {
|
||||||
@@ -270,11 +280,17 @@ export function createSchemaToolRunner(ctx: SchemaToolRunnerCtx) {
|
|||||||
get downloadWarnings() {
|
get downloadWarnings() {
|
||||||
return s.downloadWarnings;
|
return s.downloadWarnings;
|
||||||
},
|
},
|
||||||
get displayError() {
|
get stepError() {
|
||||||
return s.displayError;
|
return s.stepError;
|
||||||
},
|
},
|
||||||
set displayError(v: DisplayError | null) {
|
get sourceError() {
|
||||||
s.displayError = v;
|
return s.sourceError;
|
||||||
|
},
|
||||||
|
get actionError() {
|
||||||
|
return s.actionError;
|
||||||
|
},
|
||||||
|
clearSourceError: () => {
|
||||||
|
s.sourceError = null;
|
||||||
},
|
},
|
||||||
run: () => run(s, ctx),
|
run: () => run(s, ctx),
|
||||||
download: () => download(s, ctx),
|
download: () => download(s, ctx),
|
||||||
@@ -290,7 +306,7 @@ export function createSchemaToolRunner(ctx: SchemaToolRunnerCtx) {
|
|||||||
},
|
},
|
||||||
clearResults: () => clearResults(s),
|
clearResults: () => clearResults(s),
|
||||||
reportError: (e: unknown) => {
|
reportError: (e: unknown) => {
|
||||||
s.displayError = toDisplayError(e);
|
s.sourceError = toDisplayError(e);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ export const en: Dict = {
|
|||||||
warnSourceSkip: "{skipped} of {total} files could not be read",
|
warnSourceSkip: "{skipped} of {total} files could not be read",
|
||||||
warnSizeLimitMiss:
|
warnSizeLimitMiss:
|
||||||
"Could not fit into {limit} KB — downloaded file is {actual} KB",
|
"Could not fit into {limit} KB — downloaded file is {actual} KB",
|
||||||
|
stepFailed: "Step {n} failed",
|
||||||
},
|
},
|
||||||
savedChains: {
|
savedChains: {
|
||||||
pageTitle: "Saved pipelines — easy-png-tools",
|
pageTitle: "Saved pipelines — easy-png-tools",
|
||||||
@@ -141,6 +142,7 @@ export const en: Dict = {
|
|||||||
sizeLimitKb: "Max size, KB",
|
sizeLimitKb: "Max size, KB",
|
||||||
sizeLimitBmp:
|
sizeLimitBmp:
|
||||||
"Size limit does not apply to BMP — it is always uncompressed",
|
"Size limit does not apply to BMP — it is always uncompressed",
|
||||||
|
actionFailed: "Failed",
|
||||||
},
|
},
|
||||||
textSource: {
|
textSource: {
|
||||||
placeholder: "Paste base64 / hex / bytes…",
|
placeholder: "Paste base64 / hex / bytes…",
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ export const ru: Dict = {
|
|||||||
warnSourceSkip: "{skipped} из {total} файлов не удалось прочитать",
|
warnSourceSkip: "{skipped} из {total} файлов не удалось прочитать",
|
||||||
warnSizeLimitMiss:
|
warnSizeLimitMiss:
|
||||||
"Не удалось ужаться до {limit} КБ — скачан файл на {actual} КБ",
|
"Не удалось ужаться до {limit} КБ — скачан файл на {actual} КБ",
|
||||||
|
stepFailed: "Шаг {n}: ошибка",
|
||||||
},
|
},
|
||||||
savedChains: {
|
savedChains: {
|
||||||
pageTitle: "Сохранённые пайплайны — easy-png-tools",
|
pageTitle: "Сохранённые пайплайны — easy-png-tools",
|
||||||
@@ -142,6 +143,7 @@ export const ru: Dict = {
|
|||||||
alphaLoss: "В результате есть прозрачность — {format} её уберёт",
|
alphaLoss: "В результате есть прозрачность — {format} её уберёт",
|
||||||
sizeLimitKb: "Лимит, КБ",
|
sizeLimitKb: "Лимит, КБ",
|
||||||
sizeLimitBmp: "Лимит размера не действует на BMP — он всегда несжатый",
|
sizeLimitBmp: "Лимит размера не действует на BMP — он всегда несжатый",
|
||||||
|
actionFailed: "Ошибка",
|
||||||
},
|
},
|
||||||
textSource: {
|
textSource: {
|
||||||
placeholder: "Вставьте base64 / hex / байты…",
|
placeholder: "Вставьте base64 / hex / байты…",
|
||||||
|
|||||||
Reference in New Issue
Block a user