mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-05-06 22:33:34 -04:00
Object Kind (#397)
* add temp custom icons and tweak styles * tweaks * - added Object type structs - added extension enums with variant macros - improved explorer rendering - added database migration hotfix * - added dev only data folder - improved explorer image loading * macros do rule ! * remove baselining Co-authored-by: Brendan Allan <brendonovich@outlook.com>
This commit is contained in:
@@ -6,7 +6,7 @@ import ExplorerContextMenu from './ExplorerContextMenu';
|
||||
import { VirtualizedList } from './VirtualizedList';
|
||||
|
||||
interface Props {
|
||||
data: ExplorerData;
|
||||
data?: ExplorerData;
|
||||
}
|
||||
|
||||
export default function Explorer(props: Props) {
|
||||
@@ -24,16 +24,17 @@ export default function Explorer(props: Props) {
|
||||
<ExplorerContextMenu>
|
||||
<div className="relative flex flex-col w-full bg-gray-650">
|
||||
<TopBar />
|
||||
<div className="relative flex flex-row w-full max-h-full">
|
||||
<VirtualizedList data={props.data?.items || []} context={props.data.context} />
|
||||
|
||||
<div className="relative flex flex-row w-full max-h-full ">
|
||||
{props.data && (
|
||||
<VirtualizedList data={props.data.items || []} context={props.data.context} />
|
||||
)}
|
||||
{expStore.showInspector && (
|
||||
<div className="min-w-[260px] max-w-[260px]">
|
||||
{props.data.items[expStore.selectedRowIndex]?.id && (
|
||||
<Inspector
|
||||
key={props.data.items[expStore.selectedRowIndex].id}
|
||||
data={props.data.items[expStore.selectedRowIndex]}
|
||||
/>
|
||||
)}
|
||||
<div className="flex min-w-[260px] max-w-[260px]">
|
||||
<Inspector
|
||||
key={props.data?.items[expStore.selectedRowIndex]?.id}
|
||||
data={props.data?.items[expStore.selectedRowIndex]}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { useExplorerStore, useLibraryMutation, useLibraryQuery } from '@sd/client';
|
||||
import {
|
||||
getExplorerStore,
|
||||
useExplorerStore,
|
||||
useLibraryMutation,
|
||||
useLibraryQuery
|
||||
} from '@sd/client';
|
||||
import { ContextMenu as CM } from '@sd/ui';
|
||||
import {
|
||||
ArrowBendUpRight,
|
||||
@@ -59,7 +64,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function ExplorerContextMenu(props: Props) {
|
||||
const store = useExplorerStore();
|
||||
const store = getExplorerStore();
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
@@ -101,18 +106,13 @@ export default function ExplorerContextMenu(props: Props) {
|
||||
</CM.SubMenu>
|
||||
)}
|
||||
<CM.SubMenu label="More actions..." icon={Plus}>
|
||||
<CM.SubMenu label="Move to library" icon={FilePlus}>
|
||||
{/* {libraries.map(library => <CM.Item key={library.id} label={library.config.name} />)} */}
|
||||
<CM.Item label="Remove from library" icon={FileX} />
|
||||
</CM.SubMenu>
|
||||
<CM.Separator />
|
||||
<CM.Item label="Encrypt" icon={LockSimple} />
|
||||
<CM.Item label="Compress" icon={Package} />
|
||||
<CM.SubMenu label="Convert to" icon={ArrowBendUpRight}>
|
||||
<CM.Item label="PNG" />
|
||||
<CM.Item label="WebP" />
|
||||
</CM.SubMenu>
|
||||
<CM.Item label="Secure delete" icon={TrashSimple} />
|
||||
<CM.Item variant="danger" label="Secure delete" icon={TrashSimple} />
|
||||
</CM.SubMenu>
|
||||
|
||||
<CM.Separator />
|
||||
|
||||
@@ -18,6 +18,8 @@ function FileItem({ data, selected, index, ...rest }: Props) {
|
||||
|
||||
// props.index === store.selectedRowIndex
|
||||
|
||||
const isVid = isVideo(data.extension || '');
|
||||
|
||||
return (
|
||||
<div
|
||||
onContextMenu={(e) => {
|
||||
@@ -44,17 +46,23 @@ function FileItem({ data, selected, index, ...rest }: Props) {
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
'flex items-center justify-center h-full p-1 rounded border-transparent border-2 shrink-0'
|
||||
'flex relative items-center justify-center h-full p-1 rounded border-transparent border-2 shrink-0'
|
||||
)}
|
||||
>
|
||||
<FileThumb
|
||||
className={clsx(
|
||||
'border-4 border-gray-250 rounded-sm shadow-md shadow-gray-750 object-cover max-w-full max-h-full w-auto overflow-hidden',
|
||||
isVideo(data.extension || '') && 'border-gray-950'
|
||||
'border-4 border-gray-250 rounded shadow-md shadow-gray-750 object-cover max-w-full max-h-full w-auto overflow-hidden',
|
||||
isVid && 'border-gray-950 border-x-0 border-y-[9px]'
|
||||
)}
|
||||
data={data}
|
||||
kind={data.extension === 'zip' ? 'zip' : isVid ? 'video' : 'other'}
|
||||
size={getExplorerStore().gridItemSize}
|
||||
/>
|
||||
{data?.extension && isVid && (
|
||||
<div className="absolute bottom-4 font-semibold opacity-70 right-2 py-0.5 px-1 text-[9px] uppercase bg-gray-800 rounded">
|
||||
{data.extension}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
@@ -99,6 +107,11 @@ function isVideo(extension: string) {
|
||||
'wmv',
|
||||
'mp4',
|
||||
'webm',
|
||||
'flv'
|
||||
'flv',
|
||||
'mpg',
|
||||
'hevc',
|
||||
'ogv',
|
||||
'swf',
|
||||
'wtv'
|
||||
].includes(extension);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import videoSvg from '@sd/assets/svgs/video.svg';
|
||||
import zipSvg from '@sd/assets/svgs/zip.svg';
|
||||
import { getExplorerStore, useExplorerStore, usePlatform } from '@sd/client';
|
||||
import { ExplorerItem } from '@sd/client';
|
||||
import clsx from 'clsx';
|
||||
@@ -14,6 +16,7 @@ interface Props {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
iconClassNames?: string;
|
||||
kind?: 'video' | 'image' | 'audio' | 'zip' | 'other';
|
||||
}
|
||||
|
||||
export default function FileThumb({ data, ...props }: Props) {
|
||||
@@ -41,11 +44,30 @@ export default function FileThumb({ data, ...props }: Props) {
|
||||
return (
|
||||
<img
|
||||
style={props.style}
|
||||
decoding="async"
|
||||
// width={props.size}
|
||||
className={clsx('pointer-events-none', props.className)}
|
||||
src={url}
|
||||
/>
|
||||
);
|
||||
|
||||
if (props.kind === 'video') {
|
||||
return (
|
||||
<div className="">
|
||||
<img
|
||||
src={videoSvg}
|
||||
className={clsx('w-full overflow-hidden h-full', props.iconClassNames)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (props.kind === 'zip') {
|
||||
return (
|
||||
<div className="">
|
||||
<img src={zipSvg} className={clsx('w-full overflow-hidden h-full')} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const Icon = icons[data.extension as keyof typeof icons];
|
||||
|
||||
@@ -18,13 +18,13 @@ import { isObject } from './utils';
|
||||
|
||||
interface Props {
|
||||
context?: ExplorerContext;
|
||||
data: ExplorerItem;
|
||||
data?: ExplorerItem;
|
||||
}
|
||||
|
||||
export const Inspector = (props: Props) => {
|
||||
const is_dir = props.data?.type === 'Path' ? props.data.is_dir : false;
|
||||
|
||||
const objectData = isObject(props.data) ? props.data : props.data.object;
|
||||
const objectData = props.data ? (isObject(props.data) ? props.data : props.data.object) : null;
|
||||
|
||||
// this prevents the inspector from fetching data when the user is navigating quickly
|
||||
const [readyToFetch, setReadyToFetch] = useState(false);
|
||||
@@ -33,7 +33,7 @@ export const Inspector = (props: Props) => {
|
||||
setReadyToFetch(true);
|
||||
}, 350);
|
||||
return () => clearTimeout(timeout);
|
||||
}, [props.data.id]);
|
||||
}, [props.data?.id]);
|
||||
|
||||
// this is causing LAG
|
||||
const { data: tags } = useLibraryQuery(['tags.getForFile', objectData?.id || -1], {
|
||||
@@ -41,113 +41,115 @@ export const Inspector = (props: Props) => {
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="p-2 pt-0.5 pr-1 overflow-x-hidden custom-scroll inspector-scroll pb-[55px]">
|
||||
{!!props.data && (
|
||||
<>
|
||||
<div className="flex items-center justify-center w-full overflow-hidden bg-black rounded-md ">
|
||||
<FileThumb
|
||||
iconClassNames="!my-10"
|
||||
size={230}
|
||||
className="!m-0 flex flex-shrink flex-grow-0"
|
||||
data={props.data}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col w-full pt-0.5 pb-4 overflow-hidden shadow select-text">
|
||||
<h3 className="pt-3 pl-3 text-base font-bold">
|
||||
{props.data?.name}
|
||||
{props.data?.extension && `.${props.data.extension}`}
|
||||
</h3>
|
||||
{objectData && (
|
||||
<div className="flex flex-row m-3 space-x-2">
|
||||
<Tooltip label="Favorite">
|
||||
<FavoriteButton data={objectData} />
|
||||
</Tooltip>
|
||||
<Tooltip label="Share">
|
||||
<Button size="sm" noPadding>
|
||||
<ShareIcon className="w-[18px] h-[18px]" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip label="Link">
|
||||
<Button size="sm" noPadding>
|
||||
<Link className="w-[18px] h-[18px]" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
{!!tags?.length && (
|
||||
<>
|
||||
<Divider />
|
||||
<MetaItem
|
||||
// title="Tags"
|
||||
value={
|
||||
<div className="flex flex-wrap mt-1.5 gap-1.5">
|
||||
{tags?.map((tag) => (
|
||||
<div
|
||||
// onClick={() => setSelectedTag(tag.id === selectedTag ? null : tag.id)}
|
||||
key={tag.id}
|
||||
className={clsx(
|
||||
'flex items-center rounded px-1.5 py-0.5'
|
||||
// selectedTag === tag.id && 'ring'
|
||||
)}
|
||||
style={{ backgroundColor: tag.color + 'CC' }}
|
||||
>
|
||||
<span className="text-xs text-white drop-shadow-md">{tag.name}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{props.context?.type == 'Location' && props.data?.type === 'Path' && (
|
||||
<>
|
||||
<Divider />
|
||||
<MetaItem
|
||||
title="URI"
|
||||
value={`${props.context.local_path}/${props.data.materialized_path}`}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Divider />
|
||||
<MetaItem
|
||||
title="Date Created"
|
||||
value={moment(props.data?.date_created).format('MMMM Do YYYY, h:mm:ss a')}
|
||||
/>
|
||||
<Divider />
|
||||
<MetaItem
|
||||
title="Date Indexed"
|
||||
value={moment(props.data?.date_indexed).format('MMMM Do YYYY, h:mm:ss a')}
|
||||
/>
|
||||
{!is_dir && (
|
||||
<>
|
||||
<Divider />
|
||||
<div className="flex flex-row items-center px-3 py-2 meta-item">
|
||||
{props.data?.extension && (
|
||||
<span className="inline px-1 mr-1 text-xs font-bold uppercase bg-gray-500 rounded-md text-gray-150">
|
||||
{props.data?.extension}
|
||||
</span>
|
||||
)}
|
||||
<p className="text-xs text-gray-600 break-all truncate dark:text-gray-300">
|
||||
{props.data?.extension
|
||||
? //@ts-ignore
|
||||
types[props.data.extension.toUpperCase()]?.descriptions.join(' / ')
|
||||
: 'Unknown'}
|
||||
</p>
|
||||
<div className="p-2 pt-0.5 max-h-screen custom-scroll inspector-scroll pr-1 m-1 overflow-x-hidden">
|
||||
<div className="">
|
||||
{!!props.data && (
|
||||
<>
|
||||
<div className="flex items-center justify-center w-full overflow-hidden rounded-md ">
|
||||
<FileThumb
|
||||
iconClassNames="!my-10"
|
||||
size={230}
|
||||
className="!m-0 flex flex-shrink flex-grow-0"
|
||||
data={props.data}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col w-full pt-0.5 pb-4 overflow-hidden select-text">
|
||||
<h3 className="flex mt-3 ml-3 text-base font-bold">
|
||||
{props.data?.name}
|
||||
{props.data?.extension && `.${props.data.extension}`}
|
||||
</h3>
|
||||
{objectData && (
|
||||
<div className="flex flex-row m-3 space-x-2">
|
||||
<Tooltip label="Favorite">
|
||||
<FavoriteButton data={objectData} />
|
||||
</Tooltip>
|
||||
<Tooltip label="Share">
|
||||
<Button size="sm" noPadding>
|
||||
<ShareIcon className="w-[18px] h-[18px]" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip label="Link">
|
||||
<Button size="sm" noPadding>
|
||||
<Link className="w-[18px] h-[18px]" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{objectData && (
|
||||
<>
|
||||
<Note data={objectData} />
|
||||
<Divider />
|
||||
{objectData.cas_id && (
|
||||
<MetaItem title="Unique Content ID" value={objectData.cas_id} />
|
||||
)}
|
||||
{!!tags?.length && (
|
||||
<>
|
||||
<Divider />
|
||||
<MetaItem
|
||||
// title="Tags"
|
||||
value={
|
||||
<div className="flex flex-wrap mt-1.5 gap-1.5">
|
||||
{tags?.map((tag) => (
|
||||
<div
|
||||
// onClick={() => setSelectedTag(tag.id === selectedTag ? null : tag.id)}
|
||||
key={tag.id}
|
||||
className={clsx(
|
||||
'flex items-center rounded px-1.5 py-0.5'
|
||||
// selectedTag === tag.id && 'ring'
|
||||
)}
|
||||
style={{ backgroundColor: tag.color + 'CC' }}
|
||||
>
|
||||
<span className="text-xs text-white drop-shadow-md">{tag.name}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{props.context?.type == 'Location' && props.data?.type === 'Path' && (
|
||||
<>
|
||||
<Divider />
|
||||
<MetaItem
|
||||
title="URI"
|
||||
value={`${props.context.local_path}/${props.data.materialized_path}`}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Divider />
|
||||
<MetaItem
|
||||
title="Date Created"
|
||||
value={moment(props.data?.date_created).format('MMMM Do YYYY, h:mm:ss a')}
|
||||
/>
|
||||
<Divider />
|
||||
<MetaItem
|
||||
title="Date Indexed"
|
||||
value={moment(props.data?.date_indexed).format('MMMM Do YYYY, h:mm:ss a')}
|
||||
/>
|
||||
{!is_dir && (
|
||||
<>
|
||||
<Divider />
|
||||
<div className="flex flex-row items-center px-3 py-2 meta-item">
|
||||
{props.data?.extension && (
|
||||
<span className="inline px-1 mr-1 text-xs font-bold uppercase bg-gray-500 rounded-md text-gray-150">
|
||||
{props.data?.extension}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<p className="text-xs text-gray-600 break-all truncate dark:text-gray-300">
|
||||
{props.data?.extension
|
||||
? //@ts-ignore
|
||||
types[props.data.extension.toUpperCase()]?.descriptions.join(' / ')
|
||||
: 'Unknown'}
|
||||
</p>
|
||||
</div>
|
||||
{objectData && (
|
||||
<>
|
||||
<Note data={objectData} />
|
||||
<Divider />
|
||||
{objectData.cas_id && (
|
||||
<MetaItem title="Unique Content ID" value={objectData.cas_id} />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ExplorerLayoutMode, getExplorerStore, useExplorerStore } from '@sd/client';
|
||||
import { ExplorerContext, ExplorerItem, FilePath } from '@sd/client';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import { memo, useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useKey, useOnWindowResize, useWindowSize } from 'rooks';
|
||||
import { useSnapshot } from 'valtio';
|
||||
@@ -33,6 +33,9 @@ export const VirtualizedList: React.FC<Props> = ({ data, context }) => {
|
||||
}
|
||||
useOnWindowResize(handleWindowResize);
|
||||
useLayoutEffect(() => handleWindowResize(), []);
|
||||
useEffect(() => {
|
||||
setWidth(innerRef.current?.offsetWidth || 0);
|
||||
}, [explorerStore.showInspector]);
|
||||
|
||||
// sizing calculations
|
||||
const amountOfColumns = Math.floor(width / explorerStore.gridItemSize) || 8,
|
||||
|
||||
@@ -162,7 +162,7 @@ export function Sidebar() {
|
||||
<div
|
||||
className={clsx(
|
||||
'flex flex-col flex-grow-0 flex-shrink-0 w-48 min-h-full px-2.5 overflow-x-hidden overflow-y-scroll border-r border-gray-100 no-scrollbar bg-gray-50 dark:bg-gray-850 dark:border-gray-750',
|
||||
macOnly(os, 'dark:!bg-opacity-40')
|
||||
macOnly(os, 'dark:!bg-opacity-30')
|
||||
)}
|
||||
>
|
||||
<WindowControls />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
|
||||
import { ChevronLeftIcon, ChevronRightIcon, PhotoIcon } from '@heroicons/react/24/outline';
|
||||
import {
|
||||
OperatingSystem,
|
||||
getExplorerStore,
|
||||
@@ -8,10 +8,14 @@ import {
|
||||
import { Dropdown } from '@sd/ui';
|
||||
import clsx from 'clsx';
|
||||
import {
|
||||
Aperture,
|
||||
ArrowsClockwise,
|
||||
FilmStrip,
|
||||
IconProps,
|
||||
Image,
|
||||
Key,
|
||||
List,
|
||||
MonitorPlay,
|
||||
Rows,
|
||||
SidebarSimple,
|
||||
SquaresFour
|
||||
@@ -49,7 +53,7 @@ const TopBarButton: React.FC<TopBarButtonProps> = ({
|
||||
<button
|
||||
{...props}
|
||||
className={clsx(
|
||||
'mr-[1px] py-0.5 px-0.5 text-md font-medium hover:bg-gray-150 dark:transparent dark:hover:bg-gray-550 rounded-md transition-colors duration-100',
|
||||
'mr-[1px] flex py-0.5 px-0.5 text-md font-medium hover:bg-gray-150 dark:transparent dark:hover:bg-gray-550 rounded-md transition-colors duration-100',
|
||||
{
|
||||
'rounded-r-none rounded-l-none': group && !left && !right,
|
||||
'rounded-r-none': group && left,
|
||||
@@ -220,22 +224,31 @@ export const TopBar: React.FC<TopBarProps> = (props) => {
|
||||
|
||||
<div data-tauri-drag-region className="flex flex-row justify-center flex-grow">
|
||||
<div className="flex mx-8">
|
||||
<Tooltip label="List view">
|
||||
<Tooltip label="Grid view">
|
||||
<TopBarButton
|
||||
group
|
||||
left
|
||||
active={store.layoutMode === 'grid'}
|
||||
icon={SquaresFour}
|
||||
onClick={() => (getExplorerStore().layoutMode = 'grid')}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip label="List view">
|
||||
<TopBarButton
|
||||
group
|
||||
active={store.layoutMode === 'list'}
|
||||
icon={Rows}
|
||||
onClick={() => (getExplorerStore().layoutMode = 'list')}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip label="Grid view">
|
||||
|
||||
<Tooltip label="Media view">
|
||||
<TopBarButton
|
||||
group
|
||||
right
|
||||
active={store.layoutMode === 'grid'}
|
||||
icon={SquaresFour}
|
||||
onClick={() => (getExplorerStore().layoutMode = 'grid')}
|
||||
active={store.layoutMode === 'media'}
|
||||
icon={MonitorPlay}
|
||||
onClick={() => (getExplorerStore().layoutMode = 'media')}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
@@ -17,9 +17,9 @@ export const Tooltip = ({
|
||||
</TooltipPrimitive.Trigger>
|
||||
<TooltipPrimitive.Content
|
||||
side={position}
|
||||
className="text-sm rounded px-2 py-1 mb-[2px] bg-gray-300 dark:!bg-gray-500 dark:text-gray-100"
|
||||
className="text-xs rounded px-2 py-1 mb-[2px] bg-gray-300 dark:!bg-gray-900 dark:text-gray-100"
|
||||
>
|
||||
<TooltipPrimitive.Arrow className="fill-gray-300 dark:!fill-gray-500" />
|
||||
<TooltipPrimitive.Arrow className="fill-gray-300 dark:!fill-gray-900" />
|
||||
{label}
|
||||
</TooltipPrimitive.Content>
|
||||
</TooltipPrimitive.Root>
|
||||
|
||||
@@ -35,7 +35,7 @@ export const LocationExplorer: React.FC<unknown> = () => {
|
||||
|
||||
return (
|
||||
<div className="relative flex flex-col w-full">
|
||||
{library!.uuid && explorerData.data && <Explorer data={explorerData.data} />}
|
||||
<Explorer data={explorerData.data} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useBridgeQuery } from '@sd/client';
|
||||
import { useBridgeQuery, usePlatform } from '@sd/client';
|
||||
import { Input } from '@sd/ui';
|
||||
import { Database } from 'phosphor-react';
|
||||
|
||||
@@ -10,6 +10,8 @@ import { SettingsHeader } from '../../../components/settings/SettingsHeader';
|
||||
export default function GeneralSettings() {
|
||||
const { data: node } = useBridgeQuery(['getNode']);
|
||||
|
||||
const platform = usePlatform();
|
||||
|
||||
return (
|
||||
<SettingsContainer>
|
||||
<SettingsHeader
|
||||
@@ -55,7 +57,14 @@ export default function GeneralSettings() {
|
||||
<span className="text-sm text-gray-200">Run daemon when app closed</span>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<span className="text-xs font-medium text-gray-700 dark:text-gray-400">
|
||||
<span
|
||||
onClick={() => {
|
||||
if (node && platform?.openLink) {
|
||||
platform.openLink(node.data_path);
|
||||
}
|
||||
}}
|
||||
className="text-xs font-medium text-gray-700 dark:text-gray-400"
|
||||
>
|
||||
<Database className="inline w-4 h-4 mr-2 -mt-[2px]" />
|
||||
<b className="mr-2">Data Folder</b>
|
||||
<span className="select-text">{node?.data_path}</span>
|
||||
|
||||
@@ -5,14 +5,6 @@ export default function AboutSpacedrive() {
|
||||
return (
|
||||
<SettingsContainer>
|
||||
<SettingsHeader title="About Spacedrive" description="The file manager from the future." />
|
||||
<span>Version {}</span>
|
||||
<div className="flex flex-col">
|
||||
<span className="mb-1 text-sm font-bold">Created by</span>
|
||||
<span className="max-w-md text-xs text-gray-400">
|
||||
Jamie Pine, Brendan Allan, Oscar Beaumont, Haden Fletcher, Haris Mehrzad Benjamin Akar,
|
||||
and many more.
|
||||
</span>
|
||||
</div>
|
||||
</SettingsContainer>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user