diff --git a/apps/desktop2/src/components/column.tsx b/apps/desktop2/src/components/column.tsx index 72b170ea..17c63de0 100644 --- a/apps/desktop2/src/components/column.tsx +++ b/apps/desktop2/src/components/column.tsx @@ -44,7 +44,7 @@ export const Column = memo(function Column({ useEffect(() => { if (!isCreated) return; - const unlisten = listen("child-webview", (data) => { + const unlisten = listen("child_webview", (data) => { if (data.payload.scroll) repositionWebview(); if (data.payload.resize) repositionWebview().then(() => resizeWebview()); }); @@ -84,15 +84,8 @@ export const Column = memo(function Column({ }, [account]); return ( -
-
+
+
diff --git a/apps/desktop2/src/components/note/content.tsx b/apps/desktop2/src/components/note/content.tsx index e7670a83..4143a5cf 100644 --- a/apps/desktop2/src/components/note/content.tsx +++ b/apps/desktop2/src/components/note/content.tsx @@ -118,7 +118,7 @@ export function NoteContent({
400 + event.meta?.content.length > 500 ? "max-h-[250px] gradient-mask-b-0" : "", className, diff --git a/apps/desktop2/src/components/note/mentions/note.tsx b/apps/desktop2/src/components/note/mentions/note.tsx index 7b7bf1cf..b2538138 100644 --- a/apps/desktop2/src/components/note/mentions/note.tsx +++ b/apps/desktop2/src/components/note/mentions/note.tsx @@ -2,7 +2,6 @@ import { User } from "@/components/user"; import { LinkIcon } from "@lume/icons"; import { LumeWindow, useEvent } from "@lume/system"; import { Spinner } from "@lume/ui"; -import { cn } from "@lume/utils"; export function MentionNote({ eventId, diff --git a/apps/desktop2/src/routes/$account.home.tsx b/apps/desktop2/src/routes/$account.home.tsx index 193259ef..0cb8a17b 100644 --- a/apps/desktop2/src/routes/$account.home.tsx +++ b/apps/desktop2/src/routes/$account.home.tsx @@ -1,6 +1,6 @@ import { Column } from "@/components/column"; import { Toolbar } from "@/components/toolbar"; -import { ArrowLeftIcon, ArrowRightIcon } from "@lume/icons"; +import { ArrowLeftIcon, ArrowRightIcon, PlusIcon } from "@lume/icons"; import { NostrQuery } from "@lume/system"; import type { ColumnEvent, LumeColumn } from "@lume/types"; import { createFileRoute } from "@tanstack/react-router"; @@ -38,11 +38,22 @@ function Screen() { }, [emblaApi]); const emitScrollEvent = useCallback(() => { - getCurrent().emit("child-webview", { scroll: true }); + getCurrent().emit("child_webview", { scroll: true }); }, []); const emitResizeEvent = useCallback(() => { - getCurrent().emit("child-webview", { resize: true, direction: "x" }); + getCurrent().emit("child_webview", { resize: true, direction: "x" }); + }, []); + + const openLumeStore = useCallback(async () => { + await getCurrent().emit("columns", { + type: "add", + column: { + label: "store", + name: "Store", + content: "/store/official", + }, + }); }, []); const add = useDebouncedCallback((column: LumeColumn) => { @@ -144,6 +155,18 @@ function Screen() { account={account} /> ))} +
+
+ +
+
diff --git a/apps/desktop2/src/routes/newsfeed.tsx b/apps/desktop2/src/routes/newsfeed.tsx index 762fe1b3..29bded41 100644 --- a/apps/desktop2/src/routes/newsfeed.tsx +++ b/apps/desktop2/src/routes/newsfeed.tsx @@ -65,7 +65,6 @@ export function Screen() { }, getNextPageParam: (lastPage) => lastPage?.at(-1)?.created_at - 1, select: (data) => data?.pages.flat(), - refetchOnWindowFocus: false, }); const ref = useRef(null); @@ -196,22 +195,16 @@ function Listerner() { }; useEffect(() => { - const unlistenEvent = getCurrent().listen("new_event", (data) => { + const unlisten = getCurrent().listen("new_event", (data) => { const event = LumeEvent.from(data.payload.raw, data.payload.parsed); setEvents((prev) => [event, ...prev]); }); - const unlistenWindow = getCurrent().onCloseRequested(async () => { - await NostrQuery.unlisten(); - await getCurrent().destroy(); - }); - - // Listen for new event NostrQuery.listenLocalEvent().then(() => console.log("listen")); return () => { - unlistenEvent.then((f) => f()); - unlistenWindow.then((f) => f()); + unlisten.then((f) => f()); + NostrQuery.unlisten().then(() => console.log("unlisten")); }; }, []); diff --git a/apps/desktop2/src/routes/panel.$account.tsx b/apps/desktop2/src/routes/panel.$account.tsx index ba780055..f3a7e97b 100644 --- a/apps/desktop2/src/routes/panel.$account.tsx +++ b/apps/desktop2/src/routes/panel.$account.tsx @@ -335,7 +335,7 @@ function TextNote({ event }: { event: LumeEvent }) { Reply to:
- {pTags.map((replyTo) => ( + {[...new Set(pTags)].map((replyTo) => ( diff --git a/packages/system/src/account.ts b/packages/system/src/account.ts index dd3f5d19..a506988b 100644 --- a/packages/system/src/account.ts +++ b/packages/system/src/account.ts @@ -1,8 +1,8 @@ import type { Metadata } from "@lume/types"; import { type Result, commands } from "./commands"; -export class NostrAccount { - static async getAccounts() { +export const NostrAccount = { + getAccounts: async () => { const query = await commands.getAccounts(); if (query.status === "ok") { @@ -10,9 +10,8 @@ export class NostrAccount { } else { return []; } - } - - static async loadAccount(npub: string) { + }, + loadAccount: async (npub: string) => { const bunker: string = localStorage.getItem(`${npub}_bunker`); let query: Result; @@ -27,9 +26,8 @@ export class NostrAccount { } else { throw new Error(query.error); } - } - - static async createAccount() { + }, + createAccount: async () => { const query = await commands.createAccount(); if (query.status === "ok") { @@ -37,9 +35,8 @@ export class NostrAccount { } else { throw new Error(query.error); } - } - - static async createProfile(profile: Metadata) { + }, + createProfile: async (profile: Metadata) => { const query = await commands.createProfile( profile.name || "", profile.display_name || "", @@ -56,9 +53,8 @@ export class NostrAccount { } else { throw new Error(query.error); } - } - - static async saveAccount(nsec: string, password = "") { + }, + saveAccount: async (nsec: string, password = "") => { const query = await commands.saveAccount(nsec, password); if (query.status === "ok") { @@ -66,9 +62,8 @@ export class NostrAccount { } else { throw new Error(query.error); } - } - - static async connectRemoteAccount(uri: string) { + }, + connectRemoteAccount: async (uri: string) => { const connect = await commands.connectRemoteAccount(uri); if (connect.status === "ok") { @@ -83,9 +78,8 @@ export class NostrAccount { } else { throw new Error(connect.error); } - } - - static async setContactList(pubkeys: string[]) { + }, + setContactList: async (pubkeys: string[]) => { const query = await commands.setContactList(pubkeys); if (query.status === "ok") { @@ -93,9 +87,8 @@ export class NostrAccount { } else { throw new Error(query.error); } - } - - static async loadWallet() { + }, + loadWallet: async () => { const query = await commands.loadWallet(); if (query.status === "ok") { @@ -103,9 +96,8 @@ export class NostrAccount { } else { throw new Error(query.error); } - } - - static async setWallet(uri: string) { + }, + setWallet: async (uri: string) => { const query = await commands.setWallet(uri); if (query.status === "ok") { @@ -113,9 +105,8 @@ export class NostrAccount { } else { throw new Error(query.error); } - } - - static async removeWallet() { + }, + removeWallet: async () => { const query = await commands.removeWallet(); if (query.status === "ok") { @@ -123,9 +114,8 @@ export class NostrAccount { } else { throw new Error(query.error); } - } - - static async getProfile() { + }, + getProfile: async () => { const query = await commands.getCurrentProfile(); if (query.status === "ok") { @@ -133,9 +123,8 @@ export class NostrAccount { } else { return null; } - } - - static async getContactList() { + }, + getContactList: async () => { const query = await commands.getContactList(); if (query.status === "ok") { @@ -143,9 +132,8 @@ export class NostrAccount { } else { return []; } - } - - static async isContactListEmpty() { + }, + isContactListEmpty: async () => { const query = await commands.isContactListEmpty(); if (query.status === "ok") { @@ -153,9 +141,8 @@ export class NostrAccount { } else { return true; } - } - - static async checkContact(pubkey: string) { + }, + checkContact: async (pubkey: string) => { const query = await commands.checkContact(pubkey); if (query.status === "ok") { @@ -163,9 +150,8 @@ export class NostrAccount { } else { throw new Error(query.error); } - } - - static async toggleContact(pubkey: string, alias?: string) { + }, + toggleContact: async (pubkey: string, alias?: string) => { const query = await commands.toggleContact(pubkey, alias); if (query.status === "ok") { @@ -173,9 +159,8 @@ export class NostrAccount { } else { throw new Error(query.error); } - } - - static async f2f(npub: string) { + }, + f2f: async (npub: string) => { const query = await commands.friendToFriend(npub); if (query.status === "ok") { @@ -183,5 +168,5 @@ export class NostrAccount { } else { throw new Error(query.error); } - } -} + }, +}; diff --git a/packages/system/src/query.ts b/packages/system/src/query.ts index bae214cd..faaf1ab6 100644 --- a/packages/system/src/query.ts +++ b/packages/system/src/query.ts @@ -8,26 +8,26 @@ import { nip19 } from "nostr-tools"; import { type Result, type RichEvent, commands } from "./commands"; import { LumeEvent } from "./event"; -export class NostrQuery { - static #toLumeEvents(richEvents: RichEvent[]) { - const events = richEvents.map((item) => { - const nostrEvent: NostrEvent = JSON.parse(item.raw); +function toLumeEvents(richEvents: RichEvent[]) { + const events = richEvents.map((item) => { + const nostrEvent: NostrEvent = JSON.parse(item.raw); - if (item.parsed) { - nostrEvent.meta = item.parsed; - } else { - nostrEvent.meta = null; - } + if (item.parsed) { + nostrEvent.meta = item.parsed; + } else { + nostrEvent.meta = null; + } - const lumeEvent = new LumeEvent(nostrEvent); + const lumeEvent = new LumeEvent(nostrEvent); - return lumeEvent; - }); + return lumeEvent; + }); - return events; - } + return events; +} - static async upload(filePath?: string) { +export const NostrQuery = { + upload: async (filePath?: string) => { const allowExts = [ "png", "jpeg", @@ -80,9 +80,8 @@ export class NostrQuery { } catch (e) { throw new Error(String(e)); } - } - - static async getNotifications() { + }, + getNotifications: async () => { const query = await commands.getNotifications(); if (query.status === "ok") { @@ -94,9 +93,8 @@ export class NostrQuery { console.error(query.error); return []; } - } - - static async getProfile(pubkey: string) { + }, + getProfile: async (pubkey: string) => { const normalize = pubkey.replace("nostr:", "").replace(/[^\w\s]/gi, ""); const query = await commands.getProfile(normalize); @@ -106,9 +104,8 @@ export class NostrQuery { } else { return null; } - } - - static async getEvent(id: string, hint?: string) { + }, + getEvent: async (id: string, hint?: string) => { // Validate ID const normalizeId: string = id .replace("nostr:", "") @@ -150,9 +147,8 @@ export class NostrQuery { console.log("[getEvent]: ", query.error); return null; } - } - - static async getRepostEvent(event: LumeEvent) { + }, + getRepostEvent: async (event: LumeEvent) => { try { const embed: NostrEvent = JSON.parse(event.content); const query = await commands.getEventMeta(embed.content); @@ -181,33 +177,30 @@ export class NostrQuery { return null; } } - } - - static async getUserEvents(pubkey: string, asOf?: number) { + }, + getUserEvents: async (pubkey: string, asOf?: number) => { const until: string = asOf && asOf > 0 ? asOf.toString() : undefined; const query = await commands.getEventsBy(pubkey, until); if (query.status === "ok") { - const data = NostrQuery.#toLumeEvents(query.data); + const data = toLumeEvents(query.data); return data; } else { return []; } - } - - static async getLocalEvents(asOf?: number) { + }, + getLocalEvents: async (asOf?: number) => { const until: string = asOf && asOf > 0 ? asOf.toString() : undefined; const query = await commands.getLocalEvents(until); if (query.status === "ok") { - const data = NostrQuery.#toLumeEvents(query.data); + const data = toLumeEvents(query.data); return data; } else { return []; } - } - - static async listenLocalEvent() { + }, + listenLocalEvent: async () => { const label = getCurrent().label; const query = await commands.listenLocalEvent(label); @@ -216,46 +209,42 @@ export class NostrQuery { } else { throw new Error(query.error); } - } - - static async getGroupEvents(pubkeys: string[], asOf?: number) { + }, + getGroupEvents: async (pubkeys: string[], asOf?: number) => { const until: string = asOf && asOf > 0 ? asOf.toString() : undefined; const query = await commands.getGroupEvents(pubkeys, until); if (query.status === "ok") { - const data = NostrQuery.#toLumeEvents(query.data); + const data = toLumeEvents(query.data); return data; } else { return []; } - } - - static async getGlobalEvents(asOf?: number) { + }, + getGlobalEvents: async (asOf?: number) => { const until: string = asOf && asOf > 0 ? asOf.toString() : undefined; const query = await commands.getGlobalEvents(until); if (query.status === "ok") { - const data = NostrQuery.#toLumeEvents(query.data); + const data = toLumeEvents(query.data); return data; } else { return []; } - } - - static async getHashtagEvents(hashtags: string[], asOf?: number) { + }, + getHashtagEvents: async (hashtags: string[], asOf?: number) => { const until: string = asOf && asOf > 0 ? asOf.toString() : undefined; const nostrTags = hashtags.map((tag) => tag.replace("#", "")); const query = await commands.getHashtagEvents(nostrTags, until); if (query.status === "ok") { - const data = NostrQuery.#toLumeEvents(query.data); + const data = toLumeEvents(query.data); return data; } else { return []; } - } - - static async verifyNip05(pubkey: string, nip05?: string) { + }, + verifyNip05: async (pubkey: string, nip05?: string) => { const query = await commands.verifyNip05(pubkey, nip05); if (query.status === "ok") { @@ -263,9 +252,8 @@ export class NostrQuery { } else { return false; } - } - - static async getNstore(key: string) { + }, + getNstore: async (key: string) => { const query = await commands.getNstore(key); if (query.status === "ok") { @@ -274,9 +262,8 @@ export class NostrQuery { } else { return null; } - } - - static async setNstore(key: string, value: string) { + }, + setNstore: async (key: string, value: string) => { const query = await commands.setNstore(key, value); if (query.status === "ok") { @@ -284,9 +271,8 @@ export class NostrQuery { } else { throw new Error(query.error); } - } - - static async getUserSettings() { + }, + getUserSettings: async () => { const query = await commands.getSettings(); if (query.status === "ok") { @@ -294,9 +280,8 @@ export class NostrQuery { } else { return query.error; } - } - - static async setUserSettings(newSettings: string) { + }, + setUserSettings: async (newSettings: string) => { const query = await commands.setNewSettings(newSettings); if (query.status === "ok") { @@ -304,9 +289,8 @@ export class NostrQuery { } else { return query.error; } - } - - static async getColumns() { + }, + getColumns: async () => { const key = "lume:columns"; const systemPath = "resources/system_columns.json"; const resourcePath = await resolveResource(systemPath); @@ -331,9 +315,8 @@ export class NostrQuery { } catch { return systemColumns; } - } - - static async setColumns(columns: LumeColumn[]) { + }, + setColumns: async (columns: LumeColumn[]) => { const key = "lume:columns"; const content = JSON.stringify(columns); const query = await commands.setNstore(key, content); @@ -343,9 +326,8 @@ export class NostrQuery { } else { throw new Error(query.error); } - } - - static async getRelays() { + }, + getRelays: async () => { const query = await commands.getRelays(); if (query.status === "ok") { @@ -353,9 +335,8 @@ export class NostrQuery { } else { throw new Error(query.error); } - } - - static async connectRelay(url: string) { + }, + connectRelay: async (url: string) => { const relayUrl = new URL(url); if (relayUrl.protocol === "wss:" || relayUrl.protocol === "ws:") { @@ -367,9 +348,8 @@ export class NostrQuery { throw new Error(query.error); } } - } - - static async removeRelay(url: string) { + }, + removeRelay: async (url: string) => { const relayUrl = new URL(url); if (relayUrl.protocol === "wss:" || relayUrl.protocol === "ws:") { @@ -381,9 +361,8 @@ export class NostrQuery { throw new Error(query.error); } } - } - - static async getBootstrapRelays() { + }, + getBootstrapRelays: async () => { const query = await commands.getBootstrapRelays(); if (query.status === "ok") { @@ -401,9 +380,8 @@ export class NostrQuery { } else { return []; } - } - - static async saveBootstrapRelays(relays: Relay[]) { + }, + saveBootstrapRelays: async (relays: Relay[]) => { const text = relays .map((relay) => Object.values(relay).join(",")) .join("\n"); @@ -414,9 +392,8 @@ export class NostrQuery { } else { throw new Error(query.error); } - } - - static async unlisten(id?: string) { + }, + unlisten: async (id?: string) => { const label = id ? id : getCurrent().label; const query = await commands.unlisten(label); @@ -425,5 +402,5 @@ export class NostrQuery { } else { throw new Error(query.error); } - } -} + }, +}; diff --git a/packages/system/src/window.ts b/packages/system/src/window.ts index 18a42669..8be2353b 100644 --- a/packages/system/src/window.ts +++ b/packages/system/src/window.ts @@ -2,13 +2,12 @@ import type { NostrEvent } from "@lume/types"; import { commands } from "./commands"; import type { LumeEvent } from "./event"; -export class LumeWindow { - static async openMainWindow() { +export const LumeWindow = { + openMainWindow: async () => { const query = await commands.openMainWindow(); return query; - } - - static async openEvent(event: NostrEvent | LumeEvent) { + }, + openEvent: async (event: NostrEvent | LumeEvent) => { const eTags = event.tags.filter((tag) => tag[0] === "e" || tag[0] === "q"); const root: string = eTags.find((el) => el[3] === "root")?.[1] ?? eTags[0]?.[1]; @@ -34,9 +33,8 @@ export class LumeWindow { } else { throw new Error(query.error); } - } - - static async openProfile(pubkey: string) { + }, + openProfile: async (pubkey: string) => { const label = `user-${pubkey}`; const query = await commands.openWindow({ label, @@ -54,9 +52,8 @@ export class LumeWindow { } else { throw new Error(query.error); } - } - - static async openEditor(reply_to?: string, quote?: string) { + }, + openEditor: async (reply_to?: string, quote?: string) => { let url: string; if (reply_to) { @@ -88,9 +85,8 @@ export class LumeWindow { } else { throw new Error(query.error); } - } - - static async openZap(id: string) { + }, + openZap: async (id: string) => { const wallet = await commands.loadWallet(); if (wallet.status === "ok") { @@ -107,9 +103,8 @@ export class LumeWindow { } else { await LumeWindow.openSettings("bitcoin-connect"); } - } - - static async openSettings(path?: string) { + }, + openSettings: async (path?: string) => { const label = "settings"; const query = await commands.openWindow({ label, @@ -127,9 +122,8 @@ export class LumeWindow { } else { throw new Error(query.error); } - } - - static async openSearch(searchType: "notes" | "users", searchQuery: string) { + }, + openSearch: async (searchType: "notes" | "users", searchQuery: string) => { const url = `/search/${searchType}?query=${searchQuery}`; const label = `search-${searchQuery .toLowerCase() @@ -153,5 +147,5 @@ export class LumeWindow { } else { throw new Error(query.error); } - } -} + }, +}; diff --git a/src-tauri/tauri.macos.conf.json b/src-tauri/tauri.macos.conf.json index a723829e..695d2201 100644 --- a/src-tauri/tauri.macos.conf.json +++ b/src-tauri/tauri.macos.conf.json @@ -14,8 +14,8 @@ "titleBarStyle": "Overlay", "width": 1045, "height": 800, - "minWidth": 500, - "minHeight": 800, + "minWidth": 480, + "minHeight": 760, "hiddenTitle": true, "windowEffects": { "state": "followsWindowActiveState",