mirror of
https://github.com/lumehq/lume.git
synced 2025-03-17 21:32:32 +01:00
wip: multi-type composer
This commit is contained in:
parent
de88ca51fe
commit
cade8c8b4c
@ -83,6 +83,7 @@
|
||||
"tailwind-scrollbar": "^3.0.5",
|
||||
"tauri-controls": "^0.2.0",
|
||||
"tippy.js": "^6.3.7",
|
||||
"tiptap-markdown": "^0.8.2",
|
||||
"virtua": "^0.14.0",
|
||||
"zustand": "^4.4.3"
|
||||
},
|
||||
|
34
pnpm-lock.yaml
generated
34
pnpm-lock.yaml
generated
@ -200,6 +200,9 @@ dependencies:
|
||||
tippy.js:
|
||||
specifier: ^6.3.7
|
||||
version: 6.3.7
|
||||
tiptap-markdown:
|
||||
specifier: ^0.8.2
|
||||
version: 0.8.2(@tiptap/core@2.1.12)
|
||||
virtua:
|
||||
specifier: ^0.14.0
|
||||
version: 0.14.0(react-dom@18.2.0)(react@18.2.0)
|
||||
@ -2745,12 +2748,27 @@ packages:
|
||||
resolution: {integrity: sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==}
|
||||
dev: true
|
||||
|
||||
/@types/linkify-it@3.0.4:
|
||||
resolution: {integrity: sha512-hPpIeeHb/2UuCw06kSNAOVWgehBLXEo0/fUs0mw3W2qhqX89PI2yvok83MnuctYGCPrabGIoi0fFso4DQ+sNUQ==}
|
||||
dev: false
|
||||
|
||||
/@types/markdown-it@12.2.3:
|
||||
resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==}
|
||||
dependencies:
|
||||
'@types/linkify-it': 3.0.4
|
||||
'@types/mdurl': 1.0.4
|
||||
dev: false
|
||||
|
||||
/@types/mdast@3.0.14:
|
||||
resolution: {integrity: sha512-gVZ04PGgw1qLZKsnWnyFv4ORnaJ+DXLdHTVSFbU8yX6xZ34Bjg4Q32yPkmveUP1yItXReKfB0Aknlh/3zxTKAw==}
|
||||
dependencies:
|
||||
'@types/unist': 2.0.9
|
||||
dev: false
|
||||
|
||||
/@types/mdurl@1.0.4:
|
||||
resolution: {integrity: sha512-ARVxjAEX5TARFRzpDRVC6cEk0hUIXCCwaMhz8y7S1/PxU6zZS1UMjyobz7q4w/D/R552r4++EhwmXK1N2rAy0A==}
|
||||
dev: false
|
||||
|
||||
/@types/ms@0.7.33:
|
||||
resolution: {integrity: sha512-AuHIyzR5Hea7ij0P9q7vx7xu4z0C28ucwjAZC0ja7JhINyCnOw8/DnvAPQQ9TfOlCtZAmCERKQX9+o1mgQhuOQ==}
|
||||
dev: false
|
||||
@ -4735,6 +4753,10 @@ packages:
|
||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||
dev: false
|
||||
|
||||
/markdown-it-task-lists@2.1.1:
|
||||
resolution: {integrity: sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==}
|
||||
dev: false
|
||||
|
||||
/markdown-it@13.0.2:
|
||||
resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==}
|
||||
hasBin: true
|
||||
@ -6434,6 +6456,18 @@ packages:
|
||||
'@popperjs/core': 2.11.8
|
||||
dev: false
|
||||
|
||||
/tiptap-markdown@0.8.2(@tiptap/core@2.1.12):
|
||||
resolution: {integrity: sha512-RyfpnH475+FYVh1fCiWF9+wBvA8T6X3PqxZR1MApEewxkoQ5kREQFiVwjZiez9qUQk/Bxu3RerFSJot65V6cbQ==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^2.0.3
|
||||
dependencies:
|
||||
'@tiptap/core': 2.1.12(@tiptap/pm@2.1.12)
|
||||
'@types/markdown-it': 12.2.3
|
||||
markdown-it: 13.0.2
|
||||
markdown-it-task-lists: 2.1.1
|
||||
prosemirror-markdown: 1.11.2
|
||||
dev: false
|
||||
|
||||
/to-fast-properties@2.0.0:
|
||||
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -123,6 +123,13 @@ export default function App() {
|
||||
element: <NoteLayout />,
|
||||
errorElement: <ErrorScreen />,
|
||||
children: [
|
||||
{
|
||||
path: 'new',
|
||||
async lazy() {
|
||||
const { NewNoteScreen } = await import('@app/notes/new');
|
||||
return { Component: NewNoteScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'text/:id',
|
||||
async lazy() {
|
||||
|
@ -59,16 +59,16 @@ export function CreateAccountScreen() {
|
||||
const userNpub = nip19.npubEncode(userPubkey);
|
||||
const userNsec = nip19.nsecEncode(userPrivkey);
|
||||
|
||||
const event = new NDKEvent(ndk);
|
||||
const signer = new NDKPrivateKeySigner(userPrivkey);
|
||||
ndk.signer = signer;
|
||||
|
||||
const event = new NDKEvent(ndk);
|
||||
event.content = JSON.stringify(profile);
|
||||
event.kind = NDKKind.Metadata;
|
||||
event.created_at = Math.floor(Date.now() / 1000);
|
||||
event.pubkey = userPubkey;
|
||||
event.tags = [];
|
||||
|
||||
await event.sign(signer);
|
||||
const publish = await event.publish();
|
||||
|
||||
if (publish) {
|
||||
@ -217,7 +217,7 @@ export function CreateAccountScreen() {
|
||||
<p className="mb-2 select-text text-sm text-neutral-800 dark:text-neutral-200">
|
||||
Your private key is your password. If you lose this key, you will
|
||||
lose access to your account! Copy it and keep it in a safe place.{' '}
|
||||
<span className="text-red-500">
|
||||
<span className="text-red-600">
|
||||
There is no way to reset your private key.
|
||||
</span>
|
||||
</p>
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
import { useStorage } from '@libs/storage/provider';
|
||||
|
||||
import { ArrowLeftIcon, CheckCircleIcon, LoaderIcon } from '@shared/icons';
|
||||
@ -10,10 +12,10 @@ import { User } from '@shared/user';
|
||||
|
||||
import { useOnboarding } from '@stores/onboarding';
|
||||
|
||||
import { useNostr } from '@utils/hooks/useNostr';
|
||||
import { arrayToNIP02 } from '@utils/transform';
|
||||
|
||||
export function OnboardEnrichScreen() {
|
||||
const { ndk } = useNDK();
|
||||
const { db } = useStorage();
|
||||
const { status, data } = useQuery(['trending-profiles-widget'], async () => {
|
||||
const res = await fetch('https://api.nostr.band/v0/trending/profiles');
|
||||
@ -22,7 +24,6 @@ export function OnboardEnrichScreen() {
|
||||
}
|
||||
return res.json();
|
||||
});
|
||||
const { publish } = useNostr();
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [follows, setFollows] = useState([]);
|
||||
@ -43,10 +44,17 @@ export function OnboardEnrichScreen() {
|
||||
setLoading(true);
|
||||
|
||||
const tags = arrayToNIP02(follows);
|
||||
const event = await publish({ content: '', kind: 3, tags: tags });
|
||||
|
||||
const event = new NDKEvent(ndk);
|
||||
event.content = '';
|
||||
event.kind = NDKKind.Contacts;
|
||||
event.created_at = Math.floor(Date.now() / 1000);
|
||||
event.tags = tags;
|
||||
|
||||
const publish = await event.publish();
|
||||
|
||||
// redirect to next step
|
||||
if (event) {
|
||||
if (publish) {
|
||||
db.account.follows = follows;
|
||||
|
||||
await db.updateAccount('follows', JSON.stringify(follows));
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
import { useStorage } from '@libs/storage/provider';
|
||||
|
||||
import { ArrowLeftIcon, CheckCircleIcon, LoaderIcon } from '@shared/icons';
|
||||
@ -19,8 +21,8 @@ export function OnboardRelaysScreen() {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [relays, setRelays] = useState(new Set<string>());
|
||||
|
||||
const { publish } = useNostr();
|
||||
const { db } = useStorage();
|
||||
const { ndk } = useNDK();
|
||||
const { getAllRelaysByUsers } = useNostr();
|
||||
const { status, data } = useQuery(
|
||||
['relays'],
|
||||
@ -52,7 +54,13 @@ export function OnboardRelaysScreen() {
|
||||
}
|
||||
|
||||
const tags = Array.from(relays).map((relay) => ['r', relay.replace(/\/+$/, '')]);
|
||||
await publish({ content: '', kind: 10002, tags: tags });
|
||||
const event = new NDKEvent(ndk);
|
||||
event.content = '';
|
||||
event.kind = 10002;
|
||||
event.created_at = Math.floor(Date.now() / 1000);
|
||||
event.tags = tags;
|
||||
|
||||
await event.publish();
|
||||
|
||||
toggleRelays();
|
||||
navigate(-1);
|
||||
|
40
src/app/notes/components/editor/post.tsx
Normal file
40
src/app/notes/components/editor/post.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import Image from '@tiptap/extension-image';
|
||||
import Placeholder from '@tiptap/extension-placeholder';
|
||||
import { EditorContent, useEditor } from '@tiptap/react';
|
||||
import StarterKit from '@tiptap/starter-kit';
|
||||
|
||||
export function PostEditor() {
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
StarterKit.configure(),
|
||||
Placeholder.configure({ placeholder: 'Type something...' }),
|
||||
Image.configure({
|
||||
HTMLAttributes: {
|
||||
class:
|
||||
'rounded-lg w-full h-auto border border-white/10 outline outline-2 outline-offset-0 outline-white/20 ml-1',
|
||||
},
|
||||
}),
|
||||
],
|
||||
content: JSON.parse(localStorage.getItem('editor-post') || '{}'),
|
||||
editorProps: {
|
||||
attributes: {
|
||||
class:
|
||||
'h-full outline-none prose prose-lg prose-neutral max-w-none select-text whitespace-pre-line break-words dark:prose-invert hover:prose-a:text-blue-500',
|
||||
},
|
||||
},
|
||||
onUpdate: ({ editor }) => {
|
||||
const jsonContent = JSON.stringify(editor.getJSON());
|
||||
localStorage.setItem('editor-post', jsonContent);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<EditorContent
|
||||
editor={editor}
|
||||
spellCheck="false"
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
/>
|
||||
);
|
||||
}
|
1
src/app/notes/components/index.ts
Normal file
1
src/app/notes/components/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './editor/post';
|
74
src/app/notes/new.tsx
Normal file
74
src/app/notes/new.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
import { PostEditor } from '@app/notes/components';
|
||||
|
||||
import { ArrowLeftIcon } from '@shared/icons';
|
||||
|
||||
export function NewNoteScreen() {
|
||||
const [type, setType] = useState<'post' | 'article' | 'file' | 'raw'>('post');
|
||||
|
||||
return (
|
||||
<div className="h-full w-full pt-4">
|
||||
<div className="container mx-auto grid grid-cols-8 px-4">
|
||||
<div className="col-span-1">
|
||||
<Link
|
||||
to="/"
|
||||
className="inline-flex h-10 w-10 items-center justify-center rounded-lg bg-neutral-100 hover:bg-neutral-200 dark:bg-neutral-900"
|
||||
>
|
||||
<ArrowLeftIcon className="h-5 w-5" />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="col-span-6">
|
||||
<div className="mb-8 flex items-center gap-3">
|
||||
<div className="flex h-10 items-center gap-2 rounded-lg bg-neutral-100 px-0.5 dark:bg-neutral-800">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setType('post')}
|
||||
className={twMerge(
|
||||
'inline-flex h-9 w-20 items-center justify-center rounded-lg text-sm font-medium',
|
||||
type === 'post' ? 'bg-white shadow' : 'bg-transparent'
|
||||
)}
|
||||
>
|
||||
Post
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setType('article')}
|
||||
className={twMerge(
|
||||
'inline-flex h-9 w-20 items-center justify-center rounded-lg text-sm font-medium',
|
||||
type === 'article' ? 'bg-white shadow' : 'bg-transparent'
|
||||
)}
|
||||
>
|
||||
Article
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setType('file')}
|
||||
className={twMerge(
|
||||
'inline-flex h-9 w-20 items-center justify-center rounded-lg text-sm font-medium',
|
||||
type === 'file' ? 'bg-white shadow' : 'bg-transparent'
|
||||
)}
|
||||
>
|
||||
File
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setType('raw')}
|
||||
className={twMerge(
|
||||
'inline-flex h-9 w-20 items-center justify-center rounded-lg text-sm font-medium',
|
||||
type === 'file' ? 'bg-white shadow' : 'bg-transparent'
|
||||
)}
|
||||
>
|
||||
Raw (advance)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{type === 'post' ? <PostEditor /> : null}
|
||||
</div>
|
||||
<div className="col-span-1" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -68,8 +68,6 @@ export const NDKInstance = () => {
|
||||
// Privkey Signer
|
||||
const userPrivkey = await db.secureLoad(db.account.pubkey);
|
||||
if (userPrivkey) return new NDKPrivateKeySigner(userPrivkey);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function initNDK() {
|
||||
@ -87,9 +85,13 @@ export const NDKInstance = () => {
|
||||
try {
|
||||
// connect
|
||||
await instance.connect(2000);
|
||||
|
||||
// add signer
|
||||
const signer = await getSigner(instance);
|
||||
instance.signer = signer;
|
||||
|
||||
// update account's metadata
|
||||
// todo
|
||||
} catch (error) {
|
||||
await message(`NDK instance init failed: ${error}`, {
|
||||
title: 'Lume',
|
||||
|
@ -23,9 +23,13 @@ export class LumeStorage {
|
||||
}
|
||||
|
||||
public async secureLoad(key: string) {
|
||||
const value: string = await invoke('secure_load', { key });
|
||||
if (!value) return null;
|
||||
return value;
|
||||
try {
|
||||
const value: string = await invoke('secure_load', { key });
|
||||
if (!value) return null;
|
||||
return value;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async secureRemove(key: string) {
|
||||
|
@ -44,9 +44,7 @@ export function AccountMoreActions({ pubkey }: { pubkey: string }) {
|
||||
Settings
|
||||
</Link>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<Logout />
|
||||
</DropdownMenu.Item>
|
||||
<Logout />
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
</DropdownMenu.Root>
|
||||
|
@ -1,16 +1,23 @@
|
||||
import * as AlertDialog from '@radix-ui/react-alert-dialog';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
import { useStorage } from '@libs/storage/provider';
|
||||
|
||||
export function Logout() {
|
||||
const { db } = useStorage();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { db } = useStorage();
|
||||
const { ndk } = useNDK();
|
||||
|
||||
const logout = async () => {
|
||||
ndk.signer = null;
|
||||
|
||||
// remove account
|
||||
db.accountLogout();
|
||||
await db.accountLogout();
|
||||
await db.secureRemove(db.account.pubkey);
|
||||
await db.secureRemove(db.account.pubkey + '-bunker');
|
||||
|
||||
// redirect to welcome screen
|
||||
navigate('/auth/welcome');
|
||||
};
|
||||
@ -26,11 +33,11 @@ export function Logout() {
|
||||
</button>
|
||||
</AlertDialog.Trigger>
|
||||
<AlertDialog.Portal>
|
||||
<AlertDialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-2xl" />
|
||||
<AlertDialog.Overlay className="fixed inset-0 z-50 bg-black/50 backdrop-blur-2xl dark:bg-white/50" />
|
||||
<AlertDialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
||||
<div className="relative h-min w-full max-w-md rounded-xl bg-neutral-400 dark:bg-neutral-600">
|
||||
<div className="flex flex-col gap-2 border-b border-white/5 px-5 py-4">
|
||||
<AlertDialog.Title className="text-lg font-semibold leading-none text-white">
|
||||
<div className="relative h-min w-full max-w-md rounded-xl bg-neutral-100 dark:bg-neutral-900">
|
||||
<div className="flex flex-col gap-1 border-b border-white/5 px-5 py-4">
|
||||
<AlertDialog.Title className="text-lg font-semibold text-neutral-900 dark:text-neutral-100">
|
||||
Are you sure!
|
||||
</AlertDialog.Title>
|
||||
<AlertDialog.Description className="text-sm leading-tight text-neutral-600 dark:text-neutral-400">
|
||||
@ -40,14 +47,17 @@ export function Logout() {
|
||||
</div>
|
||||
<div className="flex justify-end gap-2 px-5 py-3">
|
||||
<AlertDialog.Cancel asChild>
|
||||
<button className="inline-flex h-9 items-center justify-center rounded-md px-4 text-sm font-medium leading-none text-white outline-none hover:bg-white/10 hover:backdrop-blur-xl">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex h-9 items-center justify-center rounded-lg px-4 text-sm font-medium text-neutral-900 outline-none hover:bg-neutral-200 dark:text-neutral-100 dark:hover:bg-neutral-800"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</AlertDialog.Cancel>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => logout()}
|
||||
className="inline-flex h-9 items-center justify-center rounded-md bg-white/10 px-4 text-sm font-medium leading-none text-white outline-none hover:bg-blue-600"
|
||||
className="inline-flex h-9 items-center justify-center rounded-lg bg-red-500 px-4 text-sm font-medium text-white outline-none hover:bg-red-600"
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
|
@ -2,8 +2,14 @@ import { Link, NavLink } from 'react-router-dom';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
import { ActiveAccount } from '@shared/accounts/active';
|
||||
import { ComposerModal } from '@shared/composer';
|
||||
import { ChatsIcon, ExploreIcon, HomeIcon, NwcIcon, RelayIcon } from '@shared/icons';
|
||||
import {
|
||||
ChatsIcon,
|
||||
ComposeIcon,
|
||||
ExploreIcon,
|
||||
HomeIcon,
|
||||
NwcIcon,
|
||||
RelayIcon,
|
||||
} from '@shared/icons';
|
||||
|
||||
export function Navigation() {
|
||||
return (
|
||||
@ -21,7 +27,7 @@ export function Navigation() {
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-lg',
|
||||
isActive
|
||||
? 'bg-black/10 text-black dark:bg-white/10 dark:text-white'
|
||||
: 'text-black/50 dark:text-neutral-400 dark:text-neutral-600'
|
||||
: 'text-black/50 dark:text-neutral-400'
|
||||
)}
|
||||
>
|
||||
<HomeIcon className="h-6 w-6" />
|
||||
@ -42,7 +48,7 @@ export function Navigation() {
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-lg',
|
||||
isActive
|
||||
? 'bg-black/10 text-black dark:bg-white/10 dark:text-white'
|
||||
: 'text-black/50 dark:text-neutral-400 dark:text-neutral-600'
|
||||
: 'text-black/50 dark:text-neutral-400'
|
||||
)}
|
||||
>
|
||||
<ChatsIcon className="h-6 w-6" />
|
||||
@ -63,7 +69,7 @@ export function Navigation() {
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-lg',
|
||||
isActive
|
||||
? 'bg-black/10 text-black dark:bg-white/10 dark:text-white'
|
||||
: 'text-black/50 dark:text-neutral-400 dark:text-neutral-600'
|
||||
: 'text-black/50 dark:text-neutral-400'
|
||||
)}
|
||||
>
|
||||
<RelayIcon className="h-6 w-6" />
|
||||
@ -84,7 +90,7 @@ export function Navigation() {
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-lg',
|
||||
isActive
|
||||
? 'bg-black/10 text-black dark:bg-white/10 dark:text-white'
|
||||
: 'text-black/50 dark:text-neutral-400 dark:text-neutral-600'
|
||||
: 'text-black/50 dark:text-neutral-400'
|
||||
)}
|
||||
>
|
||||
<ExploreIcon className="h-6 w-6" />
|
||||
@ -97,7 +103,12 @@ export function Navigation() {
|
||||
</NavLink>
|
||||
</div>
|
||||
<div className="flex shrink-0 flex-col gap-3 p-1">
|
||||
<ComposerModal />
|
||||
<Link
|
||||
to="/notes/new"
|
||||
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" />
|
||||
</Link>
|
||||
<Link
|
||||
to="/nwc"
|
||||
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"
|
||||
|
@ -317,7 +317,7 @@ export const User = memo(function User({
|
||||
if (variant === 'thread') {
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
<Avatar.Root className="shrink-0">
|
||||
<Avatar.Root className="h-10 w-10 shrink-0">
|
||||
<Avatar.Image
|
||||
src={user?.picture || user?.image}
|
||||
alt={pubkey}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import react from '@vitejs/plugin-react-swc';
|
||||
import million from 'million/compiler';
|
||||
//import million from 'million/compiler';
|
||||
import { defineConfig } from 'vite';
|
||||
import viteTsconfigPaths from 'vite-tsconfig-paths';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [million.vite({ auto: true, mute: true }), react(), viteTsconfigPaths()],
|
||||
plugins: [/*million.vite({ auto: true, mute: true }),*/ react(), viteTsconfigPaths()],
|
||||
envPrefix: ['VITE_', 'TAURI_'],
|
||||
build: {
|
||||
target: process.env.TAURI_PLATFORM === 'windows' ? 'chrome105' : 'safari13',
|
||||
|
Loading…
x
Reference in New Issue
Block a user