mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 04:15:30 +00:00
Merge 0173774f2a into c3fae1aaab
This commit is contained in:
commit
3ce53b60d6
4 changed files with 74 additions and 3 deletions
|
|
@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
<!-- @NOTE: On next release, please bump the MCP pacakge as there are breaking changes in this! -->
|
<!-- @NOTE: On next release, please bump the MCP pacakge as there are breaking changes in this! -->
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Implement dynamic tab titles for files and folders in browse tab. [#560](https://github.com/sourcebot-dev/sourcebot/pull/560)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed "dubious ownership" errors when cloning / fetching repos. [#553](https://github.com/sourcebot-dev/sourcebot/pull/553)
|
- Fixed "dubious ownership" errors when cloning / fetching repos. [#553](https://github.com/sourcebot-dev/sourcebot/pull/553)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,67 @@ import { getBrowseParamsFromPathParam } from "../hooks/utils";
|
||||||
import { CodePreviewPanel } from "./components/codePreviewPanel";
|
import { CodePreviewPanel } from "./components/codePreviewPanel";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { TreePreviewPanel } from "./components/treePreviewPanel";
|
import { TreePreviewPanel } from "./components/treePreviewPanel";
|
||||||
|
import { Metadata } from "next";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the URL path to generate a descriptive title.
|
||||||
|
* It handles three cases:
|
||||||
|
* 1. File view (`blob`): "filename.ts - owner/repo"
|
||||||
|
* 2. Directory view (`tree`): "directory/ - owner/repo"
|
||||||
|
* 3. Repository root: "owner/repo"
|
||||||
|
*
|
||||||
|
* @param path The array of path segments from Next.js params.
|
||||||
|
* @returns A formatted title string.
|
||||||
|
*/
|
||||||
|
export const parsePathForTitle = (path: string[]): string => {
|
||||||
|
const pathParam = path.join('/');
|
||||||
|
|
||||||
|
const { repoName, revisionName, path: filePath, pathType } = getBrowseParamsFromPathParam(pathParam);
|
||||||
|
|
||||||
|
// Build the base repository and revision string.
|
||||||
|
const cleanRepoName = repoName.split('/').slice(1).join('/'); // Remove the version control system prefix
|
||||||
|
const repoAndRevision = `${cleanRepoName}${revisionName ? ` @ ${revisionName}` : ''}`;
|
||||||
|
|
||||||
|
switch (pathType) {
|
||||||
|
case 'blob': {
|
||||||
|
// For blobs, get the filename from the end of the path.
|
||||||
|
const fileName = filePath.split('/').pop() || filePath;
|
||||||
|
return `${fileName} - ${repoAndRevision}`;
|
||||||
|
}
|
||||||
|
case 'tree': {
|
||||||
|
// If the path is empty, it's the repo root.
|
||||||
|
if (filePath === '' || filePath === '/') {
|
||||||
|
return repoAndRevision;
|
||||||
|
}
|
||||||
|
// Otherwise, show the directory path.
|
||||||
|
const directoryPath = filePath.endsWith('/') ? filePath : `${filePath}/`;
|
||||||
|
return `${directoryPath} - ${repoAndRevision}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
params: Promise<{
|
||||||
|
domain: string;
|
||||||
|
path: string[];
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function generateMetadata({ params: paramsPromise }: Props): Promise<Metadata> {
|
||||||
|
let title = 'Browse'; // Default Fallback
|
||||||
|
|
||||||
|
try {
|
||||||
|
const params = await paramsPromise;
|
||||||
|
title = parsePathForTitle(params.path);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to generate metadata title from path:", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
interface BrowsePageProps {
|
interface BrowsePageProps {
|
||||||
params: Promise<{
|
params: Promise<{
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,15 @@ import { PlanProvider } from "@/features/entitlements/planProvider";
|
||||||
import { getEntitlements } from "@sourcebot/shared";
|
import { getEntitlements } from "@sourcebot/shared";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Sourcebot",
|
// Using the title.template will allow child pages to set the title
|
||||||
description: "Sourcebot is a self-hosted code understanding tool. Ask questions about your codebase and get rich Markdown answers with inline citations.",
|
// while keeping a consistent suffix.
|
||||||
manifest: "/manifest.json",
|
title: {
|
||||||
|
default: "Sourcebot",
|
||||||
|
template: "%s | Sourcebot",
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
"Sourcebot is a self-hosted code understanding tool. Ask questions about your codebase and get rich Markdown answers with inline citations.",
|
||||||
|
manifest: "/manifest.json",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import { ErrorCode } from "./errorCodes";
|
||||||
import { NextRequest } from "next/server";
|
import { NextRequest } from "next/server";
|
||||||
import { Org } from "@sourcebot/db";
|
import { Org } from "@sourcebot/db";
|
||||||
import { OrgMetadata, orgMetadataSchema } from "@/types";
|
import { OrgMetadata, orgMetadataSchema } from "@/types";
|
||||||
|
import { getBrowseParamsFromPathParam } from "@/app/[domain]/browse/hooks/utils";
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs))
|
return twMerge(clsx(inputs))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue