Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance(frontend): KeepAliveのページキャッシュを削除できるように #13180

Merged
merged 2 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
- Fix: 画像をクロップするとクロップ後の解像度が異様に低くなる問題の修正
- Fix: 画像をクロップ時、正常に完了できない問題の修正
- Fix: キャプションが空の画像をクロップするとキャプションにnullという文字列が入ってしまう問題の修正
- Fix: プロフィールを編集してもリロードするまで反映されない問題を修正

### Server
- Enhance: 連合先のレートリミットに引っかかった際にリトライするようになりました
Expand Down
42 changes: 37 additions & 5 deletions packages/frontend/src/components/global/RouterView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ SPDX-License-Identifier: AGPL-3.0-only
-->

<template>
<KeepAlive :max="defaultStore.state.numberOfPageCache">
<KeepAlive
:max="defaultStore.state.numberOfPageCache"
:exclude="pageCacheController"
>
<Suspense :timeout="0">
<component :is="currentPageComponent" :key="key" v-bind="Object.fromEntries(currentPageProps)"/>

Expand All @@ -16,9 +19,11 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>

<script lang="ts" setup>
import { inject, onBeforeUnmount, provide, ref, shallowRef } from 'vue';
import { IRouter, Resolved } from '@/nirax.js';
import { inject, onBeforeUnmount, provide, ref, shallowRef, computed, nextTick } from 'vue';
import { IRouter, Resolved, RouteDef } from '@/nirax.js';
import { defaultStore } from '@/store.js';
import { globalEvents } from '@/events.js';
import MkLoadingPage from '@/pages/_loading_.vue';

const props = defineProps<{
router?: IRouter;
Expand Down Expand Up @@ -46,20 +51,47 @@ function resolveNested(current: Resolved, d = 0): Resolved | null {
}

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 key = ref(current.route.path + JSON.stringify(Object.fromEntries(current.props)));

function onChange({ resolved, key: newKey }) {
const current = resolveNested(resolved);
if (current == null) return;
if (current == null || 'redirect' in current.route) return;
currentPageComponent.value = current.route.component;
currentPageProps.value = current.props;
key.value = current.route.path + JSON.stringify(Object.fromEntries(current.props));

nextTick(() => {
// ページ遷移完了後に再びキャッシュを有効化
if (clearCacheRequested.value) {
clearCacheRequested.value = false;
}
});
}

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(() => {
router.removeListener('change', onChange);
});
Expand Down
8 changes: 6 additions & 2 deletions packages/frontend/src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
*/

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;
}>();
5 changes: 5 additions & 0 deletions packages/frontend/src/pages/settings/profile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ import { langmap } from '@/scripts/langmap.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { claimAchievement } from '@/scripts/achievements.js';
import { defaultStore } from '@/store.js';
import { globalEvents } from '@/events.js';
import MkInfo from '@/components/MkInfo.vue';
import MkTextarea from '@/components/MkTextarea.vue';

Expand Down Expand Up @@ -173,6 +174,7 @@ function saveFields() {
os.apiWithDialog('i/update', {
fields: fields.value.filter(field => field.name !== '' && field.value !== '').map(field => ({ name: field.name, value: field.value })),
});
globalEvents.emit('requestClearPageCache');
}

function save() {
Expand All @@ -191,6 +193,7 @@ function save() {
isBot: !!profile.isBot,
isCat: !!profile.isCat,
});
globalEvents.emit('requestClearPageCache');
claimAchievement('profileFilled');
if (profile.name === 'syuilo' || profile.name === 'しゅいろ') {
claimAchievement('setNameToSyuilo');
Expand Down Expand Up @@ -222,6 +225,7 @@ function changeAvatar(ev) {
});
$i.avatarId = i.avatarId;
$i.avatarUrl = i.avatarUrl;
globalEvents.emit('requestClearPageCache');
claimAchievement('profileFilled');
});
}
Expand All @@ -248,6 +252,7 @@ function changeBanner(ev) {
});
$i.bannerId = i.bannerId;
$i.bannerUrl = i.bannerUrl;
globalEvents.emit('requestClearPageCache');
});
}

Expand Down
Loading