mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-08-29 00:01:29 +00:00
ENH - phone open animation
This commit is contained in:
+49
-39
@@ -31,6 +31,7 @@ type AppMessage = {
|
||||
|
||||
const REFERENCE_VIEWPORT_WIDTH = 1920
|
||||
const REFERENCE_VIEWPORT_HEIGHT = 1080
|
||||
const PHONE_BASE_SCALE = 0.69
|
||||
|
||||
const phone = usePhoneStore()
|
||||
const clock = useClockStore()
|
||||
@@ -45,8 +46,11 @@ const viewportScale = ref(
|
||||
),
|
||||
)
|
||||
const phoneResolutionStyle = computed<CSSProperties>(() => ({
|
||||
'--phone-edge-gap': `${24 * viewportScale.value}px`,
|
||||
'--phone-zoom':
|
||||
viewportScale.value * (phone.preferences.settings.phoneScale / 100),
|
||||
viewportScale.value *
|
||||
PHONE_BASE_SCALE *
|
||||
(phone.preferences.settings.phoneScale / 100),
|
||||
}))
|
||||
const phoneFrameImage = computed(
|
||||
() => PHONE_FRAME_IMAGES[phone.preferences.settings.frame],
|
||||
@@ -134,43 +138,49 @@ onBeforeUnmount(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main
|
||||
v-if="phone.isOpen || notifications.current"
|
||||
class="phone-stage"
|
||||
:class="{ 'phone-stage--peek': notifications.isPeeking }"
|
||||
>
|
||||
<div class="phone-resolution-wrapper" :style="phoneResolutionStyle">
|
||||
<section class="phone-device" :aria-label="phone.t('Common.phone')">
|
||||
<div class="phone-screen" :class="{ 'phone-screen--app': isAppRoute }">
|
||||
<k-app
|
||||
theme="ios"
|
||||
:dark="phone.isDarkMode"
|
||||
safe-areas
|
||||
class="phone-app"
|
||||
:class="{
|
||||
dark: phone.isDarkMode,
|
||||
'phone-app--light': !phone.isDarkMode,
|
||||
}"
|
||||
<Transition name="phone-lift" appear>
|
||||
<main
|
||||
v-if="phone.isOpen || notifications.current"
|
||||
class="phone-stage"
|
||||
:class="{ 'phone-stage--peek': notifications.isPeeking }"
|
||||
:style="phoneResolutionStyle"
|
||||
>
|
||||
<div class="phone-resolution-wrapper">
|
||||
<section class="phone-device" :aria-label="phone.t('Common.phone')">
|
||||
<div
|
||||
class="phone-screen"
|
||||
:class="{ 'phone-screen--app': isAppRoute }"
|
||||
>
|
||||
<PhoneStatusBar />
|
||||
<SpringboardView />
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition name="app-window">
|
||||
<component :is="Component" v-if="isAppRoute" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
<PhoneHomeIndicator />
|
||||
<PhoneNotifications />
|
||||
</k-app>
|
||||
</div>
|
||||
<img
|
||||
class="phone-device__frame"
|
||||
:src="phoneFrameImage"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
draggable="false"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
<k-app
|
||||
theme="ios"
|
||||
:dark="phone.isDarkMode"
|
||||
safe-areas
|
||||
class="phone-app"
|
||||
:class="{
|
||||
dark: phone.isDarkMode,
|
||||
'phone-app--light': !phone.isDarkMode,
|
||||
}"
|
||||
>
|
||||
<PhoneStatusBar />
|
||||
<SpringboardView />
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition name="app-window">
|
||||
<component :is="Component" v-if="isAppRoute" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
<PhoneHomeIndicator />
|
||||
<PhoneNotifications />
|
||||
</k-app>
|
||||
</div>
|
||||
<img
|
||||
class="phone-device__frame"
|
||||
:src="phoneFrameImage"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
draggable="false"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
@@ -34,17 +34,30 @@ button {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
.phone-stage--peek {
|
||||
place-items: end;
|
||||
padding: 0 24px;
|
||||
padding: 0 var(--phone-edge-gap, 24px) var(--phone-edge-gap, 24px) 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.phone-stage--peek .phone-device {
|
||||
transform: translateY(calc(100% - 190px));
|
||||
transform-origin: right bottom;
|
||||
}
|
||||
.phone-lift-enter-active {
|
||||
transition: opacity 0.52s linear;
|
||||
}
|
||||
.phone-lift-leave-active {
|
||||
transition: opacity 0.36s linear;
|
||||
}
|
||||
.phone-lift-enter-active .phone-resolution-wrapper {
|
||||
transition: transform 0.52s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
.phone-lift-leave-active .phone-resolution-wrapper {
|
||||
transition: transform 0.36s cubic-bezier(0.7, 0, 0.84, 0);
|
||||
}
|
||||
.phone-lift-enter-from .phone-resolution-wrapper,
|
||||
.phone-lift-leave-to .phone-resolution-wrapper {
|
||||
transform: translateY(calc(100% + var(--phone-edge-gap, 24px)));
|
||||
}
|
||||
.phone-resolution-wrapper {
|
||||
width: 390px;
|
||||
height: 844px;
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('preferences', () => {
|
||||
expect(value.settings.frame).toBe('black')
|
||||
expect(value.settings.notificationVolume).toBe(0)
|
||||
expect(value.settings.notificationDurationSeconds).toBe(30)
|
||||
expect(value.settings.phoneScale).toBe(115)
|
||||
expect(value.settings.phoneScale).toBe(150)
|
||||
expect(value.settings.ringtoneVolume).toBe(100)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -13,6 +13,9 @@ export const PHONE_FRAME_IDS = [
|
||||
export const RINGTONE_IDS = ['skyline', 'horizon', 'pulse'] as const
|
||||
export const NOTIFICATION_SOUND_IDS = ['chime', 'signal', 'soft'] as const
|
||||
export const WALLPAPER_IDS = ['midnight', 'aurora', 'ember'] as const
|
||||
export const PHONE_SCALE_MIN = 50
|
||||
export const PHONE_SCALE_MAX = 150
|
||||
export const PHONE_SCALE_STEP = 5
|
||||
|
||||
export type AppearanceMode = (typeof APPEARANCE_MODE_IDS)[number]
|
||||
export type PhoneFrameId = (typeof PHONE_FRAME_IDS)[number]
|
||||
@@ -167,8 +170,8 @@ export function parsePhonePreferences(raw: string | null): PhonePreferencesV1 {
|
||||
phoneScale: readNumber(
|
||||
settings.phoneScale,
|
||||
defaults.phoneScale,
|
||||
85,
|
||||
115,
|
||||
PHONE_SCALE_MIN,
|
||||
PHONE_SCALE_MAX,
|
||||
),
|
||||
ringtone: readChoice(
|
||||
settings.ringtone,
|
||||
|
||||
@@ -31,6 +31,9 @@ import {
|
||||
APPEARANCE_MODE_IDS,
|
||||
NOTIFICATION_SOUND_IDS,
|
||||
PHONE_FRAME_IDS,
|
||||
PHONE_SCALE_MAX,
|
||||
PHONE_SCALE_MIN,
|
||||
PHONE_SCALE_STEP,
|
||||
RINGTONE_IDS,
|
||||
WALLPAPER_IDS,
|
||||
type AppearanceMode,
|
||||
@@ -624,9 +627,9 @@ function selectNotificationSound(sound: NotificationSoundId): void {
|
||||
<k-range
|
||||
class="w-full"
|
||||
:value="phone.preferences.settings.phoneScale"
|
||||
:min="85"
|
||||
:max="115"
|
||||
:step="5"
|
||||
:min="PHONE_SCALE_MIN"
|
||||
:max="PHONE_SCALE_MAX"
|
||||
:step="PHONE_SCALE_STEP"
|
||||
:aria-label="phone.t('Apps.settings.phoneScale')"
|
||||
@input="updateNumberPreference('phoneScale', $event)"
|
||||
/>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sky Phone</title>
|
||||
<script type="module" crossorigin src="./assets/sky-index-DOaxLsz3.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/sky-index-It2eOh-6.css">
|
||||
<script type="module" crossorigin src="./assets/sky-index-D8rAzywY.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/sky-index-CCqdfChw.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
Reference in New Issue
Block a user