Fix sidebar workspace row alignment
This commit is contained in:
@@ -28,6 +28,7 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
row: {
|
row: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
|
height: 20,
|
||||||
gap: 4,
|
gap: 4,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -48,9 +48,7 @@ import {
|
|||||||
ExternalLink,
|
ExternalLink,
|
||||||
FolderPlus,
|
FolderPlus,
|
||||||
GitPullRequest,
|
GitPullRequest,
|
||||||
Globe,
|
|
||||||
Settings,
|
Settings,
|
||||||
SquareTerminal,
|
|
||||||
MoreVertical,
|
MoreVertical,
|
||||||
Pencil,
|
Pencil,
|
||||||
Plus,
|
Plus,
|
||||||
@@ -150,8 +148,6 @@ const ThemedCircleAlert = withUnistyles(CircleAlert);
|
|||||||
const ThemedCircleCheck = withUnistyles(CircleCheck);
|
const ThemedCircleCheck = withUnistyles(CircleCheck);
|
||||||
const ThemedSyncedLoader = withUnistyles(SyncedLoader);
|
const ThemedSyncedLoader = withUnistyles(SyncedLoader);
|
||||||
const ThemedFolderPlus = withUnistyles(FolderPlus);
|
const ThemedFolderPlus = withUnistyles(FolderPlus);
|
||||||
const ThemedGlobe = withUnistyles(Globe);
|
|
||||||
const ThemedSquareTerminal = withUnistyles(SquareTerminal);
|
|
||||||
const ThemedMoreVertical = withUnistyles(MoreVertical);
|
const ThemedMoreVertical = withUnistyles(MoreVertical);
|
||||||
const ThemedTrash2 = withUnistyles(Trash2);
|
const ThemedTrash2 = withUnistyles(Trash2);
|
||||||
const ThemedSettings = withUnistyles(Settings);
|
const ThemedSettings = withUnistyles(Settings);
|
||||||
@@ -165,7 +161,6 @@ const foregroundMutedColorMapping = (theme: Theme) => ({
|
|||||||
});
|
});
|
||||||
const redColorMapping = (theme: Theme) => ({ color: theme.colors.palette.red[500] });
|
const redColorMapping = (theme: Theme) => ({ color: theme.colors.palette.red[500] });
|
||||||
const amberColorMapping = (theme: Theme) => ({ color: theme.colors.palette.amber[500] });
|
const amberColorMapping = (theme: Theme) => ({ color: theme.colors.palette.amber[500] });
|
||||||
const blueColorMapping = (theme: Theme) => ({ color: theme.colors.palette.blue[500] });
|
|
||||||
const greenColorMapping = (theme: Theme) => ({ color: theme.colors.palette.green[500] });
|
const greenColorMapping = (theme: Theme) => ({ color: theme.colors.palette.green[500] });
|
||||||
const purpleColorMapping = (theme: Theme) => ({ color: theme.colors.palette.purple[500] });
|
const purpleColorMapping = (theme: Theme) => ({ color: theme.colors.palette.purple[500] });
|
||||||
const syncedLoaderColorMapping = (theme: Theme) => ({
|
const syncedLoaderColorMapping = (theme: Theme) => ({
|
||||||
@@ -622,8 +617,6 @@ function WorkspaceRowRightGroup({
|
|||||||
workspace,
|
workspace,
|
||||||
isHovered,
|
isHovered,
|
||||||
isTouchPlatform,
|
isTouchPlatform,
|
||||||
showScriptsIcon,
|
|
||||||
hasRunningService,
|
|
||||||
isCreating,
|
isCreating,
|
||||||
showShortcutBadge,
|
showShortcutBadge,
|
||||||
shortcutNumber,
|
shortcutNumber,
|
||||||
@@ -640,8 +633,6 @@ function WorkspaceRowRightGroup({
|
|||||||
workspace: SidebarWorkspaceEntry;
|
workspace: SidebarWorkspaceEntry;
|
||||||
isHovered: boolean;
|
isHovered: boolean;
|
||||||
isTouchPlatform: boolean;
|
isTouchPlatform: boolean;
|
||||||
showScriptsIcon: boolean;
|
|
||||||
hasRunningService: boolean;
|
|
||||||
isCreating: boolean;
|
isCreating: boolean;
|
||||||
showShortcutBadge: boolean;
|
showShortcutBadge: boolean;
|
||||||
shortcutNumber: number | null;
|
shortcutNumber: number | null;
|
||||||
@@ -661,15 +652,6 @@ function WorkspaceRowRightGroup({
|
|||||||
const shouldRenderActionSlot = Boolean(onArchive || workspace.diffStat);
|
const shouldRenderActionSlot = Boolean(onArchive || workspace.diffStat);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{showScriptsIcon ? (
|
|
||||||
<View testID="workspace-globe-icon" accessibilityLabel="Scripts available">
|
|
||||||
{hasRunningService ? (
|
|
||||||
<ThemedGlobe size={12} uniProps={blueColorMapping} />
|
|
||||||
) : (
|
|
||||||
<ThemedSquareTerminal size={12} uniProps={blueColorMapping} />
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
) : null}
|
|
||||||
{isCreating ? <Text style={styles.workspaceCreatingText}>Creating...</Text> : null}
|
{isCreating ? <Text style={styles.workspaceCreatingText}>Creating...</Text> : null}
|
||||||
{shouldRenderActionSlot ? (
|
{shouldRenderActionSlot ? (
|
||||||
<SidebarWorkspaceTrailingActionSlot>
|
<SidebarWorkspaceTrailingActionSlot>
|
||||||
@@ -1393,6 +1375,10 @@ function WorkspaceRowInner({
|
|||||||
const hasRunningService = workspace.scripts.some(
|
const hasRunningService = workspace.scripts.some(
|
||||||
(s) => s.lifecycle === "running" && (s.type ?? "service") === "service",
|
(s) => s.lifecycle === "running" && (s.type ?? "service") === "service",
|
||||||
);
|
);
|
||||||
|
let scriptIconKind: "service" | "command" | null = null;
|
||||||
|
if (showScriptsIcon) {
|
||||||
|
scriptIconKind = hasRunningService ? "service" : "command";
|
||||||
|
}
|
||||||
const workspaceRowStyle = getProjectWorkspaceRowStyle({
|
const workspaceRowStyle = getProjectWorkspaceRowStyle({
|
||||||
isDragging,
|
isDragging,
|
||||||
selected,
|
selected,
|
||||||
@@ -1420,6 +1406,7 @@ function WorkspaceRowInner({
|
|||||||
>
|
>
|
||||||
<SidebarWorkspaceRowContent
|
<SidebarWorkspaceRowContent
|
||||||
workspace={workspace}
|
workspace={workspace}
|
||||||
|
scriptIconKind={scriptIconKind}
|
||||||
isHovered={isHovered}
|
isHovered={isHovered}
|
||||||
isLoading={isArchiving || isCreating}
|
isLoading={isArchiving || isCreating}
|
||||||
isCreating={isCreating}
|
isCreating={isCreating}
|
||||||
@@ -1430,8 +1417,6 @@ function WorkspaceRowInner({
|
|||||||
workspace={workspace}
|
workspace={workspace}
|
||||||
isHovered={isHovered}
|
isHovered={isHovered}
|
||||||
isTouchPlatform={isTouchPlatform}
|
isTouchPlatform={isTouchPlatform}
|
||||||
showScriptsIcon={showScriptsIcon}
|
|
||||||
hasRunningService={hasRunningService}
|
|
||||||
isCreating={isCreating}
|
isCreating={isCreating}
|
||||||
showShortcutBadge={showShortcutBadge}
|
showShortcutBadge={showShortcutBadge}
|
||||||
shortcutNumber={shortcutNumber}
|
shortcutNumber={shortcutNumber}
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ import {
|
|||||||
CircleDot,
|
CircleDot,
|
||||||
CircleX,
|
CircleX,
|
||||||
MoreVertical,
|
MoreVertical,
|
||||||
SquareTerminal,
|
|
||||||
Globe,
|
|
||||||
Copy,
|
Copy,
|
||||||
Archive,
|
Archive,
|
||||||
Pencil,
|
Pencil,
|
||||||
@@ -81,8 +79,6 @@ const ThemedCircleAlert = withUnistyles(CircleAlert);
|
|||||||
const ThemedCircleCheck = withUnistyles(CircleCheck);
|
const ThemedCircleCheck = withUnistyles(CircleCheck);
|
||||||
const ThemedCircleDot = withUnistyles(CircleDot);
|
const ThemedCircleDot = withUnistyles(CircleDot);
|
||||||
const ThemedCircleX = withUnistyles(CircleX);
|
const ThemedCircleX = withUnistyles(CircleX);
|
||||||
const ThemedGlobe = withUnistyles(Globe);
|
|
||||||
const ThemedSquareTerminal = withUnistyles(SquareTerminal);
|
|
||||||
const ThemedMoreVertical = withUnistyles(MoreVertical);
|
const ThemedMoreVertical = withUnistyles(MoreVertical);
|
||||||
const ThemedCopy = withUnistyles(Copy);
|
const ThemedCopy = withUnistyles(Copy);
|
||||||
const ThemedArchive = withUnistyles(Archive);
|
const ThemedArchive = withUnistyles(Archive);
|
||||||
@@ -607,6 +603,10 @@ function StatusWorkspaceRowInner({
|
|||||||
const hasRunningService = workspace.scripts.some(
|
const hasRunningService = workspace.scripts.some(
|
||||||
(s) => s.lifecycle === "running" && (s.type ?? "service") === "service",
|
(s) => s.lifecycle === "running" && (s.type ?? "service") === "service",
|
||||||
);
|
);
|
||||||
|
let scriptIconKind: "service" | "command" | null = null;
|
||||||
|
if (showScriptsIcon) {
|
||||||
|
scriptIconKind = hasRunningService ? "service" : "command";
|
||||||
|
}
|
||||||
|
|
||||||
const accessibilityState = useMemo(() => ({ selected }), [selected]);
|
const accessibilityState = useMemo(() => ({ selected }), [selected]);
|
||||||
|
|
||||||
@@ -631,38 +631,28 @@ function StatusWorkspaceRowInner({
|
|||||||
<SidebarWorkspaceRowContent
|
<SidebarWorkspaceRowContent
|
||||||
workspace={workspace}
|
workspace={workspace}
|
||||||
subtitle={projectName}
|
subtitle={projectName}
|
||||||
|
scriptIconKind={scriptIconKind}
|
||||||
isHovered={isHovered}
|
isHovered={isHovered}
|
||||||
isLoading={isArchiving}
|
isLoading={isArchiving}
|
||||||
shortcutNumber={shortcutNumber}
|
shortcutNumber={shortcutNumber}
|
||||||
showShortcutBadge={showShortcutBadge}
|
showShortcutBadge={showShortcutBadge}
|
||||||
>
|
>
|
||||||
<>
|
{shouldRenderActionSlot ? (
|
||||||
{showScriptsIcon ? (
|
<StatusWorkspaceActionSlot
|
||||||
<View accessibilityLabel="Scripts available">
|
workspace={workspace}
|
||||||
{hasRunningService ? (
|
showBase={Boolean(workspace.diffStat && !showKebabInSlot && !showShortcut)}
|
||||||
<ThemedGlobe size={12} uniProps={blueColorMapping} />
|
showOverlay={showKebabInSlot}
|
||||||
) : (
|
onCopyPath={onCopyPath}
|
||||||
<ThemedSquareTerminal size={12} uniProps={blueColorMapping} />
|
onCopyBranchName={onCopyBranchName}
|
||||||
)}
|
onRename={onRename}
|
||||||
</View>
|
onMarkAsRead={onMarkAsRead}
|
||||||
) : null}
|
onArchive={onArchive}
|
||||||
{shouldRenderActionSlot ? (
|
archiveLabel={archiveLabel}
|
||||||
<StatusWorkspaceActionSlot
|
archiveStatus={archiveStatus}
|
||||||
workspace={workspace}
|
archivePendingLabel={archivePendingLabel}
|
||||||
showBase={Boolean(workspace.diffStat && !showKebabInSlot && !showShortcut)}
|
archiveShortcutKeys={archiveShortcutKeys}
|
||||||
showOverlay={showKebabInSlot}
|
/>
|
||||||
onCopyPath={onCopyPath}
|
) : null}
|
||||||
onCopyBranchName={onCopyBranchName}
|
|
||||||
onRename={onRename}
|
|
||||||
onMarkAsRead={onMarkAsRead}
|
|
||||||
onArchive={onArchive}
|
|
||||||
archiveLabel={archiveLabel}
|
|
||||||
archiveStatus={archiveStatus}
|
|
||||||
archivePendingLabel={archivePendingLabel}
|
|
||||||
archiveShortcutKeys={archiveShortcutKeys}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
</SidebarWorkspaceRowContent>
|
</SidebarWorkspaceRowContent>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ import {
|
|||||||
Folder,
|
Folder,
|
||||||
FolderGit2,
|
FolderGit2,
|
||||||
GitPullRequest,
|
GitPullRequest,
|
||||||
|
Globe,
|
||||||
Monitor,
|
Monitor,
|
||||||
|
SquareTerminal,
|
||||||
} from "lucide-react-native";
|
} from "lucide-react-native";
|
||||||
import { GitHubIcon } from "@/components/icons/github-icon";
|
import { GitHubIcon } from "@/components/icons/github-icon";
|
||||||
import { WorkspaceHoverCard } from "@/components/workspace-hover-card";
|
import { WorkspaceHoverCard } from "@/components/workspace-hover-card";
|
||||||
@@ -42,6 +44,7 @@ const syncedLoaderColorMapping = (theme: Theme) => ({
|
|||||||
? theme.colors.palette.amber[700]
|
? theme.colors.palette.amber[700]
|
||||||
: theme.colors.palette.amber[500],
|
: theme.colors.palette.amber[500],
|
||||||
});
|
});
|
||||||
|
const blueColorMapping = (theme: Theme) => ({ color: theme.colors.palette.blue[500] });
|
||||||
const greenColorMapping = (theme: Theme) => ({ color: theme.colors.palette.green[500] });
|
const greenColorMapping = (theme: Theme) => ({ color: theme.colors.palette.green[500] });
|
||||||
const redColorMapping = (theme: Theme) => ({ color: theme.colors.palette.red[500] });
|
const redColorMapping = (theme: Theme) => ({ color: theme.colors.palette.red[500] });
|
||||||
const purpleColorMapping = (theme: Theme) => ({ color: theme.colors.palette.purple[500] });
|
const purpleColorMapping = (theme: Theme) => ({ color: theme.colors.palette.purple[500] });
|
||||||
@@ -55,6 +58,10 @@ const ThemedSyncedLoader = withUnistyles(SyncedLoader);
|
|||||||
const ThemedMonitor = withUnistyles(Monitor);
|
const ThemedMonitor = withUnistyles(Monitor);
|
||||||
const ThemedFolder = withUnistyles(Folder);
|
const ThemedFolder = withUnistyles(Folder);
|
||||||
const ThemedFolderGit2 = withUnistyles(FolderGit2);
|
const ThemedFolderGit2 = withUnistyles(FolderGit2);
|
||||||
|
const ThemedGlobe = withUnistyles(Globe);
|
||||||
|
const ThemedSquareTerminal = withUnistyles(SquareTerminal);
|
||||||
|
|
||||||
|
type SidebarWorkspaceScriptIconKind = "service" | "command";
|
||||||
|
|
||||||
export function SidebarWorkspaceRowFrame({
|
export function SidebarWorkspaceRowFrame({
|
||||||
workspace,
|
workspace,
|
||||||
@@ -86,6 +93,7 @@ export function SidebarWorkspaceRowFrame({
|
|||||||
export const SidebarWorkspaceRowContent = memo(function SidebarWorkspaceRowContent({
|
export const SidebarWorkspaceRowContent = memo(function SidebarWorkspaceRowContent({
|
||||||
workspace,
|
workspace,
|
||||||
subtitle,
|
subtitle,
|
||||||
|
scriptIconKind = null,
|
||||||
isHovered,
|
isHovered,
|
||||||
isLoading,
|
isLoading,
|
||||||
isCreating = false,
|
isCreating = false,
|
||||||
@@ -95,6 +103,7 @@ export const SidebarWorkspaceRowContent = memo(function SidebarWorkspaceRowConte
|
|||||||
}: {
|
}: {
|
||||||
workspace: SidebarWorkspaceEntry;
|
workspace: SidebarWorkspaceEntry;
|
||||||
subtitle?: string | null;
|
subtitle?: string | null;
|
||||||
|
scriptIconKind?: SidebarWorkspaceScriptIconKind | null;
|
||||||
isHovered: boolean;
|
isHovered: boolean;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
isCreating?: boolean;
|
isCreating?: boolean;
|
||||||
@@ -105,10 +114,11 @@ export const SidebarWorkspaceRowContent = memo(function SidebarWorkspaceRowConte
|
|||||||
const workspaceBranchTextStyle = useMemo(
|
const workspaceBranchTextStyle = useMemo(
|
||||||
() => [
|
() => [
|
||||||
styles.workspaceBranchText,
|
styles.workspaceBranchText,
|
||||||
|
scriptIconKind ? styles.workspaceBranchTextWithAccessory : styles.workspaceBranchTextFlexible,
|
||||||
isHovered && styles.workspaceBranchTextHovered,
|
isHovered && styles.workspaceBranchTextHovered,
|
||||||
isCreating && styles.workspaceBranchTextCreating,
|
isCreating && styles.workspaceBranchTextCreating,
|
||||||
],
|
],
|
||||||
[isHovered, isCreating],
|
[scriptIconKind, isHovered, isCreating],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -123,6 +133,7 @@ export const SidebarWorkspaceRowContent = memo(function SidebarWorkspaceRowConte
|
|||||||
<Text style={workspaceBranchTextStyle} numberOfLines={1}>
|
<Text style={workspaceBranchTextStyle} numberOfLines={1}>
|
||||||
{workspace.name}
|
{workspace.name}
|
||||||
</Text>
|
</Text>
|
||||||
|
{scriptIconKind ? <WorkspaceScriptIcon kind={scriptIconKind} /> : null}
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.workspaceRowRight}>{children}</View>
|
<View style={styles.workspaceRowRight}>{children}</View>
|
||||||
</View>
|
</View>
|
||||||
@@ -146,6 +157,22 @@ export const SidebarWorkspaceRowContent = memo(function SidebarWorkspaceRowConte
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function WorkspaceScriptIcon({ kind }: { kind: SidebarWorkspaceScriptIconKind }) {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={styles.workspaceTitleAccessory}
|
||||||
|
accessibilityLabel="Scripts available"
|
||||||
|
testID={kind === "service" ? "workspace-globe-icon" : "workspace-terminal-icon"}
|
||||||
|
>
|
||||||
|
{kind === "service" ? (
|
||||||
|
<ThemedGlobe size={12} uniProps={blueColorMapping} />
|
||||||
|
) : (
|
||||||
|
<ThemedSquareTerminal size={12} uniProps={blueColorMapping} />
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function WorkspaceStatusIndicator({
|
function WorkspaceStatusIndicator({
|
||||||
bucket,
|
bucket,
|
||||||
workspaceKind,
|
workspaceKind,
|
||||||
@@ -454,7 +481,7 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
workspaceStatusDot: {
|
workspaceStatusDot: {
|
||||||
position: "relative",
|
position: "relative",
|
||||||
width: WORKSPACE_STATUS_DOT_WIDTH,
|
width: WORKSPACE_STATUS_DOT_WIDTH,
|
||||||
height: 16,
|
height: 20,
|
||||||
borderRadius: theme.borderRadius.full,
|
borderRadius: theme.borderRadius.full,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@@ -471,9 +498,20 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
fontWeight: "400",
|
fontWeight: "400",
|
||||||
lineHeight: 20,
|
lineHeight: 20,
|
||||||
opacity: 0.76,
|
opacity: 0.76,
|
||||||
flex: 1,
|
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
},
|
},
|
||||||
|
workspaceBranchTextFlexible: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
workspaceBranchTextWithAccessory: {
|
||||||
|
flexShrink: 1,
|
||||||
|
},
|
||||||
|
workspaceTitleAccessory: {
|
||||||
|
height: 20,
|
||||||
|
flexShrink: 0,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
workspaceBranchTextCreating: {
|
workspaceBranchTextCreating: {
|
||||||
opacity: 0.92,
|
opacity: 0.92,
|
||||||
},
|
},
|
||||||
@@ -490,6 +528,7 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: theme.spacing[2],
|
gap: theme.spacing[2],
|
||||||
|
marginTop: theme.spacing[1],
|
||||||
paddingLeft: WORKSPACE_STATUS_DOT_WIDTH + theme.spacing[2],
|
paddingLeft: WORKSPACE_STATUS_DOT_WIDTH + theme.spacing[2],
|
||||||
},
|
},
|
||||||
statusDotNeedsInput: {
|
statusDotNeedsInput: {
|
||||||
|
|||||||
Reference in New Issue
Block a user