summaryrefslogtreecommitdiff
path: root/packages/frontend/src/scripts/get-note-menu.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/scripts/get-note-menu.ts')
-rw-r--r--packages/frontend/src/scripts/get-note-menu.ts79
1 files changed, 72 insertions, 7 deletions
diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts
index b273bd36f3..71ad299f50 100644
--- a/packages/frontend/src/scripts/get-note-menu.ts
+++ b/packages/frontend/src/scripts/get-note-menu.ts
@@ -16,7 +16,7 @@ import { url } from '@/config.js';
import { defaultStore, noteActions } from '@/store.js';
import { miLocalStorage } from '@/local-storage.js';
import { getUserMenu } from '@/scripts/get-user-menu.js';
-import { clipsCache } from '@/cache.js';
+import { clipsCache, favoritedChannelsCache } from '@/cache.js';
import { MenuItem } from '@/types/menu.js';
import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { isSupportShare } from '@/scripts/navigator.js';
@@ -26,6 +26,14 @@ export async function getNoteClipMenu(props: {
isDeleted: Ref<boolean>;
currentClip?: Misskey.entities.Clip;
}) {
+ function getClipName(clip: Misskey.entities.Clip) {
+ if ($i && clip.userId === $i.id && clip.notesCount != null) {
+ return `${clip.name} (${clip.notesCount}/${$i.policies.noteEachClipsLimit})`;
+ } else {
+ return clip.name;
+ }
+ }
+
const isRenote = (
props.note.renote != null &&
props.note.text == null &&
@@ -37,7 +45,7 @@ export async function getNoteClipMenu(props: {
const clips = await clipsCache.fetch();
const menu: MenuItem[] = [...clips.map(clip => ({
- text: clip.name,
+ text: getClipName(clip),
action: () => {
claimAchievement('noteClipped1');
os.promiseDialog(
@@ -50,7 +58,18 @@ export async function getNoteClipMenu(props: {
text: i18n.tsx.confirmToUnclipAlreadyClippedNote({ name: clip.name }),
});
if (!confirm.canceled) {
- os.apiWithDialog('clips/remove-note', { clipId: clip.id, noteId: appearNote.id });
+ os.apiWithDialog('clips/remove-note', { clipId: clip.id, noteId: appearNote.id }).then(() => {
+ clipsCache.set(clips.map(c => {
+ if (c.id === clip.id) {
+ return {
+ ...c,
+ notesCount: Math.max(0, ((c.notesCount ?? 0) - 1)),
+ };
+ } else {
+ return c;
+ }
+ }));
+ });
if (props.currentClip?.id === clip.id) props.isDeleted.value = true;
}
} else {
@@ -60,7 +79,18 @@ export async function getNoteClipMenu(props: {
});
}
},
- );
+ ).then(() => {
+ clipsCache.set(clips.map(c => {
+ if (c.id === clip.id) {
+ return {
+ ...c,
+ notesCount: (c.notesCount ?? 0) + 1,
+ };
+ } else {
+ return c;
+ }
+ }));
+ });
},
})), { type: 'divider' }, {
icon: 'ti ti-plus',
@@ -462,10 +492,9 @@ export function getNoteMenu(props: {
};
}
-type Visibility = 'public' | 'home' | 'followers' | 'specified';
+type Visibility = (typeof Misskey.noteVisibilities)[number];
-// defaultStore.state.visibilityがstringなためstringも受け付けている
-function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility {
+function smallerVisibility(a: Visibility, b: Visibility): Visibility {
if (a === 'specified' || b === 'specified') return 'specified';
if (a === 'followers' || b === 'followers') return 'followers';
if (a === 'home' || b === 'home') return 'home';
@@ -489,6 +518,7 @@ export function getRenoteMenu(props: {
const channelRenoteItems: MenuItem[] = [];
const normalRenoteItems: MenuItem[] = [];
+ const normalExternalChannelRenoteItems: MenuItem[] = [];
if (appearNote.channel) {
channelRenoteItems.push(...[{
@@ -567,12 +597,47 @@ export function getRenoteMenu(props: {
});
},
}]);
+
+ normalExternalChannelRenoteItems.push({
+ type: 'parent',
+ icon: 'ti ti-repeat',
+ text: appearNote.channel ? i18n.ts.renoteToOtherChannel : i18n.ts.renoteToChannel,
+ children: async () => {
+ const channels = await favoritedChannelsCache.fetch();
+ return channels.filter((channel) => {
+ if (!appearNote.channelId) return true;
+ return channel.id !== appearNote.channelId;
+ }).map((channel) => ({
+ text: channel.name,
+ 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: channel.id,
+ }).then(() => {
+ os.toast(i18n.tsx.renotedToX({ name: channel.name }));
+ });
+ }
+ },
+ }));
+ },
+ });
}
const renoteItems = [
...normalRenoteItems,
...(channelRenoteItems.length > 0 && normalRenoteItems.length > 0) ? [{ type: 'divider' }] as MenuItem[] : [],
...channelRenoteItems,
+ ...(normalExternalChannelRenoteItems.length > 0 && (normalRenoteItems.length > 0 || channelRenoteItems.length > 0)) ? [{ type: 'divider' }] as MenuItem[] : [],
+ ...normalExternalChannelRenoteItems,
];
return {