refactor: ♻️ Fix more broken UIs, rewrite account switcher

This commit is contained in:
Jesse Wierzbinski 2025-04-10 18:44:53 +02:00
parent ac0a571ecc
commit a4d42e3086
No known key found for this signature in database
31 changed files with 167 additions and 176 deletions

View file

@ -0,0 +1,92 @@
<template>
<Dialog>
<DialogTrigger as-child>
<slot />
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Accounts</DialogTitle>
<DialogDescription class="sr-only">
Manage your accounts and settings.
</DialogDescription>
</DialogHeader>
<div v-if="identities.length > 0" class="grid gap-4 py-2">
<div v-for="identity of identities" :key="identity.account.id"
class="grid grid-cols-[1fr_auto] has-[>[data-switch]]:grid-cols-[1fr_auto_auto] gap-2">
<TinyCard :account="identity.account" :domain="identity.instance.domain" naked />
<Button data-switch v-if="currentIdentity?.id !== identity.id"
@click="switchAccount(identity.account.id)" variant="outline">
Switch
</Button>
<Button @click="signOut(appData, identity)" variant="outline" size="icon"
:title="m.sharp_big_mallard_reap()">
<LogOut />
</Button>
</div>
</div>
<div v-else>
<p class="text-sm text-muted-foreground">
Log in to or register an account on your favourite instance.
</p>
</div>
<DialogFooter>
<Button :as="NuxtLink" href="/register" variant="outline">
<UserPlus />
{{ m.honest_few_baboon_pop() }}
</Button>
<Button @click="signInAction">
<LogIn />
{{ m.sunny_pink_hyena_walk() }}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>
<script lang="ts" setup>
import type { Account } from "@versia/client/types";
import { ChevronsUpDown, LogIn, LogOut, UserPlus } from "lucide-vue-next";
import { toast } from "vue-sonner";
import TinyCard from "~/components/profiles/tiny-card.vue";
import { Button } from "~/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "~/components/ui/dialog";
import * as m from "~/paraglide/messages.js";
import { NuxtLink } from "#components";
import { identity as currentIdentity } from "#imports";
const appData = useAppData();
const signInAction = async () => signIn(appData, await askForInstance());
const switchAccount = async (userId: string) => {
if (userId === currentIdentity.value?.account.id) {
return await navigateTo(`/@${currentIdentity.value.account.username}`);
}
const id = toast.loading("Switching account...");
const identityToSwitch = identities.value.find(
(i) => i.account.id === userId,
);
if (!identityToSwitch) {
toast.dismiss(id);
toast.error("No identity to switch to");
return;
}
currentIdentity.value = identityToSwitch;
toast.dismiss(id);
toast.success("Switched account");
window.location.href = "/";
};
</script>

View file

@ -1,92 +0,0 @@
<script setup lang="ts">
import { BadgeCheck, LogIn, LogOut, UserPlus } from "lucide-vue-next";
import { toast } from "vue-sonner";
import TinyCard from "~/components/profiles/tiny-card.vue";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import * as m from "~/paraglide/messages.js";
import { NuxtLink } from "#components";
const appData = useAppData();
const signInAction = async () => signIn(appData, await askForInstance());
const switchAccount = async (userId: string) => {
if (userId === identity.value?.account.id) {
return await navigateTo(`/@${identity.value.account.username}`);
}
const id = toast.loading("Switching account...");
const identityToSwitch = identities.value.find(
(i) => i.account.id === userId,
);
if (!identityToSwitch) {
toast.dismiss(id);
toast.error("No identity to switch to");
return;
}
identity.value = identityToSwitch;
toast.dismiss(id);
toast.success("Switched account");
window.location.href = "/";
};
</script>
<template>
<DropdownMenu>
<DropdownMenuTrigger :as-child="true">
<slot />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel> Your accounts </DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem
v-for="identity of identities"
:key="identity.account.id"
@click="switchAccount(identity.account.id)"
:href="`/@${identity.account.username}`"
>
<TinyCard
:account="identity.account"
:domain="identity.instance.domain"
naked
/>
</DropdownMenuItem>
<DropdownMenuItem @click="signInAction">
<UserPlus />
{{ m.sunny_pink_hyena_walk() }}
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator v-if="identity" />
<DropdownMenuGroup v-if="identity">
<DropdownMenuItem
:as="NuxtLink"
:href="`/@${identity.account.username}`"
>
<BadgeCheck />
{{ m.factual_arable_jurgen_endure() }}
</DropdownMenuItem>
<DropdownMenuItem @click="signOut(appData, identity)">
<LogOut />
{{ m.sharp_big_mallard_reap() }}
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuItem v-else :as="NuxtLink" href="/register">
<LogIn />
{{ m.honest_few_baboon_pop() }}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</template>

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ChevronsUpDown, DownloadCloud, Pen } from "lucide-vue-next";
import { ChevronsUpDown, DownloadCloud, Pen, UserPlus } from "lucide-vue-next";
import TinyCard from "~/components/profiles/tiny-card.vue";
import { Button } from "~/components/ui/button";
import {
@ -9,7 +9,7 @@ import {
SidebarMenuItem,
} from "~/components/ui/sidebar";
import * as m from "~/paraglide/messages.js";
import AccountSwitcher from "../account/account-switcher.vue";
import AccountManager from "../account/account-manager.vue";
const { $pwa } = useNuxtApp();
</script>
@ -17,38 +17,28 @@ const { $pwa } = useNuxtApp();
<SidebarFooter>
<SidebarMenu class="gap-3">
<SidebarMenuItem>
<AccountSwitcher>
<SidebarMenuButton size="lg">
<TinyCard
v-if="identity"
:account="identity.account"
:domain="identity.instance.domain"
naked
/>
<AccountManager>
<SidebarMenuButton v-if="identity" size="lg">
<TinyCard :account="identity.account" :domain="identity.instance.domain" naked />
<ChevronsUpDown class="ml-auto size-4" />
</SidebarMenuButton>
</AccountSwitcher>
<SidebarMenuButton v-else>
<UserPlus />
{{ m.sunny_pink_hyena_walk() }}
<ChevronsUpDown class="ml-auto size-4" />
</SidebarMenuButton>
</AccountManager>
</SidebarMenuItem>
<SidebarMenuItem class="flex flex-col gap-2">
<Button
v-if="identity"
variant="default"
size="lg"
class="w-full group-data-[collapsible=icon]:px-4"
@click="useEvent('composer:open')"
>
<Button v-if="identity" variant="default" size="lg" class="w-full group-data-[collapsible=icon]:px-4"
@click="useEvent('composer:open')">
<Pen />
<span class="group-data-[collapsible=icon]:hidden">
{{ m.salty_aloof_turkey_nudge() }}
</span>
</Button>
<Button
v-if="$pwa?.needRefresh"
variant="destructive"
size="lg"
class="w-full group-data-[collapsible=icon]:px-4"
@click="$pwa?.updateServiceWorker(true)"
>
<Button v-if="$pwa?.needRefresh" variant="destructive" size="lg"
class="w-full group-data-[collapsible=icon]:px-4" @click="$pwa?.updateServiceWorker(true)">
<DownloadCloud />
<span class="group-data-[collapsible=icon]:hidden">
{{ m.quaint_low_felix_pave() }}