feat(pwa): add install orientation setting (#900)

This commit is contained in:
vhqtvn
2026-04-21 23:17:34 +03:00
committed by GitHub
parent 125094d371
commit 8e86891d8e
9 changed files with 197 additions and 14 deletions
@@ -1,4 +1,13 @@
const DEFAULT_PWA_APP_NAME = 'OpenChamber - AI Coding Assistant';
const mapPwaOrientationToManifest = (value) => {
if (value === 'portrait') {
return 'portrait-primary';
}
if (value === 'landscape') {
return 'landscape-primary';
}
return undefined;
};
export const registerPwaManifestRoute = (app, dependencies) => {
const {
@@ -8,6 +17,7 @@ export const registerPwaManifestRoute = (app, dependencies) => {
getOpenCodeAuthHeaders,
readSettingsFromDiskMigrated,
normalizePwaAppName,
normalizePwaOrientation,
} = dependencies;
const recentPwaSessionsCache = new Map();
@@ -180,18 +190,26 @@ export const registerPwaManifestRoute = (app, dependencies) => {
}
const queryOverrideName = normalizePwaAppName(queryValueRaw, '');
const hasOrientationOverride = typeof req.query?.orientation === 'string';
const queryOverrideOrientation = normalizePwaOrientation(req.query?.orientation, 'system');
let storedName = '';
let storedOrientation = 'system';
try {
const settings = await readSettingsFromDiskMigrated();
storedName = normalizePwaAppName(settings?.pwaAppName, '');
storedOrientation = normalizePwaOrientation(settings?.pwaOrientation, 'system');
} catch {
storedName = '';
storedOrientation = 'system';
}
const appName = hasQueryOverride
? (queryOverrideName || DEFAULT_PWA_APP_NAME)
: (storedName || DEFAULT_PWA_APP_NAME);
const manifestOrientation = mapPwaOrientationToManifest(
hasOrientationOverride ? queryOverrideOrientation : storedOrientation
);
const shortName = appName.length > 30 ? appName.slice(0, 30) : appName;
const recentSessionShortcuts = await getRecentPwaSessionShortcuts(req);
@@ -206,7 +224,7 @@ export const registerPwaManifestRoute = (app, dependencies) => {
display: 'standalone',
background_color: '#151313',
theme_color: '#edb449',
orientation: 'any',
...(manifestOrientation ? { orientation: manifestOrientation } : {}),
icons: [
{ src: '/pwa-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' },
{ src: '/pwa-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' },
@@ -18,6 +18,7 @@ export const createSettingsHelpers = (dependencies) => {
} = dependencies;
const PWA_APP_NAME_MAX_LENGTH = 64;
const PWA_ORIENTATION_VALUES = new Set(['system', 'portrait', 'landscape']);
const normalizePwaAppName = (value, fallback = '') => {
if (typeof value !== 'string') {
@@ -30,6 +31,17 @@ export const createSettingsHelpers = (dependencies) => {
return normalized.slice(0, PWA_APP_NAME_MAX_LENGTH);
};
const normalizePwaOrientation = (value, fallback = 'system') => {
if (typeof value !== 'string') {
return fallback;
}
const normalized = value.trim();
if (PWA_ORIENTATION_VALUES.has(normalized)) {
return normalized;
}
return fallback;
};
const sanitizeSettingsUpdate = (payload) => {
if (!payload || typeof payload !== 'object') {
return {};
@@ -292,6 +304,9 @@ export const createSettingsHelpers = (dependencies) => {
if (typeof candidate.pwaAppName === 'string') {
result.pwaAppName = normalizePwaAppName(candidate.pwaAppName, undefined);
}
if (typeof candidate.pwaOrientation === 'string') {
result.pwaOrientation = normalizePwaOrientation(candidate.pwaOrientation, undefined);
}
if (typeof candidate.toolCallExpansion === 'string') {
const mode = candidate.toolCallExpansion.trim();
if (mode === 'collapsed' || mode === 'activity' || mode === 'detailed' || mode === 'changes') {
@@ -602,11 +617,13 @@ export const createSettingsHelpers = (dependencies) => {
const bookmarks = normalizeStringArray(settings.securityScopedBookmarks);
const hasManagedRemoteTunnelToken = typeof settings?.managedRemoteTunnelToken === 'string' && settings.managedRemoteTunnelToken.trim().length > 0;
const pwaAppName = normalizePwaAppName(settings?.pwaAppName, '');
const pwaOrientation = normalizePwaOrientation(settings?.pwaOrientation, 'system');
return {
...sanitized,
hasManagedRemoteTunnelToken,
...(pwaAppName ? { pwaAppName } : {}),
pwaOrientation,
approvedDirectories: approved,
securityScopedBookmarks: bookmarks,
pinnedDirectories: normalizeStringArray(settings.pinnedDirectories),
@@ -622,6 +639,7 @@ export const createSettingsHelpers = (dependencies) => {
return {
normalizePwaAppName,
normalizePwaOrientation,
sanitizeSettingsUpdate,
mergePersistedSettings,
formatSettingsResponse,
@@ -12,6 +12,7 @@ export const createStaticRoutesRuntime = (dependencies) => {
getOpenCodeAuthHeaders,
readSettingsFromDiskMigrated,
normalizePwaAppName,
normalizePwaOrientation,
} = dependencies;
const resolveDistPath = () => {
@@ -43,6 +44,7 @@ export const createStaticRoutesRuntime = (dependencies) => {
getOpenCodeAuthHeaders,
readSettingsFromDiskMigrated,
normalizePwaAppName,
normalizePwaOrientation,
});
app.get(/^(?!\/api|.*\.(js|css|svg|png|jpg|jpeg|gif|ico|woff|woff2|ttf|eot|map)).*$/, (_req, res) => {