mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-04 07:24:13 +00:00 
			
		
		
		
	refactor(frontend): refactor popup api and make sure call dispose callback
Close #14122
This commit is contained in:
		
							parent
							
								
									fab7d5e484
								
							
						
					
					
						commit
						6dd2e9fc0b
					
				
					 49 changed files with 317 additions and 196 deletions
				
			
		| 
						 | 
					@ -184,10 +184,12 @@ export async function refreshAccount() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function login(token: Account['token'], redirect?: string) {
 | 
					export async function login(token: Account['token'], redirect?: string) {
 | 
				
			||||||
	const showing = ref(true);
 | 
						const showing = ref(true);
 | 
				
			||||||
	popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), {
 | 
						const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), {
 | 
				
			||||||
		success: false,
 | 
							success: false,
 | 
				
			||||||
		showing: showing,
 | 
							showing: showing,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
	if (_DEV_) console.log('logging as token ', token);
 | 
						if (_DEV_) console.log('logging as token ', token);
 | 
				
			||||||
	const me = await fetchAccount(token, undefined, true)
 | 
						const me = await fetchAccount(token, undefined, true)
 | 
				
			||||||
		.catch(reason => {
 | 
							.catch(reason => {
 | 
				
			||||||
| 
						 | 
					@ -223,21 +225,23 @@ export async function openAccountMenu(opts: {
 | 
				
			||||||
	if (!$i) return;
 | 
						if (!$i) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function showSigninDialog() {
 | 
						function showSigninDialog() {
 | 
				
			||||||
		popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
 | 
							const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
 | 
				
			||||||
			done: res => {
 | 
								done: res => {
 | 
				
			||||||
				addAccount(res.id, res.i);
 | 
									addAccount(res.id, res.i);
 | 
				
			||||||
				success();
 | 
									success();
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function createAccount() {
 | 
						function createAccount() {
 | 
				
			||||||
		popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
 | 
							const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
 | 
				
			||||||
			done: res => {
 | 
								done: res => {
 | 
				
			||||||
				addAccount(res.id, res.i);
 | 
									addAccount(res.id, res.i);
 | 
				
			||||||
				switchAccountWithToken(res.i);
 | 
									switchAccountWithToken(res.i);
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	async function switchAccount(account: Misskey.entities.UserDetailed) {
 | 
						async function switchAccount(account: Misskey.entities.UserDetailed) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,9 @@ export async function mainBoot() {
 | 
				
			||||||
	emojiPicker.init();
 | 
						emojiPicker.init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (isClientUpdated && $i) {
 | 
						if (isClientUpdated && $i) {
 | 
				
			||||||
		popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, {}, 'closed');
 | 
							const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, {
 | 
				
			||||||
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const stream = useStream();
 | 
						const stream = useStream();
 | 
				
			||||||
| 
						 | 
					@ -96,7 +98,7 @@ export async function mainBoot() {
 | 
				
			||||||
					}).render();
 | 
										}).render();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}	
 | 
							}
 | 
				
			||||||
	} catch (error) {
 | 
						} catch (error) {
 | 
				
			||||||
		// console.error(error);
 | 
							// console.error(error);
 | 
				
			||||||
		console.error('Failed to initialise the seasonal screen effect canvas context:', error);
 | 
							console.error('Failed to initialise the seasonal screen effect canvas context:', error);
 | 
				
			||||||
| 
						 | 
					@ -108,22 +110,28 @@ export async function mainBoot() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		defaultStore.loaded.then(() => {
 | 
							defaultStore.loaded.then(() => {
 | 
				
			||||||
			if (defaultStore.state.accountSetupWizard !== -1) {
 | 
								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')) {
 | 
							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,
 | 
									announcement,
 | 
				
			||||||
			}, {}, 'closed');
 | 
								}, {
 | 
				
			||||||
 | 
									closed: () => dispose(),
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		stream.on('announcementCreated', (ev) => {
 | 
							stream.on('announcementCreated', (ev) => {
 | 
				
			||||||
			const announcement = ev.announcement;
 | 
								const announcement = ev.announcement;
 | 
				
			||||||
			if (announcement.display === 'dialog') {
 | 
								if (announcement.display === 'dialog') {
 | 
				
			||||||
				popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), {
 | 
									const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), {
 | 
				
			||||||
					announcement,
 | 
										announcement,
 | 
				
			||||||
				}, {}, 'closed');
 | 
									}, {
 | 
				
			||||||
 | 
										closed: () => dispose(),
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -247,13 +255,17 @@ export async function mainBoot() {
 | 
				
			||||||
		const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo');
 | 
							const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo');
 | 
				
			||||||
		if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) {
 | 
							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)))) {
 | 
								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');
 | 
							const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
 | 
				
			||||||
		if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') {
 | 
							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) {
 | 
							if ('Notification' in window) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,9 @@ const prevCookies = ref(0);
 | 
				
			||||||
function onClick(ev: MouseEvent) {
 | 
					function onClick(ev: MouseEvent) {
 | 
				
			||||||
	const x = ev.clientX;
 | 
						const x = ev.clientX;
 | 
				
			||||||
	const y = ev.clientY;
 | 
						const y = ev.clientY;
 | 
				
			||||||
	os.popup(MkPlusOneEffect, { x, y }, {}, 'end');
 | 
						const { dispose } = os.popup(MkPlusOneEffect, { x, y }, {
 | 
				
			||||||
 | 
							end: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	saveData.value!.cookies++;
 | 
						saveData.value!.cookies++;
 | 
				
			||||||
	saveData.value!.totalCookies++;
 | 
						saveData.value!.totalCookies++;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -257,10 +257,11 @@ function onContextmenu(ev: MouseEvent) {
 | 
				
			||||||
		text: i18n.ts.openInWindow,
 | 
							text: i18n.ts.openInWindow,
 | 
				
			||||||
		icon: 'ti ti-app-window',
 | 
							icon: 'ti ti-app-window',
 | 
				
			||||||
		action: () => {
 | 
							action: () => {
 | 
				
			||||||
			os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), {
 | 
								const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), {
 | 
				
			||||||
				initialFolder: props.folder,
 | 
									initialFolder: props.folder,
 | 
				
			||||||
			}, {
 | 
								}, {
 | 
				
			||||||
			}, 'closed');
 | 
									closed: () => dispose(),
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, { type: 'divider' }, {
 | 
						}, { type: 'divider' }, {
 | 
				
			||||||
		text: i18n.ts.rename,
 | 
							text: i18n.ts.rename,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -402,7 +402,9 @@ function chosen(emoji: any, ev?: MouseEvent) {
 | 
				
			||||||
		const rect = el.getBoundingClientRect();
 | 
							const rect = el.getBoundingClientRect();
 | 
				
			||||||
		const x = rect.left + (el.offsetWidth / 2);
 | 
							const x = rect.left + (el.offsetWidth / 2);
 | 
				
			||||||
		const y = rect.top + (el.offsetHeight / 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);
 | 
						const key = getKey(emoji);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,11 +37,13 @@ const el = ref<HTMLElement | { $el: HTMLElement }>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (isEnabledUrlPreview.value) {
 | 
					if (isEnabledUrlPreview.value) {
 | 
				
			||||||
	useTooltip(el, (showing) => {
 | 
						useTooltip(el, (showing) => {
 | 
				
			||||||
		os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
 | 
							const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
 | 
				
			||||||
			showing,
 | 
								showing,
 | 
				
			||||||
			url: props.url,
 | 
								url: props.url,
 | 
				
			||||||
			source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
 | 
								source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
 | 
				
			||||||
		}, {}, 'closed');
 | 
							}, {
 | 
				
			||||||
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -335,12 +335,14 @@ if (!props.mock) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (users.length < 1) return;
 | 
							if (users.length < 1) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		os.popup(MkUsersTooltip, {
 | 
							const { dispose } = os.popup(MkUsersTooltip, {
 | 
				
			||||||
			showing,
 | 
								showing,
 | 
				
			||||||
			users,
 | 
								users,
 | 
				
			||||||
			count: appearNote.value.renoteCount,
 | 
								count: appearNote.value.renoteCount,
 | 
				
			||||||
			targetElement: renoteButton.value,
 | 
								targetElement: renoteButton.value,
 | 
				
			||||||
		}, {}, 'closed');
 | 
							}, {
 | 
				
			||||||
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (appearNote.value.reactionAcceptance === 'likeOnly') {
 | 
						if (appearNote.value.reactionAcceptance === 'likeOnly') {
 | 
				
			||||||
| 
						 | 
					@ -355,13 +357,15 @@ if (!props.mock) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (users.length < 1) return;
 | 
								if (users.length < 1) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			os.popup(MkReactionsViewerDetails, {
 | 
								const { dispose } = os.popup(MkReactionsViewerDetails, {
 | 
				
			||||||
				showing,
 | 
									showing,
 | 
				
			||||||
				reaction: '❤️',
 | 
									reaction: '❤️',
 | 
				
			||||||
				users,
 | 
									users,
 | 
				
			||||||
				count: appearNote.value.reactionCount,
 | 
									count: appearNote.value.reactionCount,
 | 
				
			||||||
				targetElement: reactButton.value!,
 | 
									targetElement: reactButton.value!,
 | 
				
			||||||
			}, {}, 'closed');
 | 
								}, {
 | 
				
			||||||
 | 
									closed: () => dispose(),
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -409,7 +413,9 @@ function react(viaKeyboard = false): void {
 | 
				
			||||||
			const rect = el.getBoundingClientRect();
 | 
								const rect = el.getBoundingClientRect();
 | 
				
			||||||
			const x = rect.left + (el.offsetWidth / 2);
 | 
								const x = rect.left + (el.offsetWidth / 2);
 | 
				
			||||||
			const y = rect.top + (el.offsetHeight / 2);
 | 
								const y = rect.top + (el.offsetHeight / 2);
 | 
				
			||||||
			os.popup(MkRippleEffect, { x, y }, {}, 'end');
 | 
								const { dispose } = os.popup(MkRippleEffect, { x, y }, {
 | 
				
			||||||
 | 
									end: () => dispose(),
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		blur();
 | 
							blur();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -346,12 +346,14 @@ useTooltip(renoteButton, async (showing) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (users.length < 1) return;
 | 
						if (users.length < 1) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	os.popup(MkUsersTooltip, {
 | 
						const { dispose } = os.popup(MkUsersTooltip, {
 | 
				
			||||||
		showing,
 | 
							showing,
 | 
				
			||||||
		users,
 | 
							users,
 | 
				
			||||||
		count: appearNote.value.renoteCount,
 | 
							count: appearNote.value.renoteCount,
 | 
				
			||||||
		targetElement: renoteButton.value,
 | 
							targetElement: renoteButton.value,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (appearNote.value.reactionAcceptance === 'likeOnly') {
 | 
					if (appearNote.value.reactionAcceptance === 'likeOnly') {
 | 
				
			||||||
| 
						 | 
					@ -366,13 +368,15 @@ if (appearNote.value.reactionAcceptance === 'likeOnly') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (users.length < 1) return;
 | 
							if (users.length < 1) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		os.popup(MkReactionsViewerDetails, {
 | 
							const { dispose } = os.popup(MkReactionsViewerDetails, {
 | 
				
			||||||
			showing,
 | 
								showing,
 | 
				
			||||||
			reaction: '❤️',
 | 
								reaction: '❤️',
 | 
				
			||||||
			users,
 | 
								users,
 | 
				
			||||||
			count: appearNote.value.reactionCount,
 | 
								count: appearNote.value.reactionCount,
 | 
				
			||||||
			targetElement: reactButton.value!,
 | 
								targetElement: reactButton.value!,
 | 
				
			||||||
		}, {}, 'closed');
 | 
							}, {
 | 
				
			||||||
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -413,7 +417,9 @@ function react(viaKeyboard = false): void {
 | 
				
			||||||
			const rect = el.getBoundingClientRect();
 | 
								const rect = el.getBoundingClientRect();
 | 
				
			||||||
			const x = rect.left + (el.offsetWidth / 2);
 | 
								const x = rect.left + (el.offsetWidth / 2);
 | 
				
			||||||
			const y = rect.top + (el.offsetHeight / 2);
 | 
								const y = rect.top + (el.offsetHeight / 2);
 | 
				
			||||||
			os.popup(MkRippleEffect, { x, y }, {}, 'end');
 | 
								const { dispose } = os.popup(MkRippleEffect, { x, y }, {
 | 
				
			||||||
 | 
									end: () => dispose(),
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		blur();
 | 
							blur();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -463,7 +463,7 @@ function setVisibility() {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
 | 
				
			||||||
		currentVisibility: visibility.value,
 | 
							currentVisibility: visibility.value,
 | 
				
			||||||
		isSilenced: $i.isSilenced,
 | 
							isSilenced: $i.isSilenced,
 | 
				
			||||||
		localOnly: localOnly.value,
 | 
							localOnly: localOnly.value,
 | 
				
			||||||
| 
						 | 
					@ -476,7 +476,8 @@ function setVisibility() {
 | 
				
			||||||
				defaultStore.set('visibility', visibility.value);
 | 
									defaultStore.set('visibility', visibility.value);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function toggleLocalOnly() {
 | 
					async function toggleLocalOnly() {
 | 
				
			||||||
| 
						 | 
					@ -624,8 +625,8 @@ async function onPaste(ev: ClipboardEvent) {
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, "0");
 | 
								const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, '0');
 | 
				
			||||||
			const file = new File([paste], `${fileName}.txt`, { type: "text/plain" });
 | 
								const file = new File([paste], `${fileName}.txt`, { type: 'text/plain' });
 | 
				
			||||||
			upload(file, `${fileName}.txt`);
 | 
								upload(file, `${fileName}.txt`);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -731,7 +732,9 @@ async function post(ev?: MouseEvent) {
 | 
				
			||||||
			const rect = el.getBoundingClientRect();
 | 
								const rect = el.getBoundingClientRect();
 | 
				
			||||||
			const x = rect.left + (el.offsetWidth / 2);
 | 
								const x = rect.left + (el.offsetWidth / 2);
 | 
				
			||||||
			const y = rect.top + (el.offsetHeight / 2);
 | 
								const y = rect.top + (el.offsetHeight / 2);
 | 
				
			||||||
			os.popup(MkRippleEffect, { x, y }, {}, 'end');
 | 
								const { dispose } = os.popup(MkRippleEffect, { x, y }, {
 | 
				
			||||||
 | 
									end: () => dispose(),
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,7 +108,7 @@ async function rename(file) {
 | 
				
			||||||
async function describe(file) {
 | 
					async function describe(file) {
 | 
				
			||||||
	if (mock) return;
 | 
						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 : '',
 | 
							default: file.comment !== null ? file.comment : '',
 | 
				
			||||||
		file: file,
 | 
							file: file,
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
| 
						 | 
					@ -121,7 +121,8 @@ async function describe(file) {
 | 
				
			||||||
				file.comment = comment;
 | 
									file.comment = comment;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function crop(file: Misskey.entities.DriveFile): Promise<void> {
 | 
					async function crop(file: Misskey.entities.DriveFile): Promise<void> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,17 +101,19 @@ const steps = computed(() => {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const onMousedown = (ev: MouseEvent | TouchEvent) => {
 | 
					function onMousedown(ev: MouseEvent | TouchEvent) {
 | 
				
			||||||
	ev.preventDefault();
 | 
						ev.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const tooltipShowing = ref(true);
 | 
						const tooltipShowing = ref(true);
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
 | 
				
			||||||
		showing: tooltipShowing,
 | 
							showing: tooltipShowing,
 | 
				
			||||||
		text: computed(() => {
 | 
							text: computed(() => {
 | 
				
			||||||
			return props.textConverter(finalValue.value);
 | 
								return props.textConverter(finalValue.value);
 | 
				
			||||||
		}),
 | 
							}),
 | 
				
			||||||
		targetElement: thumbEl,
 | 
							targetElement: thumbEl,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const style = document.createElement('style');
 | 
						const style = document.createElement('style');
 | 
				
			||||||
	style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }'));
 | 
						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('touchmove', onDrag);
 | 
				
			||||||
	window.addEventListener('mouseup', onMouseup, { once: true });
 | 
						window.addEventListener('mouseup', onMouseup, { once: true });
 | 
				
			||||||
	window.addEventListener('touchend', onMouseup, { once: true });
 | 
						window.addEventListener('touchend', onMouseup, { once: true });
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="scss" scoped>
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,11 +24,13 @@ const elRef = shallowRef();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (props.withTooltip) {
 | 
					if (props.withTooltip) {
 | 
				
			||||||
	useTooltip(elRef, (showing) => {
 | 
						useTooltip(elRef, (showing) => {
 | 
				
			||||||
		os.popup(defineAsyncComponent(() => import('@/components/MkReactionTooltip.vue')), {
 | 
							const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkReactionTooltip.vue')), {
 | 
				
			||||||
			showing,
 | 
								showing,
 | 
				
			||||||
			reaction: props.reaction.replace(/^:(\w+):$/, ':$1@.:'),
 | 
								reaction: props.reaction.replace(/^:(\w+):$/, ':$1@.:'),
 | 
				
			||||||
			targetElement: elRef.value.$el,
 | 
								targetElement: elRef.value.$el,
 | 
				
			||||||
		}, {}, 'closed');
 | 
							}, {
 | 
				
			||||||
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,10 +114,12 @@ async function menu(ev) {
 | 
				
			||||||
		text: i18n.ts.info,
 | 
							text: i18n.ts.info,
 | 
				
			||||||
		icon: 'ti ti-info-circle',
 | 
							icon: 'ti ti-info-circle',
 | 
				
			||||||
		action: async () => {
 | 
							action: async () => {
 | 
				
			||||||
			os.popup(MkCustomEmojiDetailedDialog, {
 | 
								const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
 | 
				
			||||||
				emoji: await misskeyApiGet('emoji', {
 | 
									emoji: await misskeyApiGet('emoji', {
 | 
				
			||||||
					name: props.reaction.replace(/:/g, '').replace(/@\./, ''),
 | 
										name: props.reaction.replace(/:/g, '').replace(/@\./, ''),
 | 
				
			||||||
				}),
 | 
									}),
 | 
				
			||||||
 | 
								}, {
 | 
				
			||||||
 | 
									closed: () => dispose(),
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}], ev.currentTarget ?? ev.target);
 | 
						}], ev.currentTarget ?? ev.target);
 | 
				
			||||||
| 
						 | 
					@ -129,7 +131,9 @@ function anime() {
 | 
				
			||||||
	const rect = buttonEl.value.getBoundingClientRect();
 | 
						const rect = buttonEl.value.getBoundingClientRect();
 | 
				
			||||||
	const x = rect.left + 16;
 | 
						const x = rect.left + 16;
 | 
				
			||||||
	const y = rect.top + (buttonEl.value.offsetHeight / 2);
 | 
						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) => {
 | 
					watch(() => props.count, (newCount, oldCount) => {
 | 
				
			||||||
| 
						 | 
					@ -151,13 +155,15 @@ if (!mock) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const users = reactions.map(x => x.user);
 | 
							const users = reactions.map(x => x.user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		os.popup(XDetails, {
 | 
							const { dispose } = os.popup(XDetails, {
 | 
				
			||||||
			showing,
 | 
								showing,
 | 
				
			||||||
			reaction: props.reaction,
 | 
								reaction: props.reaction,
 | 
				
			||||||
			users,
 | 
								users,
 | 
				
			||||||
			count: props.count,
 | 
								count: props.count,
 | 
				
			||||||
			targetElement: buttonEl.value,
 | 
								targetElement: buttonEl.value,
 | 
				
			||||||
		}, {}, 'closed');
 | 
							}, {
 | 
				
			||||||
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	}, 100);
 | 
						}, 100);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -218,8 +218,9 @@ function loginFailed(err: any): void {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function resetPassword(): void {
 | 
					function resetPassword(): void {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,15 +25,15 @@ export type MkSystemWebhookResult = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise<MkSystemWebhookResult | null> {
 | 
					export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise<MkSystemWebhookResult | null> {
 | 
				
			||||||
	const { dispose, result } = await new Promise<{ dispose: () => void, result: MkSystemWebhookResult | null }>(async resolve => {
 | 
						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')),
 | 
								defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')),
 | 
				
			||||||
			props,
 | 
								props,
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				submitted: (ev: MkSystemWebhookResult) => {
 | 
									submitted: (ev: MkSystemWebhookResult) => {
 | 
				
			||||||
					resolve({ dispose: res.dispose, result: ev });
 | 
										resolve({ dispose: _dispose, result: ev });
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				closed: () => {
 | 
									closed: () => {
 | 
				
			||||||
					resolve({ dispose: res.dispose, result: null });
 | 
										resolve({ dispose: _dispose, result: null });
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,11 +188,13 @@ function adjustTweetHeight(message: any) {
 | 
				
			||||||
	if (height) tweetHeight.value = height;
 | 
						if (height) tweetHeight.value = height;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const openPlayer = (): void => {
 | 
					function openPlayer(): void {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
 | 
				
			||||||
		url: requestUrl.href,
 | 
							url: requestUrl.href,
 | 
				
			||||||
 | 
						}, {
 | 
				
			||||||
 | 
							// TODO
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(window as any).addEventListener('message', adjustTweetHeight);
 | 
					(window as any).addEventListener('message', adjustTweetHeight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -176,9 +176,11 @@ function setupComplete() {
 | 
				
			||||||
function launchTutorial() {
 | 
					function launchTutorial() {
 | 
				
			||||||
	setupComplete();
 | 
						setupComplete();
 | 
				
			||||||
	nextTick(() => {
 | 
						nextTick(() => {
 | 
				
			||||||
		os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
 | 
							const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
 | 
				
			||||||
			initialPage: 1,
 | 
								initialPage: 1,
 | 
				
			||||||
		}, {}, 'closed');
 | 
							}, {
 | 
				
			||||||
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,15 +74,19 @@ misskeyApi('stats', {}).then((res) => {
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function signin() {
 | 
					function signin() {
 | 
				
			||||||
	os.popup(XSigninDialog, {
 | 
						const { dispose } = os.popup(XSigninDialog, {
 | 
				
			||||||
		autoSet: true,
 | 
							autoSet: true,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function signup() {
 | 
					function signup() {
 | 
				
			||||||
	os.popup(XSignupDialog, {
 | 
						const { dispose } = os.popup(XSignupDialog, {
 | 
				
			||||||
		autoSet: true,
 | 
							autoSet: true,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function showMenu(ev) {
 | 
					function showMenu(ev) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,12 +106,12 @@ function onClick(ev: MouseEvent) {
 | 
				
			||||||
			text: i18n.ts.info,
 | 
								text: i18n.ts.info,
 | 
				
			||||||
			icon: 'ti ti-info-circle',
 | 
								icon: 'ti ti-info-circle',
 | 
				
			||||||
			action: async () => {
 | 
								action: async () => {
 | 
				
			||||||
				os.popup(MkCustomEmojiDetailedDialog, {
 | 
									const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
 | 
				
			||||||
					emoji: await misskeyApiGet('emoji', {
 | 
										emoji: await misskeyApiGet('emoji', {
 | 
				
			||||||
						name: customEmojiName.value,
 | 
											name: customEmojiName.value,
 | 
				
			||||||
					}),
 | 
										}),
 | 
				
			||||||
				}, {
 | 
									}, {
 | 
				
			||||||
					anchor: ev.target,
 | 
										closed: () => dispose(),
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}], ev.currentTarget ?? ev.target);
 | 
							}], ev.currentTarget ?? ev.target);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,11 +50,13 @@ const el = ref();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (props.showUrlPreview && isEnabledUrlPreview.value) {
 | 
					if (props.showUrlPreview && isEnabledUrlPreview.value) {
 | 
				
			||||||
	useTooltip(el, (showing) => {
 | 
						useTooltip(el, (showing) => {
 | 
				
			||||||
		os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
 | 
							const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
 | 
				
			||||||
			showing,
 | 
								showing,
 | 
				
			||||||
			url: props.url,
 | 
								url: props.url,
 | 
				
			||||||
			source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
 | 
								source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
 | 
				
			||||||
		}, {}, 'closed');
 | 
							}, {
 | 
				
			||||||
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,9 @@ export default {
 | 
				
			||||||
			const x = rect.left + (el.offsetWidth / 2);
 | 
								const x = rect.left + (el.offsetWidth / 2);
 | 
				
			||||||
			const y = rect.top + (el.offsetHeight / 2);
 | 
								const y = rect.top + (el.offsetHeight / 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			popup(MkRippleEffect, { x, y }, {}, 'end');
 | 
								const { dispose } = popup(MkRippleEffect, { x, y }, {
 | 
				
			||||||
 | 
									end: () => dispose(),
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,13 +51,15 @@ export default {
 | 
				
			||||||
			if (self.text == null) return;
 | 
								if (self.text == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const showing = ref(true);
 | 
								const showing = ref(true);
 | 
				
			||||||
			popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
 | 
								const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
 | 
				
			||||||
				showing,
 | 
									showing,
 | 
				
			||||||
				text: self.text,
 | 
									text: self.text,
 | 
				
			||||||
				asMfm: binding.modifiers.mfm,
 | 
									asMfm: binding.modifiers.mfm,
 | 
				
			||||||
				direction: binding.modifiers.left ? 'left' : binding.modifiers.right ? 'right' : binding.modifiers.top ? 'top' : binding.modifiers.bottom ? 'bottom' : 'top',
 | 
									direction: binding.modifiers.left ? 'left' : binding.modifiers.right ? 'right' : binding.modifiers.top ? 'top' : binding.modifiers.bottom ? 'bottom' : 'top',
 | 
				
			||||||
				targetElement: el,
 | 
									targetElement: el,
 | 
				
			||||||
			}, {}, 'closed');
 | 
								}, {
 | 
				
			||||||
 | 
									closed: () => dispose(),
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			self._close = () => {
 | 
								self._close = () => {
 | 
				
			||||||
				showing.value = false;
 | 
									showing.value = false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@ export class UserPreview {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const showing = ref(true);
 | 
							const showing = ref(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		popup(defineAsyncComponent(() => import('@/components/MkUserPopup.vue')), {
 | 
							const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserPopup.vue')), {
 | 
				
			||||||
			showing,
 | 
								showing,
 | 
				
			||||||
			q: this.user,
 | 
								q: this.user,
 | 
				
			||||||
			source: this.el,
 | 
								source: this.el,
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,8 @@ export class UserPreview {
 | 
				
			||||||
				window.clearTimeout(this.showTimer);
 | 
									window.clearTimeout(this.showTimer);
 | 
				
			||||||
				this.hideTimer = window.setTimeout(this.close, 500);
 | 
									this.hideTimer = window.setTimeout(this.close, 500);
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.promise = {
 | 
							this.promise = {
 | 
				
			||||||
			cancel: () => {
 | 
								cancel: () => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,11 +116,13 @@ export function promiseDialog<T extends Promise<any>>(
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// NOTE: dynamic importすると挙動がおかしくなる(showingの変更が伝播しない)
 | 
						// NOTE: dynamic importすると挙動がおかしくなる(showingの変更が伝播しない)
 | 
				
			||||||
	popup(MkWaitingDialog, {
 | 
						const { dispose } = popup(MkWaitingDialog, {
 | 
				
			||||||
		success: success,
 | 
							success: success,
 | 
				
			||||||
		showing: showing,
 | 
							showing: showing,
 | 
				
			||||||
		text: text,
 | 
							text: text,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return promise;
 | 
						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];
 | 
						[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,
 | 
						component: T,
 | 
				
			||||||
	props: ComponentProps<T>,
 | 
						props: ComponentProps<T>,
 | 
				
			||||||
	events: ComponentEmit<T> = {} as ComponentEmit<T>,
 | 
						events: ComponentEmit<T> = {} as ComponentEmit<T>,
 | 
				
			||||||
	disposeEvent?: keyof ComponentEmit<T>,
 | 
					): { dispose: () => void } {
 | 
				
			||||||
): Promise<{ dispose: () => void }> {
 | 
					 | 
				
			||||||
	markRaw(component);
 | 
						markRaw(component);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const id = ++popupIdCount;
 | 
						const id = ++popupIdCount;
 | 
				
			||||||
	const dispose = () => {
 | 
						const dispose = () => {
 | 
				
			||||||
		// このsetTimeoutが無いと挙動がおかしくなる(autocompleteが閉じなくなる)。Vueのバグ?
 | 
							// このsetTimeoutが無いと挙動がおかしくなる(autocompleteが閉じなくなる)。Vueのバグ?
 | 
				
			||||||
		window.setTimeout(() => {
 | 
							window.setTimeout(() => {
 | 
				
			||||||
			popups.value = popups.value.filter(popup => popup.id !== id);
 | 
								popups.value = popups.value.filter(p => p.id !== id);
 | 
				
			||||||
		}, 0);
 | 
							}, 0);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	const state = {
 | 
						const state = {
 | 
				
			||||||
		component,
 | 
							component,
 | 
				
			||||||
		props,
 | 
							props,
 | 
				
			||||||
		events: disposeEvent ? {
 | 
							events,
 | 
				
			||||||
			...events,
 | 
					 | 
				
			||||||
			[disposeEvent]: dispose,
 | 
					 | 
				
			||||||
		} : events,
 | 
					 | 
				
			||||||
		id,
 | 
							id,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -199,15 +197,19 @@ export async function popup<T extends Component>(
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function pageWindow(path: string) {
 | 
					export function pageWindow(path: string) {
 | 
				
			||||||
	popup(MkPageWindow, {
 | 
						const { dispose } = popup(MkPageWindow, {
 | 
				
			||||||
		initialPath: path,
 | 
							initialPath: path,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function toast(message: string) {
 | 
					export function toast(message: string) {
 | 
				
			||||||
	popup(MkToast, {
 | 
						const { dispose } = popup(MkToast, {
 | 
				
			||||||
		message,
 | 
							message,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function alert(props: {
 | 
					export function alert(props: {
 | 
				
			||||||
| 
						 | 
					@ -216,11 +218,12 @@ export function alert(props: {
 | 
				
			||||||
	text?: string;
 | 
						text?: string;
 | 
				
			||||||
}): Promise<void> {
 | 
					}): Promise<void> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(MkDialog, props, {
 | 
							const { dispose } = popup(MkDialog, props, {
 | 
				
			||||||
			done: () => {
 | 
								done: () => {
 | 
				
			||||||
				resolve();
 | 
									resolve();
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -232,14 +235,15 @@ export function confirm(props: {
 | 
				
			||||||
	cancelText?: string;
 | 
						cancelText?: string;
 | 
				
			||||||
}): Promise<{ canceled: boolean }> {
 | 
					}): Promise<{ canceled: boolean }> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(MkDialog, {
 | 
							const { dispose } = popup(MkDialog, {
 | 
				
			||||||
			...props,
 | 
								...props,
 | 
				
			||||||
			showCancelButton: true,
 | 
								showCancelButton: true,
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
			done: result => {
 | 
								done: result => {
 | 
				
			||||||
				resolve(result ? result : { canceled: true });
 | 
									resolve(result ? result : { canceled: true });
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -261,7 +265,7 @@ export function actions<T extends {
 | 
				
			||||||
	canceled: false; result: T[number]['value'];
 | 
						canceled: false; result: T[number]['value'];
 | 
				
			||||||
}> {
 | 
					}> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(MkDialog, {
 | 
							const { dispose } = popup(MkDialog, {
 | 
				
			||||||
			...props,
 | 
								...props,
 | 
				
			||||||
			actions: props.actions.map(a => ({
 | 
								actions: props.actions.map(a => ({
 | 
				
			||||||
				text: a.text,
 | 
									text: a.text,
 | 
				
			||||||
| 
						 | 
					@ -275,7 +279,8 @@ export function actions<T extends {
 | 
				
			||||||
			done: result => {
 | 
								done: result => {
 | 
				
			||||||
				resolve(result ? result : { canceled: true });
 | 
									resolve(result ? result : { canceled: true });
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -323,7 +328,7 @@ export function inputText(props: {
 | 
				
			||||||
	canceled: false; result: string | null;
 | 
						canceled: false; result: string | null;
 | 
				
			||||||
}> {
 | 
					}> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(MkDialog, {
 | 
							const { dispose } = popup(MkDialog, {
 | 
				
			||||||
			title: props.title,
 | 
								title: props.title,
 | 
				
			||||||
			text: props.text,
 | 
								text: props.text,
 | 
				
			||||||
			input: {
 | 
								input: {
 | 
				
			||||||
| 
						 | 
					@ -338,7 +343,8 @@ export function inputText(props: {
 | 
				
			||||||
			done: result => {
 | 
								done: result => {
 | 
				
			||||||
				resolve(result ? result : { canceled: true });
 | 
									resolve(result ? result : { canceled: true });
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -377,7 +383,7 @@ export function inputNumber(props: {
 | 
				
			||||||
	canceled: false; result: number | null;
 | 
						canceled: false; result: number | null;
 | 
				
			||||||
}> {
 | 
					}> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(MkDialog, {
 | 
							const { dispose } = popup(MkDialog, {
 | 
				
			||||||
			title: props.title,
 | 
								title: props.title,
 | 
				
			||||||
			text: props.text,
 | 
								text: props.text,
 | 
				
			||||||
			input: {
 | 
								input: {
 | 
				
			||||||
| 
						 | 
					@ -390,7 +396,8 @@ export function inputNumber(props: {
 | 
				
			||||||
			done: result => {
 | 
								done: result => {
 | 
				
			||||||
				resolve(result ? result : { canceled: true });
 | 
									resolve(result ? result : { canceled: true });
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -405,7 +412,7 @@ export function inputDate(props: {
 | 
				
			||||||
	canceled: false; result: Date;
 | 
						canceled: false; result: Date;
 | 
				
			||||||
}> {
 | 
					}> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(MkDialog, {
 | 
							const { dispose } = popup(MkDialog, {
 | 
				
			||||||
			title: props.title,
 | 
								title: props.title,
 | 
				
			||||||
			text: props.text,
 | 
								text: props.text,
 | 
				
			||||||
			input: {
 | 
								input: {
 | 
				
			||||||
| 
						 | 
					@ -417,7 +424,8 @@ export function inputDate(props: {
 | 
				
			||||||
			done: result => {
 | 
								done: result => {
 | 
				
			||||||
				resolve(result ? { result: new Date(result.result), canceled: false } : { result: undefined, canceled: true });
 | 
									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; };
 | 
						canceled: false; result: { password: string; token: string | null; };
 | 
				
			||||||
}> {
 | 
					}> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(MkPasswordDialog, {}, {
 | 
							const { dispose } = popup(MkPasswordDialog, {}, {
 | 
				
			||||||
			done: result => {
 | 
								done: result => {
 | 
				
			||||||
				resolve(result ? { canceled: false, result } : { canceled: true, result: undefined });
 | 
									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;
 | 
						canceled: false; result: C | null;
 | 
				
			||||||
}> {
 | 
					}> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(MkDialog, {
 | 
							const { dispose } = popup(MkDialog, {
 | 
				
			||||||
			title: props.title,
 | 
								title: props.title,
 | 
				
			||||||
			text: props.text,
 | 
								text: props.text,
 | 
				
			||||||
			select: {
 | 
								select: {
 | 
				
			||||||
| 
						 | 
					@ -487,7 +496,8 @@ export function select<C = any>(props: {
 | 
				
			||||||
			done: result => {
 | 
								done: result => {
 | 
				
			||||||
				resolve(result ? result : { canceled: true });
 | 
									resolve(result ? result : { canceled: true });
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -497,53 +507,57 @@ export function success(): Promise<void> {
 | 
				
			||||||
		window.setTimeout(() => {
 | 
							window.setTimeout(() => {
 | 
				
			||||||
			showing.value = false;
 | 
								showing.value = false;
 | 
				
			||||||
		}, 1000);
 | 
							}, 1000);
 | 
				
			||||||
		popup(MkWaitingDialog, {
 | 
							const { dispose } = popup(MkWaitingDialog, {
 | 
				
			||||||
			success: true,
 | 
								success: true,
 | 
				
			||||||
			showing: showing,
 | 
								showing: showing,
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
			done: () => resolve(),
 | 
								done: () => resolve(),
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function waiting(): Promise<void> {
 | 
					export function waiting(): Promise<void> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		const showing = ref(true);
 | 
							const showing = ref(true);
 | 
				
			||||||
		popup(MkWaitingDialog, {
 | 
							const { dispose } = popup(MkWaitingDialog, {
 | 
				
			||||||
			success: false,
 | 
								success: false,
 | 
				
			||||||
			showing: showing,
 | 
								showing: showing,
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
			done: () => resolve(),
 | 
								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> }> {
 | 
					export function form<F extends Form>(title: string, f: F): Promise<{ canceled: true, result?: undefined } | { canceled?: false, result: GetFormResultType<F> }> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						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 => {
 | 
								done: result => {
 | 
				
			||||||
				resolve(result);
 | 
									resolve(result);
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function selectUser(opts: { includeSelf?: boolean; localOnly?: boolean; } = {}): Promise<Misskey.entities.UserDetailed> {
 | 
					export async function selectUser(opts: { includeSelf?: boolean; localOnly?: boolean; } = {}): Promise<Misskey.entities.UserDetailed> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), {
 | 
							const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), {
 | 
				
			||||||
			includeSelf: opts.includeSelf,
 | 
								includeSelf: opts.includeSelf,
 | 
				
			||||||
			localOnly: opts.localOnly,
 | 
								localOnly: opts.localOnly,
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
			ok: user => {
 | 
								ok: user => {
 | 
				
			||||||
				resolve(user);
 | 
									resolve(user);
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function selectDriveFile(multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
 | 
					export async function selectDriveFile(multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
 | 
							const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
 | 
				
			||||||
			type: 'file',
 | 
								type: 'file',
 | 
				
			||||||
			multiple,
 | 
								multiple,
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
| 
						 | 
					@ -552,13 +566,14 @@ export async function selectDriveFile(multiple: boolean): Promise<Misskey.entiti
 | 
				
			||||||
					resolve(files);
 | 
										resolve(files);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function selectDriveFolder(multiple: boolean): Promise<Misskey.entities.DriveFolder[]> {
 | 
					export async function selectDriveFolder(multiple: boolean): Promise<Misskey.entities.DriveFolder[]> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
 | 
							const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
 | 
				
			||||||
			type: 'folder',
 | 
								type: 'folder',
 | 
				
			||||||
			multiple,
 | 
								multiple,
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
| 
						 | 
					@ -567,20 +582,22 @@ export async function selectDriveFolder(multiple: boolean): Promise<Misskey.enti
 | 
				
			||||||
					resolve(folders);
 | 
										resolve(folders);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog>): Promise<string> {
 | 
					export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog>): Promise<string> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(MkEmojiPickerDialog, {
 | 
							const { dispose } = popup(MkEmojiPickerDialog, {
 | 
				
			||||||
			src,
 | 
								src,
 | 
				
			||||||
			...opts,
 | 
								...opts,
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
			done: emoji => {
 | 
								done: emoji => {
 | 
				
			||||||
				resolve(emoji);
 | 
									resolve(emoji);
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -589,7 +606,7 @@ export async function cropImage(image: Misskey.entities.DriveFile, options: {
 | 
				
			||||||
	uploadFolder?: string | null;
 | 
						uploadFolder?: string | null;
 | 
				
			||||||
}): Promise<Misskey.entities.DriveFile> {
 | 
					}): Promise<Misskey.entities.DriveFile> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		popup(defineAsyncComponent(() => import('@/components/MkCropperDialog.vue')), {
 | 
							const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkCropperDialog.vue')), {
 | 
				
			||||||
			file: image,
 | 
								file: image,
 | 
				
			||||||
			aspectRatio: options.aspectRatio,
 | 
								aspectRatio: options.aspectRatio,
 | 
				
			||||||
			uploadFolder: options.uploadFolder,
 | 
								uploadFolder: options.uploadFolder,
 | 
				
			||||||
| 
						 | 
					@ -597,7 +614,8 @@ export async function cropImage(image: Misskey.entities.DriveFile, options: {
 | 
				
			||||||
			ok: x => {
 | 
								ok: x => {
 | 
				
			||||||
				resolve(x);
 | 
									resolve(x);
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -608,8 +626,7 @@ export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | n
 | 
				
			||||||
	onClosing?: () => void;
 | 
						onClosing?: () => void;
 | 
				
			||||||
}): Promise<void> {
 | 
					}): Promise<void> {
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		let dispose;
 | 
							const { dispose } = popup(MkPopupMenu, {
 | 
				
			||||||
		popup(MkPopupMenu, {
 | 
					 | 
				
			||||||
			items,
 | 
								items,
 | 
				
			||||||
			src,
 | 
								src,
 | 
				
			||||||
			width: options?.width,
 | 
								width: options?.width,
 | 
				
			||||||
| 
						 | 
					@ -623,8 +640,6 @@ export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | n
 | 
				
			||||||
			closing: () => {
 | 
								closing: () => {
 | 
				
			||||||
				if (options?.onClosing) options.onClosing();
 | 
									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> {
 | 
					export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
 | 
				
			||||||
	ev.preventDefault();
 | 
						ev.preventDefault();
 | 
				
			||||||
	return new Promise(resolve => {
 | 
						return new Promise(resolve => {
 | 
				
			||||||
		let dispose;
 | 
							const { dispose } = popup(MkContextMenu, {
 | 
				
			||||||
		popup(MkContextMenu, {
 | 
					 | 
				
			||||||
			items,
 | 
								items,
 | 
				
			||||||
			ev,
 | 
								ev,
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
| 
						 | 
					@ -641,8 +655,6 @@ export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
 | 
				
			||||||
				resolve();
 | 
									resolve();
 | 
				
			||||||
				dispose();
 | 
									dispose();
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}).then(res => {
 | 
					 | 
				
			||||||
			dispose = res.dispose;
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -656,14 +668,11 @@ export function post(props: Record<string, any> = {}): Promise<void> {
 | 
				
			||||||
		//       Vueが渡されたコンポーネントに内部的に__propsというプロパティを生やす影響で、
 | 
							//       Vueが渡されたコンポーネントに内部的に__propsというプロパティを生やす影響で、
 | 
				
			||||||
		//       複数のpost formを開いたときに場合によってはエラーになる
 | 
							//       複数のpost formを開いたときに場合によってはエラーになる
 | 
				
			||||||
		//       もちろん複数のpost formを開けること自体Misskeyサイドのバグなのだが
 | 
							//       もちろん複数のpost formを開けること自体Misskeyサイドのバグなのだが
 | 
				
			||||||
		let dispose;
 | 
							const { dispose } = popup(MkPostFormDialog, props, {
 | 
				
			||||||
		popup(MkPostFormDialog, props, {
 | 
					 | 
				
			||||||
			closed: () => {
 | 
								closed: () => {
 | 
				
			||||||
				resolve();
 | 
									resolve();
 | 
				
			||||||
				dispose();
 | 
									dispose();
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}).then(res => {
 | 
					 | 
				
			||||||
			dispose = res.dispose;
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -464,16 +464,20 @@ function toggleRoleItem(role) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function createAnnouncement() {
 | 
					function createAnnouncement() {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
 | 
				
			||||||
		user: user.value,
 | 
							user: user.value,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function editAnnouncement(announcement) {
 | 
					function editAnnouncement(announcement) {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
 | 
				
			||||||
		user: user.value,
 | 
							user: user.value,
 | 
				
			||||||
		announcement,
 | 
							announcement,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(() => props.userId, () => {
 | 
					watch(() => props.userId, () => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,7 +109,7 @@ async function onDeleteButtonClicked(id: string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function showEditor(mode: 'create' | 'edit', id?: string) {
 | 
					async function showEditor(mode: 'create' | 'edit', id?: string) {
 | 
				
			||||||
	const { dispose, needLoad } = await new Promise<{ dispose: () => void, needLoad: boolean }>(async resolve => {
 | 
						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')),
 | 
								defineAsyncComponent(() => import('./notification-recipient.editor.vue')),
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				mode,
 | 
									mode,
 | 
				
			||||||
| 
						 | 
					@ -117,10 +117,10 @@ async function showEditor(mode: 'create' | 'edit', id?: string) {
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				submitted: async () => {
 | 
									submitted: async () => {
 | 
				
			||||||
					resolve({ dispose: res.dispose, needLoad: true });
 | 
										resolve({ dispose: _dispose, needLoad: true });
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				closed: () => {
 | 
									closed: () => {
 | 
				
			||||||
					resolve({ dispose: res.dispose, needLoad: false });
 | 
										resolve({ dispose: _dispose, needLoad: false });
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,18 +129,19 @@ const toggleSelect = (emoji) => {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const add = async (ev: MouseEvent) => {
 | 
					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 => {
 | 
							done: result => {
 | 
				
			||||||
			if (result.created) {
 | 
								if (result.created) {
 | 
				
			||||||
				emojisPaginationComponent.value.prepend(result.created);
 | 
									emojisPaginationComponent.value.prepend(result.created);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const edit = (emoji) => {
 | 
					const edit = (emoji) => {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
 | 
				
			||||||
		emoji: emoji,
 | 
							emoji: emoji,
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
		done: result => {
 | 
							done: result => {
 | 
				
			||||||
| 
						 | 
					@ -153,7 +154,8 @@ const edit = (emoji) => {
 | 
				
			||||||
				emojisPaginationComponent.value.removeItem(emoji.id);
 | 
									emojisPaginationComponent.value.removeItem(emoji.id);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const importEmoji = (emoji) => {
 | 
					const importEmoji = (emoji) => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -160,7 +160,7 @@ function rename() {
 | 
				
			||||||
function describe() {
 | 
					function describe() {
 | 
				
			||||||
	if (!file.value) return;
 | 
						if (!file.value) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
 | 
				
			||||||
		default: file.value.comment ?? '',
 | 
							default: file.value.comment ?? '',
 | 
				
			||||||
		file: file.value,
 | 
							file: file.value,
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
| 
						 | 
					@ -172,7 +172,8 @@ function describe() {
 | 
				
			||||||
				await fetch();
 | 
									await fetch();
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function deleteFile() {
 | 
					async function deleteFile() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1008,8 +1008,18 @@ function attachGameEvents() {
 | 
				
			||||||
		const domX = rect.left + (x * viewScale);
 | 
							const domX = rect.left + (x * viewScale);
 | 
				
			||||||
		const domY = rect.top + (y * viewScale);
 | 
							const domY = rect.top + (y * viewScale);
 | 
				
			||||||
		const scoreUnit = getScoreUnit(props.gameMode);
 | 
							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) {
 | 
							if (nextMono) {
 | 
				
			||||||
			const def = monoDefinitions.value.find(x => x.id === nextMono.id)!;
 | 
								const def = monoDefinitions.value.find(x => x.id === nextMono.id)!;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,8 +14,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import * as os from '@/os.js';
 | 
					 | 
				
			||||||
import * as Misskey from 'misskey-js';
 | 
					import * as Misskey from 'misskey-js';
 | 
				
			||||||
 | 
					import * as os from '@/os.js';
 | 
				
			||||||
import { misskeyApiGet } from '@/scripts/misskey-api.js';
 | 
					import { misskeyApiGet } from '@/scripts/misskey-api.js';
 | 
				
			||||||
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
 | 
					import copyToClipboard from '@/scripts/copy-to-clipboard.js';
 | 
				
			||||||
import { i18n } from '@/i18n.js';
 | 
					import { i18n } from '@/i18n.js';
 | 
				
			||||||
| 
						 | 
					@ -40,12 +40,12 @@ function menu(ev) {
 | 
				
			||||||
		text: i18n.ts.info,
 | 
							text: i18n.ts.info,
 | 
				
			||||||
		icon: 'ti ti-info-circle',
 | 
							icon: 'ti ti-info-circle',
 | 
				
			||||||
		action: async () => {
 | 
							action: async () => {
 | 
				
			||||||
			os.popup(MkCustomEmojiDetailedDialog, {
 | 
								const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
 | 
				
			||||||
				emoji: await misskeyApiGet('emoji', {
 | 
									emoji: await misskeyApiGet('emoji', {
 | 
				
			||||||
					name: props.emoji.name,
 | 
										name: props.emoji.name,
 | 
				
			||||||
				})
 | 
									}),
 | 
				
			||||||
			}, {
 | 
								}, {
 | 
				
			||||||
				anchor: ev.target,
 | 
									closed: () => dispose(),
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}], ev.currentTarget ?? ev.target);
 | 
						}], ev.currentTarget ?? ev.target);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,9 @@ async function save() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(() => {
 | 
				
			||||||
	if (props.token == null) {
 | 
						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('/');
 | 
							mainRouter.push('/');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,9 +108,11 @@ async function registerTOTP(): Promise<void> {
 | 
				
			||||||
		token: auth.result.token,
 | 
							token: auth.result.token,
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), {
 | 
				
			||||||
		twoFactorData,
 | 
							twoFactorData,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function unregisterTOTP(): Promise<void> {
 | 
					async function unregisterTOTP(): Promise<void> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,22 +74,24 @@ async function removeAccount(account) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function addExistingAccount() {
 | 
					function addExistingAccount() {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
 | 
				
			||||||
		done: async res => {
 | 
							done: async res => {
 | 
				
			||||||
			await addAccounts(res.id, res.i);
 | 
								await addAccounts(res.id, res.i);
 | 
				
			||||||
			os.success();
 | 
								os.success();
 | 
				
			||||||
			init();
 | 
								init();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function createAccount() {
 | 
					function createAccount() {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
 | 
				
			||||||
		done: async res => {
 | 
							done: async res => {
 | 
				
			||||||
			await addAccounts(res.id, res.i);
 | 
								await addAccounts(res.id, res.i);
 | 
				
			||||||
			switchAccountWithToken(res.i);
 | 
								switchAccountWithToken(res.i);
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function switchAccount(account: any) {
 | 
					async function switchAccount(account: any) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
 | 
				
			||||||
const isDesktop = ref(window.innerWidth >= 1100);
 | 
					const isDesktop = ref(window.innerWidth >= 1100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function generateToken() {
 | 
					function generateToken() {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
 | 
				
			||||||
		done: async result => {
 | 
							done: async result => {
 | 
				
			||||||
			const { name, permissions } = result;
 | 
								const { name, permissions } = result;
 | 
				
			||||||
			const { token } = await misskeyApi('miauth/gen-token', {
 | 
								const { token } = await misskeyApi('miauth/gen-token', {
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,8 @@ function generateToken() {
 | 
				
			||||||
				text: token,
 | 
									text: token,
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const headerActions = computed(() => []);
 | 
					const headerActions = computed(() => []);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,7 +67,7 @@ misskeyApi('get-avatar-decorations').then(_avatarDecorations => {
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function openDecoration(avatarDecoration, index?: number) {
 | 
					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,
 | 
							decoration: avatarDecoration,
 | 
				
			||||||
		usingIndex: index,
 | 
							usingIndex: index,
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
| 
						 | 
					@ -108,7 +108,8 @@ function openDecoration(avatarDecoration, index?: number) {
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
			$i.avatarDecorations = update;
 | 
								$i.avatarDecorations = update;
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function detachAllDecorations() {
 | 
					function detachAllDecorations() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ function rename(file: Misskey.entities.DriveFile) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function describe(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 ?? '',
 | 
							default: file.comment ?? '',
 | 
				
			||||||
		file: file,
 | 
							file: file,
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,8 @@ function describe(file: Misskey.entities.DriveFile) {
 | 
				
			||||||
				comment: caption.length === 0 ? null : caption,
 | 
									comment: caption.length === 0 ? null : caption,
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function toggleSensitive(file: Misskey.entities.DriveFile) {
 | 
					function toggleSensitive(file: Misskey.entities.DriveFile) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,10 +136,12 @@ export function getAbuseNoteMenu(note: Misskey.entities.Note, text: string): Men
 | 
				
			||||||
			let noteInfo = '';
 | 
								let noteInfo = '';
 | 
				
			||||||
			if (note.url ?? note.uri != null) noteInfo = `Note: ${note.url ?? note.uri}\n`;
 | 
								if (note.url ?? note.uri != null) noteInfo = `Note: ${note.url ?? note.uri}\n`;
 | 
				
			||||||
			noteInfo += `Local Note: ${localUrl}\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,
 | 
									user: note.user,
 | 
				
			||||||
				initialComment: `${noteInfo}-----\n`,
 | 
									initialComment: `${noteInfo}-----\n`,
 | 
				
			||||||
			}, {}, 'closed');
 | 
								}, {
 | 
				
			||||||
 | 
									closed: () => dispose(),
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -530,7 +532,9 @@ export function getRenoteMenu(props: {
 | 
				
			||||||
					const rect = el.getBoundingClientRect();
 | 
										const rect = el.getBoundingClientRect();
 | 
				
			||||||
					const x = rect.left + (el.offsetWidth / 2);
 | 
										const x = rect.left + (el.offsetWidth / 2);
 | 
				
			||||||
					const y = rect.top + (el.offsetHeight / 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) {
 | 
									if (!props.mock) {
 | 
				
			||||||
| 
						 | 
					@ -566,7 +570,9 @@ export function getRenoteMenu(props: {
 | 
				
			||||||
					const rect = el.getBoundingClientRect();
 | 
										const rect = el.getBoundingClientRect();
 | 
				
			||||||
					const x = rect.left + (el.offsetWidth / 2);
 | 
										const x = rect.left + (el.offsetWidth / 2);
 | 
				
			||||||
					const y = rect.top + (el.offsetHeight / 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;
 | 
									const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
 | 
				
			||||||
| 
						 | 
					@ -615,7 +621,9 @@ export function getRenoteMenu(props: {
 | 
				
			||||||
							const rect = el.getBoundingClientRect();
 | 
												const rect = el.getBoundingClientRect();
 | 
				
			||||||
							const x = rect.left + (el.offsetWidth / 2);
 | 
												const x = rect.left + (el.offsetWidth / 2);
 | 
				
			||||||
							const y = rect.top + (el.offsetHeight / 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) {
 | 
											if (!props.mock) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,9 +100,11 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function reportAbuse() {
 | 
						function reportAbuse() {
 | 
				
			||||||
		os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
 | 
							const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
 | 
				
			||||||
			user: user,
 | 
								user: user,
 | 
				
			||||||
		}, {}, 'closed');
 | 
							}, {
 | 
				
			||||||
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	async function getConfirmed(text: string): Promise<boolean> {
 | 
						async function getConfirmed(text: string): Promise<boolean> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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) => {
 | 
						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,
 | 
								title: i18n.ts.tokenRequested,
 | 
				
			||||||
			information: i18n.ts.pluginTokenRequestedDescription,
 | 
								information: i18n.ts.pluginTokenRequestedDescription,
 | 
				
			||||||
			initialName: realMeta.name,
 | 
								initialName: realMeta.name,
 | 
				
			||||||
| 
						 | 
					@ -118,7 +118,8 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) {
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
				res(token);
 | 
									res(token);
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}, 'closed');
 | 
								closed: () => dispose(),
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	savePlugin({
 | 
						savePlugin({
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ import { popup } from '@/os.js';
 | 
				
			||||||
export function pleaseLogin(path?: string) {
 | 
					export function pleaseLogin(path?: string) {
 | 
				
			||||||
	if ($i) return;
 | 
						if ($i) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
 | 
						const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
 | 
				
			||||||
		autoSet: true,
 | 
							autoSet: true,
 | 
				
			||||||
		message: i18n.ts.signinRequired,
 | 
							message: i18n.ts.signinRequired,
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,8 @@ export function pleaseLogin(path?: string) {
 | 
				
			||||||
				window.location.href = path;
 | 
									window.location.href = path;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	throw new Error('signin required');
 | 
						throw new Error('signin required');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,20 +17,16 @@ export function useChartTooltip(opts: { position: 'top' | 'middle' } = { positio
 | 
				
			||||||
		borderColor: string;
 | 
							borderColor: string;
 | 
				
			||||||
		text: string;
 | 
							text: string;
 | 
				
			||||||
	}[] | null>(null);
 | 
						}[] | null>(null);
 | 
				
			||||||
	let disposeTooltipComponent;
 | 
						const { dispose: disposeTooltipComponent } = os.popup(MkChartTooltip, {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	os.popup(MkChartTooltip, {
 | 
					 | 
				
			||||||
		showing: tooltipShowing,
 | 
							showing: tooltipShowing,
 | 
				
			||||||
		x: tooltipX,
 | 
							x: tooltipX,
 | 
				
			||||||
		y: tooltipY,
 | 
							y: tooltipY,
 | 
				
			||||||
		title: tooltipTitle,
 | 
							title: tooltipTitle,
 | 
				
			||||||
		series: tooltipSeries,
 | 
							series: tooltipSeries,
 | 
				
			||||||
	}, {}).then(({ dispose }) => {
 | 
						}, {});
 | 
				
			||||||
		disposeTooltipComponent = dispose;
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	onUnmounted(() => {
 | 
						onUnmounted(() => {
 | 
				
			||||||
		if (disposeTooltipComponent) disposeTooltipComponent();
 | 
							disposeTooltipComponent();
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	onDeactivated(() => {
 | 
						onDeactivated(() => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,7 +112,9 @@ export function openInstanceMenu(ev: MouseEvent) {
 | 
				
			||||||
		text: i18n.ts._initialTutorial.launchTutorial,
 | 
							text: i18n.ts._initialTutorial.launchTutorial,
 | 
				
			||||||
		icon: 'ti ti-presentation',
 | 
							icon: 'ti ti-presentation',
 | 
				
			||||||
		action: () => {
 | 
							action: () => {
 | 
				
			||||||
			os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {}, {}, 'closed');
 | 
								const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {}, {
 | 
				
			||||||
 | 
									closed: () => dispose(),
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	} : undefined, {
 | 
						} : undefined, {
 | 
				
			||||||
		type: 'link',
 | 
							type: 'link',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,8 +74,9 @@ function openAccountMenu(ev: MouseEvent) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function more() {
 | 
					function more() {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {}, {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {}, {
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,10 +99,11 @@ function openAccountMenu(ev: MouseEvent) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function more(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,
 | 
							src: ev.currentTarget ?? ev.target,
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,11 +71,12 @@ const otherNavItemIndicated = computed<boolean>(() => {
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function more(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,
 | 
							src: ev.currentTarget ?? ev.target,
 | 
				
			||||||
		anchor: { x: 'center', y: 'bottom' },
 | 
							anchor: { x: 'center', y: 'bottom' },
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function openAccountMenu(ev: MouseEvent) {
 | 
					function openAccountMenu(ev: MouseEvent) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,9 +86,11 @@ function calcViewState() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function more(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,
 | 
							src: ev.currentTarget ?? ev.target,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function openAccountMenu(ev: MouseEvent) {
 | 
					function openAccountMenu(ev: MouseEvent) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ const props = defineProps<{
 | 
				
			||||||
const notificationsComponent = shallowRef<InstanceType<typeof XNotifications>>();
 | 
					const notificationsComponent = shallowRef<InstanceType<typeof XNotifications>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function func() {
 | 
					function func() {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
 | 
				
			||||||
		excludeTypes: props.column.excludeTypes,
 | 
							excludeTypes: props.column.excludeTypes,
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
		done: async (res) => {
 | 
							done: async (res) => {
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,8 @@ function func() {
 | 
				
			||||||
				excludeTypes: excludeTypes,
 | 
									excludeTypes: excludeTypes,
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const menu = [{
 | 
					const menu = [{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,15 +126,19 @@ const keymap = computed(() => {
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function signin() {
 | 
					function signin() {
 | 
				
			||||||
	os.popup(XSigninDialog, {
 | 
						const { dispose } = os.popup(XSigninDialog, {
 | 
				
			||||||
		autoSet: true,
 | 
							autoSet: true,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function signup() {
 | 
					function signup() {
 | 
				
			||||||
	os.popup(XSignupDialog, {
 | 
						const { dispose } = os.popup(XSignupDialog, {
 | 
				
			||||||
		autoSet: true,
 | 
							autoSet: true,
 | 
				
			||||||
	}, {}, 'closed');
 | 
						}, {
 | 
				
			||||||
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(() => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,7 @@ const { widgetProps, configure, save } = useWidgetPropsManager(name,
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const configureNotification = () => {
 | 
					const configureNotification = () => {
 | 
				
			||||||
	os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
 | 
						const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
 | 
				
			||||||
		excludeTypes: widgetProps.excludeTypes,
 | 
							excludeTypes: widgetProps.excludeTypes,
 | 
				
			||||||
	}, {
 | 
						}, {
 | 
				
			||||||
		done: async (res) => {
 | 
							done: async (res) => {
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,8 @@ const configureNotification = () => {
 | 
				
			||||||
			widgetProps.excludeTypes = excludeTypes;
 | 
								widgetProps.excludeTypes = excludeTypes;
 | 
				
			||||||
			save();
 | 
								save();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}, 'closed');
 | 
							closed: () => dispose(),
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineExpose<WidgetComponentExpose>({
 | 
					defineExpose<WidgetComponentExpose>({
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue