feat(client): make possible to switch account instantly in post form
This commit is contained in:
		@@ -129,7 +129,12 @@ export async function login(token: Account['token'], redirect?: string) {
 | 
			
		||||
	unisonReload();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function openAccountMenu(ev: MouseEvent) {
 | 
			
		||||
export async function openAccountMenu(opts: {
 | 
			
		||||
	includeCurrentAccount?: boolean;
 | 
			
		||||
	withExtraOperation: boolean;
 | 
			
		||||
	active?: misskey.entities.UserDetailed['id'];
 | 
			
		||||
	onChoose?: (account: misskey.entities.UserDetailed) => void;
 | 
			
		||||
}, ev: MouseEvent) {
 | 
			
		||||
	function showSigninDialog() {
 | 
			
		||||
		popup(import('@/components/signin-dialog.vue'), {}, {
 | 
			
		||||
			done: res => {
 | 
			
		||||
@@ -148,7 +153,7 @@ export async function openAccountMenu(ev: MouseEvent) {
 | 
			
		||||
		}, 'closed');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async function switchAccount(account: any) {
 | 
			
		||||
	async function switchAccount(account: misskey.entities.UserDetailed) {
 | 
			
		||||
		const storedAccounts = await getAccounts();
 | 
			
		||||
		const token = storedAccounts.find(x => x.id === account.id).token;
 | 
			
		||||
		switchAccountWithToken(token);
 | 
			
		||||
@@ -161,41 +166,58 @@ export async function openAccountMenu(ev: MouseEvent) {
 | 
			
		||||
	const storedAccounts = await getAccounts().then(accounts => accounts.filter(x => x.id !== $i.id));
 | 
			
		||||
	const accountsPromise = api('users/show', { userIds: storedAccounts.map(x => x.id) });
 | 
			
		||||
 | 
			
		||||
	function createItem(account: misskey.entities.UserDetailed) {
 | 
			
		||||
		return {
 | 
			
		||||
			type: 'user',
 | 
			
		||||
			user: account,
 | 
			
		||||
			active: opts.active != null ? opts.active === account.id : false,
 | 
			
		||||
			action: () => {
 | 
			
		||||
				if (opts.onChoose) {
 | 
			
		||||
					opts.onChoose(account);
 | 
			
		||||
				} else {
 | 
			
		||||
					switchAccount(account);
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const accountItemPromises = storedAccounts.map(a => new Promise(res => {
 | 
			
		||||
		accountsPromise.then(accounts => {
 | 
			
		||||
			const account = accounts.find(x => x.id === a.id);
 | 
			
		||||
			if (account == null) return res(null);
 | 
			
		||||
			res({
 | 
			
		||||
				type: 'user',
 | 
			
		||||
				user: account,
 | 
			
		||||
				action: () => { switchAccount(account); }
 | 
			
		||||
			});
 | 
			
		||||
			res(createItem(account));
 | 
			
		||||
		});
 | 
			
		||||
	}));
 | 
			
		||||
 | 
			
		||||
	popupMenu([...[{
 | 
			
		||||
		type: 'link',
 | 
			
		||||
		text: i18n.locale.profile,
 | 
			
		||||
		to: `/@${ $i.username }`,
 | 
			
		||||
		avatar: $i,
 | 
			
		||||
	}, null, ...accountItemPromises, {
 | 
			
		||||
		icon: 'fas fa-plus',
 | 
			
		||||
		text: i18n.locale.addAccount,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			popupMenu([{
 | 
			
		||||
				text: i18n.locale.existingAccount,
 | 
			
		||||
				action: () => { showSigninDialog(); },
 | 
			
		||||
			}, {
 | 
			
		||||
				text: i18n.locale.createAccount,
 | 
			
		||||
				action: () => { createAccount(); },
 | 
			
		||||
			}], ev.currentTarget || ev.target);
 | 
			
		||||
		},
 | 
			
		||||
	}, {
 | 
			
		||||
		type: 'link',
 | 
			
		||||
		icon: 'fas fa-users',
 | 
			
		||||
		text: i18n.locale.manageAccounts,
 | 
			
		||||
		to: `/settings/accounts`,
 | 
			
		||||
	}]], ev.currentTarget || ev.target, {
 | 
			
		||||
		align: 'left'
 | 
			
		||||
	});
 | 
			
		||||
	if (opts.withExtraOperation) {
 | 
			
		||||
		popupMenu([...[{
 | 
			
		||||
			type: 'link',
 | 
			
		||||
			text: i18n.locale.profile,
 | 
			
		||||
			to: `/@${ $i.username }`,
 | 
			
		||||
			avatar: $i,
 | 
			
		||||
		}, null, ...(opts.includeCurrentAccount ? [createItem($i)] : []), ...accountItemPromises, {
 | 
			
		||||
			icon: 'fas fa-plus',
 | 
			
		||||
			text: i18n.locale.addAccount,
 | 
			
		||||
			action: () => {
 | 
			
		||||
				popupMenu([{
 | 
			
		||||
					text: i18n.locale.existingAccount,
 | 
			
		||||
					action: () => { showSigninDialog(); },
 | 
			
		||||
				}, {
 | 
			
		||||
					text: i18n.locale.createAccount,
 | 
			
		||||
					action: () => { createAccount(); },
 | 
			
		||||
				}], ev.currentTarget || ev.target);
 | 
			
		||||
			},
 | 
			
		||||
		}, {
 | 
			
		||||
			type: 'link',
 | 
			
		||||
			icon: 'fas fa-users',
 | 
			
		||||
			text: i18n.locale.manageAccounts,
 | 
			
		||||
			to: `/settings/accounts`,
 | 
			
		||||
		}]], ev.currentTarget || ev.target, {
 | 
			
		||||
			align: 'left'
 | 
			
		||||
		});
 | 
			
		||||
	} else {
 | 
			
		||||
		popupMenu([...(opts.includeCurrentAccount ? [createItem($i)] : []), ...accountItemPromises], ev.currentTarget || ev.target, {
 | 
			
		||||
			align: 'left'
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,9 @@
 | 
			
		||||
>
 | 
			
		||||
	<header>
 | 
			
		||||
		<button v-if="!fixed" class="cancel _button" @click="cancel"><i class="fas fa-times"></i></button>
 | 
			
		||||
		<button v-click-anime class="account _button" @click="openAccountMenu">
 | 
			
		||||
			<MkAvatar :user="postAccount ?? $i" class="avatar"/>
 | 
			
		||||
		</button>
 | 
			
		||||
		<div>
 | 
			
		||||
			<span class="text-count" :class="{ over: textLength > maxTextLength }">{{ maxTextLength - textLength }}</span>
 | 
			
		||||
			<span v-if="localOnly" class="local-only"><i class="fas fa-biohazard"></i></span>
 | 
			
		||||
@@ -83,7 +86,7 @@ import { throttle } from 'throttle-debounce';
 | 
			
		||||
import MkInfo from '@/components/ui/info.vue';
 | 
			
		||||
import { i18n } from '@/i18n';
 | 
			
		||||
import { instance } from '@/instance';
 | 
			
		||||
import { $i } from '@/account';
 | 
			
		||||
import { $i, getAccounts, openAccountMenu as openAccountMenu_ } from '@/account';
 | 
			
		||||
 | 
			
		||||
const modal = inject('modal');
 | 
			
		||||
 | 
			
		||||
@@ -553,8 +556,15 @@ async function post() {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let token = undefined;
 | 
			
		||||
 | 
			
		||||
	if (postAccount) {
 | 
			
		||||
		const storedAccounts = await getAccounts();
 | 
			
		||||
		token = storedAccounts.find(x => x.id === postAccount.id)?.token;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	posting = true;
 | 
			
		||||
	os.api('notes/create', data).then(() => {
 | 
			
		||||
	os.api('notes/create', data, token).then(() => {
 | 
			
		||||
		clear();
 | 
			
		||||
		nextTick(() => {
 | 
			
		||||
			deleteDraft();
 | 
			
		||||
@@ -585,7 +595,7 @@ function insertMention() {
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function insertEmoji(ev) {
 | 
			
		||||
async function insertEmoji(ev: MouseEvent) {
 | 
			
		||||
	os.openEmojiPicker(ev.currentTarget || ev.target, {}, textareaEl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -602,6 +612,23 @@ function showActions(ev) {
 | 
			
		||||
	})), ev.currentTarget || ev.target);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let postAccount = $ref<misskey.entities.UserDetailed | null>(null);
 | 
			
		||||
 | 
			
		||||
function openAccountMenu(ev: MouseEvent) {
 | 
			
		||||
	openAccountMenu_({
 | 
			
		||||
		withExtraOperation: false,
 | 
			
		||||
		includeCurrentAccount: true,
 | 
			
		||||
		active: postAccount != null ? postAccount.id : $i.id,
 | 
			
		||||
		onChoose: (account) => {
 | 
			
		||||
			if (account.id === $i.id) {
 | 
			
		||||
				postAccount = null;
 | 
			
		||||
			} else {
 | 
			
		||||
				postAccount = account;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
	}, ev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
	if (props.autofocus) {
 | 
			
		||||
		focus();
 | 
			
		||||
@@ -678,6 +705,19 @@ onMounted(() => {
 | 
			
		||||
			line-height: 66px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		> .account {
 | 
			
		||||
			height: 100%;
 | 
			
		||||
			aspect-ratio: 1/1;
 | 
			
		||||
			display: inline-flex;
 | 
			
		||||
			vertical-align: bottom;
 | 
			
		||||
 | 
			
		||||
			> .avatar {
 | 
			
		||||
				width: 28px;
 | 
			
		||||
				height: 28px;
 | 
			
		||||
				margin: auto;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		> div {
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
			<span>{{ item.text }}</span>
 | 
			
		||||
			<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span>
 | 
			
		||||
		</a>
 | 
			
		||||
		<button v-else-if="item.type === 'user'" :tabindex="i" class="_button item" @click="clicked(item.action, $event)">
 | 
			
		||||
		<button v-else-if="item.type === 'user'" :tabindex="i" class="_button item" :class="{ active: item.active }" :disabled="item.active" @click="clicked(item.action, $event)">
 | 
			
		||||
			<MkAvatar :user="item.user" class="avatar"/><MkUserName :user="item.user"/>
 | 
			
		||||
			<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span>
 | 
			
		||||
		</button>
 | 
			
		||||
 
 | 
			
		||||
@@ -61,7 +61,11 @@ export default defineComponent({
 | 
			
		||||
			otherMenuItemIndicated,
 | 
			
		||||
			post: os.post,
 | 
			
		||||
			search,
 | 
			
		||||
			openAccountMenu,
 | 
			
		||||
			openAccountMenu:(ev) => {
 | 
			
		||||
				openAccountMenu({
 | 
			
		||||
					withExtraOperation: true,
 | 
			
		||||
				}, ev);
 | 
			
		||||
			},
 | 
			
		||||
			more: () => {
 | 
			
		||||
				os.popup(import('@/components/launch-pad.vue'), {}, {
 | 
			
		||||
				}, 'closed');
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,11 @@ export default defineComponent({
 | 
			
		||||
			iconOnly,
 | 
			
		||||
			post: os.post,
 | 
			
		||||
			search,
 | 
			
		||||
			openAccountMenu,
 | 
			
		||||
			openAccountMenu:(ev) => {
 | 
			
		||||
				openAccountMenu({
 | 
			
		||||
					withExtraOperation: true,
 | 
			
		||||
				}, ev);
 | 
			
		||||
			},
 | 
			
		||||
			more: () => {
 | 
			
		||||
				os.popup(import('@/components/launch-pad.vue'), {}, {
 | 
			
		||||
				}, 'closed');
 | 
			
		||||
 
 | 
			
		||||
@@ -105,7 +105,11 @@ export default defineComponent({
 | 
			
		||||
			}, 'closed');
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		openAccountMenu,
 | 
			
		||||
		openAccountMenu:(ev) => {
 | 
			
		||||
			openAccountMenu({
 | 
			
		||||
				withExtraOperation: true,
 | 
			
		||||
			}, ev);
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -125,7 +125,11 @@ export default defineComponent({
 | 
			
		||||
			}, 'closed');
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		openAccountMenu,
 | 
			
		||||
		openAccountMenu:(ev) => {
 | 
			
		||||
			openAccountMenu({
 | 
			
		||||
				withExtraOperation: true,
 | 
			
		||||
			}, ev);
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user