From ff73c8ac889b65de1cd3222afccdf0afb0d4ae36 Mon Sep 17 00:00:00 2001 From: kogeletey Date: Thu, 25 Jan 2024 15:08:24 +0300 Subject: [PATCH] feat: supporting hash of github actions cache --- .github/workflows/flatpak-bundle.yml | 4 +- apps/desktop/package.json | 13 +- apps/desktop/src/app.css | 4 + apps/desktop/src/router.tsx | 24 +- .../src/routes/auth/create-address.tsx | 263 ++++++++++++ apps/desktop/src/routes/auth/create-keys.tsx | 186 +++++++++ apps/desktop/src/routes/auth/create.tsx | 377 +++--------------- apps/desktop/src/routes/auth/login-oauth.tsx | 2 +- apps/desktop/src/routes/auth/login.tsx | 16 +- apps/desktop/src/routes/auth/onboarding.tsx | 35 +- apps/desktop/src/routes/auth/welcome.tsx | 27 +- apps/desktop/src/routes/home/index.tsx | 8 +- apps/desktop/src/routes/settings/backup.tsx | 2 +- apps/desktop/src/routes/settings/profile.tsx | 8 +- apps/web/package.json | 2 +- flatpak/Containerfile | 4 +- package.json | 2 +- packages/ark/package.json | 8 +- packages/ark/src/ark.ts | 2 +- packages/ark/src/components/column/header.tsx | 139 +++---- .../src/components/column/interestModal.tsx | 14 +- packages/ark/src/components/column/live.tsx | 8 +- .../ark/src/components/column/provider.tsx | 5 +- .../ark/src/components/note/buttons/reply.tsx | 6 +- .../src/components/note/buttons/repost.tsx | 6 +- .../ark/src/components/note/buttons/zap.tsx | 21 +- .../ark/src/components/note/mentions/user.tsx | 8 +- packages/ark/src/components/note/menu.tsx | 56 ++- .../ark/src/components/note/preview/image.tsx | 6 +- .../components/note/primitives/childReply.tsx | 2 +- .../src/components/note/primitives/reply.tsx | 2 +- .../src/components/note/primitives/repost.tsx | 2 +- .../src/components/note/primitives/text.tsx | 2 +- packages/ark/src/provider.tsx | 17 +- packages/icons/index.ts | 1 + packages/icons/src/arrowUp.tsx | 24 ++ packages/icons/src/chevronDown.tsx | 2 +- packages/icons/src/chevronUp.tsx | 42 +- packages/icons/src/download.tsx | 42 +- packages/icons/src/logout.tsx | 2 +- packages/icons/src/relay.tsx | 12 +- packages/icons/src/reply.tsx | 14 +- packages/icons/src/user.tsx | 41 +- packages/lume-column-activity/package.json | 26 -- packages/lume-column-activity/src/index.tsx | 0 .../lume-column-activity/tailwind.config.js | 8 - packages/lume-column-activity/tsconfig.json | 8 - packages/lume-column-antenas/package.json | 4 +- packages/lume-column-default/package.json | 4 +- packages/lume-column-default/src/index.tsx | 39 +- packages/lume-column-foryou/package.json | 4 +- packages/lume-column-group/package.json | 4 +- packages/lume-column-hashtag/package.json | 4 +- packages/lume-column-thread/package.json | 4 +- packages/lume-column-timeline/package.json | 4 +- packages/lume-column-timeline/src/index.tsx | 2 +- packages/lume-column-user/package.json | 4 +- packages/ui/package.json | 10 +- packages/ui/src/account/active.tsx | 20 +- packages/ui/src/account/logout.tsx | 4 +- packages/ui/src/editor/form.tsx | 18 +- packages/ui/src/editor/utils.ts | 17 +- packages/ui/src/navigation.tsx | 8 +- packages/ui/src/onboarding/interest.tsx | 5 +- packages/ui/src/onboarding/profile.tsx | 12 +- packages/ui/src/routes/event.tsx | 2 +- packages/ui/src/routes/suggest.tsx | 8 +- packages/ui/src/translateRegisterModal.tsx | 6 +- packages/ui/src/tutorial/manageColumn.tsx | 8 +- packages/ui/src/tutorial/newColumn.tsx | 6 +- packages/utils/package.json | 6 +- pnpm-lock.yaml | 264 ++++++------ src-tauri/tauri.conf.json | 237 +++++------ 73 files changed, 1202 insertions(+), 1005 deletions(-) create mode 100644 apps/desktop/src/routes/auth/create-address.tsx create mode 100644 apps/desktop/src/routes/auth/create-keys.tsx create mode 100644 packages/icons/src/arrowUp.tsx delete mode 100644 packages/lume-column-activity/package.json delete mode 100644 packages/lume-column-activity/src/index.tsx delete mode 100644 packages/lume-column-activity/tailwind.config.js delete mode 100644 packages/lume-column-activity/tsconfig.json diff --git a/.github/workflows/flatpak-bundle.yml b/.github/workflows/flatpak-bundle.yml index 2dbb7565..ea5bea22 100644 --- a/.github/workflows/flatpak-bundle.yml +++ b/.github/workflows/flatpak-bundle.yml @@ -20,7 +20,7 @@ jobs: uses: actions/cache@v3 with: path: prepare-dist - key: ${{ runner.os }}-container + key: ${{ runner.os }}-container-${{ hashFiles('prepare-dist') }} - name: Run latest-tag id: latest-tag uses: oprypin/find-latest-tag@v1 @@ -31,7 +31,7 @@ jobs: # repository: ${{ github.repository }} - name: Build container - if: steps.cache-container.outputs.cache-hit != 'true' + # if: steps.cache-container.outputs.cache-hit != 'true' run: | docker buildx build -t flatpak-prepare-lume --build-arg=${{steps.latest-tag.outputs.tag}} --rm --output=. --target=final -f flatpak/Containerfile . - name: Copy flatpak files content diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 987150aa..785f5cfd 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -25,6 +25,7 @@ "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", @@ -33,9 +34,9 @@ "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tooltip": "^1.0.7", - "@tanstack/react-query": "^5.17.15", + "@tanstack/react-query": "^5.17.19", "framer-motion": "^10.18.0", - "jotai": "^2.6.2", + "jotai": "^2.6.3", "minidenticons": "^4.2.0", "nanoid": "^5.0.4", "nostr-fetch": "^0.15.0", @@ -45,15 +46,15 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.49.3", "react-router-dom": "^6.21.3", - "smol-toml": "^1.1.3", + "smol-toml": "^1.1.4", "sonner": "^1.3.1", - "virtua": "^0.20.5" + "virtua": "^0.21.1" }, "devDependencies": { "@lume/tailwindcss": "workspace:^", "@lume/tsconfig": "workspace:^", "@lume/types": "workspace:^", - "@types/node": "^20.11.5", + "@types/node": "^20.11.6", "@types/react": "^18.2.48", "@types/react-dom": "^18.2.18", "@vitejs/plugin-react-swc": "^3.5.0", @@ -63,7 +64,7 @@ "postcss": "^8.4.33", "tailwindcss": "^3.4.1", "typescript": "^5.3.3", - "vite": "^5.0.11", + "vite": "^5.0.12", "vite-plugin-top-level-await": "^1.4.1", "vite-tsconfig-paths": "^4.3.1" } diff --git a/apps/desktop/src/app.css b/apps/desktop/src/app.css index 3f9426fa..fcc160cb 100644 --- a/apps/desktop/src/app.css +++ b/apps/desktop/src/app.css @@ -12,6 +12,10 @@ .prose :where(iframe):not(:where([class~='not-prose'] *)) { @apply w-full h-auto mx-auto aspect-video; } + + .shadow-toolbar { + box-shadow: 0 0 #0000,0 0 #0000,0 8px 24px 0 rgba(0,0,0,.2),0 2px 8px 0 rgba(0,0,0,.08),inset 0 0 0 1px rgba(0,0,0,.2),inset 0 0 0 2px hsla(0,0%,100%,.14) + } } html { diff --git a/apps/desktop/src/router.tsx b/apps/desktop/src/router.tsx index 3fd3b071..a840b26f 100644 --- a/apps/desktop/src/router.tsx +++ b/apps/desktop/src/router.tsx @@ -207,9 +207,6 @@ export default function Router() { }, { path: "create", - loader: async () => { - return await ark.getOAuthServices(); - }, async lazy() { const { CreateAccountScreen } = await import( "./routes/auth/create" @@ -217,6 +214,27 @@ export default function Router() { return { Component: CreateAccountScreen }; }, }, + { + path: "create-keys", + async lazy() { + const { CreateAccountKeys } = await import( + "./routes/auth/create-keys" + ); + return { Component: CreateAccountKeys }; + }, + }, + { + path: "create-address", + loader: async () => { + return await ark.getOAuthServices(); + }, + async lazy() { + const { CreateAccountAddress } = await import( + "./routes/auth/create-address" + ); + return { Component: CreateAccountAddress }; + }, + }, { path: "login", async lazy() { diff --git a/apps/desktop/src/routes/auth/create-address.tsx b/apps/desktop/src/routes/auth/create-address.tsx new file mode 100644 index 00000000..c99ac938 --- /dev/null +++ b/apps/desktop/src/routes/auth/create-address.tsx @@ -0,0 +1,263 @@ +import { useArk } from "@lume/ark"; +import { CheckIcon, ChevronDownIcon, LoaderIcon } from "@lume/icons"; +import { useStorage } from "@lume/storage"; +import { onboardingAtom } from "@lume/utils"; +import NDK, { + NDKEvent, + NDKKind, + NDKNip46Signer, + NDKPrivateKeySigner, +} from "@nostr-dev-kit/ndk"; +import * as Select from "@radix-ui/react-select"; +import { UnlistenFn } from "@tauri-apps/api/event"; +import { Window } from "@tauri-apps/api/window"; +import { useSetAtom } from "jotai"; +import { useState } from "react"; +import { useForm } from "react-hook-form"; +import { useLoaderData, useNavigate } from "react-router-dom"; +import { toast } from "sonner"; + +const Item = ({ event }: { event: NDKEvent }) => { + const domain = JSON.parse(event.content).nip05.replace("_@", ""); + + return ( + + @{domain} + + + + + ); +}; + +export function CreateAccountAddress() { + const ark = useArk(); + const storage = useStorage(); + const services = useLoaderData() as NDKEvent[]; + const setOnboarding = useSetAtom(onboardingAtom); + const navigate = useNavigate(); + + const [serviceId, setServiceId] = useState(services?.[0]?.id); + const [loading, setIsLoading] = useState(false); + + const { + register, + handleSubmit, + formState: { isValid }, + } = useForm(); + + const getDomainName = (id: string) => { + const event = services.find((ev) => ev.id === id); + return JSON.parse(event.content).nip05.replace("_@", "") as string; + }; + + const onSubmit = async (data: { username: string; email: string }) => { + try { + setIsLoading(true); + + const domain = getDomainName(serviceId); + const service = services.find((ev) => ev.id === serviceId); + + // generate ndk for nsecbunker + const localSigner = NDKPrivateKeySigner.generate(); + const bunker = new NDK({ + explicitRelayUrls: [ + "wss://relay.nsecbunker.com/", + "wss://nostr.vulpem.com/", + ], + }); + await bunker.connect(2000); + + // generate tmp remote singer for create account + const remoteSigner = new NDKNip46Signer( + bunker, + service.pubkey, + localSigner, + ); + + // handle auth url request + let unlisten: UnlistenFn; + let authWindow: Window; + let account: string = undefined; + + remoteSigner.addListener("authUrl", async (authUrl: string) => { + authWindow = new Window(`auth-${serviceId}`, { + url: authUrl, + title: domain, + titleBarStyle: "overlay", + width: 600, + height: 650, + center: true, + closable: false, + }); + unlisten = await authWindow.onCloseRequested(() => { + if (!account) { + setIsLoading(false); + unlisten(); + + return authWindow.close(); + } + }); + }); + + // create new account + account = await remoteSigner.createAccount( + data.username, + domain, + data.email, + ); + + if (!account) { + unlisten(); + setIsLoading(false); + + authWindow.close(); + + return toast.error("Failed to create new account, try again later"); + } + + unlisten(); + authWindow.close(); + + // add account to storage + await storage.createSetting("nsecbunker", "1"); + const newAccount = await storage.createAccount({ + pubkey: account, + privkey: localSigner.privateKey, + }); + ark.account = newAccount; + + // get final signer with newly created account + const finalSigner = new NDKNip46Signer(bunker, account, localSigner); + await finalSigner.blockUntilReady(); + + // update main ndk instance signer + ark.updateNostrSigner({ signer: finalSigner }); + + // remove default nsecbunker profile and contact list + // await ark.createEvent({ kind: NDKKind.Metadata, content: "", tags: [] }); + await ark.createEvent({ kind: NDKKind.Contacts, content: "", tags: [] }); + + setIsLoading(false); + setOnboarding({ open: true, newUser: true }); + + return navigate("/auth/onboarding", { replace: true }); + } catch (e) { + setIsLoading(false); + toast.error(String(e)); + } + }; + + return ( +
+
+
+

+ Let's set up your account on Nostr +

+
+ {!services ? ( +
+ +
+ ) : ( +
+
+
+ +
+
+ + + + @{getDomainName(serviceId)} + + + + + + + + + + Choose a Provider + + {services.map((service) => ( + + ))} + + + + + +
+ + Use to login to Lume and other Nostr apps. You can choose + provider you trust to manage your account + +
+
+
+
+ + +
+ + Use for recover your account if you lose your password + +
+
+
+ +
+
+ )} +
+
+ ); +} diff --git a/apps/desktop/src/routes/auth/create-keys.tsx b/apps/desktop/src/routes/auth/create-keys.tsx new file mode 100644 index 00000000..46cb4347 --- /dev/null +++ b/apps/desktop/src/routes/auth/create-keys.tsx @@ -0,0 +1,186 @@ +import { useArk } from "@lume/ark"; +import { CheckIcon, EyeOffIcon, EyeOnIcon, LoaderIcon } from "@lume/icons"; +import { useStorage } from "@lume/storage"; +import { onboardingAtom } from "@lume/utils"; +import { NDKPrivateKeySigner } from "@nostr-dev-kit/ndk"; +import * as Checkbox from "@radix-ui/react-checkbox"; +import { desktopDir } from "@tauri-apps/api/path"; +import { save } from "@tauri-apps/plugin-dialog"; +import { writeTextFile } from "@tauri-apps/plugin-fs"; +import { useSetAtom } from "jotai"; +import { nanoid } from "nanoid"; +import { getPublicKey, nip19 } from "nostr-tools"; +import { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { toast } from "sonner"; + +export function CreateAccountKeys() { + const ark = useArk(); + const storage = useStorage(); + const setOnboarding = useSetAtom(onboardingAtom); + const navigate = useNavigate(); + + const [key, setKey] = useState(""); + const [loading, setLoading] = useState(false); + const [showKey, setShowKey] = useState(false); + const [confirm, setConfirm] = useState({ c1: false, c2: false, c3: false }); + + const submit = async () => { + try { + setLoading(true); + + const privkey = nip19.decode(key).data as string; + const signer = new NDKPrivateKeySigner(privkey); + const pubkey = getPublicKey(privkey); + + ark.updateNostrSigner({ signer }); + + const downloadPath = await desktopDir(); + const fileName = `nostr_keys_${nanoid(4)}.txt`; + const filePath = await save({ + defaultPath: `${downloadPath}/${fileName}`, + }); + + if (!filePath) { + return toast.info("You need to save account keys before continue."); + } + + await writeTextFile( + filePath, + `Nostr Account\nGenerated by Lume (lume.nu)\n---\nPrivate key: ${key}`, + ); + + const newAccount = await storage.createAccount({ + pubkey: pubkey, + privkey: privkey, + }); + ark.account = newAccount; + + setLoading(false); + setOnboarding({ open: true, newUser: true }); + + return navigate("/auth/onboarding", { replace: true }); + } catch (e) { + setLoading(false); + toast.error(String(e)); + } + }; + + useEffect(() => { + const privkey = NDKPrivateKeySigner.generate().privateKey; + setKey(nip19.nsecEncode(privkey)); + }, []); + + return ( +
+
+
+

+ This is your new Account Key +

+

+ Keep your key in safe place. If you lose this key, you will lose + access to your account. +

+
+
+
+
+ + +
+
+
+ + setConfirm((state) => ({ ...state, c1: !state.c1 })) + } + className="flex size-7 appearance-none items-center justify-center rounded-lg bg-neutral-900 outline-none" + id="confirm1" + > + + + + + +
+
+ + setConfirm((state) => ({ ...state, c2: !state.c2 })) + } + className="flex size-7 appearance-none items-center justify-center rounded-lg bg-neutral-900 outline-none" + id="confirm2" + > + + + + + +
+
+ + setConfirm((state) => ({ ...state, c3: !state.c3 })) + } + className="flex size-7 appearance-none items-center justify-center rounded-lg bg-neutral-900 outline-none" + id="confirm3" + > + + + + + +
+
+
+ +
+
+
+ ); +} diff --git a/apps/desktop/src/routes/auth/create.tsx b/apps/desktop/src/routes/auth/create.tsx index eee72673..c0b5a301 100644 --- a/apps/desktop/src/routes/auth/create.tsx +++ b/apps/desktop/src/routes/auth/create.tsx @@ -1,192 +1,21 @@ -import { useArk } from "@lume/ark"; -import { CheckIcon, ChevronDownIcon, LoaderIcon } from "@lume/icons"; -import { useStorage } from "@lume/storage"; -import { onboardingAtom } from "@lume/utils"; -import NDK, { - NDKEvent, - NDKKind, - NDKNip46Signer, - NDKPrivateKeySigner, -} from "@nostr-dev-kit/ndk"; -import * as Select from "@radix-ui/react-select"; -import { UnlistenFn } from "@tauri-apps/api/event"; -import { desktopDir } from "@tauri-apps/api/path"; -import { Window } from "@tauri-apps/api/window"; -import { save } from "@tauri-apps/plugin-dialog"; -import { writeTextFile } from "@tauri-apps/plugin-fs"; -import { useSetAtom } from "jotai"; -import { nanoid } from "nanoid"; -import { getPublicKey, nip19 } from "nostr-tools"; +import { LoaderIcon } from "@lume/icons"; +import { cn } from "@lume/utils"; import { useState } from "react"; -import { useForm } from "react-hook-form"; -import { useLoaderData, useNavigate } from "react-router-dom"; -import { toast } from "sonner"; - -const Item = ({ event }: { event: NDKEvent }) => { - const domain = JSON.parse(event.content).nip05.replace("_@", ""); - - return ( - - @{domain} - - - - - ); -}; +import { Link, useNavigate } from "react-router-dom"; export function CreateAccountScreen() { - const ark = useArk(); - const storage = useStorage(); - const services = useLoaderData() as NDKEvent[]; - const setOnboarding = useSetAtom(onboardingAtom); const navigate = useNavigate(); - const [serviceId, setServiceId] = useState(services?.[0]?.id); - const [loading, setIsLoading] = useState(false); + const [method, setMethod] = useState<"self" | "managed">("self"); + const [loading, setLoading] = useState(false); - const { - register, - handleSubmit, - formState: { isValid }, - } = useForm(); + const next = () => { + setLoading(true); - const getDomainName = (id: string) => { - const event = services.find((ev) => ev.id === id); - return JSON.parse(event.content).nip05.replace("_@", "") as string; - }; - - const generateNostrKeys = async () => { - const signer = NDKPrivateKeySigner.generate(); - const pubkey = getPublicKey(signer.privateKey); - - const npub = nip19.npubEncode(pubkey); - const nsec = nip19.nsecEncode(signer.privateKey); - - ark.updateNostrSigner({ signer }); - - const downloadPath = await desktopDir(); - const fileName = `nostr_keys_${nanoid(4)}.txt`; - const filePath = await save({ - defaultPath: `${downloadPath}/${fileName}`, - }); - - if (!filePath) { - return toast.info("You need to save account keys before continue."); - } - - await writeTextFile( - filePath, - `Nostr Account\nGenerated by Lume (lume.nu)\n---\nPublic key: ${npub}\nPrivate key: ${nsec}`, - ); - - await storage.createAccount({ - pubkey: pubkey, - privkey: signer.privateKey, - }); - - setOnboarding({ open: true, newUser: true }); - - return navigate("/auth/onboarding", { replace: true }); - }; - - const onSubmit = async (data: { username: string; email: string }) => { - try { - setIsLoading(true); - - const domain = getDomainName(serviceId); - const service = services.find((ev) => ev.id === serviceId); - - // generate ndk for nsecbunker - const localSigner = NDKPrivateKeySigner.generate(); - const bunker = new NDK({ - explicitRelayUrls: [ - "wss://relay.nsecbunker.com/", - "wss://nostr.vulpem.com/", - ], - }); - await bunker.connect(2000); - - // generate tmp remote singer for create account - const remoteSigner = new NDKNip46Signer( - bunker, - service.pubkey, - localSigner, - ); - - // handle auth url request - let unlisten: UnlistenFn; - let authWindow: Window; - let account: string = undefined; - - remoteSigner.addListener("authUrl", async (authUrl: string) => { - authWindow = new Window(`auth-${serviceId}`, { - url: authUrl, - title: domain, - titleBarStyle: "overlay", - width: 600, - height: 650, - center: true, - closable: false, - }); - unlisten = await authWindow.onCloseRequested(() => { - if (!account) { - setIsLoading(false); - unlisten(); - - return authWindow.close(); - } - }); - }); - - // create new account - account = await remoteSigner.createAccount( - data.username, - domain, - data.email, - ); - - if (!account) { - unlisten(); - setIsLoading(false); - - authWindow.close(); - - return toast.error("Failed to create new account, try again later"); - } - - unlisten(); - authWindow.close(); - - // add account to storage - await storage.createSetting("nsecbunker", "1"); - 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); - await finalSigner.blockUntilReady(); - - // update main ndk instance signer - ark.updateNostrSigner({ signer: finalSigner }); - - // remove default nsecbunker profile and contact list - // await ark.createEvent({ kind: NDKKind.Metadata, content: "", tags: [] }); - await ark.createEvent({ kind: NDKKind.Contacts, content: "", tags: [] }); - - setIsLoading(false); - setOnboarding({ open: true, newUser: true }); - - return navigate("/auth/onboarding", { replace: true }); - } catch (e) { - setIsLoading(false); - toast.error(String(e)); + if (method === "self") { + navigate("/auth/create-keys"); + } else { + navigate("/auth/create-address"); } }; @@ -194,148 +23,50 @@ export function CreateAccountScreen() {
-

- Let's get you set up on Nostr. -

+

Let's Get Started

+

+ Choose one of methods below to create your account +

+
+
+ + +
- {!services ? ( -
- -
- ) : ( -
-
-
-
- -
-
- - - - - @{getDomainName(serviceId)} - - - - - - - - - - - Choose a Provider - - {services.map((service) => ( - - ))} - - - - - -
- - Use to login to Lume and other Nostr apps. You can choose - provider you trust to manage your account - -
-
-
-
- - -
- - Use for recover your account if you lose your password - -
-
-
- -
-
-
-
-
-
-
-
-
- - Or manage your own keys - -
-
- - Mostly compatible with other Nostr clients - -
-
- -

- If you are using this option, please make sure keep your keys - in safe place. You{" "} - cannot recover if it - lost, all your data will be{" "} - lost forever. -

-
-
-
- )}
); diff --git a/apps/desktop/src/routes/auth/login-oauth.tsx b/apps/desktop/src/routes/auth/login-oauth.tsx index 87d88496..84591e7d 100644 --- a/apps/desktop/src/routes/auth/login-oauth.tsx +++ b/apps/desktop/src/routes/auth/login-oauth.tsx @@ -130,7 +130,7 @@ export function LoginWithOAuth() {
-

Enter your NIP-05 address

+

Enter your Nostr Address

-

- Continue your experience on Nostr -

+

Welcome back, anon!

@@ -15,13 +13,13 @@ export function LoginScreen() { to="/auth/login-oauth" className="inline-flex items-center justify-center w-full h-12 text-lg font-medium text-white bg-blue-500 rounded-xl hover:bg-blue-600" > - Login with Address + Login with Nostr Address - Login with nsecbunker + Login with nsecBunker
@@ -31,7 +29,7 @@ export function LoginScreen() {
- Or (Not recommended) + Or continue with
@@ -43,8 +41,10 @@ export function LoginScreen() { Login with Private Key

- Lume will store your Private Key in{" "} - OS Secure Storage + Lume will put your Private Key in{" "} + Secure Storage depended + on your OS Platform. It will be secured by Password or Biometric + ID

diff --git a/apps/desktop/src/routes/auth/onboarding.tsx b/apps/desktop/src/routes/auth/onboarding.tsx index 75df18ff..e771f621 100644 --- a/apps/desktop/src/routes/auth/onboarding.tsx +++ b/apps/desktop/src/routes/auth/onboarding.tsx @@ -2,10 +2,7 @@ import { useArk } from "@lume/ark"; import { InfoIcon, LoaderIcon } from "@lume/icons"; import { useStorage } from "@lume/storage"; import { TranslateRegisterModal } from "@lume/ui"; -import { FETCH_LIMIT } from "@lume/utils"; -import { NDKKind } from "@nostr-dev-kit/ndk"; import * as Switch from "@radix-ui/react-switch"; -import { useQueryClient } from "@tanstack/react-query"; import { isPermissionGranted, requestPermission, @@ -17,7 +14,6 @@ import { toast } from "sonner"; export function OnboardingScreen() { const ark = useArk(); const storage = useStorage(); - const queryClient = useQueryClient(); const navigate = useNavigate(); const [loading, setLoading] = useState(false); @@ -61,32 +57,7 @@ export function OnboardingScreen() { // get account contacts await ark.getUserContacts(); - // refetch newsfeed - await queryClient.prefetchInfiniteQuery({ - queryKey: ["timeline-9999"], - initialPageParam: 0, - queryFn: async ({ - signal, - pageParam, - }: { - signal: AbortSignal; - pageParam: number; - }) => { - const events = await ark.getInfiniteEvents({ - filter: { - kinds: [NDKKind.Text, NDKKind.Repost], - authors: ark.account.contacts, - }, - limit: FETCH_LIMIT, - pageParam, - signal, - }); - - return events; - }, - }); - - navigate("/"); + navigate("/", { replace: true }); }; useEffect(() => { @@ -117,7 +88,7 @@ export function OnboardingScreen() { return (
-
+

You're almost ready to use Lume. @@ -194,7 +165,7 @@ export function OnboardingScreen() {

- Not have API ? + Don't have an API key?
diff --git a/apps/desktop/src/routes/auth/welcome.tsx b/apps/desktop/src/routes/auth/welcome.tsx index a9986055..83789082 100644 --- a/apps/desktop/src/routes/auth/welcome.tsx +++ b/apps/desktop/src/routes/auth/welcome.tsx @@ -1,16 +1,6 @@ -import { LoaderIcon } from "@lume/icons"; -import { useState } from "react"; -import { Link, useNavigate } from "react-router-dom"; +import { Link } from "react-router-dom"; export function WelcomeScreen() { - const navigate = useNavigate(); - const [loading, setLoading] = useState(false); - - const gotoCreateAccount = () => { - setLoading(true); - navigate("/auth/create"); - }; - return (
@@ -29,17 +19,12 @@ export function WelcomeScreen() {

- + Join Nostr +
-

+

Before joining Nostr, you can take time to learn more about Nostr{" "} - +

-
+
diff --git a/apps/desktop/src/routes/settings/profile.tsx b/apps/desktop/src/routes/settings/profile.tsx index 82b31d10..00b224c1 100644 --- a/apps/desktop/src/routes/settings/profile.tsx +++ b/apps/desktop/src/routes/settings/profile.tsx @@ -10,6 +10,7 @@ import { NDKKind, NDKUserProfile } from "@nostr-dev-kit/ndk"; import { useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; import { useForm } from "react-hook-form"; +import { toast } from "sonner"; import { AvatarUpload } from "./components/avatarUpload"; import { CoverUpload } from "./components/coverUpload"; @@ -92,6 +93,9 @@ export function ProfileSettingScreen() { return content; }); + // notify + toast.success("You've updated profile successfully."); + // reset state setPicture(null); setBanner(null); @@ -112,7 +116,7 @@ export function ProfileSettingScreen() { className="h-full w-full rounded-t-xl object-cover" /> ) : ( -
+
)}
@@ -236,7 +240,7 @@ export function ProfileSettingScreen() { + + {queryKey?.[0] === "foryou-9998" ? ( + + + + ) : null} + + + + + + + + + + + +
-
- - - - - - - - - - {queryKey?.[0] === "foryou-9998" ? ( - - - - ) : null} - - - - - - - - - - - - - -
-
+ ); } diff --git a/packages/ark/src/components/column/interestModal.tsx b/packages/ark/src/components/column/interestModal.tsx index b9f29441..66e9a583 100644 --- a/packages/ark/src/components/column/interestModal.tsx +++ b/packages/ark/src/components/column/interestModal.tsx @@ -40,7 +40,7 @@ export function InterestModal({ ); if (save) { - storage.interests.hashtags = hashtags; + storage.interests = { hashtags, users: [], words: [] }; await queryClient.refetchQueries({ queryKey }); } @@ -56,7 +56,7 @@ export function InterestModal({ @@ -64,7 +64,7 @@ export function InterestModal({ children ) : ( <> - + Edit interest )} @@ -86,11 +86,8 @@ export function InterestModal({
- {TOPICS.map((topic, index) => ( -
+ {TOPICS.map((topic) => ( +
{topic.content.map((hashtag) => (
); diff --git a/packages/ark/src/components/column/provider.tsx b/packages/ark/src/components/column/provider.tsx index 2136a7bf..9ce8ee35 100644 --- a/packages/ark/src/components/column/provider.tsx +++ b/packages/ark/src/components/column/provider.tsx @@ -55,7 +55,10 @@ export function ColumnProvider({ children }: { children: ReactNode }) { column.title, column.content, ); - if (result) setColumns((prev) => [...prev, result]); + if (result) { + setColumns((prev) => [...prev, result]); + vlistRef?.current.scrollToIndex(columns.length); + } }, []); const removeColumn = useCallback(async (id: number) => { diff --git a/packages/ark/src/components/note/buttons/reply.tsx b/packages/ark/src/components/note/buttons/reply.tsx index fcfebaf9..26b1d7e7 100644 --- a/packages/ark/src/components/note/buttons/reply.tsx +++ b/packages/ark/src/components/note/buttons/reply.tsx @@ -1,4 +1,4 @@ -import { ChatsIcon } from "@lume/icons"; +import { ReplyIcon } from "@lume/icons"; import * as Tooltip from "@radix-ui/react-tooltip"; import { useNavigate } from "react-router-dom"; import { useNoteContext } from "../provider"; @@ -16,12 +16,12 @@ export function NoteReply() { onClick={() => navigate(`/events/${event.id}`)} className="inline-flex items-center justify-center group h-7 w-7 text-neutral-600 dark:text-neutral-400" > - + - Quick reply + View thread diff --git a/packages/ark/src/components/note/buttons/repost.tsx b/packages/ark/src/components/note/buttons/repost.tsx index a4f6065d..8f5218a9 100644 --- a/packages/ark/src/components/note/buttons/repost.tsx +++ b/packages/ark/src/components/note/buttons/repost.tsx @@ -88,12 +88,12 @@ export function NoteRepost() { - + diff --git a/packages/ark/src/components/note/menu.tsx b/packages/ark/src/components/note/menu.tsx index 8564ba45..5f7fd79f 100644 --- a/packages/ark/src/components/note/menu.tsx +++ b/packages/ark/src/components/note/menu.tsx @@ -1,15 +1,19 @@ import { HorizontalDotsIcon } from "@lume/icons"; +import { COL_TYPES } from "@lume/utils"; import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; import { writeText } from "@tauri-apps/plugin-clipboard-manager"; import { nip19 } from "nostr-tools"; import { type EventPointer } from "nostr-tools/lib/types/nip19"; import { useState } from "react"; -import { Link } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom"; import { toast } from "sonner"; +import { useColumnContext } from "../column/provider"; import { useNoteContext } from "./provider"; export function NoteMenu() { const event = useNoteContext(); + const navigate = useNavigate(); + const { addColumn } = useColumnContext(); const [open, setOpen] = useState(false); const copyID = async () => { @@ -50,18 +54,27 @@ export function NoteMenu() { - + + + + @@ -70,34 +83,49 @@ export function NoteMenu() { - View profile + View author - + + + + @@ -106,7 +134,7 @@ export function NoteMenu() { diff --git a/packages/ark/src/components/note/preview/image.tsx b/packages/ark/src/components/note/preview/image.tsx index abb5d1ae..883ac33c 100644 --- a/packages/ark/src/components/note/preview/image.tsx +++ b/packages/ark/src/components/note/preview/image.tsx @@ -48,12 +48,12 @@ export function ImagePreview({ url }: { url: string }) {
diff --git a/packages/ark/src/components/note/primitives/childReply.tsx b/packages/ark/src/components/note/primitives/childReply.tsx index 850c0a6b..4ecfc9a8 100644 --- a/packages/ark/src/components/note/primitives/childReply.tsx +++ b/packages/ark/src/components/note/primitives/childReply.tsx @@ -8,7 +8,7 @@ export function ChildReply({
- +
diff --git a/packages/ark/src/components/note/primitives/reply.tsx b/packages/ark/src/components/note/primitives/reply.tsx index 0ff655db..a1b5e461 100644 --- a/packages/ark/src/components/note/primitives/reply.tsx +++ b/packages/ark/src/components/note/primitives/reply.tsx @@ -18,7 +18,7 @@ export function Reply({
- +
diff --git a/packages/ark/src/components/note/primitives/repost.tsx b/packages/ark/src/components/note/primitives/repost.tsx index 041e23cc..4d95a018 100644 --- a/packages/ark/src/components/note/primitives/repost.tsx +++ b/packages/ark/src/components/note/primitives/repost.tsx @@ -93,7 +93,7 @@ export function RepostNote({
- +
diff --git a/packages/ark/src/components/note/primitives/text.tsx b/packages/ark/src/components/note/primitives/text.tsx index 75ae3ead..88b41db5 100644 --- a/packages/ark/src/components/note/primitives/text.tsx +++ b/packages/ark/src/components/note/primitives/text.tsx @@ -15,7 +15,7 @@ export function TextNote({ )} >
- +
diff --git a/packages/ark/src/provider.tsx b/packages/ark/src/provider.tsx index 0ef02734..24817ce9 100644 --- a/packages/ark/src/provider.tsx +++ b/packages/ark/src/provider.tsx @@ -87,31 +87,18 @@ export const LumeProvider = ({ children }: PropsWithChildren) => { async function initNDK() { const explicitRelayUrls = normalizeRelayUrlSet([ + "wss://nostr.mutinywallet.com/", "wss://bostr.nokotaro.com/", ]); - // #TODO: user should config outbox relays - const outboxRelayUrls = normalizeRelayUrlSet(["wss://purplepag.es/"]); - - // #TODO: user should config blacklist relays - // Skip connect depot tunnel url - const blacklistRelayUrls = normalizeRelayUrlSet( - storage.settings.tunnelUrl.length - ? [storage.settings.tunnelUrl, "wss://brb.io/"] - : ["wss://brb.io/"], - ); - const tauriCache = new NDKCacheAdapterTauri(storage); const ndk = new NDK({ cacheAdapter: tauriCache, explicitRelayUrls, - outboxRelayUrls, - blacklistRelayUrls, enableOutboxModel: !storage.settings.lowPower, autoConnectUserRelays: !storage.settings.lowPower, autoFetchUserMutelist: !storage.settings.lowPower, - // clientName: "Lume", - // clientNip89: '', + clientName: "Lume", }); // use tauri fetch diff --git a/packages/icons/index.ts b/packages/icons/index.ts index ee2e00a1..96c9d564 100644 --- a/packages/icons/index.ts +++ b/packages/icons/index.ts @@ -111,3 +111,4 @@ export * from "./src/foryou"; export * from "./src/editInterest"; export * from "./src/newColumn"; export * from "./src/searchFilled"; +export * from "./src/arrowUp"; diff --git a/packages/icons/src/arrowUp.tsx b/packages/icons/src/arrowUp.tsx new file mode 100644 index 00000000..b4f26528 --- /dev/null +++ b/packages/icons/src/arrowUp.tsx @@ -0,0 +1,24 @@ +import { SVGProps } from "react"; + +export function ArrowUpIcon( + props: JSX.IntrinsicAttributes & SVGProps, +) { + return ( + + + + ); +} diff --git a/packages/icons/src/chevronDown.tsx b/packages/icons/src/chevronDown.tsx index 9311f52d..b4d13eea 100644 --- a/packages/icons/src/chevronDown.tsx +++ b/packages/icons/src/chevronDown.tsx @@ -17,7 +17,7 @@ export function ChevronDownIcon( strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" - d="M8 10.14a20.36 20.36 0 003.702 3.893c.175.141.42.141.596 0A20.361 20.361 0 0016 10.14" + d="M6 9a30.618 30.618 0 005.49 5.817c.3.244.72.244 1.02 0A30.617 30.617 0 0018 9" /> ); diff --git a/packages/icons/src/chevronUp.tsx b/packages/icons/src/chevronUp.tsx index d8144fb6..4caceb20 100644 --- a/packages/icons/src/chevronUp.tsx +++ b/packages/icons/src/chevronUp.tsx @@ -1,22 +1,24 @@ -import { SVGProps } from 'react'; +import { SVGProps } from "react"; -export function ChevronUpIcon(props: JSX.IntrinsicAttributes & SVGProps) { - return ( - - - - ); +export function ChevronUpIcon( + props: JSX.IntrinsicAttributes & SVGProps, +) { + return ( + + + + ); } diff --git a/packages/icons/src/download.tsx b/packages/icons/src/download.tsx index e8d39fee..2c676e64 100644 --- a/packages/icons/src/download.tsx +++ b/packages/icons/src/download.tsx @@ -1,22 +1,24 @@ -import { SVGProps } from 'react'; +import { SVGProps } from "react"; -export function DownloadIcon(props: JSX.IntrinsicAttributes & SVGProps) { - return ( - - - - ); +export function DownloadIcon( + props: JSX.IntrinsicAttributes & SVGProps, +) { + return ( + + + + ); } diff --git a/packages/icons/src/logout.tsx b/packages/icons/src/logout.tsx index 0ea480b7..da92eab0 100644 --- a/packages/icons/src/logout.tsx +++ b/packages/icons/src/logout.tsx @@ -17,7 +17,7 @@ export function LogoutIcon( strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" - d="M18.189 9a15 15 0 012.654 2.556c.105.13.157.287.157.444m-2.811 3a14.998 14.998 0 002.654-2.556A.704.704 0 0021 12m0 0H8m5-7.472A6 6 0 003 9v6a6 6 0 0010 4.472" + d="M5.812 9a15.001 15.001 0 00-2.655 2.556A.703.703 0 003 12m2.812 3a15 15 0 01-2.655-2.556A.703.703 0 013 12m0 0h13m-5-7.472A6 6 0 0121 9v6a6 6 0 01-10 4.472" /> ); diff --git a/packages/icons/src/relay.tsx b/packages/icons/src/relay.tsx index b2b22d40..0e5b070f 100644 --- a/packages/icons/src/relay.tsx +++ b/packages/icons/src/relay.tsx @@ -6,13 +6,15 @@ export function RelayIcon(props: JSX.IntrinsicElements["svg"]) { height="24" fill="none" viewBox="0 0 25 24" - stroke="currentColor" - strokeLinecap="round" - strokeLinejoin="round" - strokeWidth="2" {...props} > - + ); } diff --git a/packages/icons/src/reply.tsx b/packages/icons/src/reply.tsx index 58542430..19029885 100644 --- a/packages/icons/src/reply.tsx +++ b/packages/icons/src/reply.tsx @@ -1,18 +1,20 @@ export function ReplyIcon(props: JSX.IntrinsicElements["svg"]) { return ( - + ); } diff --git a/packages/icons/src/user.tsx b/packages/icons/src/user.tsx index 7bb9eb67..1295d333 100644 --- a/packages/icons/src/user.tsx +++ b/packages/icons/src/user.tsx @@ -1,21 +1,24 @@ -import { SVGProps } from 'react'; +import { SVGProps } from "react"; -export function UserIcon(props: JSX.IntrinsicAttributes & SVGProps) { - return ( - - - - ); +export function UserIcon( + props: JSX.IntrinsicAttributes & SVGProps, +) { + return ( + + + + ); } diff --git a/packages/lume-column-activity/package.json b/packages/lume-column-activity/package.json deleted file mode 100644 index 494dd569..00000000 --- a/packages/lume-column-activity/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "@columns/activity", - "version": "0.0.0", - "private": true, - "main": "./src/index.tsx", - "dependencies": { - "@lume/ark": "workspace:^", - "@lume/icons": "workspace:^", - "@lume/ui": "workspace:^", - "@lume/utils": "workspace:^", - "@nostr-dev-kit/ndk": "^2.3.3", - "@tanstack/react-query": "^5.17.15", - "react": "^18.2.0", - "react-router-dom": "^6.21.3", - "sonner": "^1.3.1", - "virtua": "^0.20.5" - }, - "devDependencies": { - "@lume/tailwindcss": "workspace:^", - "@lume/tsconfig": "workspace:^", - "@lume/types": "workspace:^", - "@types/react": "^18.2.48", - "tailwind": "^4.0.0", - "typescript": "^5.3.3" - } -} diff --git a/packages/lume-column-activity/src/index.tsx b/packages/lume-column-activity/src/index.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/lume-column-activity/tailwind.config.js b/packages/lume-column-activity/tailwind.config.js deleted file mode 100644 index 49c48c7a..00000000 --- a/packages/lume-column-activity/tailwind.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import sharedConfig from "@lume/tailwindcss"; - -const config = { - content: ["./src/**/*.{js,ts,jsx,tsx}"], - presets: [sharedConfig], -}; - -export default config; diff --git a/packages/lume-column-activity/tsconfig.json b/packages/lume-column-activity/tsconfig.json deleted file mode 100644 index 34a32891..00000000 --- a/packages/lume-column-activity/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "@lume/tsconfig/base.json", - "compilerOptions": { - "outDir": "dist" - }, - "include": ["src"], - "exclude": ["node_modules", "dist"] -} diff --git a/packages/lume-column-antenas/package.json b/packages/lume-column-antenas/package.json index b6df08f0..004d23e2 100644 --- a/packages/lume-column-antenas/package.json +++ b/packages/lume-column-antenas/package.json @@ -9,11 +9,11 @@ "@lume/ui": "workspace:^", "@lume/utils": "workspace:^", "@nostr-dev-kit/ndk": "^2.3.3", - "@tanstack/react-query": "^5.17.15", + "@tanstack/react-query": "^5.17.19", "react": "^18.2.0", "react-router-dom": "^6.21.3", "sonner": "^1.3.1", - "virtua": "^0.20.5" + "virtua": "^0.21.1" }, "devDependencies": { "@lume/tailwindcss": "workspace:^", diff --git a/packages/lume-column-default/package.json b/packages/lume-column-default/package.json index 0ebd7308..ba6475eb 100644 --- a/packages/lume-column-default/package.json +++ b/packages/lume-column-default/package.json @@ -9,11 +9,11 @@ "@lume/ui": "workspace:^", "@lume/utils": "workspace:^", "@nostr-dev-kit/ndk": "^2.3.3", - "@tanstack/react-query": "^5.17.15", + "@tanstack/react-query": "^5.17.19", "react": "^18.2.0", "react-router-dom": "^6.21.3", "sonner": "^1.3.1", - "virtua": "^0.20.5" + "virtua": "^0.21.1" }, "devDependencies": { "@lume/tailwindcss": "workspace:^", diff --git a/packages/lume-column-default/src/index.tsx b/packages/lume-column-default/src/index.tsx index a55885ab..728aa267 100644 --- a/packages/lume-column-default/src/index.tsx +++ b/packages/lume-column-default/src/index.tsx @@ -14,19 +14,36 @@ export function Default({ column }: { column: IColumn }) { icon={} />
-
-
+
+ + +
+
+
group
-
+

Group Feeds

-

+

Collective of people you're interested in.

@@ -41,19 +58,21 @@ export function Default({ column }: { column: IColumn }) {
-
-
+
+
antenas
-
+

Antenas

-

+

Keep track to specific content.

diff --git a/packages/lume-column-foryou/package.json b/packages/lume-column-foryou/package.json index bec98934..2a984532 100644 --- a/packages/lume-column-foryou/package.json +++ b/packages/lume-column-foryou/package.json @@ -10,11 +10,11 @@ "@lume/ui": "workspace:^", "@lume/utils": "workspace:^", "@nostr-dev-kit/ndk": "^2.3.3", - "@tanstack/react-query": "^5.17.15", + "@tanstack/react-query": "^5.17.19", "react": "^18.2.0", "react-router-dom": "^6.21.3", "sonner": "^1.3.1", - "virtua": "^0.20.5" + "virtua": "^0.21.1" }, "devDependencies": { "@lume/tailwindcss": "workspace:^", diff --git a/packages/lume-column-group/package.json b/packages/lume-column-group/package.json index bc77a8e8..83007f1e 100644 --- a/packages/lume-column-group/package.json +++ b/packages/lume-column-group/package.json @@ -9,11 +9,11 @@ "@lume/ui": "workspace:^", "@lume/utils": "workspace:^", "@nostr-dev-kit/ndk": "^2.3.3", - "@tanstack/react-query": "^5.17.15", + "@tanstack/react-query": "^5.17.19", "react": "^18.2.0", "react-router-dom": "^6.21.3", "sonner": "^1.3.1", - "virtua": "^0.20.5" + "virtua": "^0.21.1" }, "devDependencies": { "@lume/tailwindcss": "workspace:^", diff --git a/packages/lume-column-hashtag/package.json b/packages/lume-column-hashtag/package.json index 308a1e6a..811f5c15 100644 --- a/packages/lume-column-hashtag/package.json +++ b/packages/lume-column-hashtag/package.json @@ -9,11 +9,11 @@ "@lume/ui": "workspace:^", "@lume/utils": "workspace:^", "@nostr-dev-kit/ndk": "^2.3.3", - "@tanstack/react-query": "^5.17.15", + "@tanstack/react-query": "^5.17.19", "react": "^18.2.0", "react-router-dom": "^6.21.3", "sonner": "^1.3.1", - "virtua": "^0.20.5" + "virtua": "^0.21.1" }, "devDependencies": { "@lume/tailwindcss": "workspace:^", diff --git a/packages/lume-column-thread/package.json b/packages/lume-column-thread/package.json index 6d97ed53..f24df25a 100644 --- a/packages/lume-column-thread/package.json +++ b/packages/lume-column-thread/package.json @@ -9,11 +9,11 @@ "@lume/ui": "workspace:^", "@lume/utils": "workspace:^", "@nostr-dev-kit/ndk": "^2.3.3", - "@tanstack/react-query": "^5.17.15", + "@tanstack/react-query": "^5.17.19", "react": "^18.2.0", "react-router-dom": "^6.21.3", "sonner": "^1.3.1", - "virtua": "^0.20.5" + "virtua": "^0.21.1" }, "devDependencies": { "@lume/tailwindcss": "workspace:^", diff --git a/packages/lume-column-timeline/package.json b/packages/lume-column-timeline/package.json index 1140abc4..06043caf 100644 --- a/packages/lume-column-timeline/package.json +++ b/packages/lume-column-timeline/package.json @@ -9,11 +9,11 @@ "@lume/ui": "workspace:^", "@lume/utils": "workspace:^", "@nostr-dev-kit/ndk": "^2.3.3", - "@tanstack/react-query": "^5.17.15", + "@tanstack/react-query": "^5.17.19", "react": "^18.2.0", "react-router-dom": "^6.21.3", "sonner": "^1.3.1", - "virtua": "^0.20.5" + "virtua": "^0.21.1" }, "devDependencies": { "@lume/tailwindcss": "workspace:^", diff --git a/packages/lume-column-timeline/src/index.tsx b/packages/lume-column-timeline/src/index.tsx index 1cc4c821..87946a02 100644 --- a/packages/lume-column-timeline/src/index.tsx +++ b/packages/lume-column-timeline/src/index.tsx @@ -30,7 +30,7 @@ export function Timeline({ column }: { column: IColumn }) { id={column.id} queryKey={[colKey]} title="Timeline" - icon={} + icon={} /> {ark.account.contacts.length ? ( - + + Edit profile + + + + + Settings + diff --git a/packages/ui/src/account/logout.tsx b/packages/ui/src/account/logout.tsx index 964e3daf..0b06132b 100644 --- a/packages/ui/src/account/logout.tsx +++ b/packages/ui/src/account/logout.tsx @@ -35,9 +35,9 @@ export function Logout() { diff --git a/packages/ui/src/editor/form.tsx b/packages/ui/src/editor/form.tsx index 5233e9d7..91c4d272 100644 --- a/packages/ui/src/editor/form.tsx +++ b/packages/ui/src/editor/form.tsx @@ -106,7 +106,7 @@ const Image = ({ attributes, children, element }) => { return (
{children} -
+
{element.url} {
Transforms.removeNodes(editor, { at: path })} - className="relative user-select-none" + className="relative user-select-none my-2" > -
+
-

- New Post -

+

New Post

@@ -346,7 +344,7 @@ export function EditorForm() {
{filters.map((contact, i) => ( - // biome-ignore lint/a11y/useKeyWithClickEvents: -
{ Transforms.select(editor, target); insertMention(editor, contact); @@ -379,7 +377,7 @@ export function EditorForm() {
-
+ ))}
diff --git a/packages/ui/src/editor/utils.ts b/packages/ui/src/editor/utils.ts index 8c9f7164..66bf33ee 100644 --- a/packages/ui/src/editor/utils.ts +++ b/packages/ui/src/editor/utils.ts @@ -2,7 +2,7 @@ import { NDKCacheUserProfile } from "@lume/types"; import { ReactNode } from "react"; import ReactDOM from "react-dom"; import { BaseEditor, Transforms } from "slate"; -import { type ReactEditor } from "slate-react"; +import { ReactEditor } from "slate-react"; export const Portal = ({ children }: { children?: ReactNode }) => { return typeof document === "object" @@ -36,6 +36,8 @@ export const insertImage = (editor: ReactEditor | BaseEditor, url: string) => { }, ]; + // @ts-ignore, idk + ReactEditor.focus(editor); Transforms.insertNodes(editor, image); Transforms.insertNodes(editor, extraText); }; @@ -44,15 +46,24 @@ export const insertMention = ( editor: ReactEditor | BaseEditor, contact: NDKCacheUserProfile, ) => { + const text = { text: "" }; const mention = { type: "mention", npub: `nostr:${contact.npub}`, name: contact.name || contact.displayName || "anon", - children: [{ text: "" }], + children: [text], }; + const extraText = [ + { + type: "paragraph", + children: [text], + }, + ]; + // @ts-ignore, idk + ReactEditor.focus(editor); Transforms.insertNodes(editor, mention); - Transforms.move(editor); + Transforms.insertNodes(editor, extraText); }; export const insertNostrEvent = ( diff --git a/packages/ui/src/navigation.tsx b/packages/ui/src/navigation.tsx index 86e81401..b89d0eea 100644 --- a/packages/ui/src/navigation.tsx +++ b/packages/ui/src/navigation.tsx @@ -2,11 +2,11 @@ import { BellFilledIcon, BellIcon, ComposeFilledIcon, - ComposeIcon, DepotFilledIcon, DepotIcon, HomeFilledIcon, HomeIcon, + PlusIcon, SearchFilledIcon, SearchIcon, SettingsFilledIcon, @@ -44,11 +44,7 @@ export function Navigation() { : "bg-black/5 hover:bg-blue-500 dark:bg-white/5 dark:hover:bg-blue-500", )} > - {isEditorOpen ? ( - - ) : ( - - )} +
diff --git a/packages/ui/src/onboarding/interest.tsx b/packages/ui/src/onboarding/interest.tsx index d7542c03..95bc1296 100644 --- a/packages/ui/src/onboarding/interest.tsx +++ b/packages/ui/src/onboarding/interest.tsx @@ -57,8 +57,8 @@ export function OnboardingInterestScreen() {
- {TOPICS.map((topic, index) => ( -
+ {TOPICS.map((topic) => ( +
{topic.content.map((hashtag) => (
diff --git a/packages/ui/src/translateRegisterModal.tsx b/packages/ui/src/translateRegisterModal.tsx index 883f05b1..e114cd8e 100644 --- a/packages/ui/src/translateRegisterModal.tsx +++ b/packages/ui/src/translateRegisterModal.tsx @@ -68,9 +68,9 @@ export function TranslateRegisterModal({ setAPIKey }) {

- Translate Service is provided by{" "} - nostr.wine, you need to - deposit at least 2,500 sats to use translate 50,000 characters + Translation Service is provided by{" "} + nostr.wine. Prices + start at 2,500 sats for 50,000 characters of translated text.

You can learn more about nostr.wine{" "} diff --git a/packages/ui/src/tutorial/manageColumn.tsx b/packages/ui/src/tutorial/manageColumn.tsx index 7a9320fa..111b9dcb 100644 --- a/packages/ui/src/tutorial/manageColumn.tsx +++ b/packages/ui/src/tutorial/manageColumn.tsx @@ -5,13 +5,9 @@ export function TutorialManageColumnScreen() {

- Lume is also provide simple way to customize column after creation. + Once a new column is created, you can click on the title in its header + to find options to customize it

-

- To customize each column, you - can go to header of each column -

-

Click to "Three Dots" icon

tutorial-3
-

Lume is column based, each column is each experience

+

Lume is column based, each column is its own experience.

- To create new column, you can - look into bottom right part of screen + To create a new column, you can + click on the "Plus" icon at bottom right corner of this window.

Click to "Plus" icon

= 0.6'} @@ -3649,31 +3632,31 @@ packages: resolution: {integrity: sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w==} dev: true - /astro-seo-meta@4.1.0(astro@4.2.1): + /astro-seo-meta@4.1.0(astro@4.2.4): resolution: {integrity: sha512-v5qULt/c2hp9u6JtRyZeWTeb6YC82XDMzVcEf7XlRSuvs3C6KUQxeIOp5j+uOIek42CZHcyhbWzQF+FoRbQlfg==} peerDependencies: astro: ^4.0.0 dependencies: - astro: 4.2.1(typescript@5.3.3) + astro: 4.2.4(typescript@5.3.3) dev: false - /astro-seo-schema@4.0.0(astro@4.2.1)(schema-dts@1.1.2): + /astro-seo-schema@4.0.0(astro@4.2.4)(schema-dts@1.1.2): resolution: {integrity: sha512-ZcpxuQWSlyOVru+sN5LwUHqfrQpOEyv6Ksxq6WBNhycEHE0AEgGdiHkfhAmQbVqT4HXM8bmZOZlYlwwsYkfPAw==} peerDependencies: astro: ^4.0.0 schema-dts: ^1.1.0 dependencies: - astro: 4.2.1(typescript@5.3.3) + astro: 4.2.4(typescript@5.3.3) schema-dts: 1.1.2(typescript@5.3.3) dev: false - /astro@4.2.1(typescript@5.3.3): - resolution: {integrity: sha512-TcrveW2/lohmljrbTUgcDxajEdF1yK+zBvb7SXroloGix/d4jkegO6GANFgvyy0zprMyajW7qgJEFyhWUX86Vw==} + /astro@4.2.4(typescript@5.3.3): + resolution: {integrity: sha512-z1f52lXkHf71M5HSLKrd5G1PH5/Zfq4kMp0iUT7Na5VHcPDma/NYFPFPewDxqV6UPmyxupj3xuooFaN3j8zaow==} engines: {node: '>=18.14.1', npm: '>=6.14.0'} dependencies: - '@astrojs/compiler': 2.5.0 + '@astrojs/compiler': 2.5.1 '@astrojs/internal-helpers': 0.2.1 - '@astrojs/markdown-remark': 4.1.0 + '@astrojs/markdown-remark': 4.2.0 '@astrojs/telemetry': 3.0.4 '@babel/core': 7.23.7 '@babel/generator': 7.23.6 @@ -3724,7 +3707,7 @@ packages: semver: 7.5.4 server-destroy: 1.0.1 shikiji: 0.9.19 - string-width: 7.0.0 + string-width: 7.1.0 strip-ansi: 7.1.0 tsconfck: 3.0.1(typescript@5.3.3) unist-util-visit: 5.0.0 @@ -3899,7 +3882,7 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} dependencies: caniuse-lite: 1.0.30001579 - electron-to-chromium: 1.4.644 + electron-to-chromium: 1.4.645 node-releases: 2.0.14 update-browserslist-db: 1.0.13(browserslist@4.22.2) @@ -4090,6 +4073,7 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + requiresBuild: true /color-string@1.9.1: resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} @@ -4417,8 +4401,8 @@ packages: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: true - /electron-to-chromium@1.4.644: - resolution: {integrity: sha512-zOnPndwz3u1sVFSyBcRWcn0529Kz+jr+tDxN9iP69I3CpC5wlvYmjLrK2O7TEsg2oDDoUqooeXqbiHLvXvl6Lg==} + /electron-to-chromium@1.4.645: + resolution: {integrity: sha512-EeS1oQDCmnYsRDRy2zTeC336a/4LZ6WKqvSaM1jLocEk5ZuyszkQtCpsqvuvaIXGOUjwtvF6LTcS8WueibXvSw==} /emmet@2.4.6: resolution: {integrity: sha512-dJfbdY/hfeTyf/Ef7Y7ubLYzkBvPQ912wPaeVYpAxvFxkEBf/+hJu4H6vhAvFN6HlxqedlfVn2x1S44FfQ97pg==} @@ -5206,6 +5190,14 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 + dev: true + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} @@ -6319,7 +6311,7 @@ packages: engines: {node: '>= 4.4.x'} dependencies: debug: 3.2.7 - iconv-lite: 0.4.23 + iconv-lite: 0.4.24 sax: 1.3.0 transitivePeerDependencies: - supports-color @@ -7649,8 +7641,8 @@ packages: strip-ansi: 7.1.0 dev: false - /string-width@7.0.0: - resolution: {integrity: sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==} + /string-width@7.1.0: + resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} engines: {node: '>=18'} dependencies: emoji-regex: 10.3.0 @@ -8455,8 +8447,8 @@ packages: vfile-message: 4.0.2 dev: false - /virtua@0.20.5(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-GHL+kSTotf5L1x3/Wcir0KkNKxmQIdWiDrcrBNz+DMiLUdNtskKs+E76Z0SSeeL0+I/PFutBrI8fXw/j7N+6sQ==} + /virtua@0.21.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-6CRxablXTLvnFHIIXKRgcxn0oVoXjKQRxchXzx8sWywg+DtQ7wHZBSrJ6WTN3YzXOLP9ZJt4zs5SmsaCTQbUhA==} peerDependencies: react: '>=16.14.0' react-dom: '>=16.14.0' @@ -8558,7 +8550,7 @@ packages: optional: true dependencies: '@volar/language-service': 1.11.1 - vscode-css-languageservice: 6.2.11 + vscode-css-languageservice: 6.2.12 vscode-uri: 3.0.8 dev: false @@ -8584,7 +8576,7 @@ packages: optional: true dependencies: '@volar/language-service': 1.11.1 - vscode-html-languageservice: 5.1.1 + vscode-html-languageservice: 5.1.2 vscode-uri: 3.0.8 dev: false @@ -8632,19 +8624,19 @@ packages: vscode-uri: 3.0.8 dev: false - /vscode-css-languageservice@6.2.11: - resolution: {integrity: sha512-qn49Wa6K94LnizpVxmlYrcPf1Cb36gq1nNueW0COhi4shylXBzET5wuDbH8ZWQlJD0HM5Mmnn7WE9vQVVs+ULA==} + /vscode-css-languageservice@6.2.12: + resolution: {integrity: sha512-PS9r7HgNjqzRl3v91sXpCyZPc8UDotNo6gntFNtGCKPhGA9Frk7g/VjX1Mbv3F00pn56D+rxrFzR9ep4cawOgA==} dependencies: - '@vscode/l10n': 0.0.16 + '@vscode/l10n': 0.0.18 vscode-languageserver-textdocument: 1.0.11 vscode-languageserver-types: 3.17.5 vscode-uri: 3.0.8 dev: false - /vscode-html-languageservice@5.1.1: - resolution: {integrity: sha512-JenrspIIG/Q+93R6G3L6HdK96itSisMynE0glURqHpQbL3dKAKzdm8L40lAHNkwJeBg+BBPpAshZKv/38onrTQ==} + /vscode-html-languageservice@5.1.2: + resolution: {integrity: sha512-wkWfEx/IIR3s2P5yD4aTGHiOb8IAzFxgkSt1uSC3itJ4oDAm23yG7o0L29JljUdnXDDgLafPAvhv8A2I/8riHw==} dependencies: - '@vscode/l10n': 0.0.16 + '@vscode/l10n': 0.0.18 vscode-languageserver-textdocument: 1.0.11 vscode-languageserver-types: 3.17.5 vscode-uri: 3.0.8 diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 87c23e40..4d1893dd 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,119 +1,124 @@ { - "$schema": "../apps/desktop/node_modules/@tauri-apps/cli/schema.json", - "build": { - "beforeBuildCommand": "pnpm run build", - "beforeDevCommand": "pnpm run dev", - "devPath": "http://localhost:3000", - "distDir": "../dist", - "withGlobalTauri": true - }, - "package": { - "productName": "Lume", - "version": "3.0.0" - }, - "plugins": { - "fs": { - "scope": [ - "$APPDATA/*", - "$DATA/*", - "$LOCALDATA/*", - "$DESKTOP/*", - "$DOCUMENT/*", - "$DOWNLOAD/*", - "$HOME/*", - "$PICTURE/*", - "$PUBLIC/*", - "$VIDEO/*", - "$RESOURCE", - "$RESOURCE/*", - "$RESOURCE/**" - ] - }, - "http": { - "scope": ["http://**/", "https://**/"] - }, - "shell": { - "open": true, - "scope": [{ "name": "bin/depot", "sidecar": true, "args": true }] - }, - "updater": { - "endpoints": [ - "https://lus.reya3772.workers.dev/v1/{{target}}/{{arch}}/{{current_version}}", - "https://lus.reya3772.workers.dev/{{target}}/{{current_version}}" - ] - } - }, - "tauri": { - "bundle": { - "active": true, - "category": "SocialNetworking", - "deb": { - "depends": [] - }, - "externalBin": ["bin/depot"], - "resources": ["resources/*"], - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "copyright": "", + "$schema": "../node_modules/@tauri-apps/cli/schema.json", + "build": { + "beforeBuildCommand": "pnpm run build", + "beforeDevCommand": "pnpm run dev", + "devPath": "http://localhost:3000", + "distDir": "../dist", + "withGlobalTauri": true + }, + "package": { + "productName": "Lume", + "version": "3.0.0-beta.1" + }, + "plugins": { + "fs": { + "scope": [ + "$APPDATA/*", + "$DATA/*", + "$LOCALDATA/*", + "$DESKTOP/*", + "$DOCUMENT/*", + "$DOWNLOAD/*", + "$HOME/*", + "$PICTURE/*", + "$PUBLIC/*", + "$VIDEO/*", + "$RESOURCE", + "$RESOURCE/*", + "$RESOURCE/**" + ] + }, + "http": { + "scope": ["http://**/", "https://**/"] + }, + "shell": { + "open": true, + "scope": [{ "name": "bin/depot", "sidecar": true, "args": true }] + }, + "updater": { + "endpoints": [ + "https://lus.reya3772.workers.dev/v1/{{target}}/{{arch}}/{{current_version}}", + "https://lus.reya3772.workers.dev/{{target}}/{{current_version}}" + ] + } + }, + "tauri": { + "bundle": { + "active": true, + "category": "SocialNetworking", + "deb": { + "depends": [] + }, + "externalBin": [], + "resources": ["resources/*"], + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "copyright": "", "identifier": "nu.lume.Lume", - "longDescription": "nostr client for desktop", - "shortDescription": "", - "targets": "all", - "updater": { - "active": true, - "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEU3OTdCMkM3RjU5QzE2NzkKUldSNUZwejF4N0tYNTVHYjMrU0JkL090SlEyNUVLYU5TM2hTU3RXSWtEWngrZWJ4a0pydUhXZHEK", - "windows": { - "installMode": "quiet" - } - }, - "appimage": { - "bundleMediaFramework": true - }, - "macOS": { - "entitlements": null, - "exceptionDomain": "", - "frameworks": [], - "license": "../LICENSE", - "minimumSystemVersion": "10.15.0", - "providerShortName": null, - "signingIdentity": null - }, - "windows": { - "certificateThumbprint": null, - "digestAlgorithm": "sha256", - "timestampUrl": "" - } - }, - "security": { - "assetProtocol": { - "enable": true, - "scope": [ - "$APPDATA/*", - "$DATA/*", - "$LOCALDATA/*", - "$DESKTOP/*", - "$DOCUMENT/*", - "$DOWNLOAD/*", - "$HOME/*", - "$PICTURE/*", - "$PUBLIC/*", - "$VIDEO/*", - "$APPCONFIG/*", - "$RESOURCE/*" - ] - }, - "dangerousDisableAssetCspModification": false, - "dangerousRemoteDomainIpcAccess": [], - "freezePrototype": false - }, - "trayIcon": { - "iconPath": "icons/tray.png" - }, - "macOSPrivateApi": true - } + "longDescription": "nostr client for desktop", + "shortDescription": "nostr client", + "targets": "all", + "updater": { + "active": true, + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEU3OTdCMkM3RjU5QzE2NzkKUldSNUZwejF4N0tYNTVHYjMrU0JkL090SlEyNUVLYU5TM2hTU3RXSWtEWngrZWJ4a0pydUhXZHEK", + "windows": { + "installMode": "quiet" + } + }, + "appimage": { + "bundleMediaFramework": true + }, + "rpm": { + "epoch": 0, + "files": {}, + "release": "1" + }, + "macOS": { + "entitlements": null, + "exceptionDomain": "", + "frameworks": [], + "license": "../LICENSE", + "minimumSystemVersion": "10.15.0", + "providerShortName": null, + "signingIdentity": null + }, + "windows": { + "certificateThumbprint": null, + "digestAlgorithm": "sha256", + "timestampUrl": "" + } + }, + "security": { + "assetProtocol": { + "enable": true, + "scope": [ + "$APPDATA/*", + "$DATA/*", + "$LOCALDATA/*", + "$DESKTOP/*", + "$DOCUMENT/*", + "$DOWNLOAD/*", + "$HOME/*", + "$PICTURE/*", + "$PUBLIC/*", + "$VIDEO/*", + "$APPCONFIG/*", + "$RESOURCE/*" + ] + }, + "dangerousDisableAssetCspModification": false, + "dangerousRemoteDomainIpcAccess": [], + "freezePrototype": false + }, + "trayIcon": { + "iconPath": "icons/tray.png" + }, + "macOSPrivateApi": true + } }