feat: update default column informations
BIN
apps/desktop2/public/antenas.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
apps/desktop2/public/antenas@2x.png
Normal file
After Width: | Height: | Size: 245 KiB |
BIN
apps/desktop2/public/foryou.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
apps/desktop2/public/foryou@2x.png
Normal file
After Width: | Height: | Size: 228 KiB |
BIN
apps/desktop2/public/global.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
apps/desktop2/public/global@2x.png
Normal file
After Width: | Height: | Size: 220 KiB |
BIN
apps/desktop2/public/group.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
apps/desktop2/public/group@2x.png
Normal file
After Width: | Height: | Size: 264 KiB |
BIN
apps/desktop2/public/trending.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
apps/desktop2/public/trending@2x.png
Normal file
After Width: | Height: | Size: 211 KiB |
BIN
apps/desktop2/public/waifu.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
apps/desktop2/public/waifu@2x.png
Normal file
After Width: | Height: | Size: 257 KiB |
@ -1,6 +1,6 @@
|
||||
import { Col } from "@/components/col";
|
||||
import { Toolbar } from "@/components/toolbar";
|
||||
import { LoaderIcon } from "@lume/icons";
|
||||
import { LoaderIcon, PlusIcon } from "@lume/icons";
|
||||
import { EventColumns, LumeColumn } from "@lume/types";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import { UnlistenFn } from "@tauri-apps/api/event";
|
||||
@ -13,9 +13,8 @@ export const Route = createFileRoute("/$account/home")({
|
||||
pendingComponent: Pending,
|
||||
});
|
||||
|
||||
const COLS: LumeColumn[] = [
|
||||
const DEFAULT_COLUMNS: LumeColumn[] = [
|
||||
{ id: 1, name: "Newsfeed", content: "/newsfeed" },
|
||||
{ id: 9999, name: "Lume Store", content: "/store/official" },
|
||||
];
|
||||
|
||||
function Screen() {
|
||||
@ -23,7 +22,7 @@ function Screen() {
|
||||
const vlistRef = useRef<VListHandle>(null);
|
||||
const unlisten = useRef<UnlistenFn>(null);
|
||||
|
||||
const [columns, setColumns] = useState(COLS);
|
||||
const [columns, setColumns] = useState(DEFAULT_COLUMNS);
|
||||
const [selectedIndex, setSelectedIndex] = useState(-1);
|
||||
const [isScroll, setIsScroll] = useState(false);
|
||||
|
||||
|
@ -11,7 +11,8 @@ export const Route = createFileRoute("/store/official")({
|
||||
name: "For you",
|
||||
content: "/foryou",
|
||||
logo: "",
|
||||
cover: "",
|
||||
cover: "/foryou.png",
|
||||
coverRetina: "/foryou@2x.png",
|
||||
author: "Lume",
|
||||
description: "Keep up to date with content based on your interests.",
|
||||
},
|
||||
@ -20,7 +21,8 @@ export const Route = createFileRoute("/store/official")({
|
||||
name: "Group Feeds",
|
||||
content: "/group",
|
||||
logo: "",
|
||||
cover: "",
|
||||
cover: "/group.png",
|
||||
coverRetina: "/group@2x.png",
|
||||
author: "Lume",
|
||||
description: "Collective of people you're interested in.",
|
||||
},
|
||||
@ -29,7 +31,8 @@ export const Route = createFileRoute("/store/official")({
|
||||
name: "Antenas",
|
||||
content: "/antenas",
|
||||
logo: "",
|
||||
cover: "",
|
||||
cover: "/antenas.png",
|
||||
coverRetina: "/antenas@2x.png",
|
||||
author: "Lume",
|
||||
description: "Keep track to specific content.",
|
||||
},
|
||||
@ -38,7 +41,8 @@ export const Route = createFileRoute("/store/official")({
|
||||
name: "Trending",
|
||||
content: "/trending",
|
||||
logo: "",
|
||||
cover: "",
|
||||
cover: "/trending.png",
|
||||
coverRetina: "/trending@2x.png",
|
||||
author: "Lume",
|
||||
description: "What is trending on Nostr?.",
|
||||
},
|
||||
@ -47,7 +51,8 @@ export const Route = createFileRoute("/store/official")({
|
||||
name: "Global",
|
||||
content: "/global",
|
||||
logo: "",
|
||||
cover: "",
|
||||
cover: "/global.png",
|
||||
coverRetina: "/global@2x.png",
|
||||
author: "Lume",
|
||||
description: "All events from connected relays.",
|
||||
},
|
||||
@ -56,7 +61,8 @@ export const Route = createFileRoute("/store/official")({
|
||||
name: "Waifu",
|
||||
content: "/waifu",
|
||||
logo: "",
|
||||
cover: "",
|
||||
cover: "/waifu.png",
|
||||
coverRetina: "/waifu@2x.png",
|
||||
author: "Lume",
|
||||
description: "Show a random waifu image to boost your morale.",
|
||||
},
|
||||
@ -80,11 +86,21 @@ function Screen() {
|
||||
key={column.id}
|
||||
className="relative h-[200px] w-full overflow-hidden rounded-xl bg-gradient-to-tr from-orange-100 to-blue-200 px-3 pt-3"
|
||||
>
|
||||
<div className="absolute bottom-0 left-0 h-16 w-full bg-black/40 px-3 backdrop-blur-xl">
|
||||
{column.cover ? (
|
||||
<img
|
||||
src={column.cover}
|
||||
srcSet={column.coverRetina}
|
||||
alt={column.name}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
className="absolute left-0 top-0 z-10 h-full w-full object-cover"
|
||||
/>
|
||||
) : null}
|
||||
<div className="absolute bottom-0 left-0 z-20 h-16 w-full bg-black/40 px-3 backdrop-blur-xl">
|
||||
<div className="flex h-full items-center justify-between">
|
||||
<div>
|
||||
<h1 className="font-semibold text-white">{column.name}</h1>
|
||||
<p className="max-w-[18rem] truncate text-sm text-white/80">
|
||||
<p className="max-w-[24rem] truncate text-sm text-white/80">
|
||||
{column.description}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -1,24 +1,17 @@
|
||||
import { SVGProps } from "react";
|
||||
|
||||
export function ChevronDownIcon(
|
||||
props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
||||
props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
||||
) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M6 9a30.618 30.618 0 005.49 5.817c.3.244.72.244 1.02 0A30.617 30.617 0 0018 9"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
return (
|
||||
<svg width="24" height="24" fill="none" viewBox="0 0 24 24" {...props}>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="m20 9-6.586 6.586a2 2 0 0 1-2.828 0L4 9"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
6
packages/types/index.d.ts
vendored
@ -86,8 +86,10 @@ export interface LumeColumn {
|
||||
content: URL | string;
|
||||
description?: string;
|
||||
author?: string;
|
||||
logo?: URL | string;
|
||||
cover?: URL | string;
|
||||
logo?: string;
|
||||
cover?: string;
|
||||
coverRetina?: string;
|
||||
featured?: boolean;
|
||||
}
|
||||
|
||||
export interface EventColumns {
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { ChevronDownIcon, RefreshIcon } from "@lume/icons";
|
||||
import { cn } from "@lume/utils";
|
||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||
|
||||
export function ColumnHeader({
|
||||
name,
|
||||
@ -7,16 +9,40 @@ export function ColumnHeader({
|
||||
name: string;
|
||||
className?: string;
|
||||
}) {
|
||||
const reload = () => {
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-11 w-full shrink-0 items-center justify-center gap-2 border-b border-neutral-100 dark:border-neutral-900",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="inline-flex items-center gap-1.5">
|
||||
<div className="text-[13px] font-medium">{name}</div>
|
||||
<DropdownMenu.Root>
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-11 w-full shrink-0 items-center justify-center gap-2 border-b border-neutral-100 dark:border-neutral-900",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<DropdownMenu.Trigger asChild>
|
||||
<button type="button" className="inline-flex items-center gap-2">
|
||||
<div className="text-[13px] font-medium">{name}</div>
|
||||
<ChevronDownIcon className="size-4" />
|
||||
</button>
|
||||
</DropdownMenu.Trigger>
|
||||
</div>
|
||||
</div>
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content
|
||||
sideOffset={5}
|
||||
className="flex w-[200px] flex-col overflow-hidden rounded-xl bg-black p-1 focus:outline-none dark:bg-white"
|
||||
>
|
||||
<DropdownMenu.Item
|
||||
onClick={reload}
|
||||
className="inline-flex h-9 items-center gap-3 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"
|
||||
>
|
||||
<RefreshIcon className="size-4" />
|
||||
Reload
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Arrow className="fill-black dark:fill-white" />
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
</DropdownMenu.Root>
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { VerifiedIcon } from "@lume/icons";
|
||||
import { cn, displayNpub } from "@lume/utils";
|
||||
import { cn, displayLongHandle, displayNpub } from "@lume/utils";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useUserContext } from "./provider";
|
||||
import { useArk } from "@lume/ark";
|
||||
@ -23,7 +23,9 @@ export function UserNip05({ className }: { className?: string }) {
|
||||
<p className={cn("text-sm", className)}>
|
||||
{!user.profile?.nip05
|
||||
? displayNpub(user.pubkey, 16)
|
||||
: user.profile?.nip05.replace("_@", "")}
|
||||
: user.profile?.nip05.length > 16
|
||||
? displayLongHandle(user.profile?.nip05)
|
||||
: user.profile.nip05?.replace("_@", "")}
|
||||
</p>
|
||||
{!isLoading && verified ? (
|
||||
<VerifiedIcon className="size-4 text-teal-500" />
|
||||
|
@ -65,6 +65,14 @@ export function displayNpub(pubkey: string, len: number) {
|
||||
);
|
||||
}
|
||||
|
||||
export function displayLongHandle(str: string) {
|
||||
const split = str.split("@");
|
||||
const handle = split[0];
|
||||
const service = split[1];
|
||||
|
||||
return handle.substring(0, 16) + "..." + "@" + service;
|
||||
}
|
||||
|
||||
// convert number to K, M, B, T, etc.
|
||||
export const compactNumber = Intl.NumberFormat("en", { notation: "compact" });
|
||||
|
||||
|