diff --git a/CHANGELOG_CHERRYPICK.md b/CHANGELOG_CHERRYPICK.md
index b1ceee3cf7..664d55725f 100644
--- a/CHANGELOG_CHERRYPICK.md
+++ b/CHANGELOG_CHERRYPICK.md
@@ -52,6 +52,7 @@
- Feat: Scratchpad에서 Async: 계열 함수나 버튼 콜백 등의 오류에도 대화창을 띄우도록(시험적이라 Play 등에는 미구현) (misskey-dev/misskey#11850)
- Feat: 민감한 미디어를 돋보이게 하는 설정 추가 (misskey-dev/misskey#11851)
- Feat: 알림에서 답글이 달린 노트의 상위 노트를 표시하지 않도록 하는 설정 추가
+- Feat: 리노트와 인용 버튼을 표시하는 방법을 선택할 수 있음
- Spec: 사용자 정의 이모티콘 라이센스를 여러 항목으로 추가할 수 있도록 (MisskeyIO/misskey#130)
- Enhance: 새로운 신고가 있는 경우, 네비게이션 바의 제어판 아이콘과 제어판 페이지의 신고 섹션에 점을 표시
- Enhance: 스크롤 시 요소 표시 기능을 Friendly 이외의 UI에도 대응
diff --git a/locales/en-US.yml b/locales/en-US.yml
index 180000f6cc..faf579f5bd 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -1223,6 +1223,7 @@ _cherrypick:
renameTheButtonInPostFormToNya: "Change the \"Note\" button on the note-posting form to \"Nyan!\""
renameTheButtonInPostFormToNyaDescription: "Outside of the note-posting form, they are still as \"Note\"."
showReplyInNotification: "Show parent note of notes with replies in notifications"
+ renoteQuoteButtonSeparation: "Separate Renote and Quote buttons"
_displayHeaderNavBarWhenScroll:
all: "Display all"
hideHeaderOnly: "Hide header only"
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 0182556d61..d9e12bb769 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -1234,6 +1234,7 @@ export interface Locale {
"renameTheButtonInPostFormToNya": string;
"renameTheButtonInPostFormToNyaDescription": string;
"showReplyInNotification": string;
+ "renoteQuoteButtonSeparation": string;
};
"_displayHeaderNavBarWhenScroll": {
"all": string;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 12ba5f9b69..a4fdb7a3e4 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1232,6 +1232,7 @@ _cherrypick:
renameTheButtonInPostFormToNya: "ノート作成画面の「ノート」ボタンを「にゃ!」に変更する"
renameTheButtonInPostFormToNyaDescription: "にゃあにゃんにゃんにゃんにゃにゃん?"
showReplyInNotification: "通知で返信があるノートの親ノートを表示する"
+ renoteQuoteButtonSeparation: "リノートと引用ボタンを分けて表示する"
_displayHeaderNavBarWhenScroll:
all: "全て表示"
diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml
index deea3a7dc2..5fa16166ee 100644
--- a/locales/ko-KR.yml
+++ b/locales/ko-KR.yml
@@ -1219,6 +1219,7 @@ _cherrypick:
renameTheButtonInPostFormToNya: "노트 작성 화면의 \"노트\" 버튼을 \"냥!\"으로 변경"
renameTheButtonInPostFormToNyaDescription: "냐앙냥냥냥냐냥?"
showReplyInNotification: "알림에서 답글이 달린 노트의 상위 노트 표시하기"
+ renoteQuoteButtonSeparation: "리노트와 인용 버튼을 분리해서 표시하기"
_displayHeaderNavBarWhenScroll:
all: "모두 표시"
hideHeaderOnly: "헤더만 숨기기"
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index dca5eeca05..8699a920da 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -51,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
{{ appearNote.renoteCount }}
@@ -143,7 +143,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -216,7 +216,7 @@ const props = withDefaults(defineProps<{ pinned?: boolean; notification?: boolean; }>(), { - notification: false, + notification: false, }); const inChannel = inject('inChannel', null); @@ -275,7 +275,7 @@ const keymap = { }; onMounted(() => { - globalEvents.on('showEl', (showEl_receive) => { + globalEvents.on('showEl', (showEl_receive) => { showEl = showEl_receive; }); }); @@ -315,7 +315,89 @@ function smallerVisibility(a: Visibility | string, b: Visibility | string): Visi return 'public'; } -async function renote() { +function renote(viaKeyboard = false) { + pleaseLogin(); + showMovedDialog(); + + let items = [] as MenuItem[]; + + if (appearNote.channel) { + items = items.concat([{ + text: i18n.ts.inChannelRenote, + icon: 'ti ti-repeat', + action: () => { + const el = renoteButton.value as HTMLElement | null | undefined; + 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'); + } + + os.api('notes/create', { + renoteId: appearNote.id, + channelId: appearNote.channelId, + }).then(() => { + os.noteToast(i18n.ts.renoted); + }); + }, + }, { + text: i18n.ts.inChannelQuote, + icon: 'ti ti-quote', + action: () => { + os.post({ + renote: appearNote, + channel: appearNote.channel, + }); + }, + }, null]); + } + + items = items.concat([{ + text: i18n.ts.renote, + icon: 'ti ti-repeat', + action: () => { + const el = renoteButton.value as HTMLElement | null | undefined; + 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'); + } + + os.api('notes/create', { + localOnly, + visibility, + renoteId: appearNote.id, + }).then(() => { + os.noteToast(i18n.ts.renoted); + }); + }, + }, { + text: i18n.ts.quote, + icon: 'ti ti-quote', + action: () => { + os.post({ + renote: appearNote, + }); + }, + }]); + + os.popupMenu(items, renoteButton.value, { + viaKeyboard, + }); +} + +async function renoteOnly() { pleaseLogin(); showMovedDialog(); diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index c1a1cc3bcd..7a7202fd51 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -139,7 +139,7 @@ SPDX-License-Identifier: AGPL-3.0-only v-tooltip="i18n.ts.renote" class="_button" :class="$style.noteFooterButton" - @mousedown="renote()" + @mousedown="defaultStore.state.renoteQuoteButtonSeparation ? renoteOnly() : renote()" >{{ appearNote.renoteCount }}
@@ -157,7 +157,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -353,7 +353,78 @@ useTooltip(renoteButton, async (showing) => { }, {}, 'closed'); }); -async function renote() { +function renote(viaKeyboard = false) { + pleaseLogin(); + showMovedDialog(); + + let items = [] as MenuItem[]; + + if (appearNote.channel) { + items = items.concat([{ + text: i18n.ts.inChannelRenote, + icon: 'ti ti-repeat', + action: () => { + const el = renoteButton.value as HTMLElement | null | undefined; + 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'); + } + + os.api('notes/create', { + renoteId: appearNote.id, + channelId: appearNote.channelId, + }).then(() => { + os.noteToast(i18n.ts.renoted); + }); + }, + }, { + text: i18n.ts.inChannelQuote, + icon: 'ti ti-quote', + action: () => { + os.post({ + renote: appearNote, + channel: appearNote.channel, + }); + }, + }, null]); + } + + items = items.concat([{ + text: i18n.ts.renote, + icon: 'ti ti-repeat', + action: () => { + const el = renoteButton.value as HTMLElement | null | undefined; + 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'); + } + + os.api('notes/create', { + renoteId: appearNote.id, + }).then(() => { + os.noteToast(i18n.ts.renoted); + }); + }, + }, { + text: i18n.ts.quote, + icon: 'ti ti-quote', + action: () => { + os.post({ + renote: appearNote, + }); + }, + }]); + + os.popupMenu(items, renoteButton.value, { + viaKeyboard, + }); +} + +async function renoteOnly() { pleaseLogin(); showMovedDialog(); diff --git a/packages/frontend/src/components/MkSubNoteContent.vue b/packages/frontend/src/components/MkSubNoteContent.vue index ede99496e3..5ffd1ccefd 100644 --- a/packages/frontend/src/components/MkSubNoteContent.vue +++ b/packages/frontend/src/components/MkSubNoteContent.vue @@ -62,7 +62,7 @@ SPDX-License-Identifier: AGPL-3.0-only v-tooltip="i18n.ts.renote" :class="$style.footerButton" class="_button" - @mousedown="renote()" + @mousedown="defaultStore.state.renoteQuoteButtonSeparation ? renoteOnly() : renote()" >{{ note.renoteCount }}
@@ -80,7 +80,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -120,6 +120,7 @@ import { deepClone } from '@/scripts/clone.js'; import { reactionPicker } from '@/scripts/reaction-picker.js'; import { claimAchievement } from '@/scripts/achievements.js'; import { useNoteCapture } from '@/scripts/use-note-capture.js'; +import { MenuItem } from '@/types/menu.js'; const el = shallowRef