summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/frontend/src/components/MkMenu.vue28
-rw-r--r--packages/frontend/src/scripts/get-note-menu.ts120
2 files changed, 82 insertions, 66 deletions
diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue
index 52aba58455..09d530c4ea 100644
--- a/packages/frontend/src/components/MkMenu.vue
+++ b/packages/frontend/src/components/MkMenu.vue
@@ -56,7 +56,7 @@
</template>
<script lang="ts" setup>
-import { defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, watch } from 'vue';
+import { defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { focusPrev, focusNext } from '@/scripts/focus';
import MkSwitch from '@/components/MkSwitch.vue';
import { MenuItem, InnerMenuItem, MenuPending, MenuAction } from '@/types/menu';
@@ -111,11 +111,11 @@ watch(() => props.items, () => {
immediate: true,
});
-let childMenu = $ref<MenuItem[] | null>();
+let childMenu = ref<MenuItem[] | null>();
let childTarget = $shallowRef<HTMLElement | null>();
function closeChild() {
- childMenu = null;
+ childMenu.value = null;
childShowingItem = null;
}
@@ -140,13 +140,31 @@ function onItemMouseLeave(item) {
if (childCloseTimer) window.clearTimeout(childCloseTimer);
}
+let childrenCache = new WeakMap();
async function showChildren(item: MenuItem, ev: MouseEvent) {
+ const children = ref([]);
+ if (childrenCache.has(item)) {
+ children.value = childrenCache.get(item);
+ } else {
+ if (typeof item.children === 'function') {
+ children.value = [{
+ type: 'pending',
+ }];
+ item.children().then(x => {
+ children.value = x;
+ childrenCache.set(item, x);
+ });
+ } else {
+ children.value = item.children;
+ }
+ }
+
if (props.asDrawer) {
- os.popupMenu(item.children, ev.currentTarget ?? ev.target);
+ os.popupMenu(children, ev.currentTarget ?? ev.target);
close();
} else {
childTarget = ev.currentTarget ?? ev.target;
- childMenu = item.children;
+ childMenu = children;
childShowingItem = item;
}
}
diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts
index 9da7447bfd..f732c259fb 100644
--- a/packages/frontend/src/scripts/get-note-menu.ts
+++ b/packages/frontend/src/scripts/get-note-menu.ts
@@ -99,66 +99,6 @@ export function getNoteMenu(props: {
});
}
- async function clip(): Promise<void> {
- const clips = await os.api('clips/list');
- os.popupMenu([{
- icon: 'ti ti-plus',
- text: i18n.ts.createNew,
- action: async () => {
- const { canceled, result } = await os.form(i18n.ts.createNewClip, {
- name: {
- type: 'string',
- label: i18n.ts.name,
- },
- description: {
- type: 'string',
- required: false,
- multiline: true,
- label: i18n.ts.description,
- },
- isPublic: {
- type: 'boolean',
- label: i18n.ts.public,
- default: false,
- },
- });
- if (canceled) return;
-
- const clip = await os.apiWithDialog('clips/create', result);
-
- claimAchievement('noteClipped1');
- os.apiWithDialog('clips/add-note', { clipId: clip.id, noteId: appearNote.id });
- },
- }, null, ...clips.map(clip => ({
- text: clip.name,
- action: () => {
- claimAchievement('noteClipped1');
- os.promiseDialog(
- os.api('clips/add-note', { clipId: clip.id, noteId: appearNote.id }),
- null,
- async (err) => {
- if (err.id === '734806c4-542c-463a-9311-15c512803965') {
- const confirm = await os.confirm({
- type: 'warning',
- text: i18n.t('confirmToUnclipAlreadyClippedNote', { name: clip.name }),
- });
- if (!confirm.canceled) {
- os.apiWithDialog('clips/remove-note', { clipId: clip.id, noteId: appearNote.id });
- if (props.currentClipPage?.value.id === clip.id) props.isDeleted.value = true;
- }
- } else {
- os.alert({
- type: 'error',
- text: err.message + '\n' + err.id,
- });
- }
- },
- );
- },
- }))], props.menuButton.value, {
- }).then(focus);
- }
-
async function unclip(): Promise<void> {
os.apiWithDialog('clips/remove-note', { clipId: props.currentClipPage.value.id, noteId: appearNote.id });
props.isDeleted.value = true;
@@ -264,9 +204,67 @@ export function getNoteMenu(props: {
action: () => toggleFavorite(true),
}),
{
+ type: 'parent',
icon: 'ti ti-paperclip',
text: i18n.ts.clip,
- action: () => clip(),
+ children: async () => {
+ const clips = await os.api('clips/list');
+ return [{
+ icon: 'ti ti-plus',
+ text: i18n.ts.createNew,
+ action: async () => {
+ const { canceled, result } = await os.form(i18n.ts.createNewClip, {
+ name: {
+ type: 'string',
+ label: i18n.ts.name,
+ },
+ description: {
+ type: 'string',
+ required: false,
+ multiline: true,
+ label: i18n.ts.description,
+ },
+ isPublic: {
+ type: 'boolean',
+ label: i18n.ts.public,
+ default: false,
+ },
+ });
+ if (canceled) return;
+
+ const clip = await os.apiWithDialog('clips/create', result);
+
+ claimAchievement('noteClipped1');
+ os.apiWithDialog('clips/add-note', { clipId: clip.id, noteId: appearNote.id });
+ },
+ }, null, ...clips.map(clip => ({
+ text: clip.name,
+ action: () => {
+ claimAchievement('noteClipped1');
+ os.promiseDialog(
+ os.api('clips/add-note', { clipId: clip.id, noteId: appearNote.id }),
+ null,
+ async (err) => {
+ if (err.id === '734806c4-542c-463a-9311-15c512803965') {
+ const confirm = await os.confirm({
+ type: 'warning',
+ text: i18n.t('confirmToUnclipAlreadyClippedNote', { name: clip.name }),
+ });
+ if (!confirm.canceled) {
+ os.apiWithDialog('clips/remove-note', { clipId: clip.id, noteId: appearNote.id });
+ if (props.currentClipPage?.value.id === clip.id) props.isDeleted.value = true;
+ }
+ } else {
+ os.alert({
+ type: 'error',
+ text: err.message + '\n' + err.id,
+ });
+ }
+ },
+ );
+ },
+ }))];
+ },
},
statePromise.then(state => state.isMutedThread ? {
icon: 'ti ti-message-off',