diff --git a/app/gui/src/dashboard/App.tsx b/app/gui/src/dashboard/App.tsx index 9a6deee3dcd9..db72c7ce26fd 100644 --- a/app/gui/src/dashboard/App.tsx +++ b/app/gui/src/dashboard/App.tsx @@ -50,7 +50,6 @@ import * as inputBindingsModule from '#/configurations/inputBindings' import AuthProvider, * as authProvider from '#/providers/AuthProvider' import BackendProvider, { useLocalBackend } from '#/providers/BackendProvider' -import DriveProvider from '#/providers/DriveProvider' import { useHttpClientStrict } from '#/providers/HttpClientProvider' import InputBindingsProvider from '#/providers/InputBindingsProvider' import LocalStorageProvider, * as localStorageProvider from '#/providers/LocalStorageProvider' @@ -98,7 +97,6 @@ import { STATIC_QUERY_OPTIONS } from '#/utilities/reactQuery' import { useInitAuthService } from '#/authentication/service' import { InvitedToOrganizationModal } from '#/modals/InvitedToOrganizationModal' -import { CategoriesProvider } from './layouts/Drive/Categories/categoriesHooks' // ============================ // === Global configuration === @@ -536,20 +534,14 @@ function AppRouter(props: AppRouterProps) { onAuthenticated={onAuthenticated} > - - {/* Ideally this would be in `Drive.tsx`, but it currently must be all the way out here - * due to modals being in `TheModal`. */} - - - - {routes} - - - - - - - + + + {routes} + + + + + diff --git a/app/gui/src/dashboard/layouts/CategorySwitcher.tsx b/app/gui/src/dashboard/layouts/CategorySwitcher.tsx index f6b08477ba1b..278e517eece5 100644 --- a/app/gui/src/dashboard/layouts/CategorySwitcher.tsx +++ b/app/gui/src/dashboard/layouts/CategorySwitcher.tsx @@ -55,7 +55,7 @@ interface CategoryMetadata { /** Props for a {@link CategorySwitcherItem}. */ interface InternalCategorySwitcherItemProps extends CategoryMetadata { readonly currentCategory: Category - readonly setCategory: (category: Category) => void + readonly setCategoryId: (categoryId: Category['id']) => void readonly badgeContent?: React.ReactNode readonly isDisabled: boolean } @@ -71,7 +71,7 @@ const CATEGORY_SWITCHER_VARIANTS = tv({ /** An entry in a {@link CategorySwitcher}. */ function CategorySwitcherItem(props: InternalCategorySwitcherItemProps) { - const { currentCategory, setCategory, badgeContent, isDisabled: isDisabledRaw } = props + const { currentCategory, setCategoryId, badgeContent, isDisabled: isDisabledRaw } = props const { isNested = false, category, icon, label, buttonLabel, dropZoneLabel } = props const [isTransitioning, startTransition] = React.useTransition() @@ -126,7 +126,7 @@ function CategorySwitcherItem(props: InternalCategorySwitcherItemProps) { // and to not invoke the Suspense boundary. // This makes the transition feel more responsive and natural. startTransition(() => { - setCategory(category) + setCategoryId(category.id) }) } }) @@ -221,12 +221,12 @@ function CategorySwitcherItem(props: InternalCategorySwitcherItemProps) { /** Props for a {@link CategorySwitcher}. */ export interface CategorySwitcherProps { readonly category: Category - readonly setCategory: (category: Category) => void + readonly setCategoryId: (categoryId: Category['id']) => void } /** A switcher to choose the currently visible assets table categoryModule.categoryType. */ function CategorySwitcher(props: CategorySwitcherProps) { - const { category, setCategory } = props + const { category, setCategoryId } = props const { getText } = textProvider.useText() const [, setSearchParams] = useSearchParams() @@ -237,7 +237,7 @@ function CategorySwitcher(props: CategorySwitcherProps) { const cloudCategories = useCloudCategoryList() const localCategories = useLocalCategoryList() - const itemProps = { currentCategory: category, setCategory, dispatchAssetEvent } + const itemProps = { currentCategory: category, setCategoryId, dispatchAssetEvent } const { cloudCategory, diff --git a/app/gui/src/dashboard/layouts/Drive.tsx b/app/gui/src/dashboard/layouts/Drive.tsx index 6100f8d316ae..b07fc5778ff1 100644 --- a/app/gui/src/dashboard/layouts/Drive.tsx +++ b/app/gui/src/dashboard/layouts/Drive.tsx @@ -39,6 +39,7 @@ import { useQueryClient, useSuspenseQuery } from '@tanstack/react-query' import { useDeferredValue, useEffect } from 'react' import { toast } from 'react-toastify' import { Suspense } from '../components/Suspense' +import { useCategoriesAPI } from './Drive/Categories/categoriesHooks' import { useDirectoryIds } from './Drive/directoryIdsHooks' // ============= @@ -47,10 +48,6 @@ import { useDirectoryIds } from './Drive/directoryIdsHooks' /** Props for a {@link Drive}. */ export interface DriveProps { - readonly category: Category - readonly setCategory: (category: Category) => void - readonly setCategoryId: (categoryId: Category['id']) => void - readonly resetCategory: () => void readonly hidden: boolean readonly initialProjectName: string | null readonly assetsManagementApiRef: React.Ref @@ -60,13 +57,13 @@ const CATEGORIES_TO_DISPLAY_START_MODAL = ['cloud', 'local', 'local-directory'] /** Contains directory path and directory contents (projects, folders, secrets and files). */ function Drive(props: DriveProps) { - const { category, resetCategory } = props - const { isOffline } = offlineHooks.useOffline() const toastAndLog = toastAndLogHooks.useToastAndLog() const { user } = authProvider.useFullUserSession() const localBackend = backendProvider.useLocalBackend() const { getText } = textProvider.useText() + const categoriesAPI = useCategoriesAPI() + const { category, resetCategory, setCategory } = categoriesAPI const isCloud = categoryModule.isCloudCategory(category) @@ -128,7 +125,7 @@ function Drive(props: DriveProps) { }} > - + ) @@ -136,14 +133,21 @@ function Drive(props: DriveProps) { } } +/** + * Props for a {@link DriveAssetsView}. + */ +interface DriveAssetsViewProps extends DriveProps { + readonly category: Category + readonly setCategory: (categoryId: Category['id']) => void +} + /** * The assets view of the Drive. */ -function DriveAssetsView(props: DriveProps) { +function DriveAssetsView(props: DriveAssetsViewProps) { const { category, setCategory, - setCategoryId, hidden = false, initialProjectName, assetsManagementApiRef, @@ -254,7 +258,7 @@ function DriveAssetsView(props: DriveProps) {
- + {isCloud && ( { - setCategoryId('local') + setCategory('local') }} > {getText('switchToLocal')} diff --git a/app/gui/src/dashboard/pages/dashboard/Dashboard.tsx b/app/gui/src/dashboard/pages/dashboard/Dashboard.tsx index 92ad8203e076..f56c63b29c98 100644 --- a/app/gui/src/dashboard/pages/dashboard/Dashboard.tsx +++ b/app/gui/src/dashboard/pages/dashboard/Dashboard.tsx @@ -10,6 +10,8 @@ import { DashboardTabBar } from './DashboardTabBar' import * as eventCallbacks from '#/hooks/eventCallbackHooks' import * as projectHooks from '#/hooks/projectHooks' +import { CategoriesProvider } from '#/layouts/Drive/Categories/categoriesHooks' +import DriveProvider from '#/providers/DriveProvider' import * as authProvider from '#/providers/AuthProvider' import * as backendProvider from '#/providers/BackendProvider' @@ -43,7 +45,6 @@ import * as backendModule from '#/services/Backend' import * as localBackendModule from '#/services/LocalBackend' import * as projectManager from '#/services/ProjectManager' -import type { Category } from '#/layouts/CategorySwitcher/Category' import { useCategoriesAPI } from '#/layouts/Drive/Categories/categoriesHooks' import { baseName } from '#/utilities/fileInfo' import { tryFindSelfPermission } from '#/utilities/permissions' @@ -68,11 +69,17 @@ export interface DashboardProps { /** The component that contains the entire UI. */ export default function Dashboard(props: DashboardProps) { return ( - - - - - + + {/* Ideally this would be in `Drive.tsx`, but it currently must be all the way out here + * due to modals being in `TheModal`. */} + + + + + + + + ) } @@ -114,10 +121,6 @@ function DashboardInner(props: DashboardProps) { const categoriesAPI = useCategoriesAPI() - const setCategory = eventCallbacks.useEventCallback((newCategory: Category) => { - categoriesAPI.setCategory(newCategory.id) - }) - const projectsStore = useProjectsStore() const page = usePage() const launchedProjects = useLaunchedProjects() @@ -281,10 +284,6 @@ function DashboardInner(props: DashboardProps) { initialProjectName={initialProjectName} ydocUrl={ydocUrl} assetManagementApiRef={assetManagementApiRef} - category={categoriesAPI.category} - setCategory={setCategory} - setCategoryId={categoriesAPI.setCategory} - resetCategory={categoriesAPI.resetCategory} /> diff --git a/app/gui/src/dashboard/pages/dashboard/DashboardTabPanels.tsx b/app/gui/src/dashboard/pages/dashboard/DashboardTabPanels.tsx index f39d1279c667..1bfc4641b2f8 100644 --- a/app/gui/src/dashboard/pages/dashboard/DashboardTabPanels.tsx +++ b/app/gui/src/dashboard/pages/dashboard/DashboardTabPanels.tsx @@ -7,7 +7,6 @@ import { Suspense } from '#/components/Suspense' import { useEventCallback } from '#/hooks/eventCallbackHooks' import { useOpenProjectMutation, useRenameProjectMutation } from '#/hooks/projectHooks' import type { AssetManagementApi } from '#/layouts/AssetsTable' -import type { Category } from '#/layouts/CategorySwitcher/Category' import Drive from '#/layouts/Drive' import type { GraphEditorRunner } from '#/layouts/Editor' import Editor from '#/layouts/Editor' @@ -22,24 +21,11 @@ export interface DashboardTabPanelsProps { readonly initialProjectName: string | null readonly ydocUrl: string | null readonly assetManagementApiRef: React.RefObject | null - readonly category: Category - readonly setCategory: (category: Category) => void - readonly resetCategory: () => void - readonly setCategoryId: (categoryId: Category['id']) => void } /** The tab panels for the dashboard page. */ export function DashboardTabPanels(props: DashboardTabPanelsProps) { - const { - appRunner, - initialProjectName, - ydocUrl, - assetManagementApiRef, - category, - setCategory, - resetCategory, - setCategoryId, - } = props + const { appRunner, initialProjectName, ydocUrl, assetManagementApiRef } = props const page = usePage() @@ -64,10 +50,6 @@ export function DashboardTabPanels(props: DashboardTabPanelsProps) { children: (