Skip to content

Commit

Permalink
fix: 連合なしの状態の読み書きができない問題、他 (#206)
Browse files Browse the repository at this point in the history
* fix: 連合なしの状態の読み書きができない問題
* fix: canPakuru: trueの場合、canRenoteを無視してリノートボタンが表示される問題
* refactoring: 共通部分を関数でまとめたり、三項演算子をやめてif文の記述にしたり、など
  • Loading branch information
taiyme authored Apr 30, 2024
1 parent 5f93074 commit 3979cc2
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 110 deletions.
20 changes: 20 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9945,6 +9945,26 @@ export interface Locale extends ILocale {
* センシティブなファイルを表示しています。
*/
readonly "displayingSensitiveFiles": string;
/**
* ホームリノート
*/
readonly "homeRenote": string;
/**
* フォロワーリノート
*/
readonly "followersRenote": string;
/**
* リノート (連合なし)
*/
readonly "disableFederationRenote": string;
/**
* ホームリノート (連合なし)
*/
readonly "disableFederationHomeRenote": string;
/**
* フォロワーリノート (連合なし)
*/
readonly "disableFederationFollowersRenote": string;
/**
* パクる
*/
Expand Down
5 changes: 5 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2650,6 +2650,11 @@ _tms:
reportIssuesToGithub: "問題の報告や要望はGitHubで受け付けています。"
displayingGifFiles: "GIFファイルを表示しています。"
displayingSensitiveFiles: "センシティブなファイルを表示しています。"
homeRenote: "ホームリノート"
followersRenote: "フォロワーリノート"
disableFederationRenote: "リノート (連合なし)"
disableFederationHomeRenote: "ホームリノート (連合なし)"
disableFederationFollowersRenote: "フォロワーリノート (連合なし)"
pakuru: "パクる"
numberquote: "数字引用する"
didPakuru: "パクりました"
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/MkNote.vue
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ function renote(viaKeyboard = false) {
pleaseLogin();
showMovedDialog();

const { menu } = getRenoteMenu({ note: note.value, renoteButton, mock: props.mock });
const { menu } = getRenoteMenu({ note: note.value, renoteButton, mock: props.mock, canRenote: canRenote.value });
os.popupMenu(menu, renoteButton.value, {
viaKeyboard,
});
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/MkNoteDetailed.vue
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ function renote(viaKeyboard = false) {
pleaseLogin();
showMovedDialog();

const { menu } = getRenoteMenu({ note: note.value, renoteButton });
const { menu } = getRenoteMenu({ note: note.value, renoteButton, canRenote: canRenote.value });
os.popupMenu(menu, renoteButton.value, {
viaKeyboard,
});
Expand Down
8 changes: 6 additions & 2 deletions packages/frontend/src/components/MkPostForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ const props = withDefaults(defineProps<{
initialVisibleUsers: () => [],
autofocus: true,
mock: false,
initialLocalOnly: undefined,
});

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

localOnly.value = !localOnly.value;
if (defaultStore.state.rememberNoteVisibility) {
defaultStore.set('localOnly', localOnly.value);
}
}

async function toggleReactionAcceptance() {
Expand Down
6 changes: 4 additions & 2 deletions packages/frontend/src/components/MkPostFormDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import * as Misskey from 'misskey-js';
import MkModal from '@/components/MkModal.vue';
import MkPostForm from '@/components/MkPostForm.vue';

const props = defineProps<{
const props = withDefaults(defineProps<{
reply?: Misskey.entities.Note;
renote?: Misskey.entities.Note;
channel?: any; // TODO
Expand All @@ -31,7 +31,9 @@ const props = defineProps<{
instant?: boolean;
fixed?: boolean;
autofocus?: boolean;
}>();
}>(), {
initialLocalOnly: undefined,
});

const emit = defineEmits<{
(ev: 'closed'): void;
Expand Down
193 changes: 90 additions & 103 deletions packages/frontend/src/scripts/get-note-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { getAppearNote } from '@/scripts/tms/get-appear-note.js';
import { numberquote } from '@/scripts/tms/numberquote.js';
import { pakuru } from '@/scripts/tms/pakuru.js';
import { tooltipFromElement } from '@/scripts/tms/tooltip-from-element.js';
import { smallerVisibility } from '@/scripts/tms/visibility.js';
import { tmsStore } from '@/tms/store.js';

export async function getNoteClipMenu(props: {
Expand Down Expand Up @@ -486,126 +487,124 @@ export function getNoteMenu(props: {
};
}

type Visibility = 'public' | 'home' | 'followers' | 'specified';

// defaultStore.state.visibilityがstringなためstringも受け付けている
function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility {
if (a === 'specified' || b === 'specified') return 'specified';
if (a === 'followers' || b === 'followers') return 'followers';
if (a === 'home' || b === 'home') return 'home';
// if (a === 'public' || b === 'public')
return 'public';
}

export function getRenoteMenu(props: {
note: Misskey.entities.Note;
renoteButton: ShallowRef<HTMLElement | undefined>;
mock?: boolean;
canRenote?: boolean;
}) {
const appearNote = getAppearNote(props.note);
const canRenote = props.canRenote ?? true;

const rippleEffect = (): void => {
const el = props.renoteButton.value;
if (el == null) return;
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
const y = rect.top + (el.offsetHeight / 2);
os.popup(MkRippleEffect, { x, y }, {}, 'end');
};

const tooltipEffect = (text: string): void => {
tooltipFromElement({
targetElement: props.renoteButton.value,
primary: true,
text,
});
};

const errorDialog = (err: unknown): void => {
os.alert({
type: 'error',
text: parseErrorMessage(err),
});
};

const channelRenoteItems: MenuItem[] = [];
const normalRenoteItems: MenuItem[] = [];
const pakuruItems: MenuItem[] = [];

if (appearNote.channel) {
channelRenoteItems.push(...[{
if (canRenote && appearNote.channel != null) {
channelRenoteItems.push({
text: i18n.ts.inChannelRenote,
icon: 'ti ti-repeat',
action: () => {
const el = props.renoteButton.value;
if (el) {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
const y = rect.top + (el.offsetHeight / 2);
os.popup(MkRippleEffect, { x, y }, {}, 'end');
}

if (!props.mock) {
misskeyApi('notes/create', {
renoteId: appearNote.id,
channelId: appearNote.channelId,
}).then(() => {
os.toast(i18n.ts.renoted);
});
}
rippleEffect();
if (props.mock) return tooltipEffect(i18n.ts.renoted);
misskeyApi('notes/create', {
renoteId: appearNote.id,
channelId: appearNote.channelId,
}).then(() => tooltipEffect(i18n.ts.renoted)).catch(errorDialog);
},
}, {
text: i18n.ts.inChannelQuote,
icon: 'ti ti-quote',
action: () => {
if (!props.mock) {
});
if (!props.mock) {
channelRenoteItems.push({
text: i18n.ts.inChannelQuote,
icon: 'ti ti-quote',
action: () => {
os.post({
renote: appearNote,
channel: appearNote.channel,
});
}
},
}]);
},
});
}
}

if (!appearNote.channel || appearNote.channel.allowRenoteToExternal) {
normalRenoteItems.push(...[{
text: i18n.ts.renote,
if (canRenote && (appearNote.channel == null || appearNote.channel.allowRenoteToExternal)) {
let renoteVisibility = appearNote.visibility;
const renoteLocalOnly = appearNote.localOnly ?? false;

if (appearNote.channel?.isSensitive || $i?.isSilenced) {
renoteVisibility = smallerVisibility([renoteVisibility, 'home']);
}

const renoteButtonText = (() => {
if (renoteVisibility === 'home') {
if (renoteLocalOnly) return i18n.ts._tms.disableFederationHomeRenote;
return i18n.ts._tms.homeRenote;
}
if (renoteVisibility === 'followers') {
if (renoteLocalOnly) return i18n.ts._tms.disableFederationFollowersRenote;
return i18n.ts._tms.followersRenote;
}
if (renoteLocalOnly) return i18n.ts._tms.disableFederationRenote;
return i18n.ts.renote;
})();

normalRenoteItems.push({
text: renoteButtonText,
icon: 'ti ti-repeat',
action: () => {
const el = props.renoteButton.value;
if (el) {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
const y = rect.top + (el.offsetHeight / 2);
os.popup(MkRippleEffect, { x, y }, {}, 'end');
}

const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
const localOnly = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;

let visibility = appearNote.visibility;
visibility = smallerVisibility(visibility, configuredVisibility);
if (appearNote.channel?.isSensitive) {
visibility = smallerVisibility(visibility, 'home');
}

if (!props.mock) {
misskeyApi('notes/create', {
localOnly,
visibility,
renoteId: appearNote.id,
}).then(() => {
os.toast(i18n.ts.renoted);
});
}
rippleEffect();
if (props.mock) return tooltipEffect(i18n.ts.renoted);
misskeyApi('notes/create', {
renoteId: appearNote.id,
visibility: renoteVisibility,
localOnly: renoteLocalOnly,
}).then(() => tooltipEffect(i18n.ts.renoted)).catch(errorDialog);
},
}, (props.mock) ? undefined : {
text: i18n.ts.quote,
icon: 'ti ti-quote',
action: () => {
os.post({
renote: appearNote,
});
},
}]);
});
if (!props.mock) {
normalRenoteItems.push({
text: i18n.ts.quote,
icon: 'ti ti-quote',
action: () => {
os.post({
renote: appearNote,
});
},
});
}
}

if (tmsStore.state.enablePakuru) {
pakuruItems.push({
text: i18n.ts._tms.pakuru,
icon: 'ti ti-swipe',
action: () => {
const tooltip = (): void => {
tooltipFromElement({
targetElement: props.renoteButton.value,
text: i18n.ts._tms.didPakuru,
primary: true,
});
};
if (props.mock) return tooltip();
pakuru(appearNote).then(() => tooltip()).catch((err) => {
os.alert({
type: 'error',
text: parseErrorMessage(err),
});
});
if (props.mock) return tooltipEffect(i18n.ts._tms.didPakuru);
pakuru(appearNote).then(() => tooltipEffect(i18n.ts._tms.didPakuru)).catch(errorDialog);
},
});
}
Expand All @@ -615,20 +614,8 @@ export function getRenoteMenu(props: {
text: i18n.ts._tms.numberquote,
icon: 'ti ti-exposure-plus-1',
action: () => {
const tooltip = (): void => {
tooltipFromElement({
targetElement: props.renoteButton.value,
text: i18n.ts._tms.didNumberquote,
primary: true,
});
};
if (props.mock) return tooltip();
numberquote(appearNote).then(() => tooltip()).catch((err) => {
os.alert({
type: 'error',
text: parseErrorMessage(err),
});
});
if (props.mock) return tooltipEffect(i18n.ts._tms.didNumberquote);
numberquote(appearNote).then(() => tooltipEffect(i18n.ts._tms.didNumberquote)).catch(errorDialog);
},
});
}
Expand Down
15 changes: 15 additions & 0 deletions packages/frontend/src/scripts/tms/visibility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

import type * as Misskey from 'misskey-js';

type Visibility = (typeof Misskey.noteVisibilities)[number];

export const smallerVisibility = (list: Visibility[]): Visibility => {
if (list.includes('specified')) return 'specified' as const;
if (list.includes('followers')) return 'followers' as const;
if (list.includes('home')) return 'home' as const;
return 'public' as const;
};
2 changes: 1 addition & 1 deletion packages/frontend/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const defaultStore = markRaw(new Storage('base', {
},
defaultNoteVisibility: {
where: 'account',
default: 'public',
default: 'public' as 'public' | 'home' | 'followers' | 'specified',
},
defaultNoteLocalOnly: {
where: 'account',
Expand Down

0 comments on commit 3979cc2

Please sign in to comment.