diff --git a/frontend/src/App.vue b/frontend/src/App.vue index f5ef846..b5a81b7 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1885,6 +1885,8 @@ onBeforeUnmount(() => { class="phone-screen" :class="{ 'phone-screen--app': isAppRoute || isDevelopmentRoute, + 'phone-screen--camera-landscape': + activeAppId === 'camera' && phone.cameraLandscape, 'phone-app--light': !displayedDarkMode, [`phone-app--${phone.preferences.settings.graphicsMode}`]: true, }" diff --git a/frontend/src/assets/main.css b/frontend/src/assets/main.css index 6d7181a..48ff04e 100644 --- a/frontend/src/assets/main.css +++ b/frontend/src/assets/main.css @@ -460,6 +460,7 @@ button { } } .phone-screen { + --phone-screen-portrait-ratio: 2.30951; position: relative; container-type: size; margin: auto; @@ -470,6 +471,12 @@ button { background: #08080a; border-radius: 40px; } +.phone-screen--camera-landscape { + background: transparent; +} +.phone-screen--camera-landscape .springboard { + visibility: hidden; +} .phone-app { position: absolute !important; inset: 0 !important; @@ -3239,6 +3246,9 @@ button { backface-visibility: hidden; will-change: transform, border-radius, opacity; } +.app-window--camera-landscape { + background: transparent; +} .app-window--citywarn { backface-visibility: visible; filter: none; diff --git a/frontend/src/views/PhoneAppWindow.vue b/frontend/src/views/PhoneAppWindow.vue index 0dcc86e..19e4d3a 100644 --- a/frontend/src/views/PhoneAppWindow.vue +++ b/frontend/src/views/PhoneAppWindow.vue @@ -30,7 +30,11 @@ const launchStyle = computed(() => {
{ expect(cameraView).not.toContain('k-navbar') }) + it('stays dark when the global phone appearance is light', () => { + const cameraPageTag = cameraView.match(/]*>/s)?.[0] + + expect(cameraPageTag).toBeDefined() + expect(cameraPageTag).toMatch(/\bdark\b/) + expect(cameraView).toMatch( + /\.camera-page\s*\{[^}]*--sky-bg:\s*#000;[^}]*--sky-text:\s*#fff;[^}]*background:\s*var\(--sky-bg\);[^}]*color:\s*var\(--sky-text\);/s, + ) + }) + + it('fills the translucent landscape shell without letterbox gaps', () => { + const landscapeViewport = cameraView.match( + /\.camera-page--landscape \.camera-viewport\s*\{([^}]*)\}/s, + )?.[1] + + expect(cameraView).toMatch( + /\.camera-page--landscape\s*\{[^}]*--sky-bg:\s*rgba\(0, 0, 0, 0\.42\);/s, + ) + expect(landscapeViewport).toBeDefined() + expect(landscapeViewport).toContain('top: 50%') + expect(landscapeViewport).toContain( + 'width: calc(100% * var(--phone-screen-portrait-ratio))', + ) + expect(landscapeViewport).toContain( + 'aspect-ratio: var(--phone-screen-portrait-ratio)', + ) + expect(landscapeViewport).not.toContain('16 / 9') + expect(cameraView).toMatch( + /\.camera-page--landscape \.camera-shade\s*\{[^}]*linear-gradient\([^)]*90deg,[^)]*rgba\(0, 0, 0, 0\.42\) 0 18%,[^)]*transparent 18% 75%,[^)]*rgba\(0, 0, 0, 0\.42\) 75% 100%/s, + ) + expect(appShell).toMatch( + /'phone-screen--camera-landscape':\s*activeAppId === 'camera' && phone\.cameraLandscape/, + ) + expect(appWindow).toMatch( + /'app-window--camera-landscape':\s*app\.id === 'camera' && phone\.cameraLandscape/, + ) + expect(shellStyles).toMatch( + /\.phone-screen\s*\{[^}]*--phone-screen-portrait-ratio:\s*2\.30951;/s, + ) + expect(shellStyles).toMatch( + /\.phone-screen--camera-landscape\s*\{[^}]*background:\s*transparent;/s, + ) + expect(shellStyles).toMatch( + /\.phone-screen--camera-landscape \.springboard\s*\{[^}]*visibility:\s*hidden;/s, + ) + expect(shellStyles).toMatch( + /\.app-window--camera-landscape\s*\{[^}]*background:\s*transparent;/s, + ) + }) + + it('renders camera notices as plain text without a glass pill', () => { + const noticeMarkup = cameraView.slice( + cameraView.indexOf(' { + const zoomControl = cameraView.slice( + cameraView.indexOf('
'), + cameraView.indexOf('
@@ -685,10 +693,15 @@ onBeforeUnmount(() => {