This commit is contained in:
syuilo
2025-03-14 19:53:06 +09:00
parent 386494dd6c
commit f40c5f27dd
4 changed files with 77 additions and 34 deletions

View File

@@ -47,7 +47,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
<div v-if="appearNote.channel" :class="$style.colorBar" :style="{ background: appearNote.channel.color }"></div>
<MkAvatar :class="$style.avatar" :user="appearNote.user" :link="!mock" :preview="!mock"/>
<MkAvatar :class="$style.avatar" :user="appearNote.user" :link="!mock" :preview="!mock" :style="{ viewTransitionName: transitionName }"/>
<div :class="$style.main">
<MkNoteHeader :note="appearNote" :mini="true"/>
<MkInstanceTicker v-if="showTicker" :host="appearNote.user.host" :instance="appearNote.user.instance"/>
@@ -223,6 +223,7 @@ import { focusPrev, focusNext } from '@/utility/focus.js';
import { getAppearNote } from '@/utility/get-appear-note.js';
import { prefer } from '@/preferences.js';
import { getPluginHandlers } from '@/plugin.js';
import { prepareViewTransition } from '@/page.js';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
@@ -235,6 +236,8 @@ const props = withDefaults(defineProps<{
provide('mock', props.mock);
const transitionName = prepareViewTransition('note-noteDetailed', props.note.id).avatar;
const emit = defineEmits<{
(ev: 'reaction', emoji: string): void;
(ev: 'removeReaction', emoji: string): void;
@@ -852,6 +855,8 @@ function emitUpdReaction(emoji: string, delta: number) {
position: sticky !important;
top: calc(22px + var(--MI-stickyTop, 0px));
left: 0;
contain: paint;
}
.main {

View File

@@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:exclude="pageCacheController"
>
<Suspense :timeout="0">
<component :is="currentPageComponent" :key="key" v-bind="Object.fromEntries(currentPageProps)"/>
<component :is="currentPageComponent" :key="key" v-bind="Object.fromEntries(currentPageProps)" :style="{ viewTransitionName: viewId }"/>
<template #fallback>
<MkLoading/>
@@ -41,7 +41,8 @@ if (router == null) {
const currentDepth = inject(DI.routerCurrentDepth, 0);
provide(DI.routerCurrentDepth, currentDepth + 1);
provide(DI.viewId, uuid());
const viewId = uuid();
provide(DI.viewId, viewId);
const viewTransitionId = ref(uuid());
provide(DI.viewTransitionId, viewTransitionId);
@@ -70,10 +71,11 @@ async function onChange({ resolved, key: newKey }) {
if (current == null || 'redirect' in current.route) return;
viewTransitionId.value = uuid();
await new Promise(resolve => setTimeout(resolve, 100));
await nextTick();
nextTick(() => {
console.log('onChange', viewTransitionId.value);
document.startViewTransition(() => new Promise((res) => {
console.log('startViewTransition', viewTransitionId.value);
currentPageComponent.value = current.route.component;
currentPageProps.value = current.props;
key.value = newKey + JSON.stringify(Object.fromEntries(current.props));
@@ -117,3 +119,31 @@ onBeforeUnmount(() => {
router.removeListener('change', onChange);
});
</script>
<style lang="scss" scoped>
@keyframes fade-in {
from { opacity: 0; }
}
@keyframes fade-out {
to { opacity: 0; }
}
@keyframes slide-from-right {
from { transform: translateX(300px); }
}
@keyframes slide-to-left {
to { transform: translateX(-300px); }
}
::view-transition-old(v-bind(viewId)) {
animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(v-bind(viewId)) {
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
</style>