Merge pull request #7393 from thornbill/experimental-default

This commit is contained in:
Bill Thornton
2025-12-06 18:14:40 -05:00
committed by GitHub
8 changed files with 55 additions and 42 deletions

View File

@@ -13,13 +13,16 @@ import { STABLE_APP_ROUTES } from 'apps/stable/routes/routes';
import { WIZARD_APP_ROUTES } from 'apps/wizard/routes/routes';
import AppHeader from 'components/AppHeader';
import Backdrop from 'components/Backdrop';
import { SETTING_KEY as LAYOUT_SETTING_KEY } from 'components/layoutManager';
import BangRedirect from 'components/router/BangRedirect';
import { createRouterHistory } from 'components/router/routerHistory';
import { LayoutMode } from 'constants/layoutMode';
import browser from 'scripts/browser';
import appTheme from 'themes/themes';
import { ThemeStorageManager } from 'themes/themeStorageManager';
const layoutMode = localStorage.getItem('layout');
const isExperimentalLayout = layoutMode === 'experimental';
const layoutMode = browser.tv ? LayoutMode.Tv : localStorage.getItem(LAYOUT_SETTING_KEY);
const isExperimentalLayout = !layoutMode || layoutMode === LayoutMode.Experimental;
const router = createHashRouter([
{

View File

@@ -12,6 +12,7 @@ import React, { Fragment } from 'react';
import { appHost } from 'components/apphost';
import { AppFeature } from 'constants/appFeature';
import { LayoutMode } from 'constants/layoutMode';
import { useApi } from 'hooks/useApi';
import { useThemes } from 'hooks/useThemes';
import globalize from 'lib/globalize';
@@ -45,11 +46,10 @@ export function DisplayPreferences({ onChange, values }: Readonly<DisplayPrefere
onChange={onChange}
value={values.layout}
>
<MenuItem value='auto'>{globalize.translate('Auto')}</MenuItem>
<MenuItem value='desktop'>{globalize.translate('Desktop')}</MenuItem>
<MenuItem value='mobile'>{globalize.translate('Mobile')}</MenuItem>
<MenuItem value='tv'>{globalize.translate('TV')}</MenuItem>
<MenuItem value='experimental'>{globalize.translate('Experimental')}</MenuItem>
<MenuItem value={LayoutMode.Auto}>{globalize.translate('Auto')}</MenuItem>
<MenuItem value={LayoutMode.Desktop}>{globalize.translate('Desktop')}</MenuItem>
<MenuItem value={LayoutMode.Mobile}>{globalize.translate('Mobile')}</MenuItem>
<MenuItem value={LayoutMode.Tv}>{globalize.translate('TV')}</MenuItem>
</Select>
<FormHelperText component={Stack} id='display-settings-layout-description'>
<span>{globalize.translate('DisplayModeHelp')}</span>

View File

@@ -6,6 +6,7 @@ import * as webSettings from '../scripts/settings/webSettings';
import globalize from '../lib/globalize';
import profileBuilder from '../scripts/browserDeviceProfile';
import { AppFeature } from 'constants/appFeature';
import { LayoutMode } from 'constants/layoutMode';
const appName = 'Jellyfin Web';
@@ -181,7 +182,7 @@ function supportsFullscreen() {
}
function getDefaultLayout() {
return 'desktop';
return LayoutMode.Experimental;
}
function supportsHtmlMediaAutoplay() {
@@ -371,7 +372,7 @@ export const appHost = {
return getDefaultLayout();
},
getDeviceProfile: getDeviceProfile,
getDeviceProfile,
init: function () {
if (window.NativeShell) {
return window.NativeShell.AppHost.init();

View File

@@ -172,7 +172,6 @@
<option value="desktop">${Desktop}</option>
<option value="mobile">${Mobile}</option>
<option value="tv">${TV}</option>
<option value="experimental">${Experimental}</option>
</select>
<div class="fieldDescription">${DisplayModeHelp}</div>
<div class="fieldDescription">${LabelPleaseRestart}</div>

View File

@@ -1,3 +1,4 @@
import { LayoutMode } from 'constants/layoutMode';
import { appHost } from './apphost';
import browser from '../scripts/browser';
@@ -14,51 +15,47 @@ function setLayout(instance, layout, selectedLayout) {
}
}
export const SETTING_KEY = 'layout';
class LayoutManager {
tv = false;
mobile = false;
desktop = false;
experimental = false;
setLayout(layout, save) {
if (!layout || layout === 'auto') {
setLayout(layout = '', save = true) {
const layoutValue = (!layout || layout === LayoutMode.Auto) ? '' : layout;
if (!layoutValue) {
this.autoLayout();
if (save !== false) {
appSettings.set('layout', '');
}
} else {
setLayout(this, 'mobile', layout);
setLayout(this, 'tv', layout);
setLayout(this, 'desktop', layout);
this.experimental = layout === 'experimental';
if (this.experimental) {
const legacyLayoutMode = browser.mobile ? 'mobile' : this.defaultLayout || 'desktop';
setLayout(this, legacyLayoutMode, legacyLayoutMode);
}
if (save !== false) {
appSettings.set('layout', layout);
}
setLayout(this, LayoutMode.Mobile, layoutValue);
setLayout(this, LayoutMode.Tv, layoutValue);
setLayout(this, LayoutMode.Desktop, layoutValue);
}
console.debug('[LayoutManager] using layout mode', layoutValue);
this.experimental = layoutValue === LayoutMode.Experimental;
if (this.experimental) {
const legacyLayoutMode = browser.mobile ? LayoutMode.Mobile : LayoutMode.Desktop;
console.debug('[LayoutManager] using legacy layout mode', legacyLayoutMode);
setLayout(this, legacyLayoutMode, legacyLayoutMode);
}
if (save) appSettings.set(SETTING_KEY, layoutValue);
Events.trigger(this, 'modechange');
}
getSavedLayout() {
return appSettings.get('layout');
return appSettings.get(SETTING_KEY);
}
autoLayout() {
// Take a guess at initial layout. The consuming app can override
if (browser.mobile) {
this.setLayout('mobile', false);
} else if (browser.tv || browser.xboxOne || browser.ps4) {
this.setLayout('tv', false);
} else {
this.setLayout(this.defaultLayout || 'tv', false);
}
// Take a guess at initial layout. The consuming app can override.
// NOTE: The fallback to TV mode seems like an outdated choice. TVs should be detected properly or override the
// default layout.
this.setLayout(browser.tv ? LayoutMode.Tv : this.defaultLayout || LayoutMode.Tv, false);
}
init() {

View File

@@ -6,6 +6,7 @@ import itemHelper from '../itemHelper';
import loading from '../loading/loading';
import alert from '../alert';
import { LayoutMode } from 'constants/layoutMode';
import { getItemQuery } from 'hooks/useItem';
import { ServerConnections } from 'lib/jellyfin-apiclient';
import { toApi } from 'utils/jellyfin-apiclient/compat';
@@ -434,7 +435,7 @@ class AppRouter {
const layoutMode = localStorage.getItem('layout');
if (layoutMode === 'experimental' && item.CollectionType == CollectionType.Homevideos) {
if (layoutMode === LayoutMode.Experimental && item.CollectionType == CollectionType.Homevideos) {
url = '#/homevideos?topParentId=' + item.Id;
return url;

View File

@@ -0,0 +1,13 @@
/** The different layout modes supported by the web app. */
export enum LayoutMode {
/** Automatic layout - the app chose the best layout for the detected device. */
Auto = 'auto',
/** The legacy desktop layout. */
Desktop = 'desktop',
/** The modern React based layout. */
Experimental = 'experimental',
/** The legacy mobile layout. */
Mobile = 'mobile',
/** The TV layout. */
Tv = 'tv'
};

View File

@@ -232,7 +232,7 @@
"DeleteServerConfirmation": "Are you sure you wish to delete this server?",
"Depressed": "Depressed",
"Descending": "Descending",
"Desktop": "Desktop",
"Desktop": "Desktop (Legacy)",
"DetectingDevices": "Detecting devices",
"DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.",
"Digital": "Digital",
@@ -332,7 +332,6 @@
"EveryXHours": "Every {0} hours",
"EveryXMinutes": "Every {0} minutes",
"ExitFullscreen": "Exit full screen",
"Experimental": "Experimental",
"ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, resource intensive, and may require several gigabytes of space. It runs when videos are discovered, and also as a nightly scheduled task. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
"ExtraLarge": "Extra Large",
"Extras": "Extras",
@@ -1217,7 +1216,7 @@
"MinutesBefore": "minutes before",
"MixedMoviesShows": "Mixed Movies and Shows",
"Mixer": "Mixer",
"Mobile": "Mobile",
"Mobile": "Mobile (Legacy)",
"Monday": "Monday",
"MoreFromValue": "More from {0}",
"MoreMediaInfo": "Media Info",