implement note mutings and move favorited/renoted status into note entity directly
This commit is contained in:
parent
9bebf7718f
commit
7200c3d6c8
24 changed files with 342 additions and 181 deletions
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div
|
||||
v-if="!hardMuted && muted === false && !threadMuted"
|
||||
v-if="!hardMuted && muted === false && !threadMuted && !noteMuted"
|
||||
v-show="!isDeleted"
|
||||
ref="rootEl"
|
||||
v-hotkey="keymap"
|
||||
|
|
@ -125,9 +125,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
v-tooltip="renoteTooltip"
|
||||
:class="$style.footerButton"
|
||||
class="_button"
|
||||
:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
:style="appearNote.isRenoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
@click.stop
|
||||
@mousedown.prevent="renoted ? undoRenote(appearNote) : boostVisibility($event.shiftKey)"
|
||||
@mousedown.prevent="appearNote.isRenoted ? undoRenote(appearNote) : boostVisibility($event.shiftKey)"
|
||||
>
|
||||
<i class="ti ti-repeat"></i>
|
||||
<p v-if="appearNote.renoteCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.renoteCount) }}</p>
|
||||
|
|
@ -169,7 +169,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</article>
|
||||
</div>
|
||||
<div v-else-if="!hardMuted" :class="$style.muted" @click.stop="muted = false">
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :note="appearNote"></SkMutedNote>
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :noteMuted="noteMuted" :note="appearNote"></SkMutedNote>
|
||||
</div>
|
||||
<div v-else>
|
||||
<!--
|
||||
|
|
@ -311,8 +311,7 @@ const selfNoteIds = computed(() => getSelfNoteIds(props.note));
|
|||
const isLong = shouldCollapsed(appearNote.value, urls.value);
|
||||
const collapsed = ref(prefer.s.expandLongNote && appearNote.value.cw == null && isLong ? false : appearNote.value.cw == null && isLong);
|
||||
const isDeleted = ref(false);
|
||||
const renoted = ref(false);
|
||||
const { muted, hardMuted, threadMuted } = checkMutes(appearNote, computed(() => props.withHardMute));
|
||||
const { muted, hardMuted, threadMuted, noteMuted } = checkMutes(appearNote, computed(() => props.withHardMute));
|
||||
const translation = ref<Misskey.entities.NotesTranslateResponse | false | null>(null);
|
||||
const translating = ref(false);
|
||||
const showTicker = (prefer.s.instanceTicker === 'always') || (prefer.s.instanceTicker === 'remote' && appearNote.value.user.instance);
|
||||
|
|
@ -335,7 +334,7 @@ const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
|
|||
|
||||
const mergedCW = computed(() => computeMergedCw(appearNote.value));
|
||||
|
||||
const renoteTooltip = computeRenoteTooltip(renoted);
|
||||
const renoteTooltip = computeRenoteTooltip(appearNote);
|
||||
|
||||
let renoting = false;
|
||||
|
||||
|
|
@ -350,7 +349,7 @@ const keymap = {
|
|||
},
|
||||
'q': () => {
|
||||
if (renoteCollapsed.value) return;
|
||||
if (canRenote.value && !renoted.value && !renoting) renote(prefer.s.visibilityOnBoost);
|
||||
if (canRenote.value && !appearNote.value.isRenoted && !renoting) renote(prefer.s.visibilityOnBoost);
|
||||
},
|
||||
'm': () => {
|
||||
if (renoteCollapsed.value) return;
|
||||
|
|
@ -460,16 +459,6 @@ if (!props.mock) {
|
|||
});
|
||||
});
|
||||
|
||||
if ($i) {
|
||||
misskeyApi('notes/renotes', {
|
||||
noteId: appearNote.value.id,
|
||||
userId: $i.id,
|
||||
limit: 1,
|
||||
}).then((res) => {
|
||||
renoted.value = res.length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
||||
useTooltip(reactButton, async (showing) => {
|
||||
const reactions = await misskeyApiGet('notes/reactions', {
|
||||
|
|
@ -528,7 +517,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
channelId: appearNote.value.channelId,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
}).finally(() => { renoting = false; });
|
||||
}
|
||||
} else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) {
|
||||
|
|
@ -549,7 +538,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
renoteId: appearNote.value.id,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
}).finally(() => { renoting = false; });
|
||||
}
|
||||
}
|
||||
|
|
@ -728,7 +717,7 @@ function undoRenote(note) : void {
|
|||
noteId: note.id,
|
||||
});
|
||||
os.toast(i18n.ts.rmboost);
|
||||
renoted.value = false;
|
||||
appearNote.value.isRenoted = false;
|
||||
|
||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||
if (el) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div
|
||||
v-if="!muted && !threadMuted"
|
||||
v-if="!muted && !threadMuted && !noteMuted"
|
||||
v-show="!isDeleted"
|
||||
ref="rootEl"
|
||||
v-hotkey="keymap"
|
||||
|
|
@ -138,8 +138,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
v-tooltip="renoteTooltip"
|
||||
class="_button"
|
||||
:class="$style.noteFooterButton"
|
||||
:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
@mousedown.prevent="renoted ? undoRenote() : boostVisibility($event.shiftKey)"
|
||||
:style="appearNote.isRenoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
@mousedown.prevent="appearNote.isRenoted ? undoRenote() : boostVisibility($event.shiftKey)"
|
||||
>
|
||||
<i class="ti ti-repeat"></i>
|
||||
<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.renoteCount) }}</p>
|
||||
|
|
@ -227,7 +227,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</div>
|
||||
<div v-else class="_panel" :class="$style.muted" @click.stop="muted = false">
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :note="appearNote"></SkMutedNote>
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :noteMuted="noteMuted" :note="appearNote"></SkMutedNote>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -336,7 +336,6 @@ const galleryEl = useTemplateRef('galleryEl');
|
|||
const isMyRenote = $i && ($i.id === note.value.userId);
|
||||
const showContent = ref(prefer.s.uncollapseCW);
|
||||
const isDeleted = ref(false);
|
||||
const renoted = ref(false);
|
||||
const translation = ref<Misskey.entities.NotesTranslateResponse | false | null>(null);
|
||||
const translating = ref(false);
|
||||
const parsed = computed(() => appearNote.value.text ? mfm.parse(appearNote.value.text) : []);
|
||||
|
|
@ -352,24 +351,14 @@ const defaultLike = computed(() => prefer.s.like ? prefer.s.like : null);
|
|||
|
||||
const mergedCW = computed(() => computeMergedCw(appearNote.value));
|
||||
|
||||
const renoteTooltip = computeRenoteTooltip(renoted);
|
||||
const renoteTooltip = computeRenoteTooltip(appearNote);
|
||||
|
||||
const { muted, threadMuted } = checkMutes(appearNote);
|
||||
const { muted, threadMuted, noteMuted } = checkMutes(appearNote);
|
||||
|
||||
watch(() => props.expandAllCws, (expandAllCws) => {
|
||||
if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
|
||||
});
|
||||
|
||||
if ($i) {
|
||||
misskeyApi('notes/renotes', {
|
||||
noteId: appearNote.value.id,
|
||||
userId: $i.id,
|
||||
limit: 1,
|
||||
}).then((res) => {
|
||||
renoted.value = res.length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
let renoting = false;
|
||||
|
||||
const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
|
||||
|
|
@ -380,7 +369,7 @@ const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
|
|||
const keymap = {
|
||||
'r': () => reply(),
|
||||
'e|a|plus': () => react(),
|
||||
'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(prefer.s.visibilityOnBoost); },
|
||||
'q': () => { if (canRenote.value && !appearNote.value.isRenoted && !renoting) renote(prefer.s.visibilityOnBoost); },
|
||||
'm': () => showMenu(),
|
||||
'c': () => {
|
||||
if (!prefer.s.showClipButtonInNoteFooter) return;
|
||||
|
|
@ -554,7 +543,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
channelId: appearNote.value.channelId,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
}).finally(() => { renoting = false; });
|
||||
} else {
|
||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||
|
|
@ -573,7 +562,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
renoteId: appearNote.value.id,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
}).finally(() => { renoting = false; });
|
||||
}
|
||||
}
|
||||
|
|
@ -721,12 +710,12 @@ function undoReact(targetNote: Misskey.entities.Note): void {
|
|||
}
|
||||
|
||||
function undoRenote() : void {
|
||||
if (!renoted.value) return;
|
||||
if (!appearNote.value.isRenoted) return;
|
||||
misskeyApi('notes/unrenote', {
|
||||
noteId: appearNote.value.id,
|
||||
});
|
||||
os.toast(i18n.ts.rmboost);
|
||||
renoted.value = false;
|
||||
appearNote.value.isRenoted = false;
|
||||
|
||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||
if (el) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div v-show="!isDeleted" v-if="!muted && !threadMuted" ref="el" :class="[$style.root, { [$style.children]: depth > 1 }]">
|
||||
<div v-show="!isDeleted" v-if="!muted && !noteMuted" ref="el" :class="[$style.root, { [$style.children]: depth > 1 }]">
|
||||
<div :class="$style.main">
|
||||
<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
|
||||
<MkAvatar :class="$style.avatar" :user="note.user" link preview/>
|
||||
|
|
@ -31,8 +31,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
v-tooltip="renoteTooltip"
|
||||
class="_button"
|
||||
:class="$style.noteFooterButton"
|
||||
:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
@click.stop="renoted ? undoRenote() : boostVisibility($event.shiftKey)"
|
||||
:style="appearNote.isRenoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
@click.stop="appearNote.isRenoted ? undoRenote() : boostVisibility($event.shiftKey)"
|
||||
>
|
||||
<i class="ph-rocket-launch ph-bold ph-lg"></i>
|
||||
<p v-if="note.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ note.renoteCount }}</p>
|
||||
|
|
@ -79,7 +79,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</div>
|
||||
<div v-else :class="$style.muted" @click.stop="muted = false">
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :note="appearNote"></SkMutedNote>
|
||||
<SkMutedNote :muted="muted" :threadMuted="false" :noteMuted="noteMuted" :note="appearNote"></SkMutedNote>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -137,7 +137,6 @@ const el = shallowRef<HTMLElement>();
|
|||
const translation = ref<Misskey.entities.NotesTranslateResponse | false | null>(null);
|
||||
const translating = ref(false);
|
||||
const isDeleted = ref(false);
|
||||
const renoted = ref(false);
|
||||
const reactButton = shallowRef<HTMLElement>();
|
||||
const clipButton = useTemplateRef('clipButton');
|
||||
const renoteButton = shallowRef<HTMLElement>();
|
||||
|
|
@ -145,7 +144,7 @@ const quoteButton = shallowRef<HTMLElement>();
|
|||
const menuButton = shallowRef<HTMLElement>();
|
||||
const likeButton = shallowRef<HTMLElement>();
|
||||
|
||||
const renoteTooltip = computeRenoteTooltip(renoted);
|
||||
const renoteTooltip = computeRenoteTooltip(appearNote);
|
||||
|
||||
const defaultLike = computed(() => prefer.s.like ? prefer.s.like : null);
|
||||
const replies = ref<Misskey.entities.Note[]>([]);
|
||||
|
|
@ -172,7 +171,7 @@ async function removeReply(id: Misskey.entities.Note['id']) {
|
|||
}
|
||||
}
|
||||
|
||||
const { muted, threadMuted } = checkMutes(appearNote);
|
||||
const { muted, noteMuted } = checkMutes(appearNote);
|
||||
|
||||
useNoteCapture({
|
||||
rootEl: el,
|
||||
|
|
@ -183,16 +182,6 @@ useNoteCapture({
|
|||
onDeleteCallback: props.detail && props.depth < prefer.s.numberOfReplies ? props.onDeleteCallback : undefined,
|
||||
});
|
||||
|
||||
if ($i) {
|
||||
misskeyApi('notes/renotes', {
|
||||
noteId: appearNote.value.id,
|
||||
userId: $i.id,
|
||||
limit: 1,
|
||||
}).then((res) => {
|
||||
renoted.value = res.length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
function focus() {
|
||||
el.value?.focus();
|
||||
}
|
||||
|
|
@ -270,12 +259,12 @@ function undoReact(note): void {
|
|||
}
|
||||
|
||||
function undoRenote() : void {
|
||||
if (!renoted.value) return;
|
||||
if (!appearNote.value.isRenoted) return;
|
||||
misskeyApi('notes/unrenote', {
|
||||
noteId: appearNote.value.id,
|
||||
});
|
||||
os.toast(i18n.ts.rmboost);
|
||||
renoted.value = false;
|
||||
appearNote.value.isRenoted = false;
|
||||
|
||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||
if (el) {
|
||||
|
|
@ -322,7 +311,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
channelId: appearNote.value.channelId,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
});
|
||||
} else {
|
||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||
|
|
@ -341,7 +330,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
visibility: visibility,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkA>
|
||||
</header>
|
||||
<div>
|
||||
<div v-if="muted || threadMuted" :class="[$style.text, $style.muted]">
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :note="note"></SkMutedNote>
|
||||
<div v-if="muted || threadMuted || noteMuted" :class="[$style.text, $style.muted]">
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :noteMuted="noteMuted" :note="note"></SkMutedNote>
|
||||
</div>
|
||||
<Mfm v-else :class="$style.text" :text="getNoteSummary(note)" :isBlock="true" :plain="true" :nowrap="false" :isNote="true" nyaize="respect" :author="note.user"/>
|
||||
</div>
|
||||
|
|
@ -50,7 +50,7 @@ defineEmits<{
|
|||
(event: 'select', user: Misskey.entities.UserLite): void
|
||||
}>();
|
||||
|
||||
const { muted, hardMuted, threadMuted } = checkMutes(computed(() => props.note));
|
||||
const { muted, hardMuted, threadMuted, noteMuted } = checkMutes(computed(() => props.note));
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<I18n v-if="threadMuted" :src="i18n.ts.userSaysSomethingInMutedThread" tag="small">
|
||||
<I18n v-if="noteMuted" :src="i18n.ts.userSaysSomethingInMutedNote" tag="small">
|
||||
<template #name>
|
||||
<MkUserName :user="note.user"/>
|
||||
</template>
|
||||
</I18n>
|
||||
<I18n v-else-if="threadMuted" :src="i18n.ts.userSaysSomethingInMutedThread" tag="small">
|
||||
<template #name>
|
||||
<MkUserName :user="note.user"/>
|
||||
</template>
|
||||
|
|
@ -40,11 +45,15 @@ import { computed } from 'vue';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
|
||||
const props = defineProps<{
|
||||
const props = withDefaults(defineProps<{
|
||||
muted: false | 'sensitiveMute' | string[];
|
||||
threadMuted: boolean;
|
||||
threadMuted?: boolean;
|
||||
noteMuted?: boolean;
|
||||
note: Misskey.entities.Note;
|
||||
}>();
|
||||
}>(), {
|
||||
threadMuted: false,
|
||||
noteMuted: false,
|
||||
});
|
||||
|
||||
const mutedWords = computed(() => Array.isArray(props.muted)
|
||||
? props.muted.join(', ')
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div
|
||||
v-if="!hardMuted && muted === false && !threadMuted"
|
||||
v-if="!hardMuted && muted === false && !threadMuted && !noteMuted"
|
||||
v-show="!isDeleted"
|
||||
ref="rootEl"
|
||||
v-hotkey="keymap"
|
||||
|
|
@ -125,9 +125,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
v-tooltip="renoteTooltip"
|
||||
:class="$style.footerButton"
|
||||
class="_button"
|
||||
:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
:style="appearNote.isRenoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
@click.stop
|
||||
@mousedown.prevent="renoted ? undoRenote(appearNote) : boostVisibility($event.shiftKey)"
|
||||
@mousedown.prevent="appearNote.isRenoted ? undoRenote(appearNote) : boostVisibility($event.shiftKey)"
|
||||
>
|
||||
<i class="ti ti-repeat"></i>
|
||||
<p v-if="appearNote.renoteCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.renoteCount) }}</p>
|
||||
|
|
@ -169,7 +169,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</article>
|
||||
</div>
|
||||
<div v-else-if="!hardMuted" :class="$style.muted" @click.stop="muted = false">
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :note="appearNote"></SkMutedNote>
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :noteMuted="noteMuted" :note="appearNote"></SkMutedNote>
|
||||
</div>
|
||||
<div v-else>
|
||||
<!--
|
||||
|
|
@ -310,8 +310,7 @@ const selfNoteIds = computed(() => getSelfNoteIds(props.note));
|
|||
const isLong = shouldCollapsed(appearNote.value, urls.value);
|
||||
const collapsed = ref(prefer.s.expandLongNote && appearNote.value.cw == null && isLong ? false : appearNote.value.cw == null && isLong);
|
||||
const isDeleted = ref(false);
|
||||
const renoted = ref(false);
|
||||
const { muted, hardMuted, threadMuted } = checkMutes(appearNote, computed(() => props.withHardMute));
|
||||
const { muted, hardMuted, threadMuted, noteMuted } = checkMutes(appearNote, computed(() => props.withHardMute));
|
||||
const translation = ref<Misskey.entities.NotesTranslateResponse | false | null>(null);
|
||||
const translating = ref(false);
|
||||
const showTicker = (prefer.s.instanceTicker === 'always') || (prefer.s.instanceTicker === 'remote' && appearNote.value.user.instance);
|
||||
|
|
@ -334,7 +333,7 @@ const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
|
|||
|
||||
const mergedCW = computed(() => computeMergedCw(appearNote.value));
|
||||
|
||||
const renoteTooltip = computeRenoteTooltip(renoted);
|
||||
const renoteTooltip = computeRenoteTooltip(appearNote);
|
||||
|
||||
let renoting = false;
|
||||
|
||||
|
|
@ -349,7 +348,7 @@ const keymap = {
|
|||
},
|
||||
'q': () => {
|
||||
if (renoteCollapsed.value) return;
|
||||
if (canRenote.value && !renoted.value && !renoting) renote(prefer.s.visibilityOnBoost);
|
||||
if (canRenote.value && !appearNote.value.isRenoted && !renoting) renote(prefer.s.visibilityOnBoost);
|
||||
},
|
||||
'm': () => {
|
||||
if (renoteCollapsed.value) return;
|
||||
|
|
@ -459,16 +458,6 @@ if (!props.mock) {
|
|||
});
|
||||
});
|
||||
|
||||
if ($i) {
|
||||
misskeyApi('notes/renotes', {
|
||||
noteId: appearNote.value.id,
|
||||
userId: $i.id,
|
||||
limit: 1,
|
||||
}).then((res) => {
|
||||
renoted.value = res.length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
||||
useTooltip(reactButton, async (showing) => {
|
||||
const reactions = await misskeyApiGet('notes/reactions', {
|
||||
|
|
@ -527,7 +516,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
channelId: appearNote.value.channelId,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
}).finally(() => { renoting = false; });
|
||||
}
|
||||
} else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) {
|
||||
|
|
@ -548,7 +537,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
renoteId: appearNote.value.id,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
}).finally(() => { renoting = false; });
|
||||
}
|
||||
}
|
||||
|
|
@ -727,7 +716,7 @@ function undoRenote(note) : void {
|
|||
noteId: note.id,
|
||||
});
|
||||
os.toast(i18n.ts.rmboost);
|
||||
renoted.value = false;
|
||||
appearNote.value.isRenoted = false;
|
||||
|
||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||
if (el) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<template>
|
||||
<div
|
||||
v-if="!muted && !threadMuted"
|
||||
v-if="!muted && !threadMuted && !noteMuted"
|
||||
v-show="!isDeleted"
|
||||
ref="rootEl"
|
||||
v-hotkey="keymap"
|
||||
|
|
@ -142,8 +142,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
v-tooltip="renoteTooltip"
|
||||
class="_button"
|
||||
:class="$style.noteFooterButton"
|
||||
:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
@mousedown.prevent="renoted ? undoRenote() : boostVisibility($event.shiftKey)"
|
||||
:style="appearNote.isRenoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
@mousedown.prevent="appearNote.isRenoted ? undoRenote() : boostVisibility($event.shiftKey)"
|
||||
>
|
||||
<i class="ti ti-repeat"></i>
|
||||
<p v-if="appearNote.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.renoteCount) }}</p>
|
||||
|
|
@ -231,7 +231,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</div>
|
||||
<div v-else class="_panel" :class="$style.muted" @click.stop="muted = false">
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :note="appearNote"></SkMutedNote>
|
||||
<SkMutedNote :muted="muted" :threadMuted="threadMuted" :noteMuted="noteMuted" :note="appearNote"></SkMutedNote>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -341,7 +341,6 @@ const galleryEl = useTemplateRef('galleryEl');
|
|||
const isMyRenote = $i && ($i.id === note.value.userId);
|
||||
const showContent = ref(prefer.s.uncollapseCW);
|
||||
const isDeleted = ref(false);
|
||||
const renoted = ref(false);
|
||||
const translation = ref<Misskey.entities.NotesTranslateResponse | false | null>(null);
|
||||
const translating = ref(false);
|
||||
const parsed = computed(() => appearNote.value.text ? mfm.parse(appearNote.value.text) : []);
|
||||
|
|
@ -357,24 +356,14 @@ const defaultLike = computed(() => prefer.s.like ? prefer.s.like : null);
|
|||
|
||||
const mergedCW = computed(() => computeMergedCw(appearNote.value));
|
||||
|
||||
const renoteTooltip = computeRenoteTooltip(renoted);
|
||||
const renoteTooltip = computeRenoteTooltip(appearNote);
|
||||
|
||||
const { muted, threadMuted } = checkMutes(appearNote);
|
||||
const { muted, threadMuted, noteMuted } = checkMutes(appearNote);
|
||||
|
||||
watch(() => props.expandAllCws, (expandAllCws) => {
|
||||
if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
|
||||
});
|
||||
|
||||
if ($i) {
|
||||
misskeyApi('notes/renotes', {
|
||||
noteId: appearNote.value.id,
|
||||
userId: $i.id,
|
||||
limit: 1,
|
||||
}).then((res) => {
|
||||
renoted.value = res.length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
let renoting = false;
|
||||
|
||||
const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
|
||||
|
|
@ -385,7 +374,7 @@ const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
|
|||
const keymap = {
|
||||
'r': () => reply(),
|
||||
'e|a|plus': () => react(),
|
||||
'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(prefer.s.visibilityOnBoost); },
|
||||
'q': () => { if (canRenote.value && !appearNote.value.isRenoted && !renoting) renote(prefer.s.visibilityOnBoost); },
|
||||
'm': () => showMenu(),
|
||||
'c': () => {
|
||||
if (!prefer.s.showClipButtonInNoteFooter) return;
|
||||
|
|
@ -559,7 +548,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
channelId: appearNote.value.channelId,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
}).finally(() => { renoting = false; });
|
||||
} else {
|
||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||
|
|
@ -578,7 +567,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
renoteId: appearNote.value.id,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
}).finally(() => { renoting = false; });
|
||||
}
|
||||
}
|
||||
|
|
@ -726,12 +715,12 @@ function undoReact(targetNote: Misskey.entities.Note): void {
|
|||
}
|
||||
|
||||
function undoRenote() : void {
|
||||
if (!renoted.value) return;
|
||||
if (!appearNote.value.isRenoted) return;
|
||||
misskeyApi('notes/unrenote', {
|
||||
noteId: appearNote.value.id,
|
||||
});
|
||||
os.toast(i18n.ts.rmboost);
|
||||
renoted.value = false;
|
||||
appearNote.value.isRenoted = false;
|
||||
|
||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||
if (el) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div v-show="!isDeleted" v-if="!muted" ref="el" :class="[$style.root, { [$style.children]: depth > 1, [$style.isReply]: props.isReply, [$style.detailed]: props.detailed }]">
|
||||
<div v-show="!isDeleted" v-if="!muted && !noteMuted" ref="el" :class="[$style.root, { [$style.children]: depth > 1, [$style.isReply]: props.isReply, [$style.detailed]: props.detailed }]">
|
||||
<div v-if="!hideLine" :class="$style.line"></div>
|
||||
<div :class="$style.main">
|
||||
<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
|
||||
|
|
@ -39,8 +39,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
v-tooltip="renoteTooltip"
|
||||
class="_button"
|
||||
:class="$style.noteFooterButton"
|
||||
:style="renoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
@click.stop="renoted ? undoRenote() : boostVisibility($event.shiftKey)"
|
||||
:style="appearNote.isRenoted ? 'color: var(--MI_THEME-accent) !important;' : ''"
|
||||
@click.stop="appearNote.isRenoted ? undoRenote() : boostVisibility($event.shiftKey)"
|
||||
>
|
||||
<i class="ph-rocket-launch ph-bold ph-lg"></i>
|
||||
<p v-if="note.renoteCount > 0" :class="$style.noteFooterButtonCount">{{ note.renoteCount }}</p>
|
||||
|
|
@ -87,7 +87,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</div>
|
||||
<div v-else :class="$style.muted" @click.stop="muted = false">
|
||||
<SkMutedNote :muted="muted" :threadMuted="false" :note="appearNote"></SkMutedNote>
|
||||
<SkMutedNote :muted="muted" :threadMuted="false" :noteMuted="noteMuted" :note="appearNote"></SkMutedNote>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -151,7 +151,6 @@ const el = shallowRef<HTMLElement>();
|
|||
const translation = ref<Misskey.entities.NotesTranslateResponse | false | null>(null);
|
||||
const translating = ref(false);
|
||||
const isDeleted = ref(false);
|
||||
const renoted = ref(false);
|
||||
const reactButton = shallowRef<HTMLElement>();
|
||||
const clipButton = useTemplateRef('clipButton');
|
||||
const renoteButton = shallowRef<HTMLElement>();
|
||||
|
|
@ -159,7 +158,7 @@ const quoteButton = shallowRef<HTMLElement>();
|
|||
const menuButton = shallowRef<HTMLElement>();
|
||||
const likeButton = shallowRef<HTMLElement>();
|
||||
|
||||
const renoteTooltip = computeRenoteTooltip(renoted);
|
||||
const renoteTooltip = computeRenoteTooltip(appearNote);
|
||||
|
||||
const defaultLike = computed(() => prefer.s.like ? prefer.s.like : null);
|
||||
const replies = ref<Misskey.entities.Note[]>([]);
|
||||
|
|
@ -186,7 +185,7 @@ async function removeReply(id: Misskey.entities.Note['id']) {
|
|||
}
|
||||
}
|
||||
|
||||
const { muted } = checkMutes(appearNote);
|
||||
const { muted, noteMuted } = checkMutes(appearNote);
|
||||
|
||||
useNoteCapture({
|
||||
rootEl: el,
|
||||
|
|
@ -197,16 +196,6 @@ useNoteCapture({
|
|||
onDeleteCallback: props.detail && props.depth < prefer.s.numberOfReplies ? props.onDeleteCallback : undefined,
|
||||
});
|
||||
|
||||
if ($i) {
|
||||
misskeyApi('notes/renotes', {
|
||||
noteId: appearNote.value.id,
|
||||
userId: $i.id,
|
||||
limit: 1,
|
||||
}).then((res) => {
|
||||
renoted.value = res.length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
function focus() {
|
||||
el.value?.focus();
|
||||
}
|
||||
|
|
@ -284,12 +273,12 @@ function undoReact(note): void {
|
|||
}
|
||||
|
||||
function undoRenote() : void {
|
||||
if (!renoted.value) return;
|
||||
if (!appearNote.value.isRenoted) return;
|
||||
misskeyApi('notes/unrenote', {
|
||||
noteId: appearNote.value.id,
|
||||
});
|
||||
os.toast(i18n.ts.rmboost);
|
||||
renoted.value = false;
|
||||
appearNote.value.isRenoted = false;
|
||||
|
||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||
if (el) {
|
||||
|
|
@ -336,7 +325,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
channelId: appearNote.value.channelId,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
});
|
||||
} else {
|
||||
const el = renoteButton.value as HTMLElement | null | undefined;
|
||||
|
|
@ -355,7 +344,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
|
|||
visibility: visibility,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
renoted.value = true;
|
||||
appearNote.value.isRenoted = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,9 +82,9 @@ export function boostMenuItems(appearNote: Ref<Misskey.entities.Note>, renote: (
|
|||
];
|
||||
}
|
||||
|
||||
export function computeRenoteTooltip(renoted: Ref<boolean>): ComputedRef<string> {
|
||||
export function computeRenoteTooltip(note: ComputedRef<Misskey.entities.Note>): ComputedRef<string> {
|
||||
return computed(() => {
|
||||
if (renoted.value) return i18n.ts.unrenote;
|
||||
if (note.value.isRenoted) return i18n.ts.unrenote;
|
||||
if (prefer.s.showVisibilitySelectorOnBoost) return i18n.ts.renote;
|
||||
return i18n.ts.renoteShift;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,7 +22,12 @@ export function checkMutes(noteToCheck: ComputedRef<Misskey.entities.Note>, with
|
|||
|
||||
const threadMuted = computed(() => {
|
||||
if (!muteEnable.value) return false;
|
||||
return noteToCheck.value.isMuting;
|
||||
return noteToCheck.value.isMutingThread;
|
||||
});
|
||||
|
||||
const noteMuted = computed(() => {
|
||||
if (!muteEnable.value) return false;
|
||||
return noteToCheck.value.isMutingNote;
|
||||
});
|
||||
|
||||
const hardMuted = computed(() => {
|
||||
|
|
@ -30,7 +35,7 @@ export function checkMutes(noteToCheck: ComputedRef<Misskey.entities.Note>, with
|
|||
return checkMute(noteToCheck.value, $i?.hardMutedWords, true);
|
||||
});
|
||||
|
||||
return { muted, hardMuted, threadMuted };
|
||||
return { muted, hardMuted, threadMuted, noteMuted };
|
||||
}
|
||||
|
||||
export function checkMute(note: Misskey.entities.Note, mutes: undefined | null): false;
|
||||
|
|
|
|||
|
|
@ -213,9 +213,9 @@ export function getNoteMenu(props: {
|
|||
noteId: appearNote.id,
|
||||
});
|
||||
|
||||
os.post({ initialNote: appearNote, renote: appearNote.renote, reply: appearNote.reply, channel: appearNote.channel });
|
||||
os.post({ initialNote: appearNote, renote: appearNote.renote ?? undefined, reply: appearNote.reply ?? undefined, channel: appearNote.channel });
|
||||
|
||||
if (Date.now() - new Date(appearNote.createdAt).getTime() < 1000 * 60 && appearNote.userId === $i.id) {
|
||||
if ($i && Date.now() - new Date(appearNote.createdAt).getTime() < 1000 * 60 && appearNote.userId === $i.id) {
|
||||
claimAchievement('noteDeletedWithin1min');
|
||||
}
|
||||
});
|
||||
|
|
@ -224,8 +224,8 @@ export function getNoteMenu(props: {
|
|||
function edit(): void {
|
||||
os.post({
|
||||
initialNote: appearNote,
|
||||
renote: appearNote.renote,
|
||||
reply: appearNote.reply,
|
||||
renote: appearNote.renote ?? undefined,
|
||||
reply: appearNote.reply ?? undefined,
|
||||
channel: appearNote.channel,
|
||||
editId: appearNote.id,
|
||||
initialFiles: appearNote.files,
|
||||
|
|
@ -242,6 +242,14 @@ export function getNoteMenu(props: {
|
|||
function toggleThreadMute(mute: boolean): void {
|
||||
os.apiWithDialog(mute ? 'notes/thread-muting/create' : 'notes/thread-muting/delete', {
|
||||
noteId: appearNote.id,
|
||||
noteOnly: false,
|
||||
});
|
||||
}
|
||||
|
||||
function toggleNoteMute(mute: boolean): void {
|
||||
os.apiWithDialog(mute ? 'notes/thread-muting/create' : 'notes/thread-muting/delete', {
|
||||
noteId: appearNote.id,
|
||||
noteOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -293,9 +301,11 @@ export function getNoteMenu(props: {
|
|||
const menuItems: MenuItem[] = [];
|
||||
|
||||
if ($i) {
|
||||
/*
|
||||
const statePromise = misskeyApi('notes/state', {
|
||||
noteId: appearNote.id,
|
||||
});
|
||||
*/
|
||||
|
||||
if (props.currentClip?.userId === $i.id) {
|
||||
menuItems.push({
|
||||
|
|
@ -352,15 +362,19 @@ export function getNoteMenu(props: {
|
|||
|
||||
menuItems.push({ type: 'divider' });
|
||||
|
||||
menuItems.push(statePromise.then(state => state.isFavorited ? {
|
||||
icon: 'ti ti-star-off',
|
||||
text: i18n.ts.unfavorite,
|
||||
action: () => toggleFavorite(false),
|
||||
} : {
|
||||
icon: 'ti ti-star',
|
||||
text: i18n.ts.favorite,
|
||||
action: () => toggleFavorite(true),
|
||||
}));
|
||||
if (appearNote.isFavorited) {
|
||||
menuItems.push({
|
||||
icon: 'ti ti-star-off',
|
||||
text: i18n.ts.unfavorite,
|
||||
action: () => toggleFavorite(false),
|
||||
});
|
||||
} else {
|
||||
menuItems.push({
|
||||
icon: 'ti ti-star',
|
||||
text: i18n.ts.favorite,
|
||||
action: () => toggleFavorite(true),
|
||||
});
|
||||
}
|
||||
|
||||
menuItems.push({
|
||||
type: 'parent',
|
||||
|
|
@ -369,15 +383,33 @@ export function getNoteMenu(props: {
|
|||
children: () => getNoteClipMenu(props),
|
||||
});
|
||||
|
||||
menuItems.push(statePromise.then(state => state.isMutedThread ? {
|
||||
icon: 'ti ti-message-off',
|
||||
text: i18n.ts.unmuteThread,
|
||||
action: () => toggleThreadMute(false),
|
||||
} : {
|
||||
icon: 'ti ti-message-off',
|
||||
text: i18n.ts.muteThread,
|
||||
action: () => toggleThreadMute(true),
|
||||
}));
|
||||
if (appearNote.isMutingThread) {
|
||||
menuItems.push({
|
||||
icon: 'ti ti-message-off',
|
||||
text: i18n.ts.unmuteThread,
|
||||
action: () => toggleThreadMute(false),
|
||||
});
|
||||
} else {
|
||||
menuItems.push({
|
||||
icon: 'ti ti-message-off',
|
||||
text: i18n.ts.muteThread,
|
||||
action: () => toggleThreadMute(true),
|
||||
});
|
||||
}
|
||||
|
||||
if (appearNote.isMutingNote) {
|
||||
menuItems.push({
|
||||
icon: 'ti ti-message-off',
|
||||
text: i18n.ts.unmuteNote,
|
||||
action: () => toggleNoteMute(false),
|
||||
});
|
||||
} else {
|
||||
menuItems.push({
|
||||
icon: 'ti ti-message-off',
|
||||
text: i18n.ts.muteNote,
|
||||
action: () => toggleNoteMute(true),
|
||||
});
|
||||
}
|
||||
|
||||
if (appearNote.userId === $i.id) {
|
||||
if (($i.pinnedNoteIds ?? []).includes(appearNote.id)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue