mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-05-03 13:56:29 +01:00
fix(tv): poster design and other stuff
This commit is contained in:
@@ -1,57 +1,12 @@
|
||||
import { TVTypographyScale, useSettings } from "@/utils/atoms/settings";
|
||||
|
||||
/**
|
||||
* TV Poster Sizes
|
||||
*
|
||||
* Base sizes for poster components on TV interfaces.
|
||||
* These are scaled dynamically based on the user's tvTypographyScale setting.
|
||||
* @deprecated Import from "@/constants/TVSizes" instead.
|
||||
* This file is kept for backwards compatibility.
|
||||
*/
|
||||
|
||||
export const TVPosterSizes = {
|
||||
/** Portrait posters (movies, series) - 10:15 aspect ratio */
|
||||
poster: 256,
|
||||
export {
|
||||
type ScaledTVPosterSizes,
|
||||
TVPosterSizes,
|
||||
useScaledTVPosterSizes,
|
||||
} from "./TVSizes";
|
||||
|
||||
/** Landscape posters (continue watching, thumbs) - 16:9 aspect ratio */
|
||||
landscape: 396,
|
||||
|
||||
/** Episode cards - 16:9 aspect ratio */
|
||||
episode: 336,
|
||||
|
||||
/** Hero carousel cards - 16:9 aspect ratio */
|
||||
heroCard: 276,
|
||||
} as const;
|
||||
|
||||
export type TVPosterSizeKey = keyof typeof TVPosterSizes;
|
||||
|
||||
/**
|
||||
* Linear poster size offsets (in pixels) - synchronized with typography scale.
|
||||
* Uses fixed pixel steps for consistent linear scaling across all poster types.
|
||||
*/
|
||||
const posterScaleOffsets: Record<TVTypographyScale, number> = {
|
||||
[TVTypographyScale.Small]: -10,
|
||||
[TVTypographyScale.Default]: 0,
|
||||
[TVTypographyScale.Large]: 10,
|
||||
[TVTypographyScale.ExtraLarge]: 20,
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook that returns scaled TV poster sizes based on user settings.
|
||||
* Use this instead of the static TVPosterSizes constant for dynamic scaling.
|
||||
*
|
||||
* @example
|
||||
* const posterSizes = useScaledTVPosterSizes();
|
||||
* <View style={{ width: posterSizes.poster }}>
|
||||
*/
|
||||
export const useScaledTVPosterSizes = () => {
|
||||
const { settings } = useSettings();
|
||||
const offset =
|
||||
posterScaleOffsets[settings.tvTypographyScale] ??
|
||||
posterScaleOffsets[TVTypographyScale.Default];
|
||||
|
||||
return {
|
||||
poster: TVPosterSizes.poster + offset,
|
||||
landscape: TVPosterSizes.landscape + offset,
|
||||
episode: TVPosterSizes.episode + offset,
|
||||
heroCard: TVPosterSizes.heroCard + offset,
|
||||
};
|
||||
};
|
||||
export type TVPosterSizeKey = keyof typeof import("./TVSizes").TVPosterSizes;
|
||||
|
||||
175
constants/TVSizes.ts
Normal file
175
constants/TVSizes.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
import { TVTypographyScale, useSettings } from "@/utils/atoms/settings";
|
||||
|
||||
/**
|
||||
* TV Layout Sizes
|
||||
*
|
||||
* Unified constants for TV interface layout including posters, gaps, and padding.
|
||||
* All values scale based on the user's tvTypographyScale setting.
|
||||
*/
|
||||
|
||||
// =============================================================================
|
||||
// BASE VALUES (at Default scale)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Base poster widths in pixels.
|
||||
* Heights are calculated from aspect ratios.
|
||||
*/
|
||||
export const TVPosterSizes = {
|
||||
/** Portrait posters (movies, series) - 10:15 aspect ratio */
|
||||
poster: 210,
|
||||
|
||||
/** Landscape posters (continue watching, thumbs, hero) - 16:9 aspect ratio */
|
||||
landscape: 340,
|
||||
|
||||
/** Episode cards - 16:9 aspect ratio */
|
||||
episode: 320,
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Base gap/spacing values in pixels.
|
||||
*/
|
||||
export const TVGaps = {
|
||||
/** Gap between items in horizontal lists */
|
||||
item: 24,
|
||||
|
||||
/** Gap between sections vertically */
|
||||
section: 32,
|
||||
|
||||
/** Small gap for tight layouts */
|
||||
small: 12,
|
||||
|
||||
/** Large gap for spacious layouts */
|
||||
large: 48,
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Base padding values in pixels.
|
||||
*/
|
||||
export const TVPadding = {
|
||||
/** Horizontal padding from screen edges */
|
||||
horizontal: 60,
|
||||
|
||||
/** Padding to accommodate scale animations (1.05x) */
|
||||
scale: 20,
|
||||
|
||||
/** Vertical padding for content areas */
|
||||
vertical: 24,
|
||||
|
||||
/** Hero section height as percentage of screen height (0.0 - 1.0) */
|
||||
heroHeight: 0.6,
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Animation and interaction values.
|
||||
*/
|
||||
export const TVAnimation = {
|
||||
/** Scale factor for focused items */
|
||||
focusScale: 1.05,
|
||||
} as const;
|
||||
|
||||
// =============================================================================
|
||||
// SCALING
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Scale multipliers for each typography scale level.
|
||||
* Applied to poster sizes and gaps.
|
||||
*/
|
||||
const sizeScaleMultipliers: Record<TVTypographyScale, number> = {
|
||||
[TVTypographyScale.Small]: 0.9,
|
||||
[TVTypographyScale.Default]: 1.0,
|
||||
[TVTypographyScale.Large]: 1.1,
|
||||
[TVTypographyScale.ExtraLarge]: 1.2,
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// HOOKS
|
||||
// =============================================================================
|
||||
|
||||
export type ScaledTVPosterSizes = {
|
||||
poster: number;
|
||||
landscape: number;
|
||||
episode: number;
|
||||
};
|
||||
|
||||
export type ScaledTVGaps = {
|
||||
item: number;
|
||||
section: number;
|
||||
small: number;
|
||||
large: number;
|
||||
};
|
||||
|
||||
export type ScaledTVPadding = {
|
||||
horizontal: number;
|
||||
scale: number;
|
||||
vertical: number;
|
||||
heroHeight: number;
|
||||
};
|
||||
|
||||
export type ScaledTVSizes = {
|
||||
posters: ScaledTVPosterSizes;
|
||||
gaps: ScaledTVGaps;
|
||||
padding: ScaledTVPadding;
|
||||
animation: typeof TVAnimation;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook that returns all scaled TV sizes based on user settings.
|
||||
*
|
||||
* @example
|
||||
* const sizes = useScaledTVSizes();
|
||||
* <View style={{ width: sizes.posters.poster, marginRight: sizes.gaps.item }}>
|
||||
*/
|
||||
export const useScaledTVSizes = (): ScaledTVSizes => {
|
||||
const { settings } = useSettings();
|
||||
const scale =
|
||||
sizeScaleMultipliers[settings.tvTypographyScale] ??
|
||||
sizeScaleMultipliers[TVTypographyScale.Default];
|
||||
|
||||
return {
|
||||
posters: {
|
||||
poster: Math.round(TVPosterSizes.poster * scale),
|
||||
landscape: Math.round(TVPosterSizes.landscape * scale),
|
||||
episode: Math.round(TVPosterSizes.episode * scale),
|
||||
},
|
||||
gaps: {
|
||||
item: Math.round(TVGaps.item * scale),
|
||||
section: Math.round(TVGaps.section * scale),
|
||||
small: Math.round(TVGaps.small * scale),
|
||||
large: Math.round(TVGaps.large * scale),
|
||||
},
|
||||
padding: {
|
||||
horizontal: Math.round(TVPadding.horizontal * scale),
|
||||
scale: Math.round(TVPadding.scale * scale),
|
||||
vertical: Math.round(TVPadding.vertical * scale),
|
||||
heroHeight: TVPadding.heroHeight * scale,
|
||||
},
|
||||
animation: TVAnimation,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook that returns only scaled poster sizes.
|
||||
* Use this for backwards compatibility or when you only need poster sizes.
|
||||
*/
|
||||
export const useScaledTVPosterSizes = (): ScaledTVPosterSizes => {
|
||||
const sizes = useScaledTVSizes();
|
||||
return sizes.posters;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook that returns only scaled gap sizes.
|
||||
*/
|
||||
export const useScaledTVGaps = (): ScaledTVGaps => {
|
||||
const sizes = useScaledTVSizes();
|
||||
return sizes.gaps;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook that returns only scaled padding sizes.
|
||||
*/
|
||||
export const useScaledTVPadding = (): ScaledTVPadding => {
|
||||
const sizes = useScaledTVSizes();
|
||||
return sizes.padding;
|
||||
};
|
||||
Reference in New Issue
Block a user