summaryrefslogtreecommitdiff
path: root/packages/frontend/src
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2024-07-04 13:14:49 +0900
committersyuilo <4439005+syuilo@users.noreply.github.com>2024-07-04 13:14:49 +0900
commit6dd2e9fc0b1eeea6b5f04ccac93ccfab658f976d (patch)
tree53a677d4fdaa802774a133272ed2f5f1180dd4fa /packages/frontend/src
parentfix(storybook): build skipping even after updating impl story files (#14124) (diff)
downloadsharkey-6dd2e9fc0b1eeea6b5f04ccac93ccfab658f976d.tar.gz
sharkey-6dd2e9fc0b1eeea6b5f04ccac93ccfab658f976d.tar.bz2
sharkey-6dd2e9fc0b1eeea6b5f04ccac93ccfab658f976d.zip
refactor(frontend): refactor popup api and make sure call dispose callback
Close #14122
Diffstat (limited to 'packages/frontend/src')
-rw-r--r--packages/frontend/src/account.ts16
-rw-r--r--packages/frontend/src/boot/main-boot.ts30
-rw-r--r--packages/frontend/src/components/MkClickerGame.vue4
-rw-r--r--packages/frontend/src/components/MkDrive.folder.vue5
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.vue4
-rw-r--r--packages/frontend/src/components/MkLink.vue6
-rw-r--r--packages/frontend/src/components/MkNote.vue16
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue16
-rw-r--r--packages/frontend/src/components/MkPostForm.vue13
-rw-r--r--packages/frontend/src/components/MkPostFormAttaches.vue5
-rw-r--r--packages/frontend/src/components/MkRange.vue10
-rw-r--r--packages/frontend/src/components/MkReactionIcon.vue6
-rw-r--r--packages/frontend/src/components/MkReactionsViewer.reaction.vue14
-rw-r--r--packages/frontend/src/components/MkSignin.vue5
-rw-r--r--packages/frontend/src/components/MkSystemWebhookEditor.impl.ts6
-rw-r--r--packages/frontend/src/components/MkUrlPreview.vue8
-rw-r--r--packages/frontend/src/components/MkUserSetupDialog.vue6
-rw-r--r--packages/frontend/src/components/MkVisitorDashboard.vue12
-rw-r--r--packages/frontend/src/components/global/MkCustomEmoji.vue4
-rw-r--r--packages/frontend/src/components/global/MkUrl.vue6
-rw-r--r--packages/frontend/src/directives/ripple.ts4
-rw-r--r--packages/frontend/src/directives/tooltip.ts6
-rw-r--r--packages/frontend/src/directives/user-preview.ts5
-rw-r--r--packages/frontend/src/os.ts125
-rw-r--r--packages/frontend/src/pages/admin-user.vue12
-rw-r--r--packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue6
-rw-r--r--packages/frontend/src/pages/custom-emojis-manager.vue10
-rw-r--r--packages/frontend/src/pages/drive.file.info.vue5
-rw-r--r--packages/frontend/src/pages/drop-and-fusion.game.vue14
-rw-r--r--packages/frontend/src/pages/emojis.emoji.vue8
-rw-r--r--packages/frontend/src/pages/reset-password.vue4
-rw-r--r--packages/frontend/src/pages/settings/2fa.vue6
-rw-r--r--packages/frontend/src/pages/settings/accounts.vue10
-rw-r--r--packages/frontend/src/pages/settings/api.vue5
-rw-r--r--packages/frontend/src/pages/settings/avatar-decoration.vue5
-rw-r--r--packages/frontend/src/scripts/get-drive-file-menu.ts5
-rw-r--r--packages/frontend/src/scripts/get-note-menu.ts18
-rw-r--r--packages/frontend/src/scripts/get-user-menu.ts6
-rw-r--r--packages/frontend/src/scripts/install-plugin.ts5
-rw-r--r--packages/frontend/src/scripts/please-login.ts5
-rw-r--r--packages/frontend/src/scripts/use-chart-tooltip.ts10
-rw-r--r--packages/frontend/src/ui/_common_/common.ts4
-rw-r--r--packages/frontend/src/ui/_common_/navbar-for-mobile.vue5
-rw-r--r--packages/frontend/src/ui/_common_/navbar.vue5
-rw-r--r--packages/frontend/src/ui/classic.header.vue5
-rw-r--r--packages/frontend/src/ui/classic.sidebar.vue6
-rw-r--r--packages/frontend/src/ui/deck/notifications-column.vue5
-rw-r--r--packages/frontend/src/ui/visitor.vue12
-rw-r--r--packages/frontend/src/widgets/WidgetNotifications.vue5
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<HTMLElement | { $el: HTMLElement }>();
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(),
+ });
});
}
</script>
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<void> {
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 });
-};
+}
</script>
<style lang="scss" scoped>
diff --git a/packages/frontend/src/components/MkReactionIcon.vue b/packages/frontend/src/components/MkReactionIcon.vue
index 068a2968db..c0cbd8a65d 100644
--- a/packages/frontend/src/components/MkReactionIcon.vue
+++ b/packages/frontend/src/components/MkReactionIcon.vue
@@ -24,11 +24,13 @@ const elRef = shallowRef();
if (props.withTooltip) {
useTooltip(elRef, (showing) => {
- os.popup(defineAsyncComponent(() => import('@/components/MkReactionTooltip.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkReactionTooltip.vue')), {
showing,
reaction: props.reaction.replace(/^:(\w+):$/, ':$1@.:'),
targetElement: elRef.value.$el,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
});
}
</script>
diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
index c41811febe..26223364ab 100644
--- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
@@ -114,10 +114,12 @@ async function menu(ev) {
text: i18n.ts.info,
icon: 'ti ti-info-circle',
action: async () => {
- os.popup(MkCustomEmojiDetailedDialog, {
+ const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
emoji: await misskeyApiGet('emoji', {
name: props.reaction.replace(/:/g, '').replace(/@\./, ''),
}),
+ }, {
+ closed: () => dispose(),
});
},
}], ev.currentTarget ?? ev.target);
@@ -129,7 +131,9 @@ function anime() {
const rect = buttonEl.value.getBoundingClientRect();
const x = rect.left + 16;
const y = rect.top + (buttonEl.value.offsetHeight / 2);
- os.popup(MkReactionEffect, { reaction: props.reaction, x, y }, {}, 'end');
+ const { dispose } = os.popup(MkReactionEffect, { reaction: props.reaction, x, y }, {
+ end: () => dispose(),
+ });
}
watch(() => props.count, (newCount, oldCount) => {
@@ -151,13 +155,15 @@ if (!mock) {
const users = reactions.map(x => x.user);
- os.popup(XDetails, {
+ const { dispose } = os.popup(XDetails, {
showing,
reaction: props.reaction,
users,
count: props.count,
targetElement: buttonEl.value,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}, 100);
}
</script>
diff --git a/packages/frontend/src/components/MkSignin.vue b/packages/frontend/src/components/MkSignin.vue
index 970aff825d..db32cdd6a1 100644
--- a/packages/frontend/src/components/MkSignin.vue
+++ b/packages/frontend/src/components/MkSignin.vue
@@ -218,8 +218,9 @@ function loginFailed(err: any): void {
}
function resetPassword(): void {
- os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
- }, 'closed');
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
+ closed: () => dispose(),
+ });
}
</script>
diff --git a/packages/frontend/src/components/MkSystemWebhookEditor.impl.ts b/packages/frontend/src/components/MkSystemWebhookEditor.impl.ts
index 1222d3261d..76f54e8d37 100644
--- a/packages/frontend/src/components/MkSystemWebhookEditor.impl.ts
+++ b/packages/frontend/src/components/MkSystemWebhookEditor.impl.ts
@@ -25,15 +25,15 @@ export type MkSystemWebhookResult = {
export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise<MkSystemWebhookResult | null> {
const { dispose, result } = await new Promise<{ dispose: () => void, result: MkSystemWebhookResult | null }>(async resolve => {
- const res = await os.popup(
+ const { dispose: _dispose } = os.popup(
defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')),
props,
{
submitted: (ev: MkSystemWebhookResult) => {
- resolve({ dispose: res.dispose, result: ev });
+ resolve({ dispose: _dispose, result: ev });
},
closed: () => {
- resolve({ dispose: res.dispose, result: null });
+ resolve({ dispose: _dispose, result: null });
},
},
);
diff --git a/packages/frontend/src/components/MkUrlPreview.vue b/packages/frontend/src/components/MkUrlPreview.vue
index 6954f1f6ff..8df5e0fe40 100644
--- a/packages/frontend/src/components/MkUrlPreview.vue
+++ b/packages/frontend/src/components/MkUrlPreview.vue
@@ -188,11 +188,13 @@ function adjustTweetHeight(message: any) {
if (height) tweetHeight.value = height;
}
-const openPlayer = (): void => {
- os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
+function openPlayer(): void {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
url: requestUrl.href,
+ }, {
+ // TODO
});
-};
+}
(window as any).addEventListener('message', adjustTweetHeight);
diff --git a/packages/frontend/src/components/MkUserSetupDialog.vue b/packages/frontend/src/components/MkUserSetupDialog.vue
index cab0067813..514350c930 100644
--- a/packages/frontend/src/components/MkUserSetupDialog.vue
+++ b/packages/frontend/src/components/MkUserSetupDialog.vue
@@ -176,9 +176,11 @@ function setupComplete() {
function launchTutorial() {
setupComplete();
nextTick(() => {
- os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
initialPage: 1,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
});
}
diff --git a/packages/frontend/src/components/MkVisitorDashboard.vue b/packages/frontend/src/components/MkVisitorDashboard.vue
index f7963f9938..4d81bd0283 100644
--- a/packages/frontend/src/components/MkVisitorDashboard.vue
+++ b/packages/frontend/src/components/MkVisitorDashboard.vue
@@ -74,15 +74,19 @@ misskeyApi('stats', {}).then((res) => {
});
function signin() {
- os.popup(XSigninDialog, {
+ const { dispose } = os.popup(XSigninDialog, {
autoSet: true,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
function signup() {
- os.popup(XSignupDialog, {
+ const { dispose } = os.popup(XSignupDialog, {
autoSet: true,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
function showMenu(ev) {
diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue
index 6123835340..4581908a8a 100644
--- a/packages/frontend/src/components/global/MkCustomEmoji.vue
+++ b/packages/frontend/src/components/global/MkCustomEmoji.vue
@@ -106,12 +106,12 @@ function onClick(ev: MouseEvent) {
text: i18n.ts.info,
icon: 'ti ti-info-circle',
action: async () => {
- os.popup(MkCustomEmojiDetailedDialog, {
+ const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
emoji: await misskeyApiGet('emoji', {
name: customEmojiName.value,
}),
}, {
- anchor: ev.target,
+ closed: () => dispose(),
});
},
}], ev.currentTarget ?? ev.target);
diff --git a/packages/frontend/src/components/global/MkUrl.vue b/packages/frontend/src/components/global/MkUrl.vue
index 9d4cd559d9..d2ddd4aa85 100644
--- a/packages/frontend/src/components/global/MkUrl.vue
+++ b/packages/frontend/src/components/global/MkUrl.vue
@@ -50,11 +50,13 @@ const el = ref();
if (props.showUrlPreview && 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/directives/ripple.ts b/packages/frontend/src/directives/ripple.ts
index 2d724f771e..a043ff212d 100644
--- a/packages/frontend/src/directives/ripple.ts
+++ b/packages/frontend/src/directives/ripple.ts
@@ -17,7 +17,9 @@ export default {
const x = rect.left + (el.offsetWidth / 2);
const y = rect.top + (el.offsetHeight / 2);
- popup(MkRippleEffect, { x, y }, {}, 'end');
+ const { dispose } = popup(MkRippleEffect, { x, y }, {
+ end: () => dispose(),
+ });
});
},
};
diff --git a/packages/frontend/src/directives/tooltip.ts b/packages/frontend/src/directives/tooltip.ts
index b1c1b19907..251ce5675f 100644
--- a/packages/frontend/src/directives/tooltip.ts
+++ b/packages/frontend/src/directives/tooltip.ts
@@ -51,13 +51,15 @@ export default {
if (self.text == null) return;
const showing = ref(true);
- popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
+ const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
showing,
text: self.text,
asMfm: binding.modifiers.mfm,
direction: binding.modifiers.left ? 'left' : binding.modifiers.right ? 'right' : binding.modifiers.top ? 'top' : binding.modifiers.bottom ? 'bottom' : 'top',
targetElement: el,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
self._close = () => {
showing.value = false;
diff --git a/packages/frontend/src/directives/user-preview.ts b/packages/frontend/src/directives/user-preview.ts
index 7a008a4486..278d842d09 100644
--- a/packages/frontend/src/directives/user-preview.ts
+++ b/packages/frontend/src/directives/user-preview.ts
@@ -35,7 +35,7 @@ export class UserPreview {
const showing = ref(true);
- popup(defineAsyncComponent(() => import('@/components/MkUserPopup.vue')), {
+ const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserPopup.vue')), {
showing,
q: this.user,
source: this.el,
@@ -47,7 +47,8 @@ export class UserPreview {
window.clearTimeout(this.showTimer);
this.hideTimer = window.setTimeout(this.close, 500);
},
- }, 'closed');
+ closed: () => dispose(),
+ });
this.promise = {
cancel: () => {
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index f656a52371..560f692acf 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -116,11 +116,13 @@ export function promiseDialog<T extends Promise<any>>(
});
// NOTE: dynamic importすると挙動がおかしくなる(showingの変更が伝播しない)
- popup(MkWaitingDialog, {
+ const { dispose } = popup(MkWaitingDialog, {
success: success,
showing: showing,
text: text,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
return promise;
}
@@ -166,28 +168,24 @@ type EmitsExtractor<T> = {
[K in keyof T as K extends `onVnode${string}` ? never : K extends `on${infer E}` ? Uncapitalize<E> : K extends string ? never : K]: T[K];
};
-export async function popup<T extends Component>(
+export function popup<T extends Component>(
component: T,
props: ComponentProps<T>,
events: ComponentEmit<T> = {} as ComponentEmit<T>,
- disposeEvent?: keyof ComponentEmit<T>,
-): Promise<{ dispose: () => void }> {
+): { dispose: () => void } {
markRaw(component);
const id = ++popupIdCount;
const dispose = () => {
// このsetTimeoutが無いと挙動がおかしくなる(autocompleteが閉じなくなる)。Vueのバグ?
window.setTimeout(() => {
- popups.value = popups.value.filter(popup => popup.id !== id);
+ popups.value = popups.value.filter(p => p.id !== id);
}, 0);
};
const state = {
component,
props,
- events: disposeEvent ? {
- ...events,
- [disposeEvent]: dispose,
- } : events,
+ events,
id,
};
@@ -199,15 +197,19 @@ export async function popup<T extends Component>(
}
export function pageWindow(path: string) {
- popup(MkPageWindow, {
+ const { dispose } = popup(MkPageWindow, {
initialPath: path,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
export function toast(message: string) {
- popup(MkToast, {
+ const { dispose } = popup(MkToast, {
message,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
export function alert(props: {
@@ -216,11 +218,12 @@ export function alert(props: {
text?: string;
}): Promise<void> {
return new Promise(resolve => {
- popup(MkDialog, props, {
+ const { dispose } = popup(MkDialog, props, {
done: () => {
resolve();
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
@@ -232,14 +235,15 @@ export function confirm(props: {
cancelText?: string;
}): Promise<{ canceled: boolean }> {
return new Promise(resolve => {
- popup(MkDialog, {
+ const { dispose } = popup(MkDialog, {
...props,
showCancelButton: true,
}, {
done: result => {
resolve(result ? result : { canceled: true });
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
@@ -261,7 +265,7 @@ export function actions<T extends {
canceled: false; result: T[number]['value'];
}> {
return new Promise(resolve => {
- popup(MkDialog, {
+ const { dispose } = popup(MkDialog, {
...props,
actions: props.actions.map(a => ({
text: a.text,
@@ -275,7 +279,8 @@ export function actions<T extends {
done: result => {
resolve(result ? result : { canceled: true });
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
@@ -323,7 +328,7 @@ export function inputText(props: {
canceled: false; result: string | null;
}> {
return new Promise(resolve => {
- popup(MkDialog, {
+ const { dispose } = popup(MkDialog, {
title: props.title,
text: props.text,
input: {
@@ -338,7 +343,8 @@ export function inputText(props: {
done: result => {
resolve(result ? result : { canceled: true });
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
@@ -377,7 +383,7 @@ export function inputNumber(props: {
canceled: false; result: number | null;
}> {
return new Promise(resolve => {
- popup(MkDialog, {
+ const { dispose } = popup(MkDialog, {
title: props.title,
text: props.text,
input: {
@@ -390,7 +396,8 @@ export function inputNumber(props: {
done: result => {
resolve(result ? result : { canceled: true });
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
@@ -405,7 +412,7 @@ export function inputDate(props: {
canceled: false; result: Date;
}> {
return new Promise(resolve => {
- popup(MkDialog, {
+ const { dispose } = popup(MkDialog, {
title: props.title,
text: props.text,
input: {
@@ -417,7 +424,8 @@ export function inputDate(props: {
done: result => {
resolve(result ? { result: new Date(result.result), canceled: false } : { result: undefined, canceled: true });
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
@@ -427,11 +435,12 @@ export function authenticateDialog(): Promise<{
canceled: false; result: { password: string; token: string | null; };
}> {
return new Promise(resolve => {
- popup(MkPasswordDialog, {}, {
+ const { dispose } = popup(MkPasswordDialog, {}, {
done: result => {
resolve(result ? { canceled: false, result } : { canceled: true, result: undefined });
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
@@ -476,7 +485,7 @@ export function select<C = any>(props: {
canceled: false; result: C | null;
}> {
return new Promise(resolve => {
- popup(MkDialog, {
+ const { dispose } = popup(MkDialog, {
title: props.title,
text: props.text,
select: {
@@ -487,7 +496,8 @@ export function select<C = any>(props: {
done: result => {
resolve(result ? result : { canceled: true });
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
@@ -497,53 +507,57 @@ export function success(): Promise<void> {
window.setTimeout(() => {
showing.value = false;
}, 1000);
- popup(MkWaitingDialog, {
+ const { dispose } = popup(MkWaitingDialog, {
success: true,
showing: showing,
}, {
done: () => resolve(),
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
export function waiting(): Promise<void> {
return new Promise(resolve => {
const showing = ref(true);
- popup(MkWaitingDialog, {
+ const { dispose } = popup(MkWaitingDialog, {
success: false,
showing: showing,
}, {
done: () => resolve(),
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
export function form<F extends Form>(title: string, f: F): Promise<{ canceled: true, result?: undefined } | { canceled?: false, result: GetFormResultType<F> }> {
return new Promise(resolve => {
- popup(defineAsyncComponent(() => import('@/components/MkFormDialog.vue')), { title, form: f }, {
+ const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkFormDialog.vue')), { title, form: f }, {
done: result => {
resolve(result);
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
export async function selectUser(opts: { includeSelf?: boolean; localOnly?: boolean; } = {}): Promise<Misskey.entities.UserDetailed> {
return new Promise(resolve => {
- popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), {
+ const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), {
includeSelf: opts.includeSelf,
localOnly: opts.localOnly,
}, {
ok: user => {
resolve(user);
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
export async function selectDriveFile(multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
return new Promise(resolve => {
- popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
+ const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
type: 'file',
multiple,
}, {
@@ -552,13 +566,14 @@ export async function selectDriveFile(multiple: boolean): Promise<Misskey.entiti
resolve(files);
}
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
export async function selectDriveFolder(multiple: boolean): Promise<Misskey.entities.DriveFolder[]> {
return new Promise(resolve => {
- popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
+ const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
type: 'folder',
multiple,
}, {
@@ -567,20 +582,22 @@ export async function selectDriveFolder(multiple: boolean): Promise<Misskey.enti
resolve(folders);
}
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog>): Promise<string> {
return new Promise(resolve => {
- popup(MkEmojiPickerDialog, {
+ const { dispose } = popup(MkEmojiPickerDialog, {
src,
...opts,
}, {
done: emoji => {
resolve(emoji);
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
@@ -589,7 +606,7 @@ export async function cropImage(image: Misskey.entities.DriveFile, options: {
uploadFolder?: string | null;
}): Promise<Misskey.entities.DriveFile> {
return new Promise(resolve => {
- popup(defineAsyncComponent(() => import('@/components/MkCropperDialog.vue')), {
+ const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkCropperDialog.vue')), {
file: image,
aspectRatio: options.aspectRatio,
uploadFolder: options.uploadFolder,
@@ -597,7 +614,8 @@ export async function cropImage(image: Misskey.entities.DriveFile, options: {
ok: x => {
resolve(x);
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
}
@@ -608,8 +626,7 @@ export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | n
onClosing?: () => void;
}): Promise<void> {
return new Promise(resolve => {
- let dispose;
- popup(MkPopupMenu, {
+ const { dispose } = popup(MkPopupMenu, {
items,
src,
width: options?.width,
@@ -623,8 +640,6 @@ export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | n
closing: () => {
if (options?.onClosing) options.onClosing();
},
- }).then(res => {
- dispose = res.dispose;
});
});
}
@@ -632,8 +647,7 @@ export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | n
export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
ev.preventDefault();
return new Promise(resolve => {
- let dispose;
- popup(MkContextMenu, {
+ const { dispose } = popup(MkContextMenu, {
items,
ev,
}, {
@@ -641,8 +655,6 @@ export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
resolve();
dispose();
},
- }).then(res => {
- dispose = res.dispose;
});
});
}
@@ -656,14 +668,11 @@ export function post(props: Record<string, any> = {}): Promise<void> {
// Vueが渡されたコンポーネントに内部的に__propsというプロパティを生やす影響で、
// 複数のpost formを開いたときに場合によってはエラーになる
// もちろん複数のpost formを開けること自体Misskeyサイドのバグなのだが
- let dispose;
- popup(MkPostFormDialog, props, {
+ const { dispose } = popup(MkPostFormDialog, props, {
closed: () => {
resolve();
dispose();
},
- }).then(res => {
- dispose = res.dispose;
});
});
}
diff --git a/packages/frontend/src/pages/admin-user.vue b/packages/frontend/src/pages/admin-user.vue
index f57aa51b5b..1459997dcb 100644
--- a/packages/frontend/src/pages/admin-user.vue
+++ b/packages/frontend/src/pages/admin-user.vue
@@ -464,16 +464,20 @@ function toggleRoleItem(role) {
}
function createAnnouncement() {
- os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
user: user.value,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
function editAnnouncement(announcement) {
- os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
user: user.value,
announcement,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
watch(() => props.userId, () => {
diff --git a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue
index a52f8eb7af..93800873f9 100644
--- a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue
+++ b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue
@@ -109,7 +109,7 @@ async function onDeleteButtonClicked(id: string) {
async function showEditor(mode: 'create' | 'edit', id?: string) {
const { dispose, needLoad } = await new Promise<{ dispose: () => void, needLoad: boolean }>(async resolve => {
- const res = await os.popup(
+ const { dispose: _dispose } = os.popup(
defineAsyncComponent(() => import('./notification-recipient.editor.vue')),
{
mode,
@@ -117,10 +117,10 @@ async function showEditor(mode: 'create' | 'edit', id?: string) {
},
{
submitted: async () => {
- resolve({ dispose: res.dispose, needLoad: true });
+ resolve({ dispose: _dispose, needLoad: true });
},
closed: () => {
- resolve({ dispose: res.dispose, needLoad: false });
+ resolve({ dispose: _dispose, needLoad: false });
},
},
);
diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue
index 3e2332e408..eea3f68130 100644
--- a/packages/frontend/src/pages/custom-emojis-manager.vue
+++ b/packages/frontend/src/pages/custom-emojis-manager.vue
@@ -129,18 +129,19 @@ const toggleSelect = (emoji) => {
};
const add = async (ev: MouseEvent) => {
- os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
}, {
done: result => {
if (result.created) {
emojisPaginationComponent.value.prepend(result.created);
}
},
- }, 'closed');
+ closed: () => dispose(),
+ });
};
const edit = (emoji) => {
- os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
emoji: emoji,
}, {
done: result => {
@@ -153,7 +154,8 @@ const edit = (emoji) => {
emojisPaginationComponent.value.removeItem(emoji.id);
}
},
- }, 'closed');
+ closed: () => dispose(),
+ });
};
const importEmoji = (emoji) => {
diff --git a/packages/frontend/src/pages/drive.file.info.vue b/packages/frontend/src/pages/drive.file.info.vue
index 8077edff5f..7a8786d415 100644
--- a/packages/frontend/src/pages/drive.file.info.vue
+++ b/packages/frontend/src/pages/drive.file.info.vue
@@ -160,7 +160,7 @@ function rename() {
function describe() {
if (!file.value) return;
- os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
default: file.value.comment ?? '',
file: file.value,
}, {
@@ -172,7 +172,8 @@ function describe() {
await fetch();
});
},
- }, 'closed');
+ closed: () => dispose(),
+ });
}
async function deleteFile() {
diff --git a/packages/frontend/src/pages/drop-and-fusion.game.vue b/packages/frontend/src/pages/drop-and-fusion.game.vue
index eba5b92154..10bcfa6d4e 100644
--- a/packages/frontend/src/pages/drop-and-fusion.game.vue
+++ b/packages/frontend/src/pages/drop-and-fusion.game.vue
@@ -1008,8 +1008,18 @@ function attachGameEvents() {
const domX = rect.left + (x * viewScale);
const domY = rect.top + (y * viewScale);
const scoreUnit = getScoreUnit(props.gameMode);
- os.popup(MkRippleEffect, { x: domX, y: domY }, {}, 'end');
- os.popup(MkPlusOneEffect, { x: domX, y: domY, value: scoreDelta + (scoreUnit === 'pt' ? '' : scoreUnit) }, {}, 'end');
+
+ {
+ const { dispose } = os.popup(MkRippleEffect, { x: domX, y: domY }, {
+ end: () => dispose(),
+ });
+ }
+
+ {
+ const { dispose } = os.popup(MkPlusOneEffect, { x: domX, y: domY, value: scoreDelta + (scoreUnit === 'pt' ? '' : scoreUnit) }, {
+ end: () => dispose(),
+ });
+ }
if (nextMono) {
const def = monoDefinitions.value.find(x => x.id === nextMono.id)!;
diff --git a/packages/frontend/src/pages/emojis.emoji.vue b/packages/frontend/src/pages/emojis.emoji.vue
index 5301a08521..ae3a2c31e3 100644
--- a/packages/frontend/src/pages/emojis.emoji.vue
+++ b/packages/frontend/src/pages/emojis.emoji.vue
@@ -14,8 +14,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
-import * as os from '@/os.js';
import * as Misskey from 'misskey-js';
+import * as os from '@/os.js';
import { misskeyApiGet } from '@/scripts/misskey-api.js';
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
import { i18n } from '@/i18n.js';
@@ -40,12 +40,12 @@ function menu(ev) {
text: i18n.ts.info,
icon: 'ti ti-info-circle',
action: async () => {
- os.popup(MkCustomEmojiDetailedDialog, {
+ const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
emoji: await misskeyApiGet('emoji', {
name: props.emoji.name,
- })
+ }),
}, {
- anchor: ev.target,
+ closed: () => dispose(),
});
},
}], ev.currentTarget ?? ev.target);
diff --git a/packages/frontend/src/pages/reset-password.vue b/packages/frontend/src/pages/reset-password.vue
index 6b67a9cc87..6d24029535 100644
--- a/packages/frontend/src/pages/reset-password.vue
+++ b/packages/frontend/src/pages/reset-password.vue
@@ -44,7 +44,9 @@ async function save() {
onMounted(() => {
if (props.token == null) {
- os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {}, 'closed');
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
+ closed: () => dispose(),
+ });
mainRouter.push('/');
}
});
diff --git a/packages/frontend/src/pages/settings/2fa.vue b/packages/frontend/src/pages/settings/2fa.vue
index b7d648c1a4..6a9a1e16e2 100644
--- a/packages/frontend/src/pages/settings/2fa.vue
+++ b/packages/frontend/src/pages/settings/2fa.vue
@@ -108,9 +108,11 @@ async function registerTOTP(): Promise<void> {
token: auth.result.token,
});
- os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), {
twoFactorData,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
async function unregisterTOTP(): Promise<void> {
diff --git a/packages/frontend/src/pages/settings/accounts.vue b/packages/frontend/src/pages/settings/accounts.vue
index 1182346de9..08c9261dcf 100644
--- a/packages/frontend/src/pages/settings/accounts.vue
+++ b/packages/frontend/src/pages/settings/accounts.vue
@@ -74,22 +74,24 @@ async function removeAccount(account) {
}
function addExistingAccount() {
- os.popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
done: async res => {
await addAccounts(res.id, res.i);
os.success();
init();
},
- }, 'closed');
+ closed: () => dispose(),
+ });
}
function createAccount() {
- os.popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
done: async res => {
await addAccounts(res.id, res.i);
switchAccountWithToken(res.i);
},
- }, 'closed');
+ closed: () => dispose(),
+ });
}
async function switchAccount(account: any) {
diff --git a/packages/frontend/src/pages/settings/api.vue b/packages/frontend/src/pages/settings/api.vue
index d9596b4e45..b35d406a98 100644
--- a/packages/frontend/src/pages/settings/api.vue
+++ b/packages/frontend/src/pages/settings/api.vue
@@ -23,7 +23,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
const isDesktop = ref(window.innerWidth >= 1100);
function generateToken() {
- os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
done: async result => {
const { name, permissions } = result;
const { token } = await misskeyApi('miauth/gen-token', {
@@ -38,7 +38,8 @@ function generateToken() {
text: token,
});
},
- }, 'closed');
+ closed: () => dispose(),
+ });
}
const headerActions = computed(() => []);
diff --git a/packages/frontend/src/pages/settings/avatar-decoration.vue b/packages/frontend/src/pages/settings/avatar-decoration.vue
index 3cc911c014..77229d3349 100644
--- a/packages/frontend/src/pages/settings/avatar-decoration.vue
+++ b/packages/frontend/src/pages/settings/avatar-decoration.vue
@@ -67,7 +67,7 @@ misskeyApi('get-avatar-decorations').then(_avatarDecorations => {
});
function openDecoration(avatarDecoration, index?: number) {
- os.popup(defineAsyncComponent(() => import('./avatar-decoration.dialog.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('./avatar-decoration.dialog.vue')), {
decoration: avatarDecoration,
usingIndex: index,
}, {
@@ -108,7 +108,8 @@ function openDecoration(avatarDecoration, index?: number) {
});
$i.avatarDecorations = update;
},
- }, 'closed');
+ closed: () => dispose(),
+ });
}
function detachAllDecorations() {
diff --git a/packages/frontend/src/scripts/get-drive-file-menu.ts b/packages/frontend/src/scripts/get-drive-file-menu.ts
index 7aca5f83b2..14c83ed637 100644
--- a/packages/frontend/src/scripts/get-drive-file-menu.ts
+++ b/packages/frontend/src/scripts/get-drive-file-menu.ts
@@ -27,7 +27,7 @@ function rename(file: Misskey.entities.DriveFile) {
}
function describe(file: Misskey.entities.DriveFile) {
- os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
default: file.comment ?? '',
file: file,
}, {
@@ -37,7 +37,8 @@ function describe(file: Misskey.entities.DriveFile) {
comment: caption.length === 0 ? null : caption,
});
},
- }, 'closed');
+ closed: () => dispose(),
+ });
}
function toggleSensitive(file: Misskey.entities.DriveFile) {
diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts
index 71ad299f50..418b6abc88 100644
--- a/packages/frontend/src/scripts/get-note-menu.ts
+++ b/packages/frontend/src/scripts/get-note-menu.ts
@@ -136,10 +136,12 @@ export function getAbuseNoteMenu(note: Misskey.entities.Note, text: string): Men
let noteInfo = '';
if (note.url ?? note.uri != null) noteInfo = `Note: ${note.url ?? note.uri}\n`;
noteInfo += `Local Note: ${localUrl}\n`;
- os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
user: note.user,
initialComment: `${noteInfo}-----\n`,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
},
};
}
@@ -530,7 +532,9 @@ export function getRenoteMenu(props: {
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(),
+ });
}
if (!props.mock) {
@@ -566,7 +570,9 @@ export function getRenoteMenu(props: {
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 configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
@@ -615,7 +621,9 @@ export function getRenoteMenu(props: {
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(),
+ });
}
if (!props.mock) {
diff --git a/packages/frontend/src/scripts/get-user-menu.ts b/packages/frontend/src/scripts/get-user-menu.ts
index 3e031d232f..ac8774fad0 100644
--- a/packages/frontend/src/scripts/get-user-menu.ts
+++ b/packages/frontend/src/scripts/get-user-menu.ts
@@ -100,9 +100,11 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
}
function reportAbuse() {
- os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
user: user,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
async function getConfirmed(text: string): Promise<boolean> {
diff --git a/packages/frontend/src/scripts/install-plugin.ts b/packages/frontend/src/scripts/install-plugin.ts
index d0a8675b19..37f473b6de 100644
--- a/packages/frontend/src/scripts/install-plugin.ts
+++ b/packages/frontend/src/scripts/install-plugin.ts
@@ -103,7 +103,7 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) {
}
const token = realMeta.permissions == null || realMeta.permissions.length === 0 ? null : await new Promise((res, rej) => {
- os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {
title: i18n.ts.tokenRequested,
information: i18n.ts.pluginTokenRequestedDescription,
initialName: realMeta.name,
@@ -118,7 +118,8 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) {
});
res(token);
},
- }, 'closed');
+ closed: () => dispose(),
+ });
});
savePlugin({
diff --git a/packages/frontend/src/scripts/please-login.ts b/packages/frontend/src/scripts/please-login.ts
index 9e51272791..363da5f633 100644
--- a/packages/frontend/src/scripts/please-login.ts
+++ b/packages/frontend/src/scripts/please-login.ts
@@ -11,7 +11,7 @@ import { popup } from '@/os.js';
export function pleaseLogin(path?: string) {
if ($i) return;
- popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
+ const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
autoSet: true,
message: i18n.ts.signinRequired,
}, {
@@ -20,7 +20,8 @@ export function pleaseLogin(path?: string) {
window.location.href = path;
}
},
- }, 'closed');
+ closed: () => dispose(),
+ });
throw new Error('signin required');
}
diff --git a/packages/frontend/src/scripts/use-chart-tooltip.ts b/packages/frontend/src/scripts/use-chart-tooltip.ts
index bed221a622..bba64fc6ee 100644
--- a/packages/frontend/src/scripts/use-chart-tooltip.ts
+++ b/packages/frontend/src/scripts/use-chart-tooltip.ts
@@ -17,20 +17,16 @@ export function useChartTooltip(opts: { position: 'top' | 'middle' } = { positio
borderColor: string;
text: string;
}[] | null>(null);
- let disposeTooltipComponent;
-
- os.popup(MkChartTooltip, {
+ const { dispose: disposeTooltipComponent } = os.popup(MkChartTooltip, {
showing: tooltipShowing,
x: tooltipX,
y: tooltipY,
title: tooltipTitle,
series: tooltipSeries,
- }, {}).then(({ dispose }) => {
- disposeTooltipComponent = dispose;
- });
+ }, {});
onUnmounted(() => {
- if (disposeTooltipComponent) disposeTooltipComponent();
+ disposeTooltipComponent();
});
onDeactivated(() => {
diff --git a/packages/frontend/src/ui/_common_/common.ts b/packages/frontend/src/ui/_common_/common.ts
index 839fa5faf8..20a280f681 100644
--- a/packages/frontend/src/ui/_common_/common.ts
+++ b/packages/frontend/src/ui/_common_/common.ts
@@ -112,7 +112,9 @@ export function openInstanceMenu(ev: MouseEvent) {
text: i18n.ts._initialTutorial.launchTutorial,
icon: 'ti ti-presentation',
action: () => {
- os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {}, {}, 'closed');
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {}, {
+ closed: () => dispose(),
+ });
},
} : undefined, {
type: 'link',
diff --git a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue
index 5d0e065f09..699aa1e1c8 100644
--- a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue
+++ b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue
@@ -74,8 +74,9 @@ function openAccountMenu(ev: MouseEvent) {
}
function more() {
- os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {}, {
- }, 'closed');
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {}, {
+ closed: () => dispose(),
+ });
}
</script>
diff --git a/packages/frontend/src/ui/_common_/navbar.vue b/packages/frontend/src/ui/_common_/navbar.vue
index fa1f0eb8c7..b029533f28 100644
--- a/packages/frontend/src/ui/_common_/navbar.vue
+++ b/packages/frontend/src/ui/_common_/navbar.vue
@@ -99,10 +99,11 @@ function openAccountMenu(ev: MouseEvent) {
}
function more(ev: MouseEvent) {
- os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
src: ev.currentTarget ?? ev.target,
}, {
- }, 'closed');
+ closed: () => dispose(),
+ });
}
</script>
diff --git a/packages/frontend/src/ui/classic.header.vue b/packages/frontend/src/ui/classic.header.vue
index ee5176b558..c03afd6cd6 100644
--- a/packages/frontend/src/ui/classic.header.vue
+++ b/packages/frontend/src/ui/classic.header.vue
@@ -71,11 +71,12 @@ const otherNavItemIndicated = computed<boolean>(() => {
});
function more(ev: MouseEvent) {
- os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
src: ev.currentTarget ?? ev.target,
anchor: { x: 'center', y: 'bottom' },
}, {
- }, 'closed');
+ closed: () => dispose(),
+ });
}
function openAccountMenu(ev: MouseEvent) {
diff --git a/packages/frontend/src/ui/classic.sidebar.vue b/packages/frontend/src/ui/classic.sidebar.vue
index 19672ef87f..d8574a915f 100644
--- a/packages/frontend/src/ui/classic.sidebar.vue
+++ b/packages/frontend/src/ui/classic.sidebar.vue
@@ -86,9 +86,11 @@ function calcViewState() {
}
function more(ev: MouseEvent) {
- os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
src: ev.currentTarget ?? ev.target,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
function openAccountMenu(ev: MouseEvent) {
diff --git a/packages/frontend/src/ui/deck/notifications-column.vue b/packages/frontend/src/ui/deck/notifications-column.vue
index 451cc58791..23b0fd4f7b 100644
--- a/packages/frontend/src/ui/deck/notifications-column.vue
+++ b/packages/frontend/src/ui/deck/notifications-column.vue
@@ -27,7 +27,7 @@ const props = defineProps<{
const notificationsComponent = shallowRef<InstanceType<typeof XNotifications>>();
function func() {
- os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
excludeTypes: props.column.excludeTypes,
}, {
done: async (res) => {
@@ -36,7 +36,8 @@ function func() {
excludeTypes: excludeTypes,
});
},
- }, 'closed');
+ closed: () => dispose(),
+ });
}
const menu = [{
diff --git a/packages/frontend/src/ui/visitor.vue b/packages/frontend/src/ui/visitor.vue
index 80623083cf..c229946bd4 100644
--- a/packages/frontend/src/ui/visitor.vue
+++ b/packages/frontend/src/ui/visitor.vue
@@ -126,15 +126,19 @@ const keymap = computed(() => {
});
function signin() {
- os.popup(XSigninDialog, {
+ const { dispose } = os.popup(XSigninDialog, {
autoSet: true,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
function signup() {
- os.popup(XSignupDialog, {
+ const { dispose } = os.popup(XSignupDialog, {
autoSet: true,
- }, {}, 'closed');
+ }, {
+ closed: () => dispose(),
+ });
}
onMounted(() => {
diff --git a/packages/frontend/src/widgets/WidgetNotifications.vue b/packages/frontend/src/widgets/WidgetNotifications.vue
index 4b3265dab7..773c078b49 100644
--- a/packages/frontend/src/widgets/WidgetNotifications.vue
+++ b/packages/frontend/src/widgets/WidgetNotifications.vue
@@ -54,7 +54,7 @@ const { widgetProps, configure, save } = useWidgetPropsManager(name,
);
const configureNotification = () => {
- os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
excludeTypes: widgetProps.excludeTypes,
}, {
done: async (res) => {
@@ -62,7 +62,8 @@ const configureNotification = () => {
widgetProps.excludeTypes = excludeTypes;
save();
},
- }, 'closed');
+ closed: () => dispose(),
+ });
};
defineExpose<WidgetComponentExpose>({