Add grid item size setting and UI

Introduce a persistent gridItemSize user setting (1-10) across the app. Updates include: types (UserSettings.gridItemSize), API mappings (grid_item_size in ApiSettingsItem, CreateSettingsInput, convertApiToSettings, convertSettingsToApi), default setting values, and the App handler (handleGridItemSizeChange) to save changes. UI additions: slider control in SettingsView, slider and value in BrowseView (with syncing to incoming API settings), passing the prop and change callback from App, and a mapping from slider values to responsive Tailwind grid column classes so the grid layout adapts to the chosen size. Also added syncing of itemsPerPage in BrowseView and CastView with API-loaded settings.
This commit is contained in:
Lars Behrends
2026-04-10 23:31:24 +02:00
parent 444c908449
commit f482807387
6 changed files with 112 additions and 11 deletions

View File

@@ -631,6 +631,7 @@ export interface ApiSettingsItem {
id?: number;
enabled_categories: string[];
items_per_page: number;
grid_item_size?: number;
default_view: string;
show_adult_content: boolean;
auto_play_trailers: boolean;
@@ -643,6 +644,7 @@ export interface ApiSettingsItem {
export interface CreateSettingsInput {
enabled_categories: string[];
items_per_page?: number;
grid_item_size?: number;
default_view?: string;
show_adult_content?: boolean;
auto_play_trailers?: boolean;
@@ -657,6 +659,7 @@ export function convertApiToSettings(apiItem: ApiSettingsItem): UserSettings {
id: apiItem.id,
enabledCategories: apiItem.enabled_categories as MediaCategory[],
itemsPerPage: apiItem.items_per_page || 20,
gridItemSize: apiItem.grid_item_size || 5,
defaultView: (apiItem.default_view as 'grid' | 'list') || 'grid',
showAdultContent: apiItem.show_adult_content || false,
autoPlayTrailers: apiItem.auto_play_trailers || false,
@@ -671,6 +674,7 @@ export function convertSettingsToApi(settings: UserSettings): CreateSettingsInpu
return {
enabled_categories: settings.enabledCategories,
items_per_page: settings.itemsPerPage,
grid_item_size: settings.gridItemSize,
default_view: settings.defaultView,
show_adult_content: settings.showAdultContent,
auto_play_trailers: settings.autoPlayTrailers,
@@ -705,7 +709,6 @@ export async function fetchSettings(): Promise<UserSettings | null> {
export async function createSettings(settings: UserSettings): Promise<UserSettings | null> {
try {
const apiSettings = convertSettingsToApi(settings);
console.log('Creating settings:', apiSettings);
const response = await fetch(`${BASE_URL}/api/settings`, {
method: 'POST',
headers: {
@@ -713,14 +716,12 @@ export async function createSettings(settings: UserSettings): Promise<UserSettin
},
body: JSON.stringify(apiSettings),
});
console.log('Create settings response status:', response.status);
if (!response.ok) {
const errorText = await response.text();
console.error('Create settings error response:', errorText);
throw new Error(`HTTP error! status: ${response.status}`);
}
const data: ApiResponse<ApiSettingsItem> = await response.json();
console.log('Create settings response:', data);
if (data.success && data.data) {
return convertApiToSettings(data.data);
@@ -735,7 +736,6 @@ export async function createSettings(settings: UserSettings): Promise<UserSettin
export async function updateSettings(settings: UserSettings): Promise<UserSettings | null> {
try {
const apiSettings = convertSettingsToApi(settings);
console.log('Updating settings:', apiSettings);
const response = await fetch(`${BASE_URL}/api/settings`, {
method: 'PUT',
headers: {
@@ -743,11 +743,9 @@ export async function updateSettings(settings: UserSettings): Promise<UserSettin
},
body: JSON.stringify(apiSettings),
});
console.log('Update settings response status:', response.status);
if (!response.ok) {
// If settings don't exist (404), try creating them instead
if (response.status === 404) {
console.log('Settings not found, attempting to create...');
return createSettings(settings);
}
const errorText = await response.text();
@@ -755,7 +753,6 @@ export async function updateSettings(settings: UserSettings): Promise<UserSettin
throw new Error(`HTTP error! status: ${response.status}`);
}
const data: ApiResponse<ApiSettingsItem> = await response.json();
console.log('Update settings response:', data);
if (data.success && data.data) {
return convertApiToSettings(data.data);