Skip to content

Commit 7abc3e6

Browse files
committed
perf: update linux ui
1 parent 4a14e5c commit 7abc3e6

7 files changed

Lines changed: 100 additions & 25 deletions

File tree

src-tauri/src/setup/menu.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,14 @@ pub fn open_settings_window<R: Runtime>(app: &tauri::AppHandle<R>) {
186186

187187
match builder.build() {
188188
Ok(_win) => {
189-
#[cfg(target_os = "windows")]
189+
#[cfg(any(target_os = "windows", target_os = "linux"))]
190190
{
191-
// Windows 下禁用原生装饰(标题栏/菜单栏),与主窗口保持一致
191+
// Windows / Linux 下禁用原生装饰,与主窗口保持一致
192192
if let Err(e) = _win.set_decorations(false) {
193193
warn!("Failed to disable decorations for settings window: {}", e);
194194
}
195+
196+
#[cfg(target_os = "windows")]
195197
if let Err(e) = _win.set_shadow(false) {
196198
warn!("Failed to disable shadow for settings window: {}", e);
197199
}

src-tauri/src/setup/window_effects.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ pub fn apply_windows_blur(_win: &WebviewWindow) -> Result<(), Box<dyn std::error
4141
Ok(())
4242
}
4343

44-
/// 为 Linux 窗口保留原生标题栏,使用桌面环境自己的窗口按钮
44+
/// 为 Linux 窗口隐藏原生标题栏,使用应用内自定义按钮
4545
#[cfg(target_os = "linux")]
4646
pub fn apply_linux_window(win: &WebviewWindow) -> Result<(), Box<dyn std::error::Error>> {
47-
info!("Keeping Linux native window decorations enabled");
48-
if let Err(e) = win.set_decorations(true) {
49-
error!("Failed to enable Linux window decorations: {}", e);
47+
info!("Disabling Linux window decorations for custom header");
48+
if let Err(e) = win.set_decorations(false) {
49+
error!("Failed to disable Linux window decorations: {}", e);
5050
}
5151
Ok(())
5252
}

ui/components/Header/ActionButtons.vue

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { ActionItem } from "~/types/index";
55
import { LogicalPosition } from "@tauri-apps/api/dpi";
66
77
const { t, locale } = useI18n();
8-
const { isWindows } = usePlatform();
8+
const { isLinux, isMacOS } = usePlatform();
99
const { layouts, sort, setSort, setLayouts } = useSettingManager();
1010
1111
const localePath = useLocalePath();
@@ -17,6 +17,8 @@ const commonButtonProps = {
1717
color: "neutral" as const
1818
};
1919
20+
const showCustomWindowControls = computed(() => !isMacOS.value);
21+
2022
// 窗口控制按钮配置
2123
const windowControlButtons = computed(() => {
2224
// Windows 下显示窗口控制按钮
@@ -50,15 +52,20 @@ const windowControlButtons = computed(() => {
5052
5153
// 获取窗口控制按钮的样式类
5254
const getWindowControlButtonClass = (buttonKey: string) => {
53-
const baseClass = "rounded-none w-12 h-13 p-1 flex items-center justify-center";
55+
const isLinuxStyle = isLinux.value;
56+
const baseClass = isLinuxStyle
57+
? "h-9 w-9 rounded-full p-1 flex items-center justify-center transition-colors"
58+
: "rounded-none w-12 h-13 p-1 flex items-center justify-center";
5459
5560
switch (buttonKey) {
5661
case "minimize":
57-
return `${baseClass} `;
62+
return isLinuxStyle ? `${baseClass} hover:bg-black/6 dark:hover:bg-white/10` : `${baseClass} `;
5863
case "maximize":
59-
return `${baseClass} `;
64+
return isLinuxStyle ? `${baseClass} hover:bg-black/6 dark:hover:bg-white/10` : `${baseClass} `;
6065
case "close":
61-
return `${baseClass} hover:bg-red-500 hover:text-white active:bg-red-600`;
66+
return isLinuxStyle
67+
? `${baseClass} hover:bg-red-500/12 hover:text-red-600 dark:hover:bg-red-500/18 dark:hover:text-red-300`
68+
: `${baseClass} hover:bg-red-500 hover:text-white active:bg-red-600`;
6269
default:
6370
return baseClass;
6471
}
@@ -195,7 +202,7 @@ const actionItems = computed<ActionItem[]>(() => [
195202
196203
// 直接创建窗口
197204
198-
const useNativeWindowFrame = !isWindows.value;
205+
const useNativeWindowFrame = isMacOS.value;
199206
new useTauriWebviewWindowWebviewWindow(label, {
200207
title: t("Common.ConnectionSettings"),
201208
url: localePath({ path: "/setting" }),
@@ -242,7 +249,7 @@ const actionItems = computed<ActionItem[]>(() => [
242249
</div>
243250

244251
<!-- 窗口控制按钮 -->
245-
<div v-if="isWindows" class="flex items-center">
252+
<div v-if="showCustomWindowControls" class="flex items-center" :class="isLinux ? 'gap-1.5' : ''">
246253
<template v-for="button of windowControlButtons" :key="button.key">
247254
<UButton
248255
size="sm"

ui/components/SideBar/profile.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const userInfoStore = useUserInfoStore();
3030
3131
const { t, locales, locale } = useI18n();
3232
const { loggedIn, currentSite, userMap, currentUser } = storeToRefs(userInfoStore);
33-
const { isWindows } = usePlatform();
33+
const { isMacOS } = usePlatform();
3434
3535
const {
3636
setLang,
@@ -294,7 +294,7 @@ async function openToolWindow(
294294
return;
295295
}
296296
297-
const useNativeWindowFrame = !isWindows.value;
297+
const useNativeWindowFrame = isMacOS.value;
298298
299299
// eslint-disable-next-line no-new
300300
new useTauriWebviewWindowWebviewWindow(label, {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<script setup lang="ts">
2+
type ResizeDirection = "East" | "North" | "NorthEast" | "NorthWest" | "South" | "SouthEast" | "SouthWest" | "West";
3+
4+
const props = withDefaults(
5+
defineProps<{
6+
enabled?: boolean
7+
inset?: number
8+
}>(),
9+
{
10+
enabled: true,
11+
inset: 6
12+
}
13+
);
14+
15+
const handles = computed(() => {
16+
const inset = `${props.inset}px`;
17+
18+
return [
19+
{ key: "north", direction: "North" as ResizeDirection, class: "absolute left-3 right-3 top-0 h-1.5 cursor-ns-resize" },
20+
{ key: "south", direction: "South" as ResizeDirection, class: "absolute left-3 right-3 bottom-0 h-1.5 cursor-ns-resize" },
21+
{ key: "west", direction: "West" as ResizeDirection, class: "absolute left-0 top-3 bottom-3 w-1.5 cursor-ew-resize" },
22+
{ key: "east", direction: "East" as ResizeDirection, class: "absolute right-0 top-3 bottom-3 w-1.5 cursor-ew-resize" },
23+
{ key: "north-west", direction: "NorthWest" as ResizeDirection, class: "absolute left-0 top-0 h-3 w-3 cursor-nwse-resize" },
24+
{ key: "north-east", direction: "NorthEast" as ResizeDirection, class: "absolute right-0 top-0 h-3 w-3 cursor-nesw-resize" },
25+
{ key: "south-west", direction: "SouthWest" as ResizeDirection, class: "absolute left-0 bottom-0 h-3 w-3 cursor-nesw-resize" },
26+
{ key: "south-east", direction: "SouthEast" as ResizeDirection, class: "absolute right-0 bottom-0 h-3 w-3 cursor-nwse-resize" }
27+
].map(handle => ({
28+
...handle,
29+
style: { margin: inset }
30+
}));
31+
});
32+
33+
async function startResize(direction: ResizeDirection) {
34+
if (!props.enabled) return;
35+
36+
try {
37+
await useTauriWindowGetCurrentWindow().startResizeDragging(direction);
38+
} catch {
39+
// ignore outside desktop runtime
40+
}
41+
}
42+
</script>
43+
44+
<template>
45+
<div v-if="enabled" class="pointer-events-none absolute inset-0 z-40">
46+
<div
47+
v-for="handle of handles"
48+
:key="handle.key"
49+
class="pointer-events-auto select-none"
50+
:class="handle.class"
51+
:style="handle.style"
52+
@mousedown.left.prevent="startResize(handle.direction)"
53+
/>
54+
</div>
55+
</template>

ui/layouts/default.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts" setup>
22
const { initialTheme, listenOSThemeChange } = useThemeAdapter();
3-
const { isWindows } = usePlatform();
3+
const { isLinux, isWindows } = usePlatform();
44
55
const cardUi = computed(() => {
66
const base = ["rounded-none", "overflow-visible"];
@@ -29,7 +29,8 @@ onMounted(() => {
2929
:ui="cardUi"
3030
:style="{ backgroundColor: isWindows ? 'transparent' : 'var(--ui-bg)' }"
3131
>
32-
<div class="flex gap-0 w-full h-screen border-none">
32+
<div class="relative flex gap-0 w-full h-screen border-none">
33+
<WindowResizeFrame :enabled="isLinux" />
3334
<SideBar />
3435

3536
<Main class="flex-1 min-w-0">

ui/layouts/setting.vue

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { NavigationMenuItem } from "@nuxt/ui";
44
const localePath = useLocalePath();
55
66
const { t } = useI18n();
7-
const { isWindows } = usePlatform();
7+
const { isLinux, isMacOS, isWindows } = usePlatform();
88
const { theme } = useSettingManager();
99
const { initialTheme, listenOSThemeChange } = useThemeAdapter();
1010
@@ -14,6 +14,8 @@ const commonButtonProps = {
1414
color: "neutral" as const
1515
};
1616
17+
const showCustomWindowControls = computed(() => !isMacOS.value);
18+
1719
const windowControlButtons = computed(() => {
1820
return [
1921
{
@@ -44,19 +46,26 @@ const windowControlButtons = computed(() => {
4446
});
4547
4648
const windowControlRailClass = computed(() => {
47-
return isWindows.value ? "w-36" : "w-0";
49+
if (isWindows.value) return "w-36";
50+
if (isLinux.value) return "w-32";
51+
return "w-0";
4852
});
4953
5054
const getWindowControlButtonClass = (buttonKey: string) => {
51-
const baseClass = "rounded-none w-12 h-13 p-1 flex items-center justify-center";
55+
const isLinuxStyle = isLinux.value;
56+
const baseClass = isLinuxStyle
57+
? "h-9 w-9 rounded-full p-1 flex items-center justify-center transition-colors"
58+
: "rounded-none w-12 h-13 p-1 flex items-center justify-center";
5259
5360
switch (buttonKey) {
5461
case "minimize":
55-
return `${baseClass} `;
62+
return isLinuxStyle ? `${baseClass} hover:bg-black/6 dark:hover:bg-white/10` : `${baseClass} `;
5663
case "maximize":
57-
return `${baseClass} `;
64+
return isLinuxStyle ? `${baseClass} hover:bg-black/6 dark:hover:bg-white/10` : `${baseClass} `;
5865
case "close":
59-
return `${baseClass} hover:bg-red-500 hover:text-white active:bg-red-600`;
66+
return isLinuxStyle
67+
? `${baseClass} hover:bg-red-500/12 hover:text-red-600 dark:hover:bg-red-500/18 dark:hover:text-red-300`
68+
: `${baseClass} hover:bg-red-500 hover:text-white active:bg-red-600`;
6069
default:
6170
return baseClass;
6271
}
@@ -95,14 +104,15 @@ onMounted(() => {
95104

96105
<template>
97106
<UPage
98-
class="h-screen flex flex-col"
107+
class="relative h-screen flex flex-col"
99108
:ui="{
100109
center: 'flex flex-col h-full min-h-0'
101110
}"
102111
:style="{
103112
backgroundColor: theme === 'dark' ? '#2C2C2C' : '#F5F5F5'
104113
}"
105114
>
115+
<WindowResizeFrame :enabled="isLinux" />
106116
<UPageHeader
107117
:ui="{
108118
root: 'p-0'
@@ -131,7 +141,7 @@ onMounted(() => {
131141
:class="windowControlRailClass"
132142
data-tauri-drag-region="false"
133143
>
134-
<template v-if="isWindows">
144+
<template v-if="showCustomWindowControls">
135145
<template v-for="button of windowControlButtons" :key="button.key">
136146
<UButton
137147
:icon="button.iconName"

0 commit comments

Comments
 (0)