diff --git a/apps/desktop/src/routes/auth/create.tsx b/apps/desktop/src/routes/auth/create.tsx index 2da7ec88..1d0e6a72 100644 --- a/apps/desktop/src/routes/auth/create.tsx +++ b/apps/desktop/src/routes/auth/create.tsx @@ -75,6 +75,11 @@ export function CreateAccountScreen() { ); } // else { user cancel action } + await storage.createAccount({ + pubkey: pubkey, + privkey: signer.privateKey, + }); + return navigate("/auth/onboarding"); }; @@ -129,9 +134,9 @@ export function CreateAccountScreen() { return toast.error("Failed to create new account, try again later"); } + await storage.createSetting("nsecbunker", "1"); await storage.createAccount({ - id: localUser.npub, - pubkey: localUser.pubkey, + pubkey: account, privkey: localSigner.privateKey, }); diff --git a/apps/desktop/src/routes/auth/onboarding.tsx b/apps/desktop/src/routes/auth/onboarding.tsx index ed48230e..09fb4863 100644 --- a/apps/desktop/src/routes/auth/onboarding.tsx +++ b/apps/desktop/src/routes/auth/onboarding.tsx @@ -6,22 +6,15 @@ import { requestPermission, } from "@tauri-apps/plugin-notification"; import { useEffect, useState } from "react"; -import { useNavigate } from "react-router-dom"; +import { Link } from "react-router-dom"; export function OnboardingScreen() { const storage = useStorage(); - const navigate = useNavigate(); - const [settings, setSettings] = useState({ autoupdate: false, notification: false, }); - const next = () => { - if (!storage.account.contacts.length) return navigate("/auth/follow"); - return navigate("/auth/finish"); - }; - const toggleAutoupdate = async () => { await storage.createSetting("autoupdate", String(+!settings.autoupdate)); // update state @@ -107,13 +100,12 @@ export function OnboardingScreen() { "Settings" screen. Be sure to visit it later.

- + diff --git a/packages/ark/src/provider.tsx b/packages/ark/src/provider.tsx index 09112ff3..905ee274 100644 --- a/packages/ark/src/provider.tsx +++ b/packages/ark/src/provider.tsx @@ -51,7 +51,7 @@ const LumeProvider = ({ children }: PropsWithChildren) => { // NIP-46 Signer if (nsecbunker) { const localSignerPrivkey = await storage.loadPrivkey( - `${storage.account.id}-nsecbunker`, + storage.account.pubkey, ); if (!localSignerPrivkey) return null; @@ -63,7 +63,7 @@ const LumeProvider = ({ children }: PropsWithChildren) => { "wss://nostr.vulpem.com/", ]), }); - await bunker.connect(3000); + await bunker.connect(2000); const remoteSigner = new NDKNip46Signer( bunker, @@ -91,7 +91,7 @@ const LumeProvider = ({ children }: PropsWithChildren) => { async function init() { const platformName = await platform(); - const sqliteAdapter = await Database.load("sqlite:lume_v2.db"); + const sqliteAdapter = await Database.load("sqlite:lume_v3.db"); const storage = new LumeStorage(sqliteAdapter, platformName); await storage.init(); diff --git a/packages/lume-column-antenas/src/event.tsx b/packages/lume-column-antenas/src/event.tsx deleted file mode 100644 index 28ebae62..00000000 --- a/packages/lume-column-antenas/src/event.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { ThreadNote } from "@lume/ark"; -import { ArrowLeftIcon } from "@lume/icons"; -import { ReplyList } from "@lume/ui"; -import { useNavigate, useParams } from "react-router-dom"; -import { WVList } from "virtua"; - -export function EventRoute() { - const { id } = useParams(); - const navigate = useNavigate(); - - return ( - -
- -
-
- - -
-
- ); -} diff --git a/packages/lume-column-antenas/src/index.tsx b/packages/lume-column-antenas/src/index.tsx index 3bd36305..daf51748 100644 --- a/packages/lume-column-antenas/src/index.tsx +++ b/packages/lume-column-antenas/src/index.tsx @@ -2,9 +2,8 @@ import { Column } from "@lume/ark"; import { GroupFeedsIcon } from "@lume/icons"; import { IColumn } from "@lume/types"; import { AntenasForm } from "./components/form"; -import { EventRoute } from "./event"; import { HomeRoute } from "./home"; -import { UserRoute } from "./user"; +import { EventRoute, UserRoute } from "@lume/ui"; export function Antenas({ column }: { column: IColumn }) { const colKey = `antenas-${column.id}`; diff --git a/packages/lume-column-antenas/src/user.tsx b/packages/lume-column-antenas/src/user.tsx deleted file mode 100644 index 8d46f957..00000000 --- a/packages/lume-column-antenas/src/user.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import { - RepostNote, - TextNote, - useArk, - useProfile, - useStorage, -} from "@lume/ark"; -import { ArrowLeftIcon, ArrowRightCircleIcon, LoaderIcon } from "@lume/icons"; -import { NIP05 } from "@lume/ui"; -import { FETCH_LIMIT, displayNpub } from "@lume/utils"; -import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; -import { useInfiniteQuery } from "@tanstack/react-query"; -import { useEffect, useMemo, useState } from "react"; -import { Link, useNavigate, useParams } from "react-router-dom"; -import { toast } from "sonner"; -import { WVList } from "virtua"; - -export function UserRoute() { - const ark = useArk(); - const storage = useStorage(); - const navigate = useNavigate(); - - const { id } = useParams(); - const { user } = useProfile(id); - const { data, hasNextPage, isLoading, isFetchingNextPage, fetchNextPage } = - useInfiniteQuery({ - queryKey: ["user-posts", id], - initialPageParam: 0, - queryFn: async ({ - signal, - pageParam, - }: { - signal: AbortSignal; - pageParam: number; - }) => { - const events = await ark.getInfiniteEvents({ - filter: { - kinds: [NDKKind.Text, NDKKind.Repost], - authors: [id], - }, - limit: FETCH_LIMIT, - pageParam, - signal, - }); - - return events; - }, - getNextPageParam: (lastPage) => { - const lastEvent = lastPage.at(-1); - if (!lastEvent) return; - return lastEvent.created_at - 1; - }, - refetchOnWindowFocus: false, - }); - - const [followed, setFollowed] = useState(false); - - const allEvents = useMemo( - () => (data ? data.pages.flatMap((page) => page) : []), - [data], - ); - - const follow = async (pubkey: string) => { - try { - const add = await ark.createContact({ pubkey }); - if (add) { - setFollowed(true); - } else { - toast.success("You already follow this user"); - } - } catch (error) { - console.log(error); - } - }; - - const unfollow = async (pubkey: string) => { - try { - const remove = await ark.deleteContact({ pubkey }); - if (remove) { - setFollowed(false); - } - } catch (error) { - console.log(error); - } - }; - - const renderItem = (event: NDKEvent) => { - switch (event.kind) { - case NDKKind.Text: - return ; - case NDKKind.Repost: - return ; - default: - return ; - } - }; - - useEffect(() => { - if (storage.account.contacts.includes(id)) { - setFollowed(true); - } - }, []); - - return ( - -
- -
-
-
-
- {id} -
- {followed ? ( - - ) : ( - - )} - - Message - -
-
-
-
-
- {user?.name || - user?.display_name || - user?.displayName || - "Anon"} -
- {user?.nip05 ? ( - - ) : ( - - {displayNpub(id, 16)} - - )} -
-
- {user?.about} -
-
-
-
-

- Latest posts -

-
- {isLoading ? ( -
- -
- ) : ( - allEvents.map((item) => renderItem(item)) - )} -
- {hasNextPage ? ( - - ) : null} -
-
-
-
-
- ); -} diff --git a/packages/lume-column-group/src/event.tsx b/packages/lume-column-group/src/event.tsx deleted file mode 100644 index 1174c079..00000000 --- a/packages/lume-column-group/src/event.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { ThreadNote } from "@lume/ark"; -import { ArrowLeftIcon } from "@lume/icons"; -import { ReplyList } from "@lume/ui"; -import { useNavigate, useParams } from "react-router-dom"; -import { WVList } from "virtua"; - -export function EventRoute() { - const { id } = useParams(); - const navigate = useNavigate(); - - return ( - -
- -
-
- - -
-
- ); -} diff --git a/packages/lume-column-group/src/index.tsx b/packages/lume-column-group/src/index.tsx index 5ca24d6b..1c059d83 100644 --- a/packages/lume-column-group/src/index.tsx +++ b/packages/lume-column-group/src/index.tsx @@ -2,9 +2,8 @@ import { Column } from "@lume/ark"; import { GroupFeedsIcon } from "@lume/icons"; import { IColumn } from "@lume/types"; import { GroupForm } from "./components/form"; -import { EventRoute } from "./event"; import { HomeRoute } from "./home"; -import { UserRoute } from "./user"; +import { EventRoute, UserRoute } from "@lume/ui"; export function Group({ column }: { column: IColumn }) { const colKey = `group-${column.id}`; diff --git a/packages/lume-column-group/src/user.tsx b/packages/lume-column-group/src/user.tsx deleted file mode 100644 index 8d46f957..00000000 --- a/packages/lume-column-group/src/user.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import { - RepostNote, - TextNote, - useArk, - useProfile, - useStorage, -} from "@lume/ark"; -import { ArrowLeftIcon, ArrowRightCircleIcon, LoaderIcon } from "@lume/icons"; -import { NIP05 } from "@lume/ui"; -import { FETCH_LIMIT, displayNpub } from "@lume/utils"; -import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; -import { useInfiniteQuery } from "@tanstack/react-query"; -import { useEffect, useMemo, useState } from "react"; -import { Link, useNavigate, useParams } from "react-router-dom"; -import { toast } from "sonner"; -import { WVList } from "virtua"; - -export function UserRoute() { - const ark = useArk(); - const storage = useStorage(); - const navigate = useNavigate(); - - const { id } = useParams(); - const { user } = useProfile(id); - const { data, hasNextPage, isLoading, isFetchingNextPage, fetchNextPage } = - useInfiniteQuery({ - queryKey: ["user-posts", id], - initialPageParam: 0, - queryFn: async ({ - signal, - pageParam, - }: { - signal: AbortSignal; - pageParam: number; - }) => { - const events = await ark.getInfiniteEvents({ - filter: { - kinds: [NDKKind.Text, NDKKind.Repost], - authors: [id], - }, - limit: FETCH_LIMIT, - pageParam, - signal, - }); - - return events; - }, - getNextPageParam: (lastPage) => { - const lastEvent = lastPage.at(-1); - if (!lastEvent) return; - return lastEvent.created_at - 1; - }, - refetchOnWindowFocus: false, - }); - - const [followed, setFollowed] = useState(false); - - const allEvents = useMemo( - () => (data ? data.pages.flatMap((page) => page) : []), - [data], - ); - - const follow = async (pubkey: string) => { - try { - const add = await ark.createContact({ pubkey }); - if (add) { - setFollowed(true); - } else { - toast.success("You already follow this user"); - } - } catch (error) { - console.log(error); - } - }; - - const unfollow = async (pubkey: string) => { - try { - const remove = await ark.deleteContact({ pubkey }); - if (remove) { - setFollowed(false); - } - } catch (error) { - console.log(error); - } - }; - - const renderItem = (event: NDKEvent) => { - switch (event.kind) { - case NDKKind.Text: - return ; - case NDKKind.Repost: - return ; - default: - return ; - } - }; - - useEffect(() => { - if (storage.account.contacts.includes(id)) { - setFollowed(true); - } - }, []); - - return ( - -
- -
-
-
-
- {id} -
- {followed ? ( - - ) : ( - - )} - - Message - -
-
-
-
-
- {user?.name || - user?.display_name || - user?.displayName || - "Anon"} -
- {user?.nip05 ? ( - - ) : ( - - {displayNpub(id, 16)} - - )} -
-
- {user?.about} -
-
-
-
-

- Latest posts -

-
- {isLoading ? ( -
- -
- ) : ( - allEvents.map((item) => renderItem(item)) - )} -
- {hasNextPage ? ( - - ) : null} -
-
-
-
-
- ); -} diff --git a/packages/lume-column-hashtag/src/event.tsx b/packages/lume-column-hashtag/src/event.tsx deleted file mode 100644 index 1174c079..00000000 --- a/packages/lume-column-hashtag/src/event.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { ThreadNote } from "@lume/ark"; -import { ArrowLeftIcon } from "@lume/icons"; -import { ReplyList } from "@lume/ui"; -import { useNavigate, useParams } from "react-router-dom"; -import { WVList } from "virtua"; - -export function EventRoute() { - const { id } = useParams(); - const navigate = useNavigate(); - - return ( - -
- -
-
- - -
-
- ); -} diff --git a/packages/lume-column-hashtag/src/index.tsx b/packages/lume-column-hashtag/src/index.tsx index 5eaef192..c91d0ae8 100644 --- a/packages/lume-column-hashtag/src/index.tsx +++ b/packages/lume-column-hashtag/src/index.tsx @@ -1,9 +1,8 @@ import { Column } from "@lume/ark"; import { HashtagIcon } from "@lume/icons"; import { IColumn } from "@lume/types"; -import { EventRoute } from "./event"; import { HomeRoute } from "./home"; -import { UserRoute } from "./user"; +import { EventRoute, UserRoute } from "@lume/ui"; export function Hashtag({ column }: { column: IColumn }) { const colKey = `hashtag-${column.id}`; diff --git a/packages/lume-column-hashtag/src/user.tsx b/packages/lume-column-hashtag/src/user.tsx deleted file mode 100644 index 8d46f957..00000000 --- a/packages/lume-column-hashtag/src/user.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import { - RepostNote, - TextNote, - useArk, - useProfile, - useStorage, -} from "@lume/ark"; -import { ArrowLeftIcon, ArrowRightCircleIcon, LoaderIcon } from "@lume/icons"; -import { NIP05 } from "@lume/ui"; -import { FETCH_LIMIT, displayNpub } from "@lume/utils"; -import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; -import { useInfiniteQuery } from "@tanstack/react-query"; -import { useEffect, useMemo, useState } from "react"; -import { Link, useNavigate, useParams } from "react-router-dom"; -import { toast } from "sonner"; -import { WVList } from "virtua"; - -export function UserRoute() { - const ark = useArk(); - const storage = useStorage(); - const navigate = useNavigate(); - - const { id } = useParams(); - const { user } = useProfile(id); - const { data, hasNextPage, isLoading, isFetchingNextPage, fetchNextPage } = - useInfiniteQuery({ - queryKey: ["user-posts", id], - initialPageParam: 0, - queryFn: async ({ - signal, - pageParam, - }: { - signal: AbortSignal; - pageParam: number; - }) => { - const events = await ark.getInfiniteEvents({ - filter: { - kinds: [NDKKind.Text, NDKKind.Repost], - authors: [id], - }, - limit: FETCH_LIMIT, - pageParam, - signal, - }); - - return events; - }, - getNextPageParam: (lastPage) => { - const lastEvent = lastPage.at(-1); - if (!lastEvent) return; - return lastEvent.created_at - 1; - }, - refetchOnWindowFocus: false, - }); - - const [followed, setFollowed] = useState(false); - - const allEvents = useMemo( - () => (data ? data.pages.flatMap((page) => page) : []), - [data], - ); - - const follow = async (pubkey: string) => { - try { - const add = await ark.createContact({ pubkey }); - if (add) { - setFollowed(true); - } else { - toast.success("You already follow this user"); - } - } catch (error) { - console.log(error); - } - }; - - const unfollow = async (pubkey: string) => { - try { - const remove = await ark.deleteContact({ pubkey }); - if (remove) { - setFollowed(false); - } - } catch (error) { - console.log(error); - } - }; - - const renderItem = (event: NDKEvent) => { - switch (event.kind) { - case NDKKind.Text: - return ; - case NDKKind.Repost: - return ; - default: - return ; - } - }; - - useEffect(() => { - if (storage.account.contacts.includes(id)) { - setFollowed(true); - } - }, []); - - return ( - -
- -
-
-
-
- {id} -
- {followed ? ( - - ) : ( - - )} - - Message - -
-
-
-
-
- {user?.name || - user?.display_name || - user?.displayName || - "Anon"} -
- {user?.nip05 ? ( - - ) : ( - - {displayNpub(id, 16)} - - )} -
-
- {user?.about} -
-
-
-
-

- Latest posts -

-
- {isLoading ? ( -
- -
- ) : ( - allEvents.map((item) => renderItem(item)) - )} -
- {hasNextPage ? ( - - ) : null} -
-
-
-
-
- ); -} diff --git a/packages/lume-column-thread/src/event.tsx b/packages/lume-column-thread/src/event.tsx deleted file mode 100644 index 1174c079..00000000 --- a/packages/lume-column-thread/src/event.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { ThreadNote } from "@lume/ark"; -import { ArrowLeftIcon } from "@lume/icons"; -import { ReplyList } from "@lume/ui"; -import { useNavigate, useParams } from "react-router-dom"; -import { WVList } from "virtua"; - -export function EventRoute() { - const { id } = useParams(); - const navigate = useNavigate(); - - return ( - -
- -
-
- - -
-
- ); -} diff --git a/packages/lume-column-thread/src/home.tsx b/packages/lume-column-thread/src/home.tsx index 2eb318aa..3158199b 100644 --- a/packages/lume-column-thread/src/home.tsx +++ b/packages/lume-column-thread/src/home.tsx @@ -1,14 +1,16 @@ -import { Note, ThreadNote } from "@lume/ark"; +import { ThreadNote } from "@lume/ark"; import { ReplyList } from "@lume/ui"; -import { WVList } from "virtua"; +import { WindowVirtualizer } from "virtua"; export function HomeRoute({ id }: { id: string }) { return ( - -
- - -
-
+
+ +
+ + +
+
+
); } diff --git a/packages/lume-column-thread/src/index.tsx b/packages/lume-column-thread/src/index.tsx index 0cbb6150..bcd536ed 100644 --- a/packages/lume-column-thread/src/index.tsx +++ b/packages/lume-column-thread/src/index.tsx @@ -1,8 +1,7 @@ import { Column } from "@lume/ark"; import { IColumn } from "@lume/types"; -import { EventRoute } from "./event"; import { HomeRoute } from "./home"; -import { UserRoute } from "./user"; +import { EventRoute, UserRoute } from "@lume/ui"; export function Thread({ column }: { column: IColumn }) { return ( diff --git a/packages/lume-column-thread/src/user.tsx b/packages/lume-column-thread/src/user.tsx deleted file mode 100644 index 8d46f957..00000000 --- a/packages/lume-column-thread/src/user.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import { - RepostNote, - TextNote, - useArk, - useProfile, - useStorage, -} from "@lume/ark"; -import { ArrowLeftIcon, ArrowRightCircleIcon, LoaderIcon } from "@lume/icons"; -import { NIP05 } from "@lume/ui"; -import { FETCH_LIMIT, displayNpub } from "@lume/utils"; -import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; -import { useInfiniteQuery } from "@tanstack/react-query"; -import { useEffect, useMemo, useState } from "react"; -import { Link, useNavigate, useParams } from "react-router-dom"; -import { toast } from "sonner"; -import { WVList } from "virtua"; - -export function UserRoute() { - const ark = useArk(); - const storage = useStorage(); - const navigate = useNavigate(); - - const { id } = useParams(); - const { user } = useProfile(id); - const { data, hasNextPage, isLoading, isFetchingNextPage, fetchNextPage } = - useInfiniteQuery({ - queryKey: ["user-posts", id], - initialPageParam: 0, - queryFn: async ({ - signal, - pageParam, - }: { - signal: AbortSignal; - pageParam: number; - }) => { - const events = await ark.getInfiniteEvents({ - filter: { - kinds: [NDKKind.Text, NDKKind.Repost], - authors: [id], - }, - limit: FETCH_LIMIT, - pageParam, - signal, - }); - - return events; - }, - getNextPageParam: (lastPage) => { - const lastEvent = lastPage.at(-1); - if (!lastEvent) return; - return lastEvent.created_at - 1; - }, - refetchOnWindowFocus: false, - }); - - const [followed, setFollowed] = useState(false); - - const allEvents = useMemo( - () => (data ? data.pages.flatMap((page) => page) : []), - [data], - ); - - const follow = async (pubkey: string) => { - try { - const add = await ark.createContact({ pubkey }); - if (add) { - setFollowed(true); - } else { - toast.success("You already follow this user"); - } - } catch (error) { - console.log(error); - } - }; - - const unfollow = async (pubkey: string) => { - try { - const remove = await ark.deleteContact({ pubkey }); - if (remove) { - setFollowed(false); - } - } catch (error) { - console.log(error); - } - }; - - const renderItem = (event: NDKEvent) => { - switch (event.kind) { - case NDKKind.Text: - return ; - case NDKKind.Repost: - return ; - default: - return ; - } - }; - - useEffect(() => { - if (storage.account.contacts.includes(id)) { - setFollowed(true); - } - }, []); - - return ( - -
- -
-
-
-
- {id} -
- {followed ? ( - - ) : ( - - )} - - Message - -
-
-
-
-
- {user?.name || - user?.display_name || - user?.displayName || - "Anon"} -
- {user?.nip05 ? ( - - ) : ( - - {displayNpub(id, 16)} - - )} -
-
- {user?.about} -
-
-
-
-

- Latest posts -

-
- {isLoading ? ( -
- -
- ) : ( - allEvents.map((item) => renderItem(item)) - )} -
- {hasNextPage ? ( - - ) : null} -
-
-
-
-
- ); -} diff --git a/packages/lume-column-timeline/src/event.tsx b/packages/lume-column-timeline/src/event.tsx deleted file mode 100644 index 1174c079..00000000 --- a/packages/lume-column-timeline/src/event.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { ThreadNote } from "@lume/ark"; -import { ArrowLeftIcon } from "@lume/icons"; -import { ReplyList } from "@lume/ui"; -import { useNavigate, useParams } from "react-router-dom"; -import { WVList } from "virtua"; - -export function EventRoute() { - const { id } = useParams(); - const navigate = useNavigate(); - - return ( - -
- -
-
- - -
-
- ); -} diff --git a/packages/lume-column-timeline/src/index.tsx b/packages/lume-column-timeline/src/index.tsx index edd09f89..9feceaa9 100644 --- a/packages/lume-column-timeline/src/index.tsx +++ b/packages/lume-column-timeline/src/index.tsx @@ -4,9 +4,8 @@ import { IColumn } from "@lume/types"; import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; import { useQueryClient } from "@tanstack/react-query"; import { useRef } from "react"; -import { EventRoute } from "./event"; import { HomeRoute } from "./home"; -import { UserRoute } from "./user"; +import { EventRoute, UserRoute } from "@lume/ui"; export function Timeline({ column }: { column: IColumn }) { const colKey = `timeline-${column.id}`; diff --git a/packages/lume-column-timeline/src/user.tsx b/packages/lume-column-timeline/src/user.tsx deleted file mode 100644 index 8d46f957..00000000 --- a/packages/lume-column-timeline/src/user.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import { - RepostNote, - TextNote, - useArk, - useProfile, - useStorage, -} from "@lume/ark"; -import { ArrowLeftIcon, ArrowRightCircleIcon, LoaderIcon } from "@lume/icons"; -import { NIP05 } from "@lume/ui"; -import { FETCH_LIMIT, displayNpub } from "@lume/utils"; -import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; -import { useInfiniteQuery } from "@tanstack/react-query"; -import { useEffect, useMemo, useState } from "react"; -import { Link, useNavigate, useParams } from "react-router-dom"; -import { toast } from "sonner"; -import { WVList } from "virtua"; - -export function UserRoute() { - const ark = useArk(); - const storage = useStorage(); - const navigate = useNavigate(); - - const { id } = useParams(); - const { user } = useProfile(id); - const { data, hasNextPage, isLoading, isFetchingNextPage, fetchNextPage } = - useInfiniteQuery({ - queryKey: ["user-posts", id], - initialPageParam: 0, - queryFn: async ({ - signal, - pageParam, - }: { - signal: AbortSignal; - pageParam: number; - }) => { - const events = await ark.getInfiniteEvents({ - filter: { - kinds: [NDKKind.Text, NDKKind.Repost], - authors: [id], - }, - limit: FETCH_LIMIT, - pageParam, - signal, - }); - - return events; - }, - getNextPageParam: (lastPage) => { - const lastEvent = lastPage.at(-1); - if (!lastEvent) return; - return lastEvent.created_at - 1; - }, - refetchOnWindowFocus: false, - }); - - const [followed, setFollowed] = useState(false); - - const allEvents = useMemo( - () => (data ? data.pages.flatMap((page) => page) : []), - [data], - ); - - const follow = async (pubkey: string) => { - try { - const add = await ark.createContact({ pubkey }); - if (add) { - setFollowed(true); - } else { - toast.success("You already follow this user"); - } - } catch (error) { - console.log(error); - } - }; - - const unfollow = async (pubkey: string) => { - try { - const remove = await ark.deleteContact({ pubkey }); - if (remove) { - setFollowed(false); - } - } catch (error) { - console.log(error); - } - }; - - const renderItem = (event: NDKEvent) => { - switch (event.kind) { - case NDKKind.Text: - return ; - case NDKKind.Repost: - return ; - default: - return ; - } - }; - - useEffect(() => { - if (storage.account.contacts.includes(id)) { - setFollowed(true); - } - }, []); - - return ( - -
- -
-
-
-
- {id} -
- {followed ? ( - - ) : ( - - )} - - Message - -
-
-
-
-
- {user?.name || - user?.display_name || - user?.displayName || - "Anon"} -
- {user?.nip05 ? ( - - ) : ( - - {displayNpub(id, 16)} - - )} -
-
- {user?.about} -
-
-
-
-

- Latest posts -

-
- {isLoading ? ( -
- -
- ) : ( - allEvents.map((item) => renderItem(item)) - )} -
- {hasNextPage ? ( - - ) : null} -
-
-
-
-
- ); -} diff --git a/packages/lume-column-user/src/event.tsx b/packages/lume-column-user/src/event.tsx deleted file mode 100644 index 1174c079..00000000 --- a/packages/lume-column-user/src/event.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { ThreadNote } from "@lume/ark"; -import { ArrowLeftIcon } from "@lume/icons"; -import { ReplyList } from "@lume/ui"; -import { useNavigate, useParams } from "react-router-dom"; -import { WVList } from "virtua"; - -export function EventRoute() { - const { id } = useParams(); - const navigate = useNavigate(); - - return ( - -
- -
-
- - -
-
- ); -} diff --git a/packages/lume-column-user/src/home.tsx b/packages/lume-column-user/src/home.tsx index 1f45f613..f84b11a8 100644 --- a/packages/lume-column-user/src/home.tsx +++ b/packages/lume-column-user/src/home.tsx @@ -13,7 +13,7 @@ import { useInfiniteQuery } from "@tanstack/react-query"; import { useEffect, useMemo, useState } from "react"; import { Link } from "react-router-dom"; import { toast } from "sonner"; -import { WVList } from "virtua"; +import { WindowVirtualizer } from "virtua"; export function HomeRoute({ id }: { id: string }) { const ark = useArk(); @@ -100,102 +100,104 @@ export function HomeRoute({ id }: { id: string }) { }, []); return ( - -
-
-
- {id} -
- {followed ? ( - + ) : ( + + )} + - Unfollow - - ) : ( - - )} - - Message - -
-
-
-
-
- {user?.name || - user?.display_name || - user?.displayName || - "Anon"} -
- {user?.nip05 ? ( - - ) : ( - - {displayNpub(id, 16)} - - )} -
-
- {user?.about} -
-
-
-
-

- Latest posts -

-
- {isLoading ? ( -
- + Message + +
+
+
+
+
+ {user?.name || + user?.display_name || + user?.displayName || + "Anon"} +
+ {user?.nip05 ? ( + + ) : ( + + {displayNpub(id, 16)} + + )} +
+
+ {user?.about} +
+
+
+
+

+ Latest posts +

+
+ {isLoading ? ( +
+ +
+ ) : ( + allEvents.map((item) => renderItem(item)) + )} +
+ {hasNextPage ? ( + + ) : null}
- ) : ( - allEvents.map((item) => renderItem(item)) - )} -
- {hasNextPage ? ( - - ) : null}
-
-
+ + ); } diff --git a/packages/lume-column-user/src/index.tsx b/packages/lume-column-user/src/index.tsx index 5753b93d..74618932 100644 --- a/packages/lume-column-user/src/index.tsx +++ b/packages/lume-column-user/src/index.tsx @@ -1,9 +1,8 @@ import { Column } from "@lume/ark"; import { UserIcon } from "@lume/icons"; import { IColumn } from "@lume/types"; -import { EventRoute } from "./event"; import { HomeRoute } from "./home"; -import { UserRoute } from "./user"; +import { EventRoute, UserRoute } from "@lume/ui"; export function User({ column }: { column: IColumn }) { return ( diff --git a/packages/lume-column-user/src/user.tsx b/packages/lume-column-user/src/user.tsx deleted file mode 100644 index 8d46f957..00000000 --- a/packages/lume-column-user/src/user.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import { - RepostNote, - TextNote, - useArk, - useProfile, - useStorage, -} from "@lume/ark"; -import { ArrowLeftIcon, ArrowRightCircleIcon, LoaderIcon } from "@lume/icons"; -import { NIP05 } from "@lume/ui"; -import { FETCH_LIMIT, displayNpub } from "@lume/utils"; -import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; -import { useInfiniteQuery } from "@tanstack/react-query"; -import { useEffect, useMemo, useState } from "react"; -import { Link, useNavigate, useParams } from "react-router-dom"; -import { toast } from "sonner"; -import { WVList } from "virtua"; - -export function UserRoute() { - const ark = useArk(); - const storage = useStorage(); - const navigate = useNavigate(); - - const { id } = useParams(); - const { user } = useProfile(id); - const { data, hasNextPage, isLoading, isFetchingNextPage, fetchNextPage } = - useInfiniteQuery({ - queryKey: ["user-posts", id], - initialPageParam: 0, - queryFn: async ({ - signal, - pageParam, - }: { - signal: AbortSignal; - pageParam: number; - }) => { - const events = await ark.getInfiniteEvents({ - filter: { - kinds: [NDKKind.Text, NDKKind.Repost], - authors: [id], - }, - limit: FETCH_LIMIT, - pageParam, - signal, - }); - - return events; - }, - getNextPageParam: (lastPage) => { - const lastEvent = lastPage.at(-1); - if (!lastEvent) return; - return lastEvent.created_at - 1; - }, - refetchOnWindowFocus: false, - }); - - const [followed, setFollowed] = useState(false); - - const allEvents = useMemo( - () => (data ? data.pages.flatMap((page) => page) : []), - [data], - ); - - const follow = async (pubkey: string) => { - try { - const add = await ark.createContact({ pubkey }); - if (add) { - setFollowed(true); - } else { - toast.success("You already follow this user"); - } - } catch (error) { - console.log(error); - } - }; - - const unfollow = async (pubkey: string) => { - try { - const remove = await ark.deleteContact({ pubkey }); - if (remove) { - setFollowed(false); - } - } catch (error) { - console.log(error); - } - }; - - const renderItem = (event: NDKEvent) => { - switch (event.kind) { - case NDKKind.Text: - return ; - case NDKKind.Repost: - return ; - default: - return ; - } - }; - - useEffect(() => { - if (storage.account.contacts.includes(id)) { - setFollowed(true); - } - }, []); - - return ( - -
- -
-
-
-
- {id} -
- {followed ? ( - - ) : ( - - )} - - Message - -
-
-
-
-
- {user?.name || - user?.display_name || - user?.displayName || - "Anon"} -
- {user?.nip05 ? ( - - ) : ( - - {displayNpub(id, 16)} - - )} -
-
- {user?.about} -
-
-
-
-

- Latest posts -

-
- {isLoading ? ( -
- -
- ) : ( - allEvents.map((item) => renderItem(item)) - )} -
- {hasNextPage ? ( - - ) : null} -
-
-
-
-
- ); -} diff --git a/packages/storage/index.ts b/packages/storage/index.ts index e64648a3..1c9c1dc8 100644 --- a/packages/storage/index.ts +++ b/packages/storage/index.ts @@ -254,11 +254,9 @@ export class LumeStorage { } public async createAccount({ - id, pubkey, privkey, }: { - id: string; pubkey: string; privkey?: string; }) { @@ -274,8 +272,8 @@ export class LumeStorage { ); } else { await this.#db.execute( - "INSERT OR IGNORE INTO accounts (id, pubkey, is_active) VALUES ($1, $2, $3);", - [id, pubkey, 1], + "INSERT OR IGNORE INTO accounts (pubkey, is_active) VALUES ($1, $2);", + [pubkey, 1], ); if (privkey) await this.#keyring_save(pubkey, privkey); diff --git a/packages/ui/package.json b/packages/ui/package.json index 624b94f1..f62dbfb3 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -28,7 +28,8 @@ "react-router-dom": "^6.21.1", "slate": "^0.101.5", "slate-react": "^0.101.5", - "sonner": "^1.3.1" + "sonner": "^1.3.1", + "virtua": "^0.20.0" }, "devDependencies": { "@lume/tailwindcss": "workspace:^", diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 8259009e..e8e16a2f 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -11,3 +11,5 @@ export * from "./layouts/home"; export * from "./layouts/settings"; export * from "./mentions"; export * from "./replyList"; +export * from "./routes/event"; +export * from "./routes/user"; diff --git a/packages/ui/src/routes/event.tsx b/packages/ui/src/routes/event.tsx new file mode 100644 index 00000000..b14764c8 --- /dev/null +++ b/packages/ui/src/routes/event.tsx @@ -0,0 +1,31 @@ +import { ThreadNote } from "@lume/ark"; +import { ArrowLeftIcon } from "@lume/icons"; +import { useNavigate, useParams } from "react-router-dom"; +import { WindowVirtualizer } from "virtua"; +import { ReplyList } from "../replyList"; + +export function EventRoute() { + const { id } = useParams(); + const navigate = useNavigate(); + + return ( +
+ +
+ +
+
+ + +
+
+
+ ); +} diff --git a/packages/ui/src/routes/user.tsx b/packages/ui/src/routes/user.tsx new file mode 100644 index 00000000..dc4e67d9 --- /dev/null +++ b/packages/ui/src/routes/user.tsx @@ -0,0 +1,215 @@ +import { + RepostNote, + TextNote, + useArk, + useProfile, + useStorage, +} from "@lume/ark"; +import { ArrowLeftIcon, ArrowRightCircleIcon, LoaderIcon } from "@lume/icons"; +import { FETCH_LIMIT, displayNpub } from "@lume/utils"; +import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { useEffect, useMemo, useState } from "react"; +import { Link, useNavigate, useParams } from "react-router-dom"; +import { toast } from "sonner"; +import { WindowVirtualizer } from "virtua"; +import { NIP05 } from "../nip05"; + +export function UserRoute() { + const ark = useArk(); + const storage = useStorage(); + const navigate = useNavigate(); + + const { id } = useParams(); + const { user } = useProfile(id); + const { data, hasNextPage, isLoading, isFetchingNextPage, fetchNextPage } = + useInfiniteQuery({ + queryKey: ["user-posts", id], + initialPageParam: 0, + queryFn: async ({ + signal, + pageParam, + }: { + signal: AbortSignal; + pageParam: number; + }) => { + const events = await ark.getInfiniteEvents({ + filter: { + kinds: [NDKKind.Text, NDKKind.Repost], + authors: [id], + }, + limit: FETCH_LIMIT, + pageParam, + signal, + }); + + return events; + }, + getNextPageParam: (lastPage) => { + const lastEvent = lastPage.at(-1); + if (!lastEvent) return; + return lastEvent.created_at - 1; + }, + refetchOnWindowFocus: false, + }); + + const [followed, setFollowed] = useState(false); + + const allEvents = useMemo( + () => (data ? data.pages.flatMap((page) => page) : []), + [data], + ); + + const follow = async (pubkey: string) => { + try { + const add = await ark.createContact({ pubkey }); + if (add) { + setFollowed(true); + } else { + toast.success("You already follow this user"); + } + } catch (error) { + console.log(error); + } + }; + + const unfollow = async (pubkey: string) => { + try { + const remove = await ark.deleteContact({ pubkey }); + if (remove) { + setFollowed(false); + } + } catch (error) { + console.log(error); + } + }; + + const renderItem = (event: NDKEvent) => { + switch (event.kind) { + case NDKKind.Text: + return ; + case NDKKind.Repost: + return ; + default: + return ; + } + }; + + useEffect(() => { + if (storage.account.contacts.includes(id)) { + setFollowed(true); + } + }, []); + + return ( +
+ +
+ +
+
+
+
+ {id} +
+ {followed ? ( + + ) : ( + + )} + + Message + +
+
+
+
+
+ {user?.name || + user?.display_name || + user?.displayName || + "Anon"} +
+ {user?.nip05 ? ( + + ) : ( + + {displayNpub(id, 16)} + + )} +
+
+ {user?.about} +
+
+
+
+

+ Latest posts +

+
+ {isLoading ? ( +
+ +
+ ) : ( + allEvents.map((item) => renderItem(item)) + )} +
+ {hasNextPage ? ( + + ) : null} +
+
+
+
+
+
+ ); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be2f8f67..0a9d0eb3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -942,6 +942,9 @@ importers: sonner: specifier: ^1.3.1 version: 1.3.1(react-dom@18.2.0)(react@18.2.0) + virtua: + specifier: ^0.20.0 + version: 0.20.0(react-dom@18.2.0)(react@18.2.0) devDependencies: '@lume/tailwindcss': specifier: workspace:^ diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 92588d39..448356f6 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2690,7 +2690,7 @@ dependencies = [ [[package]] name = "lume" -version = "2.2.0" +version = "3.0.0" dependencies = [ "keyring", "serde", @@ -2702,7 +2702,7 @@ dependencies = [ "tauri-plugin-cli", "tauri-plugin-clipboard-manager", "tauri-plugin-dialog", - "tauri-plugin-fs", + "tauri-plugin-fs 2.0.0-alpha.7 (git+https://github.com/tauri-apps/plugins-workspace?branch=v2)", "tauri-plugin-http", "tauri-plugin-notification", "tauri-plugin-os", @@ -5110,7 +5110,7 @@ dependencies = [ "serde_json", "tauri", "tauri-build", - "tauri-plugin-fs", + "tauri-plugin-fs 2.0.0-alpha.7 (git+https://github.com/tauri-apps/plugins-workspace?branch=v2)", "thiserror", ] @@ -5129,10 +5129,25 @@ dependencies = [ "uuid", ] +[[package]] +name = "tauri-plugin-fs" +version = "2.0.0-alpha.7" +source = "git+https://github.com/tauri-apps/plugins-workspace?rev=ea8eadce85b2e3e8eb7eb1a779fc3aa6c1201fa3#ea8eadce85b2e3e8eb7eb1a779fc3aa6c1201fa3" +dependencies = [ + "anyhow", + "glob", + "serde", + "serde_repr", + "tauri", + "thiserror", + "url", + "uuid", +] + [[package]] name = "tauri-plugin-http" version = "2.0.0-alpha.9" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#1b1d795b5866e5524a9a9925f0fb7b2f8e3e3675" +source = "git+https://github.com/tauri-apps/plugins-workspace?rev=ea8eadce85b2e3e8eb7eb1a779fc3aa6c1201fa3#ea8eadce85b2e3e8eb7eb1a779fc3aa6c1201fa3" dependencies = [ "data-url", "glob", @@ -5141,7 +5156,7 @@ dependencies = [ "serde", "serde_json", "tauri", - "tauri-plugin-fs", + "tauri-plugin-fs 2.0.0-alpha.7 (git+https://github.com/tauri-apps/plugins-workspace?rev=ea8eadce85b2e3e8eb7eb1a779fc3aa6c1201fa3)", "thiserror", "url", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 71c8f3f5..047509d0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lume" -version = "2.2.0" +version = "3.0.0" description = "the communication app" authors = ["Ren Amamiya"] license = "GPL-3.0" @@ -23,7 +23,7 @@ tauri-plugin-cli = { git = "https://github.com/tauri-apps/plugins-workspace", br tauri-plugin-clipboard-manager = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-dialog = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-fs = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } -tauri-plugin-http = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } +tauri-plugin-http = { git = "https://github.com/tauri-apps/plugins-workspace", rev = "ea8eadce85b2e3e8eb7eb1a779fc3aa6c1201fa3" } tauri-plugin-notification = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-os = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-process = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } diff --git a/src-tauri/migrations/20230418013219_initial_data.sql b/src-tauri/migrations/20230418013219_initial_data.sql index 74b5f95d..09916b7c 100644 --- a/src-tauri/migrations/20230418013219_initial_data.sql +++ b/src-tauri/migrations/20230418013219_initial_data.sql @@ -1,27 +1,40 @@ -- create accounts table CREATE TABLE accounts ( - id TEXT NOT NULL PRIMARY KEY, + id INTEGER NOT NULL PRIMARY KEY, pubkey TEXT NOT NULL UNIQUE, - follows TEXT, - circles TEXT, is_active INTEGER NOT NULL DEFAULT 0, - last_login_at NUMBER NOT NULL DEFAULT 0, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); --- create notes table +-- create ndk cache users table CREATE TABLE - events ( + ndk_users ( + pubkey TEXT NOT NULL PRIMARY KEY, + profile TEXT, + createdAt NUMBER + ); + +-- create ndk cache events table +CREATE TABLE + ndk_events ( id TEXT NOT NULL PRIMARY KEY, - account_id INTEGER NOT NULL, - event TEXT NOT NULL, - author TEXT NOT NULL, - kind NUMBER NOT NULL DEFAULt 1, - root_id TEXT, - reply_id TEXT, - created_at INTEGER NOT NULL, - FOREIGN KEY (account_id) REFERENCES accounts (id) + pubkey TEXT, + content TEXT, + kind NUMBER, + createdAt NUMBER, + relay TEXT, + event TEXT + ); + +-- create ndk cache eventtags table +CREATE TABLE + ndk_eventtags ( + id TEXT NOT NULL PRIMARY KEY, + eventId TEXT, + tag TEXT, + value TEXT, + tagValue TEXT ); -- create settings table @@ -33,8 +46,9 @@ CREATE TABLE created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); +-- create columns table CREATE TABLE - widgets ( + columns ( id INTEGER NOT NULL PRIMARY KEY, account_id INTEGER NOT NULL, kind INTEGER NOT NULL, @@ -43,13 +57,3 @@ CREATE TABLE created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (account_id) REFERENCES accounts (id) ); - -CREATE TABLE - relays ( - id INTEGER NOT NULL PRIMARY KEY, - account_id INTEGER NOT NULL, - relay TEXT NOT NULL UNIQUE, - purpose TEXT NOT NULL DEFAULT '', - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY (account_id) REFERENCES accounts (id) - ); diff --git a/src-tauri/migrations/20231028083224_add_ndk_cache_table.sql b/src-tauri/migrations/20231028083224_add_ndk_cache_table.sql deleted file mode 100644 index d1440e3d..00000000 --- a/src-tauri/migrations/20231028083224_add_ndk_cache_table.sql +++ /dev/null @@ -1,27 +0,0 @@ --- Add migration script here -CREATE TABLE - ndk_users ( - pubkey TEXT NOT NULL PRIMARY KEY, - profile TEXT, - createdAt NUMBER - ); - -CREATE TABLE - ndk_events ( - id TEXT NOT NULL PRIMARY KEY, - pubkey TEXT, - content TEXT, - kind NUMBER, - createdAt NUMBER, - relay TEXT, - event TEXT - ); - -CREATE TABLE - ndk_eventtags ( - id TEXT NOT NULL PRIMARY KEY, - eventId TEXT, - tag TEXT, - value TEXT, - tagValue TEXT - ); diff --git a/src-tauri/migrations/20231130105202_clean_up_table.sql b/src-tauri/migrations/20231130105202_clean_up_table.sql deleted file mode 100644 index 6de5aed6..00000000 --- a/src-tauri/migrations/20231130105202_clean_up_table.sql +++ /dev/null @@ -1,5 +0,0 @@ -ALTER TABLE accounts DROP COLUMN follows; -ALTER TABLE accounts DROP COLUMN circles; -ALTER TABLE accounts DROP COLUMN last_login_at; -DROP TABLE IF EXISTS events; -DROP TABLE IF EXISTS relays; diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 2bea7d0b..9f25295a 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -1,4 +1,7 @@ use std::process::Command; +use keyring::Entry; +use std::time::Duration; +use webpage::{Webpage, WebpageOptions}; #[tauri::command] pub async fn show_in_folder(path: String) { @@ -46,3 +49,92 @@ pub async fn show_in_folder(path: String) { Command::new("open").args(["-R", &path]).spawn().unwrap(); } } + +#[derive(serde::Serialize)] +pub struct OpenGraphResponse { + title: String, + description: String, + url: String, + image: String, +} + +pub async fn fetch_opengraph(url: String) -> OpenGraphResponse { + let options = WebpageOptions { + allow_insecure: false, + max_redirections: 3, + timeout: Duration::from_secs(15), + useragent: "lume - desktop app".to_string(), + ..Default::default() + }; + + let result = match Webpage::from_url(&url, options) { + Ok(webpage) => webpage, + Err(_) => { + return OpenGraphResponse { + title: "".to_string(), + description: "".to_string(), + url: "".to_string(), + image: "".to_string(), + } + } + }; + + let html = result.html; + + return OpenGraphResponse { + title: html + .opengraph + .properties + .get("title") + .cloned() + .unwrap_or_default(), + description: html + .opengraph + .properties + .get("description") + .cloned() + .unwrap_or_default(), + url: html + .opengraph + .properties + .get("url") + .cloned() + .unwrap_or_default(), + image: html + .opengraph + .images + .get(0) + .and_then(|i| Some(i.url.clone())) + .unwrap_or_default(), + }; +} + +#[tauri::command] +pub async fn opengraph(url: String) -> OpenGraphResponse { + let result = fetch_opengraph(url).await; + return result; +} + +#[tauri::command] +pub fn secure_save(key: String, value: String) -> Result<(), ()> { + let entry = Entry::new("lume", &key).expect("Failed to create entry"); + let _ = entry.set_password(&value); + Ok(()) +} + +#[tauri::command] +pub fn secure_load(key: String) -> Result { + let entry = Entry::new("lume", &key).expect("Failed to create entry"); + if let Ok(password) = entry.get_password() { + Ok(password) + } else { + Err("not found".to_string()) + } +} + +#[tauri::command] +pub fn secure_remove(key: String) -> Result<(), ()> { + let entry = Entry::new("lume", &key).expect("Failed to create entry"); + let _ = entry.delete_password(); + Ok(()) +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 74f26bef..36bcecc7 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -5,107 +5,9 @@ mod commands; -use keyring::Entry; -use std::time::Duration; use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_sql::{Migration, MigrationKind}; use tauri_plugin_theme::ThemePlugin; -use webpage::{Webpage, WebpageOptions}; - -#[derive(Clone, serde::Serialize)] -struct Payload { - args: Vec, - cwd: String, -} - -#[derive(serde::Serialize)] -struct OpenGraphResponse { - title: String, - description: String, - url: String, - image: String, -} - -async fn fetch_opengraph(url: String) -> OpenGraphResponse { - let options = WebpageOptions { - allow_insecure: false, - max_redirections: 3, - timeout: Duration::from_secs(15), - useragent: "lume - desktop app".to_string(), - ..Default::default() - }; - - let result = match Webpage::from_url(&url, options) { - Ok(webpage) => webpage, - Err(_) => { - return OpenGraphResponse { - title: "".to_string(), - description: "".to_string(), - url: "".to_string(), - image: "".to_string(), - } - } - }; - - let html = result.html; - - return OpenGraphResponse { - title: html - .opengraph - .properties - .get("title") - .cloned() - .unwrap_or_default(), - description: html - .opengraph - .properties - .get("description") - .cloned() - .unwrap_or_default(), - url: html - .opengraph - .properties - .get("url") - .cloned() - .unwrap_or_default(), - image: html - .opengraph - .images - .get(0) - .and_then(|i| Some(i.url.clone())) - .unwrap_or_default(), - }; -} - -#[tauri::command] -async fn opengraph(url: String) -> OpenGraphResponse { - let result = fetch_opengraph(url).await; - return result; -} - -#[tauri::command] -fn secure_save(key: String, value: String) -> Result<(), ()> { - let entry = Entry::new("lume", &key).expect("Failed to create entry"); - let _ = entry.set_password(&value); - Ok(()) -} - -#[tauri::command] -fn secure_load(key: String) -> Result { - let entry = Entry::new("lume", &key).expect("Failed to create entry"); - if let Ok(password) = entry.get_password() { - Ok(password) - } else { - Err("not found".to_string()) - } -} - -#[tauri::command] -fn secure_remove(key: String) -> Result<(), ()> { - let entry = Entry::new("lume", &key).expect("Failed to create entry"); - let _ = entry.delete_password(); - Ok(()) -} fn main() { let mut ctx = tauri::generate_context!(); @@ -120,7 +22,7 @@ fn main() { .plugin( tauri_plugin_sql::Builder::default() .add_migrations( - "sqlite:lume_v2.db", + "sqlite:lume_v3.db", vec![ Migration { version: 20230418013219, @@ -128,18 +30,6 @@ fn main() { sql: include_str!("../migrations/20230418013219_initial_data.sql"), kind: MigrationKind::Up, }, - Migration { - version: 20231028083224, - description: "add ndk cache table", - sql: include_str!("../migrations/20231028083224_add_ndk_cache_table.sql"), - kind: MigrationKind::Up, - }, - Migration { - version: 20231130105202, - description: "clean up table", - sql: include_str!("../migrations/20231130105202_clean_up_table.sql"), - kind: MigrationKind::Up, - }, ], ) .build(), @@ -160,10 +50,10 @@ fn main() { Some(vec![]), )) .invoke_handler(tauri::generate_handler![ - opengraph, - secure_save, - secure_load, - secure_remove, + commands::opengraph, + commands::secure_save, + commands::secure_load, + commands::secure_remove, commands::show_in_folder, ]) .run(ctx)