feat: supporting hash of github actions cache
This commit is contained in:
@@ -18,9 +18,9 @@
|
||||
"@radix-ui/react-hover-card": "^1.0.7",
|
||||
"@radix-ui/react-popover": "^1.0.7",
|
||||
"@radix-ui/react-tooltip": "^1.0.7",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"get-urls": "^12.1.0",
|
||||
"jotai": "^2.6.2",
|
||||
"jotai": "^2.6.3",
|
||||
"linkify-react": "^4.1.3",
|
||||
"linkifyjs": "^4.1.3",
|
||||
"media-chrome": "^2.1.0",
|
||||
@@ -38,14 +38,14 @@
|
||||
"string-strip-html": "^13.4.5",
|
||||
"tippy.js": "^6.3.7",
|
||||
"use-context-selector": "^1.4.1",
|
||||
"virtua": "^0.20.5"
|
||||
"virtua": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
"@lume/tsconfig": "workspace:^",
|
||||
"@lume/types": "workspace:^",
|
||||
"@types/react": "^18.2.48",
|
||||
"tailwind-merge": "^2.2.0",
|
||||
"tailwind-merge": "^2.2.1",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ export class Ark {
|
||||
cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST,
|
||||
});
|
||||
|
||||
if (!profile) throw new Error("user not found");
|
||||
if (!profile) return null;
|
||||
return profile;
|
||||
} catch {
|
||||
throw new Error("user not found");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
HorizontalDotsIcon,
|
||||
ChevronDownIcon,
|
||||
MoveLeftIcon,
|
||||
MoveRightIcon,
|
||||
RefreshIcon,
|
||||
@@ -43,78 +43,71 @@ export function ColumnHeader({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between w-full px-3 border-b h-11 shrink-0 border-neutral-100 dark:border-neutral-900">
|
||||
<div className="inline-flex items-center gap-4">
|
||||
<div className="inline-flex items-center flex-1 gap-2 text-neutral-800 dark:text-neutral-200">
|
||||
{icon ? icon : <ThreadIcon className="size-4" />}
|
||||
<div className="text-sm font-medium">{title}</div>
|
||||
</div>
|
||||
<DropdownMenu.Root>
|
||||
<div className="flex items-center justify-center gap-2 px-3 w-full border-b h-11 shrink-0 border-neutral-100 dark:border-neutral-900">
|
||||
<DropdownMenu.Trigger asChild>
|
||||
<div className="inline-flex items-center gap-1.5">
|
||||
<div className="text-[13px] font-medium">{title}</div>
|
||||
<ChevronDownIcon className="size-5" />
|
||||
</div>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content
|
||||
sideOffset={5}
|
||||
className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-white/50 dark:bg-black/50 ring-1 ring-black/10 dark:ring-white/10 backdrop-blur-2xl focus:outline-none"
|
||||
>
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={refresh}
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
<RefreshIcon className="size-4" />
|
||||
Refresh
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
{queryKey?.[0] === "foryou-9998" ? (
|
||||
<DropdownMenu.Item asChild>
|
||||
<InterestModal
|
||||
queryKey={queryKey}
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
/>
|
||||
</DropdownMenu.Item>
|
||||
) : null}
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={moveLeft}
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
<MoveLeftIcon className="size-4" />
|
||||
Move left
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={moveRight}
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
<MoveRightIcon className="size-4" />
|
||||
Move right
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator className="h-px my-1 bg-black/10 dark:bg-white/10" />
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={deleteWidget}
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium text-red-500 rounded-lg h-9 hover:bg-red-500 hover:text-red-50 focus:outline-none"
|
||||
>
|
||||
<TrashIcon className="size-4" />
|
||||
Delete
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
</div>
|
||||
<div>
|
||||
<DropdownMenu.Root>
|
||||
<DropdownMenu.Trigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center w-6 h-6"
|
||||
>
|
||||
<HorizontalDotsIcon className="size-4" />
|
||||
</button>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-black/70 dark:bg-white/10 backdrop-blur-xl focus:outline-none">
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={refresh}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
>
|
||||
<RefreshIcon className="size-5" />
|
||||
Refresh
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
{queryKey?.[0] === "foryou-9998" ? (
|
||||
<DropdownMenu.Item asChild>
|
||||
<InterestModal
|
||||
queryKey={queryKey}
|
||||
className="text-sm font-medium text-white/50 hover:bg-black/10 hover:text-white dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
/>
|
||||
</DropdownMenu.Item>
|
||||
) : null}
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={moveLeft}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
>
|
||||
<MoveLeftIcon className="size-5" />
|
||||
Move left
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={moveRight}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
>
|
||||
<MoveRightIcon className="size-5" />
|
||||
Move right
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator className="h-px my-1 bg-white/10 dark:bg-black/10" />
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={deleteWidget}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium text-red-300 rounded-lg h-9 hover:bg-red-500 hover:text-red-50 focus:outline-none"
|
||||
>
|
||||
<TrashIcon className="size-5" />
|
||||
Delete
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
</DropdownMenu.Root>
|
||||
</div>
|
||||
</div>
|
||||
</DropdownMenu.Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export function InterestModal({
|
||||
);
|
||||
|
||||
if (save) {
|
||||
storage.interests.hashtags = hashtags;
|
||||
storage.interests = { hashtags, users: [], words: [] };
|
||||
await queryClient.refetchQueries({ queryKey });
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export function InterestModal({
|
||||
<Dialog.Root open={open} onOpenChange={setOpen}>
|
||||
<Dialog.Trigger
|
||||
className={cn(
|
||||
"inline-flex items-center gap-2 px-3 rounded-lg h-9 focus:outline-none",
|
||||
"inline-flex items-center gap-3 px-3 rounded-lg h-9 focus:outline-none",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
@@ -64,7 +64,7 @@ export function InterestModal({
|
||||
children
|
||||
) : (
|
||||
<>
|
||||
<EditInterestIcon className="size-5" />
|
||||
<EditInterestIcon className="size-4" />
|
||||
Edit interest
|
||||
</>
|
||||
)}
|
||||
@@ -86,11 +86,8 @@ export function InterestModal({
|
||||
<div className="w-full flex-1 min-h-0 flex flex-col justify-between">
|
||||
<div className="flex-1 min-h-0 overflow-y-auto px-8 py-8">
|
||||
<div className="flex flex-col gap-8">
|
||||
{TOPICS.map((topic, index) => (
|
||||
<div
|
||||
key={topic.title + index}
|
||||
className="flex flex-col gap-4"
|
||||
>
|
||||
{TOPICS.map((topic) => (
|
||||
<div key={topic.title} className="flex flex-col gap-4">
|
||||
<div className="w-full flex items-center justify-between">
|
||||
<div className="inline-flex items-center gap-2.5">
|
||||
<img
|
||||
@@ -113,6 +110,7 @@ export function InterestModal({
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
{topic.content.map((hashtag) => (
|
||||
<button
|
||||
key={hashtag}
|
||||
type="button"
|
||||
onClick={() => toggleHashtag(hashtag)}
|
||||
className={cn(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChevronUpIcon } from "@lume/icons";
|
||||
import { ArrowUpIcon } from "@lume/icons";
|
||||
import { NDKEvent, NDKFilter } from "@nostr-dev-kit/ndk";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useArk } from "../../hooks/useArk";
|
||||
@@ -34,14 +34,14 @@ export function ColumnLiveWidget({
|
||||
if (!events.length) return null;
|
||||
|
||||
return (
|
||||
<div className="absolute left-0 z-50 flex items-center justify-center w-full top-11 h-11">
|
||||
<div className="absolute left-0 z-40 flex items-center justify-center w-full top-12 h-11">
|
||||
<button
|
||||
type="button"
|
||||
onClick={update}
|
||||
className="inline-flex items-center justify-center h-8 gap-1 pl-2 pr-2.5 text-sm font-semibold rounded-full w-max bg-neutral-950 dark:bg-neutral-50 hover:bg-neutral-900 dark:hover:bg-neutral-100 text-neutral-50 dark:text-neutral-950"
|
||||
className="inline-flex items-center justify-center h-9 gap-1 pl-4 pr-3 text-sm font-semibold rounded-full w-max bg-neutral-950 dark:bg-neutral-50 hover:bg-neutral-900 dark:hover:bg-neutral-100 text-neutral-50 dark:text-neutral-950"
|
||||
>
|
||||
<ChevronUpIcon className="w-4 h-4" />
|
||||
{events.length} {events.length === 1 ? "new note" : "new notes"}
|
||||
<ArrowUpIcon className="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -55,7 +55,10 @@ export function ColumnProvider({ children }: { children: ReactNode }) {
|
||||
column.title,
|
||||
column.content,
|
||||
);
|
||||
if (result) setColumns((prev) => [...prev, result]);
|
||||
if (result) {
|
||||
setColumns((prev) => [...prev, result]);
|
||||
vlistRef?.current.scrollToIndex(columns.length);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const removeColumn = useCallback(async (id: number) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChatsIcon } from "@lume/icons";
|
||||
import { ReplyIcon } from "@lume/icons";
|
||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useNoteContext } from "../provider";
|
||||
@@ -16,12 +16,12 @@ export function NoteReply() {
|
||||
onClick={() => navigate(`/events/${event.id}`)}
|
||||
className="inline-flex items-center justify-center group h-7 w-7 text-neutral-600 dark:text-neutral-400"
|
||||
>
|
||||
<ChatsIcon className="size-5 group-hover:text-blue-500" />
|
||||
<ReplyIcon className="size-5 group-hover:text-blue-500" />
|
||||
</button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Portal>
|
||||
<Tooltip.Content className="inline-flex h-7 select-none text-neutral-50 dark:text-neutral-950 items-center justify-center rounded-md bg-neutral-950 dark:bg-neutral-50 px-3.5 text-sm will-change-[transform,opacity] data-[state=delayed-open]:data-[side=bottom]:animate-slideUpAndFade data-[state=delayed-open]:data-[side=left]:animate-slideRightAndFade data-[state=delayed-open]:data-[side=right]:animate-slideLeftAndFade data-[state=delayed-open]:data-[side=top]:animate-slideDownAndFade">
|
||||
Quick reply
|
||||
View thread
|
||||
<Tooltip.Arrow className="fill-neutral-950 dark:fill-neutral-50" />
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Portal>
|
||||
|
||||
@@ -88,12 +88,12 @@ export function NoteRepost() {
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Provider>
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-black/70 dark:bg-white/10 backdrop-blur-xl focus:outline-none">
|
||||
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-white/50 dark:bg-black/50 ring-1 ring-black/10 dark:ring-white/10 backdrop-blur-2xl focus:outline-none">
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={repost}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
<RepostIcon className="size-4" />
|
||||
Repost
|
||||
@@ -103,7 +103,7 @@ export function NoteRepost() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={quote}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
<ReplyIcon className="size-4" />
|
||||
Quote
|
||||
|
||||
@@ -131,10 +131,18 @@ export function NoteZap() {
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Provider>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/10 backdrop-blur-sm dark:bg-white/10" />
|
||||
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/20 backdrop-blur-sm dark:bg-white/20" />
|
||||
<Dialog.Content className="fixed inset-0 z-50 flex items-center justify-center min-h-full">
|
||||
<Dialog.Close className="absolute top-5 right-5 z-50">
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<div className="inline-flex items-center justify-center size-10 rounded-lg bg-white dark:bg-black">
|
||||
<CancelIcon className="size-5" />
|
||||
</div>
|
||||
<span className="text-sm font-medium">Esc</span>
|
||||
</div>
|
||||
</Dialog.Close>
|
||||
<div className="relative w-full max-w-xl bg-white h-min rounded-xl dark:bg-black">
|
||||
<div className="inline-flex items-center justify-between w-full px-5 py-3 shrink-0">
|
||||
<div className="inline-flex items-center justify-center w-full px-5 py-3 shrink-0">
|
||||
<div className="w-6" />
|
||||
<Dialog.Title className="font-semibold text-center">
|
||||
Send zap to{" "}
|
||||
@@ -142,13 +150,10 @@ export function NoteZap() {
|
||||
user?.displayName ||
|
||||
displayNpub(event.pubkey, 16)}
|
||||
</Dialog.Title>
|
||||
<Dialog.Close className="inline-flex items-center justify-center w-6 h-6 rounded-md bg-neutral-100 dark:bg-neutral-900">
|
||||
<CancelIcon className="w-4 h-4" />
|
||||
</Dialog.Close>
|
||||
</div>
|
||||
{!invoice ? (
|
||||
<div className="px-5 pb-5 overflow-x-hidden overflow-y-auto">
|
||||
<div className="relative flex flex-col h-40">
|
||||
<div className="relative flex flex-col h-36">
|
||||
<div className="inline-flex items-center justify-center flex-1 h-full gap-1">
|
||||
<CurrencyInput
|
||||
placeholder="0"
|
||||
@@ -213,13 +218,13 @@ export function NoteZap() {
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
placeholder="Enter message (optional)"
|
||||
className="w-full resize-none rounded-lg border-transparent bg-neutral-100 px-3 py-3 !outline-none placeholder:text-neutral-600 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:bg-neutral-900 dark:text-neutral-400"
|
||||
className="w-full resize-none rounded-lg border-transparent bg-neutral-100 px-3 py-3 !outline-none placeholder:text-neutral-600 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:bg-neutral-950 dark:text-neutral-400"
|
||||
/>
|
||||
<div className="flex flex-col gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => createZapRequest()}
|
||||
className="inline-flex items-center justify-center w-full px-4 font-medium text-white bg-blue-500 rounded-lg h-11 hover:bg-blue-600"
|
||||
className="inline-flex items-center justify-center w-full pb-[2px] font-semibold border-t rounded-lg border-neutral-900 dark:border-neutral-800 h-9 bg-neutral-950 text-neutral-50 dark:bg-neutral-900 hover:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
{isCompleted
|
||||
? "Zapped"
|
||||
|
||||
@@ -14,18 +14,18 @@ export function MentionUser({ pubkey }: { pubkey: string }) {
|
||||
|
||||
return (
|
||||
<DropdownMenu.Root>
|
||||
<DropdownMenu.Trigger className="text-blue-500 break-words hover:text-blue-600">
|
||||
<DropdownMenu.Trigger className="text-start text-blue-500 break-words hover:text-blue-600">
|
||||
{isLoading
|
||||
? "@anon"
|
||||
: isError
|
||||
? pubkey
|
||||
: `@${user?.name || user?.displayName || user?.username || "anon"}`}
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content className="left-[50px] z-50 relative flex w-[200px] flex-col overflow-hidden rounded-xl border border-neutral-200 bg-neutral-950 focus:outline-none dark:border-neutral-900">
|
||||
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-white/50 dark:bg-black/50 ring-1 ring-black/10 dark:ring-white/10 backdrop-blur-2xl focus:outline-none">
|
||||
<DropdownMenu.Item asChild>
|
||||
<Link
|
||||
to={`/users/${cleanPubkey}`}
|
||||
className="inline-flex items-center h-10 px-4 text-sm text-white hover:bg-neutral-900 focus:outline-none"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
View profile
|
||||
</Link>
|
||||
@@ -40,7 +40,7 @@ export function MentionUser({ pubkey }: { pubkey: string }) {
|
||||
content: cleanPubkey,
|
||||
})
|
||||
}
|
||||
className="inline-flex items-center h-10 px-4 text-sm text-white hover:bg-neutral-900 focus:outline-none"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
Pin
|
||||
</button>
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import { HorizontalDotsIcon } from "@lume/icons";
|
||||
import { COL_TYPES } from "@lume/utils";
|
||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||
import { writeText } from "@tauri-apps/plugin-clipboard-manager";
|
||||
import { nip19 } from "nostr-tools";
|
||||
import { type EventPointer } from "nostr-tools/lib/types/nip19";
|
||||
import { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { toast } from "sonner";
|
||||
import { useColumnContext } from "../column/provider";
|
||||
import { useNoteContext } from "./provider";
|
||||
|
||||
export function NoteMenu() {
|
||||
const event = useNoteContext();
|
||||
const navigate = useNavigate();
|
||||
const { addColumn } = useColumnContext();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const copyID = async () => {
|
||||
@@ -50,18 +54,27 @@ export function NoteMenu() {
|
||||
<DropdownMenu.Trigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center w-6 h-6"
|
||||
className="inline-flex items-center justify-center size-6"
|
||||
>
|
||||
<HorizontalDotsIcon className="w-4 h-4 text-neutral-800 hover:text-blue-500 dark:text-neutral-200" />
|
||||
<HorizontalDotsIcon className="size-4 hover:text-blue-500 dark:text-neutral-200" />
|
||||
</button>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-black/70 dark:bg-white/10 backdrop-blur-xl focus:outline-none">
|
||||
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-white/50 dark:bg-black/50 ring-1 ring-black/10 dark:ring-white/10 backdrop-blur-2xl focus:outline-none">
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyLink()}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
View thread
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => navigate(`/events/${event.id}`)}
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
Copy shareable link
|
||||
</button>
|
||||
@@ -70,34 +83,49 @@ export function NoteMenu() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyID()}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
Copy ID
|
||||
Copy note ID
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyNpub()}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
Copy npub
|
||||
Copy author ID
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<Link
|
||||
to={`/users/${event.pubkey}`}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
View profile
|
||||
View author
|
||||
</Link>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator className="h-px my-1 bg-white/10 dark:bg-black/10" />
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
addColumn({
|
||||
kind: COL_TYPES.user,
|
||||
title: "User",
|
||||
content: event.pubkey,
|
||||
})
|
||||
}
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
Pin author
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator className="h-px my-1 bg-black/10 dark:bg-white/10" />
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyRaw()}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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"
|
||||
>
|
||||
Copy raw event
|
||||
</button>
|
||||
@@ -106,7 +134,7 @@ export function NoteMenu() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={muteUser}
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium text-red-300 rounded-lg h-9 hover:bg-red-500 hover:text-red-50 focus:outline-none"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium text-red-500 rounded-lg h-9 hover:bg-red-500 hover:text-red-50 focus:outline-none"
|
||||
>
|
||||
Mute
|
||||
</button>
|
||||
|
||||
@@ -48,12 +48,12 @@ export function ImagePreview({ url }: { url: string }) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => downloadImage(e)}
|
||||
className="absolute z-10 items-center justify-center hidden size-8 bg-white/10 text-white backdrop-blur-xl rounded-lg right-2 top-2 group-hover:inline-flex hover:bg-blue-500"
|
||||
className="absolute z-10 items-center justify-center hidden size-10 bg-white/10 text-black/70 backdrop-blur-xl rounded-lg right-2 top-2 group-hover:inline-flex hover:bg-blue-500 hover:text-white"
|
||||
>
|
||||
{downloaded ? (
|
||||
<CheckCircleIcon className="size-4" />
|
||||
<CheckCircleIcon className="size-5" />
|
||||
) : (
|
||||
<DownloadIcon className="size-4" />
|
||||
<DownloadIcon className="size-5" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ export function ChildReply({
|
||||
<Note.Provider event={event}>
|
||||
<Note.Root className="py-2">
|
||||
<div className="flex items-center justify-between h-14">
|
||||
<Note.User className="flex-1" />
|
||||
<Note.User className="flex-1 pr-2" />
|
||||
<Note.Menu />
|
||||
</div>
|
||||
<Note.Content />
|
||||
|
||||
@@ -18,7 +18,7 @@ export function Reply({
|
||||
<Note.Provider event={event}>
|
||||
<Note.Root className="pt-2">
|
||||
<div className="flex items-center justify-between h-14">
|
||||
<Note.User className="flex-1 pr-1" />
|
||||
<Note.User className="flex-1 pr-2" />
|
||||
<Note.Menu />
|
||||
</div>
|
||||
<Note.Content />
|
||||
|
||||
@@ -93,7 +93,7 @@ export function RepostNote({
|
||||
<Note.Provider event={repostEvent}>
|
||||
<div className="relative flex flex-col gap-2 px-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<Note.User className="flex-1 pr-1" />
|
||||
<Note.User className="flex-1 pr-2" />
|
||||
<Note.Menu />
|
||||
</div>
|
||||
<Note.Content />
|
||||
|
||||
@@ -15,7 +15,7 @@ export function TextNote({
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center justify-between px-3 h-14">
|
||||
<Note.User className="flex-1 pr-1" />
|
||||
<Note.User className="flex-1 pr-2" />
|
||||
<Note.Menu />
|
||||
</div>
|
||||
<Note.Thread className="mb-2" />
|
||||
|
||||
@@ -87,31 +87,18 @@ export const LumeProvider = ({ children }: PropsWithChildren<object>) => {
|
||||
|
||||
async function initNDK() {
|
||||
const explicitRelayUrls = normalizeRelayUrlSet([
|
||||
"wss://nostr.mutinywallet.com/",
|
||||
"wss://bostr.nokotaro.com/",
|
||||
]);
|
||||
|
||||
// #TODO: user should config outbox relays
|
||||
const outboxRelayUrls = normalizeRelayUrlSet(["wss://purplepag.es/"]);
|
||||
|
||||
// #TODO: user should config blacklist relays
|
||||
// Skip connect depot tunnel url
|
||||
const blacklistRelayUrls = normalizeRelayUrlSet(
|
||||
storage.settings.tunnelUrl.length
|
||||
? [storage.settings.tunnelUrl, "wss://brb.io/"]
|
||||
: ["wss://brb.io/"],
|
||||
);
|
||||
|
||||
const tauriCache = new NDKCacheAdapterTauri(storage);
|
||||
const ndk = new NDK({
|
||||
cacheAdapter: tauriCache,
|
||||
explicitRelayUrls,
|
||||
outboxRelayUrls,
|
||||
blacklistRelayUrls,
|
||||
enableOutboxModel: !storage.settings.lowPower,
|
||||
autoConnectUserRelays: !storage.settings.lowPower,
|
||||
autoFetchUserMutelist: !storage.settings.lowPower,
|
||||
// clientName: "Lume",
|
||||
// clientNip89: '',
|
||||
clientName: "Lume",
|
||||
});
|
||||
|
||||
// use tauri fetch
|
||||
|
||||
@@ -111,3 +111,4 @@ export * from "./src/foryou";
|
||||
export * from "./src/editInterest";
|
||||
export * from "./src/newColumn";
|
||||
export * from "./src/searchFilled";
|
||||
export * from "./src/arrowUp";
|
||||
|
||||
24
packages/icons/src/arrowUp.tsx
Normal file
24
packages/icons/src/arrowUp.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { SVGProps } from "react";
|
||||
|
||||
export function ArrowUpIcon(
|
||||
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 9.83a30.23 30.23 0 015.406-5.62A.949.949 0 0112 4m6 5.83a30.233 30.233 0 00-5.406-5.62A.949.949 0 0012 4m0 0v16"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -17,7 +17,7 @@ export function ChevronDownIcon(
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M8 10.14a20.36 20.36 0 003.702 3.893c.175.141.42.141.596 0A20.361 20.361 0 0016 10.14"
|
||||
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>
|
||||
);
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
import { SVGProps } from 'react';
|
||||
import { SVGProps } from "react";
|
||||
|
||||
export function ChevronUpIcon(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="1.5"
|
||||
d="M8 14l3.646-3.646a.5.5 0 01.708 0L16 14"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
export function ChevronUpIcon(
|
||||
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 15a30.617 30.617 0 015.49-5.817.803.803 0 011.02 0A30.616 30.616 0 0118 15"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
import { SVGProps } from 'react';
|
||||
import { SVGProps } from "react";
|
||||
|
||||
export function DownloadIcon(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="1.5"
|
||||
d="M20.25 14.75v4.5a1 1 0 01-1 1H4.75a1 1 0 01-1-1v-4.5M12 15V3.75M12 15l-3.5-3.5M12 15l3.5-3.5"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
export function DownloadIcon(
|
||||
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="M3 15a5 5 0 005 5h8a5 5 0 005-5M9 12.188a15 15 0 002.556 2.655c.13.104.287.157.444.157m3-2.812a14.998 14.998 0 01-2.556 2.655A.704.704 0 0112 15m0 0V4"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export function LogoutIcon(
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M18.189 9a15 15 0 012.654 2.556c.105.13.157.287.157.444m-2.811 3a14.998 14.998 0 002.654-2.556A.704.704 0 0021 12m0 0H8m5-7.472A6 6 0 003 9v6a6 6 0 0010 4.472"
|
||||
d="M5.812 9a15.001 15.001 0 00-2.655 2.556A.703.703 0 003 12m2.812 3a15 15 0 01-2.655-2.556A.703.703 0 013 12m0 0h13m-5-7.472A6 6 0 0121 9v6a6 6 0 01-10 4.472"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -6,13 +6,15 @@ export function RelayIcon(props: JSX.IntrinsicElements["svg"]) {
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 25 24"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
{...props}
|
||||
>
|
||||
<path d="M12.5 20.875V17m0 3.875c-1.75 0-3.5.375-5 1.125m5-1.125c1.75 0 3.5.375 5 1.125m-5-5h7.6c.84 0 1.26 0 1.581-.163a1.5 1.5 0 00.655-.656c.164-.32.164-.74.164-1.581V4.4c0-.84 0-1.26-.163-1.581a1.5 1.5 0 00-.656-.656C21.361 2 20.941 2 20.1 2H4.9c-.84 0-1.26 0-1.581.163a1.5 1.5 0 00-.656.656c-.163.32-.163.74-.163 1.581v10.2c0 .84 0 1.26.163 1.581a1.5 1.5 0 00.656.655c.32.164.74.164 1.581.164h7.6z" />
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M21.5 12a9.002 9.002 0 01-4.682 7.897 9 9 0 01-5.59 1.013c-1.203-.17-1.805-.255-1.964-.267-.257-.02-.165-.016-.423-.014-.159 0-.34.014-.702.04l-2.153.153c-.857.062-1.286.092-1.607-.06a1.348 1.348 0 01-.641-.64c-.152-.32-.122-.75-.06-1.608l.153-2.153c.026-.362.04-.542.04-.702.002-.258.006-.166-.014-.423-.012-.159-.098-.76-.268-1.964A9 9 0 1121.5 12z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
export function ReplyIcon(props: JSX.IntrinsicElements["svg"]) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="25"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 25 24"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
{...props}
|
||||
>
|
||||
<path d="M9.5 12h3m0 0h3m-3 0V9m0 3v3m9-3a9 9 0 01-10.272 8.91c-1.203-.17-1.805-.255-1.964-.267-.257-.02-.165-.016-.423-.014-.159 0-.34.014-.702.04l-2.153.153c-.857.062-1.286.092-1.607-.06a1.35 1.35 0 01-.641-.641c-.152-.32-.122-.75-.06-1.607l.153-2.153c.026-.362.04-.543.04-.702.002-.258.006-.166-.014-.423-.012-.159-.098-.76-.268-1.964A9 9 0 1121.5 12z" />
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M21.5 12a9.002 9.002 0 01-4.682 7.897 9 9 0 01-5.59 1.013c-1.203-.17-1.805-.255-1.964-.267-.257-.02-.165-.016-.423-.014-.159 0-.34.014-.702.04l-2.153.153c-.857.062-1.286.092-1.607-.06a1.348 1.348 0 01-.641-.64c-.152-.32-.122-.75-.06-1.608l.153-2.153c.026-.362.04-.542.04-.702.002-.258.006-.166-.014-.423-.012-.159-.098-.76-.268-1.964A9 9 0 1121.5 12z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import { SVGProps } from 'react';
|
||||
import { SVGProps } from "react";
|
||||
|
||||
export function UserIcon(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"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
d="M5.857 18.916C7.171 16.996 9.332 15.75 12 15.75c2.668 0 4.83 1.247 6.143 3.166m-12.286 0A9.215 9.215 0 0012 21.25c2.358 0 4.51-.882 6.143-2.334m-12.286 0a9.25 9.25 0 1112.286 0M15.25 10a3.25 3.25 0 11-6.5 0 3.25 3.25 0 016.5 0z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
export function UserIcon(
|
||||
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="M18.995 19.147C18.893 17.393 17.367 16 15.5 16h-7c-1.867 0-3.393 1.393-3.495 3.147m13.99 0A9.97 9.97 0 0022 12c0-5.523-4.477-10-10-10S2 6.477 2 12a9.97 9.97 0 003.005 7.147m13.99 0A9.967 9.967 0 0112 22a9.967 9.967 0 01-6.995-2.853M15 10a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"name": "@columns/activity",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./src/index.tsx",
|
||||
"dependencies": {
|
||||
"@lume/ark": "workspace:^",
|
||||
"@lume/icons": "workspace:^",
|
||||
"@lume/ui": "workspace:^",
|
||||
"@lume/utils": "workspace:^",
|
||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"react": "^18.2.0",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"sonner": "^1.3.1",
|
||||
"virtua": "^0.20.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
"@lume/tsconfig": "workspace:^",
|
||||
"@lume/types": "workspace:^",
|
||||
"@types/react": "^18.2.48",
|
||||
"tailwind": "^4.0.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import sharedConfig from "@lume/tailwindcss";
|
||||
|
||||
const config = {
|
||||
content: ["./src/**/*.{js,ts,jsx,tsx}"],
|
||||
presets: [sharedConfig],
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "@lume/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -9,11 +9,11 @@
|
||||
"@lume/ui": "workspace:^",
|
||||
"@lume/utils": "workspace:^",
|
||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"react": "^18.2.0",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"sonner": "^1.3.1",
|
||||
"virtua": "^0.20.5"
|
||||
"virtua": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
"@lume/ui": "workspace:^",
|
||||
"@lume/utils": "workspace:^",
|
||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"react": "^18.2.0",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"sonner": "^1.3.1",
|
||||
"virtua": "^0.20.5"
|
||||
"virtua": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
|
||||
@@ -14,19 +14,36 @@ export function Default({ column }: { column: IColumn }) {
|
||||
icon={<ColumnIcon className="size-4" />}
|
||||
/>
|
||||
<div className="h-full px-3 mt-3 flex flex-col gap-3 overflow-y-auto scrollbar-none">
|
||||
<div className="flex flex-col rounded-xl overflow-hidden">
|
||||
<div className="h-[100px] w-full">
|
||||
<div className="h-11 flex items-center gap-5">
|
||||
<button
|
||||
type="button"
|
||||
className="h-9 w-max px-3 text-sm font-semibold inline-flex items-center justify-center bg-neutral-100 dark:bg-neutral-900 rounded-lg"
|
||||
>
|
||||
Official
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
disabled
|
||||
className="h-9 w-max px-3 text-sm inline-flex items-center justify-center rounded-lg disabled:opacity-50"
|
||||
>
|
||||
Community (Coming Soon)
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex flex-col rounded-xl overflow-hidden bg-neutral-50 dark:bg-neutral-950 ring-1 ring-neutral-100 dark:ring-neutral-900">
|
||||
<div className="h-[100px] w-full px-3 pt-3">
|
||||
<img
|
||||
src="/columns/group.jpg"
|
||||
srcSet="/columns/group@2x.jpg 2x"
|
||||
alt="group"
|
||||
className="w-full h-auto object-cover"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
className="w-full h-auto object-cover rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
<div className="h-16 shrink-0 px-3 flex items-center justify-between bg-neutral-50 dark:bg-neutral-950">
|
||||
<div className="h-16 shrink-0 px-3 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="font-semibold">Group Feeds</h1>
|
||||
<p className="max-w-[18rem] truncate text-sm text-neutral-500 dark:text-neutral-600">
|
||||
<p className="max-w-[18rem] truncate text-sm text-neutral-600 dark:text-neutral-500">
|
||||
Collective of people you're interested in.
|
||||
</p>
|
||||
</div>
|
||||
@@ -41,19 +58,21 @@ export function Default({ column }: { column: IColumn }) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col rounded-xl overflow-hidden">
|
||||
<div className="h-[100px] w-full">
|
||||
<div className="flex flex-col rounded-xl overflow-hidden bg-neutral-50 dark:bg-neutral-950 ring-1 ring-neutral-100 dark:ring-neutral-900">
|
||||
<div className="h-[100px] w-full px-3 pt-3">
|
||||
<img
|
||||
src="/columns/antenas.jpg"
|
||||
srcSet="/columns/antenas@2x.jpg 2x"
|
||||
alt="antenas"
|
||||
className="w-full h-auto object-cover"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
className="w-full h-auto object-cover rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
<div className="h-16 shrink-0 px-3 flex items-center justify-between bg-neutral-50 dark:bg-neutral-950">
|
||||
<div className="h-16 shrink-0 px-3 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="font-semibold">Antenas</h1>
|
||||
<p className="max-w-[18rem] truncate text-sm text-neutral-500 dark:text-neutral-600">
|
||||
<p className="max-w-[18rem] truncate text-sm text-neutral-600 dark:text-neutral-500">
|
||||
Keep track to specific content.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"@lume/ui": "workspace:^",
|
||||
"@lume/utils": "workspace:^",
|
||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"react": "^18.2.0",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"sonner": "^1.3.1",
|
||||
"virtua": "^0.20.5"
|
||||
"virtua": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
"@lume/ui": "workspace:^",
|
||||
"@lume/utils": "workspace:^",
|
||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"react": "^18.2.0",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"sonner": "^1.3.1",
|
||||
"virtua": "^0.20.5"
|
||||
"virtua": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
"@lume/ui": "workspace:^",
|
||||
"@lume/utils": "workspace:^",
|
||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"react": "^18.2.0",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"sonner": "^1.3.1",
|
||||
"virtua": "^0.20.5"
|
||||
"virtua": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
"@lume/ui": "workspace:^",
|
||||
"@lume/utils": "workspace:^",
|
||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"react": "^18.2.0",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"sonner": "^1.3.1",
|
||||
"virtua": "^0.20.5"
|
||||
"virtua": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
"@lume/ui": "workspace:^",
|
||||
"@lume/utils": "workspace:^",
|
||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"react": "^18.2.0",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"sonner": "^1.3.1",
|
||||
"virtua": "^0.20.5"
|
||||
"virtua": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
|
||||
@@ -30,7 +30,7 @@ export function Timeline({ column }: { column: IColumn }) {
|
||||
id={column.id}
|
||||
queryKey={[colKey]}
|
||||
title="Timeline"
|
||||
icon={<TimelineIcon className="size-4" />}
|
||||
icon={<TimelineIcon className="size-5" />}
|
||||
/>
|
||||
{ark.account.contacts.length ? (
|
||||
<Column.Live
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
"@lume/ui": "workspace:^",
|
||||
"@lume/utils": "workspace:^",
|
||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"react": "^18.2.0",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"sonner": "^1.3.1",
|
||||
"virtua": "^0.20.5"
|
||||
"virtua": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||
"@radix-ui/react-hover-card": "^1.0.7",
|
||||
"@radix-ui/react-popover": "^1.0.7",
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"framer-motion": "^10.18.0",
|
||||
"jotai": "^2.6.2",
|
||||
"jotai": "^2.6.3",
|
||||
"minidenticons": "^4.2.0",
|
||||
"nostr-tools": "~1.17.0",
|
||||
"react": "^18.2.0",
|
||||
@@ -28,18 +28,18 @@
|
||||
"react-hotkeys-hook": "^4.4.4",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"slate": "^0.101.5",
|
||||
"slate-react": "^0.101.5",
|
||||
"slate-react": "^0.101.6",
|
||||
"sonner": "^1.3.1",
|
||||
"uqr": "^0.1.2",
|
||||
"use-debounce": "^10.0.0",
|
||||
"virtua": "^0.20.5"
|
||||
"virtua": "^0.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tailwindcss": "workspace:^",
|
||||
"@lume/tsconfig": "workspace:^",
|
||||
"@lume/types": "workspace:^",
|
||||
"@types/react": "^18.2.48",
|
||||
"tailwind-merge": "^2.2.0",
|
||||
"tailwind-merge": "^2.2.1",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useArk, useProfile } from "@lume/ark";
|
||||
import { SettingsIcon } from "@lume/icons";
|
||||
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";
|
||||
@@ -54,17 +54,27 @@ export function ActiveAccount() {
|
||||
<DropdownMenu.Content
|
||||
side="right"
|
||||
sideOffset={5}
|
||||
className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-black/70 dark:bg-white/10 backdrop-blur-xl focus:outline-none"
|
||||
className="relative top-5 flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-white/50 dark:bg-black/50 ring-1 ring-black/10 dark:ring-white/10 backdrop-blur-2xl focus:outline-none"
|
||||
>
|
||||
<DropdownMenu.Item asChild>
|
||||
<Link
|
||||
to="/settings/"
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
to="/settings/profile"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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-5" />
|
||||
<UserIcon className="size-4" />
|
||||
Edit profile
|
||||
</Link>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<Link
|
||||
to="/settings/"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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" />
|
||||
Settings
|
||||
</Link>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator className="h-px my-1 bg-black/10 dark:bg-white/10" />
|
||||
<Logout />
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
|
||||
@@ -35,9 +35,9 @@ export function Logout() {
|
||||
<AlertDialog.Trigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
className="inline-flex items-center gap-3 px-3 text-sm font-medium rounded-lg h-9 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-5" />
|
||||
<LogoutIcon className="size-4" />
|
||||
Logout
|
||||
</button>
|
||||
</AlertDialog.Trigger>
|
||||
|
||||
@@ -106,7 +106,7 @@ const Image = ({ attributes, children, element }) => {
|
||||
return (
|
||||
<div {...attributes}>
|
||||
{children}
|
||||
<div contentEditable={false} className="relative">
|
||||
<div contentEditable={false} className="relative my-2">
|
||||
<img
|
||||
src={element.url}
|
||||
alt={element.url}
|
||||
@@ -155,7 +155,7 @@ const Event = ({ attributes, element, children }) => {
|
||||
<div
|
||||
contentEditable={false}
|
||||
onClick={() => Transforms.removeNodes(editor, { at: path })}
|
||||
className="relative user-select-none"
|
||||
className="relative user-select-none my-2"
|
||||
>
|
||||
<MentionNote
|
||||
eventId={element.eventId.replace("nostr:", "")}
|
||||
@@ -319,11 +319,9 @@ export function EditorForm() {
|
||||
setTarget(null);
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center justify-between h-16 px-3 border-b shrink-0 border-neutral-100 dark:border-neutral-900 bg-neutral-50 dark:bg-neutral-950">
|
||||
<div className="flex items-center justify-between h-16 pl-7 pr-3 border-b shrink-0 border-neutral-100 dark:border-neutral-900 bg-neutral-50 dark:bg-neutral-950">
|
||||
<div>
|
||||
<h3 className="font-semibold text-neutral-700 dark:text-neutral-500">
|
||||
New Post
|
||||
</h3>
|
||||
<h3 className="font-medium">New Post</h3>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="inline-flex items-center gap-2">
|
||||
@@ -346,7 +344,7 @@ export function EditorForm() {
|
||||
<div className="py-6 h-full overflow-y-auto px-7">
|
||||
<Editable
|
||||
key={JSON.stringify(editorValue)}
|
||||
autoFocus={false}
|
||||
autoFocus={true}
|
||||
autoCapitalize="none"
|
||||
autoCorrect="none"
|
||||
spellCheck={false}
|
||||
@@ -361,9 +359,9 @@ export function EditorForm() {
|
||||
className="top-[-9999px] left-[-9999px] absolute z-10 w-[250px] p-1 bg-white border border-neutral-50 dark:border-neutral-900 dark:bg-neutral-950 rounded-lg shadow-lg"
|
||||
>
|
||||
{filters.map((contact, i) => (
|
||||
// biome-ignore lint/a11y/useKeyWithClickEvents: <explanation>
|
||||
<div
|
||||
<button
|
||||
key={contact.npub}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
Transforms.select(editor, target);
|
||||
insertMention(editor, contact);
|
||||
@@ -379,7 +377,7 @@ export function EditorForm() {
|
||||
</div>
|
||||
</User.Root>
|
||||
</User.Provider>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</Portal>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { NDKCacheUserProfile } from "@lume/types";
|
||||
import { ReactNode } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { BaseEditor, Transforms } from "slate";
|
||||
import { type ReactEditor } from "slate-react";
|
||||
import { ReactEditor } from "slate-react";
|
||||
|
||||
export const Portal = ({ children }: { children?: ReactNode }) => {
|
||||
return typeof document === "object"
|
||||
@@ -36,6 +36,8 @@ export const insertImage = (editor: ReactEditor | BaseEditor, url: string) => {
|
||||
},
|
||||
];
|
||||
|
||||
// @ts-ignore, idk
|
||||
ReactEditor.focus(editor);
|
||||
Transforms.insertNodes(editor, image);
|
||||
Transforms.insertNodes(editor, extraText);
|
||||
};
|
||||
@@ -44,15 +46,24 @@ export const insertMention = (
|
||||
editor: ReactEditor | BaseEditor,
|
||||
contact: NDKCacheUserProfile,
|
||||
) => {
|
||||
const text = { text: "" };
|
||||
const mention = {
|
||||
type: "mention",
|
||||
npub: `nostr:${contact.npub}`,
|
||||
name: contact.name || contact.displayName || "anon",
|
||||
children: [{ text: "" }],
|
||||
children: [text],
|
||||
};
|
||||
const extraText = [
|
||||
{
|
||||
type: "paragraph",
|
||||
children: [text],
|
||||
},
|
||||
];
|
||||
|
||||
// @ts-ignore, idk
|
||||
ReactEditor.focus(editor);
|
||||
Transforms.insertNodes(editor, mention);
|
||||
Transforms.move(editor);
|
||||
Transforms.insertNodes(editor, extraText);
|
||||
};
|
||||
|
||||
export const insertNostrEvent = (
|
||||
|
||||
@@ -2,11 +2,11 @@ import {
|
||||
BellFilledIcon,
|
||||
BellIcon,
|
||||
ComposeFilledIcon,
|
||||
ComposeIcon,
|
||||
DepotFilledIcon,
|
||||
DepotIcon,
|
||||
HomeFilledIcon,
|
||||
HomeIcon,
|
||||
PlusIcon,
|
||||
SearchFilledIcon,
|
||||
SearchIcon,
|
||||
SettingsFilledIcon,
|
||||
@@ -44,11 +44,7 @@ export function Navigation() {
|
||||
: "bg-black/5 hover:bg-blue-500 dark:bg-white/5 dark:hover:bg-blue-500",
|
||||
)}
|
||||
>
|
||||
{isEditorOpen ? (
|
||||
<ComposeFilledIcon className="size-5" />
|
||||
) : (
|
||||
<ComposeIcon className="size-5" />
|
||||
)}
|
||||
<PlusIcon className="size-5" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="my-5 w-2/3 mx-auto h-px bg-black/10 dark:bg-white/10" />
|
||||
|
||||
@@ -57,8 +57,8 @@ export function OnboardingInterestScreen() {
|
||||
<div className="w-full flex-1 min-h-0 flex flex-col justify-between">
|
||||
<div className="flex-1 min-h-0 overflow-y-auto px-8 py-8">
|
||||
<div className="flex flex-col gap-8">
|
||||
{TOPICS.map((topic, index) => (
|
||||
<div key={topic.title + index} className="flex flex-col gap-4">
|
||||
{TOPICS.map((topic) => (
|
||||
<div key={topic.title} className="flex flex-col gap-4">
|
||||
<div className="w-full flex items-center justify-between">
|
||||
<div className="inline-flex items-center gap-2.5">
|
||||
<img
|
||||
@@ -79,6 +79,7 @@ export function OnboardingInterestScreen() {
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
{topic.content.map((hashtag) => (
|
||||
<button
|
||||
key={hashtag}
|
||||
type="button"
|
||||
onClick={() => toggleHashtag(hashtag)}
|
||||
className={cn(
|
||||
|
||||
@@ -35,19 +35,17 @@ export function OnboardingProfileScreen() {
|
||||
navigate("/interests");
|
||||
}
|
||||
|
||||
const oldProfile = await ark.getUserProfile();
|
||||
|
||||
const profile: NDKUserProfile = {
|
||||
const prevProfile = await ark.getUserProfile();
|
||||
const newProfile: NDKUserProfile = {
|
||||
...data,
|
||||
lud16: "", // temporary remove lud16
|
||||
nip05: oldProfile?.nip05 || "",
|
||||
nip05: prevProfile?.nip05 || "",
|
||||
bio: data.about,
|
||||
image: picture,
|
||||
picture: picture,
|
||||
};
|
||||
|
||||
const publish = await ark.createEvent({
|
||||
content: JSON.stringify(profile),
|
||||
content: JSON.stringify(newProfile),
|
||||
kind: NDKKind.Metadata,
|
||||
tags: [],
|
||||
});
|
||||
@@ -57,7 +55,7 @@ export function OnboardingProfileScreen() {
|
||||
await storage.clearProfileCache(ark.account.pubkey);
|
||||
await queryClient.setQueryData(
|
||||
["user", ark.account.pubkey],
|
||||
() => profile,
|
||||
() => newProfile,
|
||||
);
|
||||
|
||||
setLoading(false);
|
||||
|
||||
@@ -11,7 +11,7 @@ export function EventRoute() {
|
||||
return (
|
||||
<div className="pb-5 overflow-y-auto">
|
||||
<WindowVirtualizer>
|
||||
<div className="h-11 bg-neutral-50 dark:bg-neutral-950 border-b flex items-center justify-start gap-2 px-3 border-neutral-100 dark:border-neutral-900 mb-3">
|
||||
<div className="relative z-50 h-11 bg-neutral-50 dark:bg-neutral-950 border-b flex items-center justify-start gap-2 px-3 border-neutral-100 dark:border-neutral-900 mb-3">
|
||||
<button
|
||||
type="button"
|
||||
className="size-9 hover:bg-neutral-100 hover:text-blue-500 dark:hover:bg-neutral-900 rounded-lg inline-flex items-center justify-center"
|
||||
|
||||
@@ -114,11 +114,11 @@ export function SuggestRoute({ queryKey }: { queryKey: string[] }) {
|
||||
</div>
|
||||
<div className="flex flex-col divide-y divide-neutral-100 dark:divide-neutral-900">
|
||||
{isLoading ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<div className="flex h-44 w-full items-center justify-center">
|
||||
<LoaderIcon className="size-4 animate-spin" />
|
||||
</div>
|
||||
) : isError ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<div className="flex h-44 w-full items-center justify-center">
|
||||
Error. Cannot get trending users
|
||||
</div>
|
||||
) : (
|
||||
@@ -171,9 +171,9 @@ export function SuggestRoute({ queryKey }: { queryKey: string[] }) {
|
||||
type="button"
|
||||
onClick={submit}
|
||||
disabled={loading}
|
||||
className="inline-flex items-center justify-center gap-2 px-6 font-medium text-white transform bg-blue-500 rounded-full active:translate-y-1 w-36 h-11 hover:bg-blue-600 focus:outline-none disabled:cursor-not-allowed"
|
||||
className="inline-flex items-center justify-center gap-2 px-6 font-medium shadow-xl shadow-neutral-500/50 text-white transform bg-blue-500 rounded-full active:translate-y-1 w-36 h-11 hover:bg-blue-600 focus:outline-none disabled:cursor-not-allowed"
|
||||
>
|
||||
Save
|
||||
Save & Go Back
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -68,9 +68,9 @@ export function TranslateRegisterModal({ setAPIKey }) {
|
||||
<div className="flex-1 min-h-0 flex flex-col justify-between px-8 py-8">
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<p className="text-sm text-neutral-500">
|
||||
Translate Service is provided by{" "}
|
||||
<span className="text-blue-500">nostr.wine</span>, you need to
|
||||
deposit at least 2,500 sats to use translate 50,000 characters
|
||||
Translation Service is provided by{" "}
|
||||
<span className="text-blue-500">nostr.wine</span>. Prices
|
||||
start at 2,500 sats for 50,000 characters of translated text.
|
||||
</p>
|
||||
<p className="text-sm text-neutral-500">
|
||||
You can learn more about nostr.wine{" "}
|
||||
|
||||
@@ -5,13 +5,9 @@ export function TutorialManageColumnScreen() {
|
||||
<div className="px-5 h-full flex flex-col justify-between">
|
||||
<div className="h-full min-h-0 flex flex-col gap-2">
|
||||
<p>
|
||||
Lume is also provide simple way to customize column after creation.
|
||||
Once a new column is created, you can click on the title in its header
|
||||
to find options to <span className="font-semibold">customize</span> it
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-semibold">To customize each column,</span> you
|
||||
can go to header of each column
|
||||
</p>
|
||||
<p>Click to "Three Dots" icon</p>
|
||||
<img
|
||||
src="/tutorial-3.gif"
|
||||
alt="tutorial-3"
|
||||
|
||||
@@ -4,10 +4,10 @@ export function TutorialNewColumnScreen() {
|
||||
return (
|
||||
<div className="px-5 h-full flex flex-col justify-between">
|
||||
<div className="h-full min-h-0 flex flex-col gap-2">
|
||||
<p>Lume is column based, each column is each experience</p>
|
||||
<p>Lume is column based, each column is its own experience.</p>
|
||||
<p>
|
||||
<span className="font-semibold">To create new column,</span> you can
|
||||
look into bottom right part of screen
|
||||
<span className="font-semibold">To create a new column</span>, you can
|
||||
click on the "Plus" icon at bottom right corner of this window.
|
||||
</p>
|
||||
<p>Click to "Plus" icon</p>
|
||||
<img
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^5.17.15",
|
||||
"@tanstack/react-query": "^5.17.19",
|
||||
"clsx": "^2.1.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"jotai": "^2.6.2",
|
||||
"jotai": "^2.6.3",
|
||||
"nostr-tools": "1.17.0",
|
||||
"react": "^18.2.0",
|
||||
"tailwind-merge": "^2.2.0"
|
||||
"tailwind-merge": "^2.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lume/tsconfig": "workspace:^",
|
||||
|
||||
Reference in New Issue
Block a user