summaryrefslogtreecommitdiff
path: root/packages/frontend/src/scripts
diff options
context:
space:
mode:
authorおさむのひと <46447427+samunohito@users.noreply.github.com>2023-11-03 17:34:23 +0900
committerGitHub <noreply@github.com>2023-11-03 17:34:23 +0900
commit39a3f4ae98ebe436ed023fab737a823717da5e0b (patch)
treecadb9e1bb9d24f16527fe6fb912d6a746cc59748 /packages/frontend/src/scripts
parentfix(frontend): In deck layout, replies option is not saved after refresh (diff)
downloadsharkey-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.ts120
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,
+ };
+}