feat: polish

This commit is contained in:
2024-01-18 07:37:40 +07:00
parent 47800bd2ff
commit d13e7b3ef6
15 changed files with 146 additions and 123 deletions

View File

@@ -1,76 +1,73 @@
import { getVersion } from '@tauri-apps/api/app'; import { getVersion } from "@tauri-apps/api/app";
import { relaunch } from '@tauri-apps/plugin-process'; import { relaunch } from "@tauri-apps/plugin-process";
import { Update, check } from '@tauri-apps/plugin-updater'; import { Update, check } from "@tauri-apps/plugin-updater";
import { useEffect, useState } from 'react'; import { useEffect, useState } from "react";
import { Link } from 'react-router-dom'; import { Link } from "react-router-dom";
import { toast } from 'sonner'; import { toast } from "sonner";
export function AboutScreen() { export function AboutScreen() {
const [version, setVersion] = useState(''); const [version, setVersion] = useState("");
const [newUpdate, setNewUpdate] = useState<Update>(null); const [newUpdate, setNewUpdate] = useState<Update>(null);
const checkUpdate = async () => { const checkUpdate = async () => {
const update = await check(); const update = await check();
if (!update) toast.info('There is no update available'); if (!update) toast.info("There is no update available");
setNewUpdate(update); setNewUpdate(update);
}; };
const installUpdate = async () => { const installUpdate = async () => {
await newUpdate.downloadAndInstall(); await newUpdate.downloadAndInstall();
await relaunch(); await relaunch();
}; };
useEffect(() => { useEffect(() => {
async function loadVersion() { async function loadVersion() {
const appVersion = await getVersion(); const appVersion = await getVersion();
setVersion(appVersion); setVersion(appVersion);
} }
loadVersion(); loadVersion();
}, []); }, []);
return ( return (
<div className="mx-auto w-full max-w-lg"> <div className="mx-auto w-full max-w-lg">
<div className="flex items-center justify-center gap-2"> <div className="flex flex-col items-center">
<img src="/icon.png" alt="Lume's logo" className="w-16 shrink-0" /> <h1 className="leading-tight text-xl font-semibold">Lume</h1>
<div> <p className="text-sm font-medium text-neutral-700 dark:text-neutral-300">
<h1 className="text-xl font-semibold">Lume</h1> Version {version}
<p className="text-sm font-medium text-neutral-700 dark:text-neutral-300"> </p>
Version {version} </div>
</p> <div className="mx-auto mt-4 flex w-full max-w-xs flex-col gap-2">
</div> {!newUpdate ? (
</div> <button
<div className="mx-auto mt-4 flex w-full max-w-xs flex-col gap-2"> type="button"
{!newUpdate ? ( onClick={() => checkUpdate()}
<button className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-blue-500 text-sm font-medium text-white hover:bg-blue-600"
type="button" >
onClick={() => checkUpdate()} Check for update
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-blue-500 text-sm font-medium text-white hover:bg-blue-600" </button>
> ) : (
Check for update <button
</button> type="button"
) : ( onClick={() => installUpdate()}
<button className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-blue-500 text-sm font-medium text-white hover:bg-blue-600"
type="button" >
onClick={() => installUpdate()} Install {newUpdate.version}
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-blue-500 text-sm font-medium text-white hover:bg-blue-600" </button>
> )}
Install {newUpdate.version} <Link
</button> to="https://lume.nu"
)} className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-neutral-100 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
<Link >
to="https://lume.nu" Website
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-neutral-100 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800" </Link>
> <Link
Website to="https://github.com/luminous-devs/lume/issues"
</Link> className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-neutral-100 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
<Link >
to="https://github.com/luminous-devs/lume/issues" Report a issue
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-neutral-100 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800" </Link>
> </div>
Report a issue </div>
</Link> );
</div>
</div>
);
} }

View File

@@ -45,10 +45,10 @@ export function NWCScreen() {
<div> <div>
<div className="flex w-full flex-col gap-5"> <div className="flex w-full flex-col gap-5">
<div className="text-center"> <div className="text-center">
<h3 className="text-2xl font-semibold leading-tight"> <h3 className="text-xl font-semibold leading-tight">
Nostr Wallet Connect Nostr Wallet Connect
</h3> </h3>
<p className="text-lg font-medium leading-snug text-neutral-600 dark:text-neutral-500"> <p className="font-medium leading-snug text-neutral-600 dark:text-neutral-500">
Sending zap easily via Bitcoin Lightning. Sending zap easily via Bitcoin Lightning.
</p> </p>
</div> </div>

View File

@@ -109,6 +109,7 @@ export class Ark {
.replace("nostr:", "") .replace("nostr:", "")
.split("'")[0] .split("'")[0]
.split(".")[0] .split(".")[0]
.split(",")[0]
.split("?")[0]; .split("?")[0];
if ( if (

View File

@@ -99,7 +99,7 @@ export function RepostNote({
<Note.Content /> <Note.Content />
<div className="flex items-center justify-between h-14"> <div className="flex items-center justify-between h-14">
<Note.Pin /> <Note.Pin />
<div className="inline-flex items-center gap-10"> <div className="inline-flex items-center gap-4">
<Note.Reply /> <Note.Reply />
<Note.Repost /> <Note.Repost />
<Note.Zap /> <Note.Zap />

View File

@@ -22,7 +22,7 @@ export function TextNote({
<Note.Content className="min-w-0 px-3" /> <Note.Content className="min-w-0 px-3" />
<div className="flex items-center justify-between px-3 h-14"> <div className="flex items-center justify-between px-3 h-14">
<Note.Pin /> <Note.Pin />
<div className="inline-flex items-center gap-10"> <div className="inline-flex items-center gap-4">
<Note.Reply /> <Note.Reply />
<Note.Repost /> <Note.Repost />
<Note.Zap /> <Note.Zap />

View File

@@ -0,0 +1,28 @@
import { cn } from "@lume/utils";
import { useUserContext } from "./provider";
export function UserCover({ className }: { className?: string }) {
const user = useUserContext();
if (!user) {
return (
<div
className={cn(
"animate-pulse bg-neutral-300 dark:bg-neutral-700",
className,
)}
/>
);
}
return (
<img
src={user.banner || user.cover}
alt="banner"
loading="lazy"
decoding="async"
style={{ contentVisibility: "auto" }}
className={cn("object-cover", className)}
/>
);
}

View File

@@ -1,5 +1,6 @@
import { UserAbout } from "./about"; import { UserAbout } from "./about";
import { UserAvatar } from "./avatar"; import { UserAvatar } from "./avatar";
import { UserCover } from "./cover";
import { UserFollowButton } from "./followButton"; import { UserFollowButton } from "./followButton";
import { UserName } from "./name"; import { UserName } from "./name";
import { UserNip05 } from "./nip05"; import { UserNip05 } from "./nip05";
@@ -11,6 +12,7 @@ export const User = {
Provider: UserProvider, Provider: UserProvider,
Root: UserRoot, Root: UserRoot,
Avatar: UserAvatar, Avatar: UserAvatar,
Cover: UserCover,
Name: UserName, Name: UserName,
NIP05: UserNip05, NIP05: UserNip05,
Time: UserTime, Time: UserTime,

View File

@@ -394,7 +394,7 @@ export class NDKCacheAdapterTauri implements NDKCacheAdapter {
const events = await this.#storage.getCacheEvents(eventIds); const events = await this.#storage.getCacheEvents(eventIds);
for (const event of events) { for (const event of events) {
let rawEvent; let rawEvent: NostrEvent;
try { try {
rawEvent = JSON.parse(event.event); rawEvent = JSON.parse(event.event);

View File

@@ -24,7 +24,7 @@ export function ActiveAccount() {
return ( return (
<DropdownMenu.Root> <DropdownMenu.Root>
<DropdownMenu.Trigger asChild> <DropdownMenu.Trigger asChild>
<div> <div className="relative">
<Avatar.Root> <Avatar.Root>
<Avatar.Image <Avatar.Image
src={user?.picture || user?.image} src={user?.picture || user?.image}

View File

@@ -1,32 +0,0 @@
import { HorizontalDotsIcon } from "@lume/icons";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { Link } from "react-router-dom";
import { Logout } from "./logout";
export function AccountMoreActions() {
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<button
type="button"
className="inline-flex items-center justify-center rounded-md"
>
<HorizontalDotsIcon className="h-4 w-4" />
</button>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content className="ml-2 flex w-[200px] flex-col overflow-hidden rounded-xl bg-blue-500 p-2 focus:outline-none">
<DropdownMenu.Item asChild>
<Link
to="/settings/"
className="inline-flex h-10 items-center rounded-lg px-2 text-sm font-medium text-white hover:bg-blue-600 focus:outline-none"
>
Settings
</Link>
</DropdownMenu.Item>
<Logout />
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
);
}

View File

@@ -1,9 +1,6 @@
export * from "./account/active"; export * from "./account/active";
export * from "./account/logout"; export * from "./account/logout";
export * from "./account/more";
export * from "./navigation"; export * from "./navigation";
export * from "./nip05";
export * from "./user";
export * from "./titlebar"; export * from "./titlebar";
export * from "./layouts/app"; export * from "./layouts/app";
export * from "./layouts/auth"; export * from "./layouts/auth";
@@ -15,3 +12,4 @@ export * from "./emptyFeed";
export * from "./routes/event"; export * from "./routes/event";
export * from "./routes/user"; export * from "./routes/user";
export * from "./translateRegisterModal"; export * from "./translateRegisterModal";
export * from "./user";

View File

@@ -15,12 +15,7 @@ export function OnboardingFinishScreen() {
const finish = async () => { const finish = async () => {
setLoading(true); setLoading(true);
const queryCache = queryClient.getQueryCache(); await queryClient.refetchQueries({ queryKey: ["timeline-9999"] });
const queryKeys = queryCache.getAll().map((cache) => cache.queryKey);
for (const key of queryKeys) {
await queryClient.refetchQueries({ queryKey: key });
}
setLoading(false); setLoading(false);
setOnboarding(false); setOnboarding(false);

View File

@@ -1,4 +1,4 @@
import { useArk } from "@lume/ark"; import { User, useArk } from "@lume/ark";
import { import {
ArrowLeftIcon, ArrowLeftIcon,
CancelIcon, CancelIcon,
@@ -14,7 +14,6 @@ import { nip19 } from "nostr-tools";
import { useState } from "react"; import { useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { toast } from "sonner"; import { toast } from "sonner";
import { User } from "../user";
const POPULAR_USERS = [ const POPULAR_USERS = [
"npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6", "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6",
@@ -66,6 +65,7 @@ export function OnboardingFollowScreen() {
const submit = async () => { const submit = async () => {
try { try {
setLoading(true); setLoading(true);
if (!follows.length) return navigate("/finish"); if (!follows.length) return navigate("/finish");
const publish = await ark.newContactList({ const publish = await ark.newContactList({
@@ -118,7 +118,18 @@ export function OnboardingFollowScreen() {
key={pubkey} key={pubkey}
className="flex h-max w-full shrink-0 flex-col my-3 gap-4 overflow-hidden rounded-lg bg-white dark:bg-black" className="flex h-max w-full shrink-0 flex-col my-3 gap-4 overflow-hidden rounded-lg bg-white dark:bg-black"
> >
<User pubkey={pubkey} variant="large" /> <User.Provider pubkey={pubkey}>
<User.Root>
<User.Cover className="h-20 w-full rounded-t-lg" />
<div className="flex h-full w-full flex-col gap-2.5 px-3 -mt-6">
<User.Avatar className="size-10 shrink-0 rounded-lg" />
<div className="flex flex-col items-start text-start">
<User.Name className="max-w-[15rem] truncate text-lg font-semibold leadning-tight" />
<User.About className="break-p text-neutral-700 dark:text-neutral-600 max-w-none select-text whitespace-pre-line" />
</div>
</div>
</User.Root>
</User.Provider>
<div className="h-16 shrink-0 px-3 flex items-center border-t border-neutral-100 dark:border-neutral-900"> <div className="h-16 shrink-0 px-3 flex items-center border-t border-neutral-100 dark:border-neutral-900">
<button <button
type="button" type="button"
@@ -172,7 +183,18 @@ export function OnboardingFollowScreen() {
key={item.pubkey} key={item.pubkey}
className="flex h-max w-full shrink-0 flex-col my-3 gap-4 overflow-hidden rounded-lg bg-white dark:bg-black" className="flex h-max w-full shrink-0 flex-col my-3 gap-4 overflow-hidden rounded-lg bg-white dark:bg-black"
> >
<User pubkey={item.pubkey} variant="large" /> <User.Provider pubkey={item.pubkey}>
<User.Root>
<User.Cover className="h-20 w-full rounded-t-lg" />
<div className="flex h-full w-full flex-col gap-2.5 px-3 -mt-6">
<User.Avatar className="size-10 shrink-0 rounded-lg" />
<div className="flex flex-col items-start text-start">
<User.Name className="max-w-[15rem] truncate text-lg font-semibold leadning-tight" />
<User.About className="break-p text-neutral-700 dark:text-neutral-600 max-w-none select-text whitespace-pre-line" />
</div>
</div>
</User.Root>
</User.Provider>
<div className="h-16 shrink-0 px-3 flex items-center border-t border-neutral-100 dark:border-neutral-900"> <div className="h-16 shrink-0 px-3 flex items-center border-t border-neutral-100 dark:border-neutral-900">
<button <button
type="button" type="button"
@@ -196,6 +218,7 @@ export function OnboardingFollowScreen() {
</> </>
)} )}
</button> </button>
UU
</div> </div>
</div> </div>
)) ))
@@ -218,7 +241,18 @@ export function OnboardingFollowScreen() {
key={pubkey} key={pubkey}
className="flex h-max w-full shrink-0 flex-col my-3 gap-4 overflow-hidden rounded-lg bg-white dark:bg-black" className="flex h-max w-full shrink-0 flex-col my-3 gap-4 overflow-hidden rounded-lg bg-white dark:bg-black"
> >
<User pubkey={pubkey} variant="large" /> <User.Provider pubkey={pubkey}>
<User.Root>
<User.Cover className="h-20 w-full rounded-t-lg" />
<div className="flex h-full w-full flex-col gap-2.5 px-3 -mt-6">
<User.Avatar className="size-10 shrink-0 rounded-lg" />
<div className="flex flex-col items-start text-start">
<User.Name className="max-w-[15rem] truncate text-lg font-semibold leadning-tight" />
<User.About className="break-p text-neutral-700 dark:text-neutral-600 max-w-none select-text whitespace-pre-line" />
</div>
</div>
</User.Root>
</User.Provider>
<div className="h-16 shrink-0 px-3 flex items-center border-t border-neutral-100 dark:border-neutral-900"> <div className="h-16 shrink-0 px-3 flex items-center border-t border-neutral-100 dark:border-neutral-900">
<button <button
type="button" type="button"

View File

@@ -43,8 +43,8 @@ export function OnboardingProfileSettingsScreen() {
nip05: oldProfile?.nip05 || "", nip05: oldProfile?.nip05 || "",
display_name: data.name, display_name: data.name,
bio: data.about, bio: data.about,
image: picture,
picture: picture, picture: picture,
avatar: picture,
}; };
const publish = await ark.createEvent({ const publish = await ark.createEvent({

View File

@@ -60,11 +60,11 @@ export function ReplyList({
className="py-4 border-t border-neutral-100 dark:border-neutral-900" className="py-4 border-t border-neutral-100 dark:border-neutral-900"
/> />
{!data ? ( {!data ? (
<div className="pt-4 flex h-16 items-center justify-center rounded-xl bg-neutral-50 p-3 dark:bg-neutral-950"> <div className="mt-4 flex h-16 items-center justify-center p-3">
<LoaderIcon className="h-5 w-5 animate-spin" /> <LoaderIcon className="h-5 w-5 animate-spin" />
</div> </div>
) : data.length === 0 ? ( ) : data.length === 0 ? (
<div className="pt-4 flex w-full items-center justify-center bg-neutral-50 dark:bg-neutral-950 rounded-lg"> <div className="mt-4 flex w-full items-center justify-center">
<div className="flex flex-col items-center justify-center gap-2 py-6"> <div className="flex flex-col items-center justify-center gap-2 py-6">
<h3 className="text-3xl">👋</h3> <h3 className="text-3xl">👋</h3>
<p className="leading-none text-neutral-600 dark:text-neutral-400"> <p className="leading-none text-neutral-600 dark:text-neutral-400">