feat: refactor

This commit is contained in:
2024-01-12 20:32:45 +07:00
parent 67c6177291
commit 0487b8a801
63 changed files with 345 additions and 777 deletions

View File

@@ -1,4 +1,5 @@
import { ColumnProvider, LumeProvider } from "@lume/ark";
import { StorageProvider } from "@lume/storage";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Toaster } from "sonner";
import Router from "./router";
@@ -15,11 +16,13 @@ export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Toaster position="top-center" theme="system" closeButton />
<LumeProvider>
<ColumnProvider>
<Router />
</ColumnProvider>
</LumeProvider>
<StorageProvider>
<LumeProvider>
<ColumnProvider>
<Router />
</ColumnProvider>
</LumeProvider>
</StorageProvider>
</QueryClientProvider>
);
}

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { AppLayout, AuthLayout, HomeLayout, SettingsLayout } from "@lume/ui";
import { fetch } from "@tauri-apps/plugin-http";
import {
@@ -23,7 +24,7 @@ export default function Router() {
element: <HomeLayout />,
errorElement: <ErrorScreen />,
loader: async () => {
if (!storage.account) return redirect("auth");
if (!ark.account) return redirect("auth");
return null;
},
children: [

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
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,

View File

@@ -1,5 +1,5 @@
import { useStorage } from "@lume/ark";
import { EyeOffIcon, EyeOnIcon, LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { getPublicKey, nip19 } from "nostr-tools";
import { useState } from "react";
import { useForm } from "react-hook-form";

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import NDK, { NDKNip46Signer, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { nip19 } from "nostr-tools";
import { useState } from "react";

View File

@@ -1,10 +1,10 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { NIP05 } from "@lume/types";
import NDK, { NDKNip46Signer, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { Window } from "@tauri-apps/api/window";
import { fetch } from "@tauri-apps/plugin-http";
import { nip19 } from "nostr-tools";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
@@ -30,6 +30,13 @@ export function LoginWithOAuth() {
try {
setLoading(true);
if (!emailRegex.test(data.nip05)) {
setLoading(false);
return toast.error(
"Cannot verify your NIP-05 address, please try again later.",
);
}
const localPath = data.nip05.split("@")[0];
const service = data.nip05.split("@")[1];

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { InfoIcon, LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { FETCH_LIMIT } from "@lume/utils";
import { NDKKind } from "@nostr-dev-kit/ndk";
import * as Switch from "@radix-ui/react-switch";
@@ -57,7 +58,7 @@ export function OnboardingScreen() {
setLoading(true);
// get account contacts
await ark.getUserContacts(storage.account.pubkey);
await ark.getUserContacts(ark.account.pubkey);
// refetch newsfeed
await queryClient.prefetchInfiniteQuery({
@@ -73,7 +74,7 @@ export function OnboardingScreen() {
const events = await ark.getInfiniteEvents({
filter: {
kinds: [NDKKind.Text, NDKKind.Repost],
authors: storage.account.contacts,
authors: ark.account.contacts,
},
limit: FETCH_LIMIT,
pageParam,

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { LoaderIcon, RunIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { User } from "@lume/ui";
import { NDKKind } from "@nostr-dev-kit/ndk";
import { useState } from "react";
@@ -17,7 +18,7 @@ export function DepotContactCard() {
const event = await ark.getEventByFilter({
filter: {
authors: [storage.account.pubkey],
authors: [ark.account.pubkey],
kinds: [NDKKind.Contacts],
},
});
@@ -39,13 +40,13 @@ export function DepotContactCard() {
<div className="flex h-56 w-full flex-col gap-2 overflow-hidden rounded-xl bg-neutral-100 p-2 dark:bg-neutral-900">
<div className="flex flex-1 items-center justify-center rounded-lg bg-neutral-200 dark:bg-neutral-800">
<div className="isolate flex -space-x-2">
{storage.account.contacts?.slice(0, 8).map((item) => (
{ark.account.contacts?.slice(0, 8).map((item) => (
<User key={item} pubkey={item} variant="ministacked" />
))}
{storage.account.contacts?.length > 8 ? (
{ark.account.contacts?.length > 8 ? (
<div className="inline-flex h-6 w-6 items-center justify-center rounded-full bg-neutral-300 text-neutral-900 ring-1 ring-white dark:bg-neutral-700 dark:text-neutral-100 dark:ring-black">
<span className="text-[8px] font-medium">
+{storage.account.contacts?.length - 8}
+{ark.account.contacts?.length - 8}
</span>
</div>
) : null}

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { LoaderIcon, RunIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { User } from "@lume/ui";
import { NDKKind } from "@nostr-dev-kit/ndk";
import { useState } from "react";
@@ -17,7 +18,7 @@ export function DepotProfileCard() {
const event = await ark.getEventByFilter({
filter: {
authors: [storage.account.pubkey],
authors: [ark.account.pubkey],
kinds: [NDKKind.Metadata],
},
});
@@ -38,7 +39,7 @@ export function DepotProfileCard() {
return (
<div className="flex h-56 w-full flex-col gap-2 overflow-hidden rounded-xl bg-neutral-100 p-2 dark:bg-neutral-900">
<div className="flex flex-1 items-center justify-center rounded-lg bg-neutral-200 dark:bg-neutral-800">
<User pubkey={storage.account.pubkey} variant="simple" />
<User pubkey={ark.account.pubkey} variant="simple" />
</div>
<div className="inline-flex shrink-0 items-center justify-between">
<div className="text-sm font-medium">Profile</div>

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { LoaderIcon, RunIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { NDKKind } from "@nostr-dev-kit/ndk";
import { useEffect, useState } from "react";
import { toast } from "sonner";
@@ -17,7 +18,7 @@ export function DepotRelaysCard() {
const event = await ark.getEventByFilter({
filter: {
authors: [storage.account.pubkey],
authors: [ark.account.pubkey],
kinds: [NDKKind.RelayList],
},
});
@@ -39,7 +40,7 @@ export function DepotRelaysCard() {
async function loadRelays() {
const event = await ark.getEventByFilter({
filter: {
authors: [storage.account.pubkey],
authors: [ark.account.pubkey],
kinds: [NDKKind.RelayList],
},
});

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { ChevronDownIcon, DepotIcon, GossipIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { NDKKind } from "@nostr-dev-kit/ndk";
import * as Collapsible from "@radix-ui/react-collapsible";
import { invoke } from "@tauri-apps/api/core";
@@ -36,7 +37,7 @@ export function DepotScreen() {
const relayEvent = await ark.getEventByFilter({
filter: {
authors: [storage.account.pubkey],
authors: [ark.account.pubkey],
kinds: [NDKKind.RelayList],
},
});

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { delay } from "@lume/utils";
import { resolveResource } from "@tauri-apps/api/path";
import { readTextFile, writeTextFile } from "@tauri-apps/plugin-fs";
@@ -26,9 +27,7 @@ export function DepotOnboardingScreen() {
// add current user to whitelist
// biome-ignore lint/complexity/useLiteralKeys: <explanation>
parsedConfig.authorization["pubkey_whitelist"].push(
storage.account.pubkey,
);
parsedConfig.authorization["pubkey_whitelist"].push(ark.account.pubkey);
// update new config
const newConfig = stringify(parsedConfig);

View File

@@ -1,4 +1,4 @@
import { useStorage } from "@lume/ark";
import { useStorage } from "@lume/storage";
import { downloadDir } from "@tauri-apps/api/path";
import { message, save } from "@tauri-apps/plugin-dialog";
import { writeTextFile } from "@tauri-apps/plugin-fs";
@@ -25,18 +25,18 @@ export function ErrorScreen() {
const filePath = await save({
defaultPath: `${downloadPath}/${fileName}`,
});
const nsec = await storage.loadPrivkey(storage.account.pubkey);
const nsec = await storage.loadPrivkey(ark.account.pubkey);
if (filePath) {
if (nsec) {
await writeTextFile(
filePath,
`Nostr account, generated by Lume (lume.nu)\nPublic key: ${storage.account.id}\nPrivate key: ${nsec}`,
`Nostr account, generated by Lume (lume.nu)\nPublic key: ${ark.account.id}\nPrivate key: ${nsec}`,
);
} else {
await writeTextFile(
filePath,
`Nostr account, generated by Lume (lume.nu)\nPublic key: ${storage.account.id}`,
`Nostr account, generated by Lume (lume.nu)\nPublic key: ${ark.account.id}`,
);
}
} // else { user cancel action }

View File

@@ -1,5 +1,5 @@
import { useStorage } from "@lume/ark";
import { LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { useState } from "react";
import { toast } from "sonner";
@@ -25,7 +25,7 @@ export function NWCForm({ setWalletConnectURL }) {
const params = new URLSearchParams(uriObj.search);
if (params.has("relay") && params.has("secret")) {
await storage.createPrivkey(`${storage.account.pubkey}-nwc`, uri);
await storage.createPrivkey(`${ark.account.pubkey}-nwc`, uri);
setWalletConnectURL(uri);
setLoading(false);
} else {

View File

@@ -1,5 +1,5 @@
import { useStorage } from "@lume/ark";
import { CheckCircleIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { useEffect, useState } from "react";
import { NWCForm } from "./components/form";
@@ -8,13 +8,13 @@ export function NWCScreen() {
const [walletConnectURL, setWalletConnectURL] = useState<null | string>(null);
const remove = async () => {
await storage.removePrivkey(`${storage.account.pubkey}-nwc`);
await storage.removePrivkey(`${ark.account.pubkey}-nwc`);
setWalletConnectURL(null);
};
useEffect(() => {
async function getNWC() {
const nwc = await storage.loadPrivkey(`${storage.account.pubkey}-nwc`);
const nwc = await storage.loadPrivkey(`${ark.account.pubkey}-nwc`);
if (nwc) setWalletConnectURL(nwc);
}
getNWC();

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { CancelIcon, RefreshIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { NDKKind } from "@nostr-dev-kit/ndk";
import { useQuery } from "@tanstack/react-query";
import { RelayForm } from "./relayForm";
@@ -9,12 +10,12 @@ export function UserRelayList() {
const storage = useStorage();
const { status, data, refetch } = useQuery({
queryKey: ["relays", storage.account.pubkey],
queryKey: ["relays", ark.account.pubkey],
queryFn: async () => {
const event = await ark.getEventByFilter({
filter: {
kinds: [NDKKind.RelayList],
authors: [storage.account.pubkey],
authors: [ark.account.pubkey],
},
});

View File

@@ -1,4 +1,4 @@
import { useStorage } from "@lume/ark";
import { useStorage } from "@lume/storage";
export function AdvancedSettingScreen() {
const storage = useStorage();

View File

@@ -1,5 +1,5 @@
import { useStorage } from "@lume/ark";
import { EyeOffIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { nip19 } from "nostr-tools";
import { useEffect, useState } from "react";
@@ -10,12 +10,12 @@ export function BackupSettingScreen() {
const [showPassword, setShowPassword] = useState(false);
const removePrivkey = async () => {
await storage.removePrivkey(storage.account.pubkey);
await storage.removePrivkey(ark.account.pubkey);
};
useEffect(() => {
async function loadPrivkey() {
const key = await storage.loadPrivkey(storage.account.pubkey);
const key = await storage.loadPrivkey(ark.account.pubkey);
if (key) setPrivkey(key);
}

View File

@@ -1,5 +1,5 @@
import { useStorage } from "@lume/ark";
import { LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { compactNumber } from "@lume/utils";
import { useQuery } from "@tanstack/react-query";
import { fetch } from "@tauri-apps/plugin-http";
@@ -8,10 +8,10 @@ import { Link } from "react-router-dom";
export function PostCard() {
const storage = useStorage();
const { status, data } = useQuery({
queryKey: ["user-stats", storage.account.pubkey],
queryKey: ["user-stats", ark.account.pubkey],
queryFn: async ({ signal }: { signal: AbortSignal }) => {
const res = await fetch(
`https://api.nostr.band/v0/stats/profile/${storage.account.pubkey}`,
`https://api.nostr.band/v0/stats/profile/${ark.account.pubkey}`,
{
signal,
},
@@ -39,7 +39,7 @@ export function PostCard() {
<div className="flex h-full w-full flex-col justify-between p-4">
<h3 className="pt-1 text-5xl font-semibold tabular-nums text-neutral-900 dark:text-neutral-100">
{compactNumber.format(
data.stats[storage.account.pubkey].pub_note_count,
data.stats[ark.account.pubkey].pub_note_count,
)}
</h3>
<div className="mt-auto flex h-6 w-full items-center justify-between">
@@ -47,7 +47,7 @@ export function PostCard() {
Posts
</p>
<Link
to={`/users/${storage.account.pubkey}`}
to={`/users/${ark.account.pubkey}`}
className="inline-flex h-6 w-max items-center gap-1 rounded-full bg-neutral-200 px-2.5 text-sm font-medium hover:bg-neutral-300 dark:bg-neutral-800 dark:hover:bg-neutral-700"
>
View

View File

@@ -1,5 +1,6 @@
import { useProfile, useStorage } from "@lume/ark";
import { useProfile } from "@lume/ark";
import { EditIcon, LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { displayNpub } from "@lume/utils";
import * as Avatar from "@radix-ui/react-avatar";
import { writeText } from "@tauri-apps/plugin-clipboard-manager";
@@ -10,13 +11,13 @@ import { Link } from "react-router-dom";
export function ProfileCard() {
const storage = useStorage();
const svgURI = `data:image/svg+xml;utf8,${encodeURIComponent(
minidenticon(storage.account.pubkey, 90, 50),
minidenticon(ark.account.pubkey, 90, 50),
)}`;
const { isLoading, user } = useProfile(storage.account.pubkey);
const { isLoading, user } = useProfile(ark.account.pubkey);
const copyNpub = async () => {
return await writeText(nip19.npubEncode(storage.account.pubkey));
return await writeText(nip19.npubEncode(ark.account.pubkey));
};
return (
@@ -47,7 +48,7 @@ export function ProfileCard() {
<Avatar.Root className="shrink-0">
<Avatar.Image
src={user?.picture || user?.image}
alt={storage.account.pubkey}
alt={ark.account.pubkey}
loading="lazy"
decoding="async"
style={{ contentVisibility: "auto" }}
@@ -56,7 +57,7 @@ export function ProfileCard() {
<Avatar.Fallback delayMs={300}>
<img
src={svgURI}
alt={storage.account.pubkey}
alt={ark.account.pubkey}
className="h-16 w-16 rounded-xl bg-black dark:bg-white"
/>
</Avatar.Fallback>
@@ -66,7 +67,7 @@ export function ProfileCard() {
{user?.display_name || user?.name}
</h3>
<p className="text-lg text-neutral-700 dark:text-neutral-300">
{user?.nip05 || displayNpub(storage.account.pubkey, 16)}
{user?.nip05 || displayNpub(ark.account.pubkey, 16)}
</p>
</div>
</div>

View File

@@ -1,5 +1,6 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import { EditIcon, LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { compactNumber } from "@lume/utils";
import { useQuery } from "@tanstack/react-query";
import { Link } from "react-router-dom";
@@ -9,7 +10,7 @@ export function RelayCard() {
const storage = useStorage();
const { status, data } = useQuery({
queryKey: ["relays", storage.account.pubkey],
queryKey: ["relays", ark.account.pubkey],
queryFn: async () => {
const relays = await ark.getUserRelays({});
return relays;

View File

@@ -1,5 +1,5 @@
import { useStorage } from "@lume/ark";
import { LoaderIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import { compactNumber } from "@lume/utils";
import { useQuery } from "@tanstack/react-query";
import { fetch } from "@tauri-apps/plugin-http";
@@ -7,10 +7,10 @@ import { fetch } from "@tauri-apps/plugin-http";
export function ZapCard() {
const storage = useStorage();
const { status, data } = useQuery({
queryKey: ["user-stats", storage.account.pubkey],
queryKey: ["user-stats", ark.account.pubkey],
queryFn: async ({ signal }: { signal: AbortSignal }) => {
const res = await fetch(
`https://api.nostr.band/v0/stats/profile/${storage.account.pubkey}`,
`https://api.nostr.band/v0/stats/profile/${ark.account.pubkey}`,
{
signal,
},
@@ -38,8 +38,7 @@ export function ZapCard() {
<div className="flex h-full w-full flex-col justify-between p-4">
<h3 className="pt-1 text-5xl font-semibold tabular-nums text-neutral-900 dark:text-neutral-100">
{compactNumber.format(
data?.stats[storage.account.pubkey]?.zaps_received?.msats /
1000 || 0,
data?.stats[ark.account.pubkey]?.zaps_received?.msats / 1000 || 0,
)}
</h3>
<div className="mt-auto flex h-6 items-center text-xl font-medium leading-none text-neutral-600 dark:text-neutral-400">

View File

@@ -1,10 +1,11 @@
import { useArk, useStorage } from "@lume/ark";
import { useArk } from "@lume/ark";
import {
CheckCircleIcon,
LoaderIcon,
PlusIcon,
UnverifiedIcon,
} from "@lume/icons";
import { useStorage } from "@lume/storage";
import { NDKKind, NDKUserProfile } from "@nostr-dev-kit/ndk";
import { useQueryClient } from "@tanstack/react-query";
import { message } from "@tauri-apps/plugin-dialog";
@@ -31,7 +32,7 @@ export function EditProfileScreen() {
defaultValues: async () => {
const res: NDKUserProfile = queryClient.getQueryData([
"user",
storage.account.pubkey,
ark.account.pubkey,
]);
if (res.image) {
setPicture(res.image);
@@ -102,7 +103,7 @@ export function EditProfileScreen() {
if (data.nip05) {
const verify = ark.validateNIP05({
pubkey: storage.account.pubkey,
pubkey: ark.account.pubkey,
nip05: data.nip05,
});
if (verify) {
@@ -125,7 +126,7 @@ export function EditProfileScreen() {
if (publish) {
// invalid cache
queryClient.invalidateQueries({
queryKey: ["user", storage.account.pubkey],
queryKey: ["user", ark.account.pubkey],
});
// reset form
reset();

View File

@@ -1,5 +1,5 @@
import { useStorage } from "@lume/ark";
import { DarkIcon, LightIcon, SystemModeIcon } from "@lume/icons";
import { useStorage } from "@lume/storage";
import * as Switch from "@radix-ui/react-switch";
import { invoke } from "@tauri-apps/api/core";
import { getCurrent } from "@tauri-apps/api/window";

View File

@@ -1,4 +1,5 @@
import { useArk, useProfile, useStorage } from "@lume/ark";
import { useArk, useProfile } from "@lume/ark";
import { useStorage } from "@lume/storage";
import { NIP05 } from "@lume/ui";
import { displayNpub } from "@lume/utils";
import * as Avatar from "@radix-ui/react-avatar";
@@ -50,7 +51,7 @@ export function UserProfile({ pubkey }: { pubkey: string }) {
};
useEffect(() => {
if (storage.account.contacts.includes(pubkey)) {
if (ark.account.contacts.includes(pubkey)) {
setFollowed(true);
}
}, []);