wip: polish

This commit is contained in:
2023-10-18 08:43:31 +07:00
parent 7fa1e89dc8
commit 489ab6bd0b
17 changed files with 293 additions and 205 deletions

View File

@@ -67,6 +67,7 @@ export function Circle() {
lru.clear();
// done
await db.createSetting('circles', '1');
setCircle();
};

View File

@@ -1,5 +1,6 @@
import { NDKEvent, NDKKind, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk';
import { downloadDir } from '@tauri-apps/api/path';
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
import { message, save } from '@tauri-apps/plugin-dialog';
import { writeTextFile } from '@tauri-apps/plugin-fs';
import { motion } from 'framer-motion';
@@ -42,18 +43,14 @@ export function CreateAccountScreen() {
'data:image/svg+xml;utf8,' +
encodeURIComponent(minidenticon('lume new account', 90, 50));
const onSubmit = async (data: {
name: string;
display_name: string;
about: string;
}) => {
const onSubmit = async (data: { name: string; about: string }) => {
try {
setLoading(true);
const profile = {
...data,
name: data.name,
display_name: data.display_name,
display_name: data.name,
bio: data.about,
};
@@ -93,6 +90,10 @@ export function CreateAccountScreen() {
}
};
const copyNsec = async () => {
await writeText(keys.nsec);
};
const download = async () => {
try {
const downloadPath = await downloadDir();
@@ -116,7 +117,7 @@ export function CreateAccountScreen() {
return (
<div className="relative flex h-full w-full items-center justify-center">
<div className="absolute left-[8px] top-4">
<div className="absolute left-[8px] top-2">
{!keys ? (
<button
onClick={() => navigate(-1)}
@@ -230,11 +231,24 @@ export function CreateAccountScreen() {
<label htmlFor="nsec" className="text-sm font-semibold">
Private key
</label>
<input
readOnly
value={keys.nsec}
className="h-11 rounded-lg bg-neutral-200 px-3 placeholder:text-neutral-500 dark:bg-neutral-800 dark:placeholder:text-neutral-400"
/>
<div className="relative w-full">
<input
readOnly
value={
keys.nsec.substring(0, 10) + '**************************'
}
className="h-11 w-full rounded-lg bg-neutral-200 px-3 placeholder:text-neutral-500 dark:bg-neutral-800 dark:placeholder:text-neutral-400"
/>
<div className="absolute right-0 top-0 inline-flex h-11 items-center justify-center px-2">
<button
type="button"
onClick={copyNsec}
className="rounded-md bg-neutral-300 px-2 py-1 text-sm font-medium hover:bg-neutral-400 dark:bg-neutral-700 dark:hover:bg-neutral-600"
>
Copy
</button>
</div>
</div>
</div>
<div className="flex flex-col gap-1">
<label htmlFor="nsec" className="text-sm font-semibold">

View File

@@ -21,7 +21,7 @@ export function WelcomeScreen() {
to="/auth/import"
className="inline-flex h-10 w-full items-center justify-center rounded-lg font-medium text-neutral-900 hover:bg-neutral-100 dark:text-neutral-100 dark:hover:bg-neutral-900"
>
Log in
Log in with key
</Link>
</div>
</div>

View File

@@ -1,5 +1,5 @@
import { useCallback, useEffect } from 'react';
import { VList } from 'virtua';
import { useCallback, useEffect, useRef } from 'react';
import { VList, VListHandle } from 'virtua';
import { ToggleWidgetList } from '@app/space/components/toggle';
import { WidgetList } from '@app/space/components/widgetList';
@@ -31,6 +31,7 @@ import { Widget } from '@utils/types';
export function SpaceScreen() {
const { db } = useStorage();
const vlistRef = useRef<VListHandle>(null);
const [widgets, fetchWidgets] = useWidgets((state) => [
state.widgets,
@@ -88,6 +89,7 @@ export function SpaceScreen() {
<VList
className="h-full w-full flex-nowrap overflow-x-auto !overflow-y-hidden scrollbar-none"
horizontal
ref={vlistRef}
>
{!widgets ? (
<div className="flex h-full w-[420px] flex-col items-center justify-center">

View File

@@ -1,11 +1,12 @@
import { NDKFilter, NDKKind } from '@nostr-dev-kit/ndk';
import * as Avatar from '@radix-ui/react-avatar';
import { minidenticon } from 'minidenticons';
import { useEffect } from 'react';
import { Link } from 'react-router-dom';
import { useStorage } from '@libs/storage/provider';
import { HorizontalDotsIcon } from '@shared/icons';
import { Image } from '@shared/image';
import { useActivities } from '@stores/activities';
@@ -19,6 +20,9 @@ export function ActiveAccount() {
const { sub } = useNostr();
const addActivity = useActivities((state) => state.addActivity);
const svgURI =
'data:image/svg+xml;utf8,' +
encodeURIComponent(minidenticon(db.account.pubkey, 90, 50));
useEffect(() => {
const filter: NDKFilter = {
@@ -57,12 +61,24 @@ export function ActiveAccount() {
return (
<div className="flex flex-col gap-1 rounded-lg bg-neutral-100 p-1 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800">
<Link to={`/users/${db.account.pubkey}`} className="relative inline-block">
<Image
src={user?.picture || user?.image}
alt={db.account.npub}
className="aspect-square h-auto w-full rounded-md"
/>
<span className="absolute bottom-0 right-0 block h-2 w-2 rounded-full bg-emerald-500 ring-2 ring-neutral-100 dark:ring-neutral-900" />
<Avatar.Root>
<Avatar.Image
src={user?.picture || user?.image}
alt={db.account.pubkey}
loading="lazy"
decoding="async"
style={{ contentVisibility: 'auto' }}
className="aspect-square h-auto w-full rounded-md"
/>
<Avatar.Fallback delayMs={300}>
<img
src={svgURI}
alt={db.account.pubkeypubkey}
className="aspect-square h-auto w-full rounded-md bg-black dark:bg-white"
/>
</Avatar.Fallback>
</Avatar.Root>
<span className="absolute bottom-0 right-0 block h-2 w-2 rounded-full bg-teal-500 ring-2 ring-neutral-100 dark:ring-neutral-900" />
</Link>
<div className="inline-flex items-center justify-center rounded-md">
<HorizontalDotsIcon className="h-4 w-4" />

View File

@@ -25,7 +25,7 @@ export function AvatarUploader({
<button
type="button"
onClick={() => uploadAvatar()}
className="inline-flex items-center gap-1 rounded-lg border border-blue-200 bg-blue-100 px-1.5 py-1 text-sm font-medium text-blue-500 hover:bg-blue-200 dark:bg-blue-900 dark:text-blue-500 dark:hover:bg-blue-800"
className="inline-flex items-center gap-1 rounded-lg border border-blue-200 bg-blue-100 px-1.5 py-1 text-sm font-medium text-blue-500 hover:border-blue-300 hover:bg-blue-200 dark:bg-blue-900 dark:text-blue-500 dark:hover:border-blue-800 dark:hover:bg-blue-800"
>
{loading ? (
<LoaderIcon className="h-4 w-4 animate-spin" />

View File

@@ -28,7 +28,7 @@ export function ComposerModal() {
<Dialog.Trigger asChild>
<button
type="button"
className="flex aspect-square h-auto w-full items-center justify-center rounded-lg bg-neutral-300 text-black hover:bg-blue-600 hover:text-white dark:bg-neutral-700 dark:text-white dark:hover:bg-blue-600"
className="flex aspect-square h-auto w-full items-center justify-center rounded-lg bg-neutral-100 text-black hover:bg-blue-500 hover:text-white dark:bg-neutral-900 dark:text-white dark:hover:bg-blue-500"
>
<ComposeIcon className="h-5 w-5" />
</button>

View File

@@ -26,7 +26,7 @@ export function Navigation() {
>
<HomeIcon className="h-6 w-6" />
</div>
<div className="text-sm text-black dark:text-white">Home</div>
<div className="text-sm font-medium text-black dark:text-white">Home</div>
</>
)}
</NavLink>
@@ -47,7 +47,7 @@ export function Navigation() {
>
<ChatsIcon className="h-6 w-6" />
</div>
<div className="text-sm text-black dark:text-white">Chats</div>
<div className="text-sm font-medium text-black dark:text-white">Chats</div>
</>
)}
</NavLink>
@@ -68,7 +68,7 @@ export function Navigation() {
>
<RelayIcon className="h-6 w-6" />
</div>
<div className="text-sm text-black dark:text-white">Relays</div>
<div className="text-sm font-medium text-black dark:text-white">Relays</div>
</>
)}
</NavLink>
@@ -89,7 +89,9 @@ export function Navigation() {
>
<ExploreIcon className="h-6 w-6" />
</div>
<div className="text-sm text-black dark:text-white">Explore</div>
<div className="text-sm font-medium text-black dark:text-white">
Explore
</div>
</>
)}
</NavLink>
@@ -98,7 +100,7 @@ export function Navigation() {
<ComposerModal />
<Link
to="/nwc"
className="flex aspect-square h-auto w-full items-center justify-center rounded-lg bg-neutral-100 hover:bg-blue-600 hover:text-white dark:bg-neutral-900 dark:hover:bg-blue-600"
className="flex aspect-square h-auto w-full items-center justify-center rounded-lg bg-neutral-100 hover:bg-blue-500 hover:text-white dark:bg-neutral-900 dark:hover:bg-blue-500"
>
<NwcIcon className="h-5 w-5" />
</Link>

View File

@@ -1,20 +1,36 @@
import { useStorage } from '@libs/storage/provider';
import { CancelIcon } from '@shared/icons';
import { User } from '@shared/user';
import { useWidgets } from '@stores/widgets';
export function TitleBar({ id, title }: { id?: string; title: string }) {
export function TitleBar({ id, title }: { id?: string; title?: string }) {
const { db } = useStorage();
const remove = useWidgets((state) => state.removeWidget);
return (
<div className="flex h-11 w-full shrink-0 items-center justify-between overflow-hidden px-3">
<div className="w-6" />
<h3 className="text-sm font-medium tracking-wide text-neutral-900 dark:text-neutral-100">
{title}
</h3>
{id ? (
{id === '9999' ? (
<div className="isolate flex -space-x-2">
{db.account.circles
?.slice(0, 4)
.map((item) => <User key={item} pubkey={item} variant="ministacked" />)}
{db.account.circles?.length > 4 ? (
<div className="inline-flex h-6 w-6 items-center justify-center rounded-full bg-neutral-200 text-neutral-900 ring-1 ring-neutral-300 dark:bg-neutral-800 dark:text-neutral-100 dark:ring-neutral-700">
<span className="text-xs font-medium">
+{db.account.circles?.length - 4}
</span>
</div>
) : null}
</div>
) : (
<h3 className="text-sm font-medium tracking-wide text-neutral-900 dark:text-neutral-100">
{title}
</h3>
)}
{id !== '9999' ? (
<button
type="button"
onClick={() => remove(db, id)}

View File

@@ -33,7 +33,8 @@ export const User = memo(function User({
| 'large'
| 'thread'
| 'avatar'
| 'stacked';
| 'stacked'
| 'ministacked';
embedProfile?: string;
}) {
const { status, user } = useProfile(pubkey, embedProfile);
@@ -228,6 +229,28 @@ export const User = memo(function User({
);
}
if (variant === 'ministacked') {
return (
<Avatar.Root>
<Avatar.Image
src={user?.picture || user?.image}
alt={pubkey}
loading="lazy"
decoding="async"
style={{ contentVisibility: 'auto' }}
className="inline-block h-6 w-6 rounded-full ring-1 ring-white dark:ring-black"
/>
<Avatar.Fallback delayMs={300}>
<img
src={svgURI}
alt={pubkey}
className="inline-block h-6 w-6 rounded-full bg-black ring-1 ring-white dark:bg-white dark:ring-black"
/>
</Avatar.Fallback>
</Avatar.Root>
);
}
if (variant === 'repost') {
return (
<div className="flex gap-3">

View File

@@ -86,10 +86,10 @@ export function LocalNetworkWidget() {
// subscribe for new event
// sub will be managed by lru-cache
useEffect(() => {
if (db.account && db.account.network && dbEvents.length > 0) {
if (db.account && db.account.circles && dbEvents.length > 0) {
const filter: NDKFilter = {
kinds: [NDKKind.Text, NDKKind.Repost],
authors: db.account.network,
authors: db.account.circles,
since: Math.floor(Date.now() / 1000),
};
@@ -102,7 +102,7 @@ export function LocalNetworkWidget() {
return (
<WidgetWrapper>
<TitleBar title="Network" />
<TitleBar id="9999" />
<div className="flex-1">
{status === 'loading' ? (
<div className="px-3 py-1.5">

View File

@@ -57,7 +57,7 @@ export function XfeedsWidget({ params }: { params: Widget }) {
/>
</div>
<div className="flex h-[500px] w-full flex-col overflow-y-auto rounded-lg bg-neutral-200 py-2 scrollbar-none dark:bg-neutral-800">
{db.account.network.map((item: string) => (
{db.account.circles.map((item: string) => (
<button
key={item}
type="button"

View File

@@ -47,7 +47,7 @@ export const WidgetKinds = {
export const DefaultWidgets: Array<WidgetGroup> = [
{
title: 'Network / Follows',
title: 'Circles / Follows',
data: [
{
kind: WidgetKinds.tmp.xfeed,
@@ -57,12 +57,12 @@ export const DefaultWidgets: Array<WidgetGroup> = [
{
kind: WidgetKinds.local.files,
title: 'Files',
description: 'All files shared by people in your network',
description: 'All files shared by people in your circle',
},
{
kind: WidgetKinds.local.articles,
title: 'Articles',
description: 'All articles shared by people in your network',
description: 'All articles shared by people in your circle',
},
{
kind: WidgetKinds.local.follows,
@@ -130,7 +130,7 @@ export const useWidgets = create<WidgetState>()(
// default: add network widget
dbWidgets.unshift({
id: '9999',
title: 'Network',
title: '',
content: '',
kind: WidgetKinds.local.network,
});

View File

@@ -404,14 +404,14 @@ export function useNostr() {
removeContact,
getAllNIP04Chats,
getAllEventsSinceLastLogin,
getContactsByPubkey,
getEventsByPubkey,
getAllRelaysByUsers,
fetchActivities,
fetchNIP04Messages,
fetchAllReplies,
publish,
createZap,
upload,
getContactsByPubkey,
getEventsByPubkey,
getAllRelaysByUsers,
};
}