Fix frame pacing

This commit is contained in:
2026-07-21 21:59:26 +10:00
parent 7d134ff8c9
commit db864af147
10 changed files with 202 additions and 22 deletions

View File

@@ -197,6 +197,19 @@ test('renders a suspended pushed sibling and evicts it after backing out', async
await expect(page.getByTestId('runtime-lab-view')).not.toHaveAttribute('data-mount-id', firstMountId!)
})
test('clicking the root tab from a pushed sibling collapses its back history', async ({ page }) => {
await page.goto('/profile')
await page.getByRole('link', { name: /Runtime stress lab/ }).click()
await expect(page).toHaveURL(/\/profile\/runtime-lab$/)
await page.getByRole('link', { name: /You/ }).click()
await expect(page).toHaveURL(/\/profile$/)
await waitForTransition(page)
await expect(page.locator('.nvr-navigator')).toHaveAttribute('data-native-can-go-back', 'false')
await expect(page.getByTestId('runtime-lab-view')).toHaveCount(0)
})
test('lazily caches a visited sibling and pauses its active work while hidden', async ({ page }) => {
await page.goto('/stories')
const stories = page.getByTestId('stories-view')
@@ -246,6 +259,22 @@ test('evicts a cached sibling when its dynamic entry guard rejects it', async ({
await expect(page.getByTestId('stories-view')).not.toHaveAttribute('data-mount-id', firstMountId!)
})
test('manually unloads an inactive route through the public API demo', async ({ page }) => {
await page.goto('/stories')
await page.getByRole('link', { name: /You/ }).click()
await expect(page).toHaveURL(/\/profile$/)
await waitForTransition(page)
await expect(page.getByTestId('stories-view')).toHaveCount(1)
await page.getByRole('link', { name: /Navigation lab/ }).click()
await expect(page).toHaveURL(/\/settings$/)
await waitForTransition(page)
await page.getByTestId('unload-stories').click()
await expect(page.getByTestId('unload-stories')).toHaveText('Unloaded 1 Stories view')
await expect(page.getByTestId('stories-view')).toHaveCount(0)
})
test('opens and dismisses the compose sheet', async ({ page }) => {
await page.goto('/inbox')
await page.getByRole('button', { name: 'Compose' }).click()

View File

@@ -52,6 +52,17 @@ html[data-pwa-edge-guard="active"] body {
left: 0;
}
/* Blurring content that is itself moving forces WebKit to repeatedly
rasterize the tab/header chrome. Use the same dark material without the
live blur for the short duration of a route transition. */
.app-frame:has(.nvr-router-view--interactive) :is(.app-tabs, .app-header, .composer) {
backdrop-filter: none;
}
.app-frame:has(.nvr-router-view--interactive) .app-tabs {
background: rgba(11, 13, 18, .98);
}
.screen {
width: 100%;
height: 100%;

View File

@@ -1,4 +1,5 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useNativeRouter } from '@native-vue-router/core'
import AppHeader from '../components/AppHeader.vue'
import { useDemoStore } from '../data'
@@ -6,6 +7,12 @@ import { pwaBuildId, pwaEnvironment } from '../pwa'
const store = useDemoStore()
const native = useNativeRouter()
const unloadResult = ref('Unload cached Stories')
function unloadStories() {
const count = native.unload('/stories')
unloadResult.value = count ? `Unloaded ${count} Stories view` : 'Stories is not cached'
}
</script>
<template>
@@ -32,6 +39,7 @@ const native = useNativeRouter()
<p>Sibling tabs are created on first visit, then retained. Back-stack screens stay warm only while they remain useful as a predictive-back target.</p>
</section>
<button class="reset-button reset-button--neutral" type="button" @click="native.trimCache()">Trim inactive view cache</button>
<button class="reset-button reset-button--neutral" data-testid="unload-stories" type="button" @click="unloadStories">{{ unloadResult }}</button>
<section class="settings-group">
<h2>Simulation</h2>
<label><span><strong>Network latency</strong><small>{{ store.settings.simulatedLatency }} ms</small></span><input v-model.number="store.settings.simulatedLatency" type="range" min="0" max="1200" step="20" /></label>