feat: improve

This commit is contained in:
reya 2024-04-10 14:11:05 +07:00
parent 5e6692cd6d
commit c342daecc8
26 changed files with 992 additions and 789 deletions

View File

@ -19,15 +19,15 @@
"@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-switch": "^1.0.3",
"@tanstack/query-sync-storage-persister": "^5.28.13", "@tanstack/query-sync-storage-persister": "^5.29.0",
"@tanstack/react-query": "^5.28.14", "@tanstack/react-query": "^5.29.0",
"@tanstack/react-query-persist-client": "^5.28.14", "@tanstack/react-query-persist-client": "^5.29.0",
"@tanstack/react-router": "^1.26.7", "@tanstack/react-router": "^1.26.18",
"i18next": "^23.10.1", "i18next": "^23.11.1",
"i18next-resources-to-backend": "^1.2.0", "i18next-resources-to-backend": "^1.2.0",
"minidenticons": "^4.2.1", "minidenticons": "^4.2.1",
"nanoid": "^5.0.6", "nanoid": "^5.0.7",
"nostr-tools": "^2.3.2", "nostr-tools": "^2.4.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-currency-input-field": "^3.8.0", "react-currency-input-field": "^3.8.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
@ -38,21 +38,21 @@
"slate-react": "^0.102.0", "slate-react": "^0.102.0",
"sonner": "^1.4.41", "sonner": "^1.4.41",
"use-debounce": "^10.0.0", "use-debounce": "^10.0.0",
"virtua": "^0.29.1" "virtua": "^0.29.2"
}, },
"devDependencies": { "devDependencies": {
"@lume/tailwindcss": "workspace:^", "@lume/tailwindcss": "workspace:^",
"@lume/tsconfig": "workspace:^", "@lume/tsconfig": "workspace:^",
"@lume/types": "workspace:^", "@lume/types": "workspace:^",
"@tanstack/router-devtools": "^1.26.7", "@tanstack/router-devtools": "^1.26.18",
"@tanstack/router-vite-plugin": "^1.26.8", "@tanstack/router-vite-plugin": "^1.26.16",
"@types/react": "^18.2.74", "@types/react": "^18.2.75",
"@types/react-dom": "^18.2.24", "@types/react-dom": "^18.2.24",
"@vitejs/plugin-react-swc": "^3.6.0", "@vitejs/plugin-react-swc": "^3.6.0",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"typescript": "^5.4.3", "typescript": "^5.4.4",
"vite": "^5.2.8", "vite": "^5.2.8",
"vite-plugin-top-level-await": "^1.4.1", "vite-plugin-top-level-await": "^1.4.1",
"vite-tsconfig-paths": "^4.3.2" "vite-tsconfig-paths": "^4.3.2"

View File

@ -6,7 +6,6 @@ import { I18nextProvider } from "react-i18next";
import "./app.css"; import "./app.css";
import i18n from "./locale"; import i18n from "./locale";
import { Toaster } from "sonner"; import { Toaster } from "sonner";
import { locale, platform } from "@tauri-apps/plugin-os";
import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client"; import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client";
import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister"; import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister";
import { routeTree } from "./router.gen"; // auto generated file import { routeTree } from "./router.gen"; // auto generated file
@ -27,18 +26,11 @@ const persister = createSyncStoragePersister({
}); });
const ark = new Ark(); const ark = new Ark();
const platformName = await platform();
const osLocale = await locale();
// Set up a Router instance // Set up a Router instance
const router = createRouter({ const router = createRouter({
routeTree, routeTree,
context: { context: {
platform: platformName,
locale: osLocale,
settings: null,
accounts: null,
interests: null,
ark, ark,
queryClient, queryClient,
}, },

View File

@ -34,7 +34,7 @@ export function AvatarUploader({
<button <button
type="button" type="button"
onClick={() => uploadAvatar()} onClick={() => uploadAvatar()}
className={cn("", className)} className={cn("size-4", className)}
> >
{loading ? <LoaderIcon className="size-4 animate-spin" /> : children} {loading ? <LoaderIcon className="size-4 animate-spin" /> : children}
</button> </button>

View File

@ -1,8 +1,8 @@
import { useEffect, useMemo, useRef } from "react"; import { useEffect, useRef } from "react";
import { getCurrent } from "@tauri-apps/api/window";
import { LumeColumn } from "@lume/types"; import { LumeColumn } from "@lume/types";
import { invoke } from "@tauri-apps/api/core"; import { invoke } from "@tauri-apps/api/core";
import { LoaderIcon } from "@lume/icons"; import { LoaderIcon } from "@lume/icons";
import { cn } from "@lume/utils";
export function Col({ export function Col({
column, column,
@ -13,43 +13,18 @@ export function Col({
account: string; account: string;
isScroll: boolean; isScroll: boolean;
}) { }) {
const window = useMemo(() => getCurrent(), []); const webview = useRef<string | undefined>(undefined);
const webview = useRef<string>(null);
const container = useRef<HTMLDivElement>(null); const container = useRef<HTMLDivElement>(null);
const createWebview = async () => {
const rect = container.current.getBoundingClientRect();
const label = `column-${column.label}`;
const url =
column.content +
`?account=${account}&label=${column.label}&name=${column.name}`;
// create new webview
webview.current = await invoke("create_column", {
label,
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
url,
});
};
const closeWebview = async () => {
const close = await invoke("close_column", {
label: webview.current,
});
if (close) webview.current = null;
};
const repositionWebview = async () => { const repositionWebview = async () => {
if (!webview.current) return; if (webview.current && webview.current.length > 1) {
const newRect = container.current.getBoundingClientRect(); const newRect = container.current.getBoundingClientRect();
await invoke("reposition_column", { await invoke("reposition_column", {
label: webview.current, label: webview.current,
x: newRect.x, x: newRect.x,
y: newRect.y, y: newRect.y,
}); });
}
}; };
useEffect(() => { useEffect(() => {
@ -59,27 +34,50 @@ export function Col({
}, [isScroll]); }, [isScroll]);
useEffect(() => { useEffect(() => {
if (!window) return; (async () => {
if (!container.current) return; const rect = container.current.getBoundingClientRect();
if (webview.current) return; const windowLabel = `column-${column.label}`;
const url =
column.content +
`?account=${account}&label=${column.label}&name=${column.name}`;
// create webview for current column // create new webview
createWebview(); webview.current = await invoke("create_column", {
label: windowLabel,
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
url,
});
})();
// close webview when unmounted // close webview when unmounted
return () => { return () => {
if (webview.current) closeWebview(); if (webview.current && webview.current.length > 1) {
invoke("close_column", {
label: webview.current,
}).then(() => {
webview.current = undefined;
});
}
}; };
}, []); }, []);
return ( return (
<div <div ref={container} className="h-full w-[440px] shrink-0 p-2">
ref={container} <div
className="h-full w-[440px] shrink-0 p-2 flex items-center justify-center" className={cn(
> "w-full h-full flex items-center justify-center",
<button type="button" disabled> !webview?.current?.length
<LoaderIcon className="size-5 animate-spin" /> ? "rounded-xl flex-col bg-black/5 dark:bg-white/5 backdrop-blur-lg"
</button> : "",
)}
>
<button type="button" className="size-5" disabled>
<LoaderIcon className="size-5 animate-spin" />
</button>
</div>
</div> </div>
); );
} }

View File

@ -3,11 +3,12 @@ import { Toolbar } from "@/components/toolbar";
import { LoaderIcon } from "@lume/icons"; import { LoaderIcon } from "@lume/icons";
import { EventColumns, LumeColumn } from "@lume/types"; import { EventColumns, LumeColumn } from "@lume/types";
import { createFileRoute } from "@tanstack/react-router"; import { createFileRoute } from "@tanstack/react-router";
import { UnlistenFn } from "@tauri-apps/api/event"; import { listen } from "@tauri-apps/api/event";
import { resolveResource } from "@tauri-apps/api/path"; import { resolveResource } from "@tauri-apps/api/path";
import { getCurrent } from "@tauri-apps/api/window";
import { readTextFile } from "@tauri-apps/plugin-fs"; import { readTextFile } from "@tauri-apps/plugin-fs";
import { nanoid } from "nanoid";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
import { VList, VListHandle } from "virtua"; import { VList, VListHandle } from "virtua";
export const Route = createFileRoute("/$account/home")({ export const Route = createFileRoute("/$account/home")({
@ -53,40 +54,45 @@ function Screen() {
}); });
}; };
const add = (column: LumeColumn) => { const add = useDebouncedCallback((column: LumeColumn) => {
setColumns((state) => [...state, column]); column["label"] = column.label + "-" + nanoid();
};
const remove = (label: string) => { setColumns((state) => [...state, column]);
setSelectedIndex(columns.length + 1);
// scroll to the last column
vlistRef.current.scrollToIndex(columns.length + 1, {
align: "end",
});
}, 150);
const remove = useDebouncedCallback((label: string) => {
setColumns((state) => state.filter((t) => t.label !== label)); setColumns((state) => state.filter((t) => t.label !== label));
}; setSelectedIndex(columns.length - 1);
// scroll to the first column
vlistRef.current.scrollToIndex(0, {
align: "start",
});
}, 150);
useEffect(() => { useEffect(() => {
ark.set_columns(columns); ark.set_columns(columns);
}, [columns]); }, [columns]);
useEffect(() => { useEffect(() => {
let unlisten: UnlistenFn = undefined; let unlisten: Awaited<ReturnType<typeof listen>> | undefined = undefined;
const listenColumnEvent = async () => { (async () => {
const mainWindow = getCurrent(); if (unlisten) return;
if (!unlisten) { unlisten = await listen<EventColumns>("columns", (data) => {
unlisten = await mainWindow.listen<EventColumns>("columns", (data) => { if (data.payload.type === "add") add(data.payload.column);
if (data.payload.type === "add") add(data.payload.column); if (data.payload.type === "remove") remove(data.payload.label);
if (data.payload.type === "remove") remove(data.payload.label); });
}); })();
}
};
// listen for column changes
listenColumnEvent();
// clean up
return () => { return () => {
if (unlisten) { if (unlisten) unlisten();
unlisten();
unlisten = undefined;
}
}; };
}, []); }, []);
@ -122,9 +128,9 @@ function Screen() {
}} }}
className="scrollbar-none h-full w-full overflow-x-auto focus:outline-none" className="scrollbar-none h-full w-full overflow-x-auto focus:outline-none"
> >
{columns.map((column) => ( {columns.map((column, index) => (
<Col <Col
key={column.label} key={column.label + index}
column={column} column={column}
account={account} account={account}
isScroll={isScroll} isScroll={isScroll}
@ -139,7 +145,7 @@ function Screen() {
function Pending() { function Pending() {
return ( return (
<div className="flex h-full w-full items-center justify-center"> <div className="flex h-full w-full items-center justify-center">
<button type="button" disabled> <button type="button" className="size-5" disabled>
<LoaderIcon className="size-5 animate-spin" /> <LoaderIcon className="size-5 animate-spin" />
</button> </button>
</div> </div>

View File

@ -2,9 +2,14 @@ import { ComposeFilledIcon, PlusIcon } from "@lume/icons";
import { Outlet, createFileRoute, useNavigate } from "@tanstack/react-router"; import { Outlet, createFileRoute, useNavigate } from "@tanstack/react-router";
import { cn } from "@lume/utils"; import { cn } from "@lume/utils";
import { Accounts } from "@/components/accounts"; import { Accounts } from "@/components/accounts";
import { platform } from "@tauri-apps/plugin-os";
export const Route = createFileRoute("/$account")({ export const Route = createFileRoute("/$account")({
component: App, component: App,
beforeLoad: async () => {
const platformName = await platform();
return { platform: platformName };
},
}); });
function App() { function App() {

View File

@ -1,9 +1,5 @@
import { LoaderIcon } from "@lume/icons"; import { LoaderIcon } from "@lume/icons";
import { import { Outlet, createRootRouteWithContext } from "@tanstack/react-router";
Outlet,
ScrollRestoration,
createRootRouteWithContext,
} from "@tanstack/react-router";
import { type Ark } from "@lume/ark"; import { type Ark } from "@lume/ark";
import { type QueryClient } from "@tanstack/react-query"; import { type QueryClient } from "@tanstack/react-query";
import { type Platform } from "@tauri-apps/plugin-os"; import { type Platform } from "@tauri-apps/plugin-os";
@ -12,20 +8,15 @@ import { Account, Interests, Settings } from "@lume/types";
interface RouterContext { interface RouterContext {
ark: Ark; ark: Ark;
queryClient: QueryClient; queryClient: QueryClient;
platform: Platform; platform?: Platform;
locale: string; locale?: string;
settings: Settings; settings?: Settings;
interests: Interests; interests?: Interests;
accounts: Account[]; accounts?: Account[];
} }
export const Route = createRootRouteWithContext<RouterContext>()({ export const Route = createRootRouteWithContext<RouterContext>()({
component: () => ( component: () => <Outlet />,
<>
<ScrollRestoration />
<Outlet />
</>
),
pendingComponent: Pending, pendingComponent: Pending,
wrapInSuspense: true, wrapInSuspense: true,
}); });
@ -33,7 +24,9 @@ export const Route = createRootRouteWithContext<RouterContext>()({
function Pending() { function Pending() {
return ( return (
<div className="flex h-screen w-screen flex-col items-center justify-center"> <div className="flex h-screen w-screen flex-col items-center justify-center">
<LoaderIcon className="size-5 animate-spin" /> <button type="button" className="size-5" disabled>
<LoaderIcon className="size-5 animate-spin" />
</button>
</div> </div>
); );
} }

View File

@ -1,16 +1,21 @@
import { CheckIcon } from "@lume/icons"; import { LaurelIcon } from "@lume/icons";
import { createLazyFileRoute, useNavigate } from "@tanstack/react-router"; import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import * as Switch from "@radix-ui/react-switch"; import * as Switch from "@radix-ui/react-switch";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Settings } from "@lume/types"; import { AppRouteSearch, Settings } from "@lume/types";
import { import {
isPermissionGranted, isPermissionGranted,
requestPermission, requestPermission,
} from "@tauri-apps/plugin-notification"; } from "@tauri-apps/plugin-notification";
import { toast } from "sonner"; import { toast } from "sonner";
export const Route = createLazyFileRoute("/auth/settings")({ export const Route = createFileRoute("/auth/settings")({
validateSearch: (search: Record<string, string>): AppRouteSearch => {
return {
account: search.account,
};
},
component: Screen, component: Screen,
}); });
@ -25,6 +30,7 @@ function Screen() {
notification: false, notification: false,
enhancedPrivacy: false, enhancedPrivacy: false,
autoUpdate: false, autoUpdate: false,
zap: false,
}); });
const toggleNofitication = async () => { const toggleNofitication = async () => {
@ -49,6 +55,13 @@ function Screen() {
})); }));
}; };
const toggleZap = () => {
setSettings((prev) => ({
...prev,
zap: !settings.zap,
}));
};
const submit = async () => { const submit = async () => {
try { try {
const eventId = await ark.set_settings(settings); const eventId = await ark.set_settings(settings);
@ -64,7 +77,6 @@ function Screen() {
async function loadSettings() { async function loadSettings() {
const permissionGranted = await isPermissionGranted(); // get notification permission const permissionGranted = await isPermissionGranted(); // get notification permission
const settings = await ark.get_settings(); const settings = await ark.get_settings();
setSettings({ ...settings, notification: permissionGranted }); setSettings({ ...settings, notification: permissionGranted });
} }
@ -75,7 +87,7 @@ function Screen() {
<div className="mx-auto flex h-full w-full flex-col items-center justify-center gap-6 px-5 xl:max-w-xl"> <div className="mx-auto flex h-full w-full flex-col items-center justify-center gap-6 px-5 xl:max-w-xl">
<div className="flex flex-col items-center gap-5 text-center"> <div className="flex flex-col items-center gap-5 text-center">
<div className="flex size-20 items-center justify-center rounded-full bg-teal-100 text-teal-500"> <div className="flex size-20 items-center justify-center rounded-full bg-teal-100 text-teal-500">
<CheckIcon className="size-6" /> <LaurelIcon className="size-8" />
</div> </div>
<div> <div>
<h1 className="text-xl font-semibold"> <h1 className="text-xl font-semibold">
@ -135,6 +147,22 @@ function Screen() {
</p> </p>
</div> </div>
</div> </div>
<div className="flex w-full items-start justify-between gap-4 rounded-lg bg-neutral-100 px-5 py-4 dark:bg-neutral-900">
<Switch.Root
checked={settings.zap}
onClick={() => toggleZap()}
className="relative mt-1 h-7 w-12 shrink-0 cursor-default rounded-full bg-neutral-200 outline-none data-[state=checked]:bg-blue-500 dark:bg-neutral-800"
>
<Switch.Thumb className="block size-6 translate-x-0.5 rounded-full bg-white transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />
</Switch.Root>
<div className="flex-1">
<h3 className="font-semibold">Zap</h3>
<p className="text-sm text-neutral-700 dark:text-neutral-300">
Show the Zap button in each note and user's profile screen, use
for send Bitcoin tip to other users.
</p>
</div>
</div>
<div className="flex w-full items-start justify-between gap-4 rounded-lg bg-neutral-50 px-5 py-4 dark:bg-neutral-950"> <div className="flex w-full items-start justify-between gap-4 rounded-lg bg-neutral-50 px-5 py-4 dark:bg-neutral-950">
<p className="text-sm text-neutral-700 dark:text-neutral-300"> <p className="text-sm text-neutral-700 dark:text-neutral-300">
There are many more settings you can configure from the 'Settings' There are many more settings you can configure from the 'Settings'

View File

@ -1,7 +1,7 @@
import { CheckCircleIcon } from "@lume/icons"; import { CheckCircleIcon } from "@lume/icons";
import { ColumnRouteSearch } from "@lume/types"; import { ColumnRouteSearch } from "@lume/types";
import { Column, User } from "@lume/ui"; import { Column, User } from "@lume/ui";
import { createFileRoute } from "@tanstack/react-router"; import { createFileRoute, useRouter } from "@tanstack/react-router";
import { useState } from "react"; import { useState } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
@ -23,9 +23,10 @@ export const Route = createFileRoute("/create-group")({
function Screen() { function Screen() {
const contacts = Route.useLoaderData(); const contacts = Route.useLoaderData();
const router = useRouter();
const { ark } = Route.useRouteContext(); const { ark } = Route.useRouteContext();
const { label, name } = Route.useSearch(); const { label, name, redirect } = Route.useSearch();
const [title, setTitle] = useState<string>("Just a new group"); const [title, setTitle] = useState<string>("Just a new group");
const [users, setUsers] = useState<Array<string>>([]); const [users, setUsers] = useState<Array<string>>([]);
@ -40,7 +41,7 @@ function Screen() {
const submit = async () => { const submit = async () => {
try { try {
if (isDone) return history.back(); if (isDone) return router.history.push(redirect);
const groups = await ark.set_nstore( const groups = await ark.set_nstore(
`lume_group_${label}`, `lume_group_${label}`,

View File

@ -24,8 +24,10 @@ export const Route = createFileRoute("/foryou")({
if (!interests) { if (!interests) {
throw redirect({ throw redirect({
to: "/interests", to: "/interests",
replace: false, search: {
search, ...search,
redirect: "/foryou",
},
}); });
} }

View File

@ -24,8 +24,10 @@ export const Route = createFileRoute("/group")({
if (!groups) { if (!groups) {
throw redirect({ throw redirect({
to: "/create-group", to: "/create-group",
replace: false, search: {
search, ...search,
redirect: "/group",
},
}); });
} }

View File

@ -1,7 +1,7 @@
import { ColumnRouteSearch } from "@lume/types"; import { ColumnRouteSearch } from "@lume/types";
import { Column } from "@lume/ui"; import { Column } from "@lume/ui";
import { TOPICS, cn } from "@lume/utils"; import { TOPICS, cn } from "@lume/utils";
import { createFileRoute } from "@tanstack/react-router"; import { createFileRoute, useRouter } from "@tanstack/react-router";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { toast } from "sonner"; import { toast } from "sonner";
@ -19,12 +19,14 @@ export const Route = createFileRoute("/interests")({
function Screen() { function Screen() {
const { t } = useTranslation(); const { t } = useTranslation();
const { label, name } = Route.useSearch(); const { label, name, redirect } = Route.useSearch();
const { ark } = Route.useRouteContext(); const { ark } = Route.useRouteContext();
const [hashtags, setHashtags] = useState<string[]>([]); const [hashtags, setHashtags] = useState<string[]>([]);
const [isDone, setIsDone] = useState(false); const [isDone, setIsDone] = useState(false);
const router = useRouter();
const toggleHashtag = (item: string) => { const toggleHashtag = (item: string) => {
const arr = hashtags.includes(item) const arr = hashtags.includes(item)
? hashtags.filter((i) => i !== item) ? hashtags.filter((i) => i !== item)
@ -40,7 +42,7 @@ function Screen() {
const submit = async () => { const submit = async () => {
try { try {
if (isDone) { if (isDone) {
return history.back(); return router.history.push(redirect);
} }
const eventId = await ark.set_interest(undefined, undefined, hashtags); const eventId = await ark.set_interest(undefined, undefined, hashtags);

View File

@ -38,23 +38,25 @@ function Screen() {
</Link> </Link>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="h-px flex-1 bg-white/20" /> <div className="h-px flex-1 bg-white/20" />
<span className="text-white">Or</span> <div className="text-white/70">{t("login.or")}</div>
<div className="h-px flex-1 bg-white/20" /> <div className="h-px flex-1 bg-white/20" />
</div> </div>
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<Link <Link
to="/auth/remote" to="/auth/remote"
className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-lg bg-white/20 px-3 font-medium text-white backdrop-blur-md hover:bg-white/40" className="group inline-flex h-11 w-full items-center justify-between gap-2 rounded-lg bg-white/20 px-3 font-medium text-white backdrop-blur-md hover:bg-white/40"
> >
<RemoteIcon className="size-5" /> <RemoteIcon className="size-5 text-neutral-600 dark:text-neutral-400 group-hover:text-neutral-400 dark:group-hover:text-neutral-600" />
Continue with Nostr Connect Nostr Connect
<div className="size-5" />
</Link> </Link>
<Link <Link
to="/auth/privkey" to="/auth/privkey"
className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-lg bg-white/20 px-3 font-medium text-white backdrop-blur-md hover:bg-white/40" className="group inline-flex h-11 w-full items-center justify-between gap-2 rounded-lg bg-white/20 px-3 font-medium text-white backdrop-blur-md hover:bg-white/40"
> >
<KeyIcon className="size-5" /> <KeyIcon className="size-5 text-neutral-600 dark:text-neutral-400 group-hover:text-neutral-400 dark:group-hover:text-neutral-600" />
Continue with Private Key Private Key
<div className="size-5" />
</Link> </Link>
</div> </div>
</div> </div>

View File

@ -1,16 +1,19 @@
import { RepostNote } from "@/components/repost";
import { Suggest } from "@/components/suggest"; import { Suggest } from "@/components/suggest";
import { TextNote } from "@/components/text"; import {
import { LoaderIcon, ArrowRightCircleIcon, InfoIcon } from "@lume/icons"; LoaderIcon,
ArrowRightCircleIcon,
InfoIcon,
RepostIcon,
} from "@lume/icons";
import { ColumnRouteSearch, Event, Kind } from "@lume/types"; import { ColumnRouteSearch, Event, Kind } from "@lume/types";
import { Column } from "@lume/ui"; import { Column, Note, User } from "@lume/ui";
import { useInfiniteQuery } from "@tanstack/react-query"; import { cn } from "@lume/utils";
import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
import { createFileRoute } from "@tanstack/react-router"; import { createFileRoute } from "@tanstack/react-router";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Virtualizer } from "virtua"; import { Virtualizer } from "virtua";
export const Route = createFileRoute("/newsfeed")({ export const Route = createFileRoute("/newsfeed")({
component: Screen,
validateSearch: (search: Record<string, string>): ColumnRouteSearch => { validateSearch: (search: Record<string, string>): ColumnRouteSearch => {
return { return {
account: search.account, account: search.account,
@ -22,10 +25,9 @@ export const Route = createFileRoute("/newsfeed")({
const ark = context.ark; const ark = context.ark;
const settings = await ark.get_settings(); const settings = await ark.get_settings();
return { return { settings };
settings,
};
}, },
component: Screen,
}); });
export function Screen() { export function Screen() {
@ -112,3 +114,145 @@ export function Screen() {
</Column.Root> </Column.Root>
); );
} }
function TextNote({ event, className }: { event: Event; className?: string }) {
const { settings } = Route.useRouteContext();
return (
<Note.Provider event={event}>
<Note.Root
className={cn(
"flex flex-col gap-2 border-b border-neutral-100 px-3 py-5 dark:border-neutral-900",
className,
)}
>
<Note.User />
<div className="flex gap-3">
<div className="size-11 shrink-0" />
<div className="min-w-0 flex-1">
<Note.Content className="mb-2" />
<Note.Thread />
<div className="mt-4 flex items-center justify-between">
<div className="-ml-1 inline-flex items-center gap-4">
<Note.Reply />
<Note.Repost />
{settings.zap ? <Note.Zap /> : null}
</div>
<Note.Menu />
</div>
</div>
</div>
</Note.Root>
</Note.Provider>
);
}
function RepostNote({
event,
className,
}: {
event: Event;
className?: string;
}) {
const { ark, settings } = Route.useRouteContext();
const { t } = useTranslation();
const {
isLoading,
isError,
data: repostEvent,
} = useQuery({
queryKey: ["repost", event.id],
queryFn: async () => {
try {
if (event.content.length > 50) {
const embed: Event = JSON.parse(event.content);
return embed;
}
const id = event.tags.find((el) => el[0] === "e")[1];
return await ark.get_event(id);
} catch {
throw new Error("Failed to get repost event");
}
},
refetchOnWindowFocus: false,
refetchOnMount: false,
});
if (isLoading) {
return <div className="w-full px-3 pb-3">Loading...</div>;
}
if (isError || !repostEvent) {
return (
<Note.Root
className={cn(
"flex flex-col gap-2 border-b border-neutral-100 px-3 py-5 dark:border-neutral-900",
className,
)}
>
<User.Provider pubkey={event.pubkey}>
<User.Root className="flex h-14 gap-2 px-3">
<div className="inline-flex w-10 shrink-0 items-center justify-center">
<RepostIcon className="h-5 w-5 text-blue-500" />
</div>
<div className="inline-flex items-center gap-2">
<User.Avatar className="size-6 shrink-0 rounded object-cover" />
<div className="inline-flex items-baseline gap-1">
<User.Name className="font-medium text-neutral-900 dark:text-neutral-100" />
<span className="text-blue-500">{t("note.reposted")}</span>
</div>
</div>
</User.Root>
</User.Provider>
<div className="mb-3 select-text px-3">
<div className="flex flex-col items-start justify-start rounded-lg bg-red-100 px-3 py-3 dark:bg-red-900">
<p className="text-red-500">Failed to get event</p>
</div>
</div>
</Note.Root>
);
}
return (
<Note.Root
className={cn(
"flex flex-col gap-2 border-b border-neutral-100 px-3 py-5 dark:border-neutral-900",
className,
)}
>
<User.Provider pubkey={event.pubkey}>
<User.Root className="flex gap-3">
<div className="inline-flex w-11 shrink-0 items-center justify-center">
<RepostIcon className="h-5 w-5 text-blue-500" />
</div>
<div className="inline-flex items-center gap-2">
<User.Avatar className="size-6 shrink-0 rounded-full object-cover" />
<div className="inline-flex items-baseline gap-1">
<User.Name className="font-medium text-neutral-900 dark:text-neutral-100" />
<span className="text-blue-500">{t("note.reposted")}</span>
</div>
</div>
</User.Root>
</User.Provider>
<Note.Provider event={repostEvent}>
<div className="flex flex-col gap-2">
<Note.User />
<div className="flex gap-3">
<div className="size-11 shrink-0" />
<div className="min-w-0 flex-1">
<Note.Content />
<div className="mt-4 flex items-center justify-between">
<div className="-ml-1 inline-flex items-center gap-4">
<Note.Reply />
<Note.Repost />
{settings.zap ? <Note.Zap /> : null}
</div>
<Note.Menu />
</div>
</div>
</div>
</div>
</Note.Provider>
</Note.Root>
);
}

View File

@ -6,7 +6,6 @@ import { Link } from "@tanstack/react-router";
import { Outlet, createFileRoute } from "@tanstack/react-router"; import { Outlet, createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/store")({ export const Route = createFileRoute("/store")({
component: Screen,
validateSearch: (search: Record<string, string>): ColumnRouteSearch => { validateSearch: (search: Record<string, string>): ColumnRouteSearch => {
return { return {
account: search.account, account: search.account,
@ -14,6 +13,7 @@ export const Route = createFileRoute("/store")({
name: search.name, name: search.name,
}; };
}, },
component: Screen,
}); });
function Screen() { function Screen() {

View File

@ -13,12 +13,12 @@
"@astrojs/check": "^0.5.10", "@astrojs/check": "^0.5.10",
"@astrojs/tailwind": "^5.1.0", "@astrojs/tailwind": "^5.1.0",
"@fontsource/geist-mono": "^5.0.2", "@fontsource/geist-mono": "^5.0.2",
"astro": "^4.5.15", "astro": "^4.5.18",
"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",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"typescript": "^5.4.3" "typescript": "^5.4.4"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/typography": "^0.5.12" "@tailwindcss/typography": "^0.5.12"

View File

@ -14,12 +14,12 @@
"@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.28.14", "@tanstack/react-query": "^5.29.0",
"@tanstack/react-router": "^1.26.7", "@tanstack/react-router": "^1.26.18",
"get-urls": "^12.1.0", "get-urls": "^12.1.0",
"media-chrome": "^3.2.0", "media-chrome": "^3.2.0",
"minidenticons": "^4.2.1", "minidenticons": "^4.2.1",
"nanoid": "^5.0.6", "nanoid": "^5.0.7",
"qrcode.react": "^3.1.0", "qrcode.react": "^3.1.0",
"re-resizable": "^6.9.11", "re-resizable": "^6.9.11",
"react": "^18.2.0", "react": "^18.2.0",
@ -27,15 +27,15 @@
"react-i18next": "^14.1.0", "react-i18next": "^14.1.0",
"react-string-replace": "^1.1.1", "react-string-replace": "^1.1.1",
"sonner": "^1.4.41", "sonner": "^1.4.41",
"string-strip-html": "^13.4.7", "string-strip-html": "^13.4.8",
"virtua": "^0.29.1" "virtua": "^0.29.2"
}, },
"devDependencies": { "devDependencies": {
"@lume/tailwindcss": "workspace:^", "@lume/tailwindcss": "workspace:^",
"@lume/tsconfig": "workspace:^", "@lume/tsconfig": "workspace:^",
"@lume/types": "workspace:^", "@lume/types": "workspace:^",
"@types/react": "^18.2.74", "@types/react": "^18.2.75",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"typescript": "^5.4.3" "typescript": "^5.4.4"
} }
} }

View File

@ -608,6 +608,7 @@ export class Ark {
autoUpdate: false, autoUpdate: false,
enhancedPrivacy: false, enhancedPrivacy: false,
notification: false, notification: false,
zap: false,
}; };
return defaultSettings; return defaultSettings;
} }

View File

@ -8,7 +8,7 @@
}, },
"devDependencies": { "devDependencies": {
"@lume/tsconfig": "workspace:*", "@lume/tsconfig": "workspace:*",
"@types/react": "^18.2.74", "@types/react": "^18.2.75",
"typescript": "^5.4.3" "typescript": "^5.4.4"
} }
} }

View File

@ -2,6 +2,7 @@ export interface Settings {
notification: boolean; notification: boolean;
enhancedPrivacy: boolean; enhancedPrivacy: boolean;
autoUpdate: boolean; autoUpdate: boolean;
zap: boolean;
} }
export interface Keys { export interface Keys {
@ -75,10 +76,15 @@ export interface RichContent {
notes: string[]; notes: string[];
} }
export interface AppRouteSearch {
account: string;
}
export interface ColumnRouteSearch { export interface ColumnRouteSearch {
account: string; account: string;
label: string; label: string;
name: string; name: string;
redirect?: string;
} }
export interface LumeColumn { export interface LumeColumn {

View File

@ -9,6 +9,6 @@
"access": "public" "access": "public"
}, },
"devDependencies": { "devDependencies": {
"typescript": "^5.4.3" "typescript": "^5.4.4"
} }
} }

View File

@ -8,7 +8,7 @@
"@lume/ark": "workspace:^", "@lume/ark": "workspace:^",
"@lume/icons": "workspace:^", "@lume/icons": "workspace:^",
"@lume/utils": "workspace:^", "@lume/utils": "workspace:^",
"@nostr-dev-kit/ndk": "^2.6.1", "@nostr-dev-kit/ndk": "^2.7.1",
"@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",
@ -18,13 +18,13 @@
"@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.28.14", "@tanstack/react-query": "^5.29.0",
"@tanstack/react-router": "^1.26.7", "@tanstack/react-router": "^1.26.18",
"framer-motion": "^11.0.24", "framer-motion": "^11.0.25",
"get-urls": "^12.1.0", "get-urls": "^12.1.0",
"media-chrome": "^3.2.0", "media-chrome": "^3.2.0",
"minidenticons": "^4.2.1", "minidenticons": "^4.2.1",
"nanoid": "^5.0.6", "nanoid": "^5.0.7",
"qrcode.react": "^3.1.0", "qrcode.react": "^3.1.0",
"re-resizable": "^6.9.11", "re-resizable": "^6.9.11",
"react": "^18.2.0", "react": "^18.2.0",
@ -37,17 +37,17 @@
"slate": "^0.102.0", "slate": "^0.102.0",
"slate-react": "^0.102.0", "slate-react": "^0.102.0",
"sonner": "^1.4.41", "sonner": "^1.4.41",
"string-strip-html": "^13.4.7", "string-strip-html": "^13.4.8",
"uqr": "^0.1.2", "uqr": "^0.1.2",
"use-debounce": "^10.0.0", "use-debounce": "^10.0.0",
"virtua": "^0.29.1" "virtua": "^0.29.2"
}, },
"devDependencies": { "devDependencies": {
"@lume/tailwindcss": "workspace:^", "@lume/tailwindcss": "workspace:^",
"@lume/tsconfig": "workspace:^", "@lume/tsconfig": "workspace:^",
"@lume/types": "workspace:^", "@lume/types": "workspace:^",
"@types/react": "^18.2.74", "@types/react": "^18.2.75",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"typescript": "^5.4.3" "typescript": "^5.4.4"
} }
} }

View File

@ -8,11 +8,11 @@
"access": "public" "access": "public"
}, },
"dependencies": { "dependencies": {
"@tanstack/react-query": "^5.28.14", "@tanstack/react-query": "^5.29.0",
"bitcoin-units": "^1.0.0", "bitcoin-units": "^1.0.0",
"clsx": "^2.1.0", "clsx": "^2.1.0",
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"nostr-tools": "^2.3.2", "nostr-tools": "^2.4.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"slate": "^0.102.0", "slate": "^0.102.0",
@ -21,9 +21,9 @@
"devDependencies": { "devDependencies": {
"@lume/tsconfig": "workspace:^", "@lume/tsconfig": "workspace:^",
"@lume/types": "workspace:^", "@lume/types": "workspace:^",
"@types/react": "^18.2.74", "@types/react": "^18.2.75",
"@types/react-dom": "^18.2.24", "@types/react-dom": "^18.2.24",
"tailwind-merge": "^2.2.2", "tailwind-merge": "^2.2.2",
"typescript": "^5.4.3" "typescript": "^5.4.4"
} }
} }

1051
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

160
src-tauri/Cargo.lock generated
View File

@ -157,9 +157,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.81" version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
[[package]] [[package]]
name = "arboard" name = "arboard"
@ -213,7 +213,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "258b52a1aa741b9f09783b2d86cf0aeeb617bbf847f6933340a39644227acbdb" checksum = "258b52a1aa741b9f09783b2d86cf0aeeb617bbf847f6933340a39644227acbdb"
dependencies = [ dependencies = [
"event-listener 5.2.0", "event-listener 5.3.0",
"event-listener-strategy 0.5.1", "event-listener-strategy 0.5.1",
"futures-core", "futures-core",
"pin-project-lite", "pin-project-lite",
@ -226,7 +226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3"
dependencies = [ dependencies = [
"concurrent-queue", "concurrent-queue",
"event-listener 5.2.0", "event-listener 5.3.0",
"event-listener-strategy 0.5.1", "event-listener-strategy 0.5.1",
"futures-core", "futures-core",
"pin-project-lite", "pin-project-lite",
@ -234,9 +234,9 @@ dependencies = [
[[package]] [[package]]
name = "async-executor" name = "async-executor"
version = "1.9.1" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10b3e585719c2358d2660232671ca8ca4ddb4be4ce8a1842d6c2dc8685303316" checksum = "5f98c37cf288e302c16ef6c8472aad1e034c6c84ce5ea7b8101c98eb4a802fee"
dependencies = [ dependencies = [
"async-lock 3.3.0", "async-lock 3.3.0",
"async-task", "async-task",
@ -358,7 +358,7 @@ dependencies = [
"async-task", "async-task",
"blocking", "blocking",
"cfg-if", "cfg-if",
"event-listener 5.2.0", "event-listener 5.3.0",
"futures-lite 2.3.0", "futures-lite 2.3.0",
"rustix 0.38.32", "rustix 0.38.32",
"tracing", "tracing",
@ -373,7 +373,7 @@ checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -408,7 +408,7 @@ checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -687,9 +687,9 @@ dependencies = [
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.15.4" version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
@ -811,9 +811,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.90" version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41"
dependencies = [ dependencies = [
"jobserver", "jobserver",
"libc", "libc",
@ -1048,9 +1048,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]] [[package]]
name = "core-graphics" name = "core-graphics"
version = "0.23.1" version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"core-foundation", "core-foundation",
@ -1138,7 +1138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -1148,7 +1148,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -1202,7 +1202,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim 0.10.0", "strsim 0.10.0",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -1213,7 +1213,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
dependencies = [ dependencies = [
"darling_core", "darling_core",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -1390,7 +1390,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -1488,7 +1488,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -1543,9 +1543,9 @@ dependencies = [
[[package]] [[package]]
name = "event-listener" name = "event-listener"
version = "5.2.0" version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24"
dependencies = [ dependencies = [
"concurrent-queue", "concurrent-queue",
"parking", "parking",
@ -1568,7 +1568,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3" checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3"
dependencies = [ dependencies = [
"event-listener 5.2.0", "event-listener 5.3.0",
"pin-project-lite", "pin-project-lite",
] ]
@ -1683,7 +1683,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -1801,7 +1801,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -1988,9 +1988,9 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.12" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys", "js-sys",
@ -2121,7 +2121,7 @@ dependencies = [
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -2233,14 +2233,14 @@ dependencies = [
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.3.25" version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
dependencies = [ dependencies = [
"bytes", "bytes",
"fnv", "fnv",
@ -3240,7 +3240,7 @@ dependencies = [
"cbc", "cbc",
"chacha20", "chacha20",
"chacha20poly1305", "chacha20poly1305",
"getrandom 0.2.12", "getrandom 0.2.14",
"instant", "instant",
"js-sys", "js-sys",
"negentropy", "negentropy",
@ -3274,9 +3274,9 @@ dependencies = [
[[package]] [[package]]
name = "nostr-relay-pool" name = "nostr-relay-pool"
version = "0.29.2" version = "0.29.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1b306bc99d49064950a16a06d35c7c19af94d8b4052fad0dfe02e41e529d5d3" checksum = "e8efc437bcf8c433887a9897dfb6f99914170f656a2a66398e737b3050c2aa34"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"async-wsocket", "async-wsocket",
@ -3578,7 +3578,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -3870,7 +3870,7 @@ dependencies = [
"phf_shared 0.11.2", "phf_shared 0.11.2",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -3917,7 +3917,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -4123,9 +4123,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.35" version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -4190,7 +4190,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [ dependencies = [
"getrandom 0.2.12", "getrandom 0.2.14",
] ]
[[package]] [[package]]
@ -4249,7 +4249,7 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
dependencies = [ dependencies = [
"getrandom 0.2.12", "getrandom 0.2.14",
"libredox", "libredox",
"thiserror", "thiserror",
] ]
@ -4322,7 +4322,7 @@ dependencies = [
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
"rustls 0.21.10", "rustls 0.21.10",
"rustls-pemfile", "rustls-pemfile 1.0.4",
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
@ -4344,11 +4344,11 @@ dependencies = [
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.12.2" version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338" checksum = "3e6cc1e89e689536eb5aeede61520e874df5a4707df811cd5da4aa5fbb2aae19"
dependencies = [ dependencies = [
"base64 0.21.7", "base64 0.22.0",
"bytes", "bytes",
"futures-core", "futures-core",
"futures-util", "futures-util",
@ -4366,7 +4366,7 @@ dependencies = [
"once_cell", "once_cell",
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
"rustls-pemfile", "rustls-pemfile 2.1.2",
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
@ -4380,7 +4380,7 @@ dependencies = [
"wasm-bindgen-futures", "wasm-bindgen-futures",
"wasm-streams", "wasm-streams",
"web-sys", "web-sys",
"winreg 0.50.0", "winreg 0.52.0",
] ]
[[package]] [[package]]
@ -4415,7 +4415,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [ dependencies = [
"cc", "cc",
"cfg-if", "cfg-if",
"getrandom 0.2.12", "getrandom 0.2.14",
"libc", "libc",
"spin", "spin",
"untrusted", "untrusted",
@ -4513,6 +4513,16 @@ dependencies = [
"base64 0.21.7", "base64 0.21.7",
] ]
[[package]]
name = "rustls-pemfile"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d"
dependencies = [
"base64 0.22.0",
"rustls-pki-types",
]
[[package]] [[package]]
name = "rustls-pki-types" name = "rustls-pki-types"
version = "1.4.1" version = "1.4.1"
@ -4542,9 +4552,9 @@ dependencies = [
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.14" version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47"
[[package]] [[package]]
name = "ryu" name = "ryu"
@ -4754,7 +4764,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -4782,13 +4792,13 @@ dependencies = [
[[package]] [[package]]
name = "serde_repr" name = "serde_repr"
version = "0.1.18" version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -4839,7 +4849,7 @@ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -5114,9 +5124,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.57" version = "2.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -5250,7 +5260,7 @@ dependencies = [
"dirs-next", "dirs-next",
"embed_plist", "embed_plist",
"futures-util", "futures-util",
"getrandom 0.2.12", "getrandom 0.2.14",
"glob", "glob",
"gtk", "gtk",
"heck 0.4.1", "heck 0.4.1",
@ -5264,7 +5274,7 @@ dependencies = [
"objc", "objc",
"percent-encoding", "percent-encoding",
"raw-window-handle 0.6.0", "raw-window-handle 0.6.0",
"reqwest 0.12.2", "reqwest 0.12.3",
"serde", "serde",
"serde_json", "serde_json",
"serde_repr", "serde_repr",
@ -5327,7 +5337,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sha2", "sha2",
"syn 2.0.57", "syn 2.0.58",
"tauri-utils", "tauri-utils",
"thiserror", "thiserror",
"time", "time",
@ -5345,7 +5355,7 @@ dependencies = [
"heck 0.4.1", "heck 0.4.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
"tauri-codegen", "tauri-codegen",
"tauri-utils", "tauri-utils",
] ]
@ -5760,7 +5770,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -5858,7 +5868,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -6063,7 +6073,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -6107,9 +6117,9 @@ dependencies = [
[[package]] [[package]]
name = "tray-icon" name = "tray-icon"
version = "0.13.1" version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da36482ee1dbcedfddb038b3a0f6d27f04d9470dc99dabfa90b8d7cdc8b5f3d6" checksum = "a97ec55956c54569e74209ae9d29a7a79193b252d17a6ac28bcffd4c11a384ad"
dependencies = [ dependencies = [
"cocoa", "cocoa",
"core-graphics", "core-graphics",
@ -6305,7 +6315,7 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
dependencies = [ dependencies = [
"getrandom 0.2.12", "getrandom 0.2.14",
] ]
[[package]] [[package]]
@ -6410,7 +6420,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -6444,7 +6454,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -6601,7 +6611,7 @@ checksum = "ac1345798ecd8122468840bcdf1b95e5dc6d2206c5e4b0eafa078d061f59c9bc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -6732,7 +6742,7 @@ checksum = "942ac266be9249c84ca862f0a164a39533dc2f6f33dc98ec89c8da99b82ea0bd"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -6743,7 +6753,7 @@ checksum = "da33557140a288fae4e1d5f8873aaf9eb6613a9cf82c3e070223ff177f598b60"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]
@ -7180,7 +7190,7 @@ dependencies = [
"blocking", "blocking",
"derivative", "derivative",
"enumflags2", "enumflags2",
"event-listener 5.2.0", "event-listener 5.3.0",
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"futures-util", "futures-util",
@ -7269,7 +7279,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.57", "syn 2.0.58",
] ]
[[package]] [[package]]

View File

@ -199,33 +199,37 @@ pub async fn set_nstore(
#[tauri::command] #[tauri::command]
pub async fn get_nstore(key: &str, state: State<'_, Nostr>) -> Result<String, String> { pub async fn get_nstore(key: &str, state: State<'_, Nostr>) -> Result<String, String> {
let client = &state.client; let client = &state.client;
let signer = client.signer().await.unwrap();
let public_key = signer.public_key().await;
if let Ok(author) = public_key { if let Ok(signer) = client.signer().await {
let filter = Filter::new() let public_key = signer.public_key().await;
.author(author)
.kind(Kind::ApplicationSpecificData)
.identifier(key)
.limit(1);
let query = client if let Ok(author) = public_key {
.get_events_of(vec![filter], Some(Duration::from_secs(10))) let filter = Filter::new()
.await; .author(author)
.kind(Kind::ApplicationSpecificData)
.identifier(key)
.limit(1);
if let Ok(events) = query { let query = client
if let Some(event) = events.first() { .get_events_of(vec![filter], Some(Duration::from_secs(10)))
println!("get nstore key: {} - received: {}", key, event.id); .await;
Ok(event.content.to_string())
if let Ok(events) = query {
if let Some(event) = events.first() {
println!("get nstore key: {} - received: {}", key, event.id);
Ok(event.content.to_string())
} else {
println!("get nstore key: {}", key);
Err("Value not found".into())
}
} else { } else {
println!("get nstore key: {}", key); Err("Query nstore event failed".into())
Err("Value not found".into())
} }
} else { } else {
Err("Query nstore event failed".into()) Err("Something is wrong".into())
} }
} else { } else {
Err("Something is wrong".into()) Err("Signer is required".into())
} }
} }