From ecc24a43d866b8b5d850fc0be8dce8f6df1ff75f Mon Sep 17 00:00:00 2001 From: Jamie Pine Date: Mon, 24 Oct 2022 01:17:10 -0700 Subject: [PATCH] job indicator + styling --- apps/desktop/src-tauri/tauri.conf.json | 2 +- core/src/api/jobs.rs | 3 ++ core/src/job/worker.rs | 2 ++ packages/client/package.json | 2 +- packages/client/src/core.ts | 1 + packages/client/src/stores/themeStore.ts | 32 ++++++++++++++++++ packages/interface/package.json | 4 ++- .../explorer/ExplorerContextMenu.tsx | 4 +-- .../src/components/jobs/JobManager.tsx | 9 +++-- .../src/components/layout/Sidebar.tsx | 25 +++++++++++--- .../components/settings/SettingsSidebar.tsx | 2 +- packages/interface/src/screens/Overview.tsx | 1 + .../settings/client/GeneralSettings.tsx | 8 ++--- .../library/LibraryGeneralSettings.tsx | 21 +++++++----- packages/interface/src/style.scss | 2 +- packages/ui/src/ContextMenu.tsx | 13 ++++--- packages/ui/src/Loader.tsx | 2 +- packages/ui/style/colors.scss | 22 +++++++----- packages/ui/style/style.scss | 4 +++ pnpm-lock.yaml | Bin 814349 -> 814892 bytes 20 files changed, 116 insertions(+), 43 deletions(-) create mode 100644 packages/client/src/stores/themeStore.ts diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 7592122aa..8c6edd9db 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -65,7 +65,7 @@ "title": "Spacedrive", "width": 1400, "height": 725, - "minWidth": 700, + "minWidth": 768, "minHeight": 500, "resizable": true, "fullscreen": false, diff --git a/core/src/api/jobs.rs b/core/src/api/jobs.rs index 3455850e8..3ba4c5462 100644 --- a/core/src/api/jobs.rs +++ b/core/src/api/jobs.rs @@ -20,6 +20,9 @@ pub(crate) fn mount() -> RouterBuilder { .library_query("getRunning", |t| { t(|ctx, _: (), _| async move { Ok(ctx.jobs.get_running().await) }) }) + .library_query("isRunning", |t| { + t(|ctx, _: (), _| async move { Ok(ctx.jobs.get_running().await.len() > 0) }) + }) .library_query("getHistory", |t| { t(|_, _: (), library| async move { Ok(JobManager::get_history(&library).await?) }) }) diff --git a/core/src/job/worker.rs b/core/src/job/worker.rs index ea8b148a0..dbbb8c679 100644 --- a/core/src/job/worker.rs +++ b/core/src/job/worker.rs @@ -112,6 +112,7 @@ impl Worker { } drop(worker); + invalidate_query!(ctx, "jobs.isRunning"); // spawn task to handle receiving events from the worker let library_ctx = ctx.clone(); tokio::spawn(Worker::track_progress( @@ -234,6 +235,7 @@ impl Worker { error!("failed to update job report: {:#?}", e); } + invalidate_query!(library, "jobs.isRunning"); invalidate_query!(library, "jobs.getRunning"); invalidate_query!(library, "jobs.getHistory"); diff --git a/packages/client/package.json b/packages/client/package.json index 91bab13d4..b752d6bb8 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -18,7 +18,7 @@ "@rspc/react": "^0.0.0-main-7c0a67c1", "@sd/config": "workspace:*", "@tanstack/react-query": "^4.12.0", - "valtio": "^1.7.0", + "valtio": "^1.7.4", "valtio-persist": "^1.0.2" }, "devDependencies": { diff --git a/packages/client/src/core.ts b/packages/client/src/core.ts index db4e1ff94..03df06a6d 100644 --- a/packages/client/src/core.ts +++ b/packages/client/src/core.ts @@ -7,6 +7,7 @@ export type Procedures = { { key: "getNode", input: never, result: NodeState } | { key: "jobs.getHistory", input: LibraryArgs, result: Array } | { key: "jobs.getRunning", input: LibraryArgs, result: Array } | + { key: "jobs.isRunning", input: LibraryArgs, result: boolean } | { key: "library.getStatistics", input: LibraryArgs, result: Statistics } | { key: "library.list", input: never, result: Array } | { key: "locations.getById", input: LibraryArgs, result: Location | null } | diff --git a/packages/client/src/stores/themeStore.ts b/packages/client/src/stores/themeStore.ts new file mode 100644 index 000000000..2573998f2 --- /dev/null +++ b/packages/client/src/stores/themeStore.ts @@ -0,0 +1,32 @@ +import { proxy, useSnapshot } from 'valtio'; +import proxyWithPersist, { PersistStrategy, ProxyPersistStorageEngine } from 'valtio-persist'; + +const storage: ProxyPersistStorageEngine = { + getItem: (name) => window.localStorage.getItem(name), + setItem: (name, value) => window.localStorage.setItem(name, value), + removeItem: (name) => window.localStorage.removeItem(name), + getAllKeys: () => Object.keys(window.localStorage) +}; + +const appThemeStore = proxyWithPersist({ + // must be unique, files/paths will be created with this prefix + name: 'appTheme', + version: 0, + initialState: { + themeName: 'vanilla', + themeMode: 'light' as 'light' | 'dark', + syncThemeWithSystem: false, + hueValue: null as number | null + }, + persistStrategies: PersistStrategy.SingleFile, + migrations: {}, + getStorage: () => storage +}); + +export function useThemeStore() { + return useSnapshot(appThemeStore); +} + +export function getThemeStore() { + return appThemeStore; +} diff --git a/packages/interface/package.json b/packages/interface/package.json index 8eb651cf9..974d61a94 100644 --- a/packages/interface/package.json +++ b/packages/interface/package.json @@ -37,6 +37,8 @@ "byte-size": "^8.1.0", "clsx": "^1.2.1", "dayjs": "^1.11.5", + "iconoir": "^5.3.2", + "iconoir-react": "^5.3.2", "phosphor-react": "^1.4.1", "react": "^18.2.0", "react-colorful": "^5.6.1", @@ -51,7 +53,7 @@ "tailwindcss": "^3.1.8", "use-count-up": "^3.0.1", "use-debounce": "^8.0.4", - "valtio": "^1.7.0" + "valtio": "^1.7.4" }, "devDependencies": { "@sd/config": "workspace:*", diff --git a/packages/interface/src/components/explorer/ExplorerContextMenu.tsx b/packages/interface/src/components/explorer/ExplorerContextMenu.tsx index 03d5a4cdc..36401b9e0 100644 --- a/packages/interface/src/components/explorer/ExplorerContextMenu.tsx +++ b/packages/interface/src/components/explorer/ExplorerContextMenu.tsx @@ -105,8 +105,8 @@ export default function ExplorerContextMenu(props: PropsWithChildren) { - - + + diff --git a/packages/interface/src/components/jobs/JobManager.tsx b/packages/interface/src/components/jobs/JobManager.tsx index 1a1ccc77f..af8bec52f 100644 --- a/packages/interface/src/components/jobs/JobManager.tsx +++ b/packages/interface/src/components/jobs/JobManager.tsx @@ -57,7 +57,7 @@ function elapsed(seconds: number) { return new Date(seconds * 1000).toUTCString().match(/(\d\d:\d\d:\d\d)/)?.[0]; } -const HeaderContainer = tw.div`z-20 flex items-center w-full h-10 px-2 border-b border-app-line rounded-t-md bg-app-selected`; +const HeaderContainer = tw.div`z-20 flex items-center w-full h-10 px-2 border-b border-app-line/50 rounded-t-md `; export function JobsManager() { const runningJobs = useLibraryQuery(['jobs.getRunning']); @@ -71,6 +71,9 @@ export function JobsManager() { +
@@ -108,7 +111,7 @@ function Job({ job }: { job: JobReport }) {
)} -
+
{isRunning ? 'Elapsed' : job.status === 'Failed' ? 'Failed after' : 'Took'}{' '} {job.seconds_elapsed @@ -122,7 +125,7 @@ function Job({ job }: { job: JobReport }) { }
- {job.id} + {/* {job.id} */}
diff --git a/packages/interface/src/components/layout/Sidebar.tsx b/packages/interface/src/components/layout/Sidebar.tsx index 67264beae..d864fe9c8 100644 --- a/packages/interface/src/components/layout/Sidebar.tsx +++ b/packages/interface/src/components/layout/Sidebar.tsx @@ -8,7 +8,16 @@ import { useLibraryQuery, usePlatform } from '@sd/client'; -import { Button, ButtonLink, CategoryHeading, Dropdown, OverlayPanel, cva, tw } from '@sd/ui'; +import { + Button, + ButtonLink, + CategoryHeading, + Dropdown, + Loader, + OverlayPanel, + cva, + tw +} from '@sd/ui'; import clsx from 'clsx'; import { CheckCircle, CirclesFour, Planet, ShareNetwork } from 'phosphor-react'; import React, { PropsWithChildren } from 'react'; @@ -23,8 +32,10 @@ import { MacTrafficLights } from '../os/TrafficLights'; export function Sidebar() { const os = useOperatingSystem(); const { library, libraries, isLoading: isLoadingLibraries, switchLibrary } = useCurrentLibrary(); - // const itemStyles = macOnly(os, 'dark:hover:bg-sidebar-box dark:hover:bg-opacity-50'); + const { data: isRunningJob } = useLibraryQuery(['jobs.isRunning']); + + // const itemStyles = macOnly(os, 'dark:hover:bg-sidebar-box dark:hover:bg-opacity-50'); return (
*/}
-
+
@@ -114,7 +125,11 @@ export function Sidebar() { variant="outline" className="radix-state-open:bg-sidebar-selected/50" > - + {isRunningJob ? ( + + ) : ( + + )} } > diff --git a/packages/interface/src/components/settings/SettingsSidebar.tsx b/packages/interface/src/components/settings/SettingsSidebar.tsx index 27d2d5b71..0ceccff2a 100644 --- a/packages/interface/src/components/settings/SettingsSidebar.tsx +++ b/packages/interface/src/components/settings/SettingsSidebar.tsx @@ -15,7 +15,7 @@ import { SettingsHeading, SettingsIcon } from './SettingsHeader'; export const SettingsSidebar = () => { return ( -
+
Client diff --git a/packages/interface/src/screens/Overview.tsx b/packages/interface/src/screens/Overview.tsx index a4d686f52..804d8e339 100644 --- a/packages/interface/src/screens/Overview.tsx +++ b/packages/interface/src/screens/Overview.tsx @@ -1,5 +1,6 @@ import { PlusIcon } from '@heroicons/react/24/solid'; import { + getExplorerStore, onLibraryChange, queryClient, useCurrentLibrary, diff --git a/packages/interface/src/screens/settings/client/GeneralSettings.tsx b/packages/interface/src/screens/settings/client/GeneralSettings.tsx index 8a9e610d6..66ac1a303 100644 --- a/packages/interface/src/screens/settings/client/GeneralSettings.tsx +++ b/packages/interface/src/screens/settings/client/GeneralSettings.tsx @@ -35,14 +35,14 @@ export default function GeneralSettings() { Node Name
-
+
Node Port
- Run daemon when app closed + Run daemon when app closed
- + Data Folder {node?.data_path} diff --git a/packages/interface/src/screens/settings/library/LibraryGeneralSettings.tsx b/packages/interface/src/screens/settings/library/LibraryGeneralSettings.tsx index d386cdf2e..2daadfda4 100644 --- a/packages/interface/src/screens/settings/library/LibraryGeneralSettings.tsx +++ b/packages/interface/src/screens/settings/library/LibraryGeneralSettings.tsx @@ -1,4 +1,4 @@ -import { useBridgeMutation } from '@sd/client'; +import { onLibraryChange, useBridgeMutation } from '@sd/client'; import { useCurrentLibrary } from '@sd/client'; import { Button, Input, Switch } from '@sd/ui'; import { useEffect, useState } from 'react'; @@ -21,15 +21,20 @@ export default function LibraryGeneralSettings() { }); }, 500); - const { register, watch } = useForm({ - defaultValues: { - name: library?.config.name, - description: library?.config.description - } + const { register, watch, reset, getValues } = useForm({ + defaultValues: { id: library?.uuid, ...library?.config } }); - watch(debounced); // Listen for form changes - // This forces the debounce to run when the component is unmounted + // ensure the form is updated when the library changes + useEffect(() => { + if (library?.uuid !== getValues('id')) { + reset({ id: library?.uuid, ...library?.config }); + } + }, [library, getValues, reset]); + + watch(debounced); // listen for form changes + + // force the debounce to run when the component is unmounted useEffect(() => () => debounced.flush(), [debounced]); return ( diff --git a/packages/interface/src/style.scss b/packages/interface/src/style.scss index bd1ab94b8..e7cb25250 100644 --- a/packages/interface/src/style.scss +++ b/packages/interface/src/style.scss @@ -41,7 +41,7 @@ body { width: 8px; } &::-webkit-scrollbar-track { - @apply bg-[#00000006] dark:bg-[#00000000] mt-[53px] rounded-[6px]; + @apply bg-[#00000000] mt-[53px] rounded-[6px]; } &::-webkit-scrollbar-thumb { @apply rounded-[6px] bg-app-box; diff --git a/packages/ui/src/ContextMenu.tsx b/packages/ui/src/ContextMenu.tsx index dda24e175..604422478 100644 --- a/packages/ui/src/ContextMenu.tsx +++ b/packages/ui/src/ContextMenu.tsx @@ -12,9 +12,8 @@ const MENU_CLASSES = ` flex flex-col min-w-[8rem] px-1 py-0.5 text-left text-sm text-menu-ink - bg-menu border-menu-border - border border-transparent - shadow-md shadow-menu-shade/20 + bg-menu cool-shadow + border border-menu-line select-none cursor-default rounded-md `; @@ -48,7 +47,7 @@ export const SubMenu = ({ }: RadixCM.MenuSubContentProps & ItemProps) => { return ( - + @@ -63,14 +62,14 @@ export const SubMenu = ({ const itemStyles = cva( [ 'flex flex-row items-center justify-start flex-1', - 'px-2 py-1 space-x-2', + 'px-2 py-[3px] space-x-2', 'cursor-default rounded', 'focus:outline-none' ], { variants: { variant: { - default: 'hover:bg-accent focus:bg-accent', + default: 'hover:bg-accent focus:bg-accent hover:text-white', danger: [ 'text-red-600 dark:text-red-400', 'hover:text-white focus:text-white', @@ -102,7 +101,7 @@ export const Item = ({ }: ItemProps & RadixCM.MenuItemProps) => (
{children ? children : } diff --git a/packages/ui/src/Loader.tsx b/packages/ui/src/Loader.tsx index fadd2473d..eed54a5c5 100644 --- a/packages/ui/src/Loader.tsx +++ b/packages/ui/src/Loader.tsx @@ -8,7 +8,7 @@ export function Loader(props: { className?: string }) { strokeOpacity={4} strokeWidth={5} speed={1} - className={clsx('ml-0.5 mt-[2px] -mr-1 w-7 h-7', props.className)} + className={clsx('w-7 h-7', props.className)} /> ); } diff --git a/packages/ui/style/colors.scss b/packages/ui/style/colors.scss index 368870efd..1b328d9fe 100644 --- a/packages/ui/style/colors.scss +++ b/packages/ui/style/colors.scss @@ -1,5 +1,5 @@ :root { - --dark-hue: 235; //300, 295 + --dark-hue: 230; //300, 295 --light-hue: 235; // global @@ -35,8 +35,8 @@ --color-app-shade: var(--dark-hue), 15%, 0%; --color-app-frame: var(--dark-hue), 15%, 25%; // menu - --color-menu: var(--dark-hue), 16%, 7%; - --color-menu-line: var(--dark-hue), 5%, 18%; + --color-menu: var(--dark-hue), 15%, 7%; + --color-menu-line: var(--dark-hue), 15%, 7%; --color-menu-ink: var(--dark-hue), 5%, 100%; --color-menu-faint: var(--dark-hue), 5%, 80%; --color-menu-hover: var(--dark-hue), 15%, 30%; @@ -56,16 +56,15 @@ // text --color-ink: var(--light-hue), 5%, 20%; --color-ink-dull: var(--light-hue), 5%, 30%; - --color-ink-faint: var(--light-hue), 5%, 60%; + --color-ink-faint: var(--light-hue), 5%, 40%; // sidebar - --color-sidebar: var(--light-hue), 5%, 97%; + --color-sidebar: var(--light-hue), 5%, 96%; --color-sidebar-box: var(--light-hue), 5%, 100%; --color-sidebar-line: var(--light-hue), 10%, 85%; --color-sidebar-divider: var(--light-hue), 15%, 93%; --color-sidebar-button: var(--light-hue), 15%, 100%; --color-sidebar-selected: var(--light-hue), 10%, 80%; --color-sidebar-shade: var(--light-hue), 15%, 100%; - // main --color-app: var(--light-hue), 5%, 100%; --color-app-box: var(--light-hue), 5%, 98%; @@ -79,12 +78,19 @@ --color-app-hover: var(--light-hue), 5%, 100%; --color-app-shade: var(--light-hue), 15%, 50%; --color-app-frame: 0, 0%, 100%; - // menu - --color-menu: var(--light-hue), 16%, 14%; + --color-menu: var(--light-hue), 16%, 0%; --color-menu-line: var(--light-hue), 5%, 18%; --color-menu-ink: var(--light-hue), 5%, 100%; --color-menu-faint: var(--light-hue), 5%, 80%; + --color-menu-hover: var(--light-hue), 15%, 80%; + --color-menu-selected: var(--light-hue), 5%, 30%; + --color-menu-shade: var(--light-hue), 5%, 0%; + + --color-menu: var(--light-hue), 16%, 99%; + --color-menu-line: var(--light-hue), 5%, 90%; + --color-menu-ink: var(--light-hue), 5%, 30%; + --color-menu-faint: var(--light-hue), 5%, 80%; --color-menu-hover: var(--light-hue), 15%, 20%; --color-menu-selected: var(--light-hue), 5%, 30%; --color-menu-shade: var(--light-hue), 5%, 0%; diff --git a/packages/ui/style/style.scss b/packages/ui/style/style.scss index d09d63cdc..ad0bd68a2 100644 --- a/packages/ui/style/style.scss +++ b/packages/ui/style/style.scss @@ -30,3 +30,7 @@ // -webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1)); mask-image: linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100px); } + +.cool-shadow { + box-shadow: rgb(0 0 0 / 9%) 0px 3px 12px; +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f32cd5592dfeac00c4c6754295b3c84d85850fbb..d8f97758e96e8be2a69101414b0df68f8b77c3ce 100644 GIT binary patch delta 417 zcmeCZWw_>^;f4+??abu-y!^}}D}^{yJ!3s1E(I`vis}}nCMK7_=AMNKvzNR*N5m7oWNuhYFc3G7U-BAVHV|Bnr#^Bs&5jMo8@Wgl6w(2>1jycR=aeQ#TBK%H8RbP7YP*CPgk`0s`MNmf