From fab7d5e484d86dc8c24850dd98ebc1ee3688910e Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Thu, 4 Jul 2024 12:33:43 +0900 Subject: [PATCH 1/7] fix(storybook): build skipping even after updating impl story files (#14124) --- packages/frontend/.storybook/changes.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/frontend/.storybook/changes.ts b/packages/frontend/.storybook/changes.ts index 7c70972e1e..bc7601441c 100644 --- a/packages/frontend/.storybook/changes.ts +++ b/packages/frontend/.storybook/changes.ts @@ -47,7 +47,6 @@ await fs.readFile( ) ) .map((path) => path.replace(/(?:(?<=\.stories)\.(?:impl|meta)|\.msw)(?=\.ts$)/g, '')) - .map((path) => (path.startsWith('.') ? path : `./${path}`)) ); if ( micromatch(Array.from(modules), [ From 6dd2e9fc0b1eeea6b5f04ccac93ccfab658f976d Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:14:49 +0900 Subject: [PATCH 2/7] refactor(frontend): refactor popup api and make sure call dispose callback Close #14122 --- packages/frontend/src/account.ts | 16 ++- packages/frontend/src/boot/main-boot.ts | 30 +++-- .../frontend/src/components/MkClickerGame.vue | 4 +- .../src/components/MkDrive.folder.vue | 5 +- .../frontend/src/components/MkEmojiPicker.vue | 4 +- packages/frontend/src/components/MkLink.vue | 6 +- packages/frontend/src/components/MkNote.vue | 16 ++- .../src/components/MkNoteDetailed.vue | 16 ++- .../frontend/src/components/MkPostForm.vue | 13 +- .../src/components/MkPostFormAttaches.vue | 5 +- packages/frontend/src/components/MkRange.vue | 10 +- .../src/components/MkReactionIcon.vue | 6 +- .../components/MkReactionsViewer.reaction.vue | 14 +- packages/frontend/src/components/MkSignin.vue | 5 +- .../components/MkSystemWebhookEditor.impl.ts | 6 +- .../frontend/src/components/MkUrlPreview.vue | 8 +- .../src/components/MkUserSetupDialog.vue | 6 +- .../src/components/MkVisitorDashboard.vue | 12 +- .../src/components/global/MkCustomEmoji.vue | 4 +- .../frontend/src/components/global/MkUrl.vue | 6 +- packages/frontend/src/directives/ripple.ts | 4 +- packages/frontend/src/directives/tooltip.ts | 6 +- .../frontend/src/directives/user-preview.ts | 5 +- packages/frontend/src/os.ts | 125 ++++++++++-------- packages/frontend/src/pages/admin-user.vue | 12 +- .../abuse-report/notification-recipient.vue | 6 +- .../src/pages/custom-emojis-manager.vue | 10 +- .../frontend/src/pages/drive.file.info.vue | 5 +- .../src/pages/drop-and-fusion.game.vue | 14 +- packages/frontend/src/pages/emojis.emoji.vue | 8 +- .../frontend/src/pages/reset-password.vue | 4 +- packages/frontend/src/pages/settings/2fa.vue | 6 +- .../frontend/src/pages/settings/accounts.vue | 10 +- packages/frontend/src/pages/settings/api.vue | 5 +- .../src/pages/settings/avatar-decoration.vue | 5 +- .../src/scripts/get-drive-file-menu.ts | 5 +- .../frontend/src/scripts/get-note-menu.ts | 18 ++- .../frontend/src/scripts/get-user-menu.ts | 6 +- .../frontend/src/scripts/install-plugin.ts | 5 +- packages/frontend/src/scripts/please-login.ts | 5 +- .../frontend/src/scripts/use-chart-tooltip.ts | 10 +- packages/frontend/src/ui/_common_/common.ts | 4 +- .../src/ui/_common_/navbar-for-mobile.vue | 5 +- packages/frontend/src/ui/_common_/navbar.vue | 5 +- packages/frontend/src/ui/classic.header.vue | 5 +- packages/frontend/src/ui/classic.sidebar.vue | 6 +- .../src/ui/deck/notifications-column.vue | 5 +- packages/frontend/src/ui/visitor.vue | 12 +- .../src/widgets/WidgetNotifications.vue | 5 +- 49 files changed, 317 insertions(+), 196 deletions(-) diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts index f99b550a83..4172016f89 100644 --- a/packages/frontend/src/account.ts +++ b/packages/frontend/src/account.ts @@ -184,10 +184,12 @@ export async function refreshAccount() { export async function login(token: Account['token'], redirect?: string) { const showing = ref(true); - popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), { success: false, showing: showing, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); if (_DEV_) console.log('logging as token ', token); const me = await fetchAccount(token, undefined, true) .catch(reason => { @@ -223,21 +225,23 @@ export async function openAccountMenu(opts: { if (!$i) return; function showSigninDialog() { - popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, { done: res => { addAccount(res.id, res.i); success(); }, - }, 'closed'); + closed: () => dispose(), + }); } function createAccount() { - popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, { done: res => { addAccount(res.id, res.i); switchAccountWithToken(res.i); }, - }, 'closed'); + closed: () => dispose(), + }); } async function switchAccount(account: Misskey.entities.UserDetailed) { diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 5cb19f388a..faf230a1a2 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -35,7 +35,9 @@ export async function mainBoot() { emojiPicker.init(); if (isClientUpdated && $i) { - popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, { + closed: () => dispose(), + }); } const stream = useStream(); @@ -96,7 +98,7 @@ export async function mainBoot() { }).render(); } } - } + } } catch (error) { // console.error(error); console.error('Failed to initialise the seasonal screen effect canvas context:', error); @@ -108,22 +110,28 @@ export async function mainBoot() { defaultStore.loaded.then(() => { if (defaultStore.state.accountSetupWizard !== -1) { - popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, { + closed: () => dispose(), + }); } }); for (const announcement of ($i.unreadAnnouncements ?? []).filter(x => x.display === 'dialog')) { - popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { announcement, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); } stream.on('announcementCreated', (ev) => { const announcement = ev.announcement; if (announcement.display === 'dialog') { - popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { announcement, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); } }); @@ -247,13 +255,17 @@ export async function mainBoot() { const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo'); if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) { if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) { - popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, { + closed: () => dispose(), + }); } } const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read'); if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') { - popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, { + closed: () => dispose(), + }); } if ('Notification' in window) { diff --git a/packages/frontend/src/components/MkClickerGame.vue b/packages/frontend/src/components/MkClickerGame.vue index b592609e18..00506fb735 100644 --- a/packages/frontend/src/components/MkClickerGame.vue +++ b/packages/frontend/src/components/MkClickerGame.vue @@ -35,7 +35,9 @@ const prevCookies = ref(0); function onClick(ev: MouseEvent) { const x = ev.clientX; const y = ev.clientY; - os.popup(MkPlusOneEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkPlusOneEffect, { x, y }, { + end: () => dispose(), + }); saveData.value!.cookies++; saveData.value!.totalCookies++; diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index 8da0d78f35..1cc8b15b73 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -257,10 +257,11 @@ function onContextmenu(ev: MouseEvent) { text: i18n.ts.openInWindow, icon: 'ti ti-app-window', action: () => { - os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), { initialFolder: props.folder, }, { - }, 'closed'); + closed: () => dispose(), + }); }, }, { type: 'divider' }, { text: i18n.ts.rename, diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 8a6bef54d8..4bd4bee1e5 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -402,7 +402,9 @@ function chosen(emoji: any, ev?: MouseEvent) { 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 { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } const key = getKey(emoji); diff --git a/packages/frontend/src/components/MkLink.vue b/packages/frontend/src/components/MkLink.vue index 5d54a58e97..e842ec2d6e 100644 --- a/packages/frontend/src/components/MkLink.vue +++ b/packages/frontend/src/components/MkLink.vue @@ -37,11 +37,13 @@ const el = ref(); if (isEnabledUrlPreview.value) { useTooltip(el, (showing) => { - os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), { showing, url: props.url, source: el.value instanceof HTMLElement ? el.value : el.value?.$el, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); } diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 22b1691a86..1313e4c58e 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -335,12 +335,14 @@ if (!props.mock) { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: renoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); if (appearNote.value.reactionAcceptance === 'likeOnly') { @@ -355,13 +357,15 @@ if (!props.mock) { if (users.length < 1) return; - os.popup(MkReactionsViewerDetails, { + const { dispose } = os.popup(MkReactionsViewerDetails, { showing, reaction: '❤️', users, count: appearNote.value.reactionCount, targetElement: reactButton.value!, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); } } @@ -409,7 +413,9 @@ function react(viaKeyboard = false): void { 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 { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } else { blur(); diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index ed1c0a9e96..bc1f416373 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -346,12 +346,14 @@ useTooltip(renoteButton, async (showing) => { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: renoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); if (appearNote.value.reactionAcceptance === 'likeOnly') { @@ -366,13 +368,15 @@ if (appearNote.value.reactionAcceptance === 'likeOnly') { if (users.length < 1) return; - os.popup(MkReactionsViewerDetails, { + const { dispose } = os.popup(MkReactionsViewerDetails, { showing, reaction: '❤️', users, count: appearNote.value.reactionCount, targetElement: reactButton.value!, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); } @@ -413,7 +417,9 @@ function react(viaKeyboard = false): void { 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 { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } else { blur(); diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index 1df9007681..0dc1aa0891 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -463,7 +463,7 @@ function setVisibility() { return; } - os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), { currentVisibility: visibility.value, isSilenced: $i.isSilenced, localOnly: localOnly.value, @@ -476,7 +476,8 @@ function setVisibility() { defaultStore.set('visibility', visibility.value); } }, - }, 'closed'); + closed: () => dispose(), + }); } async function toggleLocalOnly() { @@ -624,8 +625,8 @@ async function onPaste(ev: ClipboardEvent) { return; } - const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, "0"); - const file = new File([paste], `${fileName}.txt`, { type: "text/plain" }); + const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, '0'); + const file = new File([paste], `${fileName}.txt`, { type: 'text/plain' }); upload(file, `${fileName}.txt`); }); } @@ -731,7 +732,9 @@ async function post(ev?: MouseEvent) { 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 { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } diff --git a/packages/frontend/src/components/MkPostFormAttaches.vue b/packages/frontend/src/components/MkPostFormAttaches.vue index 95eb367318..8854babb6b 100644 --- a/packages/frontend/src/components/MkPostFormAttaches.vue +++ b/packages/frontend/src/components/MkPostFormAttaches.vue @@ -108,7 +108,7 @@ async function rename(file) { async function describe(file) { if (mock) return; - os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), { default: file.comment !== null ? file.comment : '', file: file, }, { @@ -121,7 +121,8 @@ async function describe(file) { file.comment = comment; }); }, - }, 'closed'); + closed: () => dispose(), + }); } async function crop(file: Misskey.entities.DriveFile): Promise { diff --git a/packages/frontend/src/components/MkRange.vue b/packages/frontend/src/components/MkRange.vue index 15f8128e98..1eae642937 100644 --- a/packages/frontend/src/components/MkRange.vue +++ b/packages/frontend/src/components/MkRange.vue @@ -101,17 +101,19 @@ const steps = computed(() => { } }); -const onMousedown = (ev: MouseEvent | TouchEvent) => { +function onMousedown(ev: MouseEvent | TouchEvent) { ev.preventDefault(); const tooltipShowing = ref(true); - os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), { showing: tooltipShowing, text: computed(() => { return props.textConverter(finalValue.value); }), targetElement: thumbEl, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); const style = document.createElement('style'); style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }')); @@ -152,7 +154,7 @@ const onMousedown = (ev: MouseEvent | TouchEvent) => { window.addEventListener('touchmove', onDrag); window.addEventListener('mouseup', onMouseup, { once: true }); window.addEventListener('touchend', onMouseup, { once: true }); -}; +}