chore: ⬆️ Upgrade dependencies

This commit is contained in:
Jesse Wierzbinski 2025-03-27 22:20:04 +01:00
parent 3e28801709
commit 7649ecfb80
No known key found for this signature in database
14 changed files with 947 additions and 627 deletions

View file

@ -1,7 +1,15 @@
<template>
<DropdownMenu>
<Card
:class="cn('grid hover:cursor-pointer gap-4 items-center p-4', canEdit ? 'grid-cols-[auto,1fr,auto]' : 'grid-cols-[auto,1fr]')">
:class="
cn(
'grid hover:cursor-pointer gap-4 items-center p-4',
canEdit
? 'grid-cols-[auto,1fr,auto]'
: 'grid-cols-[auto,1fr]'
)
"
>
<Avatar shape="square">
<AvatarImage :src="emoji.url" />
</Avatar>
@ -10,7 +18,11 @@
{{ emoji.shortcode }}
</CardTitle>
<CardDescription>
{{ emoji.global ? m.real_tame_moose_greet() : m.witty_heroic_trout_cry() }}
{{
emoji.global
? m.real_tame_moose_greet()
: m.witty_heroic_trout_cry()
}}
</CardDescription>
</CardHeader>
<CardFooter class="p-0" v-if="canEdit">
@ -45,12 +57,13 @@ import { type Emoji, RolePermission } from "@versia/client/types";
import { Delete, Ellipsis, TextCursorInput } from "lucide-vue-next";
import { toast } from "vue-sonner";
import { confirmModalService } from "~/components/modals/composable";
import { Avatar } from "~/components/ui/avatar";
import { Avatar, AvatarImage } from "~/components/ui/avatar";
import { Button } from "~/components/ui/button";
import {
Card,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import {
@ -94,7 +107,7 @@ const editName = async () => {
toast.success(m.gaudy_lime_bison_adore());
identity.value.emojis = identity.value.emojis.map((e) =>
e.id === emoji.id ? data : e,
e.id === emoji.id ? data : e
);
} catch {
toast.dismiss(id);
@ -121,7 +134,7 @@ const _delete = async () => {
toast.success(m.crisp_whole_canary_tear());
identity.value.emojis = identity.value.emojis.filter(
(e) => e.id !== emoji.id,
(e) => e.id !== emoji.id
);
} catch {
toast.dismiss(id);

View file

@ -11,18 +11,37 @@
{{ m.frail_great_marten_pet() }}
</DialogDescription>
<form class="p-4 grid gap-6" @submit="submit">
<div v-if="values.image" class="flex items-center justify-around *:size-20 *:p-2 *:rounded *:border *:shadow">
<div
v-if="values.image"
class="flex items-center justify-around *:size-20 *:p-2 *:rounded *:border *:shadow"
>
<div class="bg-background">
<img class="h-full object-cover" :src="createObjectURL(values.image as File)" :alt="values.alt" />
<img
class="h-full object-cover"
:src="createObjectURL(values.image as File)"
:alt="values.alt"
/>
</div>
<div class="bg-zinc-700">
<img class="h-full object-cover" :src="createObjectURL(values.image as File)" :alt="values.alt" />
<img
class="h-full object-cover"
:src="createObjectURL(values.image as File)"
:alt="values.alt"
/>
</div>
<div class="bg-zinc-400">
<img class="h-full object-cover" :src="createObjectURL(values.image as File)" :alt="values.alt" />
<img
class="h-full object-cover"
:src="createObjectURL(values.image as File)"
:alt="values.alt"
/>
</div>
<div class="bg-foreground">
<img class="h-full object-cover" :src="createObjectURL(values.image as File)" :alt="values.alt" />
<img
class="h-full object-cover"
:src="createObjectURL(values.image as File)"
:alt="values.alt"
/>
</div>
</div>
@ -32,13 +51,19 @@
{{ m.active_direct_bear_compose() }}
</FormLabel>
<FormControl>
<Input type="file" accept="image/*" @change="(e: any) => {
<Input
type="file"
accept="image/*"
@change="(e: any) => {
handleChange(e);
if (!values.shortcode) {
setFieldValue('shortcode', e.target.files[0].name.replace(/\.[^/.]+$/, ''));
}
}" @blur="handleBlur" :disabled="isSubmitting" />
}"
@blur="handleBlur"
:disabled="isSubmitting"
/>
</FormControl>
<FormDescription>
{{ m.lime_late_millipede_urge() }}
@ -53,7 +78,10 @@
{{ m.happy_mild_fox_gleam() }}
</FormLabel>
<FormControl>
<Input v-bind="componentField" :disabled="isSubmitting" />
<Input
v-bind="componentField"
:disabled="isSubmitting"
/>
</FormControl>
<FormDescription>
{{ m.glad_day_kestrel_amaze() }}
@ -68,7 +96,10 @@
{{ m.short_cute_jackdaw_comfort() }}
</FormLabel>
<FormControl>
<Input v-bind="componentField" :disabled="isSubmitting" />
<Input
v-bind="componentField"
:disabled="isSubmitting"
/>
</FormControl>
<FormMessage />
</FormItem>
@ -80,7 +111,11 @@
{{ m.watery_left_shrimp_bless() }}
</FormLabel>
<FormControl>
<Textarea rows="2" v-bind="componentField" :disabled="isSubmitting" />
<Textarea
rows="2"
v-bind="componentField"
:disabled="isSubmitting"
/>
</FormControl>
<FormDescription>
{{ m.weird_fun_jurgen_arise() }}
@ -89,9 +124,15 @@
</FormItem>
</FormField>
<FormField v-slot="{ componentField, value, handleChange }" v-if="hasEmojiAdmin" name="global"
:as="Card">
<FormItem class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
<FormField
v-slot="{ componentField, value, handleChange }"
v-if="hasEmojiAdmin"
name="global"
:as="Card"
>
<FormItem
class="grid grid-cols-[1fr,auto] items-center p-6 gap-2"
>
<CardHeader class="space-y-0.5 p-0">
<FormLabel :as="CardTitle">
{{ m.pink_sharp_carp_work() }}
@ -101,7 +142,12 @@
</CardDescription>
</CardHeader>
<FormControl>
<Switch :checked="value" @update:checked="handleChange" v-bind="componentField" :disabled="isSubmitting" />
<Switch
:checked="value"
@update:checked="handleChange"
v-bind="componentField"
:disabled="isSubmitting"
/>
</FormControl>
<FormMessage />
</FormItem>
@ -113,7 +159,11 @@
{{ m.soft_bold_ant_attend() }}
</Button>
</DialogClose>
<Button type="submit" variant="default" :disabled="isSubmitting">
<Button
type="submit"
variant="default"
:disabled="isSubmitting"
>
{{ m.flat_safe_haddock_gaze() }}
</Button>
</DialogFooter>
@ -129,7 +179,12 @@ import { useForm } from "vee-validate";
import { toast } from "vue-sonner";
import { z } from "zod";
import { Button } from "~/components/ui/button";
import { Card, CardTitle } from "~/components/ui/card";
import {
Card,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import {
Dialog,
DialogClose,
@ -147,6 +202,9 @@ import {
FormLabel,
FormMessage,
} from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import { Switch } from "~/components/ui/switch";
import { Textarea } from "~/components/ui/textarea";
import * as m from "~/paraglide/messages.js";
const open = ref(false);
@ -169,7 +227,7 @@ const formSchema = toTypedSchema(
count:
identity.value?.instance.configuration.emojis
.emoji_size_limit ?? Number.POSITIVE_INFINITY,
}),
})
),
shortcode: z
.string()
@ -182,7 +240,7 @@ const formSchema = toTypedSchema(
identity.value?.instance.configuration.emojis
.max_emoji_shortcode_characters ??
Number.POSITIVE_INFINITY,
}),
})
)
.regex(emojiValidator),
global: z.boolean().default(false),
@ -192,7 +250,7 @@ const formSchema = toTypedSchema(
64,
m.home_cool_orangutan_hug({
count: 64,
}),
})
)
.optional(),
alt: z
@ -206,10 +264,10 @@ const formSchema = toTypedSchema(
identity.value?.instance.configuration.emojis
.max_emoji_description_characters ??
Number.POSITIVE_INFINITY,
}),
})
)
.optional(),
}),
})
);
const { isSubmitting, handleSubmit, values, setFieldValue } = useForm({
validationSchema: formSchema,
@ -230,7 +288,7 @@ const submit = handleSubmit(async (values) => {
alt: values.alt,
category: values.category,
global: values.global,
},
}
);
toast.dismiss(id);

View file

@ -7,7 +7,12 @@
{{ m.bright_late_osprey_renew() }}
</FormLabel>
<FormControl>
<Input type="file" accept="image/*" @change="handleChange" @blur="handleBlur" />
<Input
type="file"
accept="image/*"
@change="handleChange"
@blur="handleBlur"
/>
</FormControl>
<FormDescription>
{{ m.great_level_lamb_sway() }}
@ -22,7 +27,11 @@
{{ m.safe_icy_bulldog_quell() }}
</FormLabel>
<FormControl>
<ImageUploader v-model:image="identity.account.avatar" @submit-file="file => setValue(file)" @submit-url="url => setValue(url)" />
<ImageUploader
v-model:image="identity.account.avatar"
@submit-file="(file) => setValue(file)"
@submit-url="(url) => setValue(url)"
/>
</FormControl>
<FormMessage />
</FormItem>
@ -80,21 +89,61 @@
</FormLabel>
<FormControl>
<div class="grid gap-4">
<div v-for="(field, index) in value" :key="index"
class="grid items-center grid-cols-[auto,repeat(3,minmax(0,1fr))] gap-2">
<Button variant="destructive" size="icon"
@click="handleChange([...value.slice(0, index), ...value.slice(index + 1)])">
<div
v-for="(field, index) in value"
:key="index"
class="grid items-center grid-cols-[auto,repeat(3,minmax(0,1fr))] gap-2"
>
<Button
variant="destructive"
size="icon"
@click="
handleChange([
...value.slice(0, index),
...value.slice(index + 1),
])
"
>
<Trash />
</Button>
<Input v-model="field.name" placeholder="Name" @update:model-value="e => {
handleChange([...value.slice(0, index), { name: e, value: field.value }, ...value.slice(index + 1)]);
}" />
<Input v-model="field.value" placeholder="Value" class="col-span-2" @update:model-value="e => {
handleChange([...value.slice(0, index), { name: field.name, value: e }, ...value.slice(index + 1)]);
}" />
<Input
v-model="field.name"
placeholder="Name"
@update:model-value="
(e) => {
handleChange([
...value.slice(0, index),
{ name: e, value: field.value },
...value.slice(index + 1),
]);
}
"
/>
<Input
v-model="field.value"
placeholder="Value"
class="col-span-2"
@update:model-value="
(e) => {
handleChange([
...value.slice(0, index),
{ name: field.name, value: e },
...value.slice(index + 1),
]);
}
"
/>
</div>
<Button type="button" variant="secondary"
@click="handleChange([...value, { name: '', value: '' }])">
<Button
type="button"
variant="secondary"
@click="
handleChange([
...value,
{ name: '', value: '' },
])
"
>
{{ m.front_north_eel_gulp() }}
</Button>
</div>
@ -103,8 +152,14 @@
</FormItem>
</FormField>
<FormField v-slot="{ componentField, value, handleChange }" name="bot" :as="Card">
<FormItem class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
<FormField
v-slot="{ componentField, value, handleChange }"
name="bot"
:as="Card"
>
<FormItem
class="grid grid-cols-[1fr,auto] items-center p-6 gap-2"
>
<CardHeader class="space-y-0.5 p-0">
<FormLabel :as="CardTitle">
{{ m.gaudy_each_opossum_play() }}
@ -114,14 +169,24 @@
</CardDescription>
</CardHeader>
<FormControl>
<Switch :checked="value" @update:checked="handleChange" v-bind="componentField" />
<Switch
:checked="value"
@update:checked="handleChange"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
<FormField v-slot="{ componentField, value, handleChange }" name="locked" :as="Card">
<FormItem class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
<FormField
v-slot="{ componentField, value, handleChange }"
name="locked"
:as="Card"
>
<FormItem
class="grid grid-cols-[1fr,auto] items-center p-6 gap-2"
>
<CardHeader class="space-y-0.5 p-0">
<FormLabel :as="CardTitle">
{{ m.dirty_moving_shark_emerge() }}
@ -131,14 +196,24 @@
</CardDescription>
</CardHeader>
<FormControl>
<Switch :checked="value" @update:checked="handleChange" v-bind="componentField" />
<Switch
:checked="value"
@update:checked="handleChange"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
<FormField v-slot="{ componentField, value, handleChange }" name="discoverable" :as="Card">
<FormItem class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
<FormField
v-slot="{ componentField, value, handleChange }"
name="discoverable"
:as="Card"
>
<FormItem
class="grid grid-cols-[1fr,auto] items-center p-6 gap-2"
>
<CardHeader class="space-y-0.5 p-0">
<FormLabel :as="CardTitle">
{{ m.red_vivid_cuckoo_spark() }}
@ -148,14 +223,21 @@
</CardDescription>
</CardHeader>
<FormControl>
<Switch :checked="value" @update:checked="handleChange" v-bind="componentField" />
<Switch
:checked="value"
@update:checked="handleChange"
v-bind="componentField"
/>
</FormControl>
<FormMessage />
</FormItem>
</FormField>
</form>
</Card>
<Profile :account="account" class="max-w-lg overflow-auto hidden xl:block" />
<Profile
:account="account"
class="max-w-lg overflow-auto hidden xl:block"
/>
</template>
<script lang="ts" setup>
@ -167,7 +249,12 @@ import { toast } from "vue-sonner";
import { z } from "zod";
import Profile from "~/components/profiles/profile.vue";
import { Button } from "~/components/ui/button";
import { Card, CardTitle } from "~/components/ui/card";
import {
Card,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import {
FormControl,
FormDescription,
@ -200,7 +287,7 @@ const formSchema = toTypedSchema(
m.civil_icy_ant_mend({
size: identity.value?.instance.configuration.accounts
.header_size_limit,
}),
})
)
.optional(),
avatar: z
@ -213,7 +300,7 @@ const formSchema = toTypedSchema(
m.zippy_caring_raven_edit({
size: identity.value?.instance.configuration.accounts
.avatar_size_limit,
}),
})
)
.or(z.string().url())
.optional(),
@ -221,26 +308,26 @@ const formSchema = toTypedSchema(
.string()
.max(
identity.value.instance.configuration.accounts
.max_displayname_characters,
.max_displayname_characters
),
username: z
.string()
.regex(/^[a-z0-9_-]+$/, m.still_upper_otter_dine())
.max(
identity.value.instance.configuration.accounts
.max_username_characters,
.max_username_characters
),
bio: z
.string()
.max(
identity.value.instance.configuration.accounts
.max_note_characters,
.max_note_characters
),
bot: z.boolean(),
locked: z.boolean(),
discoverable: z.boolean(),
fields: z.array(z.object({ name: z.string(), value: z.string() })),
}),
})
);
const form = useForm({
@ -280,8 +367,8 @@ const handleSubmit = form.handleSubmit(async (values) => {
// Can't compare two arrays directly in JS, so we need to check if all fields are the same
fields_attributes: values.fields.every((field) =>
account.value.source?.fields?.some(
(f) => f.name === field.name && f.value === field.value,
),
(f) => f.name === field.name && f.value === field.value
)
)
? undefined
: values.fields,
@ -300,8 +387,8 @@ const handleSubmit = form.handleSubmit(async (values) => {
try {
const { data } = await client.value.updateCredentials(
Object.fromEntries(
Object.entries(changedData).filter(([, v]) => v !== undefined),
),
Object.entries(changedData).filter(([, v]) => v !== undefined)
)
);
toast.dismiss(id);

View file

@ -1,10 +1,15 @@
<template>
<Dialog v-model:open="open">
<DialogTrigger :as-child="true">
<Button v-bind="$attrs" variant="ghost" class="h-fit w-fit p-0 m-0 relative group border overflow-hidden">
<Button
v-bind="$attrs"
variant="ghost"
class="h-fit w-fit p-0 m-0 relative group border overflow-hidden"
>
<Avatar size="lg" :src="image" :name="displayName" />
<div
class="absolute inset-0 bg-background/80 flex group-hover:opacity-100 opacity-0 duration-200 items-center justify-center">
class="absolute inset-0 bg-background/80 flex group-hover:opacity-100 opacity-0 duration-200 items-center justify-center"
>
<Upload />
</div>
</Button>
@ -17,7 +22,10 @@
{{ m.suave_broad_albatross_drop() }}
</DialogDescription>
<form class="p-4 grid gap-6" @submit="submit">
<Tabs default-value="upload" class="mt-2 data-[component=tabpanel]:*:mt-6">
<Tabs
default-value="upload"
class="mt-2 data-[component=tabpanel]:*:mt-6"
>
<TabsList class="w-full *:w-full">
<TabsTrigger value="upload">
{{ m.flat_safe_haddock_gaze() }}
@ -30,14 +38,22 @@
</TabsTrigger>
</TabsList>
<TabsContent value="upload">
<FormField v-slot="{ handleChange, handleBlur }" name="image">
<FormField
v-slot="{ handleChange, handleBlur }"
name="image"
>
<FormItem>
<FormLabel class="sr-only">
{{ m.flat_safe_haddock_gaze() }}
</FormLabel>
<FormControl>
<Input type="file" accept="image/*" @change="handleChange" @blur="handleBlur"
:disabled="isSubmitting" />
<Input
type="file"
accept="image/*"
@change="handleChange"
@blur="handleBlur"
:disabled="isSubmitting"
/>
</FormControl>
<FormDescription>
{{ m.lime_late_millipede_urge() }}
@ -47,38 +63,57 @@
</FormField>
</TabsContent>
<TabsContent value="gravatar">
<FormField v-slot="{ componentField, errors, value }" name="email" @update:model-value="async (value) => {
gravatarUrl = await emailToGravatar(value)
}">
<FormField
v-slot="{ componentField, value }"
name="email"
@update:model-value="
async (value) => {
gravatarUrl = await emailToGravatar(value);
}
"
>
<FormItem>
<FormLabel>
{{ m.lower_formal_kudu_lift() }}
</FormLabel>
<FormControl>
<Input v-bind="componentField" :disabled="isSubmitting"
placeholder="peter.griffin@fox.com" />
<Input
v-bind="componentField"
:disabled="isSubmitting"
placeholder="peter.griffin@fox.com"
/>
</FormControl>
<FormMessage />
<div v-if="value" class="grid gap-4 !mt-4">
<Label>{{ m.witty_honest_wallaby_support() }}</Label>
<Label>{{
m.witty_honest_wallaby_support()
}}</Label>
<Avatar size="lg" :src="gravatarUrl" />
</div>
</FormItem>
</FormField>
</TabsContent>
<TabsContent value="url">
<FormField v-slot="{ componentField, errors, value }" name="url">
<FormField
v-slot="{ componentField, value }"
name="url"
>
<FormItem>
<FormLabel>
{{ m.proud_next_elk_beam() }}
</FormLabel>
<FormControl>
<Input v-bind="componentField" :disabled="isSubmitting"
placeholder="https://mysite.com/avatar.webp" />
<Input
v-bind="componentField"
:disabled="isSubmitting"
placeholder="https://mysite.com/avatar.webp"
/>
</FormControl>
<FormMessage />
<div v-if="value" class="grid gap-4 !mt-4">
<Label>{{ m.witty_honest_wallaby_support() }}</Label>
<Label>{{
m.witty_honest_wallaby_support()
}}</Label>
<Avatar size="lg" :src="value" />
</div>
</FormItem>
@ -91,7 +126,11 @@
{{ m.soft_bold_ant_attend() }}
</Button>
</DialogClose>
<Button type="submit" variant="default" :disabled="isSubmitting">
<Button
type="submit"
variant="default"
:disabled="isSubmitting"
>
{{ m.teary_antsy_panda_aid() }}
</Button>
</DialogFooter>
@ -106,6 +145,7 @@ import { Upload } from "lucide-vue-next";
import { useForm } from "vee-validate";
import { z } from "zod";
import Avatar from "~/components/profiles/avatar.vue";
import { Button } from "~/components/ui/button";
import {
Dialog,
DialogClose,
@ -113,6 +153,7 @@ import {
DialogDescription,
DialogFooter,
DialogTitle,
DialogTrigger,
} from "~/components/ui/dialog";
import {
FormControl,
@ -123,6 +164,7 @@ import {
FormMessage,
} from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs";
import * as m from "~/paraglide/messages.js";
@ -151,25 +193,25 @@ const schema = toTypedSchema(
(v) => v.size <= (maxSize ?? Number.MAX_SAFE_INTEGER),
m.zippy_caring_raven_edit({
size: maxSize ?? Number.MAX_SAFE_INTEGER,
}),
})
),
})
.or(
z.object({
url: z.string().url(),
}),
})
)
.or(
z.object({
email: z.string().email(),
}),
),
})
)
);
const emailToGravatar = async (email: string) => {
const sha256 = await crypto.subtle.digest(
"SHA-256",
new TextEncoder().encode(email),
new TextEncoder().encode(email)
);
return `https://www.gravatar.com/avatar/${Array.from(new Uint8Array(sha256))
@ -192,7 +234,7 @@ const submit = handleSubmit(async (values) => {
} else if ((values as { email: string }).email) {
emit(
"submitUrl",
await emailToGravatar((values as { email: string }).email),
await emailToGravatar((values as { email: string }).email)
);
}