feat: add image upscaling option and allow force stretching beyond native resolution

main
I Luk Kim 3 weeks ago
parent 0774c130de
commit e4269041ee

@ -537,21 +537,39 @@ kbd {
}
.manga-page img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
display: block;
pointer-events: none;
}
.fit-width .manga-page img {
/* Allow Upscale Mode (Default: stretch to fill container) */
.manga-page.allow-upscale.fit-width img {
width: 100%;
height: auto;
max-width: none;
max-height: none;
}
.fit-height .manga-page img {
.manga-page.allow-upscale.fit-height img {
height: 100%;
width: auto;
max-width: none;
max-height: none;
}
/* No Upscale Mode (Limit max dimensions to native image size) */
.manga-page.no-upscale.fit-width img {
width: auto;
max-width: 100%;
height: auto;
max-height: 100%;
}
.manga-page.no-upscale.fit-height img {
height: auto;
max-height: 100%;
width: auto;
max-width: 100%;
}
/* Page loading / error states */

@ -5,10 +5,11 @@ interface MangaPageProps {
imageUrl: string;
referer: string;
fitMode: FitMode;
allowUpscale?: boolean;
fetchImage: (url: string, referer: string) => Promise<string>;
}
export function MangaPage({ imageUrl, referer, fitMode, fetchImage }: MangaPageProps) {
export function MangaPage({ imageUrl, referer, fitMode, allowUpscale = true, fetchImage }: MangaPageProps) {
const [src, setSrc] = useState<string>('');
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
@ -44,6 +45,8 @@ export function MangaPage({ imageUrl, referer, fitMode, fetchImage }: MangaPageP
original: 'fit-original',
}[fitMode];
const upscaleClass = allowUpscale ? 'allow-upscale' : 'no-upscale';
if (loading) {
return (
<div className="page-placeholder">
@ -70,7 +73,7 @@ export function MangaPage({ imageUrl, referer, fitMode, fetchImage }: MangaPageP
}
return (
<div className={`manga-page ${fitClass}`}>
<div className={`manga-page ${fitClass} ${upscaleClass}`}>
<img
src={src}
alt=""

@ -309,6 +309,7 @@ export function MangaViewer({
imageUrl={imgUrl}
referer={referer}
fitMode={settings.fitMode}
allowUpscale={settings.allowUpscale}
fetchImage={fetchImage}
/>
))}

@ -138,6 +138,30 @@ export function SettingsPanel({ settings, totalImages, onChange, onClose }: Sett
</div>
</div>
{/* Upscale Mode */}
<div className="settings-group">
<label className="settings-label">
<span className="settings-hint"> </span>
</label>
<div className="option-grid cols-2">
<button
className={`option-card compact ${settings.allowUpscale ? 'selected' : ''}`}
onClick={() => onChange({ allowUpscale: true })}
>
<span> ( )</span>
<small> </small>
</button>
<button
className={`option-card compact ${!settings.allowUpscale ? 'selected' : ''}`}
onClick={() => onChange({ allowUpscale: false })}
>
<span> ( )</span>
<small> </small>
</button>
</div>
</div>
{/* Background Color */}
<div className="settings-group">
<label className="settings-label"></label>

@ -7,6 +7,7 @@ const defaultSettings: ViewerSettings = {
mode: 'spread',
direction: 'ltr',
fitMode: 'width',
allowUpscale: true,
backgroundColor: 'black',
spreadStartOffset: 0,
};

@ -15,6 +15,7 @@ export interface ViewerSettings {
mode: ViewerMode;
direction: ReadingDirection;
fitMode: FitMode;
allowUpscale: boolean;
backgroundColor: BackgroundColor;
/** 0-indexed page that starts the first "paired" spread. Pages before this are shown solo. */
spreadStartOffset: number;

Loading…
Cancel
Save