diff --git a/.cspell/project_words.txt b/.cspell/project_words.txt index b9baef73c..906cc337d 100644 --- a/.cspell/project_words.txt +++ b/.cspell/project_words.txt @@ -48,6 +48,7 @@ sharma skippable spacedrive spacedriveapp +spacetunnel specta storedkey stringly diff --git a/apps/desktop/vite.config.ts b/apps/desktop/vite.config.ts index 14438007d..c05ef33d3 100644 --- a/apps/desktop/vite.config.ts +++ b/apps/desktop/vite.config.ts @@ -19,6 +19,11 @@ export default defineConfig({ } }) ], + css: { + modules: { + localsConvention: 'camelCaseOnly' + } + }, resolve: { alias: [relativeAliasResolver] }, diff --git a/apps/landing/vite.config.ts b/apps/landing/vite.config.ts index c833a4f9d..5ca0e0bc6 100644 --- a/apps/landing/vite.config.ts +++ b/apps/landing/vite.config.ts @@ -17,6 +17,11 @@ export default defineConfig({ md({ mode: [Mode.REACT] }), visualizer() ], + css: { + modules: { + localsConvention: 'camelCaseOnly' + } + }, resolve: { alias: [ { diff --git a/core/src/api/tags.rs b/core/src/api/tags.rs index 0d842ebcf..481463f69 100644 --- a/core/src/api/tags.rs +++ b/core/src/api/tags.rs @@ -113,6 +113,19 @@ pub(crate) fn mount() -> RouterBuilder { .await?) }) }) + // .library_mutation("create", |t| { + // #[derive(Type, Deserialize)] + // pub struct TagCreateArgs { + // pub name: String, + // pub color: String, + // } + // t(|_, args: TagCreateArgs, library| async move { + // let created_tag = Tag::new(args.name, args.color); + // created_tag.save(&library.db).await?; + // invalidate_query!(library, "tags.list"); + // Ok(created_tag) + // }) + // }) .library_mutation("create", |t| { #[derive(Type, Deserialize)] pub struct TagCreateArgs { diff --git a/core/src/object/fs/decrypt.rs b/core/src/object/fs/decrypt.rs index 280b54b60..5f036c7e2 100644 --- a/core/src/object/fs/decrypt.rs +++ b/core/src/object/fs/decrypt.rs @@ -9,7 +9,7 @@ use tokio::fs::File; use crate::job::{JobError, JobReportUpdate, JobResult, JobState, StatefulJob, WorkerContext}; -use super::{context_menu_fs_info, FsInfo}; +use super::{context_menu_fs_info, FsInfo, BYTES}; pub struct FileDecryptorJob; #[derive(Serialize, Deserialize, Debug)] pub struct FileDecryptorJobState {} @@ -74,7 +74,7 @@ impl StatefulJob for FileDecryptorJob { || { let mut path = info.fs_path.clone(); let extension = path.extension().map_or("decrypted", |ext| { - if ext == ".sdenc" { + if ext == BYTES { "" } else { "decrypted" diff --git a/core/src/object/fs/encrypt.rs b/core/src/object/fs/encrypt.rs index d73591efb..efdd9997d 100644 --- a/core/src/object/fs/encrypt.rs +++ b/core/src/object/fs/encrypt.rs @@ -98,7 +98,7 @@ impl StatefulJob for FileEncryptorJob { || { let mut path = info.fs_path.clone(); let extension = path.extension().map_or_else( - || Ok("sdenc".to_string()), + || Ok("bytes".to_string()), |extension| { Ok::( extension @@ -108,7 +108,7 @@ impl StatefulJob for FileEncryptorJob { "path contents when converted to string", ), })? - .to_string() + ".sdenc", + .to_string() + ".bytes", ) }, )?; diff --git a/core/src/object/fs/mod.rs b/core/src/object/fs/mod.rs index 9d46c96d9..1e2d068fb 100644 --- a/core/src/object/fs/mod.rs +++ b/core/src/object/fs/mod.rs @@ -22,6 +22,8 @@ pub mod error; pub mod erase; +pub const BYTES: &str = "bytes"; + #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] pub enum ObjectType { File, diff --git a/core/src/object/mod.rs b/core/src/object/mod.rs index 6fc774fce..52f8ff350 100644 --- a/core/src/object/mod.rs +++ b/core/src/object/mod.rs @@ -2,6 +2,7 @@ pub mod cas; pub mod fs; pub mod identifier_job; pub mod preview; +pub mod tag; pub mod validation; // Objects are primarily created by the identifier from Paths diff --git a/core/src/object/tag.rs b/core/src/object/tag.rs new file mode 100644 index 000000000..24fdd27be --- /dev/null +++ b/core/src/object/tag.rs @@ -0,0 +1,33 @@ +use prisma_client_rust::QueryError; +use rspc::Type; +use serde::Deserialize; + +use uuid::Uuid; + +use crate::prisma::{tag, PrismaClient}; + +#[derive(Type, Deserialize)] +pub struct Tag { + pub name: String, + pub color: String, +} + +impl Tag { + pub fn new(name: String, color: String) -> Self { + Self { name, color } + } + pub async fn save(self, db: &PrismaClient) -> Result<(), QueryError> { + db.tag() + .create( + Uuid::new_v4().as_bytes().to_vec(), + vec![ + tag::name::set(Some(self.name)), + tag::color::set(Some(self.color)), + ], + ) + .exec() + .await?; + + Ok(()) + } +} diff --git a/crates/file-ext/src/extensions.rs b/crates/file-ext/src/extensions.rs index 5cc36d458..742b0104b 100644 --- a/crates/file-ext/src/extensions.rs +++ b/crates/file-ext/src/extensions.rs @@ -67,6 +67,7 @@ extension_category_enum! { Jpg = [0xFF, 0xD8], Jpeg = [0xFF, 0xD8], Png = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A], + Apng = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52], Gif = [0x47, 0x49, 0x46, 0x38, _, 0x61], Bmp = [0x42, 0x4D], Tiff = [0x49, 0x49, 0x2A, 0x00], @@ -183,11 +184,11 @@ extension_category_enum! { extension_category_enum! { EncryptedExtension _ALL_ENCRYPTED_EXTENSIONS { // Spacedrive encrypted file - SdEnc = [0x62, 0x61, 0x6C, 0x6C, 0x61, 0x70, 0x70], + Bytes = [0x62, 0x61, 0x6C, 0x6C, 0x61, 0x70, 0x70], // Spacedrive container - SdContainer = [0x73, 0x64, 0x62, 0x6F, 0x78], + Container = [0x73, 0x64, 0x62, 0x6F, 0x78], // Spacedrive block storage, - SdBlock = [0x73, 0x64, 0x62, 0x6C, 0x6F, 0x63, 0x6B], + Block = [0x73, 0x64, 0x62, 0x6C, 0x6F, 0x63, 0x6B], } } diff --git a/packages/assets/images/Compressed.png b/packages/assets/images/Compressed.png new file mode 100644 index 000000000..a2633b1e5 Binary files /dev/null and b/packages/assets/images/Compressed.png differ diff --git a/packages/assets/images/Encrypted.png b/packages/assets/images/Encrypted.png new file mode 100644 index 000000000..47ba5bf79 Binary files /dev/null and b/packages/assets/images/Encrypted.png differ diff --git a/packages/assets/images/GoogleDrive.png b/packages/assets/images/GoogleDrive.png new file mode 100644 index 000000000..8ab71bc48 Binary files /dev/null and b/packages/assets/images/GoogleDrive.png differ diff --git a/packages/assets/images/Mega.png b/packages/assets/images/Mega.png new file mode 100644 index 000000000..acc90e319 Binary files /dev/null and b/packages/assets/images/Mega.png differ diff --git a/packages/assets/images/iCloud.png b/packages/assets/images/iCloud.png new file mode 100644 index 000000000..93f2e1066 Binary files /dev/null and b/packages/assets/images/iCloud.png differ diff --git a/packages/interface/src/ErrorFallback.tsx b/packages/interface/src/ErrorFallback.tsx index 570076595..9a71d9d4c 100644 --- a/packages/interface/src/ErrorFallback.tsx +++ b/packages/interface/src/ErrorFallback.tsx @@ -1,5 +1,6 @@ import { captureException } from '@sentry/browser'; import { FallbackProps } from 'react-error-boundary'; +import { useDebugState } from '@sd/client'; import { Button } from '@sd/ui'; export function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) { @@ -8,6 +9,8 @@ export function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) { resetErrorBoundary(); }; + const debug = useDebugState(); + return (
APP CRASHED

We're past the event horizon...

Error: {error.message}
+ {debug.enabled && ( +
+					Check the console (CMD/CRTL + OPTION + i) for stack trace.
+				
+ )}
- - ); -}; - function LibraryScopedSection() { const platform = usePlatform(); @@ -352,10 +372,9 @@ function LibraryScopedSection() { - {/* */} - - + + + } > {locations.data?.map((location) => { @@ -399,7 +418,11 @@ function LibraryScopedSection() { {!!tags.data?.length && ( } + actionArea={ + + + + } >
{tags.data?.slice(0, 6).map((tag, index) => ( diff --git a/packages/interface/src/components/onboarding/OnboardingRoot.tsx b/packages/interface/src/components/onboarding/OnboardingRoot.tsx index db1d515e0..e872e163d 100644 --- a/packages/interface/src/components/onboarding/OnboardingRoot.tsx +++ b/packages/interface/src/components/onboarding/OnboardingRoot.tsx @@ -4,6 +4,7 @@ import { useEffect } from 'react'; import { Navigate, Outlet, RouteObject, useNavigate } from 'react-router'; import { getOnboardingStore } from '@sd/client'; import { tw } from '@sd/ui'; +import DragRegion from '~/components/layout/DragRegion'; import { useOperatingSystem } from '../../hooks/useOperatingSystem'; import OnboardingCreatingLibrary from './OnboardingCreatingLibrary'; import OnboardingMasterPassword from './OnboardingMasterPassword'; @@ -64,7 +65,7 @@ export default function OnboardingRoot() { 'bg-sidebar text-ink flex h-screen flex-col' )} > -
+
diff --git a/packages/interface/src/components/primitive/PopoverPicker.tsx b/packages/interface/src/components/primitive/PopoverPicker.tsx index 895ff1dee..5748c2e6a 100644 --- a/packages/interface/src/components/primitive/PopoverPicker.tsx +++ b/packages/interface/src/components/primitive/PopoverPicker.tsx @@ -19,7 +19,7 @@ export const PopoverPicker = ({ className, ...props }: PopoverPickerProps) => { return (
toggle(true)} /> diff --git a/packages/interface/src/components/primitive/Shortcut.tsx b/packages/interface/src/components/primitive/Shortcut.tsx index 7f2d5e28a..2adb8dc45 100644 --- a/packages/interface/src/components/primitive/Shortcut.tsx +++ b/packages/interface/src/components/primitive/Shortcut.tsx @@ -11,8 +11,8 @@ export const Shortcut: React.FC = (props) => { return ( = (props) => { + const Icon = props.icon ?? Ellipsis; + return ( + + ); +}; + +export const SubtleButtonContainer = tw.div`opacity-0 text-ink-faint group-hover:opacity-30 hover:!opacity-100`; diff --git a/packages/interface/src/components/settings/SettingsSubPage.tsx b/packages/interface/src/components/settings/SettingsSubPage.tsx index a26d6f622..8849fa2bc 100644 --- a/packages/interface/src/components/settings/SettingsSubPage.tsx +++ b/packages/interface/src/components/settings/SettingsSubPage.tsx @@ -2,6 +2,7 @@ import { ReactComponent as CaretDown } from '@sd/assets/svgs/caret.svg'; import { PropsWithChildren } from 'react'; import { useNavigate } from 'react-router'; import { Button, tw } from '@sd/ui'; +import DragRegion from '~/components/layout/DragRegion'; import { Divider } from '../explorer/inspector/Divider'; interface Props extends PropsWithChildren { @@ -20,7 +21,7 @@ export const SettingsSubPage = ({ children, title, topRight }: Props) => { return ( -
+ diff --git a/packages/interface/src/hooks/useExplorerStore.tsx b/packages/interface/src/hooks/useExplorerStore.tsx index 1dbc75be3..0f3687a12 100644 --- a/packages/interface/src/hooks/useExplorerStore.tsx +++ b/packages/interface/src/hooks/useExplorerStore.tsx @@ -20,7 +20,7 @@ const state = { listItemSize: 40, selectedRowIndex: 1, tagAssignMode: false, - showInspector: true, + showInspector: false, multiSelectIndexes: [] as number[], contextMenuObjectId: null as number | null, contextMenuActiveObject: null as object | null, diff --git a/packages/interface/src/screens/Debug.tsx b/packages/interface/src/screens/Debug.tsx index 72bd5a280..8e8570fbe 100644 --- a/packages/interface/src/screens/Debug.tsx +++ b/packages/interface/src/screens/Debug.tsx @@ -1,6 +1,7 @@ import { useBridgeQuery, useLibraryMutation, useLibraryQuery } from '@sd/client'; import CodeBlock from '~/components/primitive/Codeblock'; import { usePlatform } from '~/util/Platform'; +import { ScreenContainer } from './_Layout'; // TODO: Bring this back with a button in the sidebar near settings at the bottom export default function DebugScreen() { @@ -16,9 +17,8 @@ export default function DebugScreen() { // }); const { mutate: identifyFiles } = useLibraryMutation('jobs.identifyUniqueFiles'); return ( -
-
-
+ +

Developer Debugger

{/*
-
+
); } diff --git a/packages/interface/src/screens/Media.tsx b/packages/interface/src/screens/Media.tsx index 925f1192b..1cccda31a 100644 --- a/packages/interface/src/screens/Media.tsx +++ b/packages/interface/src/screens/Media.tsx @@ -1,9 +1,10 @@ import { ScreenHeading } from '@sd/ui'; +import { ScreenContainer } from './_Layout'; export default function MediaScreen() { return ( -
+ Media -
+ ); } diff --git a/packages/interface/src/screens/NotFound.tsx b/packages/interface/src/screens/NotFound.tsx index cb223a9b0..0d2037a31 100644 --- a/packages/interface/src/screens/NotFound.tsx +++ b/packages/interface/src/screens/NotFound.tsx @@ -4,17 +4,21 @@ import { Button } from '@sd/ui'; export default function NotFound() { const navigate = useNavigate(); return ( -
-

Error: 404

-

You chose nothingness.

-
- +
+
+

Error: 404

+

There's nothing here.

+

+ Its likely that this page has not been built yet, if so we're on it! +

+
+ +
); diff --git a/packages/interface/src/screens/Overview.tsx b/packages/interface/src/screens/Overview.tsx index 65c7fca23..652984db2 100644 --- a/packages/interface/src/screens/Overview.tsx +++ b/packages/interface/src/screens/Overview.tsx @@ -18,6 +18,7 @@ import { Card } from '@sd/ui'; import useCounter from '~/hooks/useCounter'; import { useLibraryId } from '~/util'; import { usePlatform } from '~/util/Platform'; +import { ScreenContainer } from './_Layout'; interface StatItemProps { title: string; @@ -97,11 +98,8 @@ export default function OverviewScreen() { overviewMounted = true; return ( -
-
- {/* PAGE */} - -
+ +
{/* STAT HEADER */}
{/* STAT CONTAINER */} @@ -138,7 +136,7 @@ export default function OverviewScreen() {
-
+ ); } diff --git a/packages/interface/src/screens/People.tsx b/packages/interface/src/screens/People.tsx index eb4c9e50a..db0e8df8a 100644 --- a/packages/interface/src/screens/People.tsx +++ b/packages/interface/src/screens/People.tsx @@ -1,9 +1,10 @@ import { ScreenHeading } from '@sd/ui'; +import { ScreenContainer } from './_Layout'; export default function PeopleScreen() { return ( -
+ People -
+ ); } diff --git a/packages/interface/src/screens/Spacedrop.module.scss b/packages/interface/src/screens/Spacedrop.module.scss new file mode 100644 index 000000000..c2a29fc88 --- /dev/null +++ b/packages/interface/src/screens/Spacedrop.module.scss @@ -0,0 +1,25 @@ +.honeycomb-outer { + font-size: 0; /*disable white space between inline block element */ + display: flex; + --s: 150px; /* size */ + --m: 4px; /* margin */ + --f: calc(1.732 * var(--s) + 4 * var(--m) - 1px); +} + +.honeycomb-container .honeycomb-item { + width: var(--s); + margin: var(--m); + height: calc(var(--s) * 1.1547); + display: inline-block; + clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%); + // background: rgba(48, 48, 55, 0.272); + margin-bottom: calc(var(--m) - var(--s) * 0.2885); +} + +.honeycomb-container::before { + content: ''; + width: calc(var(--s) / 2 + var(--m)); + float: left; + height: 120%; + shape-outside: repeating-linear-gradient(#0000 0 calc(var(--f) - 3px), #000 0 var(--f)); +} diff --git a/packages/interface/src/screens/Spacedrop.tsx b/packages/interface/src/screens/Spacedrop.tsx new file mode 100644 index 000000000..df3aac415 --- /dev/null +++ b/packages/interface/src/screens/Spacedrop.tsx @@ -0,0 +1,151 @@ +import GoogleDrive from '@sd/assets/images/GoogleDrive.png'; +import Mega from '@sd/assets/images/Mega.png'; +import iCloud from '@sd/assets/images/iCloud.png'; +import clsx from 'clsx'; +import { DeviceMobile, HardDrives, Heart, Icon, Laptop, PhoneX, Star, User } from 'phosphor-react'; +import { useRef } from 'react'; +import { Button, tw } from '@sd/ui'; +import { SearchBar } from '../components/explorer/ExplorerTopBar'; +import { SubtleButton, SubtleButtonContainer } from '../components/primitive/SubtleButton'; +import { OperatingSystem } from '../util/Platform'; +import classes from './Spacedrop.module.scss'; +import { ScreenContainer } from './_Layout'; + +// TODO: move this to UI, copied from Inspector +const Pill = tw.span`mt-1 inline border border-transparent px-0.5 text-[9px] font-medium shadow shadow-app-shade/5 bg-app-selected rounded text-ink-dull`; + +type DropItemProps = { + // TODO: remove optionals when dummy data is removed (except for icon) + name?: string; + connectionType?: 'lan' | 'bluetooth' | 'usb' | 'p2p' | 'cloud'; + receivingNodeOsType?: Omit; +} & ({ image: string } | { icon?: Icon } | { brandIcon: string }); + +function DropItem(props: DropItemProps) { + let icon; + if ('image' in props) { + icon = {props.name}; + } else if ('brandIcon' in props) { + let brandIconSrc; + switch (props.brandIcon) { + case 'google-drive': + brandIconSrc = GoogleDrive; + break; + case 'icloud': + brandIconSrc = iCloud; + break; + case 'mega': + brandIconSrc = Mega; + break; + } + if (brandIconSrc) { + icon = ( +
+ {props.name} +
+ ); + } + } else { + // + const Icon = props.icon || User; + icon = ; + } + + return ( +
+
+ + + +
{icon}
+ + + + {props.name && {props.name}} +
+ {props.receivingNodeOsType && {props.receivingNodeOsType}} + {props.connectionType && ( + + {props.connectionType} + + )} +
+
+
+ ); +} + +export default function SpacedropScreen() { + const searchRef = useRef(null); + + return ( + + + {/* */} +
+ } + className={classes.honeycombOuter} + > +
+ + + + + + + + + + + + +
+
+ ); +} diff --git a/packages/interface/src/screens/Spaces.tsx b/packages/interface/src/screens/Spaces.tsx index 1d9379599..c3b414716 100644 --- a/packages/interface/src/screens/Spaces.tsx +++ b/packages/interface/src/screens/Spaces.tsx @@ -1,9 +1,10 @@ import { ScreenHeading } from '@sd/ui'; +import { ScreenContainer } from './_Layout'; export default function SpacesScreen() { return ( -
+ Spaces -
+ ); } diff --git a/packages/interface/src/screens/_Layout.tsx b/packages/interface/src/screens/_Layout.tsx new file mode 100644 index 000000000..d8bd0e513 --- /dev/null +++ b/packages/interface/src/screens/_Layout.tsx @@ -0,0 +1,19 @@ +import clsx from 'clsx'; +import { PropsWithChildren, ReactNode, createContext } from 'react'; +import DragRegion from '~/components/layout/DragRegion'; + +export function ScreenContainer( + props: PropsWithChildren & { className?: string; dragRegionChildren?: ReactNode } +) { + return ( +
+ {props.dragRegionChildren} +
{props.children}
+
+ ); +} diff --git a/packages/interface/src/screens/index.tsx b/packages/interface/src/screens/index.tsx index a89418321..bb15c1617 100644 --- a/packages/interface/src/screens/index.tsx +++ b/packages/interface/src/screens/index.tsx @@ -11,11 +11,12 @@ const screens: RouteObject[] = [ { path: 'media', element: lazyEl(() => import('./Media')) }, { path: 'spaces', element: lazyEl(() => import('./Spaces')) }, { path: 'debug', element: lazyEl(() => import('./Debug')) }, + { path: 'spacedrop', element: lazyEl(() => import('./Spacedrop')) }, { path: 'location/:id', element: lazyEl(() => import('./LocationExplorer')) }, { path: 'tag/:id', element: lazyEl(() => import('./TagExplorer')) }, { path: 'settings', - element: lazyEl(() => import('./settings/Layout')), + element: lazyEl(() => import('./settings/_Layout')), children: settingsScreens }, { path: '*', element: lazyEl(() => import('./NotFound')) } diff --git a/packages/interface/src/screens/settings/SettingsSubPage.tsx b/packages/interface/src/screens/settings/SettingsSubPage.tsx index 6e7c34774..10c633406 100644 --- a/packages/interface/src/screens/settings/SettingsSubPage.tsx +++ b/packages/interface/src/screens/settings/SettingsSubPage.tsx @@ -1,7 +1,7 @@ import { Suspense } from 'react'; import { Outlet } from 'react-router'; -export default function SettingsScreen() { +export default function SettingsSubPageScreen() { return (
diff --git a/packages/interface/src/screens/settings/Layout.tsx b/packages/interface/src/screens/settings/_Layout.tsx similarity index 86% rename from packages/interface/src/screens/settings/Layout.tsx rename to packages/interface/src/screens/settings/_Layout.tsx index 425101e83..6d7667500 100644 --- a/packages/interface/src/screens/settings/Layout.tsx +++ b/packages/interface/src/screens/settings/_Layout.tsx @@ -2,7 +2,7 @@ import { Suspense } from 'react'; import { Outlet } from 'react-router'; import { SettingsSidebar } from '~/components/settings/SettingsSidebar'; -export default function SettingsScreen() { +export default function SettingsScreenContainer() { return (
diff --git a/packages/interface/src/screens/settings/client/ExtensionsSettings.tsx b/packages/interface/src/screens/settings/client/ExtensionsSettings.tsx index 43eff9b40..88a5d808c 100644 --- a/packages/interface/src/screens/settings/client/ExtensionsSettings.tsx +++ b/packages/interface/src/screens/settings/client/ExtensionsSettings.tsx @@ -1,5 +1,5 @@ import { MagnifyingGlass } from 'phosphor-react'; -import { Button, Card, GridLayout, Input } from '@sd/ui'; +import { Button, Card, GridLayout, Input, SearchInput } from '@sd/ui'; import { SettingsContainer } from '~/components/settings/SettingsContainer'; import { SettingsHeader } from '~/components/settings/SettingsHeader'; @@ -63,12 +63,7 @@ export default function ExtensionSettings() { - - -
- } + rightArea={} /> diff --git a/packages/interface/src/screens/settings/info/AboutSpacedrive.tsx b/packages/interface/src/screens/settings/info/AboutSpacedrive.tsx index 328249ff6..ed13c8dd7 100644 --- a/packages/interface/src/screens/settings/info/AboutSpacedrive.tsx +++ b/packages/interface/src/screens/settings/info/AboutSpacedrive.tsx @@ -1,26 +1,30 @@ import Logo from '@sd/assets/images/logo.png'; import { useBridgeQuery } from '@sd/client'; -import { SettingsContainer } from '../../../components/settings/SettingsContainer'; -import { SettingsHeader } from '../../../components/settings/SettingsHeader'; +import { SettingsContainer } from '~/components/settings/SettingsContainer'; +import { useOperatingSystem } from '~/hooks/useOperatingSystem'; export default function AboutSpacedrive() { const buildInfo = useBridgeQuery(['buildInfo']); + const os = useOperatingSystem(); + + const currentPlatformNiceName = + os === 'browser' ? 'Web' : os == 'macOS' ? os : os.charAt(0).toUpperCase() + os.slice(1); + return ( - - The file manager from the future. - - v{buildInfo.data?.version || '-.-.-'} - {buildInfo.data?.commit || 'dev'} - -
- } - > - - +
+ +
+

+ Spacedrive {os !== 'unknown' && <>for {currentPlatformNiceName}} +

+ The file manager from the future. + + v{buildInfo.data?.version || '-.-.-'} - {buildInfo.data?.commit || 'dev'} + +
+
); } diff --git a/packages/interface/src/screens/settings/library/LibraryGeneralSettings.tsx b/packages/interface/src/screens/settings/library/LibraryGeneralSettings.tsx index 9d059bafe..0eb1a44f2 100644 --- a/packages/interface/src/screens/settings/library/LibraryGeneralSettings.tsx +++ b/packages/interface/src/screens/settings/library/LibraryGeneralSettings.tsx @@ -31,11 +31,15 @@ export default function LibraryGeneralSettings() {
Name - +
Description - +
diff --git a/packages/interface/src/screens/settings/library/LocationsSettings.tsx b/packages/interface/src/screens/settings/library/LocationsSettings.tsx index 524e2f98b..b23bed0fc 100644 --- a/packages/interface/src/screens/settings/library/LocationsSettings.tsx +++ b/packages/interface/src/screens/settings/library/LocationsSettings.tsx @@ -1,7 +1,7 @@ import { MagnifyingGlass } from 'phosphor-react'; import { useLibraryMutation, useLibraryQuery } from '@sd/client'; import { LocationCreateArgs } from '@sd/client'; -import { Button, Input, dialogManager } from '@sd/ui'; +import { Button, Input, SearchInput, dialogManager } from '@sd/ui'; import AddLocationDialog from '~/components/dialog/AddLocationDialog'; import LocationListItem from '~/components/location/LocationListItem'; import { SettingsContainer } from '~/components/settings/SettingsContainer'; @@ -20,14 +20,11 @@ export default function LocationSettings() { description="Manage your storage locations." rightArea={
-
- - -
+