Skip to content

Commit

Permalink
Fix nav
Browse files Browse the repository at this point in the history
  • Loading branch information
MrFlashAccount committed Feb 24, 2025
1 parent b4d1ce2 commit f51c570
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 69 deletions.
4 changes: 2 additions & 2 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ export function BreadcrumbItem<IconType extends string>(props: BreadcrumbItemPro
: <Button
{...linkProps}
loading={dropMutation.isPending}
loaderPosition="icon"
onPress={onPress}
icon={iconComponent}
>
Expand Down
6 changes: 3 additions & 3 deletions app/gui/src/dashboard/components/Scroller/Scroller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Scroller is a component that
*/

import { useEventCallback } from '#/hooks/eventCallbackHooks'
import { useEventListener } from '#/hooks/eventListenerHooks'
import { useMeasureCallback } from '#/hooks/measureHooks'
import { mergeRefs } from '#/utilities/mergeRefs'
Expand All @@ -16,7 +17,6 @@ import {
type HTMLAttributes,
type PropsWithChildren,
} from 'react'
import { useEventCallback } from '../../hooks/eventCallbackHooks'
import type { TestIdProps } from '../AriaComponents'

export const SCROLLER_STYLES = tv({
Expand Down Expand Up @@ -145,8 +145,8 @@ export function Scroller(props: ScrollerProps) {

const containerRef = useRef<HTMLDivElement>(null)

const [startHidden, setStartHidden] = useState(false)
const [endHidden, setEndHidden] = useState(false)
const [startHidden, setStartHidden] = useState(true)
const [endHidden, setEndHidden] = useState(true)

const setHidden = useEventCallback((start: boolean, end: boolean) => {
startTransition(() => {
Expand Down
2 changes: 1 addition & 1 deletion app/gui/src/dashboard/components/dashboard/AssetRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ export function RealAssetInternalRow(props: RealAssetRowInternalProps) {
const { nodeMap, doCopy, doCut, doPaste } = state
const { category, rootDirectoryId, backend } = state

const [isLoading, startTransition] = useTransition()
const [, startTransition] = useTransition()

const driveStore = useDriveStore()
const { user } = useFullUserSession()
Expand Down
3 changes: 0 additions & 3 deletions app/gui/src/dashboard/layouts/AssetsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1201,9 +1201,6 @@ function AssetsTable(props: AssetsTableProps) {
isOpened={false}
backendType={backend.type}
state={state}
// Default states.
isSoleSelected={false}
selected={false}
rowState={INITIAL_ROW_STATE}
// The drag placeholder cannot be interacted with.
setSelected={noop}
Expand Down
7 changes: 6 additions & 1 deletion app/gui/src/dashboard/layouts/Drive/Categories/Category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,12 @@ export type TeamCategory = z.infer<typeof TEAM_CATEGORY_SCHEMA>
/** A category corresponding to the primary root directory for Local projects. */

const LOCAL_CATEGORY_SCHEMA = z
.object({ type: z.literal('local'), id: z.literal('local') })
.object({
type: z.literal('local'),
id: z.literal('local'),
rootPath: PATH_SCHEMA,
homeDirectoryId: DIRECTORY_ID_SCHEMA,
})
.merge(EACH_CATEGORY_SCHEMA)
.readonly()
/** A category corresponding to the primary root directory for Local projects. */
Expand Down
17 changes: 13 additions & 4 deletions app/gui/src/dashboard/layouts/Drive/Categories/categoriesHooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ export function useLocalCategoryList() {
id: 'local',
label: getText('localCategory'),
icon: ComputerIcon,
homeDirectoryId: newDirectoryId(localBackend?.rootPath() ?? Path('')),
rootPath: localBackend?.rootPath() ?? Path(''),
}

const predefinedLocalCategories: AnyLocalCategory[] = [localCategory]
Expand Down Expand Up @@ -203,10 +205,17 @@ export function useLocalCategoryList() {
(id: CategoryId) => categories.find((category) => category.id === id) ?? null,
)

const getCategoryByDirectoryId = useEventCallback(
(id: DirectoryId): AnyLocalCategory | null =>
categories.find((category) => category.id === id) ?? null,
)
const getCategoryByDirectoryId = useEventCallback((id: DirectoryId): AnyLocalCategory | null => {
return (
categories.find((category) => {
if ('homeDirectoryId' in category) {
return category.homeDirectoryId === id
}

return false
}) ?? null
)
})

const getCategoriesByType = useEventCallback(
<T extends AnyLocalCategory['type']>(type: T) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,26 @@ import { moveAssetsMutationOptions } from '#/hooks/backendBatchedHooks'
import { listDirectoryQueryOptions } from '#/hooks/backendHooks'
import { useEventCallback } from '#/hooks/eventCallbackHooks'
import { AssetPanelToggle } from '#/layouts/AssetPanel'
import { type Category } from '#/layouts/CategorySwitcher/Category'
import { useCategories, useCategoriesAPI } from '#/layouts/Drive/Categories/categoriesHooks'
import { useDirectoryIds } from '#/layouts/Drive/directoryIdsHooks'
import { useFullUserSession } from '#/providers/AuthProvider'
import { useDriveStore } from '#/providers/DriveProvider'
import { useText } from '#/providers/TextProvider'
import type Backend from '#/services/Backend'
import { isDirectoryId } from '#/services/Backend'
import { parseDirectoriesPath } from '#/services/utilities'
import { useMutation, useSuspenseQuery } from '@tanstack/react-query'
import { useState, useTransition } from 'react'
import { toast } from 'react-toastify'

/** Props for a {@link DriveBarNavigation}. */
export interface DriveBarNavigationProps {
readonly backend: Backend
readonly category: Category
}

/**
* Displays the current directory path and permissions, upload and download buttons,
* and a column display mode switcher.
*/
export function DriveBarNavigation(props: DriveBarNavigationProps) {
const { backend, category } = props

export function DriveBarNavigation() {
const { getText } = useText()
const { user } = useFullUserSession()
const { getCategoryByDirectoryId } = useCategories()
const { associatedBackend } = useCategoriesAPI()
const { associatedBackend, category } = useCategoriesAPI()
const [isTransitioning, startTransition] = useTransition()
const [navigatingKey, setNavigatingKey] = useState<React.Key | null>(null)

Expand All @@ -67,7 +57,7 @@ export function DriveBarNavigation(props: DriveBarNavigationProps) {

const { data: directoryData } = useSuspenseQuery({
...listDirectoryQueryOptions({
backend,
backend: associatedBackend,
parentId: parentDirectoryId,
category,
}),
Expand All @@ -91,7 +81,7 @@ export function DriveBarNavigation(props: DriveBarNavigationProps) {
}

return {
parentsPath: directory.parentsPath + '/' + currentDirectoryId,
parentsPath: directory.parentsPath + '/' + directory.id,
virtualParentsPath: virtualParentsPath(),
}
},
Expand All @@ -104,11 +94,11 @@ export function DriveBarNavigation(props: DriveBarNavigationProps) {
return
}

setNavigatingKey(id)
startTransition(() => {
setNavigatingKey(id)
setCurrentDirectoryId({
current: id,
// This is safe, because we know the index is present in the array.
// This is safe, because we know the index presents in the array.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
parent: parentId < 0 ? null : finalPath[parentId]!.id,
})
Expand Down Expand Up @@ -141,51 +131,63 @@ export function DriveBarNavigation(props: DriveBarNavigationProps) {
})

switch (category.type) {
case 'recent':
case 'trash': {
return null
return (
<div className="py-2">
<Button
icon={BackIcon}
aria-label={getText('back')}
isDisabled={currentDirectoryId === user.rootDirectoryId}
onPress={navigateToParent}
variant="icon"
/>
</div>
)
}
case 'recent':
return null
case 'cloud':
case 'local':
case 'user':
case 'team':
case 'local-directory': {
return (
<div className="flex w-full flex-none items-center">
<ButtonGroup
className="mr-2 w-auto flex-none"
buttonVariants={{ variant: 'icon', size: 'small' }}
>
<ButtonGroup className="mr-2 w-auto flex-none">
<Menu.Trigger trigger="longPress">
<Button
icon={BackIcon}
aria-label={getText('back')}
isDisabled={currentDirectoryId === user.rootDirectoryId}
onPress={navigateToParent}
variant="icon"
/>

<Menu items={[...finalPath].reverse()} onAction={navigateToDirectory}>
{(item) => (
<Menu.Item
key={item.id}
id={item.id}
icon={item.icon}
isDisabled={item.id === currentDirectoryId}
>
{item.label}
</Menu.Item>
)}
{(item) => {
const index = finalPath.findIndex((pathItem) => pathItem.id === item.id)
return (
<Menu.Item
key={item.id + index}
id={item.id}
icon={item.icon}
isDisabled={item.id === currentDirectoryId}
>
{item.label}
</Menu.Item>
)
}}
</Menu>
</Menu.Trigger>
</ButtonGroup>

<Scroller orientation="horizontal">
<Breadcrumbs onAction={navigateToDirectory} onDrop={onDrop}>
{finalPath.map((pathItem) => {
{finalPath.map((pathItem, index) => {
const isLoading = isTransitioning && pathItem.id === navigatingKey
return (
<Breadcrumbs.Item
key={pathItem.id}
key={pathItem.id + index}
id={pathItem.id}
icon={pathItem.icon}
isLoading={isLoading}
Expand Down
64 changes: 49 additions & 15 deletions app/gui/src/dashboard/services/LocalBackend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { APP_BASE_URL } from '#/utilities/appBaseUrl'
import { download } from '#/utilities/download'
import { tryGetMessage } from '#/utilities/error'
import { fileExtension, getFileName, getFolderPath } from '#/utilities/fileInfo'
import { getDirectoryAndName, joinPath } from '#/utilities/path'
import { getDirectoryAndName, joinPath, Path } from '#/utilities/path'
import { uniqueString } from 'enso-common/src/utilities/uniqueString'
import invariant from 'tiny-invariant'

Expand All @@ -28,20 +28,23 @@ function ipWithSocketToAddress(ipWithSocket: projectManager.IpWithSocket) {
// ======================================
// === Functions for manipulating ids ===
// ======================================
export const DIRECTORY_ID_PREFIX = `${backend.AssetType.directory}-`
export const PROJECT_ID_PREFIX = `${backend.AssetType.project}-`
export const FILE_ID_PREFIX = `${backend.AssetType.file}-`

/** Create a {@link backend.DirectoryId} from a path. */
export function newDirectoryId(path: projectManager.Path) {
return backend.DirectoryId(`${backend.AssetType.directory}-${path}` as const)
return backend.DirectoryId(`${DIRECTORY_ID_PREFIX}${path}` as const)
}

/** Create a {@link backend.ProjectId} from a UUID. */
export function newProjectId(uuid: projectManager.UUID, path: projectManager.Path) {
return backend.ProjectId(`${backend.AssetType.project}-${uuid}-${path}`)
return backend.ProjectId(`${PROJECT_ID_PREFIX}${uuid}-${path}`)
}

/** Create a {@link backend.FileId} from a path. */
export function newFileId(path: projectManager.Path) {
return backend.FileId(`${backend.AssetType.file}-${path}`)
return backend.FileId(`${FILE_ID_PREFIX}${path}`)
}

/** The internal asset type and properly typed corresponding internal ID of a directory. */
Expand Down Expand Up @@ -165,19 +168,50 @@ export default class LocalBackend extends Backend {
const entries = await this.projectManager.listDirectory(parentIdRaw)
result = entries
.map((entry) => {
console.log('entry', {
entry,
parentId,
parentIdRaw,
rootDirectory: this.projectManager.rootDirectory,
parentsPath: entry.path.replace(this.projectManager.rootDirectory, ''),
virtualParentsPath: entry.path.replace(this.projectManager.rootDirectory, ''),
})
switch (entry.type) {
case projectManager.FileSystemEntryType.DirectoryEntry: {
const id = newDirectoryId(entry.path)

const virtualParentsPath = (() => {
let path = entry.path.replace(this.projectManager.rootDirectory, '')

if (path.startsWith('/')) {
path = path.slice(1)
}

if (path.endsWith('/')) {
path = path.slice(0, -1)
}

return path
})()

const parentsPath = (() => {
const parentsPathArray: backend.DirectoryId[] = [newDirectoryId(this.rootPath())]
const splitPath = virtualParentsPath.split('/')

let previousPath = ''

for (const directory of splitPath) {
if (directory === '') {
continue
}

previousPath = Path(previousPath + '/' + directory)

if (previousPath.endsWith('/')) {
previousPath = previousPath.slice(0, -1)
}

parentsPathArray.push(newDirectoryId(Path(this.rootPath() + previousPath)))
}

return parentsPathArray.slice(0, -1).join('/')
})()

return {
id,
type: backend.AssetType.directory,
id: newDirectoryId(entry.path),
modifiedAt: entry.attributes.lastModifiedTime,
parentId,
title: getFileName(entry.path),
Expand All @@ -186,8 +220,8 @@ export default class LocalBackend extends Backend {
extension: null,
labels: [],
description: null,
parentsPath: entry.path.replace(this.projectManager.rootDirectory, ''),
virtualParentsPath: entry.path.replace(this.projectManager.rootDirectory, ''),
parentsPath,
virtualParentsPath,
} satisfies backend.DirectoryAsset
}
case projectManager.FileSystemEntryType.ProjectEntry: {
Expand Down
Loading

0 comments on commit f51c570

Please sign in to comment.