From 47dd6367ee39f87e45986c516fe0bca7e864702b Mon Sep 17 00:00:00 2001 From: wasimysaid Date: Sat, 25 Apr 2026 04:40:21 +0200 Subject: [PATCH 1/7] fix(tauri): dedupe tray and brand nsis installer --- studio/src-tauri/tauri.conf.json | 22 ++++++++++++++++------ studio/src-tauri/tauri.windows.conf.json | 6 ------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/studio/src-tauri/tauri.conf.json b/studio/src-tauri/tauri.conf.json index 49819f8a25..705cf0ea94 100644 --- a/studio/src-tauri/tauri.conf.json +++ b/studio/src-tauri/tauri.conf.json @@ -21,12 +21,7 @@ "visible": false, "resizable": false } - ], - "trayIcon": { - "iconPath": "icons/icon.png", - "id": "main", - "tooltip": "Unsloth Studio (Desktop)" - } + ] }, "plugins": { "updater": { @@ -42,6 +37,10 @@ "bundle": { "active": true, "createUpdaterArtifacts": true, + "publisher": "Unsloth AI", + "homepage": "https://unsloth.ai/", + "copyright": "© 2026 Unsloth AI. All rights reserved.", + "license": "AGPL-3.0-only", "targets": ["app", "appimage", "deb", "dmg", "nsis"], "resources": { "../../install.sh": "install.sh", @@ -54,6 +53,17 @@ "icons/icon.ico", "icons/icon.icns" ], + "windows": { + "nsis": { + "installerHooks": "./windows/hooks.nsh", + "installerIcon": "./icons/icon.ico", + "headerImage": "./windows/branding/nsis-header.bmp", + "sidebarImage": "./windows/branding/nsis-sidebar.bmp", + "installMode": "currentUser", + "languages": ["English"], + "displayLanguageSelector": false + } + }, "linux": { "deb": { "postRemoveScript": "./linux/postremove.sh" diff --git a/studio/src-tauri/tauri.windows.conf.json b/studio/src-tauri/tauri.windows.conf.json index a68cf6351f..83f685cda4 100644 --- a/studio/src-tauri/tauri.windows.conf.json +++ b/studio/src-tauri/tauri.windows.conf.json @@ -4,12 +4,6 @@ "signCommand": { "cmd": "trusted-signing-cli", "args": ["-e", "https://eus.codesigning.azure.net", "-d", "Unsloth Studio (Desktop)", "%1"] - }, - "nsis": { - "installerHooks": "./windows/hooks.nsh", - "installerIcon": "./icons/icon.ico", - "headerImage": "./windows/branding/nsis-header.bmp", - "sidebarImage": "./windows/branding/nsis-sidebar.bmp" } } } From 1729454db0306143082d8257998a57aa1637e602 Mon Sep 17 00:00:00 2001 From: wasimysaid Date: Sat, 25 Apr 2026 05:51:36 +0200 Subject: [PATCH 2/7] feat(tauri): add linux windows custom titlebar --- studio/frontend/src/app/provider.tsx | 35 +- studio/frontend/src/app/routes/__root.tsx | 2 +- .../src/components/tauri/startup-screen.tsx | 2 +- .../src/components/tauri/update-screen.tsx | 2 +- .../src/components/tauri/window-titlebar.tsx | 329 ++++++++++++++++++ .../features/auth/change-password-page.tsx | 2 +- .../frontend/src/features/auth/login-page.tsx | 2 +- .../data-recipes/pages/data-recipes-page.tsx | 2 +- .../data-recipes/pages/edit-recipe-page.tsx | 2 +- .../src/features/export/export-page.tsx | 2 +- .../onboarding/components/wizard-layout.tsx | 2 +- .../recipe-studio/recipe-studio-page.tsx | 2 +- .../src/features/studio/studio-page.tsx | 2 +- studio/src-tauri/capabilities/default.json | 5 + studio/src-tauri/src/main.rs | 11 + 15 files changed, 389 insertions(+), 13 deletions(-) create mode 100644 studio/frontend/src/components/tauri/window-titlebar.tsx diff --git a/studio/frontend/src/app/provider.tsx b/studio/frontend/src/app/provider.tsx index b75998a169..92783ee2be 100644 --- a/studio/frontend/src/app/provider.tsx +++ b/studio/frontend/src/app/provider.tsx @@ -4,10 +4,15 @@ import { StartupScreen } from "@/components/tauri/startup-screen"; import { UpdateBanner } from "@/components/tauri/update-banner"; import { UpdateScreen } from "@/components/tauri/update-screen"; +import { + WindowTitlebar, + shouldUseCustomWindowTitlebar, +} from "@/components/tauri/window-titlebar"; import { Toaster } from "@/components/ui/sonner"; import { useTauriBackend } from "@/hooks/use-tauri-backend"; import { useTauriUpdate } from "@/hooks/use-tauri-update"; import { isTauri } from "@/lib/api-base"; +import { useRouterState } from "@tanstack/react-router"; import { ThemeProvider } from "next-themes"; import { useEffect, useRef, type ReactNode } from "react"; @@ -119,7 +124,15 @@ function TauriUpdateLayer({ isExternalServer }: { isExternalServer: boolean }) { ); } +const HIDDEN_TITLEBAR_SIDEBAR_ROUTES = new Set([ + "/onboarding", + "/login", + "/change-password", + "/signup", +]); + function TauriWrapper({ children }: { children: ReactNode }) { + const pathname = useRouterState({ select: (s) => s.location.pathname }); const { status, logs, error, isExternalServer, currentStepIndex, progressDetail, elevationPackages, @@ -151,9 +164,13 @@ function TauriWrapper({ children }: { children: ReactNode }) { }, [status]); if (!isTauri) return <>{children}; - if (status === "running") return <>{children}; - return ( + const content = status === "running" ? ( + <> + + {children} + + ) : ( ); + + if (!shouldUseCustomWindowTitlebar()) return content; + + const showSidebarSurface = + status === "running" && !HIDDEN_TITLEBAR_SIDEBAR_ROUTES.has(pathname); + + return ( +
+ +
+ {content} +
+
+ ); } export function AppProvider({ children }: AppProviderProps) { diff --git a/studio/frontend/src/app/routes/__root.tsx b/studio/frontend/src/app/routes/__root.tsx index 19b5763557..22d149473c 100644 --- a/studio/frontend/src/app/routes/__root.tsx +++ b/studio/frontend/src/app/routes/__root.tsx @@ -81,7 +81,7 @@ function RootLayout() { pinned={pinned} setPinned={setPinned} togglePinned={togglePinned} - className="!min-h-0 h-dvh overflow-hidden" + className="!min-h-0 h-[calc(100dvh-var(--studio-titlebar-height,0px))] overflow-hidden" > diff --git a/studio/frontend/src/components/tauri/startup-screen.tsx b/studio/frontend/src/components/tauri/startup-screen.tsx index af5f241416..2b8a204afe 100644 --- a/studio/frontend/src/components/tauri/startup-screen.tsx +++ b/studio/frontend/src/components/tauri/startup-screen.tsx @@ -381,7 +381,7 @@ export function StartupScreen({ } return ( -
+
+
platform.includes(token)); +} + +async function getAppWindow(): Promise { + const { getCurrentWindow } = await import("@tauri-apps/api/window"); + return getCurrentWindow(); +} + +function WindowControlButton({ + label, + className, + onClick, + children, +}: { + label: string; + className?: string; + onClick: () => void; + children: ReactNode; +}): ReactElement { + return ( + + ); +} + +function MinimizeGlyph(): ReactElement { + return ( +