feat(surface): switch app shells when the viewport crosses the phone threshold
The mobile-vs-desktop surface is stamped once at boot, so a browser window narrowed past the phone threshold kept the desktop shell (and its legacy squeezed layout) until a manual reload. A viewport watcher now reloads into the other shell once the resize settles — the same mechanism the old Settings toggle used. Fixed shells (Capacitor, desktop, VS Code) and ?surface= overrides never switch. With the new mobile app reachable this way, the old/new mobile layout preference is gone: phones always get the mobile app.
This commit is contained in:
@@ -32,7 +32,6 @@ import { CODE_FONT_OPTIONS, DEFAULT_MONO_FONT, DEFAULT_UI_FONT, UI_FONT_OPTIONS,
|
||||
import { useI18n, type Locale } from '@/lib/i18n';
|
||||
import { useConfigStore } from '@/stores/useConfigStore';
|
||||
import { normalizeMobileKeyboardMode, supportsMobileKeyboardResizeContent, type MobileKeyboardMode } from '@/lib/mobileKeyboardMode';
|
||||
import { getStoredMobileLayoutPreference, setStoredMobileLayoutPreference, type MobileLayoutPreference } from '@/lib/mobileLayoutPreference';
|
||||
import {
|
||||
setDirectoryShowHidden,
|
||||
useDirectoryShowHidden,
|
||||
@@ -151,17 +150,6 @@ const MOBILE_KEYBOARD_MODE_OPTIONS: Option<MobileKeyboardMode>[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const MOBILE_LAYOUT_OPTIONS: Array<{ value: MobileLayoutPreference; labelKey: string }> = [
|
||||
{
|
||||
value: 'default',
|
||||
labelKey: 'settings.openchamber.visual.option.mobileLayout.default',
|
||||
},
|
||||
{
|
||||
value: 'new',
|
||||
labelKey: 'settings.openchamber.visual.option.mobileLayout.new',
|
||||
},
|
||||
];
|
||||
|
||||
type PwaInstallNameWindow = Window & {
|
||||
__OPENCHAMBER_SET_PWA_INSTALL_NAME__?: (value: string) => string;
|
||||
__OPENCHAMBER_SET_PWA_ORIENTATION__?: (value: 'system' | 'portrait' | 'landscape') => 'system' | 'portrait' | 'landscape';
|
||||
@@ -629,10 +617,9 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
const hasThemeSettings = shouldShow('theme') && !isVSCode;
|
||||
const showWindowControlsPositionSetting = shouldShow('windowControlsPosition') && showWindowControlsPosition;
|
||||
const hasLocalizationSettings = shouldShow('theme') || shouldShow('timeFormat') || shouldShow('weekStart');
|
||||
const showMobileLayoutSetting = isMobile && isWebRuntime() && !isDesktopShell() && !isVSCode;
|
||||
const hasAppearanceSettings = isVSCode
|
||||
? hasLocalizationSettings
|
||||
: (shouldShow('theme') || showWindowControlsPositionSetting || showMobileLayoutSetting || shouldShow('pwaInstallName') || shouldShow('pwaOrientation') || shouldShow('timeFormat') || shouldShow('weekStart'));
|
||||
: (shouldShow('theme') || showWindowControlsPositionSetting || shouldShow('pwaInstallName') || shouldShow('pwaOrientation') || shouldShow('timeFormat') || shouldShow('weekStart'));
|
||||
const hasLayoutSettings = shouldShow('fontSize') || shouldShow('terminalFontSize') || shouldShow('editorFontSize') || shouldShow('spacing') || (shouldShow('inputBarOffset') && isMobile);
|
||||
const hasNavigationSettings = (shouldShow('terminalQuickKeys') && !isMobile) || ((shouldShow('terminalShell') || shouldShow('terminalLoginShell')) && !isVSCode) || shouldShow('fileEditorKeymap') || shouldShow('autoSaveEnabled') || (shouldShow('expandedEditorToolbar') && !isVSCode);
|
||||
const hasBehaviorSettings = shouldShow('mermaidRendering')
|
||||
@@ -723,7 +710,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
? [...terminalLoginShells.filter((shell) => shell !== terminalShell), terminalShell]
|
||||
: terminalLoginShells.filter((shell) => shell !== terminalShell));
|
||||
};
|
||||
const [mobileLayoutPreference, setMobileLayoutPreference] = React.useState<MobileLayoutPreference>(() => getStoredMobileLayoutPreference());
|
||||
const [pwaInstallName, setPwaInstallName] = React.useState('');
|
||||
const [pwaOrientation, setPwaOrientation] = React.useState<'system' | 'portrait' | 'landscape'>('system');
|
||||
const selectedTimeFormatLabel = React.useMemo(() => {
|
||||
@@ -743,16 +729,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
return option ? tUnsafe(option.labelKey) : undefined;
|
||||
}, [mobileKeyboardMode, tUnsafe]);
|
||||
|
||||
const handleMobileLayoutPreferenceChange = React.useCallback((value: MobileLayoutPreference) => {
|
||||
if (value === mobileLayoutPreference) {
|
||||
return;
|
||||
}
|
||||
|
||||
setMobileLayoutPreference(value);
|
||||
setStoredMobileLayoutPreference(value);
|
||||
window.location.reload();
|
||||
}, [mobileLayoutPreference]);
|
||||
|
||||
const applyPwaInstallName = React.useCallback(async (value: string) => {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
@@ -877,21 +853,6 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
||||
))}
|
||||
</SettingsRadioGroup>
|
||||
|
||||
{showMobileLayoutSetting && (
|
||||
<SettingsInset>
|
||||
<SettingsStackedField label={t('settings.openchamber.visual.section.mobileLayout')}>
|
||||
<SettingsChipGroup
|
||||
value={mobileLayoutPreference}
|
||||
options={MOBILE_LAYOUT_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: tUnsafe(option.labelKey),
|
||||
}))}
|
||||
onChange={handleMobileLayoutPreferenceChange}
|
||||
aria-label={t('settings.openchamber.visual.section.mobileLayout')}
|
||||
/>
|
||||
</SettingsStackedField>
|
||||
</SettingsInset>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={SETTINGS_FIELDS_STACK_CLASS}>
|
||||
|
||||
Reference in New Issue
Block a user