diff --git a/ee/tabby-ui/app/files/components/source-code-browser.tsx b/ee/tabby-ui/app/files/components/source-code-browser.tsx index 5376c67e3147..680930a83dce 100644 --- a/ee/tabby-ui/app/files/components/source-code-browser.tsx +++ b/ee/tabby-ui/app/files/components/source-code-browser.tsx @@ -25,7 +25,7 @@ import { FileTreePanel } from './file-tree-panel' import { RawFileView } from './raw-file-view' import { TextFileView } from './text-file-view' import { - getDirectoriesFromPath, + getDirectoriesFromBasename, resolveBasenameFromPath, resolveFileNameFromPath, resolveRepoNameFromPath @@ -261,7 +261,7 @@ const SourceCodeBrowserRenderer: React.FC = ({ React.useEffect(() => { const init = async () => { - const { patchMap, expandedKeys } = await initFileMap(activePath) + const { patchMap, expandedKeys } = await getInitialFileMap(activePath) if (patchMap) { updateFileMap(patchMap) } @@ -289,7 +289,7 @@ const SourceCodeBrowserRenderer: React.FC = ({ } } updateFileMap(patchMap) - const expandedKeysToAdd = getDirectoriesFromPath(activePath, true) + const expandedKeysToAdd = getDirectoriesFromBasename(activePath, true) if (expandedKeysToAdd?.length) { setExpandedKeys(keys => { const newSet = new Set(keys) @@ -364,13 +364,14 @@ const SourceCodeBrowser: React.FC = props => { ) } -async function initFileMap(path?: string) { - const defaultRepositoryName = resolveRepoNameFromPath(path) - const defaultBasename = resolveBasenameFromPath(path) +async function getInitialFileMap(path?: string) { + const initialRepositoryName = resolveRepoNameFromPath(path) + const initialBasename = resolveBasenameFromPath(path) try { - const repos = await fetchRepositories() - const { defaultEntries, expandedDir } = await initDefaultEntries(repos) + const repos = await fetchAllRepositories() + const initialEntries = await getInitialEntries(repos) + const initialExpandedDirs = getDirectoriesFromBasename(initialBasename) const patchMap: TFileMap = {} for (const repo of repos) { @@ -378,20 +379,20 @@ async function initFileMap(path?: string) { file: repo, name: repo.basename, fullPath: repo.basename, - treeExpanded: repo.basename === defaultRepositoryName + treeExpanded: repo.basename === initialRepositoryName } } - for (const entry of defaultEntries) { - const path = `${defaultRepositoryName}/${entry.basename}` + for (const entry of initialEntries) { + const path = `${initialRepositoryName}/${entry.basename}` patchMap[path] = { file: entry, name: resolveFileNameFromPath(path), fullPath: path, - treeExpanded: expandedDir.includes(entry.basename) + treeExpanded: initialExpandedDirs.includes(entry.basename) } } - const expandedKeys = expandedDir.map(dir => - [defaultRepositoryName, dir].filter(Boolean).join('/') + const expandedKeys = initialExpandedDirs.map(dir => + [initialRepositoryName, dir].filter(Boolean).join('/') ) return { patchMap, expandedKeys } @@ -400,7 +401,7 @@ async function initFileMap(path?: string) { return {} } - async function fetchRepositories(): Promise { + async function fetchAllRepositories(): Promise { try { const repos: ResolveEntriesResponse = await fetcher( '/repositories/resolve/' @@ -411,54 +412,28 @@ async function initFileMap(path?: string) { } } - async function fetchDefaultEntries(data?: TFile[]) { + async function fetchInitialEntries(data?: TFile[]) { try { - // if (!accessToken) return undefined - - if (!defaultRepositoryName) return undefined + if (!initialRepositoryName) return undefined // match default repository const repositoryIdx = findIndex( data, - entry => entry.basename === defaultRepositoryName + entry => entry.basename === initialRepositoryName ) if (repositoryIdx < 0) return undefined - const directoryPaths = getDirectoriesFromPath(defaultBasename) - // fetch default directories - const requests: Array<() => Promise> = - directoryPaths.map(path => () => { - return fetcher( - `/repositories/${defaultRepositoryName}/resolve/${path}` - ) - }) - const entries = await Promise.all(requests.map(fn => fn())) - let result: TFile[] = [] - for (let entry of entries) { - if (entry?.entries?.length) { - result = [...result, ...entry.entries] - } - } - return result + return fetchEntriesFromPath(path) } catch (e) { console.error(e) } } - async function initDefaultEntries(data?: TFile[]) { - let result: { defaultEntries: TFile[]; expandedDir: string[] } = { - defaultEntries: [], - expandedDir: [] - } + async function getInitialEntries(data?: TFile[]) { + let result: TFile[] = [] try { - if (defaultRepositoryName && data?.length) { - const defaultEntries = await fetchDefaultEntries(data) - const expandedDir = getDirectoriesFromPath(defaultBasename) - if (defaultEntries?.length) { - result.defaultEntries = defaultEntries - } - if (expandedDir?.length) { - result.expandedDir = expandedDir - } + if (initialRepositoryName && data?.length) { + const defaultEntries = await fetchInitialEntries(data) + result = defaultEntries ?? [] } } catch (e) { console.error(e) @@ -467,19 +442,25 @@ async function initFileMap(path?: string) { } } -async function getFileViewType( - path: string, - blob: Blob | undefined -): Promise { - if (!blob) return '' - const mimeType = blob?.type - const detectedLanguage = filename2prism(path)?.[0] - - if (mimeType?.startsWith('image')) return 'image' - if (detectedLanguage || mimeType?.startsWith('text')) return 'text' - - const isReadableText = await isReadableTextFile(blob) - return isReadableText ? 'text' : 'raw' +async function fetchEntriesFromPath(path: string | undefined) { + if (!path) return [] + const repoName = resolveRepoNameFromPath(path) + const basename = resolveBasenameFromPath(path) + // array of dir basename that do not include the repo name. + const directoryPaths = getDirectoriesFromBasename(basename) + // fetch all dirs from path + const requests: Array<() => Promise> = + directoryPaths.map( + dir => () => fetcher(`/repositories/${repoName}/resolve/${dir}`).catch(e => []) + ) + const entries = await Promise.all(requests.map(fn => fn())) + let result: TFile[] = [] + for (let entry of entries) { + if (entry?.entries?.length) { + result = [...result, ...entry.entries] + } + } + return result } function isReadableTextFile(blob: Blob) { @@ -510,6 +491,21 @@ function isReadableTextFile(blob: Blob) { }) } +async function getFileViewType( + path: string, + blob: Blob | undefined +): Promise { + if (!blob) return '' + const mimeType = blob?.type + const detectedLanguage = filename2prism(path)?.[0] + + if (mimeType?.startsWith('image')) return 'image' + if (detectedLanguage || mimeType?.startsWith('text')) return 'text' + + const isReadableText = await isReadableTextFile(blob) + return isReadableText ? 'text' : 'raw' +} + export type { TFileMap, TFileMapItem } export { SourceCodeBrowserContext, SourceCodeBrowser, getFileViewType } diff --git a/ee/tabby-ui/app/files/components/utils.ts b/ee/tabby-ui/app/files/components/utils.ts index 3c045df162a9..971751d1064e 100644 --- a/ee/tabby-ui/app/files/components/utils.ts +++ b/ee/tabby-ui/app/files/components/utils.ts @@ -16,7 +16,7 @@ function resolveFileNameFromPath(path: string) { return pathSegments[pathSegments.length - 1] } -function getDirectoriesFromPath(path: string, isDir?: boolean): string[] { +function getDirectoriesFromBasename(path: string, isDir?: boolean): string[] { if (isNil(path)) return [] let result = [''] @@ -33,5 +33,5 @@ export { resolveRepoNameFromPath, resolveBasenameFromPath, resolveFileNameFromPath, - getDirectoriesFromPath + getDirectoriesFromBasename }