feat: improve

This commit is contained in:
2024-03-02 15:21:28 +07:00
parent cfcb9bc6ed
commit ca0e041731
62 changed files with 1353 additions and 1631 deletions

View File

@@ -1,81 +0,0 @@
import { useArk, useProfile } from "@lume/ark";
import { SettingsIcon, UserIcon } from "@lume/icons";
import { cn, useNetworkStatus } from "@lume/utils";
import * as Avatar from "@radix-ui/react-avatar";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { minidenticon } from "minidenticons";
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { LogoutDialog } from "./logoutDialog";
export function ActiveAccount() {
const ark = useArk();
const isOnline = useNetworkStatus();
const svgURI = useMemo(
() =>
`data:image/svg+xml;utf8,${encodeURIComponent(
minidenticon(ark.account.npub, 90, 50),
)}`,
[],
);
const { t } = useTranslation();
const { profile } = useProfile(ark.account.npub);
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<Avatar.Root
className={cn(
"rounded-full ring-1 ring-offset-2 ring-offset-neutral-200 dark:ring-offset-neutral-950",
isOnline ? "ring-teal-500" : "ring-red-500",
)}
>
<Avatar.Image
src={profile?.picture}
alt={ark.account.npub}
loading="lazy"
decoding="async"
style={{ contentVisibility: "auto" }}
className="aspect-square h-auto w-7 rounded-full object-cover"
/>
<Avatar.Fallback delayMs={150}>
<img
src={svgURI}
alt={ark.account.npub}
className="aspect-square h-auto w-7 rounded-full bg-black dark:bg-white"
/>
</Avatar.Fallback>
</Avatar.Root>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
side="left"
sideOffset={10}
className="relative top-2 flex w-[200px] flex-col overflow-hidden rounded-2xl bg-white/50 p-2 ring-1 ring-black/10 backdrop-blur-2xl focus:outline-none dark:bg-black/50 dark:ring-white/10"
>
<DropdownMenu.Item asChild>
<a
href="/settings/profile"
className="inline-flex h-9 items-center gap-3 rounded-lg px-3 text-sm font-medium text-black/70 hover:bg-black/10 hover:text-black focus:outline-none dark:text-white/70 dark:hover:bg-white/10 dark:hover:text-white"
>
<UserIcon className="size-4" />
{t("user.editProfile")}
</a>
</DropdownMenu.Item>
<DropdownMenu.Item asChild>
<a
href="/settings/"
className="inline-flex h-9 items-center gap-3 rounded-lg px-3 text-sm font-medium text-black/70 hover:bg-black/10 hover:text-black focus:outline-none dark:text-white/70 dark:hover:bg-white/10 dark:hover:text-white"
>
<SettingsIcon className="size-4" />
{t("user.settings")}
</a>
</DropdownMenu.Item>
<DropdownMenu.Separator className="my-1 h-px bg-black/10 dark:bg-white/10" />
<LogoutDialog />
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
);
}

View File

@@ -1,76 +0,0 @@
import { useArk } from "@lume/ark";
import { LogoutIcon } from "@lume/icons";
import * as AlertDialog from "@radix-ui/react-alert-dialog";
import { useQueryClient } from "@tanstack/react-query";
import { useNavigate } from "@tanstack/react-router";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
export function LogoutDialog() {
const ark = useArk();
const queryClient = useQueryClient();
const navigate = useNavigate();
const { t } = useTranslation();
const logout = async () => {
try {
// clear cache
queryClient.clear();
ark.account = null;
// redirect to welcome screen
navigate({ to: "/auth/" });
} catch (e) {
toast.error(String(e));
}
};
return (
<AlertDialog.Root>
<AlertDialog.Trigger asChild>
<button
type="button"
className="inline-flex h-9 items-center gap-3 rounded-lg px-3 text-sm font-medium text-black/70 hover:bg-black/10 hover:text-black focus:outline-none dark:text-white/70 dark:hover:bg-white/10 dark:hover:text-white"
>
<LogoutIcon className="size-4" />
{t("user.logout")}
</button>
</AlertDialog.Trigger>
<AlertDialog.Portal>
<AlertDialog.Overlay className="fixed inset-0 z-50 bg-black/20 backdrop-blur-sm dark:bg-black/20" />
<AlertDialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
<div className="relative h-min w-full max-w-md rounded-xl bg-neutral-100 dark:bg-neutral-900">
<div className="flex flex-col gap-1 border-b border-white/5 px-5 py-4">
<AlertDialog.Title className="text-lg font-semibold text-neutral-900 dark:text-neutral-100">
{t("user.logoutConfirmTitle")}
</AlertDialog.Title>
<AlertDialog.Description className="text-sm leading-tight text-neutral-600 dark:text-neutral-400">
{t("user.logoutConfirmSubtitle")}
</AlertDialog.Description>
</div>
<div className="flex justify-end gap-2 px-5 py-3">
<AlertDialog.Cancel asChild>
<button
type="button"
className="inline-flex h-9 items-center justify-center rounded-lg px-4 text-sm font-medium text-neutral-900 outline-none hover:bg-neutral-200 dark:text-neutral-100 dark:hover:bg-neutral-800"
>
{t("global.cancel")}
</button>
</AlertDialog.Cancel>
<AlertDialog.Action asChild>
<button
type="button"
onClick={() => logout()}
className="inline-flex h-9 items-center justify-center rounded-lg bg-red-500 px-4 text-sm font-medium text-white outline-none hover:bg-red-600"
>
{t("user.logout")}
</button>
</AlertDialog.Action>
</div>
</div>
</AlertDialog.Content>
</AlertDialog.Portal>
</AlertDialog.Root>
);
}

View File

@@ -9,9 +9,14 @@ export function Box({
className?: string;
}) {
return (
<div className={cn("flex h-full min-h-0 w-full", className)}>
<div className="flex h-full min-h-0 w-full">
<div className="h-full w-full flex-1 px-2 pb-2">
<div className="h-full w-full overflow-hidden overflow-y-auto rounded-xl bg-white px-3 pt-3 shadow-[rgba(50,_50,_105,_0.15)_0px_2px_5px_0px,_rgba(0,_0,_0,_0.05)_0px_1px_1px_0px] dark:bg-black dark:shadow-none dark:ring-1 dark:ring-white/5">
<div
className={cn(
"h-full w-full overflow-hidden overflow-y-auto rounded-xl bg-white shadow-[rgba(50,_50,_105,_0.15)_0px_2px_5px_0px,_rgba(0,_0,_0,_0.05)_0px_1px_1px_0px] dark:bg-black dark:shadow-none dark:ring-1 dark:ring-white/5",
className,
)}
>
{children}
</div>
</div>

View File

@@ -3,28 +3,32 @@ import { cn } from "@lume/utils";
import { useTranslation } from "react-i18next";
export function EmptyFeed({
text,
subtext,
className,
}: { text?: string; subtext?: string; className?: string }) {
const { t } = useTranslation();
text,
subtext,
className,
}: {
text?: string;
subtext?: string;
className?: string;
}) {
const { t } = useTranslation();
return (
<div
className={cn(
"w-full py-5 flex items-center justify-center flex-col gap-2 rounded-xl bg-neutral-50 dark:bg-neutral-950",
className,
)}
>
<InfoIcon className="size-8 text-blue-500" />
<div className="text-center">
<p className="font-semibold text-lg">
{text ? text : t("global.emptyFeedTitle")}
</p>
<p className="leading-tight text-sm">
{subtext ? subtext : t("global.emptyFeedSubtitle")}
</p>
</div>
</div>
);
return (
<div
className={cn(
"flex w-full flex-col items-center justify-center gap-2 rounded-xl bg-neutral-50 py-3 dark:bg-neutral-950",
className,
)}
>
<InfoIcon className="size-8 text-blue-500" />
<div className="text-center">
<p className="text-lg font-semibold">
{text ? text : t("global.emptyFeedTitle")}
</p>
<p className="text-sm leading-tight">
{subtext ? subtext : t("global.emptyFeedSubtitle")}
</p>
</div>
</div>
);
}

View File

@@ -1,4 +1,4 @@
import { ReplyIcon, ShareIcon } from "@lume/icons";
import { LinkIcon, ReplyIcon } from "@lume/icons";
import * as Tooltip from "@radix-ui/react-tooltip";
import { useTranslation } from "react-i18next";
import { useNoteContext } from "../provider";
@@ -41,8 +41,8 @@ export function NoteReply() {
onClick={() => ark.open_thread(event.id)}
className="inline-flex h-9 items-center gap-2 rounded-lg px-3 text-sm font-medium text-white hover:bg-neutral-900 focus:outline-none dark:text-black dark:hover:bg-neutral-100"
>
<ShareIcon className="size-4" />
{t("note.buttons.view")}
<LinkIcon className="size-4" />
{t("note.buttons.open")}
</button>
</DropdownMenu.Item>
<DropdownMenu.Item asChild>

View File

@@ -105,7 +105,7 @@ export function MentionNote({
}
return (
<div className="my-1 flex w-full cursor-default flex-col rounded-2xl border border-black/10 px-3 pt-1 dark:border-white/10">
<div className="my-1 flex w-full cursor-default flex-col rounded-xl border border-black/10 px-3 pt-1 dark:border-white/10">
<User.Provider pubkey={data.pubkey}>
<User.Root className="flex h-10 items-center gap-2">
<User.Avatar className="size-6 shrink-0 rounded-full object-cover" />

View File

@@ -35,7 +35,10 @@ export function ImagePreview({ url }: { url: string }) {
return (
// biome-ignore lint/a11y/useKeyWithClickEvents: <explanation>
<div onClick={open} className="group relative my-1 rounded-2xl">
<div
onClick={open}
className="group relative my-1 overflow-hidden rounded-xl"
>
<img
src={url}
alt={url}
@@ -43,7 +46,7 @@ export function ImagePreview({ url }: { url: string }) {
decoding="async"
style={{ contentVisibility: "auto" }}
onError={fallback}
className="h-auto w-full rounded-2xl object-cover"
className="h-auto w-full object-cover"
/>
<button
type="button"