diff options
| author | おさむのひと <46447427+samunohito@users.noreply.github.com> | 2023-11-03 17:34:23 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-03 17:34:23 +0900 |
| commit | 39a3f4ae98ebe436ed023fab737a823717da5e0b (patch) | |
| tree | cadb9e1bb9d24f16527fe6fb912d6a746cc59748 /packages/frontend/src/scripts | |
| parent | fix(frontend): In deck layout, replies option is not saved after refresh (diff) | |
| download | sharkey-39a3f4ae98ebe436ed023fab737a823717da5e0b.tar.gz sharkey-39a3f4ae98ebe436ed023fab737a823717da5e0b.tar.bz2 sharkey-39a3f4ae98ebe436ed023fab737a823717da5e0b.zip | |
feat: チャンネル内→チャンネル外へのリノート制限機能追加 (#12230)
* チャンネル内→チャンネル外へのリノート制限機能追加
* fix CHANGELOG.md
* コメント対応(canRenoteSwitch→allowRenoteToExternal)
* コメント対応(別チャンネルへのリノート対策)
* コメント対応(canRenote->allowRenoteToExternal)
* fix comment
* Update misskey-js.api.md
* :v:
---------
Co-authored-by: osamu <46447427+sam-osamu@users.noreply.github.com>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Diffstat (limited to 'packages/frontend/src/scripts')
| -rw-r--r-- | packages/frontend/src/scripts/get-note-menu.ts | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts index e399145fc9..d0753872ff 100644 --- a/packages/frontend/src/scripts/get-note-menu.ts +++ b/packages/frontend/src/scripts/get-note-menu.ts @@ -17,6 +17,7 @@ import { miLocalStorage } from '@/local-storage.js'; import { getUserMenu } from '@/scripts/get-user-menu.js'; import { clipsCache } from '@/cache.js'; import { MenuItem } from '@/types/menu.js'; +import MkRippleEffect from '@/components/MkRippleEffect.vue'; export async function getNoteClipMenu(props: { note: Misskey.entities.Note; @@ -418,3 +419,122 @@ export function getNoteMenu(props: { cleanup, }; } + +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: Ref<HTMLElement>; + mock?: boolean; +}) { + 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 channelRenoteItems: MenuItem[] = []; + const normalRenoteItems: MenuItem[] = []; + + if (appearNote.channel) { + channelRenoteItems.push(...[{ + text: i18n.ts.inChannelRenote, + icon: 'ti ti-repeat', + action: () => { + const el = props.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'); + } + + if (!props.mock) { + os.api('notes/create', { + renoteId: appearNote.id, + channelId: appearNote.channelId, + }).then(() => { + os.toast(i18n.ts.renoted); + }); + } + }, + }, { + text: i18n.ts.inChannelQuote, + icon: 'ti ti-quote', + action: () => { + if (!props.mock) { + os.post({ + renote: appearNote, + channel: appearNote.channel, + }); + } + }, + }]); + } + + if (!appearNote.channel || appearNote.channel?.allowRenoteToExternal) { + normalRenoteItems.push(...[{ + text: i18n.ts.renote, + icon: 'ti ti-repeat', + action: () => { + const el = props.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'); + } + + if (!props.mock) { + os.api('notes/create', { + localOnly, + visibility, + renoteId: appearNote.id, + }).then(() => { + os.toast(i18n.ts.renoted); + }); + } + }, + }, (props.mock) ? undefined : { + text: i18n.ts.quote, + icon: 'ti ti-quote', + action: () => { + os.post({ + renote: appearNote, + }); + }, + }]); + } + + // nullを挟むことで区切り線を出せる + const renoteItems = [ + ...normalRenoteItems, + ...(channelRenoteItems.length > 0 && normalRenoteItems.length > 0) ? [null] : [], + ...channelRenoteItems, + ]; + + return { + menu: renoteItems, + }; +} |