[enhancement]: support using native image aspect ratio
This commit is contained in:
parent
961d1838c0
commit
38ed083693
13 changed files with 41 additions and 9 deletions
|
@ -531,6 +531,8 @@
|
||||||
"hotkey_volumeUp": "volume up",
|
"hotkey_volumeUp": "volume up",
|
||||||
"hotkey_zoomIn": "zoom in",
|
"hotkey_zoomIn": "zoom in",
|
||||||
"hotkey_zoomOut": "zoom out",
|
"hotkey_zoomOut": "zoom out",
|
||||||
|
"imageAspectRatio": "use native cover art aspect ratio",
|
||||||
|
"imageAspectRatio_description": "if enabled, cover art will be shown using their native aspect ratio. for art that is not 1:1, the remaining space will be empty",
|
||||||
"language": "language",
|
"language": "language",
|
||||||
"language_description": "sets the language for the application ($t(common.restartRequired))",
|
"language_description": "sets the language for the application ($t(common.restartRequired))",
|
||||||
"lyricFetch": "fetch lyrics from the internet",
|
"lyricFetch": "fetch lyrics from the internet",
|
||||||
|
|
|
@ -40,6 +40,7 @@ export const App = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const accent = useSettingsStore((store) => store.general.accent);
|
const accent = useSettingsStore((store) => store.general.accent);
|
||||||
const language = useSettingsStore((store) => store.general.language);
|
const language = useSettingsStore((store) => store.general.language);
|
||||||
|
const nativeImageAspect = useSettingsStore((store) => store.general.nativeAspectRatio);
|
||||||
const { builtIn, custom, system, type } = useSettingsStore((state) => state.font);
|
const { builtIn, custom, system, type } = useSettingsStore((state) => state.font);
|
||||||
const { type: playbackType } = usePlaybackSettings();
|
const { type: playbackType } = usePlaybackSettings();
|
||||||
const { bindings } = useHotkeySettings();
|
const { bindings } = useHotkeySettings();
|
||||||
|
@ -90,6 +91,11 @@ export const App = () => {
|
||||||
root.style.setProperty('--primary-color', accent);
|
root.style.setProperty('--primary-color', accent);
|
||||||
}, [accent]);
|
}, [accent]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const root = document.documentElement;
|
||||||
|
root.style.setProperty('--image-fit', nativeImageAspect ? 'scale-down' : 'cover');
|
||||||
|
}, [nativeImageAspect]);
|
||||||
|
|
||||||
const providerValue = useMemo(() => {
|
const providerValue = useMemo(() => {
|
||||||
return { handlePlayQueueAdd };
|
return { handlePlayQueueAdd };
|
||||||
}, [handlePlayQueueAdd]);
|
}, [handlePlayQueueAdd]);
|
||||||
|
|
|
@ -92,7 +92,7 @@ const Image = styled(SimpleImg)`
|
||||||
|
|
||||||
img {
|
img {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: var(--image-fit);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ const BackgroundImage = styled.img`
|
||||||
height: 150%;
|
height: 150%;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
filter: blur(24px);
|
filter: blur(24px);
|
||||||
object-fit: cover;
|
object-fit: var(--image-fit);
|
||||||
object-position: 0 30%;
|
object-position: 0 30%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ const Image = styled(SimpleImg)`
|
||||||
|
|
||||||
img {
|
img {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: var(--image-fit);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ const Image = styled(SimpleImg)`
|
||||||
|
|
||||||
img {
|
img {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: var(--image-fit);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ const MetadataWrapper = styled.div`
|
||||||
|
|
||||||
const StyledImage = styled(SimpleImg)`
|
const StyledImage = styled(SimpleImg)`
|
||||||
img {
|
img {
|
||||||
object-fit: cover;
|
object-fit: var(--image-fit);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ const Image = styled(motion.div)`
|
||||||
const PlayerbarImage = styled.img`
|
const PlayerbarImage = styled.img`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: var(--image-fit);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const LineItem = styled.div<{ $secondary?: boolean }>`
|
const LineItem = styled.div<{ $secondary?: boolean }>`
|
||||||
|
|
|
@ -46,7 +46,7 @@ const MetadataWrapper = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledImage = styled.img`
|
const StyledImage = styled.img`
|
||||||
object-fit: cover;
|
object-fit: var(--image-fit);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,28 @@ export const ControlSettings = () => {
|
||||||
isHidden: false,
|
isHidden: false,
|
||||||
title: t('setting.playerAlbumArtResolution', { postProcess: 'sentenceCase' }),
|
title: t('setting.playerAlbumArtResolution', { postProcess: 'sentenceCase' }),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
control: (
|
||||||
|
<Switch
|
||||||
|
aria-label="Toggle using native aspect ratio"
|
||||||
|
defaultChecked={settings.nativeAspectRatio}
|
||||||
|
onChange={(e) =>
|
||||||
|
setSettings({
|
||||||
|
general: {
|
||||||
|
...settings,
|
||||||
|
nativeAspectRatio: e.currentTarget.checked,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
description: t('setting.imageAspectRatio', {
|
||||||
|
context: 'description',
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
}),
|
||||||
|
isHidden: false,
|
||||||
|
title: t('setting.imageAspectRatio', { postProcess: 'sentenceCase' }),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
control: (
|
control: (
|
||||||
<Switch
|
<Switch
|
||||||
|
|
|
@ -121,7 +121,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
object-fit: cover;
|
object-fit: var(--image-fit);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ const ImageContainer = styled(motion.div)<{ height: string }>`
|
||||||
const SidebarImage = styled.img`
|
const SidebarImage = styled.img`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: var(--image-fit);
|
||||||
background: var(--placeholder-bg);
|
background: var(--placeholder-bg);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -201,6 +201,7 @@ export interface SettingsState {
|
||||||
homeFeature: boolean;
|
homeFeature: boolean;
|
||||||
homeItems: SortableItem<HomeItem>[];
|
homeItems: SortableItem<HomeItem>[];
|
||||||
language: string;
|
language: string;
|
||||||
|
nativeAspectRatio: boolean;
|
||||||
passwordStore?: string;
|
passwordStore?: string;
|
||||||
playButtonBehavior: Play;
|
playButtonBehavior: Play;
|
||||||
resume: boolean;
|
resume: boolean;
|
||||||
|
@ -323,6 +324,7 @@ const initialState: SettingsState = {
|
||||||
homeFeature: true,
|
homeFeature: true,
|
||||||
homeItems,
|
homeItems,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
|
nativeAspectRatio: false,
|
||||||
passwordStore: undefined,
|
passwordStore: undefined,
|
||||||
playButtonBehavior: Play.NOW,
|
playButtonBehavior: Play.NOW,
|
||||||
resume: false,
|
resume: false,
|
||||||
|
|
Reference in a new issue