mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-29 16:30:55 +00:00
feat: supporting hash of github actions cache
This commit is contained in:
parent
43509fc943
commit
ff73c8ac88
4
.github/workflows/flatpak-bundle.yml
vendored
4
.github/workflows/flatpak-bundle.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
|||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: prepare-dist
|
path: prepare-dist
|
||||||
key: ${{ runner.os }}-container
|
key: ${{ runner.os }}-container-${{ hashFiles('prepare-dist') }}
|
||||||
- name: Run latest-tag
|
- name: Run latest-tag
|
||||||
id: latest-tag
|
id: latest-tag
|
||||||
uses: oprypin/find-latest-tag@v1
|
uses: oprypin/find-latest-tag@v1
|
||||||
@ -31,7 +31,7 @@ jobs:
|
|||||||
# repository: ${{ github.repository }}
|
# repository: ${{ github.repository }}
|
||||||
|
|
||||||
- name: Build container
|
- name: Build container
|
||||||
if: steps.cache-container.outputs.cache-hit != 'true'
|
# if: steps.cache-container.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
docker buildx build -t flatpak-prepare-lume --build-arg=${{steps.latest-tag.outputs.tag}} --rm --output=. --target=final -f flatpak/Containerfile .
|
docker buildx build -t flatpak-prepare-lume --build-arg=${{steps.latest-tag.outputs.tag}} --rm --output=. --target=final -f flatpak/Containerfile .
|
||||||
- name: Copy flatpak files content
|
- name: Copy flatpak files content
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
"@radix-ui/react-accordion": "^1.1.2",
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-avatar": "^1.0.4",
|
"@radix-ui/react-avatar": "^1.0.4",
|
||||||
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-collapsible": "^1.0.3",
|
"@radix-ui/react-collapsible": "^1.0.3",
|
||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||||
@ -33,9 +34,9 @@
|
|||||||
"@radix-ui/react-select": "^2.0.0",
|
"@radix-ui/react-select": "^2.0.0",
|
||||||
"@radix-ui/react-switch": "^1.0.3",
|
"@radix-ui/react-switch": "^1.0.3",
|
||||||
"@radix-ui/react-tooltip": "^1.0.7",
|
"@radix-ui/react-tooltip": "^1.0.7",
|
||||||
"@tanstack/react-query": "^5.17.15",
|
"@tanstack/react-query": "^5.17.19",
|
||||||
"framer-motion": "^10.18.0",
|
"framer-motion": "^10.18.0",
|
||||||
"jotai": "^2.6.2",
|
"jotai": "^2.6.3",
|
||||||
"minidenticons": "^4.2.0",
|
"minidenticons": "^4.2.0",
|
||||||
"nanoid": "^5.0.4",
|
"nanoid": "^5.0.4",
|
||||||
"nostr-fetch": "^0.15.0",
|
"nostr-fetch": "^0.15.0",
|
||||||
@ -45,15 +46,15 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hook-form": "^7.49.3",
|
"react-hook-form": "^7.49.3",
|
||||||
"react-router-dom": "^6.21.3",
|
"react-router-dom": "^6.21.3",
|
||||||
"smol-toml": "^1.1.3",
|
"smol-toml": "^1.1.4",
|
||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
"@lume/tsconfig": "workspace:^",
|
"@lume/tsconfig": "workspace:^",
|
||||||
"@lume/types": "workspace:^",
|
"@lume/types": "workspace:^",
|
||||||
"@types/node": "^20.11.5",
|
"@types/node": "^20.11.6",
|
||||||
"@types/react": "^18.2.48",
|
"@types/react": "^18.2.48",
|
||||||
"@types/react-dom": "^18.2.18",
|
"@types/react-dom": "^18.2.18",
|
||||||
"@vitejs/plugin-react-swc": "^3.5.0",
|
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||||
@ -63,7 +64,7 @@
|
|||||||
"postcss": "^8.4.33",
|
"postcss": "^8.4.33",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"vite": "^5.0.11",
|
"vite": "^5.0.12",
|
||||||
"vite-plugin-top-level-await": "^1.4.1",
|
"vite-plugin-top-level-await": "^1.4.1",
|
||||||
"vite-tsconfig-paths": "^4.3.1"
|
"vite-tsconfig-paths": "^4.3.1"
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,10 @@
|
|||||||
.prose :where(iframe):not(:where([class~='not-prose'] *)) {
|
.prose :where(iframe):not(:where([class~='not-prose'] *)) {
|
||||||
@apply w-full h-auto mx-auto aspect-video;
|
@apply w-full h-auto mx-auto aspect-video;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shadow-toolbar {
|
||||||
|
box-shadow: 0 0 #0000,0 0 #0000,0 8px 24px 0 rgba(0,0,0,.2),0 2px 8px 0 rgba(0,0,0,.08),inset 0 0 0 1px rgba(0,0,0,.2),inset 0 0 0 2px hsla(0,0%,100%,.14)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
|
@ -207,9 +207,6 @@ export default function Router() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "create",
|
path: "create",
|
||||||
loader: async () => {
|
|
||||||
return await ark.getOAuthServices();
|
|
||||||
},
|
|
||||||
async lazy() {
|
async lazy() {
|
||||||
const { CreateAccountScreen } = await import(
|
const { CreateAccountScreen } = await import(
|
||||||
"./routes/auth/create"
|
"./routes/auth/create"
|
||||||
@ -217,6 +214,27 @@ export default function Router() {
|
|||||||
return { Component: CreateAccountScreen };
|
return { Component: CreateAccountScreen };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "create-keys",
|
||||||
|
async lazy() {
|
||||||
|
const { CreateAccountKeys } = await import(
|
||||||
|
"./routes/auth/create-keys"
|
||||||
|
);
|
||||||
|
return { Component: CreateAccountKeys };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "create-address",
|
||||||
|
loader: async () => {
|
||||||
|
return await ark.getOAuthServices();
|
||||||
|
},
|
||||||
|
async lazy() {
|
||||||
|
const { CreateAccountAddress } = await import(
|
||||||
|
"./routes/auth/create-address"
|
||||||
|
);
|
||||||
|
return { Component: CreateAccountAddress };
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "login",
|
path: "login",
|
||||||
async lazy() {
|
async lazy() {
|
||||||
|
263
apps/desktop/src/routes/auth/create-address.tsx
Normal file
263
apps/desktop/src/routes/auth/create-address.tsx
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
import { useArk } from "@lume/ark";
|
||||||
|
import { CheckIcon, ChevronDownIcon, LoaderIcon } from "@lume/icons";
|
||||||
|
import { useStorage } from "@lume/storage";
|
||||||
|
import { onboardingAtom } from "@lume/utils";
|
||||||
|
import NDK, {
|
||||||
|
NDKEvent,
|
||||||
|
NDKKind,
|
||||||
|
NDKNip46Signer,
|
||||||
|
NDKPrivateKeySigner,
|
||||||
|
} from "@nostr-dev-kit/ndk";
|
||||||
|
import * as Select from "@radix-ui/react-select";
|
||||||
|
import { UnlistenFn } from "@tauri-apps/api/event";
|
||||||
|
import { Window } from "@tauri-apps/api/window";
|
||||||
|
import { useSetAtom } from "jotai";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useLoaderData, useNavigate } from "react-router-dom";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
const Item = ({ event }: { event: NDKEvent }) => {
|
||||||
|
const domain = JSON.parse(event.content).nip05.replace("_@", "");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select.Item
|
||||||
|
value={event.id}
|
||||||
|
className="relative flex items-center pr-10 leading-none rounded-md select-none text-neutral-100 rounded-mg h-9 pl-7"
|
||||||
|
>
|
||||||
|
<Select.ItemText>@{domain}</Select.ItemText>
|
||||||
|
<Select.ItemIndicator className="absolute left-0 inline-flex items-center justify-center transform h-7">
|
||||||
|
<CheckIcon className="size-4" />
|
||||||
|
</Select.ItemIndicator>
|
||||||
|
</Select.Item>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function CreateAccountAddress() {
|
||||||
|
const ark = useArk();
|
||||||
|
const storage = useStorage();
|
||||||
|
const services = useLoaderData() as NDKEvent[];
|
||||||
|
const setOnboarding = useSetAtom(onboardingAtom);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const [serviceId, setServiceId] = useState(services?.[0]?.id);
|
||||||
|
const [loading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { isValid },
|
||||||
|
} = useForm();
|
||||||
|
|
||||||
|
const getDomainName = (id: string) => {
|
||||||
|
const event = services.find((ev) => ev.id === id);
|
||||||
|
return JSON.parse(event.content).nip05.replace("_@", "") as string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = async (data: { username: string; email: string }) => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
const domain = getDomainName(serviceId);
|
||||||
|
const service = services.find((ev) => ev.id === serviceId);
|
||||||
|
|
||||||
|
// generate ndk for nsecbunker
|
||||||
|
const localSigner = NDKPrivateKeySigner.generate();
|
||||||
|
const bunker = new NDK({
|
||||||
|
explicitRelayUrls: [
|
||||||
|
"wss://relay.nsecbunker.com/",
|
||||||
|
"wss://nostr.vulpem.com/",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
await bunker.connect(2000);
|
||||||
|
|
||||||
|
// generate tmp remote singer for create account
|
||||||
|
const remoteSigner = new NDKNip46Signer(
|
||||||
|
bunker,
|
||||||
|
service.pubkey,
|
||||||
|
localSigner,
|
||||||
|
);
|
||||||
|
|
||||||
|
// handle auth url request
|
||||||
|
let unlisten: UnlistenFn;
|
||||||
|
let authWindow: Window;
|
||||||
|
let account: string = undefined;
|
||||||
|
|
||||||
|
remoteSigner.addListener("authUrl", async (authUrl: string) => {
|
||||||
|
authWindow = new Window(`auth-${serviceId}`, {
|
||||||
|
url: authUrl,
|
||||||
|
title: domain,
|
||||||
|
titleBarStyle: "overlay",
|
||||||
|
width: 600,
|
||||||
|
height: 650,
|
||||||
|
center: true,
|
||||||
|
closable: false,
|
||||||
|
});
|
||||||
|
unlisten = await authWindow.onCloseRequested(() => {
|
||||||
|
if (!account) {
|
||||||
|
setIsLoading(false);
|
||||||
|
unlisten();
|
||||||
|
|
||||||
|
return authWindow.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// create new account
|
||||||
|
account = await remoteSigner.createAccount(
|
||||||
|
data.username,
|
||||||
|
domain,
|
||||||
|
data.email,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!account) {
|
||||||
|
unlisten();
|
||||||
|
setIsLoading(false);
|
||||||
|
|
||||||
|
authWindow.close();
|
||||||
|
|
||||||
|
return toast.error("Failed to create new account, try again later");
|
||||||
|
}
|
||||||
|
|
||||||
|
unlisten();
|
||||||
|
authWindow.close();
|
||||||
|
|
||||||
|
// add account to storage
|
||||||
|
await storage.createSetting("nsecbunker", "1");
|
||||||
|
const newAccount = await storage.createAccount({
|
||||||
|
pubkey: account,
|
||||||
|
privkey: localSigner.privateKey,
|
||||||
|
});
|
||||||
|
ark.account = newAccount;
|
||||||
|
|
||||||
|
// get final signer with newly created account
|
||||||
|
const finalSigner = new NDKNip46Signer(bunker, account, localSigner);
|
||||||
|
await finalSigner.blockUntilReady();
|
||||||
|
|
||||||
|
// update main ndk instance signer
|
||||||
|
ark.updateNostrSigner({ signer: finalSigner });
|
||||||
|
|
||||||
|
// remove default nsecbunker profile and contact list
|
||||||
|
// await ark.createEvent({ kind: NDKKind.Metadata, content: "", tags: [] });
|
||||||
|
await ark.createEvent({ kind: NDKKind.Contacts, content: "", tags: [] });
|
||||||
|
|
||||||
|
setIsLoading(false);
|
||||||
|
setOnboarding({ open: true, newUser: true });
|
||||||
|
|
||||||
|
return navigate("/auth/onboarding", { replace: true });
|
||||||
|
} catch (e) {
|
||||||
|
setIsLoading(false);
|
||||||
|
toast.error(String(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative flex items-center justify-center w-full h-full">
|
||||||
|
<div className="flex flex-col w-full max-w-md gap-8 mx-auto">
|
||||||
|
<div className="flex flex-col gap-1 text-center items-center">
|
||||||
|
<h1 className="text-2xl font-semibold">
|
||||||
|
Let's set up your account on Nostr
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
{!services ? (
|
||||||
|
<div className="flex items-center justify-center w-full">
|
||||||
|
<LoaderIcon className="size-5 animate-spin" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<form
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
className="flex flex-col gap-3 mb-0"
|
||||||
|
>
|
||||||
|
<div className="flex flex-col gap-6 p-5 bg-neutral-950 rounded-2xl">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<label
|
||||||
|
htmlFor="username"
|
||||||
|
className="text-sm font-semibold uppercase text-neutral-600"
|
||||||
|
>
|
||||||
|
Username *
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<div className="flex items-center justify-between w-full gap-2 bg-neutral-900 rounded-xl">
|
||||||
|
<input
|
||||||
|
type={"text"}
|
||||||
|
{...register("username", {
|
||||||
|
required: true,
|
||||||
|
minLength: 1,
|
||||||
|
})}
|
||||||
|
spellCheck={false}
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
placeholder="alice"
|
||||||
|
className="flex-1 min-w-0 text-xl bg-transparent border-transparent outline-none focus:outline-none focus:ring-0 focus:border-none h-14 ring-0 placeholder:text-neutral-600"
|
||||||
|
/>
|
||||||
|
<Select.Root value={serviceId} onValueChange={setServiceId}>
|
||||||
|
<Select.Trigger className="inline-flex items-center justify-end gap-2 pr-3 text-xl font-semibold text-blue-500 w-max shrink-0">
|
||||||
|
<Select.Value>@{getDomainName(serviceId)}</Select.Value>
|
||||||
|
<Select.Icon>
|
||||||
|
<ChevronDownIcon className="size-5" />
|
||||||
|
</Select.Icon>
|
||||||
|
</Select.Trigger>
|
||||||
|
<Select.Portal>
|
||||||
|
<Select.Content className="rounded-lg border border-white/20 bg-white/10 backdrop-blur-xl">
|
||||||
|
<Select.Viewport className="p-3">
|
||||||
|
<Select.Group>
|
||||||
|
<Select.Label className="mb-2 text-sm font-medium uppercase px-7 text-neutral-600">
|
||||||
|
Choose a Provider
|
||||||
|
</Select.Label>
|
||||||
|
{services.map((service) => (
|
||||||
|
<Item key={service.id} event={service} />
|
||||||
|
))}
|
||||||
|
</Select.Group>
|
||||||
|
</Select.Viewport>
|
||||||
|
</Select.Content>
|
||||||
|
</Select.Portal>
|
||||||
|
</Select.Root>
|
||||||
|
</div>
|
||||||
|
<span className="text-sm text-neutral-600">
|
||||||
|
Use to login to Lume and other Nostr apps. You can choose
|
||||||
|
provider you trust to manage your account
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-1.5">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<label
|
||||||
|
htmlFor="email"
|
||||||
|
className="text-sm font-semibold uppercase text-neutral-600"
|
||||||
|
>
|
||||||
|
Backup Email (optional)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type={"email"}
|
||||||
|
{...register("email", { required: false })}
|
||||||
|
spellCheck={false}
|
||||||
|
autoCapitalize="none"
|
||||||
|
autoCorrect="none"
|
||||||
|
className="px-3 text-xl border-transparent rounded-xl h-14 bg-neutral-900 placeholder:text-neutral-600 focus:border-blue-500 focus:ring focus:ring-blue-800"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span className="text-sm text-neutral-600">
|
||||||
|
Use for recover your account if you lose your password
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={!isValid}
|
||||||
|
className="inline-flex items-center justify-center w-full text-lg h-12 font-medium text-white bg-blue-500 rounded-xl hover:bg-blue-600 disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<LoaderIcon className="size-5 animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Continue"
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
186
apps/desktop/src/routes/auth/create-keys.tsx
Normal file
186
apps/desktop/src/routes/auth/create-keys.tsx
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
import { useArk } from "@lume/ark";
|
||||||
|
import { CheckIcon, EyeOffIcon, EyeOnIcon, LoaderIcon } from "@lume/icons";
|
||||||
|
import { useStorage } from "@lume/storage";
|
||||||
|
import { onboardingAtom } from "@lume/utils";
|
||||||
|
import { NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
||||||
|
import * as Checkbox from "@radix-ui/react-checkbox";
|
||||||
|
import { desktopDir } from "@tauri-apps/api/path";
|
||||||
|
import { save } from "@tauri-apps/plugin-dialog";
|
||||||
|
import { writeTextFile } from "@tauri-apps/plugin-fs";
|
||||||
|
import { useSetAtom } from "jotai";
|
||||||
|
import { nanoid } from "nanoid";
|
||||||
|
import { getPublicKey, nip19 } from "nostr-tools";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export function CreateAccountKeys() {
|
||||||
|
const ark = useArk();
|
||||||
|
const storage = useStorage();
|
||||||
|
const setOnboarding = useSetAtom(onboardingAtom);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const [key, setKey] = useState("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [showKey, setShowKey] = useState(false);
|
||||||
|
const [confirm, setConfirm] = useState({ c1: false, c2: false, c3: false });
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
const privkey = nip19.decode(key).data as string;
|
||||||
|
const signer = new NDKPrivateKeySigner(privkey);
|
||||||
|
const pubkey = getPublicKey(privkey);
|
||||||
|
|
||||||
|
ark.updateNostrSigner({ signer });
|
||||||
|
|
||||||
|
const downloadPath = await desktopDir();
|
||||||
|
const fileName = `nostr_keys_${nanoid(4)}.txt`;
|
||||||
|
const filePath = await save({
|
||||||
|
defaultPath: `${downloadPath}/${fileName}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!filePath) {
|
||||||
|
return toast.info("You need to save account keys before continue.");
|
||||||
|
}
|
||||||
|
|
||||||
|
await writeTextFile(
|
||||||
|
filePath,
|
||||||
|
`Nostr Account\nGenerated by Lume (lume.nu)\n---\nPrivate key: ${key}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const newAccount = await storage.createAccount({
|
||||||
|
pubkey: pubkey,
|
||||||
|
privkey: privkey,
|
||||||
|
});
|
||||||
|
ark.account = newAccount;
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
setOnboarding({ open: true, newUser: true });
|
||||||
|
|
||||||
|
return navigate("/auth/onboarding", { replace: true });
|
||||||
|
} catch (e) {
|
||||||
|
setLoading(false);
|
||||||
|
toast.error(String(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const privkey = NDKPrivateKeySigner.generate().privateKey;
|
||||||
|
setKey(nip19.nsecEncode(privkey));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative flex items-center justify-center w-full h-full">
|
||||||
|
<div className="flex flex-col w-full max-w-md gap-8 mx-auto">
|
||||||
|
<div className="flex flex-col gap-1 text-center items-center">
|
||||||
|
<h1 className="text-2xl font-semibold">
|
||||||
|
This is your new Account Key
|
||||||
|
</h1>
|
||||||
|
<p className="text-lg font-medium leading-snug text-neutral-600 dark:text-neutral-500">
|
||||||
|
Keep your key in safe place. If you lose this key, you will lose
|
||||||
|
access to your account.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-6 mb-0">
|
||||||
|
<div className="flex flex-col gap-6">
|
||||||
|
<div className="relative">
|
||||||
|
<input
|
||||||
|
readOnly
|
||||||
|
value={key}
|
||||||
|
type={showKey ? "text" : "password"}
|
||||||
|
className="pl-3 pr-14 w-full resize-none text-xl border-transparent rounded-xl h-14 bg-neutral-900 placeholder:text-neutral-600 focus:border-blue-500 focus:ring focus:ring-blue-800"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowKey((state) => !state)}
|
||||||
|
className="absolute right-2 top-2 size-10 inline-flex items-center justify-center rounded-lg text-white bg-neutral-800 hover:bg-neutral-700"
|
||||||
|
>
|
||||||
|
{showKey ? (
|
||||||
|
<EyeOnIcon className="size-5" />
|
||||||
|
) : (
|
||||||
|
<EyeOffIcon className="size-5" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Checkbox.Root
|
||||||
|
checked={confirm.c1}
|
||||||
|
onCheckedChange={() =>
|
||||||
|
setConfirm((state) => ({ ...state, c1: !state.c1 }))
|
||||||
|
}
|
||||||
|
className="flex size-7 appearance-none items-center justify-center rounded-lg bg-neutral-900 outline-none"
|
||||||
|
id="confirm1"
|
||||||
|
>
|
||||||
|
<Checkbox.Indicator className="text-blue-500">
|
||||||
|
<CheckIcon className="size-4" />
|
||||||
|
</Checkbox.Indicator>
|
||||||
|
</Checkbox.Root>
|
||||||
|
<label
|
||||||
|
className="text-sm leading-none text-neutral-500"
|
||||||
|
htmlFor="confirm1"
|
||||||
|
>
|
||||||
|
I understand the risk of lost private key.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Checkbox.Root
|
||||||
|
checked={confirm.c2}
|
||||||
|
onCheckedChange={() =>
|
||||||
|
setConfirm((state) => ({ ...state, c2: !state.c2 }))
|
||||||
|
}
|
||||||
|
className="flex size-7 appearance-none items-center justify-center rounded-lg bg-neutral-900 outline-none"
|
||||||
|
id="confirm2"
|
||||||
|
>
|
||||||
|
<Checkbox.Indicator className="text-blue-500">
|
||||||
|
<CheckIcon className="size-4" />
|
||||||
|
</Checkbox.Indicator>
|
||||||
|
</Checkbox.Root>
|
||||||
|
<label
|
||||||
|
className="text-sm leading-none text-neutral-500"
|
||||||
|
htmlFor="confirm2"
|
||||||
|
>
|
||||||
|
I will make sure keep it safe and not sharing with anyone.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Checkbox.Root
|
||||||
|
checked={confirm.c3}
|
||||||
|
onCheckedChange={() =>
|
||||||
|
setConfirm((state) => ({ ...state, c3: !state.c3 }))
|
||||||
|
}
|
||||||
|
className="flex size-7 appearance-none items-center justify-center rounded-lg bg-neutral-900 outline-none"
|
||||||
|
id="confirm3"
|
||||||
|
>
|
||||||
|
<Checkbox.Indicator className="text-blue-500">
|
||||||
|
<CheckIcon className="size-4" />
|
||||||
|
</Checkbox.Indicator>
|
||||||
|
</Checkbox.Root>
|
||||||
|
<label
|
||||||
|
className="text-sm leading-none text-neutral-500"
|
||||||
|
htmlFor="confirm3"
|
||||||
|
>
|
||||||
|
I understand I cannot recover private key.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={submit}
|
||||||
|
disabled={!confirm.c1 || !confirm.c2 || !confirm.c3}
|
||||||
|
className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-white bg-blue-500 rounded-xl hover:bg-blue-600 disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<LoaderIcon className="size-5 animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Save key & Continue"
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -1,192 +1,21 @@
|
|||||||
import { useArk } from "@lume/ark";
|
import { LoaderIcon } from "@lume/icons";
|
||||||
import { CheckIcon, ChevronDownIcon, LoaderIcon } from "@lume/icons";
|
import { cn } from "@lume/utils";
|
||||||
import { useStorage } from "@lume/storage";
|
|
||||||
import { onboardingAtom } from "@lume/utils";
|
|
||||||
import NDK, {
|
|
||||||
NDKEvent,
|
|
||||||
NDKKind,
|
|
||||||
NDKNip46Signer,
|
|
||||||
NDKPrivateKeySigner,
|
|
||||||
} from "@nostr-dev-kit/ndk";
|
|
||||||
import * as Select from "@radix-ui/react-select";
|
|
||||||
import { UnlistenFn } from "@tauri-apps/api/event";
|
|
||||||
import { desktopDir } from "@tauri-apps/api/path";
|
|
||||||
import { Window } from "@tauri-apps/api/window";
|
|
||||||
import { save } from "@tauri-apps/plugin-dialog";
|
|
||||||
import { writeTextFile } from "@tauri-apps/plugin-fs";
|
|
||||||
import { useSetAtom } from "jotai";
|
|
||||||
import { nanoid } from "nanoid";
|
|
||||||
import { getPublicKey, nip19 } from "nostr-tools";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import { useLoaderData, useNavigate } from "react-router-dom";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
|
|
||||||
const Item = ({ event }: { event: NDKEvent }) => {
|
|
||||||
const domain = JSON.parse(event.content).nip05.replace("_@", "");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Select.Item
|
|
||||||
value={event.id}
|
|
||||||
className="relative flex items-center pr-10 leading-none rounded-md select-none text-neutral-100 rounded-mg h-9 pl-7"
|
|
||||||
>
|
|
||||||
<Select.ItemText>@{domain}</Select.ItemText>
|
|
||||||
<Select.ItemIndicator className="absolute left-0 inline-flex items-center justify-center transform h-7">
|
|
||||||
<CheckIcon className="size-4" />
|
|
||||||
</Select.ItemIndicator>
|
|
||||||
</Select.Item>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CreateAccountScreen() {
|
export function CreateAccountScreen() {
|
||||||
const ark = useArk();
|
|
||||||
const storage = useStorage();
|
|
||||||
const services = useLoaderData() as NDKEvent[];
|
|
||||||
const setOnboarding = useSetAtom(onboardingAtom);
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [serviceId, setServiceId] = useState(services?.[0]?.id);
|
const [method, setMethod] = useState<"self" | "managed">("self");
|
||||||
const [loading, setIsLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const {
|
const next = () => {
|
||||||
register,
|
setLoading(true);
|
||||||
handleSubmit,
|
|
||||||
formState: { isValid },
|
|
||||||
} = useForm();
|
|
||||||
|
|
||||||
const getDomainName = (id: string) => {
|
if (method === "self") {
|
||||||
const event = services.find((ev) => ev.id === id);
|
navigate("/auth/create-keys");
|
||||||
return JSON.parse(event.content).nip05.replace("_@", "") as string;
|
} else {
|
||||||
};
|
navigate("/auth/create-address");
|
||||||
|
|
||||||
const generateNostrKeys = async () => {
|
|
||||||
const signer = NDKPrivateKeySigner.generate();
|
|
||||||
const pubkey = getPublicKey(signer.privateKey);
|
|
||||||
|
|
||||||
const npub = nip19.npubEncode(pubkey);
|
|
||||||
const nsec = nip19.nsecEncode(signer.privateKey);
|
|
||||||
|
|
||||||
ark.updateNostrSigner({ signer });
|
|
||||||
|
|
||||||
const downloadPath = await desktopDir();
|
|
||||||
const fileName = `nostr_keys_${nanoid(4)}.txt`;
|
|
||||||
const filePath = await save({
|
|
||||||
defaultPath: `${downloadPath}/${fileName}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!filePath) {
|
|
||||||
return toast.info("You need to save account keys before continue.");
|
|
||||||
}
|
|
||||||
|
|
||||||
await writeTextFile(
|
|
||||||
filePath,
|
|
||||||
`Nostr Account\nGenerated by Lume (lume.nu)\n---\nPublic key: ${npub}\nPrivate key: ${nsec}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
await storage.createAccount({
|
|
||||||
pubkey: pubkey,
|
|
||||||
privkey: signer.privateKey,
|
|
||||||
});
|
|
||||||
|
|
||||||
setOnboarding({ open: true, newUser: true });
|
|
||||||
|
|
||||||
return navigate("/auth/onboarding", { replace: true });
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmit = async (data: { username: string; email: string }) => {
|
|
||||||
try {
|
|
||||||
setIsLoading(true);
|
|
||||||
|
|
||||||
const domain = getDomainName(serviceId);
|
|
||||||
const service = services.find((ev) => ev.id === serviceId);
|
|
||||||
|
|
||||||
// generate ndk for nsecbunker
|
|
||||||
const localSigner = NDKPrivateKeySigner.generate();
|
|
||||||
const bunker = new NDK({
|
|
||||||
explicitRelayUrls: [
|
|
||||||
"wss://relay.nsecbunker.com/",
|
|
||||||
"wss://nostr.vulpem.com/",
|
|
||||||
],
|
|
||||||
});
|
|
||||||
await bunker.connect(2000);
|
|
||||||
|
|
||||||
// generate tmp remote singer for create account
|
|
||||||
const remoteSigner = new NDKNip46Signer(
|
|
||||||
bunker,
|
|
||||||
service.pubkey,
|
|
||||||
localSigner,
|
|
||||||
);
|
|
||||||
|
|
||||||
// handle auth url request
|
|
||||||
let unlisten: UnlistenFn;
|
|
||||||
let authWindow: Window;
|
|
||||||
let account: string = undefined;
|
|
||||||
|
|
||||||
remoteSigner.addListener("authUrl", async (authUrl: string) => {
|
|
||||||
authWindow = new Window(`auth-${serviceId}`, {
|
|
||||||
url: authUrl,
|
|
||||||
title: domain,
|
|
||||||
titleBarStyle: "overlay",
|
|
||||||
width: 600,
|
|
||||||
height: 650,
|
|
||||||
center: true,
|
|
||||||
closable: false,
|
|
||||||
});
|
|
||||||
unlisten = await authWindow.onCloseRequested(() => {
|
|
||||||
if (!account) {
|
|
||||||
setIsLoading(false);
|
|
||||||
unlisten();
|
|
||||||
|
|
||||||
return authWindow.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// create new account
|
|
||||||
account = await remoteSigner.createAccount(
|
|
||||||
data.username,
|
|
||||||
domain,
|
|
||||||
data.email,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!account) {
|
|
||||||
unlisten();
|
|
||||||
setIsLoading(false);
|
|
||||||
|
|
||||||
authWindow.close();
|
|
||||||
|
|
||||||
return toast.error("Failed to create new account, try again later");
|
|
||||||
}
|
|
||||||
|
|
||||||
unlisten();
|
|
||||||
authWindow.close();
|
|
||||||
|
|
||||||
// add account to storage
|
|
||||||
await storage.createSetting("nsecbunker", "1");
|
|
||||||
const dbAccount = await storage.createAccount({
|
|
||||||
pubkey: account,
|
|
||||||
privkey: localSigner.privateKey,
|
|
||||||
});
|
|
||||||
ark.account = dbAccount;
|
|
||||||
|
|
||||||
// get final signer with newly created account
|
|
||||||
const finalSigner = new NDKNip46Signer(bunker, account, localSigner);
|
|
||||||
await finalSigner.blockUntilReady();
|
|
||||||
|
|
||||||
// update main ndk instance signer
|
|
||||||
ark.updateNostrSigner({ signer: finalSigner });
|
|
||||||
|
|
||||||
// remove default nsecbunker profile and contact list
|
|
||||||
// await ark.createEvent({ kind: NDKKind.Metadata, content: "", tags: [] });
|
|
||||||
await ark.createEvent({ kind: NDKKind.Contacts, content: "", tags: [] });
|
|
||||||
|
|
||||||
setIsLoading(false);
|
|
||||||
setOnboarding({ open: true, newUser: true });
|
|
||||||
|
|
||||||
return navigate("/auth/onboarding", { replace: true });
|
|
||||||
} catch (e) {
|
|
||||||
setIsLoading(false);
|
|
||||||
toast.error(String(e));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -194,148 +23,50 @@ export function CreateAccountScreen() {
|
|||||||
<div className="relative flex items-center justify-center w-full h-full">
|
<div className="relative flex items-center justify-center w-full h-full">
|
||||||
<div className="flex flex-col w-full max-w-md gap-8 mx-auto">
|
<div className="flex flex-col w-full max-w-md gap-8 mx-auto">
|
||||||
<div className="flex flex-col gap-1 text-center items-center">
|
<div className="flex flex-col gap-1 text-center items-center">
|
||||||
<h1 className="text-2xl font-semibold">
|
<h1 className="text-2xl font-semibold">Let's Get Started</h1>
|
||||||
Let's get you set up on Nostr.
|
<p className="text-lg font-medium leading-snug text-neutral-600 dark:text-neutral-500">
|
||||||
</h1>
|
Choose one of methods below to create your account
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setMethod("self")}
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col items-start px-4 py-3.5 bg-neutral-900 rounded-xl hover:bg-neutral-800",
|
||||||
|
method === "self" ? "ring-1 ring-teal-500" : "",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<p className="font-semibold">Self-Managed</p>
|
||||||
|
<p className="text-sm font-medium text-neutral-500">
|
||||||
|
You create your keys and keep them safe.
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setMethod("managed")}
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col items-start px-4 py-3.5 bg-neutral-900 rounded-xl hover:bg-neutral-800",
|
||||||
|
method === "managed" ? "ring-1 ring-teal-500" : "",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<p className="font-semibold">Managed by Provider</p>
|
||||||
|
<p className="text-sm font-medium text-neutral-500">
|
||||||
|
A 3rd party provider will handle your sign in keys for you.
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={next}
|
||||||
|
className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-white bg-blue-500 rounded-xl hover:bg-blue-600"
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<LoaderIcon className="size-5 animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Continue"
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{!services ? (
|
|
||||||
<div className="flex items-center justify-center w-full">
|
|
||||||
<LoaderIcon className="size-5 animate-spin" />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="flex flex-col gap-6">
|
|
||||||
<form
|
|
||||||
onSubmit={handleSubmit(onSubmit)}
|
|
||||||
className="flex flex-col gap-3 mb-0"
|
|
||||||
>
|
|
||||||
<div className="flex flex-col gap-6 p-5 bg-neutral-950 rounded-2xl">
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<label
|
|
||||||
htmlFor="username"
|
|
||||||
className="text-sm font-semibold uppercase text-neutral-600"
|
|
||||||
>
|
|
||||||
Username *
|
|
||||||
</label>
|
|
||||||
<div className="flex flex-col gap-1.5">
|
|
||||||
<div className="flex items-center justify-between w-full gap-2 bg-neutral-900 rounded-xl">
|
|
||||||
<input
|
|
||||||
type={"text"}
|
|
||||||
{...register("username", {
|
|
||||||
required: true,
|
|
||||||
minLength: 1,
|
|
||||||
})}
|
|
||||||
spellCheck={false}
|
|
||||||
autoComplete="off"
|
|
||||||
autoCorrect="off"
|
|
||||||
autoCapitalize="off"
|
|
||||||
placeholder="alice"
|
|
||||||
className="flex-1 min-w-0 text-xl bg-transparent border-transparent outline-none focus:outline-none focus:ring-0 focus:border-none h-14 ring-0 placeholder:text-neutral-600"
|
|
||||||
/>
|
|
||||||
<Select.Root
|
|
||||||
value={serviceId}
|
|
||||||
onValueChange={setServiceId}
|
|
||||||
>
|
|
||||||
<Select.Trigger className="inline-flex items-center justify-end gap-2 pr-3 text-xl font-semibold text-blue-500 w-max shrink-0">
|
|
||||||
<Select.Value>
|
|
||||||
@{getDomainName(serviceId)}
|
|
||||||
</Select.Value>
|
|
||||||
<Select.Icon>
|
|
||||||
<ChevronDownIcon className="size-5" />
|
|
||||||
</Select.Icon>
|
|
||||||
</Select.Trigger>
|
|
||||||
<Select.Portal>
|
|
||||||
<Select.Content className="rounded-lg border border-white/20 bg-white/10 backdrop-blur-xl">
|
|
||||||
<Select.Viewport className="p-3">
|
|
||||||
<Select.Group>
|
|
||||||
<Select.Label className="mb-2 text-sm font-medium uppercase px-7 text-neutral-600">
|
|
||||||
Choose a Provider
|
|
||||||
</Select.Label>
|
|
||||||
{services.map((service) => (
|
|
||||||
<Item key={service.id} event={service} />
|
|
||||||
))}
|
|
||||||
</Select.Group>
|
|
||||||
</Select.Viewport>
|
|
||||||
</Select.Content>
|
|
||||||
</Select.Portal>
|
|
||||||
</Select.Root>
|
|
||||||
</div>
|
|
||||||
<span className="text-sm text-neutral-600">
|
|
||||||
Use to login to Lume and other Nostr apps. You can choose
|
|
||||||
provider you trust to manage your account
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-1.5">
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<label
|
|
||||||
htmlFor="email"
|
|
||||||
className="text-sm font-semibold uppercase text-neutral-600"
|
|
||||||
>
|
|
||||||
Backup Email (optional)
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type={"email"}
|
|
||||||
{...register("email", { required: false })}
|
|
||||||
spellCheck={false}
|
|
||||||
autoCapitalize="none"
|
|
||||||
autoCorrect="none"
|
|
||||||
className="px-3 text-xl border-transparent rounded-xl h-14 bg-neutral-900 placeholder:text-neutral-600 focus:border-blue-500 focus:ring focus:ring-blue-800"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<span className="text-sm text-neutral-600">
|
|
||||||
Use for recover your account if you lose your password
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
disabled={!isValid}
|
|
||||||
className="inline-flex items-center justify-center w-full text-lg h-12 font-medium text-white bg-blue-500 rounded-xl hover:bg-blue-600 disabled:opacity-50"
|
|
||||||
>
|
|
||||||
{loading ? (
|
|
||||||
<LoaderIcon className="size-5 animate-spin" />
|
|
||||||
) : (
|
|
||||||
"Create Account"
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<div className="flex flex-col gap-6">
|
|
||||||
<div className="flex flex-col">
|
|
||||||
<div className="relative">
|
|
||||||
<div className="absolute inset-0 flex items-center">
|
|
||||||
<div className="w-full border-t border-neutral-900" />
|
|
||||||
</div>
|
|
||||||
<div className="relative flex justify-center">
|
|
||||||
<span className="px-2 font-medium bg-black text-neutral-500">
|
|
||||||
Or manage your own keys
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span className="mx-auto text-xs font-medium bg-black text-neutral-600">
|
|
||||||
Mostly compatible with other Nostr clients
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={generateNostrKeys}
|
|
||||||
className="mb-2 inline-flex items-center justify-center w-full h-12 text-lg font-medium text-neutral-50 rounded-xl bg-neutral-950 hover:bg-neutral-900"
|
|
||||||
>
|
|
||||||
Generate Nostr Keys
|
|
||||||
</button>
|
|
||||||
<p className="text-sm text-center text-neutral-500">
|
|
||||||
If you are using this option, please make sure keep your keys
|
|
||||||
in safe place. You{" "}
|
|
||||||
<span className="text-red-600">cannot recover</span> if it
|
|
||||||
lost, all your data will be{" "}
|
|
||||||
<span className="text-red-600">lost forever.</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -130,7 +130,7 @@ export function LoginWithOAuth() {
|
|||||||
<div className="relative flex items-center justify-center w-full h-full">
|
<div className="relative flex items-center justify-center w-full h-full">
|
||||||
<div className="flex flex-col w-full max-w-md gap-8 mx-auto">
|
<div className="flex flex-col w-full max-w-md gap-8 mx-auto">
|
||||||
<div className="flex flex-col gap-1 text-center items-center">
|
<div className="flex flex-col gap-1 text-center items-center">
|
||||||
<h1 className="text-2xl font-semibold">Enter your NIP-05 address</h1>
|
<h1 className="text-2xl font-semibold">Enter your Nostr Address</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
<form
|
<form
|
||||||
|
@ -5,9 +5,7 @@ export function LoginScreen() {
|
|||||||
<div className="relative flex items-center justify-center w-full h-full">
|
<div className="relative flex items-center justify-center w-full h-full">
|
||||||
<div className="flex flex-col w-full max-w-md gap-8 mx-auto">
|
<div className="flex flex-col w-full max-w-md gap-8 mx-auto">
|
||||||
<div className="flex flex-col gap-1 text-center items-center">
|
<div className="flex flex-col gap-1 text-center items-center">
|
||||||
<h1 className="text-2xl font-semibold">
|
<h1 className="text-2xl font-semibold">Welcome back, anon!</h1>
|
||||||
Continue your experience on Nostr
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
@ -15,13 +13,13 @@ export function LoginScreen() {
|
|||||||
to="/auth/login-oauth"
|
to="/auth/login-oauth"
|
||||||
className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-white bg-blue-500 rounded-xl hover:bg-blue-600"
|
className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-white bg-blue-500 rounded-xl hover:bg-blue-600"
|
||||||
>
|
>
|
||||||
Login with Address
|
Login with Nostr Address
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
to="/auth/login-nsecbunker"
|
to="/auth/login-nsecbunker"
|
||||||
className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-neutral-50 rounded-xl bg-neutral-950 hover:bg-neutral-900"
|
className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-neutral-50 rounded-xl bg-neutral-950 hover:bg-neutral-900"
|
||||||
>
|
>
|
||||||
Login with nsecbunker
|
Login with nsecBunker
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
@ -31,7 +29,7 @@ export function LoginScreen() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="relative flex justify-center">
|
<div className="relative flex justify-center">
|
||||||
<span className="px-2 font-medium bg-black text-neutral-600">
|
<span className="px-2 font-medium bg-black text-neutral-600">
|
||||||
Or (Not recommended)
|
Or continue with
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -43,8 +41,10 @@ export function LoginScreen() {
|
|||||||
Login with Private Key
|
Login with Private Key
|
||||||
</Link>
|
</Link>
|
||||||
<p className="text-sm text-center text-neutral-500">
|
<p className="text-sm text-center text-neutral-500">
|
||||||
Lume will store your Private Key in{" "}
|
Lume will put your Private Key in{" "}
|
||||||
<span className="text-teal-600">OS Secure Storage</span>
|
<span className="text-teal-600">Secure Storage</span> depended
|
||||||
|
on your OS Platform. It will be secured by Password or Biometric
|
||||||
|
ID
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,10 +2,7 @@ import { useArk } from "@lume/ark";
|
|||||||
import { InfoIcon, LoaderIcon } from "@lume/icons";
|
import { InfoIcon, LoaderIcon } from "@lume/icons";
|
||||||
import { useStorage } from "@lume/storage";
|
import { useStorage } from "@lume/storage";
|
||||||
import { TranslateRegisterModal } from "@lume/ui";
|
import { TranslateRegisterModal } from "@lume/ui";
|
||||||
import { FETCH_LIMIT } from "@lume/utils";
|
|
||||||
import { NDKKind } from "@nostr-dev-kit/ndk";
|
|
||||||
import * as Switch from "@radix-ui/react-switch";
|
import * as Switch from "@radix-ui/react-switch";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
|
||||||
import {
|
import {
|
||||||
isPermissionGranted,
|
isPermissionGranted,
|
||||||
requestPermission,
|
requestPermission,
|
||||||
@ -17,7 +14,6 @@ import { toast } from "sonner";
|
|||||||
export function OnboardingScreen() {
|
export function OnboardingScreen() {
|
||||||
const ark = useArk();
|
const ark = useArk();
|
||||||
const storage = useStorage();
|
const storage = useStorage();
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@ -61,32 +57,7 @@ export function OnboardingScreen() {
|
|||||||
// get account contacts
|
// get account contacts
|
||||||
await ark.getUserContacts();
|
await ark.getUserContacts();
|
||||||
|
|
||||||
// refetch newsfeed
|
navigate("/", { replace: true });
|
||||||
await queryClient.prefetchInfiniteQuery({
|
|
||||||
queryKey: ["timeline-9999"],
|
|
||||||
initialPageParam: 0,
|
|
||||||
queryFn: async ({
|
|
||||||
signal,
|
|
||||||
pageParam,
|
|
||||||
}: {
|
|
||||||
signal: AbortSignal;
|
|
||||||
pageParam: number;
|
|
||||||
}) => {
|
|
||||||
const events = await ark.getInfiniteEvents({
|
|
||||||
filter: {
|
|
||||||
kinds: [NDKKind.Text, NDKKind.Repost],
|
|
||||||
authors: ark.account.contacts,
|
|
||||||
},
|
|
||||||
limit: FETCH_LIMIT,
|
|
||||||
pageParam,
|
|
||||||
signal,
|
|
||||||
});
|
|
||||||
|
|
||||||
return events;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
navigate("/");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -117,7 +88,7 @@ export function OnboardingScreen() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex h-full w-full items-center justify-center">
|
<div className="relative flex h-full w-full items-center justify-center">
|
||||||
<div className="mx-auto flex w-full max-w-md flex-col gap-10">
|
<div className="mx-auto flex w-full max-w-md flex-col gap-8">
|
||||||
<div className="flex flex-col gap-1 text-center items-center">
|
<div className="flex flex-col gap-1 text-center items-center">
|
||||||
<h1 className="text-2xl font-semibold">
|
<h1 className="text-2xl font-semibold">
|
||||||
You're almost ready to use Lume.
|
You're almost ready to use Lume.
|
||||||
@ -194,7 +165,7 @@ export function OnboardingScreen() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="relative flex justify-center">
|
<div className="relative flex justify-center">
|
||||||
<span className="px-2 text-sm font-medium bg-neutral-950 text-neutral-600">
|
<span className="px-2 text-sm font-medium bg-neutral-950 text-neutral-600">
|
||||||
Not have API ?
|
Don't have an API key?
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,16 +1,6 @@
|
|||||||
import { LoaderIcon } from "@lume/icons";
|
import { Link } from "react-router-dom";
|
||||||
import { useState } from "react";
|
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
export function WelcomeScreen() {
|
export function WelcomeScreen() {
|
||||||
const navigate = useNavigate();
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
|
|
||||||
const gotoCreateAccount = () => {
|
|
||||||
setLoading(true);
|
|
||||||
navigate("/auth/create");
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center justify-between w-full h-full">
|
<div className="flex flex-col items-center justify-between w-full h-full">
|
||||||
<div />
|
<div />
|
||||||
@ -29,17 +19,12 @@ export function WelcomeScreen() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col w-full max-w-xs gap-2 mx-auto">
|
<div className="flex flex-col w-full max-w-xs gap-2 mx-auto">
|
||||||
<button
|
<Link
|
||||||
type="button"
|
to="/auth/create"
|
||||||
onClick={gotoCreateAccount}
|
|
||||||
className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-white bg-blue-500 rounded-xl hover:bg-blue-600"
|
className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-white bg-blue-500 rounded-xl hover:bg-blue-600"
|
||||||
>
|
>
|
||||||
{loading ? (
|
Join Nostr
|
||||||
<LoaderIcon className="size-5 animate-spin" />
|
</Link>
|
||||||
) : (
|
|
||||||
"Create New Account"
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
<Link
|
<Link
|
||||||
to="/auth/login"
|
to="/auth/login"
|
||||||
className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-neutral-50 rounded-xl bg-neutral-950 hover:bg-neutral-900"
|
className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-neutral-50 rounded-xl bg-neutral-950 hover:bg-neutral-900"
|
||||||
@ -49,7 +34,7 @@ export function WelcomeScreen() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-center h-11">
|
<div className="flex items-center justify-center h-11">
|
||||||
<p className="text-neutral-800">
|
<p className="text-neutral-700">
|
||||||
Before joining Nostr, you can take time to learn more about Nostr{" "}
|
Before joining Nostr, you can take time to learn more about Nostr{" "}
|
||||||
<Link
|
<Link
|
||||||
to="https://nostr.com"
|
to="https://nostr.com"
|
||||||
|
@ -10,7 +10,7 @@ import { useColumnContext } from "@lume/ark";
|
|||||||
import {
|
import {
|
||||||
ArrowLeftIcon,
|
ArrowLeftIcon,
|
||||||
ArrowRightIcon,
|
ArrowRightIcon,
|
||||||
NewColumnIcon,
|
PlusIcon,
|
||||||
PlusSquareIcon,
|
PlusSquareIcon,
|
||||||
} from "@lume/icons";
|
} from "@lume/icons";
|
||||||
import { IColumn } from "@lume/types";
|
import { IColumn } from "@lume/types";
|
||||||
@ -96,15 +96,15 @@ export function HomeScreen() {
|
|||||||
content: "",
|
content: "",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="size-16 inline-flex items-center justify-center rounded-full bg-blue-500 hover:bg-blue-600 text-white"
|
className="size-16 inline-flex items-center justify-center hover:bg-neutral-100 dark:hover:bg-neutral-900 rounded-2xl"
|
||||||
>
|
>
|
||||||
<NewColumnIcon className="size-7" />
|
<PlusIcon className="size-6" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</VList>
|
</VList>
|
||||||
<Tooltip.Provider>
|
<Tooltip.Provider>
|
||||||
<div className="absolute bottom-3 right-3">
|
<div className="absolute bottom-3 right-3">
|
||||||
<div className="flex items-center gap-1 p-1 bg-black/30 dark:bg-white/30 backdrop-blur-xl rounded-xl">
|
<div className="flex items-center gap-1 p-1 bg-black/50 dark:bg-white/30 backdrop-blur-xl rounded-xl shadow-toolbar">
|
||||||
<Tooltip.Root delayDuration={150}>
|
<Tooltip.Root delayDuration={150}>
|
||||||
<Tooltip.Trigger asChild>
|
<Tooltip.Trigger asChild>
|
||||||
<button
|
<button
|
||||||
|
@ -48,7 +48,7 @@ export function BackupSettingScreen() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => removePrivkey()}
|
onClick={() => removePrivkey()}
|
||||||
className="mt-2 inline-flex h-11 w-full items-center justify-center gap-2 rounded-lg bg-red-200 px-6 font-medium text-red-500 hover:bg-red-500 hover:text-white focus:outline-none dark:hover:text-white"
|
className="mt-2 inline-flex h-11 w-full items-center justify-center gap-2 rounded-lg bg-red-200 dark:bg-red-800 px-6 font-medium text-red-500 hover:bg-red-500 hover:text-white focus:outline-none dark:hover:text-white"
|
||||||
>
|
>
|
||||||
Remove private key
|
Remove private key
|
||||||
</button>
|
</button>
|
||||||
|
@ -10,6 +10,7 @@ import { NDKKind, NDKUserProfile } from "@nostr-dev-kit/ndk";
|
|||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { AvatarUpload } from "./components/avatarUpload";
|
import { AvatarUpload } from "./components/avatarUpload";
|
||||||
import { CoverUpload } from "./components/coverUpload";
|
import { CoverUpload } from "./components/coverUpload";
|
||||||
|
|
||||||
@ -92,6 +93,9 @@ export function ProfileSettingScreen() {
|
|||||||
return content;
|
return content;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// notify
|
||||||
|
toast.success("You've updated profile successfully.");
|
||||||
|
|
||||||
// reset state
|
// reset state
|
||||||
setPicture(null);
|
setPicture(null);
|
||||||
setBanner(null);
|
setBanner(null);
|
||||||
@ -112,7 +116,7 @@ export function ProfileSettingScreen() {
|
|||||||
className="h-full w-full rounded-t-xl object-cover"
|
className="h-full w-full rounded-t-xl object-cover"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-full w-full rounded-t-xl bg-neutral-200 dark:bg-neutral-900" />
|
<div className="h-full w-full rounded-t-xl bg-neutral-200 dark:bg-neutral-800" />
|
||||||
)}
|
)}
|
||||||
<div className="absolute right-4 top-4">
|
<div className="absolute right-4 top-4">
|
||||||
<CoverUpload setBanner={setBanner} />
|
<CoverUpload setBanner={setBanner} />
|
||||||
@ -236,7 +240,7 @@ export function ProfileSettingScreen() {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!isValid || loading}
|
disabled={!isValid || loading}
|
||||||
className="mx-auto inline-flex h-10 w-24 transform items-center justify-center gap-1 rounded-lg bg-blue-500 font-medium text-white hover:bg-blue-600 focus:outline-none active:translate-y-1 disabled:pointer-events-none disabled:opacity-50"
|
className="inline-flex items-center justify-center w-24 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"
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<LoaderIcon className="size-4 animate-spin" />
|
<LoaderIcon className="size-4 animate-spin" />
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
"@astrojs/check": "^0.4.1",
|
"@astrojs/check": "^0.4.1",
|
||||||
"@astrojs/tailwind": "^5.1.0",
|
"@astrojs/tailwind": "^5.1.0",
|
||||||
"@fontsource/geist-mono": "^5.0.1",
|
"@fontsource/geist-mono": "^5.0.1",
|
||||||
"astro": "^4.2.1",
|
"astro": "^4.2.4",
|
||||||
"astro-seo-meta": "^4.1.0",
|
"astro-seo-meta": "^4.1.0",
|
||||||
"astro-seo-schema": "^4.0.0",
|
"astro-seo-schema": "^4.0.0",
|
||||||
"schema-dts": "^1.1.2",
|
"schema-dts": "^1.1.2",
|
||||||
|
@ -35,8 +35,8 @@ RUN pnpm install --frozen-lockfile
|
|||||||
# Path for disable updater
|
# Path for disable updater
|
||||||
#ADD flatpak/0001-disable-tauri-updater.patch .
|
#ADD flatpak/0001-disable-tauri-updater.patch .
|
||||||
#RUN patch -p1 -t -i flatpak/0001-disable-tauri-updater.patch
|
#RUN patch -p1 -t -i flatpak/0001-disable-tauri-updater.patch
|
||||||
ADD flatpak/0002-depot-remove.patch .
|
#ADD flatpak/0002-depot-remove.patch .
|
||||||
RUN patch -p1 -t -i 0002-depot-remove.patch
|
#RUN patch -p1 -t -i 0002-depot-remove.patch
|
||||||
|
|
||||||
# compile depot
|
# compile depot
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"tauri": "tauri"
|
"tauri": "tauri"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.5.2",
|
"@biomejs/biome": "^1.5.3",
|
||||||
"@tauri-apps/cli": "2.0.0-alpha.21",
|
"@tauri-apps/cli": "2.0.0-alpha.21",
|
||||||
"turbo": "^1.11.3"
|
"turbo": "^1.11.3"
|
||||||
},
|
},
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
"@radix-ui/react-hover-card": "^1.0.7",
|
"@radix-ui/react-hover-card": "^1.0.7",
|
||||||
"@radix-ui/react-popover": "^1.0.7",
|
"@radix-ui/react-popover": "^1.0.7",
|
||||||
"@radix-ui/react-tooltip": "^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",
|
"get-urls": "^12.1.0",
|
||||||
"jotai": "^2.6.2",
|
"jotai": "^2.6.3",
|
||||||
"linkify-react": "^4.1.3",
|
"linkify-react": "^4.1.3",
|
||||||
"linkifyjs": "^4.1.3",
|
"linkifyjs": "^4.1.3",
|
||||||
"media-chrome": "^2.1.0",
|
"media-chrome": "^2.1.0",
|
||||||
@ -38,14 +38,14 @@
|
|||||||
"string-strip-html": "^13.4.5",
|
"string-strip-html": "^13.4.5",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"use-context-selector": "^1.4.1",
|
"use-context-selector": "^1.4.1",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
"@lume/tsconfig": "workspace:^",
|
"@lume/tsconfig": "workspace:^",
|
||||||
"@lume/types": "workspace:^",
|
"@lume/types": "workspace:^",
|
||||||
"@types/react": "^18.2.48",
|
"@types/react": "^18.2.48",
|
||||||
"tailwind-merge": "^2.2.0",
|
"tailwind-merge": "^2.2.1",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ export class Ark {
|
|||||||
cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST,
|
cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!profile) throw new Error("user not found");
|
if (!profile) return null;
|
||||||
return profile;
|
return profile;
|
||||||
} catch {
|
} catch {
|
||||||
throw new Error("user not found");
|
throw new Error("user not found");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
HorizontalDotsIcon,
|
ChevronDownIcon,
|
||||||
MoveLeftIcon,
|
MoveLeftIcon,
|
||||||
MoveRightIcon,
|
MoveRightIcon,
|
||||||
RefreshIcon,
|
RefreshIcon,
|
||||||
@ -43,78 +43,71 @@ export function ColumnHeader({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
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">
|
<DropdownMenu.Root>
|
||||||
<div className="inline-flex items-center gap-4">
|
<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">
|
||||||
<div className="inline-flex items-center flex-1 gap-2 text-neutral-800 dark:text-neutral-200">
|
<DropdownMenu.Trigger asChild>
|
||||||
{icon ? icon : <ThreadIcon className="size-4" />}
|
<div className="inline-flex items-center gap-1.5">
|
||||||
<div className="text-sm font-medium">{title}</div>
|
<div className="text-[13px] font-medium">{title}</div>
|
||||||
</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>
|
||||||
<div>
|
</DropdownMenu.Root>
|
||||||
<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>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ export function InterestModal({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (save) {
|
if (save) {
|
||||||
storage.interests.hashtags = hashtags;
|
storage.interests = { hashtags, users: [], words: [] };
|
||||||
await queryClient.refetchQueries({ queryKey });
|
await queryClient.refetchQueries({ queryKey });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ export function InterestModal({
|
|||||||
<Dialog.Root open={open} onOpenChange={setOpen}>
|
<Dialog.Root open={open} onOpenChange={setOpen}>
|
||||||
<Dialog.Trigger
|
<Dialog.Trigger
|
||||||
className={cn(
|
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,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@ -64,7 +64,7 @@ export function InterestModal({
|
|||||||
children
|
children
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<EditInterestIcon className="size-5" />
|
<EditInterestIcon className="size-4" />
|
||||||
Edit interest
|
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="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-1 min-h-0 overflow-y-auto px-8 py-8">
|
||||||
<div className="flex flex-col gap-8">
|
<div className="flex flex-col gap-8">
|
||||||
{TOPICS.map((topic, index) => (
|
{TOPICS.map((topic) => (
|
||||||
<div
|
<div key={topic.title} className="flex flex-col gap-4">
|
||||||
key={topic.title + index}
|
|
||||||
className="flex flex-col gap-4"
|
|
||||||
>
|
|
||||||
<div className="w-full flex items-center justify-between">
|
<div className="w-full flex items-center justify-between">
|
||||||
<div className="inline-flex items-center gap-2.5">
|
<div className="inline-flex items-center gap-2.5">
|
||||||
<img
|
<img
|
||||||
@ -113,6 +110,7 @@ export function InterestModal({
|
|||||||
<div className="flex flex-wrap items-center gap-3">
|
<div className="flex flex-wrap items-center gap-3">
|
||||||
{topic.content.map((hashtag) => (
|
{topic.content.map((hashtag) => (
|
||||||
<button
|
<button
|
||||||
|
key={hashtag}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => toggleHashtag(hashtag)}
|
onClick={() => toggleHashtag(hashtag)}
|
||||||
className={cn(
|
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 { NDKEvent, NDKFilter } from "@nostr-dev-kit/ndk";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useArk } from "../../hooks/useArk";
|
import { useArk } from "../../hooks/useArk";
|
||||||
@ -34,14 +34,14 @@ export function ColumnLiveWidget({
|
|||||||
if (!events.length) return null;
|
if (!events.length) return null;
|
||||||
|
|
||||||
return (
|
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
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={update}
|
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"}
|
{events.length} {events.length === 1 ? "new note" : "new notes"}
|
||||||
|
<ArrowUpIcon className="size-4" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -55,7 +55,10 @@ export function ColumnProvider({ children }: { children: ReactNode }) {
|
|||||||
column.title,
|
column.title,
|
||||||
column.content,
|
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) => {
|
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 * as Tooltip from "@radix-ui/react-tooltip";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useNoteContext } from "../provider";
|
import { useNoteContext } from "../provider";
|
||||||
@ -16,12 +16,12 @@ export function NoteReply() {
|
|||||||
onClick={() => navigate(`/events/${event.id}`)}
|
onClick={() => navigate(`/events/${event.id}`)}
|
||||||
className="inline-flex items-center justify-center group h-7 w-7 text-neutral-600 dark:text-neutral-400"
|
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>
|
</button>
|
||||||
</Tooltip.Trigger>
|
</Tooltip.Trigger>
|
||||||
<Tooltip.Portal>
|
<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">
|
<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.Arrow className="fill-neutral-950 dark:fill-neutral-50" />
|
||||||
</Tooltip.Content>
|
</Tooltip.Content>
|
||||||
</Tooltip.Portal>
|
</Tooltip.Portal>
|
||||||
|
@ -88,12 +88,12 @@ export function NoteRepost() {
|
|||||||
</Tooltip.Root>
|
</Tooltip.Root>
|
||||||
</Tooltip.Provider>
|
</Tooltip.Provider>
|
||||||
<DropdownMenu.Portal>
|
<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>
|
<DropdownMenu.Item asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={repost}
|
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" />
|
<RepostIcon className="size-4" />
|
||||||
Repost
|
Repost
|
||||||
@ -103,7 +103,7 @@ export function NoteRepost() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={quote}
|
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" />
|
<ReplyIcon className="size-4" />
|
||||||
Quote
|
Quote
|
||||||
|
@ -131,10 +131,18 @@ export function NoteZap() {
|
|||||||
</Tooltip.Root>
|
</Tooltip.Root>
|
||||||
</Tooltip.Provider>
|
</Tooltip.Provider>
|
||||||
<Dialog.Portal>
|
<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.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="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" />
|
<div className="w-6" />
|
||||||
<Dialog.Title className="font-semibold text-center">
|
<Dialog.Title className="font-semibold text-center">
|
||||||
Send zap to{" "}
|
Send zap to{" "}
|
||||||
@ -142,13 +150,10 @@ export function NoteZap() {
|
|||||||
user?.displayName ||
|
user?.displayName ||
|
||||||
displayNpub(event.pubkey, 16)}
|
displayNpub(event.pubkey, 16)}
|
||||||
</Dialog.Title>
|
</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>
|
</div>
|
||||||
{!invoice ? (
|
{!invoice ? (
|
||||||
<div className="px-5 pb-5 overflow-x-hidden overflow-y-auto">
|
<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">
|
<div className="inline-flex items-center justify-center flex-1 h-full gap-1">
|
||||||
<CurrencyInput
|
<CurrencyInput
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
@ -213,13 +218,13 @@ export function NoteZap() {
|
|||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
autoCapitalize="off"
|
autoCapitalize="off"
|
||||||
placeholder="Enter message (optional)"
|
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">
|
<div className="flex flex-col gap-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => createZapRequest()}
|
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
|
{isCompleted
|
||||||
? "Zapped"
|
? "Zapped"
|
||||||
|
@ -14,18 +14,18 @@ export function MentionUser({ pubkey }: { pubkey: string }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Root>
|
<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
|
{isLoading
|
||||||
? "@anon"
|
? "@anon"
|
||||||
: isError
|
: isError
|
||||||
? pubkey
|
? pubkey
|
||||||
: `@${user?.name || user?.displayName || user?.username || "anon"}`}
|
: `@${user?.name || user?.displayName || user?.username || "anon"}`}
|
||||||
</DropdownMenu.Trigger>
|
</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>
|
<DropdownMenu.Item asChild>
|
||||||
<Link
|
<Link
|
||||||
to={`/users/${cleanPubkey}`}
|
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
|
View profile
|
||||||
</Link>
|
</Link>
|
||||||
@ -40,7 +40,7 @@ export function MentionUser({ pubkey }: { pubkey: string }) {
|
|||||||
content: cleanPubkey,
|
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
|
Pin
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
import { HorizontalDotsIcon } from "@lume/icons";
|
import { HorizontalDotsIcon } from "@lume/icons";
|
||||||
|
import { COL_TYPES } from "@lume/utils";
|
||||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||||
import { writeText } from "@tauri-apps/plugin-clipboard-manager";
|
import { writeText } from "@tauri-apps/plugin-clipboard-manager";
|
||||||
import { nip19 } from "nostr-tools";
|
import { nip19 } from "nostr-tools";
|
||||||
import { type EventPointer } from "nostr-tools/lib/types/nip19";
|
import { type EventPointer } from "nostr-tools/lib/types/nip19";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
import { useColumnContext } from "../column/provider";
|
||||||
import { useNoteContext } from "./provider";
|
import { useNoteContext } from "./provider";
|
||||||
|
|
||||||
export function NoteMenu() {
|
export function NoteMenu() {
|
||||||
const event = useNoteContext();
|
const event = useNoteContext();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { addColumn } = useColumnContext();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const copyID = async () => {
|
const copyID = async () => {
|
||||||
@ -50,18 +54,27 @@ export function NoteMenu() {
|
|||||||
<DropdownMenu.Trigger asChild>
|
<DropdownMenu.Trigger asChild>
|
||||||
<button
|
<button
|
||||||
type="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>
|
</button>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownMenu.Portal>
|
<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>
|
<DropdownMenu.Item asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => copyLink()}
|
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
|
Copy shareable link
|
||||||
</button>
|
</button>
|
||||||
@ -70,34 +83,49 @@ export function NoteMenu() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => copyID()}
|
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>
|
</button>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Item asChild>
|
<DropdownMenu.Item asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => copyNpub()}
|
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>
|
</button>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Item asChild>
|
<DropdownMenu.Item asChild>
|
||||||
<Link
|
<Link
|
||||||
to={`/users/${event.pubkey}`}
|
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>
|
</Link>
|
||||||
</DropdownMenu.Item>
|
</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>
|
<DropdownMenu.Item asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => copyRaw()}
|
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
|
Copy raw event
|
||||||
</button>
|
</button>
|
||||||
@ -106,7 +134,7 @@ export function NoteMenu() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={muteUser}
|
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
|
Mute
|
||||||
</button>
|
</button>
|
||||||
|
@ -48,12 +48,12 @@ export function ImagePreview({ url }: { url: string }) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={(e) => downloadImage(e)}
|
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 ? (
|
{downloaded ? (
|
||||||
<CheckCircleIcon className="size-4" />
|
<CheckCircleIcon className="size-5" />
|
||||||
) : (
|
) : (
|
||||||
<DownloadIcon className="size-4" />
|
<DownloadIcon className="size-5" />
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,7 +8,7 @@ export function ChildReply({
|
|||||||
<Note.Provider event={event}>
|
<Note.Provider event={event}>
|
||||||
<Note.Root className="py-2">
|
<Note.Root className="py-2">
|
||||||
<div className="flex items-center justify-between h-14">
|
<div className="flex items-center justify-between h-14">
|
||||||
<Note.User className="flex-1" />
|
<Note.User className="flex-1 pr-2" />
|
||||||
<Note.Menu />
|
<Note.Menu />
|
||||||
</div>
|
</div>
|
||||||
<Note.Content />
|
<Note.Content />
|
||||||
|
@ -18,7 +18,7 @@ export function Reply({
|
|||||||
<Note.Provider event={event}>
|
<Note.Provider event={event}>
|
||||||
<Note.Root className="pt-2">
|
<Note.Root className="pt-2">
|
||||||
<div className="flex items-center justify-between h-14">
|
<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 />
|
<Note.Menu />
|
||||||
</div>
|
</div>
|
||||||
<Note.Content />
|
<Note.Content />
|
||||||
|
@ -93,7 +93,7 @@ export function RepostNote({
|
|||||||
<Note.Provider event={repostEvent}>
|
<Note.Provider event={repostEvent}>
|
||||||
<div className="relative flex flex-col gap-2 px-3">
|
<div className="relative flex flex-col gap-2 px-3">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<Note.User className="flex-1 pr-1" />
|
<Note.User className="flex-1 pr-2" />
|
||||||
<Note.Menu />
|
<Note.Menu />
|
||||||
</div>
|
</div>
|
||||||
<Note.Content />
|
<Note.Content />
|
||||||
|
@ -15,7 +15,7 @@ export function TextNote({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between px-3 h-14">
|
<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 />
|
<Note.Menu />
|
||||||
</div>
|
</div>
|
||||||
<Note.Thread className="mb-2" />
|
<Note.Thread className="mb-2" />
|
||||||
|
@ -87,31 +87,18 @@ export const LumeProvider = ({ children }: PropsWithChildren<object>) => {
|
|||||||
|
|
||||||
async function initNDK() {
|
async function initNDK() {
|
||||||
const explicitRelayUrls = normalizeRelayUrlSet([
|
const explicitRelayUrls = normalizeRelayUrlSet([
|
||||||
|
"wss://nostr.mutinywallet.com/",
|
||||||
"wss://bostr.nokotaro.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 tauriCache = new NDKCacheAdapterTauri(storage);
|
||||||
const ndk = new NDK({
|
const ndk = new NDK({
|
||||||
cacheAdapter: tauriCache,
|
cacheAdapter: tauriCache,
|
||||||
explicitRelayUrls,
|
explicitRelayUrls,
|
||||||
outboxRelayUrls,
|
|
||||||
blacklistRelayUrls,
|
|
||||||
enableOutboxModel: !storage.settings.lowPower,
|
enableOutboxModel: !storage.settings.lowPower,
|
||||||
autoConnectUserRelays: !storage.settings.lowPower,
|
autoConnectUserRelays: !storage.settings.lowPower,
|
||||||
autoFetchUserMutelist: !storage.settings.lowPower,
|
autoFetchUserMutelist: !storage.settings.lowPower,
|
||||||
// clientName: "Lume",
|
clientName: "Lume",
|
||||||
// clientNip89: '',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// use tauri fetch
|
// use tauri fetch
|
||||||
|
@ -111,3 +111,4 @@ export * from "./src/foryou";
|
|||||||
export * from "./src/editInterest";
|
export * from "./src/editInterest";
|
||||||
export * from "./src/newColumn";
|
export * from "./src/newColumn";
|
||||||
export * from "./src/searchFilled";
|
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"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
strokeWidth="2"
|
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>
|
</svg>
|
||||||
);
|
);
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
import { SVGProps } from 'react';
|
import { SVGProps } from "react";
|
||||||
|
|
||||||
export function ChevronUpIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
export function ChevronUpIcon(
|
||||||
return (
|
props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
||||||
<svg
|
) {
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
return (
|
||||||
width="24"
|
<svg
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="none"
|
width="24"
|
||||||
viewBox="0 0 24 24"
|
height="24"
|
||||||
{...props}
|
fill="none"
|
||||||
>
|
viewBox="0 0 24 24"
|
||||||
<path
|
{...props}
|
||||||
stroke="currentColor"
|
>
|
||||||
strokeLinecap="round"
|
<path
|
||||||
strokeLinejoin="round"
|
stroke="currentColor"
|
||||||
strokeWidth="1.5"
|
strokeLinecap="round"
|
||||||
d="M8 14l3.646-3.646a.5.5 0 01.708 0L16 14"
|
strokeLinejoin="round"
|
||||||
></path>
|
strokeWidth="2"
|
||||||
</svg>
|
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>) {
|
export function DownloadIcon(
|
||||||
return (
|
props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
||||||
<svg
|
) {
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
return (
|
||||||
width="24"
|
<svg
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="none"
|
width="24"
|
||||||
viewBox="0 0 24 24"
|
height="24"
|
||||||
{...props}
|
fill="none"
|
||||||
>
|
viewBox="0 0 24 24"
|
||||||
<path
|
{...props}
|
||||||
stroke="currentColor"
|
>
|
||||||
strokeLinecap="round"
|
<path
|
||||||
strokeLinejoin="round"
|
stroke="currentColor"
|
||||||
strokeWidth="1.5"
|
strokeLinecap="round"
|
||||||
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"
|
strokeLinejoin="round"
|
||||||
></path>
|
strokeWidth="2"
|
||||||
</svg>
|
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"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
strokeWidth="2"
|
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>
|
</svg>
|
||||||
);
|
);
|
||||||
|
@ -6,13 +6,15 @@ export function RelayIcon(props: JSX.IntrinsicElements["svg"]) {
|
|||||||
height="24"
|
height="24"
|
||||||
fill="none"
|
fill="none"
|
||||||
viewBox="0 0 25 24"
|
viewBox="0 0 25 24"
|
||||||
stroke="currentColor"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="2"
|
|
||||||
{...props}
|
{...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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
export function ReplyIcon(props: JSX.IntrinsicElements["svg"]) {
|
export function ReplyIcon(props: JSX.IntrinsicElements["svg"]) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
{...props}
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="25"
|
width="25"
|
||||||
height="24"
|
height="24"
|
||||||
fill="none"
|
fill="none"
|
||||||
viewBox="0 0 25 24"
|
viewBox="0 0 25 24"
|
||||||
stroke="currentColor"
|
{...props}
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="2"
|
|
||||||
>
|
>
|
||||||
<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>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,24 @@
|
|||||||
import { SVGProps } from 'react';
|
import { SVGProps } from "react";
|
||||||
|
|
||||||
export function UserIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
export function UserIcon(
|
||||||
return (
|
props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
||||||
<svg
|
) {
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
return (
|
||||||
width="24"
|
<svg
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="none"
|
width="24"
|
||||||
viewBox="0 0 24 24"
|
height="24"
|
||||||
{...props}
|
fill="none"
|
||||||
>
|
viewBox="0 0 24 24"
|
||||||
<path
|
{...props}
|
||||||
stroke="currentColor"
|
>
|
||||||
strokeLinejoin="round"
|
<path
|
||||||
strokeWidth="1.5"
|
stroke="currentColor"
|
||||||
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"
|
strokeLinecap="round"
|
||||||
></path>
|
strokeLinejoin="round"
|
||||||
</svg>
|
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/ui": "workspace:^",
|
||||||
"@lume/utils": "workspace:^",
|
"@lume/utils": "workspace:^",
|
||||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||||
"@tanstack/react-query": "^5.17.15",
|
"@tanstack/react-query": "^5.17.19",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-router-dom": "^6.21.3",
|
"react-router-dom": "^6.21.3",
|
||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
"@lume/ui": "workspace:^",
|
"@lume/ui": "workspace:^",
|
||||||
"@lume/utils": "workspace:^",
|
"@lume/utils": "workspace:^",
|
||||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||||
"@tanstack/react-query": "^5.17.15",
|
"@tanstack/react-query": "^5.17.19",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-router-dom": "^6.21.3",
|
"react-router-dom": "^6.21.3",
|
||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
|
@ -14,19 +14,36 @@ export function Default({ column }: { column: IColumn }) {
|
|||||||
icon={<ColumnIcon className="size-4" />}
|
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="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-11 flex items-center gap-5">
|
||||||
<div className="h-[100px] w-full">
|
<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
|
<img
|
||||||
src="/columns/group.jpg"
|
src="/columns/group.jpg"
|
||||||
srcSet="/columns/group@2x.jpg 2x"
|
srcSet="/columns/group@2x.jpg 2x"
|
||||||
alt="group"
|
alt="group"
|
||||||
className="w-full h-auto object-cover"
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
className="w-full h-auto object-cover rounded-lg"
|
||||||
/>
|
/>
|
||||||
</div>
|
</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>
|
<div>
|
||||||
<h1 className="font-semibold">Group Feeds</h1>
|
<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.
|
Collective of people you're interested in.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -41,19 +58,21 @@ export function Default({ column }: { column: IColumn }) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col rounded-xl overflow-hidden">
|
<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">
|
<div className="h-[100px] w-full px-3 pt-3">
|
||||||
<img
|
<img
|
||||||
src="/columns/antenas.jpg"
|
src="/columns/antenas.jpg"
|
||||||
srcSet="/columns/antenas@2x.jpg 2x"
|
srcSet="/columns/antenas@2x.jpg 2x"
|
||||||
alt="antenas"
|
alt="antenas"
|
||||||
className="w-full h-auto object-cover"
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
className="w-full h-auto object-cover rounded-lg"
|
||||||
/>
|
/>
|
||||||
</div>
|
</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>
|
<div>
|
||||||
<h1 className="font-semibold">Antenas</h1>
|
<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.
|
Keep track to specific content.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
"@lume/ui": "workspace:^",
|
"@lume/ui": "workspace:^",
|
||||||
"@lume/utils": "workspace:^",
|
"@lume/utils": "workspace:^",
|
||||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||||
"@tanstack/react-query": "^5.17.15",
|
"@tanstack/react-query": "^5.17.19",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-router-dom": "^6.21.3",
|
"react-router-dom": "^6.21.3",
|
||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
"@lume/ui": "workspace:^",
|
"@lume/ui": "workspace:^",
|
||||||
"@lume/utils": "workspace:^",
|
"@lume/utils": "workspace:^",
|
||||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||||
"@tanstack/react-query": "^5.17.15",
|
"@tanstack/react-query": "^5.17.19",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-router-dom": "^6.21.3",
|
"react-router-dom": "^6.21.3",
|
||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
"@lume/ui": "workspace:^",
|
"@lume/ui": "workspace:^",
|
||||||
"@lume/utils": "workspace:^",
|
"@lume/utils": "workspace:^",
|
||||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||||
"@tanstack/react-query": "^5.17.15",
|
"@tanstack/react-query": "^5.17.19",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-router-dom": "^6.21.3",
|
"react-router-dom": "^6.21.3",
|
||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
"@lume/ui": "workspace:^",
|
"@lume/ui": "workspace:^",
|
||||||
"@lume/utils": "workspace:^",
|
"@lume/utils": "workspace:^",
|
||||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||||
"@tanstack/react-query": "^5.17.15",
|
"@tanstack/react-query": "^5.17.19",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-router-dom": "^6.21.3",
|
"react-router-dom": "^6.21.3",
|
||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
"@lume/ui": "workspace:^",
|
"@lume/ui": "workspace:^",
|
||||||
"@lume/utils": "workspace:^",
|
"@lume/utils": "workspace:^",
|
||||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||||
"@tanstack/react-query": "^5.17.15",
|
"@tanstack/react-query": "^5.17.19",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-router-dom": "^6.21.3",
|
"react-router-dom": "^6.21.3",
|
||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
|
@ -30,7 +30,7 @@ export function Timeline({ column }: { column: IColumn }) {
|
|||||||
id={column.id}
|
id={column.id}
|
||||||
queryKey={[colKey]}
|
queryKey={[colKey]}
|
||||||
title="Timeline"
|
title="Timeline"
|
||||||
icon={<TimelineIcon className="size-4" />}
|
icon={<TimelineIcon className="size-5" />}
|
||||||
/>
|
/>
|
||||||
{ark.account.contacts.length ? (
|
{ark.account.contacts.length ? (
|
||||||
<Column.Live
|
<Column.Live
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
"@lume/ui": "workspace:^",
|
"@lume/ui": "workspace:^",
|
||||||
"@lume/utils": "workspace:^",
|
"@lume/utils": "workspace:^",
|
||||||
"@nostr-dev-kit/ndk": "^2.3.3",
|
"@nostr-dev-kit/ndk": "^2.3.3",
|
||||||
"@tanstack/react-query": "^5.17.15",
|
"@tanstack/react-query": "^5.17.19",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-router-dom": "^6.21.3",
|
"react-router-dom": "^6.21.3",
|
||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||||
"@radix-ui/react-hover-card": "^1.0.7",
|
"@radix-ui/react-hover-card": "^1.0.7",
|
||||||
"@radix-ui/react-popover": "^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",
|
"framer-motion": "^10.18.0",
|
||||||
"jotai": "^2.6.2",
|
"jotai": "^2.6.3",
|
||||||
"minidenticons": "^4.2.0",
|
"minidenticons": "^4.2.0",
|
||||||
"nostr-tools": "~1.17.0",
|
"nostr-tools": "~1.17.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
@ -28,18 +28,18 @@
|
|||||||
"react-hotkeys-hook": "^4.4.4",
|
"react-hotkeys-hook": "^4.4.4",
|
||||||
"react-router-dom": "^6.21.3",
|
"react-router-dom": "^6.21.3",
|
||||||
"slate": "^0.101.5",
|
"slate": "^0.101.5",
|
||||||
"slate-react": "^0.101.5",
|
"slate-react": "^0.101.6",
|
||||||
"sonner": "^1.3.1",
|
"sonner": "^1.3.1",
|
||||||
"uqr": "^0.1.2",
|
"uqr": "^0.1.2",
|
||||||
"use-debounce": "^10.0.0",
|
"use-debounce": "^10.0.0",
|
||||||
"virtua": "^0.20.5"
|
"virtua": "^0.21.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tailwindcss": "workspace:^",
|
"@lume/tailwindcss": "workspace:^",
|
||||||
"@lume/tsconfig": "workspace:^",
|
"@lume/tsconfig": "workspace:^",
|
||||||
"@lume/types": "workspace:^",
|
"@lume/types": "workspace:^",
|
||||||
"@types/react": "^18.2.48",
|
"@types/react": "^18.2.48",
|
||||||
"tailwind-merge": "^2.2.0",
|
"tailwind-merge": "^2.2.1",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useArk, useProfile } from "@lume/ark";
|
import { useArk, useProfile } from "@lume/ark";
|
||||||
import { SettingsIcon } from "@lume/icons";
|
import { SettingsIcon, UserIcon } from "@lume/icons";
|
||||||
import { cn, useNetworkStatus } from "@lume/utils";
|
import { cn, useNetworkStatus } from "@lume/utils";
|
||||||
import * as Avatar from "@radix-ui/react-avatar";
|
import * as Avatar from "@radix-ui/react-avatar";
|
||||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||||
@ -54,17 +54,27 @@ export function ActiveAccount() {
|
|||||||
<DropdownMenu.Content
|
<DropdownMenu.Content
|
||||||
side="right"
|
side="right"
|
||||||
sideOffset={5}
|
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>
|
<DropdownMenu.Item asChild>
|
||||||
<Link
|
<Link
|
||||||
to="/settings/"
|
to="/settings/profile"
|
||||||
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"
|
||||||
>
|
>
|
||||||
<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
|
Settings
|
||||||
</Link>
|
</Link>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
|
<DropdownMenu.Separator className="h-px my-1 bg-black/10 dark:bg-white/10" />
|
||||||
<Logout />
|
<Logout />
|
||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
</DropdownMenu.Portal>
|
</DropdownMenu.Portal>
|
||||||
|
@ -35,9 +35,9 @@ export function Logout() {
|
|||||||
<AlertDialog.Trigger asChild>
|
<AlertDialog.Trigger asChild>
|
||||||
<button
|
<button
|
||||||
type="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
|
Logout
|
||||||
</button>
|
</button>
|
||||||
</AlertDialog.Trigger>
|
</AlertDialog.Trigger>
|
||||||
|
@ -106,7 +106,7 @@ const Image = ({ attributes, children, element }) => {
|
|||||||
return (
|
return (
|
||||||
<div {...attributes}>
|
<div {...attributes}>
|
||||||
{children}
|
{children}
|
||||||
<div contentEditable={false} className="relative">
|
<div contentEditable={false} className="relative my-2">
|
||||||
<img
|
<img
|
||||||
src={element.url}
|
src={element.url}
|
||||||
alt={element.url}
|
alt={element.url}
|
||||||
@ -155,7 +155,7 @@ const Event = ({ attributes, element, children }) => {
|
|||||||
<div
|
<div
|
||||||
contentEditable={false}
|
contentEditable={false}
|
||||||
onClick={() => Transforms.removeNodes(editor, { at: path })}
|
onClick={() => Transforms.removeNodes(editor, { at: path })}
|
||||||
className="relative user-select-none"
|
className="relative user-select-none my-2"
|
||||||
>
|
>
|
||||||
<MentionNote
|
<MentionNote
|
||||||
eventId={element.eventId.replace("nostr:", "")}
|
eventId={element.eventId.replace("nostr:", "")}
|
||||||
@ -319,11 +319,9 @@ export function EditorForm() {
|
|||||||
setTarget(null);
|
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>
|
<div>
|
||||||
<h3 className="font-semibold text-neutral-700 dark:text-neutral-500">
|
<h3 className="font-medium">New Post</h3>
|
||||||
New Post
|
|
||||||
</h3>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="inline-flex items-center gap-2">
|
<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">
|
<div className="py-6 h-full overflow-y-auto px-7">
|
||||||
<Editable
|
<Editable
|
||||||
key={JSON.stringify(editorValue)}
|
key={JSON.stringify(editorValue)}
|
||||||
autoFocus={false}
|
autoFocus={true}
|
||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
autoCorrect="none"
|
autoCorrect="none"
|
||||||
spellCheck={false}
|
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"
|
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) => (
|
{filters.map((contact, i) => (
|
||||||
// biome-ignore lint/a11y/useKeyWithClickEvents: <explanation>
|
<button
|
||||||
<div
|
|
||||||
key={contact.npub}
|
key={contact.npub}
|
||||||
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
Transforms.select(editor, target);
|
Transforms.select(editor, target);
|
||||||
insertMention(editor, contact);
|
insertMention(editor, contact);
|
||||||
@ -379,7 +377,7 @@ export function EditorForm() {
|
|||||||
</div>
|
</div>
|
||||||
</User.Root>
|
</User.Root>
|
||||||
</User.Provider>
|
</User.Provider>
|
||||||
</div>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</Portal>
|
</Portal>
|
||||||
|
@ -2,7 +2,7 @@ import { NDKCacheUserProfile } from "@lume/types";
|
|||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import { BaseEditor, Transforms } from "slate";
|
import { BaseEditor, Transforms } from "slate";
|
||||||
import { type ReactEditor } from "slate-react";
|
import { ReactEditor } from "slate-react";
|
||||||
|
|
||||||
export const Portal = ({ children }: { children?: ReactNode }) => {
|
export const Portal = ({ children }: { children?: ReactNode }) => {
|
||||||
return typeof document === "object"
|
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, image);
|
||||||
Transforms.insertNodes(editor, extraText);
|
Transforms.insertNodes(editor, extraText);
|
||||||
};
|
};
|
||||||
@ -44,15 +46,24 @@ export const insertMention = (
|
|||||||
editor: ReactEditor | BaseEditor,
|
editor: ReactEditor | BaseEditor,
|
||||||
contact: NDKCacheUserProfile,
|
contact: NDKCacheUserProfile,
|
||||||
) => {
|
) => {
|
||||||
|
const text = { text: "" };
|
||||||
const mention = {
|
const mention = {
|
||||||
type: "mention",
|
type: "mention",
|
||||||
npub: `nostr:${contact.npub}`,
|
npub: `nostr:${contact.npub}`,
|
||||||
name: contact.name || contact.displayName || "anon",
|
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.insertNodes(editor, mention);
|
||||||
Transforms.move(editor);
|
Transforms.insertNodes(editor, extraText);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const insertNostrEvent = (
|
export const insertNostrEvent = (
|
||||||
|
@ -2,11 +2,11 @@ import {
|
|||||||
BellFilledIcon,
|
BellFilledIcon,
|
||||||
BellIcon,
|
BellIcon,
|
||||||
ComposeFilledIcon,
|
ComposeFilledIcon,
|
||||||
ComposeIcon,
|
|
||||||
DepotFilledIcon,
|
DepotFilledIcon,
|
||||||
DepotIcon,
|
DepotIcon,
|
||||||
HomeFilledIcon,
|
HomeFilledIcon,
|
||||||
HomeIcon,
|
HomeIcon,
|
||||||
|
PlusIcon,
|
||||||
SearchFilledIcon,
|
SearchFilledIcon,
|
||||||
SearchIcon,
|
SearchIcon,
|
||||||
SettingsFilledIcon,
|
SettingsFilledIcon,
|
||||||
@ -44,11 +44,7 @@ export function Navigation() {
|
|||||||
: "bg-black/5 hover:bg-blue-500 dark:bg-white/5 dark:hover:bg-blue-500",
|
: "bg-black/5 hover:bg-blue-500 dark:bg-white/5 dark:hover:bg-blue-500",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{isEditorOpen ? (
|
<PlusIcon className="size-5" />
|
||||||
<ComposeFilledIcon className="size-5" />
|
|
||||||
) : (
|
|
||||||
<ComposeIcon className="size-5" />
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="my-5 w-2/3 mx-auto h-px bg-black/10 dark:bg-white/10" />
|
<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="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-1 min-h-0 overflow-y-auto px-8 py-8">
|
||||||
<div className="flex flex-col gap-8">
|
<div className="flex flex-col gap-8">
|
||||||
{TOPICS.map((topic, index) => (
|
{TOPICS.map((topic) => (
|
||||||
<div key={topic.title + index} className="flex flex-col gap-4">
|
<div key={topic.title} className="flex flex-col gap-4">
|
||||||
<div className="w-full flex items-center justify-between">
|
<div className="w-full flex items-center justify-between">
|
||||||
<div className="inline-flex items-center gap-2.5">
|
<div className="inline-flex items-center gap-2.5">
|
||||||
<img
|
<img
|
||||||
@ -79,6 +79,7 @@ export function OnboardingInterestScreen() {
|
|||||||
<div className="flex flex-wrap items-center gap-3">
|
<div className="flex flex-wrap items-center gap-3">
|
||||||
{topic.content.map((hashtag) => (
|
{topic.content.map((hashtag) => (
|
||||||
<button
|
<button
|
||||||
|
key={hashtag}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => toggleHashtag(hashtag)}
|
onClick={() => toggleHashtag(hashtag)}
|
||||||
className={cn(
|
className={cn(
|
||||||
|
@ -35,19 +35,17 @@ export function OnboardingProfileScreen() {
|
|||||||
navigate("/interests");
|
navigate("/interests");
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldProfile = await ark.getUserProfile();
|
const prevProfile = await ark.getUserProfile();
|
||||||
|
const newProfile: NDKUserProfile = {
|
||||||
const profile: NDKUserProfile = {
|
|
||||||
...data,
|
...data,
|
||||||
lud16: "", // temporary remove lud16
|
nip05: prevProfile?.nip05 || "",
|
||||||
nip05: oldProfile?.nip05 || "",
|
|
||||||
bio: data.about,
|
bio: data.about,
|
||||||
image: picture,
|
image: picture,
|
||||||
picture: picture,
|
picture: picture,
|
||||||
};
|
};
|
||||||
|
|
||||||
const publish = await ark.createEvent({
|
const publish = await ark.createEvent({
|
||||||
content: JSON.stringify(profile),
|
content: JSON.stringify(newProfile),
|
||||||
kind: NDKKind.Metadata,
|
kind: NDKKind.Metadata,
|
||||||
tags: [],
|
tags: [],
|
||||||
});
|
});
|
||||||
@ -57,7 +55,7 @@ export function OnboardingProfileScreen() {
|
|||||||
await storage.clearProfileCache(ark.account.pubkey);
|
await storage.clearProfileCache(ark.account.pubkey);
|
||||||
await queryClient.setQueryData(
|
await queryClient.setQueryData(
|
||||||
["user", ark.account.pubkey],
|
["user", ark.account.pubkey],
|
||||||
() => profile,
|
() => newProfile,
|
||||||
);
|
);
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
@ -11,7 +11,7 @@ export function EventRoute() {
|
|||||||
return (
|
return (
|
||||||
<div className="pb-5 overflow-y-auto">
|
<div className="pb-5 overflow-y-auto">
|
||||||
<WindowVirtualizer>
|
<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
|
<button
|
||||||
type="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"
|
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>
|
||||||
<div className="flex flex-col divide-y divide-neutral-100 dark:divide-neutral-900">
|
<div className="flex flex-col divide-y divide-neutral-100 dark:divide-neutral-900">
|
||||||
{isLoading ? (
|
{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" />
|
<LoaderIcon className="size-4 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
) : isError ? (
|
) : 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
|
Error. Cannot get trending users
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@ -171,9 +171,9 @@ export function SuggestRoute({ queryKey }: { queryKey: string[] }) {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={submit}
|
onClick={submit}
|
||||||
disabled={loading}
|
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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</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-1 min-h-0 flex flex-col justify-between px-8 py-8">
|
||||||
<div className="flex flex-col gap-1.5">
|
<div className="flex flex-col gap-1.5">
|
||||||
<p className="text-sm text-neutral-500">
|
<p className="text-sm text-neutral-500">
|
||||||
Translate Service is provided by{" "}
|
Translation Service is provided by{" "}
|
||||||
<span className="text-blue-500">nostr.wine</span>, you need to
|
<span className="text-blue-500">nostr.wine</span>. Prices
|
||||||
deposit at least 2,500 sats to use translate 50,000 characters
|
start at 2,500 sats for 50,000 characters of translated text.
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-neutral-500">
|
<p className="text-sm text-neutral-500">
|
||||||
You can learn more about nostr.wine{" "}
|
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="px-5 h-full flex flex-col justify-between">
|
||||||
<div className="h-full min-h-0 flex flex-col gap-2">
|
<div className="h-full min-h-0 flex flex-col gap-2">
|
||||||
<p>
|
<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>
|
||||||
<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
|
<img
|
||||||
src="/tutorial-3.gif"
|
src="/tutorial-3.gif"
|
||||||
alt="tutorial-3"
|
alt="tutorial-3"
|
||||||
|
@ -4,10 +4,10 @@ export function TutorialNewColumnScreen() {
|
|||||||
return (
|
return (
|
||||||
<div className="px-5 h-full flex flex-col justify-between">
|
<div className="px-5 h-full flex flex-col justify-between">
|
||||||
<div className="h-full min-h-0 flex flex-col gap-2">
|
<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>
|
<p>
|
||||||
<span className="font-semibold">To create new column,</span> you can
|
<span className="font-semibold">To create a new column</span>, you can
|
||||||
look into bottom right part of screen
|
click on the "Plus" icon at bottom right corner of this window.
|
||||||
</p>
|
</p>
|
||||||
<p>Click to "Plus" icon</p>
|
<p>Click to "Plus" icon</p>
|
||||||
<img
|
<img
|
||||||
|
@ -8,13 +8,13 @@
|
|||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/react-query": "^5.17.15",
|
"@tanstack/react-query": "^5.17.19",
|
||||||
"clsx": "^2.1.0",
|
"clsx": "^2.1.0",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"jotai": "^2.6.2",
|
"jotai": "^2.6.3",
|
||||||
"nostr-tools": "1.17.0",
|
"nostr-tools": "1.17.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"tailwind-merge": "^2.2.0"
|
"tailwind-merge": "^2.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lume/tsconfig": "workspace:^",
|
"@lume/tsconfig": "workspace:^",
|
||||||
|
264
pnpm-lock.yaml
264
pnpm-lock.yaml
@ -52,7 +52,7 @@ importers:
|
|||||||
version: 2.6.4
|
version: 2.6.4
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@biomejs/biome':
|
'@biomejs/biome':
|
||||||
specifier: ^1.5.2
|
specifier: ^1.5.3
|
||||||
version: 1.5.3
|
version: 1.5.3
|
||||||
'@tauri-apps/cli':
|
'@tauri-apps/cli':
|
||||||
specifier: 2.0.0-alpha.21
|
specifier: 2.0.0-alpha.21
|
||||||
@ -117,6 +117,9 @@ importers:
|
|||||||
'@radix-ui/react-avatar':
|
'@radix-ui/react-avatar':
|
||||||
specifier: ^1.0.4
|
specifier: ^1.0.4
|
||||||
version: 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-checkbox':
|
||||||
|
specifier: ^1.0.4
|
||||||
|
version: 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@radix-ui/react-collapsible':
|
'@radix-ui/react-collapsible':
|
||||||
specifier: ^1.0.3
|
specifier: ^1.0.3
|
||||||
version: 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
@ -142,13 +145,13 @@ importers:
|
|||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
framer-motion:
|
framer-motion:
|
||||||
specifier: ^10.18.0
|
specifier: ^10.18.0
|
||||||
version: 10.18.0(react-dom@18.2.0)(react@18.2.0)
|
version: 10.18.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
jotai:
|
jotai:
|
||||||
specifier: ^2.6.2
|
specifier: ^2.6.3
|
||||||
version: 2.6.3(@types/react@18.2.48)(react@18.2.0)
|
version: 2.6.3(@types/react@18.2.48)(react@18.2.0)
|
||||||
minidenticons:
|
minidenticons:
|
||||||
specifier: ^4.2.0
|
specifier: ^4.2.0
|
||||||
@ -178,14 +181,14 @@ importers:
|
|||||||
specifier: ^6.21.3
|
specifier: ^6.21.3
|
||||||
version: 6.21.3(react-dom@18.2.0)(react@18.2.0)
|
version: 6.21.3(react-dom@18.2.0)(react@18.2.0)
|
||||||
smol-toml:
|
smol-toml:
|
||||||
specifier: ^1.1.3
|
specifier: ^1.1.4
|
||||||
version: 1.1.4
|
version: 1.1.4
|
||||||
sonner:
|
sonner:
|
||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -197,7 +200,7 @@ importers:
|
|||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
version: link:../../packages/types
|
version: link:../../packages/types
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^20.11.5
|
specifier: ^20.11.6
|
||||||
version: 20.11.6
|
version: 20.11.6
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^18.2.48
|
specifier: ^18.2.48
|
||||||
@ -227,7 +230,7 @@ importers:
|
|||||||
specifier: ^5.3.3
|
specifier: ^5.3.3
|
||||||
version: 5.3.3
|
version: 5.3.3
|
||||||
vite:
|
vite:
|
||||||
specifier: ^5.0.11
|
specifier: ^5.0.12
|
||||||
version: 5.0.12(@types/node@20.11.6)
|
version: 5.0.12(@types/node@20.11.6)
|
||||||
vite-plugin-top-level-await:
|
vite-plugin-top-level-await:
|
||||||
specifier: ^1.4.1
|
specifier: ^1.4.1
|
||||||
@ -243,19 +246,19 @@ importers:
|
|||||||
version: 0.4.1(typescript@5.3.3)
|
version: 0.4.1(typescript@5.3.3)
|
||||||
'@astrojs/tailwind':
|
'@astrojs/tailwind':
|
||||||
specifier: ^5.1.0
|
specifier: ^5.1.0
|
||||||
version: 5.1.0(astro@4.2.1)(tailwindcss@3.4.1)
|
version: 5.1.0(astro@4.2.4)(tailwindcss@3.4.1)
|
||||||
'@fontsource/geist-mono':
|
'@fontsource/geist-mono':
|
||||||
specifier: ^5.0.1
|
specifier: ^5.0.1
|
||||||
version: 5.0.1
|
version: 5.0.1
|
||||||
astro:
|
astro:
|
||||||
specifier: ^4.2.1
|
specifier: ^4.2.4
|
||||||
version: 4.2.1(typescript@5.3.3)
|
version: 4.2.4(typescript@5.3.3)
|
||||||
astro-seo-meta:
|
astro-seo-meta:
|
||||||
specifier: ^4.1.0
|
specifier: ^4.1.0
|
||||||
version: 4.1.0(astro@4.2.1)
|
version: 4.1.0(astro@4.2.4)
|
||||||
astro-seo-schema:
|
astro-seo-schema:
|
||||||
specifier: ^4.0.0
|
specifier: ^4.0.0
|
||||||
version: 4.0.0(astro@4.2.1)(schema-dts@1.1.2)
|
version: 4.0.0(astro@4.2.4)(schema-dts@1.1.2)
|
||||||
schema-dts:
|
schema-dts:
|
||||||
specifier: ^1.1.2
|
specifier: ^1.1.2
|
||||||
version: 1.1.2(typescript@5.3.3)
|
version: 1.1.2(typescript@5.3.3)
|
||||||
@ -315,13 +318,13 @@ importers:
|
|||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
get-urls:
|
get-urls:
|
||||||
specifier: ^12.1.0
|
specifier: ^12.1.0
|
||||||
version: 12.1.0
|
version: 12.1.0
|
||||||
jotai:
|
jotai:
|
||||||
specifier: ^2.6.2
|
specifier: ^2.6.3
|
||||||
version: 2.6.3(@types/react@18.2.48)(react@18.2.0)
|
version: 2.6.3(@types/react@18.2.48)(react@18.2.0)
|
||||||
linkify-react:
|
linkify-react:
|
||||||
specifier: ^4.1.3
|
specifier: ^4.1.3
|
||||||
@ -375,8 +378,8 @@ importers:
|
|||||||
specifier: ^1.4.1
|
specifier: ^1.4.1
|
||||||
version: 1.4.1(react-dom@18.2.0)(react@18.2.0)(scheduler@0.23.0)
|
version: 1.4.1(react-dom@18.2.0)(react@18.2.0)(scheduler@0.23.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -391,7 +394,7 @@ importers:
|
|||||||
specifier: ^18.2.48
|
specifier: ^18.2.48
|
||||||
version: 18.2.48
|
version: 18.2.48
|
||||||
tailwind-merge:
|
tailwind-merge:
|
||||||
specifier: ^2.2.0
|
specifier: ^2.2.1
|
||||||
version: 2.2.1
|
version: 2.2.1
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^3.4.1
|
specifier: ^3.4.1
|
||||||
@ -416,58 +419,6 @@ importers:
|
|||||||
specifier: ^5.3.3
|
specifier: ^5.3.3
|
||||||
version: 5.3.3
|
version: 5.3.3
|
||||||
|
|
||||||
packages/lume-column-activity:
|
|
||||||
dependencies:
|
|
||||||
'@lume/ark':
|
|
||||||
specifier: workspace:^
|
|
||||||
version: link:../ark
|
|
||||||
'@lume/icons':
|
|
||||||
specifier: workspace:^
|
|
||||||
version: link:../icons
|
|
||||||
'@lume/ui':
|
|
||||||
specifier: workspace:^
|
|
||||||
version: link:../ui
|
|
||||||
'@lume/utils':
|
|
||||||
specifier: workspace:^
|
|
||||||
version: link:../utils
|
|
||||||
'@nostr-dev-kit/ndk':
|
|
||||||
specifier: ^2.3.3
|
|
||||||
version: 2.3.3(typescript@5.3.3)
|
|
||||||
'@tanstack/react-query':
|
|
||||||
specifier: ^5.17.15
|
|
||||||
version: 5.17.19(react@18.2.0)
|
|
||||||
react:
|
|
||||||
specifier: ^18.2.0
|
|
||||||
version: 18.2.0
|
|
||||||
react-router-dom:
|
|
||||||
specifier: ^6.21.3
|
|
||||||
version: 6.21.3(react-dom@18.2.0)(react@18.2.0)
|
|
||||||
sonner:
|
|
||||||
specifier: ^1.3.1
|
|
||||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
|
||||||
virtua:
|
|
||||||
specifier: ^0.20.5
|
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
|
||||||
devDependencies:
|
|
||||||
'@lume/tailwindcss':
|
|
||||||
specifier: workspace:^
|
|
||||||
version: link:../tailwindcss
|
|
||||||
'@lume/tsconfig':
|
|
||||||
specifier: workspace:^
|
|
||||||
version: link:../tsconfig
|
|
||||||
'@lume/types':
|
|
||||||
specifier: workspace:^
|
|
||||||
version: link:../types
|
|
||||||
'@types/react':
|
|
||||||
specifier: ^18.2.48
|
|
||||||
version: 18.2.48
|
|
||||||
tailwind:
|
|
||||||
specifier: ^4.0.0
|
|
||||||
version: 4.0.0
|
|
||||||
typescript:
|
|
||||||
specifier: ^5.3.3
|
|
||||||
version: 5.3.3
|
|
||||||
|
|
||||||
packages/lume-column-antenas:
|
packages/lume-column-antenas:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@lume/ark':
|
'@lume/ark':
|
||||||
@ -486,7 +437,7 @@ importers:
|
|||||||
specifier: ^2.3.3
|
specifier: ^2.3.3
|
||||||
version: 2.3.3(typescript@5.3.3)
|
version: 2.3.3(typescript@5.3.3)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
@ -498,8 +449,8 @@ importers:
|
|||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -538,7 +489,7 @@ importers:
|
|||||||
specifier: ^2.3.3
|
specifier: ^2.3.3
|
||||||
version: 2.3.3(typescript@5.3.3)
|
version: 2.3.3(typescript@5.3.3)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
@ -550,8 +501,8 @@ importers:
|
|||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -593,7 +544,7 @@ importers:
|
|||||||
specifier: ^2.3.3
|
specifier: ^2.3.3
|
||||||
version: 2.3.3(typescript@5.3.3)
|
version: 2.3.3(typescript@5.3.3)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
@ -605,8 +556,8 @@ importers:
|
|||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -645,7 +596,7 @@ importers:
|
|||||||
specifier: ^2.3.3
|
specifier: ^2.3.3
|
||||||
version: 2.3.3(typescript@5.3.3)
|
version: 2.3.3(typescript@5.3.3)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
@ -657,8 +608,8 @@ importers:
|
|||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -697,7 +648,7 @@ importers:
|
|||||||
specifier: ^2.3.3
|
specifier: ^2.3.3
|
||||||
version: 2.3.3(typescript@5.3.3)
|
version: 2.3.3(typescript@5.3.3)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
@ -709,8 +660,8 @@ importers:
|
|||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -749,7 +700,7 @@ importers:
|
|||||||
specifier: ^2.3.3
|
specifier: ^2.3.3
|
||||||
version: 2.3.3(typescript@5.3.3)
|
version: 2.3.3(typescript@5.3.3)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
@ -761,8 +712,8 @@ importers:
|
|||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -801,7 +752,7 @@ importers:
|
|||||||
specifier: ^2.3.3
|
specifier: ^2.3.3
|
||||||
version: 2.3.3(typescript@5.3.3)
|
version: 2.3.3(typescript@5.3.3)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
@ -813,8 +764,8 @@ importers:
|
|||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -853,7 +804,7 @@ importers:
|
|||||||
specifier: ^2.3.3
|
specifier: ^2.3.3
|
||||||
version: 2.3.3(typescript@5.3.3)
|
version: 2.3.3(typescript@5.3.3)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
@ -865,8 +816,8 @@ importers:
|
|||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
version: 1.3.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -1016,13 +967,13 @@ importers:
|
|||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
framer-motion:
|
framer-motion:
|
||||||
specifier: ^10.18.0
|
specifier: ^10.18.0
|
||||||
version: 10.18.0(react-dom@18.2.0)(react@18.2.0)
|
version: 10.18.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
jotai:
|
jotai:
|
||||||
specifier: ^2.6.2
|
specifier: ^2.6.3
|
||||||
version: 2.6.3(@types/react@18.2.48)(react@18.2.0)
|
version: 2.6.3(@types/react@18.2.48)(react@18.2.0)
|
||||||
minidenticons:
|
minidenticons:
|
||||||
specifier: ^4.2.0
|
specifier: ^4.2.0
|
||||||
@ -1049,7 +1000,7 @@ importers:
|
|||||||
specifier: ^0.101.5
|
specifier: ^0.101.5
|
||||||
version: 0.101.5
|
version: 0.101.5
|
||||||
slate-react:
|
slate-react:
|
||||||
specifier: ^0.101.5
|
specifier: ^0.101.6
|
||||||
version: 0.101.6(react-dom@18.2.0)(react@18.2.0)(slate@0.101.5)
|
version: 0.101.6(react-dom@18.2.0)(react@18.2.0)(slate@0.101.5)
|
||||||
sonner:
|
sonner:
|
||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
@ -1061,8 +1012,8 @@ importers:
|
|||||||
specifier: ^10.0.0
|
specifier: ^10.0.0
|
||||||
version: 10.0.0(react@18.2.0)
|
version: 10.0.0(react@18.2.0)
|
||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.20.5
|
specifier: ^0.21.1
|
||||||
version: 0.20.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tailwindcss':
|
'@lume/tailwindcss':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@ -1077,7 +1028,7 @@ importers:
|
|||||||
specifier: ^18.2.48
|
specifier: ^18.2.48
|
||||||
version: 18.2.48
|
version: 18.2.48
|
||||||
tailwind-merge:
|
tailwind-merge:
|
||||||
specifier: ^2.2.0
|
specifier: ^2.2.1
|
||||||
version: 2.2.1
|
version: 2.2.1
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^3.4.1
|
specifier: ^3.4.1
|
||||||
@ -1089,7 +1040,7 @@ importers:
|
|||||||
packages/utils:
|
packages/utils:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.15
|
specifier: ^5.17.19
|
||||||
version: 5.17.19(react@18.2.0)
|
version: 5.17.19(react@18.2.0)
|
||||||
clsx:
|
clsx:
|
||||||
specifier: ^2.1.0
|
specifier: ^2.1.0
|
||||||
@ -1098,7 +1049,7 @@ importers:
|
|||||||
specifier: ^1.11.10
|
specifier: ^1.11.10
|
||||||
version: 1.11.10
|
version: 1.11.10
|
||||||
jotai:
|
jotai:
|
||||||
specifier: ^2.6.2
|
specifier: ^2.6.3
|
||||||
version: 2.6.3(@types/react@18.2.48)(react@18.2.0)
|
version: 2.6.3(@types/react@18.2.48)(react@18.2.0)
|
||||||
nostr-tools:
|
nostr-tools:
|
||||||
specifier: 1.17.0
|
specifier: 1.17.0
|
||||||
@ -1107,7 +1058,7 @@ importers:
|
|||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
version: 18.2.0
|
version: 18.2.0
|
||||||
tailwind-merge:
|
tailwind-merge:
|
||||||
specifier: ^2.2.0
|
specifier: ^2.2.1
|
||||||
version: 2.2.1
|
version: 2.2.1
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@lume/tsconfig':
|
'@lume/tsconfig':
|
||||||
@ -1153,8 +1104,8 @@ packages:
|
|||||||
- prettier-plugin-astro
|
- prettier-plugin-astro
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@astrojs/compiler@2.5.0:
|
/@astrojs/compiler@2.5.1:
|
||||||
resolution: {integrity: sha512-ZDluNgMIJT+z+HJcZ6QEJ/KqaFkTkrb+Za6c6VZs8G/nb1LBErL14/iU5EVJ9yu25i4QCLweuBJ3m5df34gZJg==}
|
resolution: {integrity: sha512-o2hKiFJXZOm1Gov+RGXSWnKlnb/UF7KRTx/Y2uazYe3+MrLY+sqLN+yB4EH2bElc0l1K9cDb4mZSejuq563rGQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@astrojs/internal-helpers@0.2.1:
|
/@astrojs/internal-helpers@0.2.1:
|
||||||
@ -1172,7 +1123,7 @@ packages:
|
|||||||
prettier-plugin-astro:
|
prettier-plugin-astro:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/compiler': 2.5.0
|
'@astrojs/compiler': 2.5.1
|
||||||
'@jridgewell/sourcemap-codec': 1.4.15
|
'@jridgewell/sourcemap-codec': 1.4.15
|
||||||
'@volar/kit': 1.11.1(typescript@5.3.3)
|
'@volar/kit': 1.11.1(typescript@5.3.3)
|
||||||
'@volar/language-core': 1.11.1
|
'@volar/language-core': 1.11.1
|
||||||
@ -1188,14 +1139,14 @@ packages:
|
|||||||
volar-service-prettier: 0.0.17(@volar/language-service@1.11.1)
|
volar-service-prettier: 0.0.17(@volar/language-service@1.11.1)
|
||||||
volar-service-typescript: 0.0.17(@volar/language-service@1.11.1)(@volar/typescript@1.11.1)
|
volar-service-typescript: 0.0.17(@volar/language-service@1.11.1)(@volar/typescript@1.11.1)
|
||||||
volar-service-typescript-twoslash-queries: 0.0.17(@volar/language-service@1.11.1)
|
volar-service-typescript-twoslash-queries: 0.0.17(@volar/language-service@1.11.1)
|
||||||
vscode-html-languageservice: 5.1.1
|
vscode-html-languageservice: 5.1.2
|
||||||
vscode-uri: 3.0.8
|
vscode-uri: 3.0.8
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- typescript
|
- typescript
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@astrojs/markdown-remark@4.1.0:
|
/@astrojs/markdown-remark@4.2.0:
|
||||||
resolution: {integrity: sha512-JnIy6zk+6f/SgSVMZecZFxQt0faT1uBckwYCuBxKH1hYYJsal8OOe+tx6JxfnyaV+xViyjUvQ28mmn+p/F5LkQ==}
|
resolution: {integrity: sha512-qQB+LoxmIqzkhLXaQAzfzlBxZU1jeQYailsifurz89WeY0Q8ywIj8uQQSyqxb7rPPg3ZfdNdxsN9lF5UaCRn0w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/prism': 3.0.0
|
'@astrojs/prism': 3.0.0
|
||||||
github-slugger: 2.0.0
|
github-slugger: 2.0.0
|
||||||
@ -1222,13 +1173,13 @@ packages:
|
|||||||
prismjs: 1.29.0
|
prismjs: 1.29.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@astrojs/tailwind@5.1.0(astro@4.2.1)(tailwindcss@3.4.1):
|
/@astrojs/tailwind@5.1.0(astro@4.2.4)(tailwindcss@3.4.1):
|
||||||
resolution: {integrity: sha512-BJoCDKuWhU9FT2qYg+fr6Nfb3qP4ShtyjXGHKA/4mHN94z7BGcmauQK23iy+YH5qWvTnhqkd6mQPQ1yTZTe9Ig==}
|
resolution: {integrity: sha512-BJoCDKuWhU9FT2qYg+fr6Nfb3qP4ShtyjXGHKA/4mHN94z7BGcmauQK23iy+YH5qWvTnhqkd6mQPQ1yTZTe9Ig==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
astro: ^3.0.0 || ^4.0.0
|
astro: ^3.0.0 || ^4.0.0
|
||||||
tailwindcss: ^3.0.24
|
tailwindcss: ^3.0.24
|
||||||
dependencies:
|
dependencies:
|
||||||
astro: 4.2.1(typescript@5.3.3)
|
astro: 4.2.4(typescript@5.3.3)
|
||||||
autoprefixer: 10.4.17(postcss@8.4.33)
|
autoprefixer: 10.4.17(postcss@8.4.33)
|
||||||
postcss: 8.4.33
|
postcss: 8.4.33
|
||||||
postcss-load-config: 4.0.2(postcss@8.4.33)
|
postcss-load-config: 4.0.2(postcss@8.4.33)
|
||||||
@ -2137,6 +2088,34 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-checkbox@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.23.8
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-size': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
'@types/react-dom': 18.2.18
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==}
|
resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -3502,6 +3481,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-JT5CvrIYYCrmB+dCana8sUqJEcGB1ZDXNLMQ2+42bW995WmNoenijWMUdZfwmuQUTQcEVVIa2OecZzTYWUW9Cg==}
|
resolution: {integrity: sha512-JT5CvrIYYCrmB+dCana8sUqJEcGB1ZDXNLMQ2+42bW995WmNoenijWMUdZfwmuQUTQcEVVIa2OecZzTYWUW9Cg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@vscode/l10n@0.0.18:
|
||||||
|
resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/accepts@1.3.8:
|
/accepts@1.3.8:
|
||||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
@ -3649,31 +3632,31 @@ packages:
|
|||||||
resolution: {integrity: sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w==}
|
resolution: {integrity: sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/astro-seo-meta@4.1.0(astro@4.2.1):
|
/astro-seo-meta@4.1.0(astro@4.2.4):
|
||||||
resolution: {integrity: sha512-v5qULt/c2hp9u6JtRyZeWTeb6YC82XDMzVcEf7XlRSuvs3C6KUQxeIOp5j+uOIek42CZHcyhbWzQF+FoRbQlfg==}
|
resolution: {integrity: sha512-v5qULt/c2hp9u6JtRyZeWTeb6YC82XDMzVcEf7XlRSuvs3C6KUQxeIOp5j+uOIek42CZHcyhbWzQF+FoRbQlfg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
astro: ^4.0.0
|
astro: ^4.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
astro: 4.2.1(typescript@5.3.3)
|
astro: 4.2.4(typescript@5.3.3)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/astro-seo-schema@4.0.0(astro@4.2.1)(schema-dts@1.1.2):
|
/astro-seo-schema@4.0.0(astro@4.2.4)(schema-dts@1.1.2):
|
||||||
resolution: {integrity: sha512-ZcpxuQWSlyOVru+sN5LwUHqfrQpOEyv6Ksxq6WBNhycEHE0AEgGdiHkfhAmQbVqT4HXM8bmZOZlYlwwsYkfPAw==}
|
resolution: {integrity: sha512-ZcpxuQWSlyOVru+sN5LwUHqfrQpOEyv6Ksxq6WBNhycEHE0AEgGdiHkfhAmQbVqT4HXM8bmZOZlYlwwsYkfPAw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
astro: ^4.0.0
|
astro: ^4.0.0
|
||||||
schema-dts: ^1.1.0
|
schema-dts: ^1.1.0
|
||||||
dependencies:
|
dependencies:
|
||||||
astro: 4.2.1(typescript@5.3.3)
|
astro: 4.2.4(typescript@5.3.3)
|
||||||
schema-dts: 1.1.2(typescript@5.3.3)
|
schema-dts: 1.1.2(typescript@5.3.3)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/astro@4.2.1(typescript@5.3.3):
|
/astro@4.2.4(typescript@5.3.3):
|
||||||
resolution: {integrity: sha512-TcrveW2/lohmljrbTUgcDxajEdF1yK+zBvb7SXroloGix/d4jkegO6GANFgvyy0zprMyajW7qgJEFyhWUX86Vw==}
|
resolution: {integrity: sha512-z1f52lXkHf71M5HSLKrd5G1PH5/Zfq4kMp0iUT7Na5VHcPDma/NYFPFPewDxqV6UPmyxupj3xuooFaN3j8zaow==}
|
||||||
engines: {node: '>=18.14.1', npm: '>=6.14.0'}
|
engines: {node: '>=18.14.1', npm: '>=6.14.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/compiler': 2.5.0
|
'@astrojs/compiler': 2.5.1
|
||||||
'@astrojs/internal-helpers': 0.2.1
|
'@astrojs/internal-helpers': 0.2.1
|
||||||
'@astrojs/markdown-remark': 4.1.0
|
'@astrojs/markdown-remark': 4.2.0
|
||||||
'@astrojs/telemetry': 3.0.4
|
'@astrojs/telemetry': 3.0.4
|
||||||
'@babel/core': 7.23.7
|
'@babel/core': 7.23.7
|
||||||
'@babel/generator': 7.23.6
|
'@babel/generator': 7.23.6
|
||||||
@ -3724,7 +3707,7 @@ packages:
|
|||||||
semver: 7.5.4
|
semver: 7.5.4
|
||||||
server-destroy: 1.0.1
|
server-destroy: 1.0.1
|
||||||
shikiji: 0.9.19
|
shikiji: 0.9.19
|
||||||
string-width: 7.0.0
|
string-width: 7.1.0
|
||||||
strip-ansi: 7.1.0
|
strip-ansi: 7.1.0
|
||||||
tsconfck: 3.0.1(typescript@5.3.3)
|
tsconfck: 3.0.1(typescript@5.3.3)
|
||||||
unist-util-visit: 5.0.0
|
unist-util-visit: 5.0.0
|
||||||
@ -3899,7 +3882,7 @@ packages:
|
|||||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||||
dependencies:
|
dependencies:
|
||||||
caniuse-lite: 1.0.30001579
|
caniuse-lite: 1.0.30001579
|
||||||
electron-to-chromium: 1.4.644
|
electron-to-chromium: 1.4.645
|
||||||
node-releases: 2.0.14
|
node-releases: 2.0.14
|
||||||
update-browserslist-db: 1.0.13(browserslist@4.22.2)
|
update-browserslist-db: 1.0.13(browserslist@4.22.2)
|
||||||
|
|
||||||
@ -4090,6 +4073,7 @@ packages:
|
|||||||
|
|
||||||
/color-name@1.1.4:
|
/color-name@1.1.4:
|
||||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||||
|
requiresBuild: true
|
||||||
|
|
||||||
/color-string@1.9.1:
|
/color-string@1.9.1:
|
||||||
resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
|
resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
|
||||||
@ -4417,8 +4401,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/electron-to-chromium@1.4.644:
|
/electron-to-chromium@1.4.645:
|
||||||
resolution: {integrity: sha512-zOnPndwz3u1sVFSyBcRWcn0529Kz+jr+tDxN9iP69I3CpC5wlvYmjLrK2O7TEsg2oDDoUqooeXqbiHLvXvl6Lg==}
|
resolution: {integrity: sha512-EeS1oQDCmnYsRDRy2zTeC336a/4LZ6WKqvSaM1jLocEk5ZuyszkQtCpsqvuvaIXGOUjwtvF6LTcS8WueibXvSw==}
|
||||||
|
|
||||||
/emmet@2.4.6:
|
/emmet@2.4.6:
|
||||||
resolution: {integrity: sha512-dJfbdY/hfeTyf/Ef7Y7ubLYzkBvPQ912wPaeVYpAxvFxkEBf/+hJu4H6vhAvFN6HlxqedlfVn2x1S44FfQ97pg==}
|
resolution: {integrity: sha512-dJfbdY/hfeTyf/Ef7Y7ubLYzkBvPQ912wPaeVYpAxvFxkEBf/+hJu4H6vhAvFN6HlxqedlfVn2x1S44FfQ97pg==}
|
||||||
@ -5206,6 +5190,14 @@ packages:
|
|||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer: 2.1.2
|
safer-buffer: 2.1.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/iconv-lite@0.4.24:
|
||||||
|
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dependencies:
|
||||||
|
safer-buffer: 2.1.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/iconv-lite@0.6.3:
|
/iconv-lite@0.6.3:
|
||||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||||
@ -6319,7 +6311,7 @@ packages:
|
|||||||
engines: {node: '>= 4.4.x'}
|
engines: {node: '>= 4.4.x'}
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
iconv-lite: 0.4.23
|
iconv-lite: 0.4.24
|
||||||
sax: 1.3.0
|
sax: 1.3.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@ -7649,8 +7641,8 @@ packages:
|
|||||||
strip-ansi: 7.1.0
|
strip-ansi: 7.1.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/string-width@7.0.0:
|
/string-width@7.1.0:
|
||||||
resolution: {integrity: sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==}
|
resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
dependencies:
|
dependencies:
|
||||||
emoji-regex: 10.3.0
|
emoji-regex: 10.3.0
|
||||||
@ -8455,8 +8447,8 @@ packages:
|
|||||||
vfile-message: 4.0.2
|
vfile-message: 4.0.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/virtua@0.20.5(react-dom@18.2.0)(react@18.2.0):
|
/virtua@0.21.1(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-GHL+kSTotf5L1x3/Wcir0KkNKxmQIdWiDrcrBNz+DMiLUdNtskKs+E76Z0SSeeL0+I/PFutBrI8fXw/j7N+6sQ==}
|
resolution: {integrity: sha512-6CRxablXTLvnFHIIXKRgcxn0oVoXjKQRxchXzx8sWywg+DtQ7wHZBSrJ6WTN3YzXOLP9ZJt4zs5SmsaCTQbUhA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '>=16.14.0'
|
react: '>=16.14.0'
|
||||||
react-dom: '>=16.14.0'
|
react-dom: '>=16.14.0'
|
||||||
@ -8558,7 +8550,7 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@volar/language-service': 1.11.1
|
'@volar/language-service': 1.11.1
|
||||||
vscode-css-languageservice: 6.2.11
|
vscode-css-languageservice: 6.2.12
|
||||||
vscode-uri: 3.0.8
|
vscode-uri: 3.0.8
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@ -8584,7 +8576,7 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@volar/language-service': 1.11.1
|
'@volar/language-service': 1.11.1
|
||||||
vscode-html-languageservice: 5.1.1
|
vscode-html-languageservice: 5.1.2
|
||||||
vscode-uri: 3.0.8
|
vscode-uri: 3.0.8
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@ -8632,19 +8624,19 @@ packages:
|
|||||||
vscode-uri: 3.0.8
|
vscode-uri: 3.0.8
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vscode-css-languageservice@6.2.11:
|
/vscode-css-languageservice@6.2.12:
|
||||||
resolution: {integrity: sha512-qn49Wa6K94LnizpVxmlYrcPf1Cb36gq1nNueW0COhi4shylXBzET5wuDbH8ZWQlJD0HM5Mmnn7WE9vQVVs+ULA==}
|
resolution: {integrity: sha512-PS9r7HgNjqzRl3v91sXpCyZPc8UDotNo6gntFNtGCKPhGA9Frk7g/VjX1Mbv3F00pn56D+rxrFzR9ep4cawOgA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vscode/l10n': 0.0.16
|
'@vscode/l10n': 0.0.18
|
||||||
vscode-languageserver-textdocument: 1.0.11
|
vscode-languageserver-textdocument: 1.0.11
|
||||||
vscode-languageserver-types: 3.17.5
|
vscode-languageserver-types: 3.17.5
|
||||||
vscode-uri: 3.0.8
|
vscode-uri: 3.0.8
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vscode-html-languageservice@5.1.1:
|
/vscode-html-languageservice@5.1.2:
|
||||||
resolution: {integrity: sha512-JenrspIIG/Q+93R6G3L6HdK96itSisMynE0glURqHpQbL3dKAKzdm8L40lAHNkwJeBg+BBPpAshZKv/38onrTQ==}
|
resolution: {integrity: sha512-wkWfEx/IIR3s2P5yD4aTGHiOb8IAzFxgkSt1uSC3itJ4oDAm23yG7o0L29JljUdnXDDgLafPAvhv8A2I/8riHw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vscode/l10n': 0.0.16
|
'@vscode/l10n': 0.0.18
|
||||||
vscode-languageserver-textdocument: 1.0.11
|
vscode-languageserver-textdocument: 1.0.11
|
||||||
vscode-languageserver-types: 3.17.5
|
vscode-languageserver-types: 3.17.5
|
||||||
vscode-uri: 3.0.8
|
vscode-uri: 3.0.8
|
||||||
|
@ -1,119 +1,124 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../apps/desktop/node_modules/@tauri-apps/cli/schema.json",
|
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeBuildCommand": "pnpm run build",
|
"beforeBuildCommand": "pnpm run build",
|
||||||
"beforeDevCommand": "pnpm run dev",
|
"beforeDevCommand": "pnpm run dev",
|
||||||
"devPath": "http://localhost:3000",
|
"devPath": "http://localhost:3000",
|
||||||
"distDir": "../dist",
|
"distDir": "../dist",
|
||||||
"withGlobalTauri": true
|
"withGlobalTauri": true
|
||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "Lume",
|
"productName": "Lume",
|
||||||
"version": "3.0.0"
|
"version": "3.0.0-beta.1"
|
||||||
},
|
},
|
||||||
"plugins": {
|
"plugins": {
|
||||||
"fs": {
|
"fs": {
|
||||||
"scope": [
|
"scope": [
|
||||||
"$APPDATA/*",
|
"$APPDATA/*",
|
||||||
"$DATA/*",
|
"$DATA/*",
|
||||||
"$LOCALDATA/*",
|
"$LOCALDATA/*",
|
||||||
"$DESKTOP/*",
|
"$DESKTOP/*",
|
||||||
"$DOCUMENT/*",
|
"$DOCUMENT/*",
|
||||||
"$DOWNLOAD/*",
|
"$DOWNLOAD/*",
|
||||||
"$HOME/*",
|
"$HOME/*",
|
||||||
"$PICTURE/*",
|
"$PICTURE/*",
|
||||||
"$PUBLIC/*",
|
"$PUBLIC/*",
|
||||||
"$VIDEO/*",
|
"$VIDEO/*",
|
||||||
"$RESOURCE",
|
"$RESOURCE",
|
||||||
"$RESOURCE/*",
|
"$RESOURCE/*",
|
||||||
"$RESOURCE/**"
|
"$RESOURCE/**"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"http": {
|
"http": {
|
||||||
"scope": ["http://**/", "https://**/"]
|
"scope": ["http://**/", "https://**/"]
|
||||||
},
|
},
|
||||||
"shell": {
|
"shell": {
|
||||||
"open": true,
|
"open": true,
|
||||||
"scope": [{ "name": "bin/depot", "sidecar": true, "args": true }]
|
"scope": [{ "name": "bin/depot", "sidecar": true, "args": true }]
|
||||||
},
|
},
|
||||||
"updater": {
|
"updater": {
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
"https://lus.reya3772.workers.dev/v1/{{target}}/{{arch}}/{{current_version}}",
|
"https://lus.reya3772.workers.dev/v1/{{target}}/{{arch}}/{{current_version}}",
|
||||||
"https://lus.reya3772.workers.dev/{{target}}/{{current_version}}"
|
"https://lus.reya3772.workers.dev/{{target}}/{{current_version}}"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"bundle": {
|
"bundle": {
|
||||||
"active": true,
|
"active": true,
|
||||||
"category": "SocialNetworking",
|
"category": "SocialNetworking",
|
||||||
"deb": {
|
"deb": {
|
||||||
"depends": []
|
"depends": []
|
||||||
},
|
},
|
||||||
"externalBin": ["bin/depot"],
|
"externalBin": [],
|
||||||
"resources": ["resources/*"],
|
"resources": ["resources/*"],
|
||||||
"icon": [
|
"icon": [
|
||||||
"icons/32x32.png",
|
"icons/32x32.png",
|
||||||
"icons/128x128.png",
|
"icons/128x128.png",
|
||||||
"icons/128x128@2x.png",
|
"icons/128x128@2x.png",
|
||||||
"icons/icon.icns",
|
"icons/icon.icns",
|
||||||
"icons/icon.ico"
|
"icons/icon.ico"
|
||||||
],
|
],
|
||||||
"copyright": "",
|
"copyright": "",
|
||||||
"identifier": "nu.lume.Lume",
|
"identifier": "nu.lume.Lume",
|
||||||
"longDescription": "nostr client for desktop",
|
"longDescription": "nostr client for desktop",
|
||||||
"shortDescription": "",
|
"shortDescription": "nostr client",
|
||||||
"targets": "all",
|
"targets": "all",
|
||||||
"updater": {
|
"updater": {
|
||||||
"active": true,
|
"active": true,
|
||||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEU3OTdCMkM3RjU5QzE2NzkKUldSNUZwejF4N0tYNTVHYjMrU0JkL090SlEyNUVLYU5TM2hTU3RXSWtEWngrZWJ4a0pydUhXZHEK",
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEU3OTdCMkM3RjU5QzE2NzkKUldSNUZwejF4N0tYNTVHYjMrU0JkL090SlEyNUVLYU5TM2hTU3RXSWtEWngrZWJ4a0pydUhXZHEK",
|
||||||
"windows": {
|
"windows": {
|
||||||
"installMode": "quiet"
|
"installMode": "quiet"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"appimage": {
|
"appimage": {
|
||||||
"bundleMediaFramework": true
|
"bundleMediaFramework": true
|
||||||
},
|
},
|
||||||
"macOS": {
|
"rpm": {
|
||||||
"entitlements": null,
|
"epoch": 0,
|
||||||
"exceptionDomain": "",
|
"files": {},
|
||||||
"frameworks": [],
|
"release": "1"
|
||||||
"license": "../LICENSE",
|
},
|
||||||
"minimumSystemVersion": "10.15.0",
|
"macOS": {
|
||||||
"providerShortName": null,
|
"entitlements": null,
|
||||||
"signingIdentity": null
|
"exceptionDomain": "",
|
||||||
},
|
"frameworks": [],
|
||||||
"windows": {
|
"license": "../LICENSE",
|
||||||
"certificateThumbprint": null,
|
"minimumSystemVersion": "10.15.0",
|
||||||
"digestAlgorithm": "sha256",
|
"providerShortName": null,
|
||||||
"timestampUrl": ""
|
"signingIdentity": null
|
||||||
}
|
},
|
||||||
},
|
"windows": {
|
||||||
"security": {
|
"certificateThumbprint": null,
|
||||||
"assetProtocol": {
|
"digestAlgorithm": "sha256",
|
||||||
"enable": true,
|
"timestampUrl": ""
|
||||||
"scope": [
|
}
|
||||||
"$APPDATA/*",
|
},
|
||||||
"$DATA/*",
|
"security": {
|
||||||
"$LOCALDATA/*",
|
"assetProtocol": {
|
||||||
"$DESKTOP/*",
|
"enable": true,
|
||||||
"$DOCUMENT/*",
|
"scope": [
|
||||||
"$DOWNLOAD/*",
|
"$APPDATA/*",
|
||||||
"$HOME/*",
|
"$DATA/*",
|
||||||
"$PICTURE/*",
|
"$LOCALDATA/*",
|
||||||
"$PUBLIC/*",
|
"$DESKTOP/*",
|
||||||
"$VIDEO/*",
|
"$DOCUMENT/*",
|
||||||
"$APPCONFIG/*",
|
"$DOWNLOAD/*",
|
||||||
"$RESOURCE/*"
|
"$HOME/*",
|
||||||
]
|
"$PICTURE/*",
|
||||||
},
|
"$PUBLIC/*",
|
||||||
"dangerousDisableAssetCspModification": false,
|
"$VIDEO/*",
|
||||||
"dangerousRemoteDomainIpcAccess": [],
|
"$APPCONFIG/*",
|
||||||
"freezePrototype": false
|
"$RESOURCE/*"
|
||||||
},
|
]
|
||||||
"trayIcon": {
|
},
|
||||||
"iconPath": "icons/tray.png"
|
"dangerousDisableAssetCspModification": false,
|
||||||
},
|
"dangerousRemoteDomainIpcAccess": [],
|
||||||
"macOSPrivateApi": true
|
"freezePrototype": false
|
||||||
}
|
},
|
||||||
|
"trayIcon": {
|
||||||
|
"iconPath": "icons/tray.png"
|
||||||
|
},
|
||||||
|
"macOSPrivateApi": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user