list multiple select

This commit is contained in:
mattyatea 2024-01-14 03:39:43 +09:00
parent 1dce38dfed
commit 693efb99a0
3 changed files with 41 additions and 15 deletions

View File

@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkModalWindow <MkModalWindow
ref="dialogEl" ref="dialogEl"
:withOkButton="true" :withOkButton="true"
:okButtonDisabled="selected == null" :okButtonDisabled="(!selected && multipleSelected.length < 1)"
@click="cancel()" @click="cancel()"
@close="cancel()" @close="cancel()"
@ok="ok()" @ok="ok()"
@ -27,9 +27,10 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkInput> </MkInput>
</FormSplit> </FormSplit>
</div> </div>
<div v-if="username != '' || host != ''" :class="[$style.result, { [$style.hit]: users.length > 0 }]"> <div v-if="username != '' || host != ''" :class="[$style.result, { [$style.hit]: users.length > 0 }]">
<div v-if="users.length > 0" :class="$style.users"> <div v-if="users.length > 0" :class="$style.users">
<div v-for="user in users" :key="user.id" class="_button" :class="[$style.user, { [$style.selected]: selected && selected.id === user.id }]" @click="selected = user" @dblclick="ok()"> <div v-for="user in users" :key="user.id" class="_button" :class="[$style.user, { [$style.selected]: selected && selected.id === user.id || multipleSelected.includes(user)}]" @click="multiple ? (multipleSelected.includes(user) ? multipleSelected.splice(multipleSelected.indexOf(user), 1) : multipleSelected.push(user)) : selected = user" @dblclick="ok()">
<MkAvatar :user="user" :class="$style.avatar" indicator/> <MkAvatar :user="user" :class="$style.avatar" indicator/>
<div :class="$style.userBody"> <div :class="$style.userBody">
<MkUserName :user="user" :class="$style.userName"/> <MkUserName :user="user" :class="$style.userName"/>
@ -43,7 +44,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div> </div>
<div v-if="username == '' && host == ''" :class="$style.recent"> <div v-if="username == '' && host == ''" :class="$style.recent">
<div :class="$style.users"> <div :class="$style.users">
<div v-for="user in recentUsers" :key="user.id" class="_button" :class="[$style.user, { [$style.selected]: selected && selected.id === user.id }]" @click="selected = user" @dblclick="ok()"> <div v-for="user in recentUsers" :key="user.id" class="_button" :class="[$style.user, { [$style.selected]: selected && selected.id === user.id || multipleSelected.includes(user) }]" @click="multiple ? (multipleSelected.includes(user) ? multipleSelected.splice(multipleSelected.indexOf(user), 1) : multipleSelected.push(user)) : selected = user" @dblclick="ok()">
<MkAvatar :user="user" :class="$style.avatar" indicator/> <MkAvatar :user="user" :class="$style.avatar" indicator/>
<div :class="$style.userBody"> <div :class="$style.userBody">
<MkUserName :user="user" :class="$style.userName"/> <MkUserName :user="user" :class="$style.userName"/>
@ -67,6 +68,7 @@ import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { $i } from '@/account.js'; import { $i } from '@/account.js';
import { hostname } from '@/config.js'; import { hostname } from '@/config.js';
import { multipleSelectUser } from '@/os.js';
const emit = defineEmits<{ const emit = defineEmits<{
(ev: 'ok', selected: Misskey.entities.UserDetailed): void; (ev: 'ok', selected: Misskey.entities.UserDetailed): void;
@ -76,6 +78,7 @@ const emit = defineEmits<{
const props = defineProps<{ const props = defineProps<{
includeSelf?: boolean; includeSelf?: boolean;
multiple?: boolean;
}>(); }>();
const username = ref(''); const username = ref('');
@ -83,6 +86,7 @@ const host = ref('');
const users = ref<Misskey.entities.UserDetailed[]>([]); const users = ref<Misskey.entities.UserDetailed[]>([]);
const recentUsers = ref<Misskey.entities.UserDetailed[]>([]); const recentUsers = ref<Misskey.entities.UserDetailed[]>([]);
const selected = ref<Misskey.entities.UserDetailed | null>(null); const selected = ref<Misskey.entities.UserDetailed | null>(null);
const multipleSelected = ref<Misskey.entities.UserDetailed[]>([]);
const dialogEl = ref(); const dialogEl = ref();
const search = () => { const search = () => {
@ -101,11 +105,12 @@ const search = () => {
}; };
const ok = () => { const ok = () => {
if (selected.value == null) return; if ((!selected.value && multipleSelected.value.length < 1)) return;
emit('ok', selected.value); emit('ok', selected.value ?? multipleSelected.value);
dialogEl.value.close(); dialogEl.value.close();
// 使 // 使
if (multipleSelected.value.length < 0) return;
let recents = defaultStore.state.recentlyUsedUsers; let recents = defaultStore.state.recentlyUsedUsers;
recents = recents.filter(x => x !== selected.value.id); recents = recents.filter(x => x !== selected.value.id);
recents.unshift(selected.value.id); recents.unshift(selected.value.id);

View File

@ -24,7 +24,7 @@ import MkContextMenu from '@/components/MkContextMenu.vue';
import { MenuItem } from '@/types/menu.js'; import { MenuItem } from '@/types/menu.js';
import copyToClipboard from '@/scripts/copy-to-clipboard.js'; import copyToClipboard from '@/scripts/copy-to-clipboard.js';
import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
import MkSwitch from "@/components/MkSwitch.vue"; import MkSwitch from '@/components/MkSwitch.vue';
export const openingWindowsCount = ref(0); export const openingWindowsCount = ref(0);
@ -220,7 +220,7 @@ export function switch1(props: {
text?: string | null; text?: string | null;
okText?: string; okText?: string;
cancelText?: string; cancelText?: string;
}): Promise<{ canceled: boolean , result: boolean }> { }): Promise<{ canceled: boolean, result: boolean }> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
popup(MkDialog, { popup(MkDialog, {
...props, ...props,
@ -437,7 +437,20 @@ export function form(title, form) {
}); });
} }
export async function selectUser(opts: { includeSelf?: boolean } = {}) { export async function selectUser(opts: { includeSelf?: boolean, multiple?: boolean, } = {}) {
return new Promise((resolve, reject) => {
popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), {
includeSelf: opts.includeSelf,
multiple: opts.multiple,
}, {
ok: user => {
resolve(user);
},
}, 'closed');
});
}
export async function multipleSelectUser(opts: { includeSelf?: boolean } = {}) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), { popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), {
includeSelf: opts.includeSelf, includeSelf: opts.includeSelf,

View File

@ -104,14 +104,22 @@ function fetchList() {
} }
function addUser() { function addUser() {
os.selectUser().then(user => { os.selectUser( { multiple: true }).then(user => {
if (!list.value) return; if (!list.value) return;
os.apiWithDialog('users/lists/push', { if (Array.isArray(user)) {
listId: list.value.id, user.forEach(u => {
userId: user.id, misskeyApi('users/lists/push', {
}).then(() => { listId: list.value.id,
paginationEl.value.reload(); userId: u.id,
}); });
});
} else if (typeof user === 'string') {
os.apiWithDialog('users/lists/push', {
listId: list.value.id,
userId: user.id,
});
}
paginationEl.value.reload();
}); });
} }