enhance(frontend): KeepAliveのページキャッシュを削除できるように (#13180)
* enhance(frontend): 内部のページキャッシュを削除できるように * Update Changelog
This commit is contained in:
parent
16eccad492
commit
edb39a089d
|
@ -66,6 +66,7 @@
|
||||||
- Fix: 画像をクロップするとクロップ後の解像度が異様に低くなる問題の修正
|
- Fix: 画像をクロップするとクロップ後の解像度が異様に低くなる問題の修正
|
||||||
- Fix: 画像をクロップ時、正常に完了できない問題の修正
|
- Fix: 画像をクロップ時、正常に完了できない問題の修正
|
||||||
- Fix: キャプションが空の画像をクロップするとキャプションにnullという文字列が入ってしまう問題の修正
|
- Fix: キャプションが空の画像をクロップするとキャプションにnullという文字列が入ってしまう問題の修正
|
||||||
|
- Fix: プロフィールを編集してもリロードするまで反映されない問題を修正
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
- Enhance: 連合先のレートリミットに引っかかった際にリトライするようになりました
|
- Enhance: 連合先のレートリミットに引っかかった際にリトライするようになりました
|
||||||
|
|
|
@ -4,7 +4,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<KeepAlive :max="defaultStore.state.numberOfPageCache">
|
<KeepAlive
|
||||||
|
:max="defaultStore.state.numberOfPageCache"
|
||||||
|
:exclude="pageCacheController"
|
||||||
|
>
|
||||||
<Suspense :timeout="0">
|
<Suspense :timeout="0">
|
||||||
<component :is="currentPageComponent" :key="key" v-bind="Object.fromEntries(currentPageProps)"/>
|
<component :is="currentPageComponent" :key="key" v-bind="Object.fromEntries(currentPageProps)"/>
|
||||||
|
|
||||||
|
@ -16,9 +19,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { inject, onBeforeUnmount, provide, ref, shallowRef } from 'vue';
|
import { inject, onBeforeUnmount, provide, ref, shallowRef, computed, nextTick } from 'vue';
|
||||||
import { IRouter, Resolved } from '@/nirax.js';
|
import { IRouter, Resolved, RouteDef } from '@/nirax.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
import { globalEvents } from '@/events.js';
|
||||||
|
import MkLoadingPage from '@/pages/_loading_.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
router?: IRouter;
|
router?: IRouter;
|
||||||
|
@ -46,20 +51,47 @@ function resolveNested(current: Resolved, d = 0): Resolved | null {
|
||||||
}
|
}
|
||||||
|
|
||||||
const current = resolveNested(router.current)!;
|
const current = resolveNested(router.current)!;
|
||||||
const currentPageComponent = shallowRef(current.route.component);
|
const currentPageComponent = shallowRef('component' in current.route ? current.route.component : MkLoadingPage);
|
||||||
const currentPageProps = ref(current.props);
|
const currentPageProps = ref(current.props);
|
||||||
const key = ref(current.route.path + JSON.stringify(Object.fromEntries(current.props)));
|
const key = ref(current.route.path + JSON.stringify(Object.fromEntries(current.props)));
|
||||||
|
|
||||||
function onChange({ resolved, key: newKey }) {
|
function onChange({ resolved, key: newKey }) {
|
||||||
const current = resolveNested(resolved);
|
const current = resolveNested(resolved);
|
||||||
if (current == null) return;
|
if (current == null || 'redirect' in current.route) return;
|
||||||
currentPageComponent.value = current.route.component;
|
currentPageComponent.value = current.route.component;
|
||||||
currentPageProps.value = current.props;
|
currentPageProps.value = current.props;
|
||||||
key.value = current.route.path + JSON.stringify(Object.fromEntries(current.props));
|
key.value = current.route.path + JSON.stringify(Object.fromEntries(current.props));
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
// ページ遷移完了後に再びキャッシュを有効化
|
||||||
|
if (clearCacheRequested.value) {
|
||||||
|
clearCacheRequested.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
router.addListener('change', onChange);
|
router.addListener('change', onChange);
|
||||||
|
|
||||||
|
// #region キャッシュ制御
|
||||||
|
|
||||||
|
/**
|
||||||
|
* キャッシュクリアが有効になったら、全キャッシュをクリアする
|
||||||
|
*
|
||||||
|
* keepAlive側にwatcherがあるのですぐ消えるとはおもうけど、念のためページ遷移完了まではキャッシュを無効化しておく。
|
||||||
|
* キャッシュ有効時向けにexcludeを使いたい場合は、pageCacheControllerに並列に突っ込むのではなく、下に追記すること
|
||||||
|
*/
|
||||||
|
const pageCacheController = computed(() => clearCacheRequested.value ? /.*/ : undefined);
|
||||||
|
const clearCacheRequested = ref(false);
|
||||||
|
|
||||||
|
globalEvents.on('requestClearPageCache', () => {
|
||||||
|
if (_DEV_) console.log('clear page cache requested');
|
||||||
|
if (!clearCacheRequested.value) {
|
||||||
|
clearCacheRequested.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
router.removeListener('change', onChange);
|
router.removeListener('change', onChange);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EventEmitter } from 'eventemitter3';
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
import * as Misskey from 'misskey-js';
|
||||||
|
|
||||||
// TODO: 型付け
|
export const globalEvents = new EventEmitter<{
|
||||||
export const globalEvents = new EventEmitter();
|
themeChanged: () => void;
|
||||||
|
clientNotification: (notification: Misskey.entities.Notification) => void;
|
||||||
|
requestClearPageCache: () => void;
|
||||||
|
}>();
|
||||||
|
|
|
@ -125,6 +125,7 @@ import { langmap } from '@/scripts/langmap.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { claimAchievement } from '@/scripts/achievements.js';
|
import { claimAchievement } from '@/scripts/achievements.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
import { globalEvents } from '@/events.js';
|
||||||
import MkInfo from '@/components/MkInfo.vue';
|
import MkInfo from '@/components/MkInfo.vue';
|
||||||
import MkTextarea from '@/components/MkTextarea.vue';
|
import MkTextarea from '@/components/MkTextarea.vue';
|
||||||
|
|
||||||
|
@ -173,6 +174,7 @@ function saveFields() {
|
||||||
os.apiWithDialog('i/update', {
|
os.apiWithDialog('i/update', {
|
||||||
fields: fields.value.filter(field => field.name !== '' && field.value !== '').map(field => ({ name: field.name, value: field.value })),
|
fields: fields.value.filter(field => field.name !== '' && field.value !== '').map(field => ({ name: field.name, value: field.value })),
|
||||||
});
|
});
|
||||||
|
globalEvents.emit('requestClearPageCache');
|
||||||
}
|
}
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
|
@ -191,6 +193,7 @@ function save() {
|
||||||
isBot: !!profile.isBot,
|
isBot: !!profile.isBot,
|
||||||
isCat: !!profile.isCat,
|
isCat: !!profile.isCat,
|
||||||
});
|
});
|
||||||
|
globalEvents.emit('requestClearPageCache');
|
||||||
claimAchievement('profileFilled');
|
claimAchievement('profileFilled');
|
||||||
if (profile.name === 'syuilo' || profile.name === 'しゅいろ') {
|
if (profile.name === 'syuilo' || profile.name === 'しゅいろ') {
|
||||||
claimAchievement('setNameToSyuilo');
|
claimAchievement('setNameToSyuilo');
|
||||||
|
@ -222,6 +225,7 @@ function changeAvatar(ev) {
|
||||||
});
|
});
|
||||||
$i.avatarId = i.avatarId;
|
$i.avatarId = i.avatarId;
|
||||||
$i.avatarUrl = i.avatarUrl;
|
$i.avatarUrl = i.avatarUrl;
|
||||||
|
globalEvents.emit('requestClearPageCache');
|
||||||
claimAchievement('profileFilled');
|
claimAchievement('profileFilled');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -248,6 +252,7 @@ function changeBanner(ev) {
|
||||||
});
|
});
|
||||||
$i.bannerId = i.bannerId;
|
$i.bannerId = i.bannerId;
|
||||||
$i.bannerUrl = i.bannerUrl;
|
$i.bannerUrl = i.bannerUrl;
|
||||||
|
globalEvents.emit('requestClearPageCache');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue