Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .t3-opensoftware/userdata/keybindings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[
{
"key": "mod+j",
"command": "terminal.toggle"
},
{
"key": "mod+d",
"command": "terminal.split",
"when": "terminalFocus"
},
{
"key": "mod+n",
"command": "terminal.new",
"when": "terminalFocus"
},
{
"key": "mod+w",
"command": "terminal.close",
"when": "terminalFocus"
},
{
"key": "mod+d",
"command": "diff.toggle",
"when": "!terminalFocus"
},
{
"key": "mod+n",
"command": "chat.new",
"when": "!terminalFocus"
},
{
"key": "mod+shift+o",
"command": "chat.new",
"when": "!terminalFocus"
},
{
"key": "mod+shift+n",
"command": "chat.newLocal",
"when": "!terminalFocus"
},
{
"key": "mod+o",
"command": "editor.openFavorite"
}
]
Binary file added .t3-opensoftware/userdata/state.sqlite
Binary file not shown.
Binary file added .t3-opensoftware/userdata/state.sqlite-shm
Binary file not shown.
Binary file added .t3-opensoftware/userdata/state.sqlite-wal
Binary file not shown.
2 changes: 1 addition & 1 deletion apps/desktop/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const ROOT_DIR = Path.resolve(__dirname, "../../..");
const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const APP_USER_MODEL_ID = "com.t3tools.t3code";
const USER_DATA_DIR_NAME = isDevelopment ? "t3code-dev" : "t3code";
const USER_DATA_DIR_NAME = "t3code";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
const COMMIT_HASH_DISPLAY_LENGTH = 12;
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const deriveServerPaths = Effect.fn(function* (
devUrl: ServerConfigShape["devUrl"],
): Effect.fn.Return<ServerDerivedPaths, never, Path.Path> {
const { join } = yield* Path.Path;
const stateDir = join(baseDir, devUrl !== undefined ? "dev" : "userdata");
const stateDir = join(baseDir, "userdata");
const dbPath = join(stateDir, "state.sqlite");
const attachmentsDir = join(stateDir, "attachments");
const logsDir = join(stateDir, "logs");
Expand Down
2 changes: 1 addition & 1 deletion apps/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300..800;1,9..40,300..800&display=swap"
href="https://fonts.googleapis.com/css2?family=Instrument+Serif&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap"
rel="stylesheet"
/>
<title>T3 Code (Alpha)</title>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/BranchToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export default function BranchToolbar({
if (!activeThreadId || !activeProject) return null;

return (
<div className="mx-auto flex w-full max-w-3xl items-center justify-between px-5 pb-3 pt-1">
<div className="flex items-center gap-2">
{envLocked || activeWorktreePath ? (
<span className="inline-flex items-center gap-1 border border-transparent px-[calc(--spacing(3)-1px)] text-sm font-medium text-muted-foreground/70 sm:text-xs">
{activeWorktreePath ? (
Expand Down
5 changes: 3 additions & 2 deletions apps/web/src/components/BranchToolbarBranchSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
gitStatusQueryOptions,
invalidateGitQueries,
} from "../lib/gitReactQuery";
import { cn } from "~/lib/utils";
import { readNativeApi } from "../nativeApi";
import { parsePullRequestReference } from "../pullRequestReference";
import {
Expand Down Expand Up @@ -387,7 +388,7 @@ export function BranchToolbarBranchSelector({
key={itemValue}
index={index}
value={itemValue}
className={itemValue === resolvedActiveBranch ? "bg-accent text-foreground" : undefined}
className={cn("!py-2", itemValue === resolvedActiveBranch && "bg-accent text-foreground")}
style={style}
onClick={() => selectBranch(branch)}
>
Expand Down Expand Up @@ -424,7 +425,7 @@ export function BranchToolbarBranchSelector({
<ComboboxPopup align="end" side="top" className="w-80">
<div className="border-b p-1">
<ComboboxInput
className="[&_input]:font-sans rounded-md"
className="rounded-md [&_input]:!font-sans"
inputClassName="ring-0"
placeholder="Search branches..."
showTrigger={false}
Expand Down
26 changes: 14 additions & 12 deletions apps/web/src/components/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3491,6 +3491,19 @@ export default function ChatView({ threadId }: ChatViewProps) {
onUpdateProjectScript={updateProjectScript}
onDeleteProjectScript={deleteProjectScript}
onToggleDiff={onToggleDiff}
branchToolbar={
isGitRepo ? (
<BranchToolbar
threadId={activeThread.id}
onEnvModeChange={onEnvModeChange}
envLocked={envLocked}
onComposerFocusRequest={scheduleComposerFocus}
{...(canCheckoutPullRequestIntoThread
? { onCheckoutPullRequestRequest: openPullRequestDialog }
: {})}
/>
) : null
}
/>
</header>

Expand All @@ -3509,7 +3522,7 @@ export default function ChatView({ threadId }: ChatViewProps) {
{/* Messages */}
<div
ref={setMessagesScrollContainerRef}
className="min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-y-contain px-3 py-3 sm:px-5 sm:py-4"
className="min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-y-contain px-3 py-4 sm:px-5 sm:py-5"
onScroll={onMessagesScroll}
onClickCapture={onMessagesClickCapture}
onWheel={onMessagesWheel}
Expand Down Expand Up @@ -4057,17 +4070,6 @@ export default function ChatView({ threadId }: ChatViewProps) {
</form>
</div>

{isGitRepo && (
<BranchToolbar
threadId={activeThread.id}
onEnvModeChange={onEnvModeChange}
envLocked={envLocked}
onComposerFocusRequest={scheduleComposerFocus}
{...(canCheckoutPullRequestIntoThread
? { onCheckoutPullRequestRequest: openPullRequestDialog }
: {})}
/>
)}
{pullRequestDialogState ? (
<PullRequestThreadDialog
key={pullRequestDialogState.key}
Expand Down
8 changes: 6 additions & 2 deletions apps/web/src/components/DiffPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ const DIFF_PANEL_UNSAFE_CSS = `
color: color-mix(in srgb, var(--foreground) 84%, var(--primary)) !important;
text-decoration-color: currentColor;
}

[data-separator='line-info']:first-child {
margin-block-start: 8px !important;
}
`;

type RenderablePatch =
Expand Down Expand Up @@ -402,10 +406,10 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) {
<>
<div className="relative min-w-0 flex-1 [-webkit-app-region:no-drag]">
{canScrollTurnStripLeft && (
<div className="pointer-events-none absolute inset-y-0 left-8 z-10 w-7 bg-linear-to-r from-card to-transparent" />
<div className="pointer-events-none absolute inset-y-0 left-0 z-10 w-14 bg-linear-to-r from-background from-50% to-transparent" />
)}
{canScrollTurnStripRight && (
<div className="pointer-events-none absolute inset-y-0 right-8 z-10 w-7 bg-linear-to-l from-card to-transparent" />
<div className="pointer-events-none absolute inset-y-0 right-0 z-10 w-14 bg-linear-to-l from-background from-50% to-transparent" />
)}
<button
type="button"
Expand Down
70 changes: 39 additions & 31 deletions apps/web/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ArrowLeftIcon,
ChevronRightIcon,
ChevronsDownUpIcon,
ChevronsUpDownIcon,
FolderIcon,
GitPullRequestIcon,
PlusIcon,
Expand Down Expand Up @@ -99,10 +100,13 @@ function formatRelativeTime(iso: string): string {
const diff = Date.now() - new Date(iso).getTime();
const minutes = Math.floor(diff / 60_000);
if (minutes < 1) return "just now";
if (minutes < 60) return `${minutes}m ago`;
if (minutes < 60) return `${minutes} min ago`;
const hours = Math.floor(minutes / 60);
if (hours < 24) return `${hours}h ago`;
return `${Math.floor(hours / 24)}d ago`;
if (hours < 24) return `${hours} ${hours === 1 ? "hour" : "hours"} ago`;
const days = Math.floor(hours / 24);
if (days < 30) return `${days} ${days === 1 ? "day" : "days"} ago`;
const months = Math.floor(days / 30);
return `${months} ${months === 1 ? "month" : "months"} ago`;
}

interface TerminalStatusIndicator {
Expand Down Expand Up @@ -1381,33 +1385,41 @@ export default function Sidebar() {
});
}}
>
{!project.expanded && projectStatus ? (
<span
aria-hidden="true"
title={projectStatus.label}
className={`-ml-0.5 relative inline-flex size-3.5 shrink-0 items-center justify-center ${projectStatus.colorClass}`}
>
<span className="absolute inset-0 flex items-center justify-center transition-opacity duration-150 group-hover/project-header:opacity-0">
<span
className={`size-[9px] rounded-full ${projectStatus.dotClass} ${
projectStatus.pulse ? "animate-pulse" : ""
}`}
/>
</span>
<ChevronRightIcon className="absolute inset-0 m-auto size-3.5 text-muted-foreground/70 opacity-0 transition-opacity duration-150 group-hover/project-header:opacity-100" />
</span>
) : (
<ChevronRightIcon
className={`-ml-0.5 size-3.5 shrink-0 text-muted-foreground/70 transition-transform duration-150 ${
project.expanded ? "rotate-90" : ""
}`}
/>
)}
<ProjectFavicon cwd={project.cwd} />
<span className="flex-1 truncate text-xs font-medium text-foreground/90">
{project.name}
</span>
</SidebarMenuButton>
<Tooltip>
<TooltipTrigger
render={
<SidebarMenuAction
render={
<button
type="button"
aria-label={project.expanded ? `Collapse ${project.name}` : `Expand ${project.name}`}
/>
}
showOnHover
className="top-1 right-7 size-5 rounded-md p-0 text-muted-foreground/70 hover:bg-secondary hover:text-foreground"
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
handleProjectTitleClick(event as unknown as MouseEvent<HTMLButtonElement>, project.id);
}}
>
{project.expanded ? (
<ChevronsDownUpIcon className="size-3" strokeWidth={2.5} />
) : (
<ChevronsUpDownIcon className="size-3" strokeWidth={2.5} />
)}
</SidebarMenuAction>
}
/>
<TooltipPopup side="top">
{project.expanded ? "Collapse" : "Expand"}
</TooltipPopup>
</Tooltip>
<Tooltip>
<TooltipTrigger
render={
Expand Down Expand Up @@ -1444,7 +1456,7 @@ export default function Sidebar() {
</div>

<CollapsibleContent keepMounted>
<SidebarMenuSub className="mx-1 my-0 w-full translate-x-0 gap-0.5 px-1.5 py-0">
<SidebarMenuSub className="mx-1 my-0 w-full translate-x-0 gap-0.5 px-1.5 pt-1 pb-0">
{visibleThreads.map((thread) => {
const isActive = routeThreadId === thread.id;
const isSelected = selectedThreadIds.has(thread.id);
Expand Down Expand Up @@ -1549,9 +1561,6 @@ export default function Sidebar() {
threadStatus.pulse ? "animate-pulse" : ""
}`}
/>
<span className="hidden md:inline">
{threadStatus.label}
</span>
</span>
)}
{renamingThreadId === thread.id ? (
Expand Down Expand Up @@ -1676,7 +1685,6 @@ export default function Sidebar() {
</SidebarGroup>
</SidebarContent>

<SidebarSeparator />
<SidebarFooter className="p-2">
<SidebarMenu>
<SidebarMenuItem>
Expand Down
5 changes: 4 additions & 1 deletion apps/web/src/components/chat/ChatHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
type ResolvedKeybindingsConfig,
type ThreadId,
} from "@t3tools/contracts";
import { memo } from "react";
import { memo, type ReactNode } from "react";
import GitActionsControl from "../GitActionsControl";
import { DiffIcon } from "lucide-react";
import { Badge } from "../ui/badge";
Expand Down Expand Up @@ -32,6 +32,7 @@ interface ChatHeaderProps {
onUpdateProjectScript: (scriptId: string, input: NewProjectScriptInput) => Promise<void>;
onDeleteProjectScript: (scriptId: string) => Promise<void>;
onToggleDiff: () => void;
branchToolbar?: ReactNode;
}

export const ChatHeader = memo(function ChatHeader({
Expand All @@ -52,6 +53,7 @@ export const ChatHeader = memo(function ChatHeader({
onUpdateProjectScript,
onDeleteProjectScript,
onToggleDiff,
branchToolbar,
}: ChatHeaderProps) {
return (
<div className="flex min-w-0 flex-1 items-center gap-2">
Expand All @@ -73,6 +75,7 @@ export const ChatHeader = memo(function ChatHeader({
No Git
</Badge>
)}
{branchToolbar}
</div>
<div className="@container/header-actions flex min-w-0 flex-1 items-center justify-end gap-2 @sm/header-actions:gap-3">
{activeProjectScripts && (
Expand Down
Loading