diff --git a/apps/desktop2/src/components/col.tsx b/apps/desktop2/src/components/col.tsx index 535e0096..08855730 100644 --- a/apps/desktop2/src/components/col.tsx +++ b/apps/desktop2/src/components/col.tsx @@ -2,6 +2,7 @@ import { useEffect, useMemo, useRef } from "react"; import { getCurrent } from "@tauri-apps/api/window"; import { LumeColumn } from "@lume/types"; import { invoke } from "@tauri-apps/api/core"; +import { LoaderIcon } from "@lume/icons"; export function Col({ column, @@ -18,10 +19,10 @@ export function Col({ const createWebview = async () => { const rect = container.current.getBoundingClientRect(); - const label = `column-${column.id}`; + const label = `column-${column.label}`; const url = column.content + - `?account=${account}&id=${column.id}&name=${column.name}`; + `?account=${account}&label=${column.label}&name=${column.name}`; // create new webview webview.current = await invoke("create_column", { @@ -71,5 +72,14 @@ export function Col({ }; }, []); - return
; + return ( +
+ +
+ ); } diff --git a/apps/desktop2/src/routes/$account.home.tsx b/apps/desktop2/src/routes/$account.home.tsx index 94a2c569..97042ef5 100644 --- a/apps/desktop2/src/routes/$account.home.tsx +++ b/apps/desktop2/src/routes/$account.home.tsx @@ -4,27 +4,38 @@ import { LoaderIcon } from "@lume/icons"; import { EventColumns, LumeColumn } from "@lume/types"; import { createFileRoute } from "@tanstack/react-router"; import { UnlistenFn } from "@tauri-apps/api/event"; +import { resolveResource } from "@tauri-apps/api/path"; import { getCurrent } from "@tauri-apps/api/window"; +import { readTextFile } from "@tauri-apps/plugin-fs"; import { useEffect, useRef, useState } from "react"; import { VList, VListHandle } from "virtua"; export const Route = createFileRoute("/$account/home")({ component: Screen, pendingComponent: Pending, -}); + beforeLoad: async ({ context }) => { + 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(); -const DEFAULT_COLUMNS: LumeColumn[] = [ - { id: 10001, name: "Newsfeed", content: "/newsfeed" }, - { id: 10000, name: "Open Lume Store", content: "/open" }, -]; + return { + storedColumns: !userColumns.length ? systemColumns : userColumns, + }; + }, +}); function Screen() { const { account } = Route.useParams(); - const vlistRef = useRef(null); + const { ark, storedColumns } = Route.useRouteContext(); - const [columns, setColumns] = useState(DEFAULT_COLUMNS); const [selectedIndex, setSelectedIndex] = useState(-1); const [isScroll, setIsScroll] = useState(false); + const [columns, setColumns] = useState(storedColumns); + + const vlistRef = useRef(null); const goLeft = () => { const prevIndex = Math.max(selectedIndex - 1, 0); @@ -43,41 +54,43 @@ function Screen() { }; const add = (column: LumeColumn) => { - const existed = columns.find((item) => item.id === column.id); + const existed = columns.find((item) => item.label === column.label); if (!existed) { - let lastColIndex: number; - const openColIndex = columns.findIndex((item) => item.id === 10000); - const storeColIndex = columns.findIndex((item) => item.id === 9999); - - if (storeColIndex) { - lastColIndex = storeColIndex; - } else { - lastColIndex = openColIndex; - } - + const lastColIndex = columns.findIndex((item) => item.label === "open"); const newColumns = [ ...columns.slice(0, lastColIndex), column, ...columns.slice(lastColIndex), ]; - // update state & scroll to new column + // update state setColumns(newColumns); setSelectedIndex(newColumns.length - 1); - vlistRef.current.scrollToIndex(newColumns.length - 1, { - align: "center", - }); - } - }; - const remove = (id: number) => { - setColumns((prev) => prev.filter((t) => t.id !== id)); - setSelectedIndex(columns.length); - vlistRef.current.scrollToIndex(columns.length, { + // save state + ark.set_columns(newColumns); + } + + // scroll to new column + vlistRef.current.scrollToIndex(columns.length - 1, { align: "center", }); }; + const remove = (label: string) => { + const newColumns = columns.filter((t) => t.label !== label); + + // update state + setColumns(newColumns); + setSelectedIndex(newColumns.length - 1); + vlistRef.current.scrollToIndex(newColumns.length - 1, { + align: "center", + }); + + // save state + ark.set_columns(newColumns); + }; + useEffect(() => { let unlisten: UnlistenFn = undefined; @@ -86,7 +99,7 @@ function Screen() { if (!unlisten) { unlisten = await mainWindow.listen("columns", (data) => { if (data.payload.type === "add") add(data.payload.column); - if (data.payload.type === "remove") remove(data.payload.id); + if (data.payload.type === "remove") remove(data.payload.label); }); } }; @@ -98,7 +111,7 @@ function Screen() { return () => { if (unlisten) { unlisten(); - unlisten = null; + unlisten = undefined; } }; }, []); @@ -137,7 +150,7 @@ function Screen() { > {columns.map((column) => ( { - const ark = context.ark; - const settings = await ark.get_settings(params.account); - const interests = await ark.get_interest(params.account); - - return { - settings, - interests, - }; - }, }); function App() { diff --git a/apps/desktop2/src/routes/auth/settings.lazy.tsx b/apps/desktop2/src/routes/auth/settings.lazy.tsx index 3e612c6c..baefe8bf 100644 --- a/apps/desktop2/src/routes/auth/settings.lazy.tsx +++ b/apps/desktop2/src/routes/auth/settings.lazy.tsx @@ -17,7 +17,6 @@ export const Route = createLazyFileRoute("/auth/settings")({ function Screen() { const navigate = useNavigate(); - // @ts-ignore, magic!!! const { account } = Route.useSearch(); const { t } = useTranslation(); const { ark } = Route.useRouteContext(); @@ -64,7 +63,7 @@ function Screen() { useEffect(() => { async function loadSettings() { const permissionGranted = await isPermissionGranted(); // get notification permission - const settings = await ark.get_settings(account); + const settings = await ark.get_settings(); setSettings({ ...settings, notification: permissionGranted }); } @@ -146,7 +145,7 @@ function Screen() { diff --git a/apps/desktop2/src/routes/editor/index.tsx b/apps/desktop2/src/routes/editor/index.tsx index 955cae6c..97d6105d 100644 --- a/apps/desktop2/src/routes/editor/index.tsx +++ b/apps/desktop2/src/routes/editor/index.tsx @@ -275,8 +275,13 @@ function Screen() { function Pending() { return ( -
- +
+

Loading cache...

); diff --git a/apps/desktop2/src/routes/foryou.tsx b/apps/desktop2/src/routes/foryou.tsx index 7f249ab2..9e7cff13 100644 --- a/apps/desktop2/src/routes/foryou.tsx +++ b/apps/desktop2/src/routes/foryou.tsx @@ -2,7 +2,7 @@ import { RepostNote } from "@/components/repost"; import { Suggest } from "@/components/suggest"; import { TextNote } from "@/components/text"; import { LoaderIcon, ArrowRightCircleIcon, InfoIcon } from "@lume/icons"; -import { Event, Kind } from "@lume/types"; +import { ColumnRouteSearch, Event, Kind } from "@lume/types"; import { Column } from "@lume/ui"; import { useInfiniteQuery } from "@tanstack/react-query"; import { createFileRoute, redirect } from "@tanstack/react-router"; @@ -10,10 +10,16 @@ import { useTranslation } from "react-i18next"; import { Virtualizer } from "virtua"; export const Route = createFileRoute("/foryou")({ + validateSearch: (search: Record): ColumnRouteSearch => { + return { + account: search.account, + label: search.label, + name: search.name, + }; + }, beforeLoad: async ({ search, context }) => { const ark = context.ark; - // @ts-ignore, useless !!! - const interests = await ark.get_interest(search.account); + const interests = await ark.get_interest(); if (!interests) { throw redirect({ @@ -31,13 +37,12 @@ export const Route = createFileRoute("/foryou")({ }); export function Screen() { - // @ts-ignore, just work!!! - const { id, name, account } = Route.useSearch(); + const { label, name, account } = Route.useSearch(); const { ark, interests } = Route.useRouteContext(); const { t } = useTranslation(); const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } = useInfiniteQuery({ - queryKey: ["foryou", account], + queryKey: [name, account], initialPageParam: 0, queryFn: async ({ pageParam }: { pageParam: number }) => { const events = await ark.get_events_from_interests( @@ -68,7 +73,7 @@ export function Screen() { return ( - + {isLoading ? (
diff --git a/apps/desktop2/src/routes/group.create.tsx b/apps/desktop2/src/routes/group.create.tsx new file mode 100644 index 00000000..ca36dbd2 --- /dev/null +++ b/apps/desktop2/src/routes/group.create.tsx @@ -0,0 +1,5 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/group/create')({ + component: () =>
Hello /group/create!
+}) \ No newline at end of file diff --git a/apps/desktop2/src/routes/group.lazy.tsx b/apps/desktop2/src/routes/group.tsx similarity index 64% rename from apps/desktop2/src/routes/group.lazy.tsx rename to apps/desktop2/src/routes/group.tsx index 5178ccd0..1bbf4dd8 100644 --- a/apps/desktop2/src/routes/group.lazy.tsx +++ b/apps/desktop2/src/routes/group.tsx @@ -1,30 +1,52 @@ import { RepostNote } from "@/components/repost"; import { Suggest } from "@/components/suggest"; import { TextNote } from "@/components/text"; -import { useEvents } from "@lume/ark"; import { LoaderIcon, ArrowRightCircleIcon, InfoIcon } from "@lume/icons"; -import { Event, Kind } from "@lume/types"; +import { ColumnRouteSearch, Event, Kind } from "@lume/types"; import { Column } from "@lume/ui"; -import { createLazyFileRoute } from "@tanstack/react-router"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { createFileRoute, redirect } from "@tanstack/react-router"; import { useTranslation } from "react-i18next"; import { Virtualizer } from "virtua"; -export const Route = createLazyFileRoute("/group")({ +export const Route = createFileRoute("/group")({ component: Screen, + validateSearch: (search: Record): ColumnRouteSearch => { + return { + account: search.account, + label: search.label, + name: search.name, + }; + }, + beforeLoad: async ({ context }) => { + const ark = context.ark; + if (!ark) { + throw redirect({ + to: "/group/create", + }); + } + }, }); export function Screen() { - // @ts-ignore, just work!!! - const { id, name, account } = Route.useSearch(); + const { label, name, account } = Route.useSearch(); + const { ark } = Route.useRouteContext(); const { t } = useTranslation(); - const { - data, - hasNextPage, - isLoading, - isRefetching, - isFetchingNextPage, - fetchNextPage, - } = useEvents("local", account); + const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } = + useInfiniteQuery({ + queryKey: [name, account], + initialPageParam: 0, + queryFn: async ({ pageParam }: { pageParam: number }) => { + const events = await ark.get_events(20, pageParam); + return events; + }, + getNextPageParam: (lastPage) => { + const lastEvent = lastPage?.at(-1); + return lastEvent ? lastEvent.created_at - 1 : null; + }, + select: (data) => data?.pages.flatMap((page) => page), + refetchOnWindowFocus: false, + }); const renderItem = (event: Event) => { if (!event) return; @@ -38,9 +60,9 @@ export function Screen() { return ( - + - {isLoading || isRefetching ? ( + {isLoading ? (
diff --git a/apps/desktop2/src/routes/interests.lazy.tsx b/apps/desktop2/src/routes/interests.tsx similarity index 88% rename from apps/desktop2/src/routes/interests.lazy.tsx rename to apps/desktop2/src/routes/interests.tsx index 2289eeb8..64988414 100644 --- a/apps/desktop2/src/routes/interests.lazy.tsx +++ b/apps/desktop2/src/routes/interests.tsx @@ -1,23 +1,30 @@ +import { ColumnRouteSearch } from "@lume/types"; import { Column } from "@lume/ui"; import { TOPICS, cn } from "@lume/utils"; -import { createLazyFileRoute } from "@tanstack/react-router"; +import { createFileRoute } from "@tanstack/react-router"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; -export const Route = createLazyFileRoute("/interests")({ +export const Route = createFileRoute("/interests")({ component: Screen, + validateSearch: (search: Record): ColumnRouteSearch => { + return { + account: search.account, + label: search.label, + name: search.name, + }; + }, }); function Screen() { const { t } = useTranslation(); + const { label, name } = Route.useSearch(); + const { ark } = Route.useRouteContext(); const [hashtags, setHashtags] = useState([]); const [isDone, setIsDone] = useState(false); - const context = Route.useRouteContext(); - const search = Route.useSearch(); - const toggleHashtag = (item: string) => { const arr = hashtags.includes(item) ? hashtags.filter((i) => i !== item) @@ -36,9 +43,7 @@ function Screen() { return history.back(); } - const ark = context.ark; const eventId = await ark.set_interest(undefined, undefined, hashtags); - if (eventId) { setIsDone(true); toast.success("Interest has been updated successfully."); @@ -50,7 +55,7 @@ function Screen() { return ( - +
diff --git a/apps/desktop2/src/routes/landing/index.tsx b/apps/desktop2/src/routes/landing/index.tsx index c5689746..7fbcf6f2 100644 --- a/apps/desktop2/src/routes/landing/index.tsx +++ b/apps/desktop2/src/routes/landing/index.tsx @@ -8,7 +8,6 @@ export const Route = createFileRoute("/landing/")({ function Screen() { const { t } = useTranslation(); - const context = Route.useRouteContext(); return (
diff --git a/apps/desktop2/src/routes/newsfeed.lazy.tsx b/apps/desktop2/src/routes/newsfeed.tsx similarity index 83% rename from apps/desktop2/src/routes/newsfeed.lazy.tsx rename to apps/desktop2/src/routes/newsfeed.tsx index 7aba3594..15345211 100644 --- a/apps/desktop2/src/routes/newsfeed.lazy.tsx +++ b/apps/desktop2/src/routes/newsfeed.tsx @@ -2,25 +2,39 @@ import { RepostNote } from "@/components/repost"; import { Suggest } from "@/components/suggest"; import { TextNote } from "@/components/text"; import { LoaderIcon, ArrowRightCircleIcon, InfoIcon } from "@lume/icons"; -import { Event, Kind } from "@lume/types"; +import { ColumnRouteSearch, Event, Kind } from "@lume/types"; import { Column } from "@lume/ui"; import { useInfiniteQuery } from "@tanstack/react-query"; -import { createLazyFileRoute } from "@tanstack/react-router"; +import { createFileRoute } from "@tanstack/react-router"; import { useTranslation } from "react-i18next"; import { Virtualizer } from "virtua"; -export const Route = createLazyFileRoute("/newsfeed")({ +export const Route = createFileRoute("/newsfeed")({ component: Screen, + validateSearch: (search: Record): ColumnRouteSearch => { + return { + account: search.account, + label: search.label, + name: search.name, + }; + }, + beforeLoad: async ({ context }) => { + const ark = context.ark; + const settings = await ark.get_settings(); + + return { + settings, + }; + }, }); export function Screen() { - // @ts-ignore, just work!!! - const { id, name, account } = Route.useSearch(); + const { label, name, account } = Route.useSearch(); const { ark } = Route.useRouteContext(); const { t } = useTranslation(); const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } = useInfiniteQuery({ - queryKey: ["local", account], + queryKey: [name, account], initialPageParam: 0, queryFn: async ({ pageParam }: { pageParam: number }) => { const events = await ark.get_events(20, pageParam); @@ -46,7 +60,7 @@ export function Screen() { return ( - + {isLoading ? (
diff --git a/apps/desktop2/src/routes/open.lazy.tsx b/apps/desktop2/src/routes/open.lazy.tsx index 51ea076c..5eac8dfe 100644 --- a/apps/desktop2/src/routes/open.lazy.tsx +++ b/apps/desktop2/src/routes/open.lazy.tsx @@ -22,8 +22,8 @@ function Screen() { type="button" onClick={() => install({ - id: 9999, - name: "Lume Store", + label: "store", + name: "Store", content: "/store/official", }) } @@ -36,8 +36,8 @@ function Screen() { type="button" onClick={() => install({ - id: 9999, - name: "Lume Store", + label: "store", + name: "Store", content: "/store/official", }) } diff --git a/apps/desktop2/src/routes/store.official.tsx b/apps/desktop2/src/routes/store.official.tsx index 881a4bd7..2f6d093f 100644 --- a/apps/desktop2/src/routes/store.official.tsx +++ b/apps/desktop2/src/routes/store.official.tsx @@ -1,68 +1,27 @@ import { LumeColumn } from "@lume/types"; import { createFileRoute } from "@tanstack/react-router"; +import { resolveResource } from "@tauri-apps/api/path"; import { getCurrent } from "@tauri-apps/api/window"; +import { readTextFile } from "@tauri-apps/plugin-fs"; export const Route = createFileRoute("/store/official")({ component: Screen, - loader: () => { - const columns: LumeColumn[] = [ - { - id: 10002, - name: "For you", - content: "/foryou", - logo: "", - cover: "/foryou.png", - coverRetina: "/foryou@2x.png", - author: "Lume", - description: "Keep up to date with content based on your interests.", - }, - { - id: 10003, - name: "Group Feeds", - content: "/group", - logo: "", - cover: "/group.png", - coverRetina: "/group@2x.png", - author: "Lume", - description: "Collective of people you're interested in.", - }, - { - id: 10004, - name: "Antenas", - content: "/antenas", - logo: "", - cover: "/antenas.png", - coverRetina: "/antenas@2x.png", - author: "Lume", - description: "Keep track to specific content.", - }, - { - id: 10005, - name: "Trending", - content: "/trending", - logo: "", - cover: "/trending.png", - coverRetina: "/trending@2x.png", - author: "Lume", - description: "What is trending on Nostr?.", - }, - { - id: 10006, - name: "Global", - content: "/global", - logo: "", - cover: "/global.png", - coverRetina: "/global@2x.png", - author: "Lume", - description: "All events from connected relays.", - }, - ]; - return columns; + beforeLoad: async () => { + const resourcePath = await resolveResource( + "resources/official_columns.json", + ); + const officialColumns: LumeColumn[] = JSON.parse( + await readTextFile(resourcePath), + ); + + return { + officialColumns, + }; }, }); function Screen() { - const data = Route.useLoaderData(); + const { officialColumns } = Route.useRouteContext(); const install = async (column: LumeColumn) => { const mainWindow = getCurrent(); @@ -71,9 +30,9 @@ function Screen() { return (
- {data.map((column) => ( + {officialColumns.map((column) => (
{column.cover ? ( diff --git a/apps/desktop2/src/routes/store.tsx b/apps/desktop2/src/routes/store.tsx index 905e9a7a..46d98bd7 100644 --- a/apps/desktop2/src/routes/store.tsx +++ b/apps/desktop2/src/routes/store.tsx @@ -1,63 +1,61 @@ -import { CancelIcon, GlobalIcon, LaurelIcon } from "@lume/icons"; +import { GlobalIcon, LaurelIcon } from "@lume/icons"; +import { ColumnRouteSearch } from "@lume/types"; import { Column } from "@lume/ui"; import { cn } from "@lume/utils"; import { Link } from "@tanstack/react-router"; import { Outlet, createFileRoute } from "@tanstack/react-router"; -import { getCurrent } from "@tauri-apps/api/window"; export const Route = createFileRoute("/store")({ component: Screen, + validateSearch: (search: Record): ColumnRouteSearch => { + return { + account: search.account, + label: search.label, + name: search.name, + }; + }, }); function Screen() { - // @ts-ignore, just work!!! - const { id } = Route.useSearch(); - - const close = async () => { - const mainWindow = getCurrent(); - await mainWindow.emit("columns", { type: "remove", id }); - }; + const { label, name } = Route.useSearch(); return ( - -
-
- - {({ isActive }) => ( -
- - Official -
- )} - - - {({ isActive }) => ( -
- - Community -
- )} - -
- + +
+ + {({ isActive }) => ( +
+ + Official +
+ )} + + + {({ isActive }) => ( +
+ + Community +
+ )} +
+
+ diff --git a/packages/ark/src/ark.ts b/packages/ark/src/ark.ts index b392bcdf..592f517f 100644 --- a/packages/ark/src/ark.ts +++ b/packages/ark/src/ark.ts @@ -6,6 +6,7 @@ import type { EventWithReplies, Interests, Keys, + LumeColumn, Metadata, Settings, } from "@lume/types"; @@ -14,6 +15,13 @@ import { open } from "@tauri-apps/plugin-dialog"; import { readFile } from "@tauri-apps/plugin-fs"; import { generateContentTags } from "@lume/utils"; +enum NSTORE_KEYS { + settings = "lume_user_settings", + interests = "lume_user_interests", + columns = "lume_user_columns", + group = "lume_group_", +} + export class Ark { public windows: WebviewWindow[]; @@ -565,13 +573,36 @@ export class Ark { } } - public async get_settings(id: string) { + public async get_columns() { try { - const cmd: string = await invoke("get_settings", { id }); - if (!cmd) return null; - if (!cmd.length) return null; + const cmd: string = await invoke("get_nstore", { + key: NSTORE_KEYS.columns, + }); + const columns: LumeColumn[] = cmd ? JSON.parse(cmd) : []; + return columns; + } catch { + return []; + } + } - const settings: Settings = JSON.parse(cmd); + public async set_columns(columns: LumeColumn[]) { + try { + const cmd: string = await invoke("set_nstore", { + key: NSTORE_KEYS.columns, + content: JSON.stringify(columns), + }); + return cmd; + } catch (e) { + throw new Error(e); + } + } + + public async get_settings() { + try { + const cmd: string = await invoke("get_nstore", { + key: NSTORE_KEYS.settings, + }); + const settings: Settings = cmd ? JSON.parse(cmd) : null; return settings; } catch { const defaultSettings: Settings = { @@ -585,7 +616,8 @@ export class Ark { public async set_settings(settings: Settings) { try { - const cmd: string = await invoke("set_settings", { + const cmd: string = await invoke("set_nstore", { + key: NSTORE_KEYS.settings, content: JSON.stringify(settings), }); return cmd; @@ -594,13 +626,12 @@ export class Ark { } } - public async get_interest(id: string) { + public async get_interest() { try { - const cmd: string = await invoke("get_interest", { id }); - if (!cmd) return null; - if (!cmd.length) return null; - - const interests: Interests = JSON.parse(cmd); + const cmd: string = await invoke("get_nstore", { + key: NSTORE_KEYS.interests, + }); + const interests: Interests = cmd ? JSON.parse(cmd) : null; return interests; } catch { return null; @@ -618,7 +649,8 @@ export class Ark { users: users ?? [], hashtags: hashtags ?? [], }; - const cmd: string = await invoke("set_interest", { + const cmd: string = await invoke("set_nstore", { + key: NSTORE_KEYS.interests, content: JSON.stringify(interests), }); return cmd; diff --git a/packages/icons/src/refresh.tsx b/packages/icons/src/refresh.tsx index 1bf56169..02a482a8 100644 --- a/packages/icons/src/refresh.tsx +++ b/packages/icons/src/refresh.tsx @@ -1,18 +1,17 @@ -export function RefreshIcon(props: JSX.IntrinsicElements['svg']) { +export function RefreshIcon(props: JSX.IntrinsicElements["svg"]) { return ( - - + + + ); } diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts index 012aa982..4dcbaead 100644 --- a/packages/types/index.d.ts +++ b/packages/types/index.d.ts @@ -75,8 +75,14 @@ export interface RichContent { notes: string[]; } +export interface ColumnRouteSearch { + account: string; + label: string; + name: string; +} + export interface LumeColumn { - id: number; + label: string; name: string; content: URL | string; description?: string; @@ -89,7 +95,7 @@ export interface LumeColumn { export interface EventColumns { type: "add" | "remove" | "update" | "left" | "right"; - id?: number; + label?: string; column?: LumeColumn; } diff --git a/packages/ui/src/column/header.tsx b/packages/ui/src/column/header.tsx index c3e48e45..3977e51e 100644 --- a/packages/ui/src/column/header.tsx +++ b/packages/ui/src/column/header.tsx @@ -1,16 +1,18 @@ -import { ChevronDownIcon, RefreshIcon, TrashIcon } from "@lume/icons"; +import { CancelIcon, RefreshIcon } from "@lume/icons"; import { cn } from "@lume/utils"; -import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import { getCurrent } from "@tauri-apps/api/window"; +import { ReactNode } from "react"; export function ColumnHeader({ - id, + label, name, className, + children, }: { - id: number; + label: string; name: string; className?: string; + children?: ReactNode; }) { const reload = () => { window.location.reload(); @@ -18,46 +20,37 @@ export function ColumnHeader({ const close = async () => { const mainWindow = getCurrent(); - await mainWindow.emit("columns", { type: "remove", id }); + await mainWindow.emit("columns", { type: "remove", label }); }; return ( - -
- - - -
- - + {!children ? ( +
{name}
+ ) : ( + children + )} +
+ + +
+
); } diff --git a/packages/ui/src/column/root.tsx b/packages/ui/src/column/root.tsx index dcc46107..41e554ea 100644 --- a/packages/ui/src/column/root.tsx +++ b/packages/ui/src/column/root.tsx @@ -3,20 +3,20 @@ import { ReactNode } from "react"; export function ColumnRoot({ children, - shadow = true, - background = true, className, + background = true, + shadow = true, }: { children: ReactNode; - shadow?: boolean; - background?: boolean; className?: string; + background?: boolean; + shadow?: boolean; }) { return (
) -> Result) -> Result { +pub async fn set_nstore( + key: &str, + content: &str, + state: State<'_, Nostr>, +) -> Result { let client = &state.client; - let tag = Tag::Identifier("lume_user_interest".into()); + let tag = Tag::Identifier(key.into()); let builder = EventBuilder::new(Kind::ApplicationSpecificData, content, vec![tag]); if let Ok(event_id) = client.send_event_builder(builder).await { + println!("set nstore: {}", event_id); Ok(event_id) } else { - Err("Set interest failed".into()) + Err("Event has been published failled".into()) } } #[tauri::command] -pub async fn get_interest(id: &str, state: State<'_, Nostr>) -> Result { +pub async fn get_nstore(key: &str, state: State<'_, Nostr>) -> Result { let client = &state.client; - let public_key: Option = match Nip19::from_bech32(id) { - Ok(val) => match val { - Nip19::Pubkey(pubkey) => Some(pubkey), - Nip19::Profile(profile) => Some(profile.public_key), - _ => None, - }, - Err(_) => match PublicKey::from_str(id) { - Ok(val) => Some(val), - Err(_) => None, - }, - }; + let signer = client.signer().await.unwrap(); + let public_key = signer.public_key().await; - if let Some(author) = public_key { + if let Ok(author) = public_key { let filter = Filter::new() .author(author) .kind(Kind::ApplicationSpecificData) - .identifier("lume_user_interest") + .identifier(key) .limit(1); let query = client @@ -219,68 +215,17 @@ pub async fn get_interest(id: &str, state: State<'_, Nostr>) -> Result) -> Result { - let client = &state.client; - let tag = Tag::Identifier("lume_user_settings".into()); - let builder = EventBuilder::new(Kind::ApplicationSpecificData, content, vec![tag]); - - if let Ok(event_id) = client.send_event_builder(builder).await { - Ok(event_id) - } else { - Err("Set settings failed".into()) - } -} - -#[tauri::command] -pub async fn get_settings(id: &str, state: State<'_, Nostr>) -> Result { - let client = &state.client; - let public_key: Option = match Nip19::from_bech32(id) { - Ok(val) => match val { - Nip19::Pubkey(pubkey) => Some(pubkey), - Nip19::Profile(profile) => Some(profile.public_key), - _ => None, - }, - Err(_) => match PublicKey::from_str(id) { - Ok(val) => Some(val), - Err(_) => None, - }, - }; - - if let Some(author) = public_key { - let filter = Filter::new() - .author(author) - .kind(Kind::ApplicationSpecificData) - .identifier("lume_user_settings") - .limit(1); - - let query = client - .get_events_of(vec![filter], Some(Duration::from_secs(10))) - .await; - - if let Ok(events) = query { - if let Some(event) = events.first() { - Ok(event.content.to_string()) - } else { - Err("User settings not found".into()) - } - } else { - Err("User settings not found".into()) - } - } else { - Err("Get settings failed".into()) + Err("Something is wrong".into()) } } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 524ddfb8..8a67f2d9 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -44,7 +44,7 @@ "targets": "all", "active": true, "category": "SocialNetworking", - "resources": ["resources/*", "./locales/*"], + "resources": ["resources/*", "locales/*"], "icon": [ "icons/32x32.png", "icons/128x128.png",