Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 0 additions & 12 deletions apps/desktop/src/lib/trpc/routers/projects/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ function extractRepoName(urlInput: string): string | null {
if (parsed.protocol === "http:" || parsed.protocol === "https:") {
// Get pathname and strip query/hash (URL constructor handles this)
const pathname = parsed.pathname;
// Get the last segment of the path
repoSegment = pathname.split("/").filter(Boolean).pop();
}
} catch {
Expand All @@ -121,20 +120,15 @@ function extractRepoName(urlInput: string): string | null {

if (!repoSegment) return null;

// Strip query string and hash if present (for edge cases)
repoSegment = repoSegment.split("?")[0].split("#")[0];

// Remove trailing .git extension
repoSegment = repoSegment.replace(/\.git$/, "");

// Decode percent-encoded characters
try {
repoSegment = decodeURIComponent(repoSegment);
} catch {
// Invalid encoding, continue with raw value
}

// Trim any remaining whitespace or special characters at boundaries
repoSegment = repoSegment.trim();

// Validate against safe filename regex
Expand Down Expand Up @@ -196,7 +190,6 @@ export const createProjectsRouter = (getWindow: () => BrowserWindow | null) => {
// If we can't get remotes, assume no origin
}

// Get all branches (local and remote)
const branchSummary = await git.branch(["-a"]);

const localBranches: string[] = [];
Expand Down Expand Up @@ -463,7 +456,6 @@ export const createProjectsRouter = (getWindow: () => BrowserWindow | null) => {
.delete(projects)
.where(eq(projects.id, existingProject.id))
.run();
// Continue to normal creation flow below
}
}

Expand Down Expand Up @@ -658,14 +650,12 @@ export const createProjectsRouter = (getWindow: () => BrowserWindow | null) => {
throw new Error("Project not found");
}

// Find all workspaces for this project
const projectWorkspaces = localDb
.select()
.from(workspaces)
.where(eq(workspaces.projectId, input.id))
.all();

// Kill all terminal processes in all workspaces of this project
let totalFailed = 0;
for (const workspace of projectWorkspaces) {
const terminalResult = await terminalManager.killByWorkspaceId(
Expand All @@ -674,10 +664,8 @@ export const createProjectsRouter = (getWindow: () => BrowserWindow | null) => {
totalFailed += terminalResult.failed;
}

// Get workspace IDs for cleanup
const closedWorkspaceIds = projectWorkspaces.map((w) => w.id);

// Remove all workspaces for this project
if (closedWorkspaceIds.length > 0) {
localDb
.delete(workspaces)
Expand Down
15 changes: 3 additions & 12 deletions apps/desktop/src/lib/trpc/routers/workspaces/utils/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,16 +564,8 @@ export async function checkBranchCheckoutSafety(
const git = simpleGit(repoPath);

try {
// Check for uncommitted changes
const status = await git.status();

// Check all forms of uncommitted changes:
// - staged: files added to index
// - modified: tracked files with unstaged changes
// - deleted: tracked files deleted but not staged
// - created: new files staged for commit
// - renamed: files renamed (staged)
// - conflicted: merge conflicts
const hasUncommittedChanges =
status.staged.length > 0 ||
status.modified.length > 0 ||
Expand All @@ -582,7 +574,6 @@ export async function checkBranchCheckoutSafety(
status.renamed.length > 0 ||
status.conflicted.length > 0;

// Untracked files that could be overwritten by checkout
const hasUntrackedFiles = status.not_added.length > 0;

if (hasUncommittedChanges) {
Expand All @@ -595,7 +586,7 @@ export async function checkBranchCheckoutSafety(
};
}

// Block on untracked files as they could be overwritten
// Block on untracked files as they could be overwritten by checkout
if (hasUntrackedFiles) {
return {
safe: false,
Expand All @@ -606,11 +597,11 @@ export async function checkBranchCheckoutSafety(
};
}

// Fetch and prune stale remote refs (best-effort)
// Fetch and prune stale remote refs (best-effort, ignore errors if offline)
try {
await git.fetch(["--prune"]);
} catch {
// Ignore fetch errors (e.g., offline) - not critical for safety
// Ignore fetch errors
}

return {
Expand Down
1 change: 0 additions & 1 deletion apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1340,7 +1340,6 @@ export const createWorkspacesRouter = () => {
throw new Error("Workspace not found");
}

// Kill all terminal processes in this workspace
const terminalResult = await terminalManager.killByWorkspaceId(
input.id,
);
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/main/lib/terminal-history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export class HistoryWriter {
this.stream?.end(() => resolve());
});
} catch {
// Ignore close errors
// Ignore
}
}
this.stream = null;
Expand Down
1 change: 0 additions & 1 deletion apps/desktop/src/renderer/lib/trpc-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ function createTrpcStorageAdapter(config: TrpcStorageConfig): StateStorage {
try {
const state = await config.get();
if (!state) return null;
// Wrap in zustand persist format
return JSON.stringify({ state, version: 0 });
} catch (error) {
console.error("[trpc-storage] Failed to get state:", error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export function TabView({ tab, panes }: TabViewProps) {

const focusedPaneId = focusedPaneIds[tab.id];

// Get valid pane IDs for this tab
const validPaneIds = new Set(getPaneIdsForTab(panes, tab.id));
const cleanedLayout = cleanLayout(tab.layout, validPaneIds);

Expand Down Expand Up @@ -73,7 +72,6 @@ export function TabView({ tab, panes }: TabViewProps) {
removePane(removedId);
}

// Update the layout
updateTabLayout(tab.id, newLayout);
},
[tab.id, tab.layout, updateTabLayout, removePane],
Expand Down
11 changes: 0 additions & 11 deletions apps/desktop/src/renderer/stores/tabs/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,22 +123,18 @@ export const useTabsStore = create<TabsStore>()(
const tabToRemove = state.tabs.find((t) => t.id === tabId);
if (!tabToRemove) return;

// Kill all terminals for panes in this tab
const paneIds = getPaneIdsForTab(state.panes, tabId);
for (const paneId of paneIds) {
killTerminalForPane(paneId);
}

// Remove all panes belonging to this tab
const newPanes = { ...state.panes };
for (const paneId of paneIds) {
delete newPanes[paneId];
}

// Remove tab
const newTabs = state.tabs.filter((t) => t.id !== tabId);

// Update active tab if needed
const workspaceId = tabToRemove.workspaceId;
const newActiveTabIds = { ...state.activeTabIds };
const newHistoryStack = (
Expand All @@ -149,7 +145,6 @@ export const useTabsStore = create<TabsStore>()(
newActiveTabIds[workspaceId] = findNextTab(state, tabId);
}

// Clean up focused pane tracking
const newFocusedPaneIds = { ...state.focusedPaneIds };
delete newFocusedPaneIds[tabId];

Expand Down Expand Up @@ -281,11 +276,9 @@ export const useTabsStore = create<TabsStore>()(
const tab = state.tabs.find((t) => t.id === tabId);
if (!tab) return;

// Get panes that should exist based on the new layout
const newPaneIds = new Set(extractPaneIdsFromLayout(layout));
const oldPaneIds = new Set(extractPaneIdsFromLayout(tab.layout));

// Find removed panes and clean them up
const removedPaneIds = Array.from(oldPaneIds).filter(
(id) => !newPaneIds.has(id),
);
Expand Down Expand Up @@ -326,7 +319,6 @@ export const useTabsStore = create<TabsStore>()(

const newPane = createPane(tabId, "terminal", options);

// Add pane to layout (append to the right)
const newLayout: MosaicNode<string> = {
direction: "row",
first: tab.layout,
Expand Down Expand Up @@ -362,18 +354,15 @@ export const useTabsStore = create<TabsStore>()(
return;
}

// Kill the terminal
killTerminalForPane(paneId);

// Remove pane from layout
const newLayout = removePaneFromLayout(tab.layout, paneId);
if (!newLayout) {
// This shouldn't happen since we checked isLastPaneInTab
get().removeTab(tab.id);
return;
}

// Remove pane from panes map
const newPanes = { ...state.panes };
delete newPanes[paneId];

Expand Down
6 changes: 0 additions & 6 deletions apps/desktop/src/renderer/stores/tabs/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ export const generateTabName = (existingTabs: Tab[]): string => {
})
.filter((n) => n > 0);

// Find the next available number
let nextNumber = 1;
while (existingNumbers.includes(nextNumber)) {
nextNumber++;
Expand Down Expand Up @@ -168,18 +167,13 @@ export const removePaneFromLayout = (
return layout === paneIdToRemove ? null : layout;
}

// Recursively remove from both branches
const newFirst = removePaneFromLayout(layout.first, paneIdToRemove);
const newSecond = removePaneFromLayout(layout.second, paneIdToRemove);

// If both branches are gone, return null
if (!newFirst && !newSecond) return null;

// If one branch is gone, return the other
if (!newFirst) return newSecond;
if (!newSecond) return newFirst;

// Both branches still exist, return updated layout
return {
...layout,
first: newFirst,
Expand Down
Loading