From 78eabdd3cbb9c31f9e046205bc3fa7f679ae11b3 Mon Sep 17 00:00:00 2001 From: ameer2468 <33054370+ameer2468@users.noreply.github.com> Date: Wed, 25 Oct 2023 21:29:21 +0300 Subject: [PATCH] [ENG-1206] Account page (#1673) * account page * Remove spacedrive account from general --- interface/app/$libraryId/settings/Sidebar.tsx | 7 +- .../$libraryId/settings/client/account.tsx | 191 ++++++++++++++++++ .../$libraryId/settings/client/general.tsx | 15 +- .../app/$libraryId/settings/client/index.ts | 1 + interface/components/TruncatedText.tsx | 2 +- 5 files changed, 200 insertions(+), 16 deletions(-) create mode 100644 interface/app/$libraryId/settings/client/account.tsx diff --git a/interface/app/$libraryId/settings/Sidebar.tsx b/interface/app/$libraryId/settings/Sidebar.tsx index 920abd6eb..546917472 100644 --- a/interface/app/$libraryId/settings/Sidebar.tsx +++ b/interface/app/$libraryId/settings/Sidebar.tsx @@ -11,7 +11,8 @@ import { PuzzlePiece, Receipt, ShieldCheck, - TagSimple + TagSimple, + User } from '@phosphor-icons/react'; import { useFeatureFlag } from '@sd/client'; import { tw } from '@sd/ui'; @@ -49,6 +50,10 @@ export default () => { General + + + Account + Libraries diff --git a/interface/app/$libraryId/settings/client/account.tsx b/interface/app/$libraryId/settings/client/account.tsx new file mode 100644 index 000000000..64e5bb049 --- /dev/null +++ b/interface/app/$libraryId/settings/client/account.tsx @@ -0,0 +1,191 @@ +import { Cube, Envelope, User } from '@phosphor-icons/react'; +import { Collection, Drive_Light, Folder, Laptop } from '@sd/assets/icons'; +import { memo, useEffect, useMemo, useState } from 'react'; +import { auth, byteSize, useBridgeQuery, useDiscoveredPeers, useLibraryQuery } from '@sd/client'; +import { Button, Card } from '@sd/ui'; +import { TruncatedText } from '~/components'; +import { AuthRequiredOverlay } from '~/components/AuthRequiredOverlay'; +import { useCounter } from '~/hooks'; + +import { Heading } from '../Layout'; + +export const Component = () => { + const me = useBridgeQuery(['auth.me'], { retry: false }); + const authStore = auth.useStateSnapshot(); + return ( + <> + + {authStore.status === 'loggedIn' && ( +
+ +
+ )} + + } + title="Your account" + description="Spacedrive account and information." + /> +
+ + +
+ + ); +}; + +const Profile = ({ email, authStore }: { email?: string; authStore: { status: string } }) => { + const emailName = authStore.status === 'loggedIn' ? email?.split('@')[0] : 'guest user'; + return ( + + +
+ +
+

+ Welcome {emailName}, +

+
+ +
+ +
+ + {authStore.status === 'loggedIn' ? email : 'guestuser@outlook.com'} + +
+ +
+ +
+

Free

+
+
+
+ ); +}; + +const Usage = memo(() => { + const stats = useLibraryQuery(['library.statistics'], { + refetchOnWindowFocus: false, + initialData: { total_bytes_capacity: '0', library_db_size: '0' } + }); + const locations = useLibraryQuery(['locations.list'], { + refetchOnWindowFocus: false + }); + const discoveredPeers = useDiscoveredPeers(); + const info = useMemo(() => { + const tb_capacity = byteSize(stats.data?.total_bytes_capacity); + const library_db_size = byteSize(stats.data?.library_db_size); + const data: { + icon: string; + title?: string; + numberTitle?: number; + titleCount?: number; + unit?: string; + sub: string; + dataLength?: number; + }[] = [ + { + icon: Folder, + title: 'Locations', + titleCount: locations.data?.length, + sub: 'indexed directories', + dataLength: locations.data?.length + }, + { + icon: Laptop, + title: discoveredPeers.size > 1 ? 'Devices' : 'Device', + titleCount: discoveredPeers.size, + sub: 'in your network', + dataLength: discoveredPeers.size + }, + { + icon: Drive_Light, + numberTitle: tb_capacity.value, + sub: 'Total capacity', + unit: tb_capacity.unit + }, + { + icon: Collection, + numberTitle: library_db_size.value, + sub: 'Library size', + unit: library_db_size.unit + } + ]; + return data; + }, [locations, discoveredPeers, stats]); + + return ( + +

Usage & Hardware

+
+ {info.map((i, index) => ( + + ))} +
+
+ ); +}); + +interface Props { + icon: string; + title: string; + titleCount?: number; + numberTitle?: number; + statsLoading: boolean; + unit?: string; + sub: string; +} + +let mounted = false; +const UsageCard = memo( + ({ icon, title, titleCount, numberTitle, unit, sub, statsLoading }: Props) => { + const [isMounted] = useState(mounted); + const sizeCount = useCounter({ + name: title, + end: Number(numberTitle ? numberTitle : titleCount), + duration: isMounted ? 0 : 1, + precision: numberTitle ? 1 : 0, + saveState: false + }); + useEffect(() => { + if (!statsLoading) mounted = true; + }); + return ( + +
+ +
+

+ {titleCount && {sizeCount}} + {numberTitle && sizeCount} + {title} + {unit && ( + + {unit} + + )} +

+

{sub}

+
+
+
+ ); + } +); diff --git a/interface/app/$libraryId/settings/client/general.tsx b/interface/app/$libraryId/settings/client/general.tsx index 29e445bf3..2a75fef9c 100644 --- a/interface/app/$libraryId/settings/client/general.tsx +++ b/interface/app/$libraryId/settings/client/general.tsx @@ -11,24 +11,12 @@ import { useFeatureFlag, useZodForm } from '@sd/client'; -import { - Button, - Card, - Input, - InputField, - Select, - SelectOption, - Switch, - SwitchField, - tw, - z -} from '@sd/ui'; +import { Button, Card, Input, Select, SelectOption, Switch, tw, z } from '@sd/ui'; import { useDebouncedFormWatch } from '~/hooks'; import { usePlatform } from '~/util/Platform'; import { Heading } from '../Layout'; import Setting from '../Setting'; -import { SpacedriveAccount } from './SpacedriveAccount'; const NodePill = tw.div`px-1.5 py-[2px] rounded text-xs font-medium bg-app-selected`; const NodeSettingLabel = tw.div`mb-1 text-xs font-medium`; @@ -87,7 +75,6 @@ export const Component = () => { title="General Settings" description="General settings related to this client." /> -
diff --git a/interface/app/$libraryId/settings/client/index.ts b/interface/app/$libraryId/settings/client/index.ts index b5f296491..7fbe84c7e 100644 --- a/interface/app/$libraryId/settings/client/index.ts +++ b/interface/app/$libraryId/settings/client/index.ts @@ -2,6 +2,7 @@ import { RouteObject } from 'react-router'; export default [ { path: 'general', lazy: () => import('./general') }, + { path: 'account', lazy: () => import('./account') }, { path: 'appearance', lazy: () => import('./appearance') }, { path: 'keybindings', lazy: () => import('./keybindings') }, { path: 'extensions', lazy: () => import('./extensions') }, diff --git a/interface/components/TruncatedText.tsx b/interface/components/TruncatedText.tsx index bc19a3df0..7dc2704b4 100644 --- a/interface/components/TruncatedText.tsx +++ b/interface/components/TruncatedText.tsx @@ -12,7 +12,7 @@ export const TruncatedText = ({ const isTruncated = useIsTextTruncated(ref); return ( - +
{children}