S
diff --git a/src/components/layout/WindowControls.vue b/src/components/layout/WindowControls.vue
new file mode 100644
index 00000000..e42ff74b
--- /dev/null
+++ b/src/components/layout/WindowControls.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/composables/index.ts b/src/composables/index.ts
index 9faa9ffd..853a9a88 100644
--- a/src/composables/index.ts
+++ b/src/composables/index.ts
@@ -5,3 +5,4 @@ export { useDataGridSelection } from './useDataGridSelection'
export { useDataGridSort } from './useDataGridSort'
export { useDataStudioChatAgent } from './useDataStudioChatAgent'
export { formatSql, resolveDialect, useSqlFormatter } from './useSqlFormatter'
+export { shouldReserveMacTrafficLightInset, useWindowControls } from './useWindowControls'
diff --git a/src/composables/usePlatform.ts b/src/composables/usePlatform.ts
index b5c06d05..98fb994c 100644
--- a/src/composables/usePlatform.ts
+++ b/src/composables/usePlatform.ts
@@ -2,6 +2,7 @@ import { platform } from '@tauri-apps/plugin-os'
import { computed, ref } from 'vue'
const platformCache = ref
(null)
+const platformReady = ref(false)
async function getPlatform(): Promise {
if (platformCache.value) {
@@ -10,9 +11,12 @@ async function getPlatform(): Promise {
try {
const p = await platform()
platformCache.value = p
+ platformReady.value = true
return p
}
catch {
+ platformCache.value = 'unknown'
+ platformReady.value = true
return 'unknown'
}
}
@@ -42,6 +46,7 @@ function usePlatform() {
modifierKey,
altKey,
platform: platformCache,
+ platformReady,
}
}
diff --git a/src/composables/useWindowControls.ts b/src/composables/useWindowControls.ts
new file mode 100644
index 00000000..c9e1a7f3
--- /dev/null
+++ b/src/composables/useWindowControls.ts
@@ -0,0 +1,55 @@
+import { getCurrentWindow } from '@tauri-apps/api/window'
+import { onMounted, onUnmounted, ref } from 'vue'
+
+export function shouldReserveMacTrafficLightInset(
+ isMac: boolean,
+ isFullscreen: boolean,
+ isDesktop = true,
+): boolean {
+ return isDesktop && isMac && !isFullscreen
+}
+
+export function useWindowControls() {
+ const isMaximized = ref(false)
+ const isFullscreen = ref(false)
+
+ let unlistenResize: (() => void) | null = null
+
+ async function refreshState() {
+ try {
+ const window = getCurrentWindow()
+ const [maximized, fullscreen] = await Promise.all([
+ window.isMaximized(),
+ window.isFullscreen(),
+ ])
+ isMaximized.value = maximized
+ isFullscreen.value = fullscreen
+ }
+ catch {
+ // Not in Tauri environment — leave defaults
+ }
+ }
+
+ const minimize = () => getCurrentWindow().minimize()
+ const toggleMaximize = () => getCurrentWindow().toggleMaximize()
+ const close = () => getCurrentWindow().close()
+
+ onMounted(async () => {
+ await refreshState()
+ try {
+ const unlisten = await getCurrentWindow().onResized(() => {
+ refreshState()
+ })
+ unlistenResize = unlisten
+ }
+ catch {
+ // Not in Tauri environment
+ }
+ })
+
+ onUnmounted(() => {
+ unlistenResize?.()
+ })
+
+ return { isMaximized, isFullscreen, minimize, toggleMaximize, close }
+}