Skip to content

Commit

Permalink
✨ 改进模态窗口 (#199)
Browse files Browse the repository at this point in the history
  • Loading branch information
A-kirami authored Aug 1, 2024
1 parent b6e035c commit 1273024
Show file tree
Hide file tree
Showing 16 changed files with 1,181 additions and 1,054 deletions.
1,970 changes: 991 additions & 979 deletions src/auto-imports.d.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ declare module 'vue' {
Input: typeof import('./components/ui/input/Input.vue')['default']
Label: typeof import('./components/ui/label/Label.vue')['default']
MemberEditFormDialog: typeof import('./components/chat/MemberEditFormDialog.vue')['default']
ModalWindow: typeof import('./components/ModalWindow.vue')['default']
RadioGroup: typeof import('./components/ui/radio-group/RadioGroup.vue')['default']
RadioGroupItem: typeof import('./components/ui/radio-group/RadioGroupItem.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
Expand Down
10 changes: 2 additions & 8 deletions src/components/AppSidebarManageButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { check } from '@tauri-apps/plugin-updater'
import { SlidersHorizontal, Info, Bolt, Terminal, RefreshCw } from 'lucide-vue-next'
import { toast } from 'vue-sonner'
import type { Update } from '@tauri-apps/plugin-updater'
import { github } from '~build/git'
import { isRelease } from '~build/meta'
Expand Down Expand Up @@ -36,16 +34,13 @@ async function openAbout() {
let commandOpen = $ref(false)
let updateOpen = $ref(false)
let updateInfo = $ref<Update>()
const modal = useModalStore()
async function manualCheckUpdate() {
try {
const update = await check()
if (update?.available) {
updateInfo = update
updateOpen = true
modal.openModal('checkUpdate', { updateInfo: update })
} else {
toast.success('', { description: '当前已是最新版本,无需更新' })
}
Expand Down Expand Up @@ -93,5 +88,4 @@ const isDev = import.meta.env.DEV
</DropdownMenuContent>
</DropdownMenu>
<AppCommand v-model:open="commandOpen" />
<CheckUpdateDialog v-if="updateInfo" v-model:open="updateOpen" :update-info="updateInfo" />
</template>
49 changes: 27 additions & 22 deletions src/components/AppSidebarUserAvatar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,34 @@ defineOptions({
})
const state = useStateStore()
const modal = useModalStore()
function openUserManage() {
modal.openModal('userManage')
}
</script>

<template>
<UserManageDialog>
<div v-if="state.user" class="relative cursor-pointer" v-bind="$attrs">
<Avatar class="size-9">
<AvatarImage :src="state.user.avatar" alt="user avatar" />
<AvatarFallback>{{ state.user.name }}</AvatarFallback>
</Avatar>
<span
class="absolute bottom-0.5 size-4 border-2 border-transparent rounded-full bg-clip-padding -right-1"
:class="[state.isConnected ? 'bg-emerald-400' : 'bg-rose-400']"
></span>
</div>
<Button
v-else
variant="outline"
size="icon"
class="size-9 rounded-full ring-2 ring-gray-200 dark:ring-gray-700"
hover:svg="rotate-90 scale-110 stroke-2"
v-bind="$attrs"
>
<Plus class="rotate-45 stroke-1.5 text-gray-600 transition-transform" />
</Button>
</UserManageDialog>
<div v-if="state.user" class="relative cursor-pointer" v-bind="$attrs" @click="openUserManage">
<Avatar class="size-9">
<AvatarImage :src="state.user.avatar" alt="user avatar" />
<AvatarFallback>{{ state.user.name }}</AvatarFallback>
</Avatar>
<span
class="absolute bottom-0.5 size-4 border-2 border-transparent rounded-full bg-clip-padding -right-1"
:class="[state.isConnected ? 'bg-emerald-400' : 'bg-rose-400']"
></span>
</div>
<Button
v-else
variant="outline"
size="icon"
class="size-9 rounded-full ring-2 ring-gray-200 dark:ring-gray-700"
hover:svg="rotate-90 scale-110 stroke-2"
v-bind="$attrs"
@click="openUserManage"
>
<Plus class="rotate-45 stroke-1.5 text-gray-600 transition-transform" />
</Button>
</template>
11 changes: 11 additions & 0 deletions src/components/ModalWindow.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
const modal = useModalStore()
</script>

<template>
<component
:is="modal.modalState?.component"
v-bind="modal.modalState?.props"
v-model:open="modal.modalOpen"
></component>
</template>
4 changes: 3 additions & 1 deletion src/components/UserManageDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@ async function assignUser(type: 'user' | 'bot', uid: string) {
}
await db.users.update(uid, { lastUseTime: getTimestamp() })
}
const open = $(defineModel('open', { default: false }))
</script>

<template>
<Dialog>
<Dialog v-model:open="open">
<DialogTrigger as-child>
<slot></slot>
</DialogTrigger>
Expand Down
20 changes: 10 additions & 10 deletions src/components/chat/ChatBoxHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import { liveQuery } from 'dexie'
import { EllipsisVertical, UserRoundPlus, LogIn, LogOut, Pencil, UserRoundMinus } from 'lucide-vue-next'
import { Behav } from '~/adapter/behav'
import GroupEditFormDialog from '~/components/chat/GroupEditFormDialog.vue'
import UserEditFormDialog from '~/components/chat/UserEditFormDialog.vue'
const behav = new Behav()
Expand Down Expand Up @@ -48,9 +46,13 @@ async function handleFriend() {
}
}
const EditDialog = $computed(() => {
return state.chatTarget?.type === 'group' ? GroupEditFormDialog : UserEditFormDialog
})
const modal = useModalStore()
function openEditDialog() {
modal.openModal(state.chatTarget?.type === 'group' ? 'groupEdit' : 'userEdit', {
targetId: state.chatTarget!.id,
})
}
</script>

<template>
Expand All @@ -64,11 +66,9 @@ const EditDialog = $computed(() => {
<TooltipProvider :delay-duration="1500">
<Tooltip>
<TooltipTrigger>
<component :is="EditDialog" v-if="state.chatTarget" :target-id="state.chatTarget?.id">
<Button variant="ghost" size="icon">
<Pencil class="size-5 stroke-1.5" />
</Button>
</component>
<Button variant="ghost" size="icon" @click="openEditDialog">
<Pencil class="size-5 stroke-1.5" />
</Button>
</TooltipTrigger>
<TooltipContent side="bottom" class="px-2">
<p class="text-xs">{{ state.chatTarget?.type === 'group' ? '编辑群组' : '编辑用户' }}</p>
Expand Down
10 changes: 7 additions & 3 deletions src/components/chat/ChatContactsList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ watchDebounced(
},
{ immediate: true, debounce: 50, maxWait: 100 }
)
const modal = useModalStore()
function openUserManage() {
modal.openModal('userManage')
}
</script>

<template>
Expand All @@ -69,8 +75,6 @@ watchDebounced(
</RouterLink>
</li>
</ul>
<UserManageDialog v-else>
<Button class="h-8 w-full">管理机器人</Button>
</UserManageDialog>
<Button v-else class="h-8 w-full" @click="openUserManage">管理机器人</Button>
</OverlayScrollbarsComponent>
</template>
55 changes: 31 additions & 24 deletions src/components/chat/ChatContactsListItemMenu.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<script setup lang="tsx">
<script setup lang="ts">
import { Pin, PinOff, Pencil, Trash2 } from 'lucide-vue-next'
import { toast } from 'vue-sonner'
import GroupEditFormDialog from '~/components/chat/GroupEditFormDialog.vue'
import UserEditFormDialog from '~/components/chat/UserEditFormDialog.vue'
import type { Contact } from '~/types'
const { contact, isPinned } = $defineProps<{
Expand All @@ -22,21 +19,30 @@ function handlePin() {
}
}
const editOpen = $ref(false)
const deleteOpen = $ref(false)
async function deleteGroup() {
await db.groups.delete(contact.id)
const isGroup = contact.type === 'group'
const contactText = isGroup ? '群组' : '角色'
async function deleteContact() {
const contactDb = isGroup ? db.groups : db.users
await contactDb.delete(contact.id)
if (state.chatTarget?.id === contact.id) {
state.chatTarget = null
}
toast.success('', { description: '删除群组成功' })
if (!isGroup) {
state.bot = null
}
toast.success('', { description: `删除${contactText}成功` })
}
const EditFormDialog = () => {
const EditComponent = contact.type === 'group' ? GroupEditFormDialog : UserEditFormDialog
return <EditComponent v-model:open={editOpen} targetId={contact.id} />
const modal = useModalStore()
function openEditDialog() {
modal.openModal(isGroup ? 'groupEdit' : 'userEdit', {
targetId: contact.id,
})
}
</script>

Expand All @@ -46,15 +52,17 @@ const EditFormDialog = () => {
<slot></slot>
</ContextMenuTrigger>
<ContextMenuContent class="text-sm space-y-1">
<ContextMenuItem v-if="isPinned" class="flex items-center gap-2 px-2 py-1 text-gray-500" @click="handlePin">
<PinOff class="size-4 stroke-1" />
<span>取消置顶</span>
</ContextMenuItem>
<ContextMenuItem v-else class="flex items-center gap-2 px-2 py-1 text-gray-500" @click="handlePin">
<Pin class="size-4 stroke-1" />
<span>置顶</span>
</ContextMenuItem>
<ContextMenuItem class="flex items-center gap-2 px-2 py-1 text-gray-500" @click="editOpen = true">
<template v-if="isGroup">
<ContextMenuItem v-if="isPinned" class="flex items-center gap-2 px-2 py-1 text-gray-500" @click="handlePin">
<PinOff class="size-4 stroke-1" />
<span>取消置顶</span>
</ContextMenuItem>
<ContextMenuItem v-else class="flex items-center gap-2 px-2 py-1 text-gray-500" @click="handlePin">
<Pin class="size-4 stroke-1" />
<span>置顶</span>
</ContextMenuItem>
</template>
<ContextMenuItem class="flex items-center gap-2 px-2 py-1 text-gray-500" @click="openEditDialog">
<Pencil class="size-4 stroke-1" />
<span>编辑</span>
</ContextMenuItem>
Expand All @@ -64,16 +72,15 @@ const EditFormDialog = () => {
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
<EditFormDialog />
<AlertDialog v-model:open="deleteOpen">
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>删除此联系人</AlertDialogTitle>
<AlertDialogTitle>删除此{{ contactText }}</AlertDialogTitle>
<AlertDialogDescription>删除后将无法恢复,确定要删除吗?</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>取消</AlertDialogCancel>
<AlertDialogAction variant="destructive" @click="deleteGroup">确认</AlertDialogAction>
<AlertDialogAction variant="destructive" @click="deleteContact">确认</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
Expand Down
15 changes: 14 additions & 1 deletion src/components/chat/ChatDetailsInfoGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ const getMemberRole = $computed(() => (id: string) => {
}
return member.role
})
const state = useStateStore()
const modal = useModalStore()
function openMemberEdit(member: Contact) {
modal.openModal('memberEdit', {
groupId: state.chatTarget!.id,
userId: member.id,
userName: member.name,
})
}
</script>

<template>
Expand All @@ -21,11 +33,12 @@ const getMemberRole = $computed(() => (id: string) => {
<Tooltip v-for="member in memberContacts.slice(0, MAX_AVATAR_COUNT)" :key="member.id">
<TooltipTrigger as-child>
<Avatar
class="size-8 ring-2 ring-white hover:z-1"
class="size-8 cursor-pointer ring-2 ring-white hover:z-1"
:class="{
'ring-amber-200': getMemberRole(member.id) === 'owner',
'ring-sky-200': getMemberRole(member.id) === 'admin',
}"
@click="openMemberEdit(member)"
>
<AvatarImage :src="member.avatar" alt="member avatar" />
<AvatarFallback>{{ member.name }}</AvatarFallback>
Expand Down
8 changes: 6 additions & 2 deletions src/components/chat/GroupEditFormDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,16 @@ async function deleteGroup() {
toast.success('', { description: '删除群组成功' })
}

onUpdated(async () => {
async function resetForm() {
const group = await db.groups.get(targetId)
if (formRef && group) {
formRef.resetForm({ values: { name: group.name } })
}
})
}

onMounted(resetForm)

onUpdated(resetForm)
</script>

<template>
Expand Down
8 changes: 6 additions & 2 deletions src/components/chat/MemberEditFormDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@ async function removeMember() {
toast.success('', { description: '移除成员成功' })
}

onUpdated(async () => {
async function resetForm() {
const member = await db.members.get([groupId, userId])
if (formRef && member) {
formRef.resetForm({ values: { card: member.card, role: member.role } })
}
})
}

onMounted(resetForm)

onUpdated(resetForm)
</script>

<template>
Expand Down
8 changes: 6 additions & 2 deletions src/components/chat/UserEditFormDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,16 @@ async function deleteUser() {
toast.success('', { description: '删除角色成功' })
}

onUpdated(async () => {
async function resetForm() {
const user = await db.users.get(targetId)
if (formRef && user) {
formRef.resetForm({ values: { name: user.name } })
}
})
}

onMounted(resetForm)

onUpdated(resetForm)
</script>

<template>
Expand Down
1 change: 1 addition & 0 deletions src/layouts/default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ onMounted(async () => {
</RouterView>
</div>
<Toaster class="pointer-events-auto" />
<ModalWindow />
</template>

<style module>
Expand Down
Loading

0 comments on commit 1273024

Please sign in to comment.