mirror of
https://github.com/versia-pub/frontend.git
synced 2025-12-06 16:38:20 +01:00
148 lines
5.2 KiB
Vue
148 lines
5.2 KiB
Vue
<template>
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger as-child>
|
|
<SidebarMenuButton size="lg"
|
|
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground">
|
|
<Avatar v-if="identity" class="size-8" :src="identity.account.avatar" :name="identity.account.display_name" />
|
|
<Avatar v-else class="size-8" name="AB" />
|
|
<div class="grid flex-1 text-left text-sm leading-tight">
|
|
<span class="truncate font-semibold" v-render-emojis="identity?.account.emojis">{{
|
|
identity?.account.display_name ?? "Not signed in"
|
|
}}</span>
|
|
<span class="truncate text-xs" v-if="identity">@{{ identity?.account.acct }}</span>
|
|
</div>
|
|
<ChevronsUpDown class="ml-auto size-4" />
|
|
</SidebarMenuButton>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent class="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg" side="bottom"
|
|
align="end" :side-offset="4">
|
|
<DropdownMenuLabel class="p-0 font-normal">
|
|
<Button @click="switchAccount(identity.account.id)" variant="ghost" size="lg" :href="`/@${identity.account.username}`" v-for="identity of identities" class="flex w-full items-center gap-2 px-1 text-left text-sm">
|
|
<Avatar class="size-8" :src="identity.account.avatar" :name="identity.account.display_name" />
|
|
<div class="grid flex-1 text-left text-sm leading-tight">
|
|
<span class="truncate font-semibold" v-render-emojis="identity.account.emojis">{{
|
|
identity.account.display_name
|
|
}}</span>
|
|
<span class="truncate text-xs">@{{
|
|
identity.account.acct
|
|
}}</span>
|
|
</div>
|
|
</Button>
|
|
<DropdownMenuItem @click="signInAction">
|
|
<UserPlus />
|
|
{{ m.sunny_pink_hyena_walk() }}
|
|
</DropdownMenuItem>
|
|
</DropdownMenuLabel>
|
|
<DropdownMenuSeparator v-if="identity" />
|
|
<DropdownMenuGroup v-if="identity">
|
|
<DropdownMenuItem :as="NuxtLink" :href="`/@${identity.account.username}`">
|
|
<BadgeCheck />
|
|
{{ m.factual_arable_jurgen_endure() }}
|
|
</DropdownMenuItem>
|
|
</DropdownMenuGroup>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem @click="signOut()" v-if="identity">
|
|
<LogOut />
|
|
{{ m.sharp_big_mallard_reap() }}
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem :as="NuxtLink" href="/register" v-else>
|
|
<LogIn />
|
|
{{ m.honest_few_baboon_pop() }}
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import {
|
|
BadgeCheck,
|
|
ChevronsUpDown,
|
|
LogIn,
|
|
LogOut,
|
|
UserPlus,
|
|
} from "lucide-vue-next";
|
|
import { toast } from "vue-sonner";
|
|
import * as m from "~/paraglide/messages.js";
|
|
import { NuxtLink } from "#components";
|
|
import Avatar from "../profiles/avatar.vue";
|
|
import { Button } from "../ui/button";
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuGroup,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from "../ui/dropdown-menu";
|
|
import { SidebarMenuButton } from "../ui/sidebar";
|
|
|
|
const appData = useAppData();
|
|
|
|
const signInAction = () => signIn(appData);
|
|
|
|
const signOut = async (userId?: string) => {
|
|
const id = toast.loading("Signing out...");
|
|
|
|
if (!(appData.value && identity.value)) {
|
|
toast.dismiss(id);
|
|
toast.error("No app or identity data to sign out");
|
|
return;
|
|
}
|
|
|
|
const identityToRevoke = userId
|
|
? identities.value.find((i) => i.account.id === userId)
|
|
: identity.value;
|
|
|
|
if (!identityToRevoke) {
|
|
toast.dismiss(id);
|
|
toast.error("No identity to revoke");
|
|
return;
|
|
}
|
|
|
|
// Don't do anything on error, as Versia Server doesn't implement the revoke endpoint yet
|
|
await client.value
|
|
?.revokeToken(
|
|
appData.value.client_id,
|
|
identityToRevoke.tokens.access_token,
|
|
identityToRevoke.tokens.access_token,
|
|
)
|
|
.catch(() => {
|
|
// Do nothing
|
|
});
|
|
|
|
if (!userId) {
|
|
identity.value = null;
|
|
await navigateTo("/");
|
|
return;
|
|
}
|
|
|
|
identities.value = identities.value.filter((i) => i.id !== userId);
|
|
toast.dismiss(id);
|
|
toast.success("Signed out");
|
|
};
|
|
|
|
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> |