feat(desktop): always-on-top for main and detached windows

This commit is contained in:
Mo-Moore authored and GitHub committed 2026-09-22 16:30:19 +08:00
1 parent 933ed6a670
commit 78d8076c53
18 files changed
+262 -11

No files matched your search

@@ -2,7 +2,7 @@
import { computed, ref, onMounted, onBeforeUnmount, h, nextTick, watch } from "vue";
import { useI18n } from "vue-i18n";
import { invoke } from "@tauri-apps/api/core";
import { ChevronsRight, DatabaseZap, FilePlus2, Moon, Sun, SunMoon, History, Bot, ArrowLeftRight, FileCode, BookMarked, GitCompareArrows, TableProperties, Settings, CloudDownload, Package, PlugZap, FileDown, FolderTree } from "@lucide/vue";
import { ChevronsRight, DatabaseZap, FilePlus2, Moon, Sun, SunMoon, History, Bot, ArrowLeftRight, FileCode, BookMarked, GitCompareArrows, TableProperties, Settings, CloudDownload, Package, PlugZap, FileDown, FolderTree, Pin, PinOff } from "@lucide/vue";
import { Button } from "@/components/ui/button";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import LightDropdown from "@/components/ui/LightDropdown.vue";
@@ -79,7 +79,7 @@ const { toast } = useToast();
const settingsStore = useSettingsStore();
const toolbarItems = computed(() => settingsStore.editorSettings.toolbarItems);
const showToolbarUpdateEntry = computed(() => toolbarItems.value.checkUpdates || props.hasUpdateAvailable);
const { isMac, isDesktop, showControls, isMaximized, isFullscreen, minimize, toggleMaximize, close } = useWindowControls();
const { isMac, isDesktop, showControls, isMaximized, isFullscreen, isAlwaysOnTop, minimize, toggleMaximize, toggleAlwaysOnTop, close } = useWindowControls();
const updateTooltip = computed(() => {
if (props.hasUpdateAvailable && props.updateReady) return t("updates.restartRequiredTooltip");
if (props.hasUpdateAvailable && props.updateReadyToInstall) return t("updates.downloadedReady", { version: props.updateVersion ?? "" });
@@ -645,6 +645,24 @@ const toolbarStyle = computed(() => {
</Tooltip>
</template>
<Tooltip v-if="isDesktop">
<TooltipTrigger as-child>
<Button
variant="ghost"
size="icon"
class="toolbar-action-button relative h-8 w-8 shrink-0"
:class="{ 'toolbar-action-button--active bg-accent': isAlwaysOnTop }"
:aria-pressed="isAlwaysOnTop"
:aria-label="isAlwaysOnTop ? t('toolbar.alwaysOnTopOff') : t('toolbar.alwaysOnTop')"
@click="toggleAlwaysOnTop"
>
<Pin v-if="isAlwaysOnTop" class="toolbar-action-icon h-4 w-4 fill-current" />
<PinOff v-else class="toolbar-action-icon h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>{{ isAlwaysOnTop ? t("toolbar.alwaysOnTopOff") : t("toolbar.alwaysOnTop") }}</TooltipContent>
</Tooltip>
<div v-show="isRightItemVisible('exportProgress')" class="contents">
<ExportProgressPopover />
</div>
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ArrowLeft, Minus, Square, Copy, X, Grip } from "@lucide/vue";
import { ArrowLeft, Minus, Square, Copy, X, Grip, Pin, PinOff } from "@lucide/vue";
import { useI18n } from "vue-i18n";
import { useWindowControls } from "@/composables/useWindowControls";
@@ -17,7 +17,7 @@ const emit = defineEmits<{
}>();
const { t } = useI18n();
const { isMac, isMaximized, minimize, toggleMaximize } = useWindowControls();
const { isMac, isMaximized, isAlwaysOnTop, minimize, toggleMaximize, toggleAlwaysOnTop } = useWindowControls();
let dragging = false;
@@ -73,6 +73,19 @@ async function handleDragEnd(event: PointerEvent) {
<ArrowLeft class="h-3.5 w-3.5" />
<span>{{ t("tabs.returnToMainWindow") }}</span>
</button>
<button
type="button"
class="mr-1 inline-flex h-7 w-7 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground"
:class="{ 'bg-accent text-foreground': isAlwaysOnTop }"
:title="isAlwaysOnTop ? t('toolbar.alwaysOnTopOff') : t('toolbar.alwaysOnTop')"
:aria-pressed="isAlwaysOnTop"
:aria-label="isAlwaysOnTop ? t('toolbar.alwaysOnTopOff') : t('toolbar.alwaysOnTop')"
@pointerdown.stop
@click="toggleAlwaysOnTop"
>
<Pin v-if="isAlwaysOnTop" class="h-3.5 w-3.5 fill-current" />
<PinOff v-else class="h-3.5 w-3.5" />
</button>
<template v-if="!isMac">
<button type="button" class="inline-flex h-10 w-10 items-center justify-center hover:bg-foreground/10" :title="t('tabs.minimizeWindow')" @click="minimize"><Minus class="h-4 w-4" /></button>
<button type="button" class="inline-flex h-10 w-10 items-center justify-center hover:bg-foreground/10" :title="t('tabs.maximizeWindow')" @click="toggleMaximize"><Copy v-if="isMaximized" class="h-3.5 w-3.5" /><Square v-else class="h-3.5 w-3.5" /></button>