diff --git a/apps/desktop2/src/components/balance.tsx b/apps/desktop2/src/components/balance.tsx
index efb846d9..e4cb027e 100644
--- a/apps/desktop2/src/components/balance.tsx
+++ b/apps/desktop2/src/components/balance.tsx
@@ -1,42 +1,42 @@
-import { User } from "./user";
+import { User } from "@/components/user";
import { getBitcoinDisplayValues } from "@lume/utils";
import { useRouteContext } from "@tanstack/react-router";
import { useEffect, useMemo, useState } from "react";
export function Balance({ account }: { account: string }) {
- const { ark } = useRouteContext({ strict: false });
- const [balance, setBalance] = useState(0);
- const value = useMemo(() => getBitcoinDisplayValues(balance), [balance]);
+ const { ark } = useRouteContext({ strict: false });
+ const [balance, setBalance] = useState(0);
+ const value = useMemo(() => getBitcoinDisplayValues(balance), [balance]);
- useEffect(() => {
- async function getBalance() {
- const val = await ark.get_balance();
- setBalance(val);
- }
+ useEffect(() => {
+ async function getBalance() {
+ const val = await ark.get_balance();
+ setBalance(val);
+ }
- getBalance();
- }, []);
+ getBalance();
+ }, []);
- return (
-
-
-
-
- Your balance
-
-
- ₿ {value.bitcoinFormatted}
-
-
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+ Your balance
+
+
+ ₿ {value.bitcoinFormatted}
+
+
+
+
+
+
+
+
+
+ );
}
diff --git a/apps/desktop2/src/components/col.tsx b/apps/desktop2/src/components/col.tsx
deleted file mode 100644
index c6e06b8a..00000000
--- a/apps/desktop2/src/components/col.tsx
+++ /dev/null
@@ -1,160 +0,0 @@
-import { CancelIcon, CheckIcon } from "@lume/icons";
-import type { LumeColumn } from "@lume/types";
-import { cn } from "@lume/utils";
-import { invoke } from "@tauri-apps/api/core";
-import { getCurrent } from "@tauri-apps/api/webviewWindow";
-import { useEffect, useRef, useState } from "react";
-
-export function Col({
- column,
- account,
- isScroll,
- isResize,
-}: {
- column: LumeColumn;
- account: string;
- isScroll: boolean;
- isResize: boolean;
-}) {
- const container = useRef(null);
- const [webview, setWebview] = useState(undefined);
-
- const repositionWebview = async () => {
- if (webview && webview.length > 1) {
- const newRect = container.current.getBoundingClientRect();
- await invoke("reposition_column", {
- label: webview,
- x: newRect.x,
- y: newRect.y,
- });
- }
- };
-
- const resizeWebview = async () => {
- if (webview && webview.length > 1) {
- const newRect = container.current.getBoundingClientRect();
- await invoke("resize_column", {
- label: webview,
- width: newRect.width,
- height: newRect.height,
- });
- }
- };
-
- useEffect(() => {
- resizeWebview();
- }, [isResize]);
-
- useEffect(() => {
- if (isScroll) repositionWebview();
- }, [isScroll]);
-
- useEffect(() => {
- (async () => {
- if (webview && webview.length > 1) return;
-
- const rect = container.current.getBoundingClientRect();
- const windowLabel = `column-${column.label}`;
- const url = `${column.content}?account=${account}&label=${column.label}&name=${column.name}`;
-
- // create new webview
- const label: string = await invoke("create_column", {
- label: windowLabel,
- x: rect.x,
- y: rect.y,
- width: rect.width,
- height: rect.height,
- url,
- });
-
- setWebview(label);
- })();
-
- // close webview when unmounted
- return () => {
- if (webview && webview.length > 1) {
- invoke("close_column", {
- label: webview,
- });
- }
- };
- }, [webview]);
-
- return (
-
-
- {column.label !== "open" ? (
-
- ) : null}
-
-
-
- );
-}
-
-function Header({ label, name }: { label: string; name: string }) {
- const [title, setTitle] = useState(name);
- const [isChanged, setIsChanged] = useState(false);
-
- const saveNewTitle = async () => {
- const mainWindow = getCurrent();
- await mainWindow.emit("columns", { type: "set_title", label, title });
-
- // update search params
- // @ts-ignore, hahaha
- search.name = title;
-
- // reset state
- setIsChanged(false);
- };
-
- const close = async () => {
- const mainWindow = getCurrent();
- await mainWindow.emit("columns", { type: "remove", label });
- };
-
- useEffect(() => {
- if (title.length !== name.length) setIsChanged(true);
- }, [title]);
-
- return (
-
-
-
-
-
setTitle(e.currentTarget.textContent)}
- className="text-sm font-medium focus:outline-none"
- >
- {name}
-
- {isChanged ? (
-
- ) : null}
-
-
-
-
- );
-}
diff --git a/apps/desktop2/src/components/column.tsx b/apps/desktop2/src/components/column.tsx
new file mode 100644
index 00000000..bc7eef47
--- /dev/null
+++ b/apps/desktop2/src/components/column.tsx
@@ -0,0 +1,147 @@
+import { CancelIcon, CheckIcon } from "@lume/icons";
+import type { LumeColumn } from "@lume/types";
+import { cn } from "@lume/utils";
+import { invoke } from "@tauri-apps/api/core";
+import { getCurrent } from "@tauri-apps/api/webviewWindow";
+import { useEffect, useRef, useState } from "react";
+
+export function Column({
+ column,
+ account,
+ isScroll,
+ isResize,
+}: {
+ column: LumeColumn;
+ account: string;
+ isScroll: boolean;
+ isResize: boolean;
+}) {
+ const container = useRef(null);
+ const webviewLabel = `column-${account}_${column.label}`;
+
+ const [isCreated, setIsCreated] = useState(false);
+
+ const repositionWebview = async () => {
+ const newRect = container.current.getBoundingClientRect();
+ await invoke("reposition_column", {
+ label: webviewLabel,
+ x: newRect.x,
+ y: newRect.y,
+ });
+ };
+
+ const resizeWebview = async () => {
+ const newRect = container.current.getBoundingClientRect();
+ await invoke("resize_column", {
+ label: webviewLabel,
+ width: newRect.width,
+ height: newRect.height,
+ });
+ };
+
+ useEffect(() => {
+ if (isCreated) resizeWebview();
+ }, [isResize]);
+
+ useEffect(() => {
+ if (isScroll && isCreated) repositionWebview();
+ }, [isScroll]);
+
+ useEffect(() => {
+ const rect = container.current.getBoundingClientRect();
+ const url = `${column.content}?account=${account}&label=${column.label}&name=${column.name}`;
+
+ // create new webview
+ invoke("create_column", {
+ label: webviewLabel,
+ x: rect.x,
+ y: rect.y,
+ width: rect.width,
+ height: rect.height,
+ url,
+ }).then(() => setIsCreated(true));
+
+ // close webview when unmounted
+ return () => {
+ invoke("close_column", { label: webviewLabel });
+ };
+ }, [account]);
+
+ return (
+
+
+ {column.label !== "open" ? (
+
+ ) : null}
+
+
+
+ );
+}
+
+function Header({ label, name }: { label: string; name: string }) {
+ const [title, setTitle] = useState(name);
+ const [isChanged, setIsChanged] = useState(false);
+
+ const saveNewTitle = async () => {
+ const mainWindow = getCurrent();
+ await mainWindow.emit("columns", { type: "set_title", label, title });
+
+ // update search params
+ // @ts-ignore, hahaha
+ search.name = title;
+
+ // reset state
+ setIsChanged(false);
+ };
+
+ const close = async () => {
+ const mainWindow = getCurrent();
+ await mainWindow.emit("columns", { type: "remove", label });
+ };
+
+ useEffect(() => {
+ if (title.length !== name.length) setIsChanged(true);
+ }, [title]);
+
+ return (
+
+
+
+
+
setTitle(e.currentTarget.textContent)}
+ className="text-sm font-medium focus:outline-none"
+ >
+ {name}
+
+ {isChanged ? (
+
+ ) : null}
+
+
+
+
+ );
+}
diff --git a/apps/desktop2/src/components/conversation.tsx b/apps/desktop2/src/components/conversation.tsx
index d8fbadc6..879cd091 100644
--- a/apps/desktop2/src/components/conversation.tsx
+++ b/apps/desktop2/src/components/conversation.tsx
@@ -1,48 +1,48 @@
import { ThreadIcon } from "@lume/icons";
import type { Event } from "@lume/types";
-import { Note } from "./note";
+import { Note } from "@/components/note";
import { cn } from "@lume/utils";
import { useRouteContext } from "@tanstack/react-router";
export function Conversation({
- event,
- className,
+ event,
+ className,
}: {
- event: Event;
- className?: string;
+ event: Event;
+ className?: string;
}) {
- const { ark } = useRouteContext({ strict: false });
- const thread = ark.parse_event_thread(event.tags);
+ const { ark } = useRouteContext({ strict: false });
+ const thread = ark.parse_event_thread(event.tags);
- return (
-
-
-
- {thread?.root ?
: null}
-
- {thread?.reply ?
: null}
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+ {thread?.root ?
: null}
+
+ {thread?.reply ?
: null}
+
+
+
+
+
+
+
+ );
}
diff --git a/apps/desktop2/src/components/note/index.ts b/apps/desktop2/src/components/note/index.ts
index c52887b0..0112a7e4 100644
--- a/apps/desktop2/src/components/note/index.ts
+++ b/apps/desktop2/src/components/note/index.ts
@@ -12,16 +12,16 @@ import { NoteRoot } from "./root";
import { NoteUser } from "./user";
export const Note = {
- Provider: NoteProvider,
- Root: NoteRoot,
- User: NoteUser,
- Menu: NoteMenu,
- Reply: NoteReply,
- Repost: NoteRepost,
- Content: NoteContent,
- ContentLarge: NoteContentLarge,
- Zap: NoteZap,
- Open: NoteOpenThread,
- Child: NoteChild,
- Activity: NoteActivity,
+ Provider: NoteProvider,
+ Root: NoteRoot,
+ User: NoteUser,
+ Menu: NoteMenu,
+ Reply: NoteReply,
+ Repost: NoteRepost,
+ Content: NoteContent,
+ ContentLarge: NoteContentLarge,
+ Zap: NoteZap,
+ Open: NoteOpenThread,
+ Child: NoteChild,
+ Activity: NoteActivity,
};
diff --git a/apps/desktop2/src/components/notification.tsx b/apps/desktop2/src/components/notification.tsx
index 8b6964d2..7daf6d6b 100644
--- a/apps/desktop2/src/components/notification.tsx
+++ b/apps/desktop2/src/components/notification.tsx
@@ -1,32 +1,32 @@
import type { Event } from "@lume/types";
-import { Note } from "./note";
+import { Note } from "@/components/note";
import { cn } from "@lume/utils";
export function Notification({
- event,
- className,
+ event,
+ className,
}: {
- event: Event;
- className?: string;
+ event: Event;
+ className?: string;
}) {
- return (
-
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+
+ );
}
diff --git a/apps/desktop2/src/components/quote.tsx b/apps/desktop2/src/components/quote.tsx
index 06d738d6..d4a2913e 100644
--- a/apps/desktop2/src/components/quote.tsx
+++ b/apps/desktop2/src/components/quote.tsx
@@ -1,47 +1,47 @@
import { QuoteIcon } from "@lume/icons";
import type { Event } from "@lume/types";
-import { Note } from "./note";
+import { Note } from "@/components/note";
import { cn } from "@lume/utils";
export function Quote({
- event,
- className,
+ event,
+ className,
}: {
- event: Event;
- className?: string;
+ event: Event;
+ className?: string;
}) {
- const quoteEventId = event.tags.find(
- (tag) => tag[0] === "q" || tag[3] === "mention",
- )?.[1];
+ const quoteEventId = event.tags.find(
+ (tag) => tag[0] === "q" || tag[3] === "mention",
+ )?.[1];
- return (
-
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+
+ );
}
diff --git a/apps/desktop2/src/components/repost.tsx b/apps/desktop2/src/components/repost.tsx
index 0ffb9b00..43ee5302 100644
--- a/apps/desktop2/src/components/repost.tsx
+++ b/apps/desktop2/src/components/repost.tsx
@@ -1,85 +1,85 @@
import type { Event } from "@lume/types";
import { Spinner } from "@lume/ui";
-import { Note } from "./note";
-import { User } from "./user";
+import { Note } from "@/components/note";
+import { User } from "@/components/user";
import { cn } from "@lume/utils";
import { useQuery } from "@tanstack/react-query";
import { useRouteContext } from "@tanstack/react-router";
export function RepostNote({
- event,
- className,
+ event,
+ className,
}: {
- event: Event;
- className?: string;
+ event: Event;
+ className?: string;
}) {
- const { ark } = useRouteContext({ strict: false });
- 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 { ark } = useRouteContext({ strict: false });
+ 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];
- const repostEvent = await ark.get_event(id);
+ const id = event.tags.find((el) => el[0] === "e")?.[1];
+ const repostEvent = await ark.get_event(id);
- return repostEvent;
- } catch (e) {
- throw new Error(e);
- }
- },
- refetchOnWindowFocus: false,
- refetchOnMount: false,
- });
+ return repostEvent;
+ } catch (e) {
+ throw new Error(e);
+ }
+ },
+ refetchOnWindowFocus: false,
+ refetchOnMount: false,
+ });
- return (
-
-
-
-
- Reposted by
-
-
-
-
- {isLoading ? (
-
-
- Loading event...
-
- ) : isError || !repostEvent ? (
-
- Event not found within your current relay set
-
- ) : (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
-
- );
+ return (
+
+
+
+
+ Reposted by
+
+
+
+
+ {isLoading ? (
+
+
+ Loading event...
+
+ ) : isError || !repostEvent ? (
+
+ Event not found within your current relay set
+
+ ) : (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ );
}
diff --git a/apps/desktop2/src/components/text.tsx b/apps/desktop2/src/components/text.tsx
index 7ec993d4..8b91b639 100644
--- a/apps/desktop2/src/components/text.tsx
+++ b/apps/desktop2/src/components/text.tsx
@@ -1,34 +1,34 @@
import type { Event } from "@lume/types";
import { cn } from "@lume/utils";
-import { Note } from "./note";
+import { Note } from "@/components/note";
export function TextNote({
- event,
- className,
+ event,
+ className,
}: {
- event: Event;
- className?: string;
+ event: Event;
+ className?: string;
}) {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
}
diff --git a/apps/desktop2/src/routes/$account.home.tsx b/apps/desktop2/src/routes/$account.home.tsx
index c69037e0..fea4fa0d 100644
--- a/apps/desktop2/src/routes/$account.home.tsx
+++ b/apps/desktop2/src/routes/$account.home.tsx
@@ -1,4 +1,4 @@
-import { Col } from "@/components/col";
+import { Column } from "@/components/column";
import { Toolbar } from "@/components/toolbar";
import { ArrowLeftIcon, ArrowRightIcon } from "@lume/icons";
import type { EventColumns, LumeColumn } from "@lume/types";
@@ -13,170 +13,175 @@ import { useDebouncedCallback } from "use-debounce";
import { VList, type VListHandle } from "virtua";
export const Route = createFileRoute("/$account/home")({
- beforeLoad: async ({ context }) => {
- try {
- const ark = context.ark;
- const resourcePath = await resolveResource(
- "resources/system_columns.json",
- );
- const systemColumns: LumeColumn[] = JSON.parse(
- await readTextFile(resourcePath),
- );
- const userColumns = await ark.get_columns();
+ loader: async ({ context }) => {
+ try {
+ const userColumns = await context.ark.get_columns();
+ if (userColumns.length > 0) {
+ return userColumns;
+ } else {
+ const systemPath = "resources/system_columns.json";
+ const resourcePath = await resolveResource(systemPath);
+ const resourceFile = await readTextFile(resourcePath);
+ const systemColumns: LumeColumn[] = JSON.parse(resourceFile);
- return {
- storedColumns: !userColumns.length ? systemColumns : userColumns,
- };
- } catch (e) {
- console.error(String(e));
- }
- },
- component: Screen,
+ return systemColumns;
+ }
+ } catch (e) {
+ console.error(String(e));
+ }
+ },
+ component: Screen,
});
function Screen() {
- const vlistRef = useRef(null);
+ const userSavedColumns = Route.useLoaderData();
+ const vlistRef = useRef(null);
- const { account } = Route.useParams();
- const { ark, storedColumns } = Route.useRouteContext();
+ const { account } = Route.useParams();
+ const { ark } = Route.useRouteContext();
- const [selectedIndex, setSelectedIndex] = useState(-1);
- const [columns, setColumns] = useState(storedColumns);
- const [isScroll, setIsScroll] = useState(false);
- const [isResize, setIsResize] = useState(false);
+ const [selectedIndex, setSelectedIndex] = useState(-1);
+ const [columns, setColumns] = useState([]);
+ const [isScroll, setIsScroll] = useState(false);
+ const [isResize, setIsResize] = useState(false);
- const goLeft = () => {
- const prevIndex = Math.max(selectedIndex - 1, 0);
- setSelectedIndex(prevIndex);
- vlistRef.current.scrollToIndex(prevIndex, {
- align: "center",
- });
- };
+ const goLeft = () => {
+ const prevIndex = Math.max(selectedIndex - 1, 0);
+ setSelectedIndex(prevIndex);
+ vlistRef.current.scrollToIndex(prevIndex, {
+ align: "center",
+ });
+ };
- const goRight = () => {
- const nextIndex = Math.min(selectedIndex + 1, columns.length - 1);
- setSelectedIndex(nextIndex);
- vlistRef.current.scrollToIndex(nextIndex, {
- align: "center",
- });
- };
+ const goRight = () => {
+ const nextIndex = Math.min(selectedIndex + 1, columns.length - 1);
+ setSelectedIndex(nextIndex);
+ vlistRef.current.scrollToIndex(nextIndex, {
+ align: "center",
+ });
+ };
- const add = useDebouncedCallback((column: LumeColumn) => {
- // update col label
- column.label = `${column.label}-${nanoid()}`;
+ const add = useDebouncedCallback((column: LumeColumn) => {
+ // update col label
+ column.label = `${column.label}-${nanoid()}`;
- // create new cols
- const cols = [...columns];
- const openColIndex = cols.findIndex((col) => col.label === "open");
- const newCols = [
- ...cols.slice(0, openColIndex),
- column,
- ...cols.slice(openColIndex),
- ];
+ // create new cols
+ const cols = [...columns];
+ const openColIndex = cols.findIndex((col) => col.label === "open");
+ const newCols = [
+ ...cols.slice(0, openColIndex),
+ column,
+ ...cols.slice(openColIndex),
+ ];
- setColumns(newCols);
- setSelectedIndex(newCols.length);
- setIsScroll(true);
+ setColumns(newCols);
+ setSelectedIndex(newCols.length);
+ setIsScroll(true);
- // scroll to the newest column
- vlistRef.current.scrollToIndex(newCols.length - 1, {
- align: "end",
- });
- }, 150);
+ // scroll to the newest column
+ vlistRef.current.scrollToIndex(newCols.length - 1, {
+ align: "end",
+ });
+ }, 150);
- const remove = useDebouncedCallback((label: string) => {
- const newCols = columns.filter((t) => t.label !== label);
+ const remove = useDebouncedCallback((label: string) => {
+ const newCols = columns.filter((t) => t.label !== label);
- setColumns(newCols);
- setSelectedIndex(newCols.length);
- setIsScroll(true);
+ setColumns(newCols);
+ setSelectedIndex(newCols.length);
+ setIsScroll(true);
- // scroll to the first column
- vlistRef.current.scrollToIndex(newCols.length - 1, {
- align: "start",
- });
- }, 150);
+ // scroll to the first column
+ vlistRef.current.scrollToIndex(newCols.length - 1, {
+ align: "start",
+ });
+ }, 150);
- const updateName = useDebouncedCallback((label: string, title: string) => {
- const currentColIndex = columns.findIndex((col) => col.label === label);
+ const updateName = useDebouncedCallback((label: string, title: string) => {
+ const currentColIndex = columns.findIndex((col) => col.label === label);
- const updatedCol = Object.assign({}, columns[currentColIndex]);
- updatedCol.name = title;
+ const updatedCol = Object.assign({}, columns[currentColIndex]);
+ updatedCol.name = title;
- const newCols = columns.slice();
- newCols[currentColIndex] = updatedCol;
+ const newCols = columns.slice();
+ newCols[currentColIndex] = updatedCol;
- setColumns(newCols);
- }, 150);
+ setColumns(newCols);
+ }, 150);
- const startResize = useDebouncedCallback(
- () => setIsResize((prev) => !prev),
- 150,
- );
+ const startResize = useDebouncedCallback(
+ () => setIsResize((prev) => !prev),
+ 150,
+ );
- useEffect(() => {
- // save state
- ark.set_columns(columns);
- }, [columns]);
+ useEffect(() => {
+ setColumns(userSavedColumns);
+ }, [userSavedColumns]);
- useEffect(() => {
- const unlistenColEvent = listen("columns", (data) => {
- if (data.payload.type === "add") add(data.payload.column);
- if (data.payload.type === "remove") remove(data.payload.label);
- if (data.payload.type === "set_title")
- updateName(data.payload.label, data.payload.title);
- });
+ useEffect(() => {
+ // save state
+ ark.set_columns(columns);
+ }, [columns]);
- const unlistenWindowResize = getCurrent().listen("tauri://resize", () => {
- startResize();
- });
+ useEffect(() => {
+ const unlistenColEvent = listen("columns", (data) => {
+ if (data.payload.type === "add") add(data.payload.column);
+ if (data.payload.type === "remove") remove(data.payload.label);
+ if (data.payload.type === "set_title")
+ updateName(data.payload.label, data.payload.title);
+ });
- return () => {
- unlistenColEvent.then((f) => f());
- unlistenWindowResize.then((f) => f());
- };
- }, []);
+ const unlistenWindowResize = getCurrent().listen("tauri://resize", () => {
+ startResize();
+ });
- return (
-
-
setIsScroll(true)}
- onScrollEnd={() => setIsScroll(false)}
- className="scrollbar-none h-full w-full overflow-x-auto focus:outline-none"
- >
- {columns.map((column) => (
-
- ))}
-
-
-
-
-
-
-
-
- );
+ return () => {
+ unlistenColEvent.then((f) => f());
+ unlistenWindowResize.then((f) => f());
+ };
+ }, []);
+
+ return (
+
+
setIsScroll(true)}
+ onScrollEnd={() => setIsScroll(false)}
+ className="scrollbar-none h-full w-full overflow-x-auto focus:outline-none"
+ cache={null}
+ >
+ {columns.map((column) => (
+
+ ))}
+
+
+
+
+
+
+
+
+ );
}
diff --git a/apps/desktop2/src/routes/$account.tsx b/apps/desktop2/src/routes/$account.tsx
index 04caf33e..4da85563 100644
--- a/apps/desktop2/src/routes/$account.tsx
+++ b/apps/desktop2/src/routes/$account.tsx
@@ -2,177 +2,183 @@ import { BellIcon, ComposeFilledIcon, PlusIcon, SearchIcon } from "@lume/icons";
import { Event, Kind } from "@lume/types";
import { User } from "@/components/user";
import {
- cn,
- decodeZapInvoice,
- displayNpub,
- sendNativeNotification,
+ cn,
+ decodeZapInvoice,
+ displayNpub,
+ sendNativeNotification,
} from "@lume/utils";
import { Outlet, createFileRoute } from "@tanstack/react-router";
import { invoke } from "@tauri-apps/api/core";
import { getCurrent } from "@tauri-apps/api/window";
import { useEffect, useState } from "react";
+import { toast } from "sonner";
export const Route = createFileRoute("/$account")({
- beforeLoad: async ({ context }) => {
- const ark = context.ark;
- const accounts = await ark.get_all_accounts();
+ beforeLoad: async ({ context }) => {
+ const ark = context.ark;
+ const accounts = await ark.get_all_accounts();
- return { accounts };
- },
- component: Screen,
+ return { accounts };
+ },
+ component: Screen,
});
function Screen() {
- const { ark, platform } = Route.useRouteContext();
- const navigate = Route.useNavigate();
+ const { ark, platform } = Route.useRouteContext();
+ const navigate = Route.useNavigate();
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
}
function Accounts() {
- const navigate = Route.useNavigate();
- const { ark, accounts } = Route.useRouteContext();
- const { account } = Route.useParams();
+ const navigate = Route.useNavigate();
+ const { ark, accounts } = Route.useRouteContext();
+ const { account } = Route.useParams();
- const changeAccount = async (npub: string) => {
- if (npub === account) return;
+ const changeAccount = async (npub: string) => {
+ if (npub === account) {
+ return await ark.open_profile(account);
+ }
- const select = await ark.load_selected_account(npub);
+ // change current account and update signer
+ const select = await ark.load_selected_account(npub);
- if (select) {
- return navigate({ to: "/$account/home", params: { account: npub } });
- }
- };
+ if (select) {
+ return navigate({ to: "/$account/home", params: { account: npub } });
+ } else {
+ toast.warning("Something wrong.");
+ }
+ };
- return (
-
- {accounts.map((user) => (
-
- ))}
-
- );
+ return (
+
+ {accounts.map((user) => (
+
+ ))}
+
+ );
}
function Bell() {
- const { ark } = Route.useRouteContext();
- const { account } = Route.useParams();
+ const { ark } = Route.useRouteContext();
+ const { account } = Route.useParams();
- const [count, setCount] = useState(0);
+ const [count, setCount] = useState(0);
- useEffect(() => {
- const unlisten = getCurrent().listen(
- "activity",
- async (payload) => {
- setCount((prevCount) => prevCount + 1);
- await invoke("set_badge", { count });
+ useEffect(() => {
+ const unlisten = getCurrent().listen(
+ "activity",
+ async (payload) => {
+ setCount((prevCount) => prevCount + 1);
+ await invoke("set_badge", { count });
- const event: Event = JSON.parse(payload.payload);
- const user = await ark.get_profile(event.pubkey);
- const userName =
- user.display_name || user.name || displayNpub(event.pubkey, 16);
+ const event: Event = JSON.parse(payload.payload);
+ const user = await ark.get_profile(event.pubkey);
+ const userName =
+ user.display_name || user.name || displayNpub(event.pubkey, 16);
- switch (event.kind) {
- case Kind.Text: {
- sendNativeNotification("Mentioned you in a note", userName);
- break;
- }
- case Kind.Repost: {
- sendNativeNotification("Reposted your note", userName);
- break;
- }
- case Kind.ZapReceipt: {
- const amount = decodeZapInvoice(event.tags);
- sendNativeNotification(
- `Zapped ₿ ${amount.bitcoinFormatted}`,
- userName,
- );
- break;
- }
- default:
- break;
- }
- },
- );
+ switch (event.kind) {
+ case Kind.Text: {
+ sendNativeNotification("Mentioned you in a note", userName);
+ break;
+ }
+ case Kind.Repost: {
+ sendNativeNotification("Reposted your note", userName);
+ break;
+ }
+ case Kind.ZapReceipt: {
+ const amount = decodeZapInvoice(event.tags);
+ sendNativeNotification(
+ `Zapped ₿ ${amount.bitcoinFormatted}`,
+ userName,
+ );
+ break;
+ }
+ default:
+ break;
+ }
+ },
+ );
- return () => {
- unlisten.then((f) => f());
- };
- }, []);
+ return () => {
+ unlisten.then((f) => f());
+ };
+ }, []);
- return (
-
- );
+ return (
+
+ );
}
diff --git a/src-tauri/gen/schemas/capabilities.json b/src-tauri/gen/schemas/capabilities.json
index fb7cfe46..837ce7b6 100644
--- a/src-tauri/gen/schemas/capabilities.json
+++ b/src-tauri/gen/schemas/capabilities.json
@@ -1 +1 @@
-{"desktop-capability":{"identifier":"desktop-capability","description":"Capability for the desktop","local":true,"windows":["main","splash","settings","search","nwc","activity","zap-*","event-*","user-*","editor-*","column-*"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default","notification:allow-is-permission-granted","notification:allow-request-permission","notification:default","os:allow-locale","os:allow-platform","updater:default","updater:allow-check","updater:allow-download-and-install","window:allow-start-dragging","window:allow-create","window:allow-close","window:allow-set-focus","clipboard-manager:allow-write","clipboard-manager:allow-read","webview:allow-create-webview-window","webview:allow-create-webview","webview:allow-set-webview-size","webview:allow-set-webview-position","webview:allow-webview-close","dialog:default","dialog:allow-ask","dialog:allow-message","fs:allow-read-file","shell:allow-open",{"identifier":"http:default","allow":[{"url":"http://**/"},{"url":"https://**/"}]},{"identifier":"fs:allow-read-text-file","allow":[{"path":"$RESOURCE/locales/*"},{"path":"$RESOURCE/resources/*"}]}],"platforms":["linux","macOS","windows"]}}
\ No newline at end of file
+{"desktop-capability":{"identifier":"desktop-capability","description":"Capability for the desktop","local":true,"windows":["main","splash","settings","search","nwc","activity","zap-*","event-*","user-*","editor-*","column-*"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default","notification:allow-is-permission-granted","notification:allow-request-permission","notification:default","os:allow-locale","os:allow-platform","updater:default","updater:allow-check","updater:allow-download-and-install","window:allow-start-dragging","window:allow-create","window:allow-close","window:allow-set-focus","clipboard-manager:allow-write","clipboard-manager:allow-read","webview:allow-create-webview-window","webview:allow-create-webview","webview:allow-set-webview-size","webview:allow-set-webview-position","webview:allow-webview-close","dialog:default","dialog:allow-ask","dialog:allow-message","process:allow-restart","fs:allow-read-file","shell:allow-open",{"identifier":"http:default","allow":[{"url":"http://**/"},{"url":"https://**/"}]},{"identifier":"fs:allow-read-text-file","allow":[{"path":"$RESOURCE/locales/*"},{"path":"$RESOURCE/resources/*"}]}],"platforms":["linux","macOS","windows"]}}
\ No newline at end of file
diff --git a/src-tauri/src/nostr/metadata.rs b/src-tauri/src/nostr/metadata.rs
index fa8c339b..a5102f15 100644
--- a/src-tauri/src/nostr/metadata.rs
+++ b/src-tauri/src/nostr/metadata.rs
@@ -289,7 +289,7 @@ pub async fn unfollow(id: &str, state: State<'_, Nostr>) -> Result {
- println!("set nstore: {}", event_id);
- Ok(event_id)
- }
+ Ok(event_id) => Ok(event_id),
Err(err) => Err(err.to_string()),
}
}
@@ -322,38 +319,29 @@ pub async fn get_nstore(key: &str, state: State<'_, Nostr>) -> Result {
if let Some(event) = events.first() {
- println!("get nstore key: {} - received: {}", key, event.id);
-
let content = event.content();
-
- match signer.nip44_decrypt(author, content).await {
+ match signer.nip44_decrypt(public_key, content).await {
Ok(decrypted) => Ok(decrypted),
Err(_) => Err(event.content.to_string()),
}
} else {
- println!("get nstore key: {}", key);
Err("Value not found".into())
}
- } else {
- Err("Query nstore event failed".into())
}
- } else {
- Err("Something is wrong".into())
+ Err(err) => Err(err.to_string()),
}
} else {
Err("Signer is required".into())