redesign sidebar

This commit is contained in:
Ren Amamiya 2023-08-01 14:26:16 +07:00
parent 9941305998
commit e97d0281e2
22 changed files with 310 additions and 200 deletions

View File

@ -4,7 +4,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lume</title> <title>Lume</title>
</head> </head>
<body class="cursor-default select-none overflow-hidden font-sans antialiased h-screen w-screen bg-white dark:bg-black text-black dark:text-white"> <body class="relative cursor-default select-none overflow-hidden font-sans antialiased h-screen w-screen text-white">
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
</body> </body>

View File

@ -20,6 +20,7 @@
"@headlessui/react": "^1.7.16", "@headlessui/react": "^1.7.16",
"@nostr-dev-kit/ndk": "^0.7.7", "@nostr-dev-kit/ndk": "^0.7.7",
"@nostr-fetch/adapter-ndk": "^0.11.0", "@nostr-fetch/adapter-ndk": "^0.11.0",
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-popover": "^1.0.6",
"@radix-ui/react-tooltip": "^1.0.6", "@radix-ui/react-tooltip": "^1.0.6",

View File

@ -10,6 +10,9 @@ dependencies:
'@nostr-fetch/adapter-ndk': '@nostr-fetch/adapter-ndk':
specifier: ^0.11.0 specifier: ^0.11.0
version: 0.11.0(@nostr-dev-kit/ndk@0.7.7)(nostr-fetch@0.12.2) version: 0.11.0(@nostr-dev-kit/ndk@0.7.7)(nostr-fetch@0.12.2)
'@radix-ui/react-collapsible':
specifier: ^1.0.3
version: 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.18)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-dialog': '@radix-ui/react-dialog':
specifier: ^1.0.4 specifier: ^1.0.4
version: 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.18)(react-dom@18.2.0)(react@18.2.0) version: 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.18)(react-dom@18.2.0)(react@18.2.0)
@ -1084,6 +1087,34 @@ packages:
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
dev: false dev: false
/@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.18)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
dependencies:
'@babel/runtime': 7.22.6
'@radix-ui/primitive': 1.0.1
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.18)(react@18.2.0)
'@radix-ui/react-context': 1.0.1(@types/react@18.2.18)(react@18.2.0)
'@radix-ui/react-id': 1.0.1(@types/react@18.2.18)(react@18.2.0)
'@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.18)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.18)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.18)(react@18.2.0)
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.18)(react@18.2.0)
'@types/react': 18.2.18
'@types/react-dom': 18.2.7
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.18)(react@18.2.0): /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.18)(react@18.2.0):
resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
peerDependencies: peerDependencies:

106
src-tauri/Cargo.lock generated
View File

@ -182,7 +182,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6041616acea41d67c4a984709ddab1587fd0b10efe5cc563fee954d2f011854" checksum = "d6041616acea41d67c4a984709ddab1587fd0b10efe5cc563fee954d2f011854"
dependencies = [ dependencies = [
"clipboard-win", "clipboard-win",
"core-graphics", "core-graphics 0.22.3",
"image", "image",
"log", "log",
"objc", "objc",
@ -787,8 +787,24 @@ dependencies = [
"block", "block",
"cocoa-foundation", "cocoa-foundation",
"core-foundation", "core-foundation",
"core-graphics", "core-graphics 0.22.3",
"foreign-types", "foreign-types 0.3.2",
"libc",
"objc",
]
[[package]]
name = "cocoa"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c"
dependencies = [
"bitflags 1.3.2",
"block",
"cocoa-foundation",
"core-foundation",
"core-graphics 0.23.1",
"foreign-types 0.5.0",
"libc", "libc",
"objc", "objc",
] ]
@ -803,7 +819,7 @@ dependencies = [
"block", "block",
"core-foundation", "core-foundation",
"core-graphics-types", "core-graphics-types",
"foreign-types", "foreign-types 0.3.2",
"libc", "libc",
"objc", "objc",
] ]
@ -901,7 +917,20 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"core-foundation", "core-foundation",
"core-graphics-types", "core-graphics-types",
"foreign-types", "foreign-types 0.3.2",
"libc",
]
[[package]]
name = "core-graphics"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"core-graphics-types",
"foreign-types 0.5.0",
"libc", "libc",
] ]
@ -1465,7 +1494,28 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [ dependencies = [
"foreign-types-shared", "foreign-types-shared 0.1.1",
]
[[package]]
name = "foreign-types"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
dependencies = [
"foreign-types-macros",
"foreign-types-shared 0.3.1",
]
[[package]]
name = "foreign-types-macros"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.27",
] ]
[[package]] [[package]]
@ -1474,6 +1524,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "foreign-types-shared"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
[[package]] [[package]]
name = "form_urlencoded" name = "form_urlencoded"
version = "1.2.0" version = "1.2.0"
@ -2562,7 +2618,7 @@ dependencies = [
name = "lume" name = "lume"
version = "1.1.1" version = "1.1.1"
dependencies = [ dependencies = [
"cocoa", "cocoa 0.24.1",
"objc", "objc",
"rand 0.8.5", "rand 0.8.5",
"rust-argon2", "rust-argon2",
@ -2587,6 +2643,8 @@ dependencies = [
"tauri-plugin-updater", "tauri-plugin-updater",
"tauri-plugin-upload", "tauri-plugin-upload",
"tauri-plugin-window", "tauri-plugin-window",
"window-shadows",
"window-vibrancy",
] ]
[[package]] [[package]]
@ -4652,9 +4710,9 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"cairo-rs", "cairo-rs",
"cc", "cc",
"cocoa", "cocoa 0.24.1",
"core-foundation", "core-foundation",
"core-graphics", "core-graphics 0.22.3",
"crossbeam-channel", "crossbeam-channel",
"dirs-next", "dirs-next",
"dispatch", "dispatch",
@ -4728,7 +4786,7 @@ checksum = "2e18377a75e314aa1d476896af881ed63f57a78ca84889fe63e69067f0de158d"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
"cocoa", "cocoa 0.24.1",
"dirs-next", "dirs-next",
"embed_plist", "embed_plist",
"futures-util", "futures-util",
@ -5091,7 +5149,7 @@ version = "0.13.0-alpha.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1231be42085f3a8b150e615601f8a070bd16bf579771a5dafe2931970a05b518" checksum = "1231be42085f3a8b150e615601f8a070bd16bf579771a5dafe2931970a05b518"
dependencies = [ dependencies = [
"cocoa", "cocoa 0.24.1",
"gtk", "gtk",
"jni", "jni",
"percent-encoding", "percent-encoding",
@ -5857,6 +5915,28 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "window-shadows"
version = "0.2.1"
source = "git+https://github.com/tauri-apps/window-shadows?branch=dev#dd8ca283fa50b1484043e686fa0b1e45ba5a969d"
dependencies = [
"cocoa 0.25.0",
"objc",
"raw-window-handle",
"windows-sys 0.48.0",
]
[[package]]
name = "window-vibrancy"
version = "0.4.0"
source = "git+https://github.com/tauri-apps/window-vibrancy?branch=dev#d1b349f3c3f524ffd3ba37b64349ec6ad6410272"
dependencies = [
"cocoa 0.25.0",
"objc",
"raw-window-handle",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "windows" name = "windows"
version = "0.36.1" version = "0.36.1"
@ -6175,8 +6255,8 @@ checksum = "7d15f9f827d537cefe6d047be3930f5d89b238dfb85e08ba6a319153217635aa"
dependencies = [ dependencies = [
"base64 0.13.1", "base64 0.13.1",
"block", "block",
"cocoa", "cocoa 0.24.1",
"core-graphics", "core-graphics 0.22.3",
"crossbeam-channel", "crossbeam-channel",
"dunce", "dunce",
"gdk", "gdk",

View File

@ -16,7 +16,7 @@ tauri-build = { version = "2.0.0-alpha.6", features = [] }
[dependencies] [dependencies]
serde_json = "1.0" serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tauri = { version = "2.0.0-alpha.10", features = ["system-tray"] } tauri = { version = "2.0.0-alpha.10", features = [ "macos-private-api", "system-tray"] }
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-stronghold = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-stronghold = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
@ -32,6 +32,8 @@ tauri-plugin-process = { git = "https://github.com/tauri-apps/plugins-workspace"
tauri-plugin-os = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-os = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-window = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-window = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
window-shadows = { git = "https://github.com/tauri-apps/window-shadows", branch = "dev" }
window-vibrancy = { git = "https://github.com/tauri-apps/window-vibrancy", branch = "dev" }
sqlx-cli = { version = "0.7.0", default-features = false, features = [ sqlx-cli = { version = "0.7.0", default-features = false, features = [
"sqlite", "sqlite",
] } ] }

View File

@ -7,6 +7,8 @@
use tauri::{Manager}; use tauri::{Manager};
use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_autostart::MacosLauncher;
use tauri_plugin_sql::{Migration, MigrationKind}; use tauri_plugin_sql::{Migration, MigrationKind};
use window_shadows::set_shadow;
use window_vibrancy::{apply_blur, apply_vibrancy, NSVisualEffectMaterial};
#[derive(Clone, serde::Serialize)] #[derive(Clone, serde::Serialize)]
struct Payload { struct Payload {
@ -136,6 +138,22 @@ fn main() {
.plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_window::init()) .plugin(tauri_plugin_window::init())
.plugin(tauri_plugin_store::Builder::default().build()) .plugin(tauri_plugin_store::Builder::default().build())
.setup(|app| {
let window = app.get_window("main").unwrap();
// native shadow
set_shadow(&window, true).expect("Unsupported platform!");
#[cfg(target_os = "macos")]
apply_vibrancy(&window, NSVisualEffectMaterial::HudWindow, None, None)
.expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS");
#[cfg(target_os = "windows")]
apply_blur(&window, Some((18, 18, 18, 125)))
.expect("Unsupported platform! 'apply_blur' is only supported on Windows");
Ok(())
})
.run(tauri::generate_context!()) .run(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application");
} }

View File

@ -103,10 +103,11 @@
"theme": "Dark", "theme": "Dark",
"title": "Lume", "title": "Lume",
"titleBarStyle": "Overlay", "titleBarStyle": "Overlay",
"transparent": false, "transparent": true,
"width": 1080, "width": 1080,
"center": true "center": true
} }
] ],
"macOSPrivateApi": true
} }
} }

View File

@ -6,14 +6,14 @@ import { Image } from '@shared/image';
import { DEFAULT_AVATAR } from '@stores/constants'; import { DEFAULT_AVATAR } from '@stores/constants';
import { useProfile } from '@utils/hooks/useProfile'; import { useProfile } from '@utils/hooks/useProfile';
import { shortenKey } from '@utils/shortenKey'; import { displayNpub } from '@utils/shortenKey';
export function ChatsListItem({ data }: { data: any }) { export function ChatsListItem({ data }: { data: any }) {
const { status, user } = useProfile(data.sender_pubkey); const { status, user } = useProfile(data.sender_pubkey);
if (status === 'loading') { if (status === 'loading') {
return ( return (
<div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5"> <div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2">
<div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" /> <div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" />
<div className="h-2.5 w-2/3 animate-pulse rounded bg-zinc-800" /> <div className="h-2.5 w-2/3 animate-pulse rounded bg-zinc-800" />
</div> </div>
@ -26,28 +26,24 @@ export function ChatsListItem({ data }: { data: any }) {
preventScrollReset={true} preventScrollReset={true}
className={({ isActive }) => className={({ isActive }) =>
twMerge( twMerge(
'inline-flex h-9 items-center gap-2.5 rounded-md px-2.5', 'inline-flex h-9 items-center gap-2.5 rounded-md px-2',
isActive ? 'bg-zinc-900/50 text-zinc-100' : '' isActive ? 'bg-white/10 text-white' : 'text-white/80'
) )
} }
> >
<div className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded border-t border-zinc-800/50 bg-zinc-900"> <Image
<Image src={user?.picture || user?.image}
src={user?.picture || user?.image} fallback={DEFAULT_AVATAR}
fallback={DEFAULT_AVATAR} alt={data.sender_pubkey}
alt={data.sender_pubkey} className="h-6 w-6 shrink-0 rounded object-cover"
className="h-6 w-6 rounded object-cover" />
/> <div className="inline-flex w-full flex-1 items-center justify-between">
</div> <h5 className="max-w-[10rem] truncate">
<div className="inline-flex w-full items-center justify-between"> {user?.nip05 ||
<div className="inline-flex items-baseline gap-1"> user?.name ||
<h5 className="max-w-[10rem] truncate font-medium text-zinc-200"> user?.displayName ||
{user?.nip05 || displayNpub(data.sender_pubkey, 16)}
user?.name || </h5>
user?.displayName ||
shortenKey(data.sender_pubkey)}
</h5>
</div>
<div className="flex items-center"> <div className="flex items-center">
{data.new_messages > 0 && ( {data.new_messages > 0 && (
<span className="inline-flex w-8 items-center justify-center rounded bg-fuchsia-400/10 px-1 py-1 text-xs font-medium text-fuchsia-500 ring-1 ring-inset ring-fuchsia-400/20"> <span className="inline-flex w-8 items-center justify-center rounded bg-fuchsia-400/10 px-1 py-1 text-xs font-medium text-fuchsia-500 ring-1 ring-inset ring-fuchsia-400/20">

View File

@ -50,20 +50,20 @@ export function ChatsList() {
{account ? ( {account ? (
<ChatsListSelfItem data={account} /> <ChatsListSelfItem data={account} />
) : ( ) : (
<div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5"> <div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2">
<div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" /> <div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" />
<div className="h-3 w-full animate-pulse rounded-sm bg-zinc-800" /> <div className="h-3 w-full animate-pulse rounded-sm bg-zinc-800" />
</div> </div>
)} )}
{chats.follows.map((item) => renderItem(item))} {chats.follows.map((item) => renderItem(item))}
{chats.unknowns.length > 0 && <UnknownsModal data={chats.unknowns} />}
<NewMessageModal />
{isFetching && ( {isFetching && (
<div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5"> <div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2">
<div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" /> <div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" />
<div className="h-3 w-full animate-pulse rounded-sm bg-zinc-800" /> <div className="h-3 w-full animate-pulse rounded-sm bg-zinc-800" />
</div> </div>
)} )}
{chats.unknowns.length > 0 && <UnknownsModal data={chats.unknowns} />}
<NewMessageModal />
</div> </div>
); );
} }

View File

@ -33,13 +33,13 @@ export function NewMessageModal() {
<button <button
type="button" type="button"
onClick={() => openModal()} onClick={() => openModal()}
className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5" className="inline-flex h-9 items-center gap-2.5 rounded-md px-2"
> >
<div className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded border-t border-zinc-800/50 bg-zinc-900"> <div className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded bg-white/10">
<PlusIcon className="h-3 w-3 text-zinc-200" /> <PlusIcon className="h-3 w-3 text-white" />
</div> </div>
<div> <div>
<h5 className="font-medium text-zinc-400">New chat</h5> <h5 className="text-white/50">New chat</h5>
</div> </div>
</button> </button>
<Transition appear show={isOpen} as={Fragment}> <Transition appear show={isOpen} as={Fragment}>

View File

@ -6,14 +6,14 @@ import { Image } from '@shared/image';
import { DEFAULT_AVATAR } from '@stores/constants'; import { DEFAULT_AVATAR } from '@stores/constants';
import { useProfile } from '@utils/hooks/useProfile'; import { useProfile } from '@utils/hooks/useProfile';
import { shortenKey } from '@utils/shortenKey'; import { displayNpub } from '@utils/shortenKey';
export function ChatsListSelfItem({ data }: { data: { pubkey: string } }) { export function ChatsListSelfItem({ data }: { data: { pubkey: string } }) {
const { status, user } = useProfile(data.pubkey); const { status, user } = useProfile(data.pubkey);
if (status === 'loading') { if (status === 'loading') {
return ( return (
<div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5"> <div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2">
<div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" /> <div className="relative h-6 w-6 shrink-0 animate-pulse rounded bg-zinc-800" />
<div> <div>
<div className="h-2.5 w-full animate-pulse truncate rounded bg-zinc-800 text-base font-medium" /> <div className="h-2.5 w-full animate-pulse truncate rounded bg-zinc-800 text-base font-medium" />
@ -28,24 +28,22 @@ export function ChatsListSelfItem({ data }: { data: { pubkey: string } }) {
preventScrollReset={true} preventScrollReset={true}
className={({ isActive }) => className={({ isActive }) =>
twMerge( twMerge(
'inline-flex h-9 items-center gap-2.5 rounded-md px-2.5', 'inline-flex h-9 items-center gap-2.5 rounded-md px-2',
isActive ? 'bg-zinc-900/50 text-zinc-100' : '' isActive ? 'bg-white/10 text-white' : 'text-white/80'
) )
} }
> >
<div className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded border-t border-zinc-800/50 bg-zinc-900"> <Image
<Image src={user?.picture || user?.image}
src={user?.picture || user?.image} fallback={DEFAULT_AVATAR}
fallback={DEFAULT_AVATAR} alt={data.pubkey}
alt={data.pubkey} className="h-6 w-6 shrink-0 rounded bg-white object-cover"
className="h-6 w-6 rounded bg-white object-cover" />
/>
</div>
<div className="inline-flex items-baseline gap-1"> <div className="inline-flex items-baseline gap-1">
<h5 className="max-w-[9rem] truncate font-medium text-zinc-200"> <h5 className="max-w-[10rem] truncate">
{user?.nip05 || user?.name || shortenKey(data.pubkey)} {user?.nip05 || user?.name || displayNpub(data.pubkey, 16)}
</h5> </h5>
<span className="text-zinc-500">(you)</span> <span className="text-white/50">(you)</span>
</div> </div>
</NavLink> </NavLink>
); );

View File

@ -31,15 +31,13 @@ export function UnknownsModal({ data }: { data: Chats[] }) {
<button <button
type="button" type="button"
onClick={() => openModal()} onClick={() => openModal()}
className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5" className="inline-flex h-9 items-center gap-2.5 rounded-md px-2"
> >
<div className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded border-t border-zinc-800/50 bg-zinc-900"> <div className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded bg-white/10">
<StrangersIcon className="h-3 w-3 text-zinc-200" /> <StrangersIcon className="h-3 w-3 text-white" />
</div> </div>
<div> <div>
<h5 className="font-medium text-zinc-400"> <h5 className="text-white/50">{compactNumber.format(data.length)} unknowns</h5>
{compactNumber.format(data.length)} unknowns
</h5>
</div> </div>
</button> </button>
<Transition appear show={isOpen} as={Fragment}> <Transition appear show={isOpen} as={Fragment}>

View File

@ -175,12 +175,9 @@ export function Root() {
}, [status]); }, [status]);
return ( return (
<div className="h-screen w-screen bg-zinc-50 text-zinc-900 dark:bg-zinc-950 dark:text-zinc-100"> <div className="h-screen w-screen">
<div className="flex h-screen w-full flex-col"> <div className="flex h-screen w-full flex-col">
<div <div data-tauri-drag-region className="h-11 shrink-0" />
data-tauri-drag-region
className="relative h-11 shrink-0 border border-zinc-100 bg-white dark:border-zinc-900 dark:bg-black"
/>
<div className="relative flex min-h-0 w-full flex-1 items-center justify-center"> <div className="relative flex min-h-0 w-full flex-1 items-center justify-center">
<div className="flex flex-col items-center justify-center gap-4"> <div className="flex flex-col items-center justify-center gap-4">
<LoaderIcon className="h-6 w-6 animate-spin text-zinc-100" /> <LoaderIcon className="h-6 w-6 animate-spin text-zinc-100" />

View File

@ -16,7 +16,7 @@ import { sendNativeNotification } from '@utils/notification';
const lastLogin = await getLastLogin(); const lastLogin = await getLastLogin();
export function ActiveAccount({ data }: { data: any }) { export function ActiveAccount({ data }: { data: { pubkey: string; npub: string } }) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { ndk } = useNDK(); const { ndk } = useNDK();

View File

@ -1,49 +0,0 @@
import { useNavigate } from 'react-router-dom';
import { ArrowLeftIcon, ArrowRightIcon } from '@shared/icons';
export function AppHeader({ reverse }: { reverse?: boolean }) {
const navigate = useNavigate();
const goBack = () => {
navigate(-1);
};
const goForward = () => {
navigate(1);
};
return (
<div
data-tauri-drag-region
className={`flex h-11 w-full shrink-0 items-center border-b border-zinc-900 px-3 ${
reverse ? 'justify-start' : 'justify-end'
}`}
>
<div className="flex gap-2.5">
<button
type="button"
onClick={() => goBack()}
className="group inline-flex h-6 w-6 items-center justify-center rounded hover:bg-zinc-900"
>
<ArrowLeftIcon
width={16}
height={16}
className="text-zinc-500 group-hover:text-zinc-300"
/>
</button>
<button
type="button"
onClick={() => goForward()}
className="group inline-flex h-6 w-6 items-center justify-center rounded hover:bg-zinc-900"
>
<ArrowRightIcon
width={16}
height={16}
className="text-zinc-500 group-hover:text-zinc-300"
/>
</button>
</div>
</div>
);
}

View File

@ -5,10 +5,10 @@ import { Navigation } from '@shared/navigation';
export function AppLayout() { export function AppLayout() {
return ( return (
<div className="flex h-screen w-screen"> <div className="flex h-screen w-screen">
<div className="relative flex shrink-0 flex-row"> <div className="shrink-0">
<Navigation /> <Navigation />
</div> </div>
<div className="h-full w-full"> <div className="h-full w-full flex-1 bg-black">
<Outlet /> <Outlet />
<ScrollRestoration /> <ScrollRestoration />
</div> </div>

View File

@ -16,7 +16,7 @@ export function Button({
switch (preset) { switch (preset) {
case 'small': case 'small':
preClass = preClass =
'w-min h-9 px-4 bg-fuchsia-500 rounded-md text-sm font-medium text-zinc-100 hover:bg-fuchsia-600'; 'w-min h-9 px-4 bg-white/10 rounded-md text-sm font-medium text-white hover:bg-fuchsia-500';
break; break;
case 'publish': case 'publish':
preClass = preClass =

View File

@ -34,9 +34,9 @@ export function Logout() {
type="button" type="button"
onClick={() => openModal()} onClick={() => openModal()}
aria-label="Logout" aria-label="Logout"
className="inline-flex h-9 w-9 transform items-center justify-center rounded-md border-t border-zinc-700/50 bg-zinc-800 active:translate-y-1" className="inline-flex h-9 w-9 transform items-center justify-center rounded-md bg-white/20 active:translate-y-1"
> >
<LogoutIcon className="h-4 w-4 text-zinc-400" /> <LogoutIcon className="h-4 w-4 text-white" />
</button> </button>
<Transition appear show={isOpen} as={Fragment}> <Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={closeModal}> <Dialog as="div" className="relative z-10" onClose={closeModal}>

View File

@ -11,7 +11,7 @@ export function LumeBar() {
const { status, account } = useAccount(); const { status, account } = useAccount();
return ( return (
<div className="rounded-xl border-t border-zinc-800/50 bg-zinc-900/80 p-2 backdrop-blur-md"> <div className="rounded-xl bg-white/10 p-2 backdrop-blur-xl">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
{status === 'loading' ? ( {status === 'loading' ? (
<> <>
@ -26,9 +26,9 @@ export function LumeBar() {
)} )}
<Link <Link
to="/settings/general" to="/settings/general"
className="inline-flex h-9 w-9 transform items-center justify-center rounded-md border-t border-zinc-700/50 bg-zinc-800 active:translate-y-1" className="inline-flex h-9 w-9 transform items-center justify-center rounded-md bg-white/20 active:translate-y-1"
> >
<SettingsIcon className="h-4 w-4 text-zinc-400" /> <SettingsIcon className="h-4 w-4 text-white" />
</Link> </Link>
<Logout /> <Logout />
</div> </div>

View File

@ -1,62 +1,123 @@
import { Disclosure } from '@headlessui/react'; import * as Collapsible from '@radix-ui/react-collapsible';
import { NavLink } from 'react-router-dom'; import { useState } from 'react';
import { NavLink, useNavigate } from 'react-router-dom';
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
import { ChatsList } from '@app/chats/components/list'; import { ChatsList } from '@app/chats/components/list';
import { AppHeader } from '@shared/appHeader';
import { ComposerModal } from '@shared/composer/modal'; import { ComposerModal } from '@shared/composer/modal';
import { NavArrowDownIcon, SpaceIcon, TrendingIcon } from '@shared/icons'; import {
ArrowLeftIcon,
ArrowRightIcon,
NavArrowDownIcon,
SpaceIcon,
TrendingIcon,
} from '@shared/icons';
import { LumeBar } from '@shared/lumeBar'; import { LumeBar } from '@shared/lumeBar';
export function Navigation() { export function Navigation() {
const navigate = useNavigate();
const [feeds, setFeeds] = useState(true);
const [chats, setChats] = useState(true);
return ( return (
<div className="relative flex w-[232px] flex-col gap-3 border-r border-zinc-900"> <div className="relative h-full w-[232px] bg-black/80">
<AppHeader />
<div className="scrollbar-hide flex flex-col gap-5 overflow-y-auto pb-20"> <div className="scrollbar-hide flex flex-col gap-5 overflow-y-auto pb-20">
<div className="inlin-lflex h-8 px-3.5"> <div className="inline-flex h-8 items-center justify-between px-2 pb-4 pt-14">
<ComposerModal /> <ComposerModal />
</div> <div className="flex gap-2.5">
{/* Newsfeed */} <button
<div className="flex flex-col gap-0.5 px-1.5"> type="button"
<div className="px-2.5"> onClick={() => navigate(-1)}
<h3 className="text-[11px] font-bold uppercase tracking-widest text-zinc-600"> className="group inline-flex h-8 w-8 items-center justify-center rounded hover:bg-white/10"
Feeds
</h3>
</div>
<div className="flex flex-col">
<NavLink
to="/app/space"
preventScrollReset={true}
className={({ isActive }) =>
twMerge(
'flex h-9 items-center gap-2.5 rounded-md px-2.5 text-zinc-200',
isActive ? 'bg-zinc-900/50' : ''
)
}
> >
<span className="inline-flex h-6 w-6 items-center justify-center rounded border-t border-zinc-800/50 bg-zinc-900"> <ArrowLeftIcon className="h-5 w-5 text-white/50 group-hover:text-white" />
<SpaceIcon width={12} height={12} className="text-zinc-100" /> </button>
</span> <button
<span className="font-medium">Spaces</span> type="button"
</NavLink> onClick={() => navigate(1)}
<NavLink className="group inline-flex h-8 w-8 items-center justify-center rounded hover:bg-white/10"
to="/app/trending"
preventScrollReset={true}
className={({ isActive }) =>
twMerge(
'flex h-9 items-center gap-2.5 rounded-md px-2.5 text-zinc-200',
isActive ? 'bg-zinc-900/50' : ''
)
}
> >
<span className="inline-flex h-6 w-6 items-center justify-center rounded border-t border-zinc-800/50 bg-zinc-900"> <ArrowRightIcon className="h-5 w-5 text-white/50 group-hover:text-white" />
<TrendingIcon width={12} height={12} className="text-zinc-100" /> </button>
</span>
<span className="font-medium">Trending</span>
</NavLink>
</div> </div>
</div> </div>
<Collapsible.Root open={feeds} onOpenChange={setFeeds}>
<div className="flex flex-col gap-1 px-2">
<Collapsible.Trigger asChild>
<button className="flex items-center gap-1">
<div
className={twMerge(
'inline-flex h-5 w-5 transform items-center justify-center transition-transform duration-150 ease-in-out',
open ? '' : 'rotate-180'
)}
>
<NavArrowDownIcon width={12} height={12} className="text-white/50" />
</div>
<h3 className="text-[11px] font-bold uppercase tracking-widest text-white/50">
Feeds
</h3>
</button>
</Collapsible.Trigger>
<Collapsible.Content>
<div className="flex flex-col">
<NavLink
to="/app/space"
preventScrollReset={true}
className={({ isActive }) =>
twMerge(
'flex h-9 items-center gap-2.5 rounded-md px-2',
isActive ? 'bg-white/10 text-white' : 'text-white/80'
)
}
>
<span className="inline-flex h-6 w-6 items-center justify-center rounded bg-white/10">
<SpaceIcon className="h-3 w-3 text-white" />
</span>
<span className="font-medium">Spaces</span>
</NavLink>
<NavLink
to="/app/trending"
preventScrollReset={true}
className={({ isActive }) =>
twMerge(
'flex h-9 items-center gap-2.5 rounded-md px-2 ',
isActive ? 'bg-white/10 text-white' : 'text-white/80'
)
}
>
<span className="inline-flex h-6 w-6 items-center justify-center rounded bg-white/10">
<TrendingIcon className="h-3 w-3 text-white" />
</span>
<span className="font-medium">Trending</span>
</NavLink>
</div>
</Collapsible.Content>
</div>
</Collapsible.Root>
<Collapsible.Root open={chats} onOpenChange={setChats}>
<div className="flex flex-col gap-1 px-2">
<Collapsible.Trigger asChild>
<button className="flex items-center gap-1">
<div
className={twMerge(
'inline-flex h-5 w-5 transform items-center justify-center transition-transform duration-150 ease-in-out',
open ? '' : 'rotate-180'
)}
>
<NavArrowDownIcon width={12} height={12} className="text-white/50" />
</div>
<h3 className="text-[11px] font-bold uppercase tracking-widest text-white/50">
Chats
</h3>
</button>
</Collapsible.Trigger>
<Collapsible.Content>
<ChatsList />
</Collapsible.Content>
</div>
</Collapsible.Root>
{/* Channels {/* Channels
<Disclosure defaultOpen={true}> <Disclosure defaultOpen={true}>
{({ open }) => ( {({ open }) => (
@ -84,28 +145,6 @@ export function Navigation() {
)} )}
</Disclosure> </Disclosure>
*/} */}
{/* Chats */}
<Disclosure defaultOpen={true}>
{({ open }) => (
<div className="flex flex-col gap-0.5 px-1.5 pb-6">
<Disclosure.Button className="flex items-center gap-1 px-3">
<div
className={`inline-flex h-5 w-5 transform items-center justify-center transition-transform duration-150 ease-in-out ${
open ? '' : 'rotate-180'
}`}
>
<NavArrowDownIcon width={12} height={12} className="text-zinc-700" />
</div>
<h3 className="text-[11px] font-bold uppercase tracking-widest text-zinc-600">
Chats
</h3>
</Disclosure.Button>
<Disclosure.Panel>
<ChatsList />
</Disclosure.Panel>
</div>
)}
</Disclosure>
</div> </div>
<div className="absolute bottom-3 left-0 w-full px-10"> <div className="absolute bottom-3 left-0 w-full px-10">
<LumeBar /> <LumeBar />

View File

@ -51,9 +51,9 @@ export function NotificationModal({ pubkey }: { pubkey: string }) {
<Dialog.Trigger asChild> <Dialog.Trigger asChild>
<button <button
type="button" type="button"
className="inline-flex h-9 w-9 transform items-center justify-center rounded-md border-t border-zinc-700/50 bg-zinc-800 active:translate-y-1" className="inline-flex h-9 w-9 transform items-center justify-center rounded-md bg-white/20 active:translate-y-1"
> >
<BellIcon className="h-4 w-4 text-zinc-400" /> <BellIcon className="h-4 w-4 text-white" />
</button> </button>
</Dialog.Trigger> </Dialog.Trigger>
<Dialog.Portal className="relative z-10"> <Dialog.Portal className="relative z-10">

View File

@ -1,7 +1,6 @@
import { NavLink, Outlet, ScrollRestoration } from 'react-router-dom'; import { NavLink, Outlet, ScrollRestoration } from 'react-router-dom';
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
import { AppHeader } from '@shared/appHeader';
import { LumeBar } from '@shared/lumeBar'; import { LumeBar } from '@shared/lumeBar';
export function SettingsLayout() { export function SettingsLayout() {
@ -9,7 +8,6 @@ export function SettingsLayout() {
<div className="flex h-screen w-screen"> <div className="flex h-screen w-screen">
<div className="relative flex shrink-0 flex-row"> <div className="relative flex shrink-0 flex-row">
<div className="relative flex w-[232px] flex-col gap-3 border-r border-zinc-900"> <div className="relative flex w-[232px] flex-col gap-3 border-r border-zinc-900">
<AppHeader />
<div className="scrollbar-hide flex flex-col gap-5 overflow-y-auto pb-20"> <div className="scrollbar-hide flex flex-col gap-5 overflow-y-auto pb-20">
<div className="flex flex-col gap-0.5 px-1.5"> <div className="flex flex-col gap-0.5 px-1.5">
<div className="px-2.5"> <div className="px-2.5">