Skip to content

Commit 3979cc2

Browse files
authored
fix: 連合なしの状態の読み書きができない問題、他 (#206)
* fix: 連合なしの状態の読み書きができない問題 * fix: canPakuru: trueの場合、canRenoteを無視してリノートボタンが表示される問題 * refactoring: 共通部分を関数でまとめたり、三項演算子をやめてif文の記述にしたり、など
1 parent 5f93074 commit 3979cc2

File tree

9 files changed

+143
-110
lines changed

9 files changed

+143
-110
lines changed

locales/index.d.ts

+20
Original file line numberDiff line numberDiff line change
@@ -9945,6 +9945,26 @@ export interface Locale extends ILocale {
99459945
* センシティブなファイルを表示しています。
99469946
*/
99479947
readonly "displayingSensitiveFiles": string;
9948+
/**
9949+
* ホームリノート
9950+
*/
9951+
readonly "homeRenote": string;
9952+
/**
9953+
* フォロワーリノート
9954+
*/
9955+
readonly "followersRenote": string;
9956+
/**
9957+
* リノート (連合なし)
9958+
*/
9959+
readonly "disableFederationRenote": string;
9960+
/**
9961+
* ホームリノート (連合なし)
9962+
*/
9963+
readonly "disableFederationHomeRenote": string;
9964+
/**
9965+
* フォロワーリノート (連合なし)
9966+
*/
9967+
readonly "disableFederationFollowersRenote": string;
99489968
/**
99499969
* パクる
99509970
*/

locales/ja-JP.yml

+5
Original file line numberDiff line numberDiff line change
@@ -2650,6 +2650,11 @@ _tms:
26502650
reportIssuesToGithub: "問題の報告や要望はGitHubで受け付けています。"
26512651
displayingGifFiles: "GIFファイルを表示しています。"
26522652
displayingSensitiveFiles: "センシティブなファイルを表示しています。"
2653+
homeRenote: "ホームリノート"
2654+
followersRenote: "フォロワーリノート"
2655+
disableFederationRenote: "リノート (連合なし)"
2656+
disableFederationHomeRenote: "ホームリノート (連合なし)"
2657+
disableFederationFollowersRenote: "フォロワーリノート (連合なし)"
26532658
pakuru: "パクる"
26542659
numberquote: "数字引用する"
26552660
didPakuru: "パクりました"

packages/frontend/src/components/MkNote.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ function renote(viaKeyboard = false) {
367367
pleaseLogin();
368368
showMovedDialog();
369369

370-
const { menu } = getRenoteMenu({ note: note.value, renoteButton, mock: props.mock });
370+
const { menu } = getRenoteMenu({ note: note.value, renoteButton, mock: props.mock, canRenote: canRenote.value });
371371
os.popupMenu(menu, renoteButton.value, {
372372
viaKeyboard,
373373
});

packages/frontend/src/components/MkNoteDetailed.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ function renote(viaKeyboard = false) {
377377
pleaseLogin();
378378
showMovedDialog();
379379

380-
const { menu } = getRenoteMenu({ note: note.value, renoteButton });
380+
const { menu } = getRenoteMenu({ note: note.value, renoteButton, canRenote: canRenote.value });
381381
os.popupMenu(menu, renoteButton.value, {
382382
viaKeyboard,
383383
});

packages/frontend/src/components/MkPostForm.vue

+6-2
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ const props = withDefaults(defineProps<{
156156
initialVisibleUsers: () => [],
157157
autofocus: true,
158158
mock: false,
159+
initialLocalOnly: undefined,
159160
});
160161

161162
provide('mock', props.mock);
@@ -185,8 +186,8 @@ watch(showPreview, () => defaultStore.set('showPreview', showPreview.value));
185186
const showAddMfmFunction = ref(defaultStore.state.enableQuickAddMfmFunction);
186187
watch(showAddMfmFunction, () => defaultStore.set('enableQuickAddMfmFunction', showAddMfmFunction.value));
187188
const cw = ref<string | null>(props.initialCw ?? null);
188-
const localOnly = ref<boolean>(props.initialLocalOnly ?? defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly);
189-
const visibility = ref(props.initialVisibility ?? (defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility) as typeof Misskey.noteVisibilities[number]);
189+
const localOnly = ref(props.initialLocalOnly ?? (defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly));
190+
const visibility = ref(props.initialVisibility ?? (defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility));
190191
const visibleUsers = ref<Misskey.entities.UserDetailed[]>([]);
191192
if (props.initialVisibleUsers) {
192193
props.initialVisibleUsers.forEach(pushVisibleUser);
@@ -518,6 +519,9 @@ async function toggleLocalOnly() {
518519
}
519520

520521
localOnly.value = !localOnly.value;
522+
if (defaultStore.state.rememberNoteVisibility) {
523+
defaultStore.set('localOnly', localOnly.value);
524+
}
521525
}
522526

523527
async function toggleReactionAcceptance() {

packages/frontend/src/components/MkPostFormDialog.vue

+4-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import * as Misskey from 'misskey-js';
1515
import MkModal from '@/components/MkModal.vue';
1616
import MkPostForm from '@/components/MkPostForm.vue';
1717

18-
const props = defineProps<{
18+
const props = withDefaults(defineProps<{
1919
reply?: Misskey.entities.Note;
2020
renote?: Misskey.entities.Note;
2121
channel?: any; // TODO
@@ -31,7 +31,9 @@ const props = defineProps<{
3131
instant?: boolean;
3232
fixed?: boolean;
3333
autofocus?: boolean;
34-
}>();
34+
}>(), {
35+
initialLocalOnly: undefined,
36+
});
3537

3638
const emit = defineEmits<{
3739
(ev: 'closed'): void;

packages/frontend/src/scripts/get-note-menu.ts

+90-103
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { getAppearNote } from '@/scripts/tms/get-appear-note.js';
2525
import { numberquote } from '@/scripts/tms/numberquote.js';
2626
import { pakuru } from '@/scripts/tms/pakuru.js';
2727
import { tooltipFromElement } from '@/scripts/tms/tooltip-from-element.js';
28+
import { smallerVisibility } from '@/scripts/tms/visibility.js';
2829
import { tmsStore } from '@/tms/store.js';
2930

3031
export async function getNoteClipMenu(props: {
@@ -486,126 +487,124 @@ export function getNoteMenu(props: {
486487
};
487488
}
488489

489-
type Visibility = 'public' | 'home' | 'followers' | 'specified';
490-
491-
// defaultStore.state.visibilityがstringなためstringも受け付けている
492-
function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility {
493-
if (a === 'specified' || b === 'specified') return 'specified';
494-
if (a === 'followers' || b === 'followers') return 'followers';
495-
if (a === 'home' || b === 'home') return 'home';
496-
// if (a === 'public' || b === 'public')
497-
return 'public';
498-
}
499-
500490
export function getRenoteMenu(props: {
501491
note: Misskey.entities.Note;
502492
renoteButton: ShallowRef<HTMLElement | undefined>;
503493
mock?: boolean;
494+
canRenote?: boolean;
504495
}) {
505496
const appearNote = getAppearNote(props.note);
497+
const canRenote = props.canRenote ?? true;
498+
499+
const rippleEffect = (): void => {
500+
const el = props.renoteButton.value;
501+
if (el == null) return;
502+
const rect = el.getBoundingClientRect();
503+
const x = rect.left + (el.offsetWidth / 2);
504+
const y = rect.top + (el.offsetHeight / 2);
505+
os.popup(MkRippleEffect, { x, y }, {}, 'end');
506+
};
507+
508+
const tooltipEffect = (text: string): void => {
509+
tooltipFromElement({
510+
targetElement: props.renoteButton.value,
511+
primary: true,
512+
text,
513+
});
514+
};
515+
516+
const errorDialog = (err: unknown): void => {
517+
os.alert({
518+
type: 'error',
519+
text: parseErrorMessage(err),
520+
});
521+
};
506522

507523
const channelRenoteItems: MenuItem[] = [];
508524
const normalRenoteItems: MenuItem[] = [];
509525
const pakuruItems: MenuItem[] = [];
510526

511-
if (appearNote.channel) {
512-
channelRenoteItems.push(...[{
527+
if (canRenote && appearNote.channel != null) {
528+
channelRenoteItems.push({
513529
text: i18n.ts.inChannelRenote,
514530
icon: 'ti ti-repeat',
515531
action: () => {
516-
const el = props.renoteButton.value;
517-
if (el) {
518-
const rect = el.getBoundingClientRect();
519-
const x = rect.left + (el.offsetWidth / 2);
520-
const y = rect.top + (el.offsetHeight / 2);
521-
os.popup(MkRippleEffect, { x, y }, {}, 'end');
522-
}
523-
524-
if (!props.mock) {
525-
misskeyApi('notes/create', {
526-
renoteId: appearNote.id,
527-
channelId: appearNote.channelId,
528-
}).then(() => {
529-
os.toast(i18n.ts.renoted);
530-
});
531-
}
532+
rippleEffect();
533+
if (props.mock) return tooltipEffect(i18n.ts.renoted);
534+
misskeyApi('notes/create', {
535+
renoteId: appearNote.id,
536+
channelId: appearNote.channelId,
537+
}).then(() => tooltipEffect(i18n.ts.renoted)).catch(errorDialog);
532538
},
533-
}, {
534-
text: i18n.ts.inChannelQuote,
535-
icon: 'ti ti-quote',
536-
action: () => {
537-
if (!props.mock) {
539+
});
540+
if (!props.mock) {
541+
channelRenoteItems.push({
542+
text: i18n.ts.inChannelQuote,
543+
icon: 'ti ti-quote',
544+
action: () => {
538545
os.post({
539546
renote: appearNote,
540547
channel: appearNote.channel,
541548
});
542-
}
543-
},
544-
}]);
549+
},
550+
});
551+
}
545552
}
546553

547-
if (!appearNote.channel || appearNote.channel.allowRenoteToExternal) {
548-
normalRenoteItems.push(...[{
549-
text: i18n.ts.renote,
554+
if (canRenote && (appearNote.channel == null || appearNote.channel.allowRenoteToExternal)) {
555+
let renoteVisibility = appearNote.visibility;
556+
const renoteLocalOnly = appearNote.localOnly ?? false;
557+
558+
if (appearNote.channel?.isSensitive || $i?.isSilenced) {
559+
renoteVisibility = smallerVisibility([renoteVisibility, 'home']);
560+
}
561+
562+
const renoteButtonText = (() => {
563+
if (renoteVisibility === 'home') {
564+
if (renoteLocalOnly) return i18n.ts._tms.disableFederationHomeRenote;
565+
return i18n.ts._tms.homeRenote;
566+
}
567+
if (renoteVisibility === 'followers') {
568+
if (renoteLocalOnly) return i18n.ts._tms.disableFederationFollowersRenote;
569+
return i18n.ts._tms.followersRenote;
570+
}
571+
if (renoteLocalOnly) return i18n.ts._tms.disableFederationRenote;
572+
return i18n.ts.renote;
573+
})();
574+
575+
normalRenoteItems.push({
576+
text: renoteButtonText,
550577
icon: 'ti ti-repeat',
551578
action: () => {
552-
const el = props.renoteButton.value;
553-
if (el) {
554-
const rect = el.getBoundingClientRect();
555-
const x = rect.left + (el.offsetWidth / 2);
556-
const y = rect.top + (el.offsetHeight / 2);
557-
os.popup(MkRippleEffect, { x, y }, {}, 'end');
558-
}
559-
560-
const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
561-
const localOnly = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
562-
563-
let visibility = appearNote.visibility;
564-
visibility = smallerVisibility(visibility, configuredVisibility);
565-
if (appearNote.channel?.isSensitive) {
566-
visibility = smallerVisibility(visibility, 'home');
567-
}
568-
569-
if (!props.mock) {
570-
misskeyApi('notes/create', {
571-
localOnly,
572-
visibility,
573-
renoteId: appearNote.id,
574-
}).then(() => {
575-
os.toast(i18n.ts.renoted);
576-
});
577-
}
579+
rippleEffect();
580+
if (props.mock) return tooltipEffect(i18n.ts.renoted);
581+
misskeyApi('notes/create', {
582+
renoteId: appearNote.id,
583+
visibility: renoteVisibility,
584+
localOnly: renoteLocalOnly,
585+
}).then(() => tooltipEffect(i18n.ts.renoted)).catch(errorDialog);
578586
},
579-
}, (props.mock) ? undefined : {
580-
text: i18n.ts.quote,
581-
icon: 'ti ti-quote',
582-
action: () => {
583-
os.post({
584-
renote: appearNote,
585-
});
586-
},
587-
}]);
587+
});
588+
if (!props.mock) {
589+
normalRenoteItems.push({
590+
text: i18n.ts.quote,
591+
icon: 'ti ti-quote',
592+
action: () => {
593+
os.post({
594+
renote: appearNote,
595+
});
596+
},
597+
});
598+
}
588599
}
589600

590601
if (tmsStore.state.enablePakuru) {
591602
pakuruItems.push({
592603
text: i18n.ts._tms.pakuru,
593604
icon: 'ti ti-swipe',
594605
action: () => {
595-
const tooltip = (): void => {
596-
tooltipFromElement({
597-
targetElement: props.renoteButton.value,
598-
text: i18n.ts._tms.didPakuru,
599-
primary: true,
600-
});
601-
};
602-
if (props.mock) return tooltip();
603-
pakuru(appearNote).then(() => tooltip()).catch((err) => {
604-
os.alert({
605-
type: 'error',
606-
text: parseErrorMessage(err),
607-
});
608-
});
606+
if (props.mock) return tooltipEffect(i18n.ts._tms.didPakuru);
607+
pakuru(appearNote).then(() => tooltipEffect(i18n.ts._tms.didPakuru)).catch(errorDialog);
609608
},
610609
});
611610
}
@@ -615,20 +614,8 @@ export function getRenoteMenu(props: {
615614
text: i18n.ts._tms.numberquote,
616615
icon: 'ti ti-exposure-plus-1',
617616
action: () => {
618-
const tooltip = (): void => {
619-
tooltipFromElement({
620-
targetElement: props.renoteButton.value,
621-
text: i18n.ts._tms.didNumberquote,
622-
primary: true,
623-
});
624-
};
625-
if (props.mock) return tooltip();
626-
numberquote(appearNote).then(() => tooltip()).catch((err) => {
627-
os.alert({
628-
type: 'error',
629-
text: parseErrorMessage(err),
630-
});
631-
});
617+
if (props.mock) return tooltipEffect(i18n.ts._tms.didNumberquote);
618+
numberquote(appearNote).then(() => tooltipEffect(i18n.ts._tms.didNumberquote)).catch(errorDialog);
632619
},
633620
});
634621
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* SPDX-FileCopyrightText: syuilo and misskey-project
3+
* SPDX-License-Identifier: AGPL-3.0-only
4+
*/
5+
6+
import type * as Misskey from 'misskey-js';
7+
8+
type Visibility = (typeof Misskey.noteVisibilities)[number];
9+
10+
export const smallerVisibility = (list: Visibility[]): Visibility => {
11+
if (list.includes('specified')) return 'specified' as const;
12+
if (list.includes('followers')) return 'followers' as const;
13+
if (list.includes('home')) return 'home' as const;
14+
return 'public' as const;
15+
};

packages/frontend/src/store.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export const defaultStore = markRaw(new Storage('base', {
9494
},
9595
defaultNoteVisibility: {
9696
where: 'account',
97-
default: 'public',
97+
default: 'public' as 'public' | 'home' | 'followers' | 'specified',
9898
},
9999
defaultNoteLocalOnly: {
100100
where: 'account',

0 commit comments

Comments
 (0)