diff --git a/herdr/desktop/layouts/refactoria.json b/herdr/desktop/layouts/refactoria.json index 1ecdf78..dde3f35 100644 --- a/herdr/desktop/layouts/refactoria.json +++ b/herdr/desktop/layouts/refactoria.json @@ -14,7 +14,7 @@ "id": "brand", "type": "block", "content": { - "mod": "workspace-chrome" + "mod": "refactoria-chrome" }, "size": { "px": 46 @@ -53,7 +53,7 @@ "id": "sidebar-footer", "type": "block", "content": { - "mod": "workspace-chrome", + "mod": "refactoria-chrome", "props": { "footer": true } diff --git a/herdr/desktop/mods/refactoria-chrome/logo.png b/herdr/desktop/mods/refactoria-chrome/logo.png new file mode 100644 index 0000000..6904dd8 Binary files /dev/null and b/herdr/desktop/mods/refactoria-chrome/logo.png differ diff --git a/herdr/desktop/mods/refactoria-chrome/main.js b/herdr/desktop/mods/refactoria-chrome/main.js new file mode 100644 index 0000000..a2f590c --- /dev/null +++ b/herdr/desktop/mods/refactoria-chrome/main.js @@ -0,0 +1,54 @@ +// Clone of the shipped workspace-chrome mod: same header and footer, with the +// Refactoria beard and wordmark in place of the Herdr logo and name. +import { View, div, image, svg } from "gpui-kit"; +import { h_flex, v_flex } from "gpui-base"; +import { theme, run, props, window, shared, setShared, updates, layout } from "herdr"; + +function find(node, id) { + if (node?.id === id) return node; + for (const child of node?.children ?? []) { + const found = find(child, id); + if (found) return found; + } + return null; +} + +// The sidebar's rail goes by its width, not a flag: dragging its edge narrows it too. +const narrow = () => (find(layout(), "sidebar")?.size?.px ?? Infinity) < 160; + +// To the rail (on macOS wide enough for the traffic lights), or back to the width it had. +function toggleSidebar() { + const width = find(layout(), "sidebar")?.size?.px; + if (!narrow()) setShared("sidebar.width", width); + // Mods edited before the rail went by width still read the flag. + setShared("sidebar.collapsed", !narrow()); + run("layout.resize", { id: "sidebar", px: narrow() ? (shared("sidebar.width") ?? 268) : window()?.platform === "macos" ? 76 : 44 }); +} + +export default class RefactoriaChrome extends View { + button(id, label, action) { + const t = theme(); + return div().id(id).size(26).flex_none().flex().items_center().justify_center().rounded(6).text_color(t.muted).hover(s => s.bg(t.hover).text_color(t.foreground)) + .on_mouse_down("left", (_e, cx) => cx.stop_propagation()).on_click(action).child(label); + } + render() { + const t = theme(); + const collapsed = narrow(); + if (props()?.footer) { + const row = (id, icon, label, dim, action) => h_flex().id(id).h(28).px(8).gap(9).items_center().rounded(8) + .text_color(dim ? t.dim : t.muted).hover(s => s.bg(t.hover).text_color(t.foreground)).cursor_pointer() + .on_click(action).child(svg(`mods/workspace-chrome/${icon}.svg`).size(14)) + .when(!collapsed, el => el.child(label)); + return v_flex().size_full().bg(t.chrome).border_t(1).border_color(t.border).px(8).pt(4).pb(8).text_size(13) + .child(row("settings", "settings", "Settings", false, () => run("app.settings")) + .when(Boolean(updates().app.ready), el => el.child(div().size(6).rounded_full().bg(t.accent)))) + .child(row("machine", "plus", "Add machine", true, () => run("mod.open", { name: "machine-add" }))); + } + return h_flex().size_full().bg(t.chrome).pl(collapsed ? 6 : 14).pr(10).gap(4).items_center().text_size(13.5) + .when(window()?.platform === "macos" && !collapsed, el => el.pl(76)) + .when(!collapsed, el => el.child(h_flex().flex_1().gap(8).items_center().child(image("mods/refactoria-chrome/logo.png").size(20).rounded(5)).child(image("mods/refactoria-chrome/wordmark.png").h(16).w(108)))) + .when(!collapsed, el => el.child(this.button("search", svg("mods/workspace-chrome/search.svg").size(15), () => run("mod.open", { name: "picker" })))) + // On the macOS rail the traffic lights fill the row; the agents list's ยป unfolds it. + .when(!(collapsed && window()?.platform === "macos"), el => el.child(this.button("sidebar-toggle", svg("mods/workspace-chrome/sidebar.svg").size(15), toggleSidebar))); + } +} diff --git a/herdr/desktop/mods/refactoria-chrome/mod.json b/herdr/desktop/mods/refactoria-chrome/mod.json new file mode 100644 index 0000000..79364d5 --- /dev/null +++ b/herdr/desktop/mods/refactoria-chrome/mod.json @@ -0,0 +1,6 @@ +{ + "place": "none", + "cloned_from": { + "name": "workspace-chrome" + } +} diff --git a/herdr/desktop/mods/refactoria-chrome/wordmark.png b/herdr/desktop/mods/refactoria-chrome/wordmark.png new file mode 100644 index 0000000..4ee5054 Binary files /dev/null and b/herdr/desktop/mods/refactoria-chrome/wordmark.png differ diff --git a/install.sh b/install.sh index 7af96ad..808ccb6 100755 --- a/install.sh +++ b/install.sh @@ -36,6 +36,8 @@ MANAGED_LINKS=( "herdr/desktop/mods/refactoria-agents/mod.json|$HOME/.config/herdr-app/mods/refactoria-agents/mod.json|darwin" "herdr/desktop/mods/refactoria-prs/main.js|$HOME/.config/herdr-app/mods/refactoria-prs/main.js|darwin" "herdr/desktop/mods/refactoria-prs/mod.json|$HOME/.config/herdr-app/mods/refactoria-prs/mod.json|darwin" + "herdr/desktop/mods/refactoria-chrome/main.js|$HOME/.config/herdr-app/mods/refactoria-chrome/main.js|darwin" + "herdr/desktop/mods/refactoria-chrome/mod.json|$HOME/.config/herdr-app/mods/refactoria-chrome/mod.json|darwin" "ghostty/shaders|$HOME/.config/ghostty/shaders|all" "ghostty/profiles/barbatdev.conf|$HOME/.config/ghostty/profiles/barbatdev.conf|darwin" "ghostty/profiles/refactoria.conf|$HOME/.config/ghostty/profiles/refactoria.conf|darwin" @@ -576,6 +578,11 @@ seed_file "$DOTFILES/opencode/tui.json" "$HOME/.config/opencode/tui.json" # Herdr Desktop rewrites settings.json (theme picker, zoom keys): seed a copy. if [[ "$PLATFORM" == "Darwin" ]]; then seed_file "$DOTFILES/herdr/desktop/settings.json" "$HOME/.config/herdr-app/settings.json" + # Herdr Desktop does not load mod images through a symlink: copy them. + for image in logo.png wordmark.png; do + seed_file "$DOTFILES/herdr/desktop/mods/refactoria-chrome/$image" \ + "$HOME/.config/herdr-app/mods/refactoria-chrome/$image" + done fi # Pi owns settings.json: merge only the RefactorIA appearance keys into it. if command -v python3 &>/dev/null; then