Skip to content

Commit 11692e5

Browse files
fix(frontend): ユーザーの「概要」ページで引っ張って更新しても何も更新されない問題を修正 (#17965)
* fix(frontend): プロフィールページの pull to refresh が何も再取得しない (shiroha-a/misskey-ts#3150) Co-Authored-By: しろは <admin@k7a.org> * clean up * Update Changelog * clean up * Update Changelog * fix --------- Co-authored-by: しろは <admin@k7a.org>
1 parent 721948c commit 11692e5

4 files changed

Lines changed: 39 additions & 8 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
-
55

66
### Client
7-
-
7+
- Fix: ユーザーの「概要」ページで引っ張って更新しても何も更新されない問題を修正
8+
(Cherry-picked from https://github.com/shiroha-a/misskey-ts/commit/c946a42dbb71234dd9d9bbc14474853f0709431c)
89

910
### Server
1011
- Fix: HTTP Signaturesの`(request-target)`にクエリ文字列が含まれない問題を修正

‎packages/frontend/src/pages/user/home.vue‎

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ SPDX-License-Identifier: AGPL-3.0-only
6262
</span>
6363
</div>
6464
<div v-if="iAmModerator" class="moderationNote">
65-
<MkTextarea v-if="editModerationNote || (moderationNote != null && moderationNote !== '')" v-model="moderationNote" manualSave>
65+
<MkTextarea v-if="editModerationNote || (moderationNote != null && moderationNote !== '')" v-model="moderationNote" manualSave @savingStateChange="(changed) => { isModerationNoteDirty = changed; }">
6666
<template #label>{{ i18n.ts.moderationNote }}</template>
6767
<template #caption>{{ i18n.ts.moderationNoteDescription }}</template>
6868
</MkTextarea>
@@ -144,7 +144,7 @@ SPDX-License-Identifier: AGPL-3.0-only
144144
</template>
145145
<div v-if="!disableNotes">
146146
<MkLazy>
147-
<XTimeline :user="user"/>
147+
<XTimeline ref="timelineEl" :user="user"/>
148148
</MkLazy>
149149
</div>
150150
</div>
@@ -187,6 +187,7 @@ import MkSparkle from '@/components/MkSparkle.vue';
187187
import { prefer } from '@/preferences.js';
188188
import MkPullToRefresh from '@/components/MkPullToRefresh.vue';
189189
import { isBirthday } from '@/utility/is-birthday.js';
190+
import type XTimeline_TypeReferenceOnly from './index.timeline.vue';
190191
191192
function calcAge(birthdate: string): number {
192193
const date = new Date(birthdate);
@@ -209,9 +210,12 @@ const XTimeline = defineAsyncComponent(() => import('./index.timeline.vue'));
209210
210211
const props = withDefaults(defineProps<{
211212
user: Misskey.entities.UserDetailed;
213+
/** Refetches the user in place. Supplied by the parent page. */
214+
refreshUser?: () => Promise<void>;
212215
/** Test only; MkNotesTimeline currently causes problems in vitest */
213216
disableNotes?: boolean;
214217
}>(), {
218+
refreshUser: undefined,
215219
disableNotes: false,
216220
});
217221
@@ -226,13 +230,18 @@ const narrow = ref<null | boolean>(null);
226230
const rootEl = useTemplateRef('rootEl');
227231
const bannerEl = useTemplateRef('bannerEl');
228232
const memoTextareaEl = useTemplateRef('memoTextareaEl');
233+
const timelineEl = useTemplateRef<InstanceType<typeof XTimeline_TypeReferenceOnly>>('timelineEl');
229234
const memoDraft = ref(props.user.memo);
230235
const isEditingMemo = ref(false);
231236
const moderationNote = ref(props.user.moderationNote ?? '');
232237
const editModerationNote = ref(false);
238+
const isModerationNoteDirty = ref(false);
233239
234-
watch(moderationNote, async () => {
235-
await misskeyApi('admin/update-user-note', { userId: props.user.id, text: moderationNote.value });
240+
watch(moderationNote, async (newValue) => {
241+
// 再取得した値を同期しただけの場合は保存しない
242+
if (newValue === (user.value.moderationNote ?? '')) return;
243+
await misskeyApi('admin/update-user-note', { userId: user.value.id, text: newValue });
244+
user.value = { ...user.value, moderationNote: newValue };
236245
});
237246
238247
const style = computed(() => {
@@ -278,12 +287,20 @@ async function updateMemo() {
278287
isEditingMemo.value = false;
279288
}
280289
281-
watch([props.user], () => {
290+
watch(() => props.user, () => {
291+
user.value = props.user;
292+
// 編集中は上書きしない (入力中の内容を消してしまう)
293+
if (!isModerationNoteDirty.value) moderationNote.value = props.user.moderationNote ?? '';
294+
if (isEditingMemo.value) return;
282295
memoDraft.value = props.user.memo;
283296
});
284297
298+
// ここでは失敗は握りつぶす(Pull to Refreshがもどらなくなるので)
285299
async function reload() {
286-
// TODO
300+
await Promise.allSettled([
301+
props.refreshUser?.(),
302+
timelineEl.value?.reload(),
303+
]);
287304
}
288305
289306
let bannerParallaxResizeObserver: ResizeObserver | null = null;

‎packages/frontend/src/pages/user/index.timeline.vue‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ const notesPaginator = markRaw(new Paginator('users/notes', {
5454
withFiles: tab.value === 'files',
5555
})),
5656
}));
57+
58+
defineExpose({
59+
reload: () => (tab.value === 'featured' ? featuredPaginator : notesPaginator).reload(),
60+
});
5761
</script>
5862

5963
<style lang="scss" module>

‎packages/frontend/src/pages/user/index.vue‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
66
<template>
77
<PageWithHeader v-model:tab="tab" :tabs="headerTabs" :actions="headerActions" :swipable="true">
88
<div v-if="user">
9-
<XHome v-if="tab === 'home'" :user="user" @showMoreFiles="() => { tab = 'files'; }"/>
9+
<XHome v-if="tab === 'home'" :user="user" :refreshUser="refreshUser" @showMoreFiles="() => { tab = 'files'; }"/>
1010
<XNotes v-else-if="tab === 'notes'" :user="user"/>
1111
<XFiles v-else-if="tab === 'files'" :user="user"/>
1212
<XActivity v-else-if="tab === 'activity'" :user="user"/>
@@ -62,6 +62,7 @@ const tab = ref(props.page);
6262
const user = ref<null | Misskey.entities.UserDetailed>(CTX_USER);
6363
const error = ref<any>(null);
6464
65+
// 初回読込時専用(使える場合はサーバーコンテキストから取得する)
6566
function fetchUser(): void {
6667
if (props.acct == null) return;
6768
@@ -87,6 +88,14 @@ watch(() => props.acct, fetchUser, {
8788
immediate: true,
8889
});
8990
91+
// 再読込時専用(強制fetch)
92+
async function refreshUser(): Promise<void> {
93+
if (props.acct == null) return;
94+
95+
const { username, host } = Misskey.acct.parse(props.acct);
96+
user.value = await misskeyApi('users/show', { username, host });
97+
}
98+
9099
const headerActions = computed(() => []);
91100
92101
const headerTabs = computed(() => user.value ? [{

0 commit comments

Comments
 (0)