refactor(frontend): refactor popup api and make sure call dispose callback

Close #14122
This commit is contained in:
syuilo
2024-07-04 13:14:49 +09:00
parent fab7d5e484
commit 6dd2e9fc0b
49 changed files with 317 additions and 196 deletions

View File

@@ -35,7 +35,9 @@ const prevCookies = ref(0);
function onClick(ev: MouseEvent) {
const x = ev.clientX;
const y = ev.clientY;
os.popup(MkPlusOneEffect, { x, y }, {}, 'end');
const { dispose } = os.popup(MkPlusOneEffect, { x, y }, {
end: () => dispose(),
});
saveData.value!.cookies++;
saveData.value!.totalCookies++;

View File

@@ -257,10 +257,11 @@ function onContextmenu(ev: MouseEvent) {
text: i18n.ts.openInWindow,
icon: 'ti ti-app-window',
action: () => {
os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), {
initialFolder: props.folder,
}, {
}, 'closed');
closed: () => dispose(),
});
},
}, { type: 'divider' }, {
text: i18n.ts.rename,

View File

@@ -402,7 +402,9 @@ function chosen(emoji: any, ev?: MouseEvent) {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
const y = rect.top + (el.offsetHeight / 2);
os.popup(MkRippleEffect, { x, y }, {}, 'end');
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
end: () => dispose(),
});
}
const key = getKey(emoji);

View File

@@ -37,11 +37,13 @@ const el = ref<HTMLElement | { $el: HTMLElement }>();
if (isEnabledUrlPreview.value) {
useTooltip(el, (showing) => {
os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
showing,
url: props.url,
source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
});
}
</script>

View File

@@ -335,12 +335,14 @@ if (!props.mock) {
if (users.length < 1) return;
os.popup(MkUsersTooltip, {
const { dispose } = os.popup(MkUsersTooltip, {
showing,
users,
count: appearNote.value.renoteCount,
targetElement: renoteButton.value,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
});
if (appearNote.value.reactionAcceptance === 'likeOnly') {
@@ -355,13 +357,15 @@ if (!props.mock) {
if (users.length < 1) return;
os.popup(MkReactionsViewerDetails, {
const { dispose } = os.popup(MkReactionsViewerDetails, {
showing,
reaction: '❤️',
users,
count: appearNote.value.reactionCount,
targetElement: reactButton.value!,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
});
}
}
@@ -409,7 +413,9 @@ function react(viaKeyboard = false): void {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
const y = rect.top + (el.offsetHeight / 2);
os.popup(MkRippleEffect, { x, y }, {}, 'end');
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
end: () => dispose(),
});
}
} else {
blur();

View File

@@ -346,12 +346,14 @@ useTooltip(renoteButton, async (showing) => {
if (users.length < 1) return;
os.popup(MkUsersTooltip, {
const { dispose } = os.popup(MkUsersTooltip, {
showing,
users,
count: appearNote.value.renoteCount,
targetElement: renoteButton.value,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
});
if (appearNote.value.reactionAcceptance === 'likeOnly') {
@@ -366,13 +368,15 @@ if (appearNote.value.reactionAcceptance === 'likeOnly') {
if (users.length < 1) return;
os.popup(MkReactionsViewerDetails, {
const { dispose } = os.popup(MkReactionsViewerDetails, {
showing,
reaction: '❤️',
users,
count: appearNote.value.reactionCount,
targetElement: reactButton.value!,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
});
}
@@ -413,7 +417,9 @@ function react(viaKeyboard = false): void {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
const y = rect.top + (el.offsetHeight / 2);
os.popup(MkRippleEffect, { x, y }, {}, 'end');
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
end: () => dispose(),
});
}
} else {
blur();

View File

@@ -463,7 +463,7 @@ function setVisibility() {
return;
}
os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
currentVisibility: visibility.value,
isSilenced: $i.isSilenced,
localOnly: localOnly.value,
@@ -476,7 +476,8 @@ function setVisibility() {
defaultStore.set('visibility', visibility.value);
}
},
}, 'closed');
closed: () => dispose(),
});
}
async function toggleLocalOnly() {
@@ -624,8 +625,8 @@ async function onPaste(ev: ClipboardEvent) {
return;
}
const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, "0");
const file = new File([paste], `${fileName}.txt`, { type: "text/plain" });
const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, '0');
const file = new File([paste], `${fileName}.txt`, { type: 'text/plain' });
upload(file, `${fileName}.txt`);
});
}
@@ -731,7 +732,9 @@ async function post(ev?: MouseEvent) {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
const y = rect.top + (el.offsetHeight / 2);
os.popup(MkRippleEffect, { x, y }, {}, 'end');
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
end: () => dispose(),
});
}
}

View File

@@ -108,7 +108,7 @@ async function rename(file) {
async function describe(file) {
if (mock) return;
os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
default: file.comment !== null ? file.comment : '',
file: file,
}, {
@@ -121,7 +121,8 @@ async function describe(file) {
file.comment = comment;
});
},
}, 'closed');
closed: () => dispose(),
});
}
async function crop(file: Misskey.entities.DriveFile): Promise<void> {

View File

@@ -101,17 +101,19 @@ const steps = computed(() => {
}
});
const onMousedown = (ev: MouseEvent | TouchEvent) => {
function onMousedown(ev: MouseEvent | TouchEvent) {
ev.preventDefault();
const tooltipShowing = ref(true);
os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
showing: tooltipShowing,
text: computed(() => {
return props.textConverter(finalValue.value);
}),
targetElement: thumbEl,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
const style = document.createElement('style');
style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }'));
@@ -152,7 +154,7 @@ const onMousedown = (ev: MouseEvent | TouchEvent) => {
window.addEventListener('touchmove', onDrag);
window.addEventListener('mouseup', onMouseup, { once: true });
window.addEventListener('touchend', onMouseup, { once: true });
};
}
</script>
<style lang="scss" scoped>

View File

@@ -24,11 +24,13 @@ const elRef = shallowRef();
if (props.withTooltip) {
useTooltip(elRef, (showing) => {
os.popup(defineAsyncComponent(() => import('@/components/MkReactionTooltip.vue')), {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkReactionTooltip.vue')), {
showing,
reaction: props.reaction.replace(/^:(\w+):$/, ':$1@.:'),
targetElement: elRef.value.$el,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
});
}
</script>

View File

@@ -114,10 +114,12 @@ async function menu(ev) {
text: i18n.ts.info,
icon: 'ti ti-info-circle',
action: async () => {
os.popup(MkCustomEmojiDetailedDialog, {
const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
emoji: await misskeyApiGet('emoji', {
name: props.reaction.replace(/:/g, '').replace(/@\./, ''),
}),
}, {
closed: () => dispose(),
});
},
}], ev.currentTarget ?? ev.target);
@@ -129,7 +131,9 @@ function anime() {
const rect = buttonEl.value.getBoundingClientRect();
const x = rect.left + 16;
const y = rect.top + (buttonEl.value.offsetHeight / 2);
os.popup(MkReactionEffect, { reaction: props.reaction, x, y }, {}, 'end');
const { dispose } = os.popup(MkReactionEffect, { reaction: props.reaction, x, y }, {
end: () => dispose(),
});
}
watch(() => props.count, (newCount, oldCount) => {
@@ -151,13 +155,15 @@ if (!mock) {
const users = reactions.map(x => x.user);
os.popup(XDetails, {
const { dispose } = os.popup(XDetails, {
showing,
reaction: props.reaction,
users,
count: props.count,
targetElement: buttonEl.value,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
}, 100);
}
</script>

View File

@@ -218,8 +218,9 @@ function loginFailed(err: any): void {
}
function resetPassword(): void {
os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
}, 'closed');
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
closed: () => dispose(),
});
}
</script>

View File

@@ -25,15 +25,15 @@ export type MkSystemWebhookResult = {
export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise<MkSystemWebhookResult | null> {
const { dispose, result } = await new Promise<{ dispose: () => void, result: MkSystemWebhookResult | null }>(async resolve => {
const res = await os.popup(
const { dispose: _dispose } = os.popup(
defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')),
props,
{
submitted: (ev: MkSystemWebhookResult) => {
resolve({ dispose: res.dispose, result: ev });
resolve({ dispose: _dispose, result: ev });
},
closed: () => {
resolve({ dispose: res.dispose, result: null });
resolve({ dispose: _dispose, result: null });
},
},
);

View File

@@ -188,11 +188,13 @@ function adjustTweetHeight(message: any) {
if (height) tweetHeight.value = height;
}
const openPlayer = (): void => {
os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
function openPlayer(): void {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
url: requestUrl.href,
}, {
// TODO
});
};
}
(window as any).addEventListener('message', adjustTweetHeight);

View File

@@ -176,9 +176,11 @@ function setupComplete() {
function launchTutorial() {
setupComplete();
nextTick(() => {
os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
initialPage: 1,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
});
}

View File

@@ -74,15 +74,19 @@ misskeyApi('stats', {}).then((res) => {
});
function signin() {
os.popup(XSigninDialog, {
const { dispose } = os.popup(XSigninDialog, {
autoSet: true,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
}
function signup() {
os.popup(XSignupDialog, {
const { dispose } = os.popup(XSignupDialog, {
autoSet: true,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
}
function showMenu(ev) {

View File

@@ -106,12 +106,12 @@ function onClick(ev: MouseEvent) {
text: i18n.ts.info,
icon: 'ti ti-info-circle',
action: async () => {
os.popup(MkCustomEmojiDetailedDialog, {
const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
emoji: await misskeyApiGet('emoji', {
name: customEmojiName.value,
}),
}, {
anchor: ev.target,
closed: () => dispose(),
});
},
}], ev.currentTarget ?? ev.target);

View File

@@ -50,11 +50,13 @@ const el = ref();
if (props.showUrlPreview && isEnabledUrlPreview.value) {
useTooltip(el, (showing) => {
os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
showing,
url: props.url,
source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
}, {}, 'closed');
}, {
closed: () => dispose(),
});
});
}