mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-18 11:13:30 +00:00
update ui consistent for cross platform
This commit is contained in:
parent
37668393f1
commit
a4cf65e7c2
@ -5,6 +5,7 @@ import { AuthImportScreen } from '@app/auth/import';
|
|||||||
import { OnboardingScreen } from '@app/auth/onboarding';
|
import { OnboardingScreen } from '@app/auth/onboarding';
|
||||||
import { ErrorScreen } from '@app/error';
|
import { ErrorScreen } from '@app/error';
|
||||||
|
|
||||||
|
import { Frame } from '@shared/frame';
|
||||||
import { LoaderIcon } from '@shared/icons';
|
import { LoaderIcon } from '@shared/icons';
|
||||||
import { AppLayout } from '@shared/layouts/app';
|
import { AppLayout } from '@shared/layouts/app';
|
||||||
import { AuthLayout } from '@shared/layouts/auth';
|
import { AuthLayout } from '@shared/layouts/auth';
|
||||||
@ -261,9 +262,9 @@ export default function App() {
|
|||||||
<RouterProvider
|
<RouterProvider
|
||||||
router={router}
|
router={router}
|
||||||
fallbackElement={
|
fallbackElement={
|
||||||
<div className="flex h-full w-full items-center justify-center bg-black/90 backdrop-blur-xl">
|
<Frame className="flex h-full w-full items-center justify-center">
|
||||||
<LoaderIcon className="h-6 w-6 animate-spin text-white" />
|
<LoaderIcon className="h-6 w-6 animate-spin text-white" />
|
||||||
</div>
|
</Frame>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -35,7 +35,7 @@ export function NewMessageModal() {
|
|||||||
</button>
|
</button>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
<Dialog.Portal className="relative z-10">
|
<Dialog.Portal className="relative z-10">
|
||||||
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-xl" />
|
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-2xl" />
|
||||||
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
||||||
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
||||||
<div className="h-min w-full shrink-0 border-b border-white/10 bg-white/5 px-5 py-5">
|
<div className="h-min w-full shrink-0 border-b border-white/10 bg-white/5 px-5 py-5">
|
||||||
|
@ -35,7 +35,7 @@ export function UnknownsModal({ data }: { data: string[] }) {
|
|||||||
</button>
|
</button>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
<Dialog.Portal className="relative z-10">
|
<Dialog.Portal className="relative z-10">
|
||||||
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-xl" />
|
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-2xl" />
|
||||||
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
||||||
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
||||||
<div className="h-min w-full shrink-0 border-b border-white/10 bg-white/5 px-5 py-5">
|
<div className="h-min w-full shrink-0 border-b border-white/10 bg-white/5 px-5 py-5">
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useLocation, useRouteError } from 'react-router-dom';
|
import { useLocation, useRouteError } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { Frame } from '@shared/frame';
|
||||||
|
|
||||||
interface IRouteError {
|
interface IRouteError {
|
||||||
statusText: string;
|
statusText: string;
|
||||||
message: string;
|
message: string;
|
||||||
@ -33,7 +35,7 @@ export function ErrorScreen() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full items-center justify-center bg-black/90 backdrop-blur-xl">
|
<Frame className="flex h-full items-center justify-center">
|
||||||
<div className="flex max-w-lg flex-col gap-4">
|
<div className="flex max-w-lg flex-col gap-4">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<h1 className="mb-1 text-2xl font-semibold text-white">
|
<h1 className="mb-1 text-2xl font-semibold text-white">
|
||||||
@ -75,6 +77,6 @@ export function ErrorScreen() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Frame>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ export function EditProfileModal() {
|
|||||||
</button>
|
</button>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
<Dialog.Portal className="relative z-10">
|
<Dialog.Portal className="relative z-10">
|
||||||
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-xl" />
|
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-2xl" />
|
||||||
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
||||||
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
||||||
<div className="h-min w-full shrink-0 border-b border-white/10 bg-white/5 px-5 py-5">
|
<div className="h-min w-full shrink-0 border-b border-white/10 bg-white/5 px-5 py-5">
|
||||||
|
@ -58,7 +58,7 @@ export function UserProfile({ pubkey }: { pubkey: string }) {
|
|||||||
className="h-full w-full object-cover"
|
className="h-full w-full object-cover"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-full w-full bg-black/50" />
|
<div className="h-full w-full bg-black" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="-mt-7 flex w-full flex-col items-center px-5">
|
<div className="-mt-7 flex w-full flex-col items-center px-5">
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||||
import { BaseDirectory, removeFile } from '@tauri-apps/api/fs';
|
import { BaseDirectory, removeFile } from '@tauri-apps/api/fs';
|
||||||
|
import { Platform } from '@tauri-apps/api/os';
|
||||||
import Database from 'tauri-plugin-sql-api';
|
import Database from 'tauri-plugin-sql-api';
|
||||||
import { Stronghold } from 'tauri-plugin-stronghold-api';
|
import { Stronghold } from 'tauri-plugin-stronghold-api';
|
||||||
|
|
||||||
@ -7,11 +8,13 @@ import { Account, DBEvent, Relays, Widget } from '@utils/types';
|
|||||||
|
|
||||||
export class LumeStorage {
|
export class LumeStorage {
|
||||||
public db: Database;
|
public db: Database;
|
||||||
|
public platform: Platform;
|
||||||
public secureDB: Stronghold;
|
public secureDB: Stronghold;
|
||||||
public account: Account | null = null;
|
public account: Account | null = null;
|
||||||
|
|
||||||
constructor(sqlite: Database, stronghold?: Stronghold) {
|
constructor(sqlite: Database, platform: Platform, stronghold?: Stronghold) {
|
||||||
this.db = sqlite;
|
this.db = sqlite;
|
||||||
|
this.platform = platform ?? undefined;
|
||||||
this.secureDB = stronghold ?? undefined;
|
this.secureDB = stronghold ?? undefined;
|
||||||
this.account = null;
|
this.account = null;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { message } from '@tauri-apps/api/dialog';
|
import { message } from '@tauri-apps/api/dialog';
|
||||||
|
import { platform } from '@tauri-apps/api/os';
|
||||||
import { PropsWithChildren, createContext, useContext, useEffect, useState } from 'react';
|
import { PropsWithChildren, createContext, useContext, useEffect, useState } from 'react';
|
||||||
import Database from 'tauri-plugin-sql-api';
|
import Database from 'tauri-plugin-sql-api';
|
||||||
|
|
||||||
@ -18,7 +19,8 @@ const StorageProvider = ({ children }: PropsWithChildren<object>) => {
|
|||||||
async function initLumeStorage() {
|
async function initLumeStorage() {
|
||||||
try {
|
try {
|
||||||
const sqlite = await Database.load('sqlite:lume.db');
|
const sqlite = await Database.load('sqlite:lume.db');
|
||||||
const lumeStorage = new LumeStorage(sqlite);
|
const platformName = await platform();
|
||||||
|
const lumeStorage = new LumeStorage(sqlite, platformName);
|
||||||
|
|
||||||
if (!lumeStorage.account) await lumeStorage.getActiveAccount();
|
if (!lumeStorage.account) await lumeStorage.getActiveAccount();
|
||||||
setDB(lumeStorage);
|
setDB(lumeStorage);
|
||||||
|
@ -37,7 +37,7 @@ export function ComposerModal() {
|
|||||||
</button>
|
</button>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
<Dialog.Portal className="relative z-10">
|
<Dialog.Portal className="relative z-10">
|
||||||
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-xl" />
|
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-2xl" />
|
||||||
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
||||||
<div
|
<div
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
|
29
src/shared/frame.tsx
Normal file
29
src/shared/frame.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { HTMLProps, ReactNode, useCallback } from 'react';
|
||||||
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
|
import { useStorage } from '@libs/storage/provider';
|
||||||
|
|
||||||
|
export function Frame({
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
lighter,
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
className: HTMLProps<HTMLElement>['className'];
|
||||||
|
lighter?: boolean;
|
||||||
|
}) {
|
||||||
|
const { db } = useStorage();
|
||||||
|
|
||||||
|
const platformStyles = useCallback(() => {
|
||||||
|
switch (db.platform) {
|
||||||
|
case 'darwin':
|
||||||
|
case 'win32':
|
||||||
|
if (lighter) return 'bg-black/80';
|
||||||
|
return 'bg-black/90';
|
||||||
|
default:
|
||||||
|
return 'bg-black';
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return <div className={twMerge(className, platformStyles())}>{children}</div>;
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { Outlet, ScrollRestoration } from 'react-router-dom';
|
import { Outlet, ScrollRestoration } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { Frame } from '@shared/frame';
|
||||||
import { Navigation } from '@shared/navigation';
|
import { Navigation } from '@shared/navigation';
|
||||||
|
|
||||||
export function AppLayout() {
|
export function AppLayout() {
|
||||||
@ -8,14 +9,14 @@ export function AppLayout() {
|
|||||||
<div className="shrink-0">
|
<div className="shrink-0">
|
||||||
<Navigation />
|
<Navigation />
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full w-full flex-1 bg-black/90 backdrop-blur-xl">
|
<Frame className="h-full w-full flex-1">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
<ScrollRestoration
|
<ScrollRestoration
|
||||||
getKey={(location) => {
|
getKey={(location) => {
|
||||||
return location.pathname;
|
return location.pathname;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Frame>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { Frame } from '@shared/frame';
|
||||||
|
|
||||||
export function AuthLayout() {
|
export function AuthLayout() {
|
||||||
return (
|
return (
|
||||||
<div className="relative h-screen w-screen bg-black/90 backdrop-blur-xl">
|
<Frame className="relative h-screen w-screen">
|
||||||
<div className="absolute left-0 top-0 z-50 h-16 w-full" data-tauri-drag-region />
|
<div className="absolute left-0 top-0 z-50 h-16 w-full" data-tauri-drag-region />
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</Frame>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { Frame } from '@shared/frame';
|
||||||
|
|
||||||
export function NoteLayout() {
|
export function NoteLayout() {
|
||||||
return (
|
return (
|
||||||
<div className="relative h-screen w-screen bg-black/90 backdrop-blur-xl">
|
<Frame className="relative h-screen w-screen">
|
||||||
<div className="absolute left-0 top-0 z-50 h-16 w-full" data-tauri-drag-region />
|
<div className="absolute left-0 top-0 z-50 h-16 w-full" data-tauri-drag-region />
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</Frame>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { Link, NavLink, Outlet, ScrollRestoration } from 'react-router-dom';
|
import { Link, NavLink, Outlet, ScrollRestoration } from 'react-router-dom';
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
|
import { Frame } from '@shared/frame';
|
||||||
import { ArrowLeftIcon, SecureIcon, SettingsIcon } from '@shared/icons';
|
import { ArrowLeftIcon, SecureIcon, SettingsIcon } from '@shared/icons';
|
||||||
|
|
||||||
export function SettingsLayout() {
|
export function SettingsLayout() {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen w-screen">
|
<div className="flex h-screen w-screen">
|
||||||
<div className="relative flex h-full w-[232px] flex-col bg-black/80">
|
<Frame className="relative flex h-full w-[232px] flex-col" lighter>
|
||||||
<div data-tauri-drag-region className="h-11 w-full shrink-0" />
|
<div data-tauri-drag-region className="h-11 w-full shrink-0" />
|
||||||
<div className="scrollbar-hide flex h-full flex-1 flex-col gap-2 overflow-y-auto pb-32">
|
<div className="scrollbar-hide flex h-full flex-1 flex-col gap-2 overflow-y-auto pb-32">
|
||||||
<div className="inline-flex items-center gap-2 border-l-2 border-transparent pl-4">
|
<div className="inline-flex items-center gap-2 border-l-2 border-transparent pl-4">
|
||||||
@ -55,7 +56,7 @@ export function SettingsLayout() {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Frame>
|
||||||
<div className="h-full w-full flex-1 bg-black/90 backdrop-blur-xl">
|
<div className="h-full w-full flex-1 bg-black/90 backdrop-blur-xl">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
<ScrollRestoration
|
<ScrollRestoration
|
||||||
|
@ -6,6 +6,7 @@ import { ChatsList } from '@app/chats/components/list';
|
|||||||
|
|
||||||
import { ActiveAccount } from '@shared/accounts/active';
|
import { ActiveAccount } from '@shared/accounts/active';
|
||||||
import { ComposerModal } from '@shared/composer';
|
import { ComposerModal } from '@shared/composer';
|
||||||
|
import { Frame } from '@shared/frame';
|
||||||
import { BellIcon, NavArrowDownIcon, SpaceIcon } from '@shared/icons';
|
import { BellIcon, NavArrowDownIcon, SpaceIcon } from '@shared/icons';
|
||||||
|
|
||||||
import { useSidebar } from '@stores/sidebar';
|
import { useSidebar } from '@stores/sidebar';
|
||||||
@ -14,7 +15,7 @@ export function Navigation() {
|
|||||||
const [chats, toggleChats] = useSidebar((state) => [state.chats, state.toggleChats]);
|
const [chats, toggleChats] = useSidebar((state) => [state.chats, state.toggleChats]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex h-full w-[232px] flex-col bg-black/80">
|
<Frame className="relative flex h-full w-[232px] flex-col" lighter>
|
||||||
<div data-tauri-drag-region className="h-11 w-full shrink-0" />
|
<div data-tauri-drag-region className="h-11 w-full shrink-0" />
|
||||||
<div className="scrollbar-hide flex h-full flex-1 flex-col gap-6 overflow-y-auto pb-32">
|
<div className="scrollbar-hide flex h-full flex-1 flex-col gap-6 overflow-y-auto pb-32">
|
||||||
<div className="flex flex-col pr-2">
|
<div className="flex flex-col pr-2">
|
||||||
@ -80,6 +81,6 @@ export function Navigation() {
|
|||||||
<div className="shrink-0">
|
<div className="shrink-0">
|
||||||
<ActiveAccount />
|
<ActiveAccount />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Frame>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ export function NoteRepost({ id, pubkey }: { id: string; pubkey: string }) {
|
|||||||
</Tooltip.Portal>
|
</Tooltip.Portal>
|
||||||
</Tooltip.Root>
|
</Tooltip.Root>
|
||||||
<AlertDialog.Portal className="relative z-10">
|
<AlertDialog.Portal className="relative z-10">
|
||||||
<AlertDialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-xl" />
|
<AlertDialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-2xl" />
|
||||||
<AlertDialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
<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-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
||||||
<div className="flex flex-col gap-2 border-b border-white/5 px-5 py-4">
|
<div className="flex flex-col gap-2 border-b border-white/5 px-5 py-4">
|
||||||
|
@ -38,7 +38,7 @@ export function NoteZap({ id }: { id: string }) {
|
|||||||
</button>
|
</button>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
<Dialog.Portal className="relative z-10">
|
<Dialog.Portal className="relative z-10">
|
||||||
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-xl" />
|
<Dialog.Overlay className="fixed inset-0 z-50 bg-black/80 backdrop-blur-2xl" />
|
||||||
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
<Dialog.Content className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
||||||
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
<div className="relative h-min w-full max-w-xl rounded-xl bg-white/10 backdrop-blur-xl">
|
||||||
<div className="relative h-min w-full shrink-0 border-b border-white/5 bg-white/5 px-5 py-5">
|
<div className="relative h-min w-full shrink-0 border-b border-white/5 bg-white/5 px-5 py-5">
|
||||||
|
Loading…
Reference in New Issue
Block a user