fix: compression UI — proper before/after display with folds tokens

Always shows Original size pill even before checkbox is checked.
After checking: shows 'compressing...' then reveals Compressed pill
with exact size and percentage saved. Green tint on compressed pill
when >5% saving; neutral when minimal gain.

Replaced all var(--bg-*) / var(--tc-*) CSS vars with folds
color.Surface.* and color.SurfaceVariant.* tokens so the UI renders
correctly in all themes. Blob cleanup is automatic — the compressed
Blob is referenced only during upload and GC'd with the upload atom.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 12:37:11 -04:00
parent c8b2de4a08
commit f1ca6e3a44
@@ -117,7 +117,6 @@ function CompressionCheckbox({ fileItem, metadata, setMetadata }: CompressionChe
return; return;
} }
// Optimistically mark as enabled; kick off compression in background
setMetadata(fileItem, { ...metadata, compressImage: true, compressionResult: undefined }); setMetadata(fileItem, { ...metadata, compressImage: true, compressionResult: undefined });
setCompressing(true); setCompressing(true);
@@ -136,63 +135,108 @@ function CompressionCheckbox({ fileItem, metadata, setMetadata }: CompressionChe
? Math.round(((result.originalSize - result.compressedSize) / result.originalSize) * 100) ? Math.round(((result.originalSize - result.compressedSize) / result.originalSize) * 100)
: null; : null;
const originalSize = formatFileSize(originalFile.size);
return ( return (
<Box <Box
direction="Column" direction="Column"
gap="100" gap="200"
style={{ style={{
marginTop: '4px', marginTop: config.space.S100,
padding: '6px 8px', padding: `${config.space.S200} ${config.space.S300}`,
background: 'var(--bg-surface-low)', background: color.SurfaceVariant.Container,
borderRadius: '6px', borderRadius: config.radii.R300,
border: '1px solid var(--bg-surface-border)', border: `1px solid ${color.SurfaceVariant.ContainerLine}`,
fontSize: '0.8rem',
}} }}
> >
{/* Checkbox row */}
<Box alignItems="Center" gap="200"> <Box alignItems="Center" gap="200">
<input <input
id={`compress-${originalFile.name}-${originalFile.size}`} id={`compress-${originalFile.name}-${originalFile.size}`}
type="checkbox" type="checkbox"
checked={checked} checked={checked}
onChange={handleChange} onChange={handleChange}
style={{ cursor: 'pointer', accentColor: 'var(--bg-secondary)' }} style={{ cursor: 'pointer', flexShrink: 0 }}
/> />
<label <label
htmlFor={`compress-${originalFile.name}-${originalFile.size}`} htmlFor={`compress-${originalFile.name}-${originalFile.size}`}
style={{ cursor: 'pointer', color: 'var(--text-primary)', userSelect: 'none' }} style={{
cursor: 'pointer',
color: color.SurfaceVariant.OnContainer,
userSelect: 'none',
fontSize: '0.8rem',
}}
> >
Compress before uploading Compress before uploading
</label> </label>
{compressing && ( {compressing && (
<Text size="T200" style={{ color: 'var(--text-secondary)', marginLeft: '4px' }}> <Text size="T200" style={{ opacity: 0.6, marginLeft: 'auto' }}>
estimating compressing
</Text> </Text>
)} )}
</Box> </Box>
{checked && !compressing && result !== undefined && (
<Text {/* Before / after row — always show original; show compressed when ready */}
size="T200" <Box gap="200" alignItems="Center" wrap="Wrap">
<Box
gap="100"
alignItems="Center"
style={{ style={{
color: result padding: `2px ${config.space.S200}`,
? savingPct !== null && savingPct > 0 borderRadius: config.radii.R300,
? 'var(--tc-success-normal, #2e7d32)' background: color.Surface.Container,
: 'var(--text-secondary)' border: `1px solid ${color.Surface.ContainerLine}`,
: 'var(--tc-danger-normal)',
paddingLeft: '20px',
}} }}
> >
{result <Text size="T200" style={{ opacity: 0.6 }}>
? savingPct !== null && savingPct > 0 Original
? `→ ~${formatFileSize(result.compressedSize)} (${savingPct}% smaller)` </Text>
: `${formatFileSize(result.compressedSize)} (no significant saving)` <Text size="T200" style={{ fontWeight: 600 }}>
: 'Compression not available for this file'} {originalSize}
</Text> </Text>
)} </Box>
{checked && !compressing && result === undefined && (
<Text size="T200" style={{ color: 'var(--text-secondary)', paddingLeft: '20px' }}> {checked && !compressing && result !== undefined && (
Original: {formatFileSize(originalFile.size)} <>
</Text> <Text size="T200" style={{ opacity: 0.5 }}>
)}
</Text>
<Box
gap="100"
alignItems="Center"
style={{
padding: `2px ${config.space.S200}`,
borderRadius: config.radii.R300,
background:
savingPct !== null && savingPct > 5
? (color.Success?.Container ?? color.Primary.Container)
: color.Surface.Container,
border: `1px solid ${
savingPct !== null && savingPct > 5
? (color.Success?.ContainerLine ?? color.Primary.ContainerLine)
: color.Surface.ContainerLine
}`,
}}
>
<Text size="T200" style={{ opacity: 0.6 }}>
Compressed
</Text>
{result ? (
<Text size="T200" style={{ fontWeight: 600 }}>
{formatFileSize(result.compressedSize)}
{savingPct !== null && savingPct > 0 && (
<span style={{ opacity: 0.7, marginLeft: 4 }}>({savingPct}% smaller)</span>
)}
</Text>
) : (
<Text size="T200" style={{ opacity: 0.6 }}>
unavailable
</Text>
)}
</Box>
</>
)}
</Box>
</Box> </Box>
); );
} }