diff --git a/apps/desktop/postcss.config.js b/apps/desktop/postcss.config.js index b0c1e3b5..e873f1a4 100644 --- a/apps/desktop/postcss.config.js +++ b/apps/desktop/postcss.config.js @@ -1,5 +1,6 @@ module.exports = { plugins: { tailwindcss: {}, + autoprefixer: {}, }, }; diff --git a/apps/desktop/src/routes/activty/components/list.tsx b/apps/desktop/src/routes/activty/components/list.tsx index e7accdd5..b0ee6e39 100644 --- a/apps/desktop/src/routes/activty/components/list.tsx +++ b/apps/desktop/src/routes/activty/components/list.tsx @@ -50,7 +50,6 @@ export function ActivityList() { }; } }, - staleTime: 360 * 1000, refetchOnWindowFocus: false, refetchOnMount: false, diff --git a/apps/desktop/src/routes/auth/create.tsx b/apps/desktop/src/routes/auth/create.tsx index af56b9b7..8cb8caa1 100644 --- a/apps/desktop/src/routes/auth/create.tsx +++ b/apps/desktop/src/routes/auth/create.tsx @@ -145,10 +145,11 @@ export function CreateAccountScreen() { // add account to storage await storage.createSetting("nsecbunker", "1"); - await storage.createAccount({ + const dbAccount = await storage.createAccount({ pubkey: account, privkey: localSigner.privateKey, }); + ark.account = dbAccount; // get final signer with newly created account const finalSigner = new NDKNip46Signer(bunker, account, localSigner); @@ -156,7 +157,6 @@ export function CreateAccountScreen() { // update main ndk instance signer ark.updateNostrSigner({ signer: finalSigner }); - console.log(ark.ndk.signer); // remove default nsecbunker profile and contact list await ark.createEvent({ kind: NDKKind.Metadata, content: "", tags: [] }); diff --git a/apps/desktop/src/routes/auth/login-key.tsx b/apps/desktop/src/routes/auth/login-key.tsx index 26a7333f..871d26de 100644 --- a/apps/desktop/src/routes/auth/login-key.tsx +++ b/apps/desktop/src/routes/auth/login-key.tsx @@ -1,3 +1,4 @@ +import { useArk } from "@lume/ark"; import { EyeOffIcon, EyeOnIcon, LoaderIcon } from "@lume/icons"; import { useStorage } from "@lume/storage"; import { getPublicKey, nip19 } from "nostr-tools"; @@ -7,6 +8,7 @@ import { useNavigate } from "react-router-dom"; import { toast } from "sonner"; export function LoginWithKey() { + const ark = useArk(); const storage = useStorage(); const navigate = useNavigate(); @@ -30,10 +32,11 @@ export function LoginWithKey() { const privkey = nip19.decode(data.nsec).data as string; const pubkey = getPublicKey(privkey); - await storage.createAccount({ + const account = await storage.createAccount({ pubkey: pubkey, privkey: privkey, }); + ark.account = account; return navigate("/auth/onboarding", { replace: true }); } catch (e) { diff --git a/apps/desktop/src/routes/auth/login-nsecbunker.tsx b/apps/desktop/src/routes/auth/login-nsecbunker.tsx index 61f09ef3..4679ab76 100644 --- a/apps/desktop/src/routes/auth/login-nsecbunker.tsx +++ b/apps/desktop/src/routes/auth/login-nsecbunker.tsx @@ -48,10 +48,11 @@ export function LoginWithNsecbunker() { ark.updateNostrSigner({ signer: remoteSigner }); await storage.createSetting("nsecbunker", "1"); - await storage.createAccount({ - pubkey, + const account = await storage.createAccount({ + pubkey: pubkey, privkey: localSigner.privateKey, }); + ark.account = account; return navigate("/auth/onboarding", { replace: true }); } catch (e) { diff --git a/apps/desktop/src/routes/auth/login-oauth.tsx b/apps/desktop/src/routes/auth/login-oauth.tsx index 53e266a3..87d88496 100644 --- a/apps/desktop/src/routes/auth/login-oauth.tsx +++ b/apps/desktop/src/routes/auth/login-oauth.tsx @@ -109,10 +109,11 @@ export function LoginWithOAuth() { ark.updateNostrSigner({ signer: remoteSigner }); await storage.createSetting("nsecbunker", "1"); - await storage.createAccount({ + const account = await storage.createAccount({ pubkey, privkey: localSigner.privateKey, }); + ark.account = account; return navigate("/auth/onboarding", { replace: true }); } diff --git a/apps/desktop/src/routes/auth/onboarding.tsx b/apps/desktop/src/routes/auth/onboarding.tsx index 77d6ab4b..bd7ec00c 100644 --- a/apps/desktop/src/routes/auth/onboarding.tsx +++ b/apps/desktop/src/routes/auth/onboarding.tsx @@ -29,7 +29,7 @@ export function OnboardingScreen() { const toggleLowPower = async () => { await storage.createSetting("lowPower", String(+!settings.lowPower)); - setSettings((state) => ({ ...state, autoupdate: !settings.lowPower })); + setSettings((state) => ({ ...state, lowPower: !settings.lowPower })); }; const toggleTranslation = async () => { @@ -58,7 +58,7 @@ export function OnboardingScreen() { setLoading(true); // get account contacts - await ark.getUserContacts(ark.account.pubkey); + await ark.getUserContacts(); // refetch newsfeed await queryClient.prefetchInfiniteQuery({ @@ -154,7 +154,7 @@ export function OnboardingScreen() {

Low Power Mode

Limited relay connection and hide all media, sustainable for low - network environment + network environment.

@@ -171,7 +171,8 @@ export function OnboardingScreen() { Translation (nostr.wine)

- Translate text to your preferred language, powered by Nostr Wine + Translate text to your preferred language, powered by Nostr + Wine.

diff --git a/apps/desktop/src/routes/depot/components/members.tsx b/apps/desktop/src/routes/depot/components/members.tsx index 1f9a369b..4b368150 100644 --- a/apps/desktop/src/routes/depot/components/members.tsx +++ b/apps/desktop/src/routes/depot/components/members.tsx @@ -87,7 +87,7 @@ export function DepotMembers() { - +
diff --git a/apps/desktop/src/routes/settings/advanced.tsx b/apps/desktop/src/routes/settings/advanced.tsx index 23f1a619..2fcb0a02 100644 --- a/apps/desktop/src/routes/settings/advanced.tsx +++ b/apps/desktop/src/routes/settings/advanced.tsx @@ -13,14 +13,14 @@ export function AdvancedSettingScreen() {
- Caches + Cache
-
Use for boost up NDK
+
Use for boost up nostr connection
diff --git a/apps/desktop/src/routes/settings/components/postCard.tsx b/apps/desktop/src/routes/settings/components/postCard.tsx index f0496075..f828d4a0 100644 --- a/apps/desktop/src/routes/settings/components/postCard.tsx +++ b/apps/desktop/src/routes/settings/components/postCard.tsx @@ -1,12 +1,12 @@ +import { useArk } from "@lume/ark"; import { LoaderIcon } from "@lume/icons"; -import { useStorage } from "@lume/storage"; import { compactNumber } from "@lume/utils"; import { useQuery } from "@tanstack/react-query"; import { fetch } from "@tauri-apps/plugin-http"; import { Link } from "react-router-dom"; export function PostCard() { - const storage = useStorage(); + const ark = useArk(); const { status, data } = useQuery({ queryKey: ["user-stats", ark.account.pubkey], queryFn: async ({ signal }: { signal: AbortSignal }) => { diff --git a/apps/desktop/src/routes/settings/components/profileCard.tsx b/apps/desktop/src/routes/settings/components/profileCard.tsx index 8dc18b3e..7b949df4 100644 --- a/apps/desktop/src/routes/settings/components/profileCard.tsx +++ b/apps/desktop/src/routes/settings/components/profileCard.tsx @@ -1,6 +1,5 @@ -import { useProfile } from "@lume/ark"; +import { useArk, useProfile } from "@lume/ark"; import { EditIcon, LoaderIcon } from "@lume/icons"; -import { useStorage } from "@lume/storage"; import { displayNpub } from "@lume/utils"; import * as Avatar from "@radix-ui/react-avatar"; import { writeText } from "@tauri-apps/plugin-clipboard-manager"; @@ -9,7 +8,7 @@ import { nip19 } from "nostr-tools"; import { Link } from "react-router-dom"; export function ProfileCard() { - const storage = useStorage(); + const ark = useArk(); const svgURI = `data:image/svg+xml;utf8,${encodeURIComponent( minidenticon(ark.account.pubkey, 90, 50), )}`; diff --git a/apps/desktop/src/routes/settings/components/relayCard.tsx b/apps/desktop/src/routes/settings/components/relayCard.tsx index 132d506b..c170a2cc 100644 --- a/apps/desktop/src/routes/settings/components/relayCard.tsx +++ b/apps/desktop/src/routes/settings/components/relayCard.tsx @@ -1,13 +1,11 @@ import { useArk } from "@lume/ark"; import { EditIcon, LoaderIcon } from "@lume/icons"; -import { useStorage } from "@lume/storage"; import { compactNumber } from "@lume/utils"; import { useQuery } from "@tanstack/react-query"; import { Link } from "react-router-dom"; export function RelayCard() { const ark = useArk(); - const storage = useStorage(); const { status, data } = useQuery({ queryKey: ["relays", ark.account.pubkey], diff --git a/apps/desktop/src/routes/settings/components/zapCard.tsx b/apps/desktop/src/routes/settings/components/zapCard.tsx index e1771d42..362e19cc 100644 --- a/apps/desktop/src/routes/settings/components/zapCard.tsx +++ b/apps/desktop/src/routes/settings/components/zapCard.tsx @@ -1,11 +1,11 @@ +import { useArk } from "@lume/ark"; import { LoaderIcon } from "@lume/icons"; -import { useStorage } from "@lume/storage"; import { compactNumber } from "@lume/utils"; import { useQuery } from "@tanstack/react-query"; import { fetch } from "@tauri-apps/plugin-http"; export function ZapCard() { - const storage = useStorage(); + const ark = useArk(); const { status, data } = useQuery({ queryKey: ["user-stats", ark.account.pubkey], queryFn: async ({ signal }: { signal: AbortSignal }) => { diff --git a/apps/desktop/src/routes/settings/general.tsx b/apps/desktop/src/routes/settings/general.tsx index 01f112d0..4ba3e3f3 100644 --- a/apps/desktop/src/routes/settings/general.tsx +++ b/apps/desktop/src/routes/settings/general.tsx @@ -15,6 +15,7 @@ export function GeneralSettingScreen() { const storage = useStorage(); const [settings, setSettings] = useState({ + lowPower: false, autoupdate: false, autolaunch: false, outbox: false, @@ -30,6 +31,11 @@ export function GeneralSettingScreen() { setSettings((prev) => ({ ...prev, appearance: theme })); }; + const toggleLowPower = async () => { + await storage.createSetting("lowPower", String(+!settings.lowPower)); + setSettings((state) => ({ ...state, lowPower: !settings.lowPower })); + }; + const toggleAutolaunch = async () => { if (!settings.autolaunch) { await enable(); @@ -42,12 +48,6 @@ export function GeneralSettingScreen() { } }; - const toggleOutbox = async () => { - await storage.createSetting("outbox", String(+!settings.outbox)); - // update state - setSettings((prev) => ({ ...prev, outbox: !settings.outbox })); - }; - const toggleMedia = async () => { await storage.createSetting("media", String(+!settings.media)); storage.settings.media = !settings.media; @@ -98,6 +98,12 @@ export function GeneralSettingScreen() { autoupdate: !!parseInt(item.value), })); + if (item.key === "lowPower") + setSettings((prev) => ({ + ...prev, + lowPower: !!parseInt(item.value), + })); + if (item.key === "outbox") setSettings((prev) => ({ ...prev, @@ -127,9 +133,9 @@ export function GeneralSettingScreen() {
- Updater + Update
-
Auto download new update at Login
+
Automatically download new update
+
+
+
+ Low Power +
+
+ Sustainable for low network environment. +
+
+ toggleLowPower()} + className="relative h-7 w-12 cursor-default rounded-full bg-neutral-200 outline-none data-[state=checked]:bg-blue-500 dark:bg-neutral-800" + > + + +
@@ -154,21 +177,6 @@ export function GeneralSettingScreen() {
-
-
-
- Gossip -
-
Use Outbox model
-
- toggleOutbox()} - className="relative h-7 w-12 cursor-default rounded-full bg-neutral-200 outline-none data-[state=checked]:bg-blue-500 dark:bg-neutral-800" - > - - -
@@ -189,7 +197,7 @@ export function GeneralSettingScreen() {
Hashtag
-
Hide all hashtags in content
+
Show all hashtags in content
- +
diff --git a/packages/ark/src/components/note/content.tsx b/packages/ark/src/components/note/content.tsx index 47662cc8..b17971dc 100644 --- a/packages/ark/src/components/note/content.tsx +++ b/packages/ark/src/components/note/content.tsx @@ -5,6 +5,7 @@ import { NOSTR_EVENTS, NOSTR_MENTIONS, VIDEOS, + canPreview, cn, regionNames, } from "@lume/utils"; @@ -27,9 +28,11 @@ import { useNoteContext } from "./provider"; export function NoteContent({ className, + mini = false, isTranslatable = false, }: { className?: string; + mini?: boolean; isTranslatable?: boolean; }) { const storage = useStorage(); @@ -52,7 +55,7 @@ export function NoteContent({ const words = text.split(/( |\n)/); const urls = [...getUrls(text)]; - if (storage.settings.media && !storage.settings.lowPower) { + if (storage.settings.media && !storage.settings.lowPower && !mini) { images = urls.filter((word) => IMAGES.some((el) => { const url = new URL(word); @@ -79,9 +82,11 @@ export function NoteContent({ ); } - events = words.filter((word) => - NOSTR_EVENTS.some((el) => word.startsWith(el)), - ); + if (!mini) { + events = words.filter((word) => + NOSTR_EVENTS.some((el) => word.startsWith(el)), + ); + } const hashtags = words.filter((word) => word.startsWith("#")); const mentions = words.filter((word) => @@ -198,7 +203,7 @@ export function NoteContent({ (match, i) => { const url = new URL(match); - if (!linkPreview) { + if (!linkPreview && canPreview(match)) { linkPreview = match; return ; } @@ -217,9 +222,11 @@ export function NoteContent({ }, ); - parsedContent = reactStringReplace(parsedContent, "\n", () => { - return
; - }); + if (!mini) { + parsedContent = reactStringReplace(parsedContent, "\n", () => { + return
; + }); + } if (typeof parsedContent[0] === "string") { parsedContent[0] = parsedContent[0].trimStart(); @@ -259,7 +266,12 @@ export function NoteContent({ return (
-
+
{richContent}
{isTranslatable && storage.settings.translation ? ( diff --git a/packages/ark/src/components/note/mentions/note.tsx b/packages/ark/src/components/note/mentions/note.tsx index 72b9bf94..c34c13ea 100644 --- a/packages/ark/src/components/note/mentions/note.tsx +++ b/packages/ark/src/components/note/mentions/note.tsx @@ -1,13 +1,17 @@ +import { PinIcon } from "@lume/icons"; +import { COL_TYPES } from "@lume/utils"; import { memo } from "react"; import { Link } from "react-router-dom"; import { Note } from "../"; import { useEvent } from "../../../hooks/useEvent"; +import { useColumnContext } from "../../column/provider"; import { User } from "../../user"; export const MentionNote = memo(function MentionNote({ eventId, openable = true, }: { eventId: string; openable?: boolean }) { + const { addColumn } = useColumnContext(); const { isLoading, isError, data } = useEvent(eventId); if (isLoading) { @@ -34,11 +38,11 @@ export const MentionNote = memo(function MentionNote({ return ( - + - + -
+
ยท -
- - {openable ? ( + + {openable ? ( +
Show more - ) : null} -
+ +
+ ) : null} ); diff --git a/packages/ark/src/components/note/user.tsx b/packages/ark/src/components/note/user.tsx index ac38b4f6..5718fc3d 100644 --- a/packages/ark/src/components/note/user.tsx +++ b/packages/ark/src/components/note/user.tsx @@ -12,7 +12,7 @@ export function NoteUser({ return ( - +
`data:image/svg+xml;utf8,${encodeURIComponent( @@ -20,7 +23,7 @@ export function UserAvatar({ className }: { className?: string }) {
@@ -30,13 +33,23 @@ export function UserAvatar({ className }: { className?: string }) { return ( - + {storage.settings.lowPower ? ( + + ) : ( + + )} @@ -16,7 +16,7 @@ export function UserName({ className }: { className?: string }) { } return ( -
+
{user.displayName || user.name || "Anon"}
); diff --git a/packages/ark/src/components/user/nip05.tsx b/packages/ark/src/components/user/nip05.tsx index 5b0a1db3..25ce0418 100644 --- a/packages/ark/src/components/user/nip05.tsx +++ b/packages/ark/src/components/user/nip05.tsx @@ -29,7 +29,7 @@ export function UserNip05({ return (
diff --git a/packages/ark/src/provider.tsx b/packages/ark/src/provider.tsx index ab897a1f..b2d3dd89 100644 --- a/packages/ark/src/provider.tsx +++ b/packages/ark/src/provider.tsx @@ -9,6 +9,7 @@ import NDK, { NDKPrivateKeySigner, NDKRelay, NDKRelayAuthPolicies, + NDKUser, } from "@nostr-dev-kit/ndk"; import { fetch } from "@tauri-apps/plugin-http"; import Linkify from "linkify-react"; @@ -19,7 +20,9 @@ import { LumeContext } from "./context"; export const LumeProvider = ({ children }: PropsWithChildren) => { const storage = useStorage(); - const [context, setContext] = useState(undefined); + + const [ark, setArk] = useState(undefined); + const [ndk, setNDK] = useState(undefined); async function initNostrSigner({ nsecbunker, @@ -67,7 +70,7 @@ export const LumeProvider = ({ children }: PropsWithChildren) => { } } - async function init() { + async function initNDK() { const explicitRelayUrls = normalizeRelayUrlSet([ "wss://bostr.nokotaro.com/", "wss://nostr.mutinywallet.com/", @@ -77,14 +80,12 @@ export const LumeProvider = ({ children }: PropsWithChildren) => { const outboxRelayUrls = normalizeRelayUrlSet(["wss://purplepag.es/"]); // #TODO: user should config blacklist relays - // No need to connect depot tunnel url - const blacklistRelayUrls = storage.settings.tunnelUrl.length - ? [ - storage.settings.tunnelUrl, - `${storage.settings.tunnelUrl}/`, - "wss://brb.io/", - ] - : ["wss://brb.io/"]; + // Skip connect depot tunnel url + const blacklistRelayUrls = normalizeRelayUrlSet( + storage.settings.tunnelUrl.length + ? [storage.settings.tunnelUrl, "wss://brb.io/"] + : ["wss://brb.io/"], + ); const cacheAdapter = new NDKCacheAdapterTauri(storage); const ndk = new NDK({ @@ -115,29 +116,37 @@ export const LumeProvider = ({ children }: PropsWithChildren) => { // auth ndk.relayAuthDefaultPolicy = async (relay: NDKRelay, challenge: string) => { const signIn = NDKRelayAuthPolicies.signIn({ ndk }); - const event = await signIn(relay, challenge).catch((e) => console.log(e)); + const event = await signIn(relay, challenge).catch((e) => + console.error(e), + ); if (event) { - sendNativeNotification( + await sendNativeNotification( `You've sign in sucessfully to relay: ${relay.url}`, ); return event; } }; - // update account's metadata - if (signer) { - const user = ndk.getUser({ pubkey: storage.currentUser.pubkey }); + setNDK(ndk); + } + + async function initArk() { + // ark utils + const ark = new Ark({ ndk, account: storage.currentUser }); + + if (ndk && storage.currentUser) { + const user = new NDKUser({ pubkey: storage.currentUser.pubkey }); ndk.activeUser = user; - const contacts = await user.follows(); - storage.currentUser.contacts = [...contacts].map((user) => user.pubkey); + // update contacts + await ark.getUserContacts(); // subscribe for new activity const sub = ndk.subscribe( { kinds: [NDKKind.Text, NDKKind.Repost, NDKKind.Zap], since: Math.floor(Date.now() / 1000), - "#p": [storage.currentUser.pubkey], + "#p": [ark.account.pubkey], }, { closeOnEose: false, groupable: false }, ); @@ -169,18 +178,18 @@ export const LumeProvider = ({ children }: PropsWithChildren) => { }); } - // ark utils - const ark = new Ark({ ndk, account: storage.currentUser }); - - // update context - setContext(ark); + setArk(ark); } useEffect(() => { - if (!context) init(); + if (ndk) initArk(); + }, [ndk]); + + useEffect(() => { + if (!ark && !ndk) initNDK(); }, []); - if (!context) { + if (!ark) { return (
) => { ); } - return ( - {children} - ); + return {children}; }; diff --git a/packages/storage/src/storage.ts b/packages/storage/src/storage.ts index 218f407c..a29a1375 100644 --- a/packages/storage/src/storage.ts +++ b/packages/storage/src/storage.ts @@ -279,9 +279,6 @@ export class LumeStorage { } const account = await this.getActiveAccount(); - this.currentUser = account; - this.currentUser.contacts = []; - return account; } diff --git a/packages/ui/src/activity/column.tsx b/packages/ui/src/activity/column.tsx deleted file mode 100644 index 2555d890..00000000 --- a/packages/ui/src/activity/column.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { activityAtom } from "@lume/utils"; -import { AnimatePresence, motion } from "framer-motion"; -import { useAtomValue } from "jotai"; -import { ActivityContent } from "./content"; - -export function Activity() { - const isActivityOpen = useAtomValue(activityAtom); - - return ( - - {isActivityOpen ? ( - - - - ) : null} - - ); -} diff --git a/packages/ui/src/activity/content.tsx b/packages/ui/src/activity/content.tsx deleted file mode 100644 index a3854cbf..00000000 --- a/packages/ui/src/activity/content.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import { useArk } from "@lume/ark"; -import { LoaderIcon } from "@lume/icons"; -import { useStorage } from "@lume/storage"; -import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; -import { useInfiniteQuery } from "@tanstack/react-query"; -import { useCallback, useMemo } from "react"; -import { ReplyActivity } from "./reply"; -import { RepostActivity } from "./repost"; -import { ZapActivity } from "./zap"; - -export function ActivityContent() { - const ark = useArk(); - const storage = useStorage(); - - const { isLoading, data, hasNextPage, isFetchingNextPage, fetchNextPage } = - useInfiniteQuery({ - queryKey: ["activity"], - initialPageParam: 0, - queryFn: async ({ - signal, - pageParam, - }: { - signal: AbortSignal; - pageParam: number; - }) => { - const events = await ark.getInfiniteEvents({ - filter: { - kinds: [NDKKind.Zap], - "#p": [ark.account.pubkey], - }, - limit: 100, - pageParam, - signal, - }); - - return events; - }, - getNextPageParam: (lastPage) => { - const lastEvent = lastPage.at(-1); - if (!lastEvent) return; - return lastEvent.created_at - 1; - }, - refetchOnWindowFocus: false, - refetchOnMount: false, - refetchOnReconnect: false, - }); - - const allEvents = useMemo( - () => (data ? data.pages.flatMap((page) => page) : []), - [data], - ); - - const renderEvent = useCallback((event: NDKEvent) => { - if (event.pubkey === ark.account.pubkey) return null; - - switch (event.kind) { - case NDKKind.Text: - return ; - case NDKKind.Repost: - return ; - case NDKKind.Zap: - return ; - default: - return ; - } - }, []); - - return ( -
-
- {isLoading ? ( -
- -
- ) : allEvents.length < 1 ? ( -
-

๐ŸŽ‰

-

Yo! Nothing new yet.

-
- ) : ( - renderEvent(allEvents[0]) - )} -
-
- - -
-
- ); -} diff --git a/packages/ui/src/activity/reply.tsx b/packages/ui/src/activity/reply.tsx deleted file mode 100644 index 0afae083..00000000 --- a/packages/ui/src/activity/reply.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Note, useArk } from "@lume/ark"; -import { NDKEvent } from "@nostr-dev-kit/ndk"; -import { ActivityRootNote } from "./rootNote"; - -export function ReplyActivity({ event }: { event: NDKEvent }) { - const ark = useArk(); - const thread = ark.getEventThread({ - content: event.content, - tags: event.tags, - }); - - return ( -
-
-

- Conversation -

-

- @ Someone has replied to your note -

-
-
- {thread ? ( -
- - -
- ) : null} -
-
-

New reply

-
-
-
- - -
- -
- -
- -
-
- - -
-
-
- ); -} diff --git a/packages/ui/src/activity/repost.tsx b/packages/ui/src/activity/repost.tsx deleted file mode 100644 index 87c657cb..00000000 --- a/packages/ui/src/activity/repost.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { formatCreatedAt } from "@lume/utils"; -import { NDKEvent } from "@nostr-dev-kit/ndk"; -import { User } from "../user"; -import { ActivityRootNote } from "./rootNote"; - -export function RepostActivity({ event }: { event: NDKEvent }) { - const repostId = event.tags.find((el) => el[0] === "e")[1]; - const createdAt = formatCreatedAt(event.created_at); - - return ( -
-
-

Boost

-

- @ Someone has reposted to your note -

-
-
-
- -
-

Reposted

-
-
-
-
-
- -
-
-
- ); -} diff --git a/packages/ui/src/activity/rootNote.tsx b/packages/ui/src/activity/rootNote.tsx deleted file mode 100644 index 5ba7e589..00000000 --- a/packages/ui/src/activity/rootNote.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Note, useEvent } from "@lume/ark"; - -export function ActivityRootNote({ eventId }: { eventId: string }) { - const { isLoading, isError, data } = useEvent(eventId); - - if (isLoading) { - return ( -
-
-
-
-
- ); - } - - if (isError) { - return ( -
-
- Failed to fetch event -
-
- ); - } - - return ( - - -
- -
- -
- -
-
- - - ); -} diff --git a/packages/ui/src/activity/zap.tsx b/packages/ui/src/activity/zap.tsx deleted file mode 100644 index 3da017ff..00000000 --- a/packages/ui/src/activity/zap.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { compactNumber, formatCreatedAt } from "@lume/utils"; -import { NDKEvent, zapInvoiceFromEvent } from "@nostr-dev-kit/ndk"; -import { User } from "../user"; -import { ActivityRootNote } from "./rootNote"; - -export function ZapActivity({ event }: { event: NDKEvent }) { - const zapEventId = event.tags.find((tag) => tag[0] === "e")[1]; - const invoice = zapInvoiceFromEvent(event); - - return ( -
-
-

Zap

-

- @ Someone love your note -

-
-
-
- -
-

Zapped

-
-
-
-
-
- -
-
-
- ); -} diff --git a/packages/ui/src/layouts/settings.tsx b/packages/ui/src/layouts/settings.tsx index 5b8dfd41..db8cfaee 100644 --- a/packages/ui/src/layouts/settings.tsx +++ b/packages/ui/src/layouts/settings.tsx @@ -20,7 +20,7 @@ export function SettingsLayout() { twMerge( "flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900", isActive - ? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-900" + ? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900" : "", ) } @@ -34,7 +34,7 @@ export function SettingsLayout() { twMerge( "flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900", isActive - ? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-900" + ? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900" : "", ) } @@ -48,7 +48,7 @@ export function SettingsLayout() { twMerge( "flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900", isActive - ? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-900" + ? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900" : "", ) } @@ -62,7 +62,7 @@ export function SettingsLayout() { twMerge( "flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900", isActive - ? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-900" + ? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900" : "", ) } @@ -76,7 +76,7 @@ export function SettingsLayout() { twMerge( "flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900", isActive - ? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-900" + ? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900" : "", ) } diff --git a/packages/ui/src/onboarding/modal.tsx b/packages/ui/src/onboarding/modal.tsx index c645d9f1..060c9edf 100644 --- a/packages/ui/src/onboarding/modal.tsx +++ b/packages/ui/src/onboarding/modal.tsx @@ -9,7 +9,7 @@ export function OnboardingModal() { return ( - +
diff --git a/packages/utils/src/formater.ts b/packages/utils/src/formater.ts index 53100f6c..9d0e511b 100644 --- a/packages/utils/src/formater.ts +++ b/packages/utils/src/formater.ts @@ -2,6 +2,7 @@ import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime"; import updateLocale from "dayjs/plugin/updateLocale"; import { nip19 } from "nostr-tools"; +import { AUDIOS, IMAGES, VIDEOS } from "./constants"; dayjs.extend(relativeTime); dayjs.extend(updateLocale); @@ -68,3 +69,23 @@ export const compactNumber = Intl.NumberFormat("en", { notation: "compact" }); // country name export const regionNames = new Intl.DisplayNames(["en"], { type: "language" }); + +// verify link can be preview +export function canPreview(text: string) { + const url = new URL(text); + const ext = url.pathname.split(".").pop(); + const hostname = url.hostname; + + if (VIDEOS.includes(ext)) return false; + if (IMAGES.includes(ext)) return false; + if (AUDIOS.includes(ext)) return false; + + if (hostname === "youtube.com") return false; + if (hostname === "youtu.be") return false; + if (hostname === "x.com") return false; + if (hostname === "twitter.com") return false; + if (hostname === "facebook.com") return false; + if (hostname === "vimeo.com") return false; + + return true; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 78336841..44448d05 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -270,25 +270,25 @@ importers: version: 0.15.0(@nostr-dev-kit/ndk@2.3.2)(nostr-fetch@0.15.0) '@radix-ui/react-avatar': specifier: ^1.0.4 - version: 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-collapsible': specifier: ^1.0.3 - version: 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-dialog': specifier: ^1.0.5 - version: 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.5(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-dropdown-menu': specifier: ^2.0.6 - version: 2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + version: 2.0.6(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-hover-card': specifier: ^1.0.7 - version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.7(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-popover': specifier: ^1.0.7 - version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.7(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-tooltip': specifier: ^1.0.7 - version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.7(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) '@tanstack/react-query': specifier: ^5.17.9 version: 5.17.9(react@18.2.0) @@ -1927,6 +1927,26 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-arrow@1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-avatar@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==} peerDependencies: @@ -1951,6 +1971,29 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-avatar@1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==} peerDependencies: @@ -1979,6 +2022,33 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-collapsible@1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} peerDependencies: @@ -2003,6 +2073,29 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-collection@1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.47)(react@18.2.0): resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -2065,6 +2158,39 @@ packages: react-remove-scroll: 2.5.5(@types/react@18.2.47)(react@18.2.0) dev: false + /@radix-ui/react-dialog@1.0.5(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.47)(react@18.2.0) + dev: false + /@radix-ui/react-direction@1.0.1(@types/react@18.2.47)(react@18.2.0): resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} peerDependencies: @@ -2104,6 +2230,30 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-dismissable-layer@1.0.5(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==} peerDependencies: @@ -2131,6 +2281,32 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-dropdown-menu@2.0.6(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-menu': 2.0.6(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.47)(react@18.2.0): resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} peerDependencies: @@ -2168,6 +2344,28 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-focus-scope@1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-hover-card@1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-OcUN2FU0YpmajD/qkph3XzMcK/NmSk9hGWnjV68p6QiZMgILugusgQwnLSDs3oFSJYGKf3Y49zgFedhGh04k9A==} peerDependencies: @@ -2197,6 +2395,34 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-hover-card@1.0.7(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-OcUN2FU0YpmajD/qkph3XzMcK/NmSk9hGWnjV68p6QiZMgILugusgQwnLSDs3oFSJYGKf3Y49zgFedhGh04k9A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-id@1.0.1(@types/react@18.2.47)(react@18.2.0): resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==} peerDependencies: @@ -2250,6 +2476,43 @@ packages: react-remove-scroll: 2.5.5(@types/react@18.2.47)(react@18.2.0) dev: false + /@radix-ui/react-menu@2.0.6(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-roving-focus': 1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.47)(react@18.2.0) + dev: false + /@radix-ui/react-popover@1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==} peerDependencies: @@ -2285,6 +2548,40 @@ packages: react-remove-scroll: 2.5.5(@types/react@18.2.47)(react@18.2.0) dev: false + /@radix-ui/react-popover@1.0.7(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.47)(react@18.2.0) + dev: false + /@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==} peerDependencies: @@ -2315,6 +2612,35 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-popper@1.1.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@floating-ui/react-dom': 2.0.5(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-arrow': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/rect': 1.0.1 + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==} peerDependencies: @@ -2336,6 +2662,26 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-portal@1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} peerDependencies: @@ -2358,6 +2704,27 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-presence@1.0.1(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} peerDependencies: @@ -2379,6 +2746,26 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-primitive@1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} peerDependencies: @@ -2408,6 +2795,34 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-roving-focus@1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-select@2.0.0(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-RH5b7af4oHtkcHS7pG6Sgv5rk5Wxa7XI8W5gvB1N/yiuDGZxko1ynvOiVhFM7Cis2A8zxF9bTOUVbRDzPepe6w==} peerDependencies: @@ -2523,6 +2938,37 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-tooltip@1.0.7(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.47)(react@18.2.0): resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} peerDependencies: @@ -2646,6 +3092,26 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-visually-hidden@1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.8 + '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.47 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/rect@1.0.1: resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==} dependencies: diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 9f25295a..c99f8d7b 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -1,5 +1,5 @@ -use std::process::Command; use keyring::Entry; +use std::process::Command; use std::time::Duration; use webpage::{Webpage, WebpageOptions}; @@ -117,14 +117,14 @@ pub async fn opengraph(url: String) -> OpenGraphResponse { #[tauri::command] pub fn secure_save(key: String, value: String) -> Result<(), ()> { - let entry = Entry::new("lume", &key).expect("Failed to create entry"); + 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"); + let entry = Entry::new("Lume", &key).expect("Failed to create entry"); if let Ok(password) = entry.get_password() { Ok(password) } else { @@ -134,7 +134,7 @@ pub fn secure_load(key: String) -> Result { #[tauri::command] pub fn secure_remove(key: String) -> Result<(), ()> { - let entry = Entry::new("lume", &key).expect("Failed to create entry"); + let entry = Entry::new("Lume", &key).expect("Failed to create entry"); let _ = entry.delete_password(); Ok(()) }