chore: releaes prep

This commit is contained in:
LukeGus
2026-05-26 22:58:00 -05:00
parent c5b9467186
commit 0a32bf518e
17 changed files with 96 additions and 19 deletions
+4
View File
@@ -292,6 +292,10 @@ networks:
<td><img src="./repo-images/Image 11.png" alt="Termix Screenshot 11" width="400" /></td>
<td><img src="./repo-images/Image 12.png" alt="Termix Screenshot 12" width="400" /></td>
</tr>
<tr>
<td><img src="./repo-images/Image 13.png" alt="Termix Screenshot 13" width="400" /></td>
<td><img src="./repo-images/Image 14.png" alt="Termix Screenshot 14" width="400" /></td>
</tr>
</table>
<sub>Some videos and images may be out of date or may not perfectly showcase features.</sub>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 409 KiB

After

Width:  |  Height:  |  Size: 794 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 567 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 372 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 449 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 113 KiB

+51 -11
View File
@@ -4,7 +4,14 @@ import { Separator } from "@/components/separator";
import { Button } from "@/components/button";
import { Sheet, SheetContent } from "@/components/sheet";
import { ChevronLeft, ChevronRight, Maximize2 } from "lucide-react";
import { useState, useRef, useCallback, useEffect, createRef } from "react";
import {
useState,
useRef,
useCallback,
useEffect,
createRef,
createPortal,
} from "react";
import { useIsMobile } from "@/hooks/use-mobile";
import { MobileBottomBar } from "@/shell/MobileBottomBar";
import { CommandPalette } from "@/shell/CommandPalette";
@@ -166,6 +173,21 @@ export function AppShell({
const terminalRefs = useRef<Map<string, ReturnType<typeof createRef>>>(
new Map(),
);
const [paneContentEls, setPaneContentEls] = useState<
(HTMLDivElement | null)[]
>(Array(6).fill(null));
const onPaneContentRef = useCallback(
(paneIndex: number, el: HTMLDivElement | null) => {
setPaneContentEls((prev) => {
if (prev[paneIndex] === el) return prev;
const next = [...prev];
next[paneIndex] = el;
return next;
});
},
[],
);
const sidebarTitle: Record<RailView, string> = {
hosts: "Hosts",
@@ -721,6 +743,7 @@ export function AppShell({
onOpenSingletonTab={openSingletonTab}
onOpenTab={openTab}
onTerminalResize={resizeAllTerminals}
onPaneContentRef={onPaneContentRef}
/>
</div>
)}
@@ -730,11 +753,34 @@ export function AppShell({
className="absolute inset-0 flex flex-col"
style={{ display: isSplit && !isMobile ? "none" : "flex" }}
>
{/* Terminal tabs: always in DOM, visibility-toggled so xterm keeps its dimensions */}
{/* Terminal tabs: always in DOM, visibility-toggled so xterm keeps its dimensions.
When split is active and this tab is assigned to a pane, portal it there. */}
{tabs
.filter((tab) => tab.type === "terminal")
.map((tab) => {
const visible = tab.id === activeTabId;
const paneIdx = isSplit ? paneTabIds.indexOf(tab.id) : -1;
const inPane = paneIdx !== -1;
const paneEl = inPane ? paneContentEls[paneIdx] : null;
const visible = inPane || tab.id === activeTabId;
const terminalContent = renderTabContent(
tab,
openSingletonTab,
openTab,
closeTab,
visible,
);
if (inPane && paneEl) {
return createPortal(
<div className="absolute inset-0 overflow-hidden">
{terminalContent}
</div>,
paneEl,
tab.id,
);
}
return (
<div
key={tab.id}
@@ -742,16 +788,10 @@ export function AppShell({
style={{
visibility: visible ? "visible" : "hidden",
pointerEvents: visible ? "auto" : "none",
zIndex: visible ? 1 : 0,
zIndex: tab.id === activeTabId && !isSplit ? 1 : 0,
}}
>
{renderTabContent(
tab,
openSingletonTab,
openTab,
closeTab,
visible,
)}
{terminalContent}
</div>
);
})}
+41 -8
View File
@@ -1,4 +1,4 @@
import React, { useState, useRef, useEffect, memo } from "react";
import React, { useState, useRef, useEffect, memo, useCallback } from "react";
import { useTranslation } from "react-i18next";
import { splitDragState, notifyDragEnd } from "@/lib/splitDragging";
import { renderTabContent, tabIcon } from "@/shell/tabUtils";
@@ -323,24 +323,39 @@ const Pane = memo(function Pane({
isDragging,
onOpenSingletonTab,
onOpenTab,
onPaneContentRef,
}: {
tab: Tab | null;
paneIndex: number;
isDragging: boolean;
onOpenSingletonTab: (type: TabType) => void;
onOpenTab: (host: Host, type: TabType) => void;
onPaneContentRef?: (paneIndex: number, el: HTMLDivElement | null) => void;
}) {
const isTerminal = tab?.type === "terminal";
const contentRef = useCallback(
(el: HTMLDivElement | null) => {
onPaneContentRef?.(paneIndex, el);
},
[paneIndex, onPaneContentRef],
);
return (
<div className="relative flex flex-col w-full h-full min-w-0 min-h-0 overflow-hidden">
<PaneHeader tab={tab} paneIndex={paneIndex} />
<div className="flex-1 min-h-0 overflow-hidden">
<div className="flex-1 min-h-0 overflow-hidden relative">
{tab ? (
<PaneContent
key={tab.id}
tab={tab}
onOpenSingletonTab={onOpenSingletonTab}
onOpenTab={onOpenTab}
/>
isTerminal ? (
// Terminal tabs are portaled in from AppShell to avoid remounting
<div ref={contentRef} className="absolute inset-0" />
) : (
<PaneContent
key={tab.id}
tab={tab}
onOpenSingletonTab={onOpenSingletonTab}
onOpenTab={onOpenTab}
/>
)
) : (
<EmptyPane />
)}
@@ -366,6 +381,7 @@ const Row = memo(function Row({
onOpenTab,
onColDivider,
onColDividerTouch,
onPaneContentRef,
}: {
rowIdx: number;
paneIndices: number[];
@@ -382,6 +398,7 @@ const Row = memo(function Row({
rowIdx: number,
colIdx: number,
) => void;
onPaneContentRef?: (paneIndex: number, el: HTMLDivElement | null) => void;
}) {
const widths = colWidths ?? [];
return (
@@ -402,6 +419,7 @@ const Row = memo(function Row({
isDragging={isDragging}
onOpenSingletonTab={onOpenSingletonTab}
onOpenTab={onOpenTab}
onPaneContentRef={onPaneContentRef}
/>
</div>
{ci < paneIndices.length - 1 && (
@@ -426,6 +444,7 @@ export const SplitView = memo(function SplitView({
onOpenSingletonTab,
onOpenTab,
onTerminalResize,
onPaneContentRef,
}: {
tabs: Tab[];
paneTabIds: (string | null)[];
@@ -433,6 +452,7 @@ export const SplitView = memo(function SplitView({
onOpenSingletonTab: (type: TabType) => void;
onOpenTab: (host: Host, type: TabType) => void;
onTerminalResize?: () => void;
onPaneContentRef?: (paneIndex: number, el: HTMLDivElement | null) => void;
}) {
const {
rowSizes,
@@ -485,6 +505,7 @@ export const SplitView = memo(function SplitView({
onOpenTab={onOpenTab}
onColDivider={onColDivider}
onColDividerTouch={onColDividerTouch}
onPaneContentRef={onPaneContentRef}
/>
)}
@@ -500,6 +521,7 @@ export const SplitView = memo(function SplitView({
isDragging={isDragging}
onOpenSingletonTab={onOpenSingletonTab}
onOpenTab={onOpenTab}
onPaneContentRef={onPaneContentRef}
/>
</div>
<ColDivider
@@ -517,6 +539,7 @@ export const SplitView = memo(function SplitView({
isDragging={isDragging}
onOpenSingletonTab={onOpenSingletonTab}
onOpenTab={onOpenTab}
onPaneContentRef={onPaneContentRef}
/>
</div>
<RowDivider
@@ -533,6 +556,7 @@ export const SplitView = memo(function SplitView({
isDragging={isDragging}
onOpenSingletonTab={onOpenSingletonTab}
onOpenTab={onOpenTab}
onPaneContentRef={onPaneContentRef}
/>
</div>
</div>
@@ -555,6 +579,7 @@ export const SplitView = memo(function SplitView({
isDragging={isDragging}
onOpenSingletonTab={onOpenSingletonTab}
onOpenTab={onOpenTab}
onPaneContentRef={onPaneContentRef}
/>
</div>
<ColDivider
@@ -568,6 +593,7 @@ export const SplitView = memo(function SplitView({
isDragging={isDragging}
onOpenSingletonTab={onOpenSingletonTab}
onOpenTab={onOpenTab}
onPaneContentRef={onPaneContentRef}
/>
</div>
</div>
@@ -582,6 +608,7 @@ export const SplitView = memo(function SplitView({
isDragging={isDragging}
onOpenSingletonTab={onOpenSingletonTab}
onOpenTab={onOpenTab}
onPaneContentRef={onPaneContentRef}
/>
</div>
</div>
@@ -601,6 +628,7 @@ export const SplitView = memo(function SplitView({
onOpenTab={onOpenTab}
onColDivider={onColDivider}
onColDividerTouch={onColDividerTouch}
onPaneContentRef={onPaneContentRef}
/>
<RowDivider
onMouseDown={(e) => onRowDivider(e, 0)}
@@ -618,6 +646,7 @@ export const SplitView = memo(function SplitView({
onOpenTab={onOpenTab}
onColDivider={onColDivider}
onColDividerTouch={onColDividerTouch}
onPaneContentRef={onPaneContentRef}
/>
</div>
)}
@@ -636,6 +665,7 @@ export const SplitView = memo(function SplitView({
onOpenTab={onOpenTab}
onColDivider={onColDivider}
onColDividerTouch={onColDividerTouch}
onPaneContentRef={onPaneContentRef}
/>
<RowDivider
onMouseDown={(e) => onRowDivider(e, 0)}
@@ -653,6 +683,7 @@ export const SplitView = memo(function SplitView({
onOpenTab={onOpenTab}
onColDivider={onColDivider}
onColDividerTouch={onColDividerTouch}
onPaneContentRef={onPaneContentRef}
/>
</div>
)}
@@ -671,6 +702,7 @@ export const SplitView = memo(function SplitView({
onOpenTab={onOpenTab}
onColDivider={onColDivider}
onColDividerTouch={onColDividerTouch}
onPaneContentRef={onPaneContentRef}
/>
<RowDivider
onMouseDown={(e) => onRowDivider(e, 0)}
@@ -688,6 +720,7 @@ export const SplitView = memo(function SplitView({
onOpenTab={onOpenTab}
onColDivider={onColDivider}
onColDividerTouch={onColDividerTouch}
onPaneContentRef={onPaneContentRef}
/>
</div>
)}