diff options
| author | syuilo <4439005+syuilo@users.noreply.github.com> | 2024-07-04 13:14:49 +0900 |
|---|---|---|
| committer | syuilo <4439005+syuilo@users.noreply.github.com> | 2024-07-04 13:14:49 +0900 |
| commit | 6dd2e9fc0b1eeea6b5f04ccac93ccfab658f976d (patch) | |
| tree | 53a677d4fdaa802774a133272ed2f5f1180dd4fa /packages/frontend/src/os.ts | |
| parent | fix(storybook): build skipping even after updating impl story files (#14124) (diff) | |
| download | sharkey-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/os.ts')
| -rw-r--r-- | packages/frontend/src/os.ts | 125 |
1 files changed, 67 insertions, 58 deletions
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; }); }); } |