mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-09-14 21:46:35 +00:00
refactor: separate tool page for A\B testing
This commit is contained in:
@@ -14,14 +14,12 @@
|
||||
import { executeStep } from '$lib/tools/executor';
|
||||
import { t } from '$lib/i18n/t';
|
||||
import { toolDescription, toolTitle } from '$lib/i18n/tool-strings';
|
||||
import ParamsCard from './tool/ParamsCard.svelte';
|
||||
import ResultCard from './tool/ResultCard.svelte';
|
||||
import SourceCard from './tool/SourceCard.svelte';
|
||||
import TextInputCard from './tool/TextInputCard.svelte';
|
||||
import type { StageStatus } from './stage/stage-props';
|
||||
import ToolStageClassic from './stage/ToolStageClassic.svelte';
|
||||
|
||||
let { tool, restoreChain = false }: { tool: ToolEntry; restoreChain?: boolean } = $props();
|
||||
|
||||
type Status = 'idle' | 'loaded' | 'processing' | 'error';
|
||||
type Status = StageStatus;
|
||||
|
||||
let status = $state<Status>('idle');
|
||||
let source = $state<PixelImage | null>(null);
|
||||
@@ -267,61 +265,34 @@
|
||||
<div class="error-banner" role="alert">{errorText}</div>
|
||||
{/if}
|
||||
|
||||
<div class="panel tool-block">
|
||||
<div class="tool-stage" class:single={isSourceless}>
|
||||
{#if !isSourceless}
|
||||
<span class="edge-legend source-legend" aria-hidden="true">{t('toolPage.legendSource')}</span>
|
||||
<div class="cell">
|
||||
{#if isTextSource && !source}
|
||||
<TextInputCard onSubmit={handleTextSubmit} />
|
||||
{:else}
|
||||
<SourceCard
|
||||
{source}
|
||||
onFile={handleFile}
|
||||
onError={(e) => (errorText = errorMessage(e))}
|
||||
onReset={reset}
|
||||
pipetteActive={!!pipetteTargetId}
|
||||
onPickColor={handlePickColor}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<span class="edge-legend result-legend" aria-hidden="true">
|
||||
{isInfo ? t('toolPage.legendSummary') : t('toolPage.legendResult')}
|
||||
</span>
|
||||
<div class="cell">
|
||||
<ResultCard
|
||||
{tool}
|
||||
sourceLoaded={isSourceless ? true : !!source}
|
||||
{status}
|
||||
{result}
|
||||
displayImage={shownBase}
|
||||
{info}
|
||||
{isInfo}
|
||||
params={sanitized}
|
||||
textResult={textResult}
|
||||
onChainToggle={canChainBase ? toggleChain : undefined}
|
||||
hasChain={chain.length > 0}
|
||||
onDownloadError={showError}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if (source || isSourceless) && !isInfo && (tool.params.length > 0 || hasMask)}
|
||||
<div class="params-sep">
|
||||
<span class="edge-legend" aria-hidden="true">{t('toolPage.legendParams')}</span>
|
||||
</div>
|
||||
<ParamsCard
|
||||
<ToolStageClassic
|
||||
tool={tool}
|
||||
params={tool.params}
|
||||
bind:values
|
||||
{pipetteTargetId}
|
||||
onPipetteToggle={handlePipetteToggle}
|
||||
source={source}
|
||||
result={result}
|
||||
displayImage={shownBase}
|
||||
info={info}
|
||||
status={status}
|
||||
isInfo={isInfo}
|
||||
isSourceless={isSourceless}
|
||||
isTextSource={isTextSource}
|
||||
textResult={textResult}
|
||||
sanitized={sanitized}
|
||||
canChainBase={canChainBase}
|
||||
hasChain={chain.length > 0}
|
||||
hasMask={hasMask}
|
||||
bind:showMask
|
||||
bind:values
|
||||
pipetteTargetId={pipetteTargetId}
|
||||
handleFile={handleFile}
|
||||
onTextSubmit={handleTextSubmit}
|
||||
onSourceError={(e) => (errorText = errorMessage(e))}
|
||||
reset={reset}
|
||||
toggleChain={toggleChain}
|
||||
handlePipetteToggle={handlePipetteToggle}
|
||||
handlePickColor={handlePickColor}
|
||||
showError={showError}
|
||||
errorMessage={errorMessage}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="chain-stack">
|
||||
{#each chain as step, index (step.id)}
|
||||
@@ -374,27 +345,6 @@
|
||||
margin-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.tool-stage {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.source-legend {
|
||||
left: 25%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.result-legend {
|
||||
left: 75%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
@media (max-width: 48rem) {
|
||||
.source-legend,
|
||||
.result-legend {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-slot {
|
||||
padding: var(--space-3);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
<script lang="ts">
|
||||
import { t } from '$lib/i18n/t';
|
||||
import ParamsCard from '../tool/ParamsCard.svelte';
|
||||
import ResultCard from '../tool/ResultCard.svelte';
|
||||
import SourceCard from '../tool/SourceCard.svelte';
|
||||
import TextInputCard from '../tool/TextInputCard.svelte';
|
||||
import type { StageProps } from './stage-props';
|
||||
|
||||
let {
|
||||
tool,
|
||||
source,
|
||||
result,
|
||||
displayImage,
|
||||
info,
|
||||
status,
|
||||
isInfo,
|
||||
isSourceless,
|
||||
isTextSource,
|
||||
textResult,
|
||||
sanitized,
|
||||
canChainBase,
|
||||
hasChain,
|
||||
hasMask,
|
||||
showMask = $bindable(false),
|
||||
values = $bindable(),
|
||||
pipetteTargetId,
|
||||
handleFile,
|
||||
onTextSubmit,
|
||||
onSourceError,
|
||||
reset,
|
||||
toggleChain,
|
||||
handlePipetteToggle,
|
||||
handlePickColor,
|
||||
showError,
|
||||
errorMessage
|
||||
}: StageProps = $props();
|
||||
</script>
|
||||
|
||||
<div class="panel tool-block">
|
||||
<div class="tool-stage" class:single={isSourceless}>
|
||||
{#if !isSourceless}
|
||||
<span class="edge-legend source-legend" aria-hidden="true">{t('toolPage.legendSource')}</span>
|
||||
<div class="cell">
|
||||
{#if isTextSource && !source}
|
||||
<TextInputCard onSubmit={onTextSubmit} />
|
||||
{:else}
|
||||
<SourceCard
|
||||
{source}
|
||||
onFile={handleFile}
|
||||
onError={onSourceError}
|
||||
onReset={reset}
|
||||
pipetteActive={!!pipetteTargetId}
|
||||
onPickColor={handlePickColor}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<span class="edge-legend result-legend" aria-hidden="true">
|
||||
{isInfo ? t('toolPage.legendSummary') : t('toolPage.legendResult')}
|
||||
</span>
|
||||
<div class="cell">
|
||||
<ResultCard
|
||||
{tool}
|
||||
sourceLoaded={isSourceless ? true : !!source}
|
||||
{status}
|
||||
{result}
|
||||
displayImage={displayImage}
|
||||
{info}
|
||||
{isInfo}
|
||||
params={sanitized}
|
||||
textResult={textResult}
|
||||
onChainToggle={canChainBase ? toggleChain : undefined}
|
||||
{hasChain}
|
||||
onDownloadError={showError}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if (source || isSourceless) && !isInfo && (tool.params.length > 0 || hasMask)}
|
||||
<div class="params-sep">
|
||||
<span class="edge-legend" aria-hidden="true">{t('toolPage.legendParams')}</span>
|
||||
</div>
|
||||
<ParamsCard
|
||||
{tool}
|
||||
params={tool.params}
|
||||
bind:values
|
||||
{pipetteTargetId}
|
||||
onPipetteToggle={handlePipetteToggle}
|
||||
{hasMask}
|
||||
bind:showMask
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.tool-stage {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.source-legend {
|
||||
left: 25%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.result-legend {
|
||||
left: 75%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
@media (max-width: 48rem) {
|
||||
.source-legend,
|
||||
.result-legend {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { ImageInfo } from '$lib/core/analyze';
|
||||
import type { PixelImage } from '$lib/core/types';
|
||||
import type { ToolEntry } from '$lib/registry';
|
||||
|
||||
export type StageStatus = 'idle' | 'loaded' | 'processing' | 'error';
|
||||
|
||||
export interface StageProps {
|
||||
tool: ToolEntry;
|
||||
source: PixelImage | null;
|
||||
result: PixelImage | null;
|
||||
displayImage: PixelImage | null;
|
||||
info: ImageInfo | null;
|
||||
status: StageStatus;
|
||||
isInfo: boolean;
|
||||
isSourceless: boolean;
|
||||
isTextSource: boolean;
|
||||
textResult: string | null;
|
||||
sanitized: Record<string, any>;
|
||||
canChainBase: boolean;
|
||||
hasChain: boolean;
|
||||
hasMask: boolean;
|
||||
showMask: boolean;
|
||||
values: Record<string, any>;
|
||||
pipetteTargetId: string | null;
|
||||
handleFile: (file: File) => Promise<void> | void;
|
||||
onTextSubmit: (text: string) => Promise<void> | void;
|
||||
onSourceError: (e: unknown) => void;
|
||||
reset: () => void;
|
||||
toggleChain: () => void;
|
||||
handlePipetteToggle: (id: string) => void;
|
||||
handlePickColor: (hex: string) => void;
|
||||
showError: (e: unknown) => void;
|
||||
errorMessage: (e: unknown) => string;
|
||||
}
|
||||
Reference in New Issue
Block a user