mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
feat: add download size limit warning
This commit is contained in:
@@ -15,6 +15,9 @@
|
||||
dims?: string;
|
||||
note?: string;
|
||||
noteTone?: "warning" | "info";
|
||||
// Runtime warnings (chain/download events): shown as badges next to the
|
||||
// derived result note, but from a different source.
|
||||
warnings?: string[];
|
||||
actions?: Snippet;
|
||||
}
|
||||
let {
|
||||
@@ -27,6 +30,7 @@
|
||||
dims = undefined,
|
||||
note = undefined,
|
||||
noteTone = "warning",
|
||||
warnings = [],
|
||||
actions = undefined,
|
||||
}: Props = $props();
|
||||
</script>
|
||||
@@ -52,6 +56,9 @@
|
||||
{#if note}
|
||||
<Badge tone={noteTone} label={note} />
|
||||
{/if}
|
||||
{#each warnings as warning (warning)}
|
||||
<Badge tone="warning" label={warning} role="status" />
|
||||
{/each}
|
||||
</span>
|
||||
</figcaption>
|
||||
<div class="canvas" class:checker={mode === "image"}>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
resultKind?: ResultKind;
|
||||
result: PixelImage | null;
|
||||
resultNote?: ResultNote | null;
|
||||
warnings?: string[];
|
||||
fileResult?: FileResult | null;
|
||||
textResult?: string | null;
|
||||
textVars?: Record<string, string | number>;
|
||||
@@ -28,6 +29,7 @@
|
||||
resultKind = "image",
|
||||
result,
|
||||
resultNote = null,
|
||||
warnings = [],
|
||||
fileResult = null,
|
||||
textResult = null,
|
||||
textVars = undefined,
|
||||
@@ -68,6 +70,7 @@
|
||||
dims={resultDims}
|
||||
note={resultNote ? t(resultNote.key) : undefined}
|
||||
noteTone={resultNote?.tone ?? "warning"}
|
||||
{warnings}
|
||||
>
|
||||
{#snippet actions()}
|
||||
{#if ontogglemask}
|
||||
|
||||
@@ -123,7 +123,11 @@
|
||||
const stepFileSets = $derived(runner.stepFileSets);
|
||||
const runWarnings = $derived(runner.runWarnings);
|
||||
const displayError = $derived(runner.displayError);
|
||||
const allWarnings = $derived([...upload.sourceWarnings, ...runWarnings]);
|
||||
const warningTexts = $derived(
|
||||
[...upload.sourceWarnings, ...runWarnings, ...runner.downloadWarnings].map(
|
||||
chainWarningText,
|
||||
),
|
||||
);
|
||||
|
||||
const masks = createStepMasks({
|
||||
steps: () => steps,
|
||||
@@ -316,6 +320,7 @@
|
||||
resultKind={displayResultKind}
|
||||
result={out}
|
||||
{resultNote}
|
||||
warnings={warningTexts}
|
||||
{fileResult}
|
||||
{textResult}
|
||||
textVars={verdictVars}
|
||||
@@ -440,9 +445,6 @@
|
||||
{#if errorText}
|
||||
<p class="error" role="alert">{errorText}</p>
|
||||
{/if}
|
||||
{#each allWarnings as w (chainWarningText(w))}
|
||||
<p class="warn" role="status">{chainWarningText(w)}</p>
|
||||
{/each}
|
||||
<StepReorderOverlay {steps} dnd={stepDnd} />
|
||||
</DragDropProvider>
|
||||
</div>
|
||||
@@ -620,11 +622,6 @@
|
||||
.no-schema {
|
||||
font: var(--font-size-s) var(--font-mono);
|
||||
}
|
||||
.warn {
|
||||
margin: var(--space-s) 0 0;
|
||||
color: var(--color-warning);
|
||||
font: var(--font-size-s) var(--font-mono);
|
||||
}
|
||||
@media (--bp-tablet) {
|
||||
.workspace,
|
||||
.workspace.aligned {
|
||||
|
||||
@@ -56,6 +56,8 @@ interface RunnerState {
|
||||
// Full named set per step (batch/fan-out); intermediate tiles show a grid.
|
||||
stepFileSets: ToolImageFile[][];
|
||||
runWarnings: ChainWarning[];
|
||||
// Size-limit feedback from the last download (limit unreachable etc.).
|
||||
downloadWarnings: ChainWarning[];
|
||||
displayError: DisplayError | null;
|
||||
}
|
||||
|
||||
@@ -153,10 +155,29 @@ async function download(s: RunnerState, ctx: SchemaToolRunnerCtx) {
|
||||
const q = ctx.quality();
|
||||
const limit = ctx.limitKb();
|
||||
const quality = q !== undefined ? q / 100 : undefined;
|
||||
const blob = limit
|
||||
? await fitWithinBytes(s.result, out.mime, limit * 1024, quality, encode)
|
||||
: await encode(s.result, out.mime, quality);
|
||||
downloadBlob(blob, `${ctx.pageSlug()}.${out.ext}`);
|
||||
s.downloadWarnings = [];
|
||||
if (limit) {
|
||||
const fitted = await fitWithinBytes(
|
||||
s.result,
|
||||
out.mime,
|
||||
limit * 1024,
|
||||
quality,
|
||||
encode,
|
||||
);
|
||||
if (fitted.achievedBytes > limit * 1024) {
|
||||
s.downloadWarnings = [
|
||||
{
|
||||
kind: "sizeLimitMiss",
|
||||
limitKb: limit,
|
||||
actualKb: Math.ceil(fitted.achievedBytes / 1024),
|
||||
},
|
||||
];
|
||||
}
|
||||
downloadBlob(fitted.blob, `${ctx.pageSlug()}.${out.ext}`);
|
||||
} else {
|
||||
const blob = await encode(s.result, out.mime, quality);
|
||||
downloadBlob(blob, `${ctx.pageSlug()}.${out.ext}`);
|
||||
}
|
||||
} catch (e) {
|
||||
s.displayError = toDisplayError(e);
|
||||
} finally {
|
||||
@@ -193,6 +214,7 @@ function clearResults(s: RunnerState) {
|
||||
s.fileResult = null;
|
||||
s.textResult = null;
|
||||
s.verdictVars = undefined;
|
||||
s.downloadWarnings = [];
|
||||
s.displayError = null;
|
||||
}
|
||||
|
||||
@@ -211,6 +233,7 @@ export function createSchemaToolRunner(ctx: SchemaToolRunnerCtx) {
|
||||
stepResults: [],
|
||||
stepFileSets: [],
|
||||
runWarnings: [],
|
||||
downloadWarnings: [],
|
||||
displayError: null,
|
||||
});
|
||||
return {
|
||||
@@ -244,6 +267,9 @@ export function createSchemaToolRunner(ctx: SchemaToolRunnerCtx) {
|
||||
get runWarnings() {
|
||||
return s.runWarnings;
|
||||
},
|
||||
get downloadWarnings() {
|
||||
return s.downloadWarnings;
|
||||
},
|
||||
get displayError() {
|
||||
return s.displayError;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user