mirror of
https://github.com/lumehq/lume.git
synced 2025-03-18 05:41:53 +01:00
feat(ui): update ui consistent
This commit is contained in:
parent
ec2ac2dce3
commit
d9e8d05db7
12
package.json
12
package.json
@ -34,7 +34,7 @@
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-toolbar": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.0.7",
|
||||
"@tanstack/react-query": "^5.14.0",
|
||||
"@tanstack/react-query": "^5.14.1",
|
||||
"@tauri-apps/api": "2.0.0-alpha.11",
|
||||
"@tauri-apps/cli": "2.0.0-alpha.17",
|
||||
"@tauri-apps/plugin-autostart": "2.0.0-alpha.3",
|
||||
@ -84,18 +84,18 @@
|
||||
"tippy.js": "^6.3.7",
|
||||
"tiptap-markdown": "^0.8.8",
|
||||
"use-react-workers": "^0.3.0",
|
||||
"virtua": "^0.17.5"
|
||||
"virtua": "^0.17.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/html-to-text": "^9.0.4",
|
||||
"@types/node": "^20.10.4",
|
||||
"@types/node": "^20.10.5",
|
||||
"@types/react": "^18.2.45",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
||||
"@typescript-eslint/parser": "^6.14.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
||||
"@typescript-eslint/parser": "^6.15.0",
|
||||
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"clsx": "^2.0.0",
|
||||
@ -114,7 +114,7 @@
|
||||
"prop-types": "^15.8.1",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwind-scrollbar": "^3.0.5",
|
||||
"tailwindcss": "^3.3.6",
|
||||
"tailwindcss": "^3.3.7",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10",
|
||||
"vite-tsconfig-paths": "^4.2.2"
|
||||
|
480
pnpm-lock.yaml
generated
480
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
52
src-tauri/Cargo.lock
generated
52
src-tauri/Cargo.lock
generated
@ -327,9 +327,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.5.0"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1"
|
||||
checksum = "e1d90cd0b264dfdd8eb5bad0a2c217c1f88fa96a8573f40e7b12de23fb468f46"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
@ -646,9 +646,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cargo_toml"
|
||||
version = "0.17.1"
|
||||
version = "0.17.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d1ece59890e746567b467253aea0adbe8a21784d0b025d8a306f66c391c2957"
|
||||
checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"toml 0.8.2",
|
||||
@ -2208,9 +2208,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.27"
|
||||
version = "0.14.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
|
||||
checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
@ -2223,7 +2223,7 @@ dependencies = [
|
||||
"httpdate",
|
||||
"itoa 1.0.10",
|
||||
"pin-project-lite",
|
||||
"socket2 0.4.10",
|
||||
"socket2 0.5.5",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@ -3937,9 +3937,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.22"
|
||||
version = "0.11.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
|
||||
checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes",
|
||||
@ -5064,7 +5064,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-autostart"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"auto-launch",
|
||||
"log",
|
||||
@ -5077,7 +5077,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-cli"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"log",
|
||||
@ -5090,7 +5090,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-clipboard-manager"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"arboard",
|
||||
"log",
|
||||
@ -5104,7 +5104,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-dialog"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"glib 0.16.9",
|
||||
"log",
|
||||
@ -5121,7 +5121,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-fs"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"glob",
|
||||
@ -5134,7 +5134,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-http"
|
||||
version = "2.0.0-alpha.6"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"data-url",
|
||||
"glob",
|
||||
@ -5151,7 +5151,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-notification"
|
||||
version = "2.0.0-alpha.6"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"log",
|
||||
"notify-rust",
|
||||
@ -5169,7 +5169,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-os"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"gethostname 0.4.3",
|
||||
"log",
|
||||
@ -5185,7 +5185,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-process"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"tauri",
|
||||
]
|
||||
@ -5193,7 +5193,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-shell"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"log",
|
||||
@ -5210,7 +5210,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-sql"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"log",
|
||||
@ -5226,7 +5226,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-store"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
@ -5254,7 +5254,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-updater"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"dirs-next",
|
||||
@ -5280,7 +5280,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-upload"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
@ -5297,7 +5297,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-plugin-window-state"
|
||||
version = "2.0.0-alpha.5"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#68cb23f9c0722343a79096044122a811fd8cc059"
|
||||
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#b1c6a7885e6aa036ec08b332bffa82b99a794e85"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags 2.4.1",
|
||||
@ -6430,9 +6430,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.28"
|
||||
version = "0.5.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2"
|
||||
checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
119
src/app.tsx
119
src/app.tsx
@ -122,6 +122,69 @@ export default function App() {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'settings',
|
||||
element: <SettingsLayout />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
async lazy() {
|
||||
const { UserSettingScreen } = await import('@app/settings');
|
||||
return { Component: UserSettingScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'edit-profile',
|
||||
async lazy() {
|
||||
const { EditProfileScreen } = await import(
|
||||
'@app/settings/editProfile'
|
||||
);
|
||||
return { Component: EditProfileScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'edit-contact',
|
||||
async lazy() {
|
||||
const { EditContactScreen } = await import(
|
||||
'@app/settings/editContact'
|
||||
);
|
||||
return { Component: EditContactScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'general',
|
||||
async lazy() {
|
||||
const { GeneralSettingScreen } = await import(
|
||||
'@app/settings/general'
|
||||
);
|
||||
return { Component: GeneralSettingScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'backup',
|
||||
async lazy() {
|
||||
const { BackupSettingScreen } = await import('@app/settings/backup');
|
||||
return { Component: BackupSettingScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'advanced',
|
||||
async lazy() {
|
||||
const { AdvancedSettingScreen } = await import(
|
||||
'@app/settings/advanced'
|
||||
);
|
||||
return { Component: AdvancedSettingScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'about',
|
||||
async lazy() {
|
||||
const { AboutScreen } = await import('@app/settings/about');
|
||||
return { Component: AboutScreen };
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
@ -203,62 +266,6 @@ export default function App() {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'settings',
|
||||
element: <SettingsLayout platform={ark.platform} />,
|
||||
errorElement: <ErrorScreen />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
async lazy() {
|
||||
const { UserSettingScreen } = await import('@app/settings');
|
||||
return { Component: UserSettingScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'edit-profile',
|
||||
async lazy() {
|
||||
const { EditProfileScreen } = await import('@app/settings/editProfile');
|
||||
return { Component: EditProfileScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'edit-contact',
|
||||
async lazy() {
|
||||
const { EditContactScreen } = await import('@app/settings/editContact');
|
||||
return { Component: EditContactScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'general',
|
||||
async lazy() {
|
||||
const { GeneralSettingScreen } = await import('@app/settings/general');
|
||||
return { Component: GeneralSettingScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'backup',
|
||||
async lazy() {
|
||||
const { BackupSettingScreen } = await import('@app/settings/backup');
|
||||
return { Component: BackupSettingScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'advanced',
|
||||
async lazy() {
|
||||
const { AdvancedSettingScreen } = await import('@app/settings/advanced');
|
||||
return { Component: AdvancedSettingScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'about',
|
||||
async lazy() {
|
||||
const { AboutScreen } = await import('@app/settings/about');
|
||||
return { Component: AboutScreen };
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
return (
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useArk } from '@libs/ark/provider';
|
||||
import { useArk } from '@libs/ark';
|
||||
import { NoteChildUser } from './childUser';
|
||||
|
||||
export function NoteChild({ eventId, isRoot }: { eventId: string; isRoot?: boolean }) {
|
||||
|
@ -2,7 +2,7 @@ import * as Avatar from '@radix-ui/react-avatar';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { minidenticon } from 'minidenticons';
|
||||
import { useMemo } from 'react';
|
||||
import { useArk } from '@libs/ark/provider';
|
||||
import { useArk } from '@libs/ark';
|
||||
import { displayNpub } from '@utils/formater';
|
||||
|
||||
export function NoteChildUser({ pubkey, subtext }: { pubkey: string; subtext: string }) {
|
||||
|
@ -1,10 +1,22 @@
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import { useRichContent } from '@utils/hooks/useRichContent';
|
||||
|
||||
export function NoteContent({ content }: { content: string }) {
|
||||
export function NoteContent({
|
||||
content,
|
||||
className,
|
||||
}: {
|
||||
content: string;
|
||||
className?: string;
|
||||
}) {
|
||||
const { parsedContent } = useRichContent(content);
|
||||
|
||||
return (
|
||||
<div className="break-p select-text whitespace-pre-line leading-normal">
|
||||
<div
|
||||
className={twMerge(
|
||||
'break-p select-text whitespace-pre-line leading-normal',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{parsedContent}
|
||||
</div>
|
||||
);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { NoteChild } from './child';
|
||||
import { NoteContent } from './content';
|
||||
import { NoteMenu } from './menu';
|
||||
import { NoteReaction } from './reaction';
|
||||
import { NoteReply } from './reply';
|
||||
import { NoteRepost } from './repost';
|
||||
@ -10,6 +11,7 @@ import { NoteZap } from './zap';
|
||||
export const Note = {
|
||||
Root: NoteRoot,
|
||||
User: NoteUser,
|
||||
Menu: NoteMenu,
|
||||
Content: NoteContent,
|
||||
Reply: NoteReply,
|
||||
Repost: NoteRepost,
|
||||
|
0
src/libs/ark/components/note/kinds/repost.tsx
Normal file
0
src/libs/ark/components/note/kinds/repost.tsx
Normal file
@ -1,5 +1,5 @@
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { useArk } from '@libs/ark/provider';
|
||||
import { useArk } from '@libs/ark';
|
||||
import { Note } from '..';
|
||||
|
||||
export function TextNote({ event }: { event: NDKEvent }) {
|
||||
@ -8,9 +8,12 @@ export function TextNote({ event }: { event: NDKEvent }) {
|
||||
|
||||
return (
|
||||
<Note.Root>
|
||||
<Note.User pubkey={event.pubkey} time={event.created_at} />
|
||||
<div className="flex h-14 items-center justify-between gap-2 px-3">
|
||||
<Note.User pubkey={event.pubkey} time={event.created_at} className="w-full" />
|
||||
<Note.Menu eventId={event.id} pubkey={event.pubkey} />
|
||||
</div>
|
||||
{thread ? (
|
||||
<div className="w-full px-3">
|
||||
<div className="mb-2 w-full px-3">
|
||||
<div className="flex h-min w-full flex-col gap-3 rounded-lg bg-neutral-100 p-3 dark:bg-neutral-900">
|
||||
{thread.rootEventId ? (
|
||||
<Note.Child eventId={thread.rootEventId} isRoot />
|
||||
@ -25,7 +28,7 @@ export function TextNote({ event }: { event: NDKEvent }) {
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
<Note.Content content={event.content} />
|
||||
<Note.Content content={event.content} className="px-3" />
|
||||
<div className="flex h-14 items-center justify-between px-3">
|
||||
<div />
|
||||
<div className="inline-flex items-center gap-10">
|
||||
|
64
src/libs/ark/components/note/menu.tsx
Normal file
64
src/libs/ark/components/note/menu.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
|
||||
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { EventPointer } from 'nostr-tools/lib/types/nip19';
|
||||
import { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { HorizontalDotsIcon } from '@shared/icons';
|
||||
|
||||
export function NoteMenu({ eventId, pubkey }: { eventId: string; pubkey: string }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const copyID = async () => {
|
||||
await writeText(nip19.neventEncode({ id: eventId, author: pubkey } as EventPointer));
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const copyLink = async () => {
|
||||
await writeText(
|
||||
'https://njump.me/' +
|
||||
nip19.neventEncode({ id: eventId, author: pubkey } as EventPointer)
|
||||
);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<DropdownMenu.Root open={open} onOpenChange={setOpen}>
|
||||
<DropdownMenu.Trigger asChild>
|
||||
<button type="button" className="inline-flex h-6 w-6 items-center justify-center">
|
||||
<HorizontalDotsIcon className="h-4 w-4 text-neutral-800 hover:text-blue-500 dark:text-neutral-200" />
|
||||
</button>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content className="flex w-[200px] flex-col overflow-hidden rounded-xl border border-neutral-200 bg-neutral-100 focus:outline-none dark:border-neutral-800 dark:bg-neutral-900">
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyLink()}
|
||||
className="inline-flex h-10 items-center px-4 text-sm text-neutral-900 hover:bg-neutral-200 focus:outline-none dark:text-neutral-100 dark:hover:bg-neutral-800"
|
||||
>
|
||||
Copy shareable link
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyID()}
|
||||
className="inline-flex h-10 items-center px-4 text-sm text-neutral-900 hover:bg-neutral-200 focus:outline-none dark:text-neutral-100 dark:hover:bg-neutral-800"
|
||||
>
|
||||
Copy ID
|
||||
</button>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item asChild>
|
||||
<Link
|
||||
to={`/users/${pubkey}`}
|
||||
className="inline-flex h-10 items-center px-4 text-sm text-neutral-900 hover:bg-neutral-200 focus:outline-none dark:text-neutral-100 dark:hover:bg-neutral-800"
|
||||
>
|
||||
View profile
|
||||
</Link>
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
</DropdownMenu.Root>
|
||||
);
|
||||
}
|
@ -10,7 +10,7 @@ export function NoteRoot({
|
||||
}) {
|
||||
return (
|
||||
<div className={twMerge('h-min w-full p-3', className)}>
|
||||
<div className="relative flex flex-col gap-2 overflow-hidden rounded-xl bg-neutral-50 dark:bg-neutral-950">
|
||||
<div className="relative flex flex-col overflow-hidden rounded-xl bg-neutral-50 dark:bg-neutral-950">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2,6 +2,7 @@ import * as Avatar from '@radix-ui/react-avatar';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { minidenticon } from 'minidenticons';
|
||||
import { useMemo } from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import { useArk } from '@libs/ark';
|
||||
import { RepostIcon } from '@shared/icons';
|
||||
import { displayNpub, formatCreatedAt } from '@utils/formater';
|
||||
@ -10,10 +11,12 @@ export function NoteUser({
|
||||
pubkey,
|
||||
time,
|
||||
variant = 'text',
|
||||
className,
|
||||
}: {
|
||||
pubkey: string;
|
||||
time: number;
|
||||
variant?: 'text' | 'repost';
|
||||
className?: string;
|
||||
}) {
|
||||
const ark = useArk();
|
||||
const createdAt = useMemo(() => formatCreatedAt(time), [time]);
|
||||
@ -48,7 +51,7 @@ export function NoteUser({
|
||||
if (variant === 'repost') {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex gap-3">
|
||||
<div className={twMerge('flex gap-3', className)}>
|
||||
<div className="inline-flex w-10 items-center justify-center">
|
||||
<RepostIcon className="h-5 w-5 text-blue-500" />
|
||||
</div>
|
||||
@ -61,7 +64,7 @@ export function NoteUser({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<div className={twMerge('flex gap-2', className)}>
|
||||
<div className="inline-flex w-10 items-center justify-center">
|
||||
<RepostIcon className="h-5 w-5 text-blue-500" />
|
||||
</div>
|
||||
@ -95,7 +98,7 @@ export function NoteUser({
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={twMerge('flex items-center gap-3', className)}>
|
||||
<Avatar.Root className="h-9 w-9 shrink-0">
|
||||
<Avatar.Image
|
||||
src={fallbackAvatar}
|
||||
@ -113,7 +116,7 @@ export function NoteUser({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={twMerge('flex items-center gap-3', className)}>
|
||||
<Avatar.Root className="h-9 w-9 shrink-0">
|
||||
<Avatar.Image
|
||||
src={user?.picture || user?.image}
|
||||
@ -130,13 +133,11 @@ export function NoteUser({
|
||||
/>
|
||||
</Avatar.Fallback>
|
||||
</Avatar.Root>
|
||||
<div className="flex h-6 flex-1 items-start gap-2">
|
||||
<div className="flex h-6 flex-1 items-start justify-between gap-2">
|
||||
<div className="max-w-[15rem] truncate font-semibold text-neutral-950 dark:text-neutral-50">
|
||||
{user?.name || user?.display_name || user?.displayName || fallbackName}
|
||||
</div>
|
||||
<div className="ml-auto inline-flex items-center gap-3">
|
||||
<div className="text-neutral-500 dark:text-neutral-400">{createdAt}</div>
|
||||
</div>
|
||||
<div className="text-neutral-500 dark:text-neutral-400">{createdAt}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -4,9 +4,9 @@ import { ReactNode } from 'react';
|
||||
import {
|
||||
ArrowLeftIcon,
|
||||
ArrowRightIcon,
|
||||
HomeIcon,
|
||||
HorizontalDotsIcon,
|
||||
RefreshIcon,
|
||||
ThreadIcon,
|
||||
TrashIcon,
|
||||
} from '@shared/icons';
|
||||
import { useWidget } from '@utils/hooks/useWidget';
|
||||
@ -19,14 +19,14 @@ export function WidgetHeader({
|
||||
}: {
|
||||
id: string;
|
||||
title: string;
|
||||
queryKey?: string;
|
||||
queryKey?: string[];
|
||||
icon?: ReactNode;
|
||||
}) {
|
||||
const queryClient = useQueryClient();
|
||||
const { removeWidget } = useWidget();
|
||||
|
||||
const refresh = async () => {
|
||||
if (queryKey) await queryClient.refetchQueries({ queryKey: [queryKey] });
|
||||
if (queryKey) await queryClient.refetchQueries({ queryKey });
|
||||
};
|
||||
|
||||
const moveLeft = async () => {
|
||||
@ -46,7 +46,7 @@ export function WidgetHeader({
|
||||
<div className="inline-flex items-center gap-4">
|
||||
<div className="h-5 w-1 rounded-full bg-blue-500" />
|
||||
<div className="inline-flex items-center gap-2">
|
||||
{icon ? icon : <HomeIcon className="h-5 w-5" />}
|
||||
{icon ? icon : <ThreadIcon className="h-5 w-5" />}
|
||||
<div className="text-sm font-medium">{title}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -18,7 +18,7 @@ export function ActiveAccount() {
|
||||
encodeURIComponent(minidenticon(ark.account.pubkey, 90, 50));
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-1 rounded-lg bg-neutral-100 p-1 ring-1 ring-transparent hover:bg-neutral-200 hover:ring-blue-500 dark:bg-neutral-900 dark:hover:bg-neutral-800">
|
||||
<div className="flex flex-col gap-1 rounded-lg bg-black/10 p-1 ring-1 ring-transparent hover:bg-black/20 hover:ring-blue-500 dark:bg-white/10 dark:hover:bg-white/20">
|
||||
<Link to="/settings/" className="relative inline-block">
|
||||
<Avatar.Root>
|
||||
<Avatar.Image
|
||||
|
18
src/shared/icons/depot.tsx
Normal file
18
src/shared/icons/depot.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
export function DepotIcon(props: JSX.IntrinsicElements['svg']) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
>
|
||||
<path d="M20 5.7V12m0-6.3c0 1.491-3.582 2.7-8 2.7S4 7.191 4 5.7m16 0C20 4.209 16.418 3 12 3S4 4.209 4 5.7M20 12v6.131C20 19.716 16.418 21 12 21s-8-1.284-8-2.869V12m16 0c0 1.491-3.582 2.7-8 2.7S4 13.491 4 12m0 0V5.7M16 11h.01M16 17h.01" />
|
||||
</svg>
|
||||
);
|
||||
}
|
@ -85,3 +85,5 @@ export * from './light';
|
||||
export * from './dark';
|
||||
export * from './system';
|
||||
export * from './announcement';
|
||||
export * from './depot';
|
||||
export * from './search';
|
||||
|
@ -1,19 +1,18 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
export function NwcIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
export function NwcIcon(props: JSX.IntrinsicElements['svg']) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M14.002 2.401c0-1.484-1.925-2.066-2.748-.832L3.188 13.668c-.665.997.05 2.332 1.248 2.332h5.566V21.6c0 1.484 1.925 2.067 2.748.832l8.066-12.099C21.48 9.335 20.766 8 19.568 8h-5.566V2.401z"
|
||||
></path>
|
||||
<path d="M2 14.5V11c0-2.8 0-4.2.545-5.27A5 5 0 0 1 4.73 3.545C5.8 3 7.2 3 10 3h3.5c1.398 0 2.097 0 2.648.228a3 3 0 0 1 1.624 1.624c.207.5.226 1.123.228 2.28M2 14.5c0 1.33 0 2.495.38 3.413a5 5 0 0 0 2.707 2.706c.696.289 1.534.359 2.913.376M2 14.5c0-2.33 0-3.495.38-4.413A5 5 0 0 1 5.088 7.38C6.005 7 7.17 7 9.5 7h5c1.634 0 2.695 0 3.5.131M14 12h3m1-4.869c.343.056.639.136.913.25a5 5 0 0 1 2.706 2.706c.289.696.359 1.534.376 2.913m-3.03 3h.037A2.999 2.999 0 0 1 22 19c0 1.657-1.342 3-2.998 3h-.037m-3.93-6h-.037A2.999 2.999 0 0 0 12 19c0 1.657 1.342 3 2.998 3h.037m.962-3h1.999" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
export function PlusIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
export function PlusIcon(props: JSX.IntrinsicElements['svg']) {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path
|
||||
d="M12 3.75V12M12 12V20.25M12 12H3.75M12 12H20.25"
|
||||
stroke="currentColor"
|
||||
strokeWidth={1.5}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
>
|
||||
<path d="M12 19v-7m0 0V5m0 7H5m7 0h7" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
@ -1,21 +1,18 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
export function RelayIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
export function RelayIcon(props: JSX.IntrinsicElements['svg']) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
fillRule="evenodd"
|
||||
d="M4 5a3 3 0 013-3h10a3 3 0 013 3v11c0 .889-.386 1.687-1 2.236V20a2 2 0 01-2 2H7a2 2 0 01-2-2v-1.75-.014c-.614-.55-1-1.348-1-2.236V5zm3-1a1 1 0 00-1 1v11a1 1 0 001 1h10a1 1 0 001-1V5a1 1 0 00-1-1H7zm0 2a1 1 0 011-1h8a1 1 0 011 1v6a1 1 0 01-1 1H8a1 1 0 01-1-1V6zm6 9a1 1 0 011-1h2a1 1 0 110 2h-2a1 1 0 01-1-1z"
|
||||
clipRule="evenodd"
|
||||
></path>
|
||||
<path d="M7 12h10M7 12c-.464 0-.697 0-.892.022a3.5 3.5 0 0 0-3.086 3.086C3 15.303 3 15.536 3 16s0 .697.022.892a3.5 3.5 0 0 0 3.086 3.086C6.303 20 6.536 20 7 20h10c.464 0 .697 0 .892-.022a3.5 3.5 0 0 0 3.086-3.086C21 16.697 21 16.464 21 16s0-.697-.022-.892a3.5 3.5 0 0 0-3.086-3.086C17.697 12 17.464 12 17 12M7 12c-.464 0-.697 0-.892-.022a3.5 3.5 0 0 1-3.086-3.086C3 8.697 3 8.464 3 8s0-.697.022-.892a3.5 3.5 0 0 1 3.086-3.086C6.303 4 6.536 4 7 4h10c.464 0 .697 0 .892.022a3.5 3.5 0 0 1 3.086 3.086C21 7.303 21 7.536 21 8s0 .697-.022.892a3.5 3.5 0 0 1-3.086 3.086C17.697 12 17.464 12 17 12m-4-4h.01M17 8h.01M13 16h.01M17 16h.01" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
18
src/shared/icons/search.tsx
Normal file
18
src/shared/icons/search.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
export function SearchIcon(props: JSX.IntrinsicElements['svg']) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
>
|
||||
<path d="m21 21-3.49-3.49m0 0A8.5 8.5 0 1 0 5.49 5.49a8.5 8.5 0 0 0 12.02 12.02Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
@ -1,19 +1,18 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
export function ThreadIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
export function ThreadIcon(props: JSX.IntrinsicElements['svg']) {
|
||||
return (
|
||||
<svg
|
||||
{...props}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 19v1a1 1 0 001-1h-1zm8-9a1 1 0 102 0h-2zm0 4a1 1 0 10-2 0h2zm-2 6a1 1 0 102 0h-2zm-2-4a1 1 0 100 2v-2zm6 2a1 1 0 100-2v2zM4 17V7H2v10h2zm8 1H5v2h7v-2zm8-11v3h2V7h-2zM5 6h7V4H5v2zm7 0h7V4h-7v2zm1 13V5h-2v14h2zm5-5v3h2v-3h-2zm0 3v3h2v-3h-2zm-2 1h3v-2h-3v2zm3 0h3v-2h-3v2zm3-11a3 3 0 00-3-3v2a1 1 0 011 1h2zM4 7a1 1 0 011-1V4a3 3 0 00-3 3h2zM2 17a3 3 0 003 3v-2a1 1 0 01-1-1H2z"
|
||||
></path>
|
||||
<path d="M16.193 18.866c.143 0 .306.012.632.036l1.938.138c.771.055 1.157.083 1.446-.054.253-.12.457-.324.577-.577.137-.289.11-.675.054-1.446l-.138-1.938a10.8 10.8 0 0 1-.036-.632c-.002-.232-.005-.15.013-.38.01-.143.088-.685.24-1.768A8.1 8.1 0 0 0 5.642 7.5m8.159 8.1a5.4 5.4 0 1 0-10.733.856c.096.6.144.9.152.992.012.139.011.108.01.247 0 .093-.008.204-.023.428l-.1 1.385c-.036.515-.055.772.037.965a.81.81 0 0 0 .385.384c.192.092.45.073.964.037l1.385-.1a6.97 6.97 0 0 1 .428-.024c.14 0 .108-.001.247.011.093.008.393.056.992.152a5.387 5.387 0 0 0 4.893-1.745 5.38 5.38 0 0 0 1.363-3.588Z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
@ -1,114 +1,92 @@
|
||||
import { Platform } from '@tauri-apps/plugin-os';
|
||||
import { NavLink, Outlet, useNavigate } from 'react-router-dom';
|
||||
import { NavLink, Outlet } from 'react-router-dom';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import {
|
||||
AdvancedSettingsIcon,
|
||||
ArrowLeftIcon,
|
||||
InfoIcon,
|
||||
SecureIcon,
|
||||
SettingsIcon,
|
||||
UserIcon,
|
||||
} from '@shared/icons';
|
||||
import { WindowTitleBar } from '@shared/titlebar';
|
||||
|
||||
export function SettingsLayout({ platform }: { platform: Platform }) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
export function SettingsLayout() {
|
||||
return (
|
||||
<div className="flex h-screen w-screen flex-col bg-neutral-50 dark:bg-neutral-950">
|
||||
{platform !== 'macos' ? (
|
||||
<WindowTitleBar platform={platform} />
|
||||
) : (
|
||||
<div data-tauri-drag-region className="h-9 shrink-0" />
|
||||
)}
|
||||
<div className="flex h-full min-h-0 w-full flex-col gap-8 overflow-y-auto">
|
||||
<div className="flex h-20 w-full items-center justify-between border-b border-neutral-200 px-2 pb-2 dark:border-neutral-900">
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => navigate(-1)}
|
||||
className="inline-flex h-12 w-12 items-center justify-center rounded-xl"
|
||||
>
|
||||
<ArrowLeftIcon className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex items-center gap-0.5">
|
||||
<NavLink
|
||||
to="/settings/"
|
||||
end
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',
|
||||
isActive
|
||||
? 'bg-neutral-50 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900'
|
||||
: ''
|
||||
)
|
||||
}
|
||||
>
|
||||
<UserIcon className="h-6 w-6" />
|
||||
<p className="text-sm font-medium">User</p>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="/settings/general"
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',
|
||||
isActive
|
||||
? 'bg-neutral-50 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900'
|
||||
: ''
|
||||
)
|
||||
}
|
||||
>
|
||||
<SettingsIcon className="h-6 w-6" />
|
||||
<p className="text-sm font-medium">General</p>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="/settings/backup"
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',
|
||||
isActive
|
||||
? 'bg-neutral-50 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900'
|
||||
: ''
|
||||
)
|
||||
}
|
||||
>
|
||||
<SecureIcon className="h-6 w-6" />
|
||||
<p className="text-sm font-medium">Backup</p>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="/settings/advanced"
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',
|
||||
isActive
|
||||
? 'bg-neutral-50 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900'
|
||||
: ''
|
||||
)
|
||||
}
|
||||
>
|
||||
<AdvancedSettingsIcon className="h-6 w-6" />
|
||||
<p className="text-sm font-medium">Advanced</p>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="/settings/about"
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',
|
||||
isActive
|
||||
? 'bg-neutral-50 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900'
|
||||
: ''
|
||||
)
|
||||
}
|
||||
>
|
||||
<InfoIcon className="h-6 w-6" />
|
||||
<p className="text-sm font-medium">About</p>
|
||||
</NavLink>
|
||||
</div>
|
||||
<div />
|
||||
<div className="flex h-full min-h-0 w-full flex-col gap-8 overflow-y-auto">
|
||||
<div className="flex h-24 w-full items-center justify-center border-b border-neutral-200 px-2 dark:border-neutral-900">
|
||||
<div className="flex items-center gap-0.5">
|
||||
<NavLink
|
||||
to="/settings/"
|
||||
end
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',
|
||||
isActive
|
||||
? 'bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-900'
|
||||
: ''
|
||||
)
|
||||
}
|
||||
>
|
||||
<UserIcon className="h-6 w-6" />
|
||||
<p className="text-sm font-medium">User</p>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="/settings/general"
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',
|
||||
isActive
|
||||
? 'bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-900'
|
||||
: ''
|
||||
)
|
||||
}
|
||||
>
|
||||
<SettingsIcon className="h-6 w-6" />
|
||||
<p className="text-sm font-medium">General</p>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="/settings/backup"
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',
|
||||
isActive
|
||||
? 'bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-900'
|
||||
: ''
|
||||
)
|
||||
}
|
||||
>
|
||||
<SecureIcon className="h-6 w-6" />
|
||||
<p className="text-sm font-medium">Backup</p>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="/settings/advanced"
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',
|
||||
isActive
|
||||
? 'bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-900'
|
||||
: ''
|
||||
)
|
||||
}
|
||||
>
|
||||
<AdvancedSettingsIcon className="h-6 w-6" />
|
||||
<p className="text-sm font-medium">Advanced</p>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="/settings/about"
|
||||
className={({ isActive }) =>
|
||||
twMerge(
|
||||
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',
|
||||
isActive
|
||||
? 'bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-900'
|
||||
: ''
|
||||
)
|
||||
}
|
||||
>
|
||||
<InfoIcon className="h-6 w-6" />
|
||||
<p className="text-sm font-medium">About</p>
|
||||
</NavLink>
|
||||
</div>
|
||||
<Outlet />
|
||||
</div>
|
||||
<Outlet />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,12 +1,16 @@
|
||||
import { Link, NavLink } from 'react-router-dom';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import { ActiveAccount } from '@shared/accounts/active';
|
||||
import { ChatsIcon, ComposeIcon, HomeIcon, NwcIcon, RelayIcon } from '@shared/icons';
|
||||
import { compactNumber } from '@utils/formater';
|
||||
import {
|
||||
DepotIcon,
|
||||
HomeIcon,
|
||||
NwcIcon,
|
||||
PlusIcon,
|
||||
RelayIcon,
|
||||
SearchIcon,
|
||||
} from '@shared/icons';
|
||||
|
||||
export function Navigation() {
|
||||
const newMessages = 0;
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col justify-between p-3">
|
||||
<div className="flex flex-1 flex-col gap-5">
|
||||
@ -19,7 +23,7 @@ export function Navigation() {
|
||||
<>
|
||||
<div
|
||||
className={twMerge(
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-lg',
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-xl',
|
||||
isActive
|
||||
? 'bg-black/10 text-black dark:bg-white/10 dark:text-white'
|
||||
: 'text-black/50 dark:text-neutral-400'
|
||||
@ -27,33 +31,14 @@ export function Navigation() {
|
||||
>
|
||||
<HomeIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="text-sm font-medium text-black dark:text-white">Home</div>
|
||||
</>
|
||||
)}
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="/chats"
|
||||
preventScrollReset={true}
|
||||
className="inline-flex flex-col items-center justify-center"
|
||||
>
|
||||
{({ isActive }) => (
|
||||
<>
|
||||
<div
|
||||
className={twMerge(
|
||||
'relative 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'
|
||||
'text-sm text-black dark:text-white',
|
||||
isActive ? 'font-semibold' : 'font-medium'
|
||||
)}
|
||||
>
|
||||
<ChatsIcon className="h-6 w-6" />
|
||||
{newMessages > 0 ? (
|
||||
<div className="absolute right-0 top-0 inline-flex h-5 w-5 items-center justify-center rounded-full bg-blue-500 text-[9px] font-medium text-white">
|
||||
{compactNumber.format(newMessages)}
|
||||
</div>
|
||||
) : null}
|
||||
Home
|
||||
</div>
|
||||
<div className="text-sm font-medium text-black dark:text-white">Chats</div>
|
||||
</>
|
||||
)}
|
||||
</NavLink>
|
||||
@ -66,7 +51,7 @@ export function Navigation() {
|
||||
<>
|
||||
<div
|
||||
className={twMerge(
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-lg',
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-xl',
|
||||
isActive
|
||||
? 'bg-black/10 text-black dark:bg-white/10 dark:text-white'
|
||||
: 'text-black/50 dark:text-neutral-400'
|
||||
@ -74,7 +59,14 @@ export function Navigation() {
|
||||
>
|
||||
<RelayIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="text-sm font-medium text-black dark:text-white">Relays</div>
|
||||
<div
|
||||
className={twMerge(
|
||||
'text-sm text-black dark:text-white',
|
||||
isActive ? 'font-semibold' : 'font-medium'
|
||||
)}
|
||||
>
|
||||
Relays
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</NavLink>
|
||||
@ -87,15 +79,50 @@ export function Navigation() {
|
||||
<>
|
||||
<div
|
||||
className={twMerge(
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-lg',
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-xl',
|
||||
isActive
|
||||
? 'bg-black/10 text-black dark:bg-white/10 dark:text-white'
|
||||
: 'text-black/50 dark:text-neutral-400'
|
||||
)}
|
||||
>
|
||||
<RelayIcon className="h-6 w-6" />
|
||||
<DepotIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div
|
||||
className={twMerge(
|
||||
'text-sm text-black dark:text-white',
|
||||
isActive ? 'font-semibold' : 'font-medium'
|
||||
)}
|
||||
>
|
||||
Depot
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="/nwc"
|
||||
preventScrollReset={true}
|
||||
className="inline-flex flex-col items-center justify-center"
|
||||
>
|
||||
{({ isActive }) => (
|
||||
<>
|
||||
<div
|
||||
className={twMerge(
|
||||
'inline-flex aspect-square h-auto w-full items-center justify-center rounded-xl',
|
||||
isActive
|
||||
? 'bg-black/10 text-black dark:bg-white/10 dark:text-white'
|
||||
: 'text-black/50 dark:text-neutral-400'
|
||||
)}
|
||||
>
|
||||
<NwcIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div
|
||||
className={twMerge(
|
||||
'text-sm text-black dark:text-white',
|
||||
isActive ? 'font-semibold' : 'font-medium'
|
||||
)}
|
||||
>
|
||||
Wallet
|
||||
</div>
|
||||
<div className="text-sm font-medium text-black dark:text-white">Depot</div>
|
||||
</>
|
||||
)}
|
||||
</NavLink>
|
||||
@ -103,15 +130,15 @@ export function Navigation() {
|
||||
<div className="flex shrink-0 flex-col gap-3 p-1">
|
||||
<Link
|
||||
to="/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"
|
||||
className="flex aspect-square h-auto w-full items-center justify-center rounded-xl bg-black/10 text-black hover:bg-blue-500 hover:text-white dark:bg-white/10 dark:text-white dark:hover:bg-blue-500"
|
||||
>
|
||||
<ComposeIcon className="h-5 w-5" />
|
||||
<PlusIcon 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"
|
||||
className="flex aspect-square h-auto w-full items-center justify-center rounded-xl bg-black/10 hover:bg-blue-500 hover:text-white dark:bg-white/10 dark:hover:bg-blue-500"
|
||||
>
|
||||
<NwcIcon className="h-5 w-5" />
|
||||
<SearchIcon className="h-5 w-5" />
|
||||
</Link>
|
||||
<ActiveAccount />
|
||||
</div>
|
||||
|
@ -69,6 +69,7 @@ export function NewsfeedWidget() {
|
||||
<Widget.Root>
|
||||
<Widget.Header
|
||||
id="9999"
|
||||
queryKey={['newsfeed']}
|
||||
title="Timeline"
|
||||
icon={<TimelineIcon className="h-5 w-5" />}
|
||||
/>
|
||||
|
@ -126,6 +126,7 @@ export function NotificationWidget() {
|
||||
<Widget.Root>
|
||||
<Widget.Header
|
||||
id="9998"
|
||||
queryKey={['notification']}
|
||||
title="Notification"
|
||||
icon={<AnnouncementIcon className="h-5 w-5" />}
|
||||
/>
|
||||
@ -138,8 +139,8 @@ export function NotificationWidget() {
|
||||
</div>
|
||||
</div>
|
||||
) : allEvents.length < 1 ? (
|
||||
<div className="flex h-[400px] w-full flex-col items-center justify-center">
|
||||
<p className="mb-2 text-4xl">🎉</p>
|
||||
<div className="my-3 flex w-full items-center justify-center gap-2">
|
||||
<div>🎉</div>
|
||||
<p className="text-center font-medium text-neutral-900 dark:text-neutral-100">
|
||||
Hmm! Nothing new yet.
|
||||
</p>
|
||||
|
Loading…
x
Reference in New Issue
Block a user