Compare commits
11 Commits
0c75d9a9f9
...
7842771af2
Author | SHA1 | Date |
---|---|---|
|
7842771af2 | |
|
3734fc8514 | |
|
c82cf4457e | |
|
9dc2ea97ec | |
|
f6f6384acf | |
|
58bdd7c129 | |
|
911c368d05 | |
|
be2e596027 | |
|
f6c2fae089 | |
|
25ae63f6cd | |
|
73f7972d62 |
|
@ -4,6 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="muted && appearNote" :class="$style.muted" @click="muted = false">
|
||||
<I18n :src="i18n.ts.userSaysSomething" tag="small">
|
||||
<template #name>
|
||||
|
@ -135,6 +136,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -184,7 +186,7 @@ if (props.setNote) {
|
|||
const {
|
||||
note, interruptorUnwatch, executeInterruptor,
|
||||
isRenote, isMyRenote, appearNote,
|
||||
urls, isLong, canRenote,
|
||||
urls, isLong, canRenote, showTicker,
|
||||
} = noteManager.getNoteViewBase(props.note.id);
|
||||
|
||||
const el = shallowRef<HTMLElement>();
|
||||
|
@ -194,7 +196,7 @@ const renoteTime = shallowRef<HTMLElement>();
|
|||
const reactButton = shallowRef<HTMLElement>();
|
||||
const clipButton = shallowRef<HTMLElement>();
|
||||
const showContent = ref(false);
|
||||
const collapsed = ref(appearNote.value?.cw == null && isLong);
|
||||
const collapsed = ref(appearNote.value?.cw == null && isLong.value);
|
||||
const isDeleted = ref(note === null);
|
||||
const muted = ref(appearNote.value ? checkWordMute(appearNote.value, $i, defaultStore.state.mutedWords) : false);
|
||||
const translation = ref<any>(null);
|
||||
|
@ -473,7 +475,8 @@ function showReactions(): void {
|
|||
}
|
||||
|
||||
const unuse = ref<() => void>();
|
||||
unuse.value = noteManager.useNote(props.note.id, true).unuse;
|
||||
|
||||
unuse.value = noteManager.useNote(appearNote.value?.id ?? props.note.id, true).unuse;
|
||||
|
||||
onMounted(() => {
|
||||
executeInterruptor();
|
||||
|
@ -488,19 +491,20 @@ onUnmounted(() => {
|
|||
});
|
||||
|
||||
onActivated(() => {
|
||||
if (!unuse.value) {
|
||||
unuse.value = noteManager.useNote(props.note.id, true).unuse;
|
||||
if (!unuse.value && appearNote.value) {
|
||||
unuse.value = noteManager.useNote(appearNote.value?.id ?? props.note.id, true).unuse;
|
||||
}
|
||||
});
|
||||
|
||||
onDeactivated(() => {
|
||||
const _unuse = unuse.value;
|
||||
unuse.value = undefined;
|
||||
// 不要なキャッシュ消去や通信を防止するため遅延させる
|
||||
setTimeout(() => {
|
||||
if (unuse.value) {
|
||||
unuse.value();
|
||||
unuse.value = undefined;
|
||||
}
|
||||
}, 1000);
|
||||
if (_unuse) {
|
||||
setTimeout(() => {
|
||||
_unuse();
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -407,7 +407,7 @@ function blur() {
|
|||
el.value?.blur();
|
||||
}
|
||||
|
||||
const { note: fetching, unuse } = noteManager.useNote(props.note.id, true);
|
||||
const { note: fetching, unuse } = noteManager.useNote(appearNote.value?.id ?? props.note.id, true);
|
||||
|
||||
onMounted(async () => {
|
||||
await fetching;
|
||||
|
|
|
@ -33,12 +33,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { shallowRef } from 'vue';
|
||||
import { computed, shallowRef } from 'vue';
|
||||
import MkNote from '@/components/MkNote.vue';
|
||||
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
|
||||
import MkDateSeparatedList, { MisskeyEntity } from '@/components/MkDateSeparatedList.vue';
|
||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||
import { i18n } from '@/i18n';
|
||||
import { infoImageUrl } from '@/instance';
|
||||
import { noteManager } from '@/scripts/entity-manager';
|
||||
import { Note } from 'misskey-js/built/entities';
|
||||
|
||||
const props = defineProps<{
|
||||
pagination: Paging;
|
||||
|
@ -47,6 +49,23 @@ const props = defineProps<{
|
|||
|
||||
const pagingComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
|
||||
const transform = (notes: Note[]): MisskeyEntity[] => {
|
||||
return notes.map(note => {
|
||||
noteManager.set(note);
|
||||
return {
|
||||
id: note.id,
|
||||
createdAt: note.createdAt,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const pagination = computed(() => {
|
||||
return {
|
||||
transform,
|
||||
...props.pagination,
|
||||
};
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
pagingComponent,
|
||||
});
|
||||
|
|
|
@ -26,9 +26,6 @@ import { $i } from '@/account';
|
|||
import { defaultStore } from '@/store';
|
||||
import { i18n } from '@/i18n';
|
||||
import { instance } from '@/instance';
|
||||
import { noteManager } from '@/scripts/entity-manager';
|
||||
import { Note } from 'misskey-js/built/entities';
|
||||
import { MisskeyEntity } from '@/types/date-separated-list';
|
||||
|
||||
const props = defineProps<{
|
||||
src: string;
|
||||
|
@ -65,16 +62,6 @@ const prepend = note => {
|
|||
}
|
||||
};
|
||||
|
||||
const transform = (notes: Note[]): MisskeyEntity[] => {
|
||||
return notes.map(note => {
|
||||
noteManager.set(note);
|
||||
return {
|
||||
id: note.id,
|
||||
createdAt: note.createdAt,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
let endpoint;
|
||||
let query;
|
||||
let connection;
|
||||
|
@ -178,7 +165,6 @@ const pagination = {
|
|||
endpoint: endpoint,
|
||||
limit: 10,
|
||||
params: query,
|
||||
transform: transform,
|
||||
};
|
||||
|
||||
onUnmounted(() => {
|
||||
|
|
|
@ -47,6 +47,14 @@ type CachedNoteSource = Ref<OmittedNote | null>;
|
|||
type CachedNote = ComputedRef<Note | null>;
|
||||
type InterruptedCachedNote = Ref<Note | null>;
|
||||
|
||||
export function isRenote(note: Note | OmittedNote | null): boolean {
|
||||
return note != null &&
|
||||
note.renoteId != null &&
|
||||
note.text == null &&
|
||||
note.fileIds?.length === 0 &&
|
||||
note.poll == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* ノートのキャッシュを管理する
|
||||
* 基本的な使い方:
|
||||
|
@ -164,15 +172,16 @@ export class NoteManager {
|
|||
executeInterruptor: () => Promise<void>,
|
||||
} {
|
||||
const note = this.get(id);
|
||||
const interruptedNote = ref<Note | null>(unref(note));
|
||||
const interruptedNote = ref<Note | null>(note.value);
|
||||
|
||||
async function executeInterruptor() {
|
||||
if (note.value == null) {
|
||||
interruptedNote.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (noteViewInterruptors.length > 0) {
|
||||
interruptedNote.value = unref(note);
|
||||
if (noteViewInterruptors.length === 0) {
|
||||
interruptedNote.value = note.value;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -196,19 +205,13 @@ export class NoteManager {
|
|||
*/
|
||||
public getNoteViewBase(id: string) {
|
||||
const { interruptedNote: note, interruptorUnwatch, executeInterruptor } = this.getInterrupted(id);
|
||||
const isRenote = computed(() => (
|
||||
note.value != null &&
|
||||
note.value.renote != null &&
|
||||
note.value.text == null &&
|
||||
note.value.fileIds?.length === 0 &&
|
||||
note.value.poll == null
|
||||
));
|
||||
const isMyRenote = computed(() => $i && ($i.id === note.value?.userId));
|
||||
const appearNote = computed(() => (isRenote.value ? note.value?.renote : note.value) ?? null);
|
||||
const noteIsRenote = computed(() => isRenote(note.value));
|
||||
const isMyRenote = computed(() => noteIsRenote.value && $i && ($i.id === note.value?.userId));
|
||||
const appearNote = computed(() => (noteIsRenote.value ? note.value?.renote : note.value) ?? null);
|
||||
|
||||
return {
|
||||
note, interruptorUnwatch, executeInterruptor,
|
||||
isRenote, isMyRenote, appearNote,
|
||||
isRenote: noteIsRenote, isMyRenote, appearNote,
|
||||
urls: computed(() => appearNote.value?.text ? extractUrlFromMfm(mfm.parse(appearNote.value.text)) : null),
|
||||
isLong: computed(() => appearNote.value ? shouldCollapsed(appearNote.value) : false),
|
||||
canRenote: computed(() => (!!appearNote.value && !!$i) && (['public', 'home'].includes(appearNote.value.visibility) || appearNote.value.userId === $i.id)),
|
||||
|
@ -218,10 +221,13 @@ export class NoteManager {
|
|||
|
||||
public async fetch(id: string, force = false): Promise<CachedNote> {
|
||||
if (!force) {
|
||||
const updatedAt = this.updatedAt.get(id);
|
||||
const cachedNote = this.get(id);
|
||||
// Renoteの場合はRenote元の更新日時も考慮する
|
||||
const updatedAt = isRenote(cachedNote.value) ?
|
||||
this.updatedAt.get(id) :
|
||||
Math.max(this.updatedAt.get(id) ?? 0, this.updatedAt.get(cachedNote.value!.renoteId!) ?? 0);
|
||||
// 2分以上経過していない場合はキャッシュを返す
|
||||
if (updatedAt && Date.now() - updatedAt < 1000 * 120) {
|
||||
const cachedNote = this.get(id);
|
||||
if (cachedNote) {
|
||||
return cachedNote;
|
||||
}
|
||||
|
@ -233,14 +239,7 @@ export class NoteManager {
|
|||
return this.get(id)!;
|
||||
})
|
||||
.catch(() => {
|
||||
// エラーが発生した場合はとりあえず削除されたものとして扱う
|
||||
const cached = this.notesSource.get(id);
|
||||
if (cached) {
|
||||
cached.value = null;
|
||||
} else {
|
||||
this.notesSource.set(id, ref(null));
|
||||
}
|
||||
// updateAtはしない
|
||||
// エラーが発生した場合は何もしない
|
||||
return this.get(id)!;
|
||||
});
|
||||
}
|
||||
|
@ -368,7 +367,11 @@ export class NoteManager {
|
|||
this.capture(id);
|
||||
using = true;
|
||||
})
|
||||
.catch(err => console.error(err));
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
this.capture(id);
|
||||
using = true;
|
||||
});
|
||||
|
||||
const unuse = () => {
|
||||
CapturePromise.then(() => {
|
||||
|
|
Loading…
Reference in New Issue