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