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

fix(frontend): リノートの判定が甘いのを修正 #14396

Merged
merged 12 commits into from
Aug 17, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Fix: ページ遷移に失敗することがある問題を修正
- Fix: iOSでユーザー名などがリンクとして誤検知される現象を抑制
- Fix: mCaptchaを使用していてもbotプロテクションに関する警告が消えないのを修正
- Fix: 特定の条件下でノートの削除ボタンが出ないのを修正

### Server
- Fix: WSの`readAllNotifications` メッセージが `body` を持たない場合に動作しない問題 #14374
Expand Down
16 changes: 4 additions & 12 deletions packages/frontend/src/components/MkNote.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="pinned" :class="$style.tip"><i class="ti ti-pin"></i> {{ i18n.ts.pinnedNote }}</div>
<!--<div v-if="appearNote._prId_" class="tip"><i class="ti ti-speakerphone"></i> {{ i18n.ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ i18n.ts.hideThisNote }} <i class="ti ti-x"></i></button></div>-->
<!--<div v-if="appearNote._featuredId_" class="tip"><i class="ti ti-bolt"></i> {{ i18n.ts.featured }}</div>-->
<div v-if="isRenote" :class="$style.renote">
<div v-if="isRenote(note)" :class="$style.renote">
<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
<i class="ti ti-repeat" style="margin-right: 4px;"></i>
Expand Down Expand Up @@ -200,6 +200,7 @@ import { host } from '@/config.js';
import { isEnabledUrlPreview } from '@/instance.js';
import { type Keymap } from '@/scripts/hotkey.js';
import { focusPrev, focusNext } from '@/scripts/focus.js';
import { isRenote, getAppearNote } from '@/scripts/note.js';

const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
Expand Down Expand Up @@ -242,22 +243,13 @@ if (noteViewInterruptors.length > 0) {
});
}

const isRenote = (
note.value.renote != null &&
note.value.reply == null &&
note.value.text == null &&
note.value.cw == null &&
note.value.fileIds && note.value.fileIds.length === 0 &&
note.value.poll == null
);

const rootEl = shallowRef<HTMLElement>();
const menuButton = shallowRef<HTMLElement>();
const renoteButton = shallowRef<HTMLElement>();
const renoteTime = shallowRef<HTMLElement>();
const reactButton = shallowRef<HTMLElement>();
const clipButton = shallowRef<HTMLElement>();
const appearNote = computed(() => isRenote ? note.value.renote as Misskey.entities.Note : note.value);
const appearNote = computed(() => getAppearNote(note.value));
const galleryEl = shallowRef<InstanceType<typeof MkMediaList>>();
const isMyRenote = $i && ($i.id === note.value.userId);
const showContent = ref(false);
Expand All @@ -273,7 +265,7 @@ const translating = ref(false);
const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.value.user.instance);
const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i?.id));
const renoteCollapsed = ref(
defaultStore.state.collapseRenotes && isRenote && (
defaultStore.state.collapseRenotes && isRenote(props.note) && (
($i && ($i.id === note.value.userId || $i.id === appearNote.value.userId)) || // `||` must be `||`! See https://github.com/misskey-dev/misskey/issues/13131
(appearNote.value.myReaction != null)
),
Expand Down
14 changes: 3 additions & 11 deletions packages/frontend/src/components/MkNoteDetailed.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkNoteSub v-for="note in conversation" :key="note.id" :class="$style.replyToMore" :note="note"/>
</div>
<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo"/>
<div v-if="isRenote" :class="$style.renote">
<div v-if="isRenote(note)" :class="$style.renote">
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
<i class="ti ti-repeat" style="margin-right: 4px;"></i>
<span :class="$style.renoteText">
Expand Down Expand Up @@ -235,6 +235,7 @@ import MkPagination, { type Paging } from '@/components/MkPagination.vue';
import MkReactionIcon from '@/components/MkReactionIcon.vue';
import MkButton from '@/components/MkButton.vue';
import { isEnabledUrlPreview } from '@/instance.js';
import { isRenote, getAppearNote } from '@/scripts/note.js';
import { type Keymap } from '@/scripts/hotkey.js';

const props = withDefaults(defineProps<{
Expand Down Expand Up @@ -267,22 +268,13 @@ if (noteViewInterruptors.length > 0) {
});
}

const isRenote = (
note.value.renote != null &&
note.value.reply == null &&
note.value.text == null &&
note.value.cw == null &&
note.value.fileIds && note.value.fileIds.length === 0 &&
note.value.poll == null
);

const rootEl = shallowRef<HTMLElement>();
const menuButton = shallowRef<HTMLElement>();
const renoteButton = shallowRef<HTMLElement>();
const renoteTime = shallowRef<HTMLElement>();
const reactButton = shallowRef<HTMLElement>();
const clipButton = shallowRef<HTMLElement>();
const appearNote = computed(() => isRenote ? note.value.renote as Misskey.entities.Note : note.value);
const appearNote = computed(() => getAppearNote(note.value));
const galleryEl = shallowRef<InstanceType<typeof MkMediaList>>();
const isMyRenote = $i && ($i.id === note.value.userId);
const showContent = ref(false);
Expand Down
33 changes: 8 additions & 25 deletions packages/frontend/src/scripts/get-note-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import { MenuItem } from '@/types/menu.js';
import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { isSupportShare } from '@/scripts/navigator.js';
import { getAppearNote } from '@/scripts/note.js';

export async function getNoteClipMenu(props: {
note: Misskey.entities.Note;
Expand All @@ -34,14 +35,7 @@
}
}

const isRenote = (
props.note.renote != null &&
props.note.text == null &&
props.note.fileIds.length === 0 &&
props.note.poll == null
);

const appearNote = isRenote ? props.note.renote as Misskey.entities.Note : props.note;
const appearNote = getAppearNote(props.note);

const clips = await clipsCache.fetch();
const menu: MenuItem[] = [...clips.map(clip => ({
Expand Down Expand Up @@ -163,15 +157,9 @@
translating: Ref<boolean>;
isDeleted: Ref<boolean>;
currentClip?: Misskey.entities.Clip;
}) {

Check failure on line 160 in packages/frontend/src/scripts/get-note-menu.ts

View workflow job for this annotation

GitHub Actions / lint (frontend)

Block must not be padded by blank lines
const isRenote = (
props.note.renote != null &&
props.note.text == null &&
props.note.fileIds.length === 0 &&
props.note.poll == null
);

const appearNote = isRenote ? props.note.renote as Misskey.entities.Note : props.note;
const appearNote = getAppearNote(props.note);

const cleanups = [] as (() => void)[];

Expand Down Expand Up @@ -248,6 +236,7 @@
}

async function unclip(): Promise<void> {
if (!props.currentClip) return;
os.apiWithDialog('clips/remove-note', { clipId: props.currentClip.id, noteId: appearNote.id });
props.isDeleted.value = true;
}
Expand All @@ -267,8 +256,8 @@

function share(): void {
navigator.share({
title: i18n.tsx.noteOf({ user: appearNote.user.name }),
text: appearNote.text,
title: i18n.tsx.noteOf({ user: appearNote.user.name ?? appearNote.user.username }),
text: appearNote.text ?? '',
url: `${url}/notes/${appearNote.id}`,
});
}
Expand Down Expand Up @@ -508,15 +497,9 @@
note: Misskey.entities.Note;
renoteButton: ShallowRef<HTMLElement | undefined>;
mock?: boolean;
}) {

Check failure on line 500 in packages/frontend/src/scripts/get-note-menu.ts

View workflow job for this annotation

GitHub Actions / lint (frontend)

Block must not be padded by blank lines
const isRenote = (
props.note.renote != null &&
props.note.text == null &&
props.note.fileIds.length === 0 &&
props.note.poll == null
);

const appearNote = isRenote ? props.note.renote as Misskey.entities.Note : props.note;

const appearNote = getAppearNote(props.note);

const channelRenoteItems: MenuItem[] = [];
const normalRenoteItems: MenuItem[] = [];
Expand Down
21 changes: 21 additions & 0 deletions packages/frontend/src/scripts/note.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

import * as Misskey from 'misskey-js';

export function isRenote(note: Misskey.entities.Note): boolean {
return (
note.renote != null &&
note.reply == null &&
note.text == null &&
note.cw == null &&
(note.fileIds == null || note.fileIds.length === 0) &&
note.poll == null
);
}
KisaragiEffective marked this conversation as resolved.
Show resolved Hide resolved

export function getAppearNote(note: Misskey.entities.Note): Misskey.entities.Note {
return isRenote(note) ? note.renote! : note;
}
Loading