From 1497533f14e4174e11d0e7aa2b467942bd7aa0a3 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Feb 2026 17:58:19 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=E5=AE=8C=E5=96=84=E9=9D=9E=E5=9B=9E?= =?UTF-8?q?=E6=AD=A3=E6=A8=A1=E5=BC=8F=E4=B8=8B=E7=9A=84=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE&=E5=A4=A7=E5=B0=8F=E5=A4=84=E7=90=86=20(#226?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ⚡️大幅提升UIGF导入速度 (#225) * Initial plan * perf: optimize gacha import with batch transactions and reduced UI delays - Wrap DB inserts in transactions (batches of 500) for mergeUIGF/mergeUIGF4 - Pre-transform all data before batch insert loop - Pass timeout: 0 to showLoading.update in progress callbacks - Remove 1500ms snackbar delay in cleanGachaRecords - Reduce per-item loading update delay in refreshGachaPool Co-authored-by: Mikachu2333 <63829496+Mikachu2333@users.noreply.github.com> * fix: increment progress counter per item instead of per batch for accurate progress display Co-authored-by: Mikachu2333 <63829496+Mikachu2333@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Mikachu2333 <63829496+Mikachu2333@users.noreply.github.com> * Initial plan * feat: calculate window size based on resolution/scaling with baseline check and centering - resizeWindow: add baseline check (1920x1080@150%), clamp to screen bounds - setWindowPos: ensure window fits on screen and always center - App.vue: use setWindowPos instead of manual positioning, center on deep link show - tray.rs: center window when showing from system tray Co-authored-by: Mikachu2333 <63829496+Mikachu2333@users.noreply.github.com> * fix: address code review - add zero guard and use setWindowPos consistently Co-authored-by: Mikachu2333 <63829496+Mikachu2333@users.noreply.github.com> * refactor: address review feedback - move baseline to setWindowPos, revert tray.rs - tray.rs: reverted, center() removed as redundant - TGWindow.ts: baseline check moved to setWindowPos, resizeWindow restored as fallback - App.vue: needResize=false → setWindowPos, else → center; deep link reverted; handleResizeListen true path unchanged, setWindowPos moved inside else Co-authored-by: Mikachu2333 <63829496+Mikachu2333@users.noreply.github.com> * refactor: use needResize judgment condition (targetZoom/scaleFactor/textScale) in setWindowPos Replace the simple curSize > screen.size overflow check with the same condition used by resizeWindow(): targetZoom < 1, which considers scaleFactor and textScale. Falls back to resizeWindow() when below baseline or when targetZoom < 1. Co-authored-by: Mikachu2333 <63829496+Mikachu2333@users.noreply.github.com> * 🚸 调整尺寸判断 * 🚸 处理溢出 * 🚸 优化处理 * 🚸 移除冗余scale处理 * 🎨 CodeStyle --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: Mikachu2333 <63829496+Mikachu2333@users.noreply.github.com> Co-authored-by: BTMuli --- src/App.vue | 21 ++++++++------------- src/utils/TGWindow.ts | 34 ++++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/App.vue b/src/App.vue index ca34622b..8cc629b7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -28,12 +28,12 @@ import useAppStore from "@store/app.js"; import useUserStore from "@store/user.js"; import { app, core, event, webviewWindow } from "@tauri-apps/api"; import type { Event, UnlistenFn } from "@tauri-apps/api/event"; -import { getCurrentWindow, LogicalPosition, LogicalSize } from "@tauri-apps/api/window"; +import { getCurrentWindow } from "@tauri-apps/api/window"; import { type CliMatches, getMatches } from "@tauri-apps/plugin-cli"; import { mkdir } from "@tauri-apps/plugin-fs"; import { openUrl } from "@tauri-apps/plugin-opener"; import TGLogger from "@utils/TGLogger.js"; -import { getWindowSize, resizeWindow } from "@utils/TGWindow.js"; +import { resizeWindow, setWindowPos } from "@utils/TGWindow.js"; import { storeToRefs } from "pinia"; import { computed, nextTick, onMounted, onUnmounted, ref } from "vue"; import { useRouter } from "vue-router"; @@ -74,11 +74,10 @@ onMounted(async () => { textScaleListener = await event.listen("text_scale_change", resizeWindow); const isShow = await win.isVisible(); if (!isShow) { - if (needResize.value !== "false") await win.center(); - else { - // TODO: 结合窗口尺寸&放缩以及设计尺寸放置合适位置 - const position = new LogicalPosition(20, 20); - await win.setPosition(position); + if (needResize.value === "false") { + await setWindowPos(); + } else { + await win.center(); } await win.show(); } @@ -275,15 +274,11 @@ function handleThemeListen(event: Event): void { * @returns {Promise} */ async function handleResizeListen(event: Event): Promise { - const win = getCurrentWindow(); - const webview = webviewWindow.getCurrentWebviewWindow(); if (event.payload !== "false") { await resizeWindow(); - await win.center(); + await getCurrentWindow().center(); } else { - const size = getWindowSize(webview.label); - await win.setSize(new LogicalSize(size.width, size.height)); - await webview.setZoom(1); + await setWindowPos(); } } diff --git a/src/utils/TGWindow.ts b/src/utils/TGWindow.ts index 1423f5be..c9b205cd 100644 --- a/src/utils/TGWindow.ts +++ b/src/utils/TGWindow.ts @@ -1,13 +1,13 @@ /** * 窗口创建相关工具函数 - * @since Beta v0.9.6 + * @since Beta v0.9.8 */ import type { RenderCard } from "@comp/app/t-postcard.vue"; import showSnackbar from "@comp/func/snackbar.js"; import { core, webviewWindow, window as TauriWindow } from "@tauri-apps/api"; import { invoke } from "@tauri-apps/api/core"; -import { PhysicalSize } from "@tauri-apps/api/dpi"; +import { PhysicalPosition, PhysicalSize } from "@tauri-apps/api/dpi"; import { currentMonitor, WindowOptions } from "@tauri-apps/api/window"; import { openUrl } from "@tauri-apps/plugin-opener"; @@ -100,24 +100,42 @@ export function getWindowSize(label: string): PhysicalSize { } /** - * 判断窗口位置 + * 判断窗口位置,确保窗口不超出屏幕并居中 * @since Beta v0.9.8 + * @remarks 当窗口超出屏幕时回滚到 resizeWindow,此时回正配置默认生效 * @returns 无返回值 */ export async function setWindowPos(): Promise { const screen = await currentMonitor(); + const NAV_BAR_HEIGHT = 28; if (screen === null) { showSnackbar.error("获取屏幕信息失败!", 3000); return; } const windowCur = webviewWindow.getCurrentWebviewWindow(); - const textScale = await invoke("read_text_scale"); if (await windowCur.isMaximized()) return; const designSize = getWindowSize(windowCur.label); - console.log(textScale, designSize); - // TODO: 判断设计大小是否会超出窗口大小 - // 如果超出,设计合适窗口位置使得顶部能够展示或者将窗口最大化 - // 否则直接居中 + const screenScale = screen.scaleFactor; + const targetWidth = Math.round(designSize.width * screenScale); + const targetHeight = Math.round(designSize.height * screenScale); + const cpWidth = screen.size.width - NAV_BAR_HEIGHT * screenScale; + const cpHeight = screen.size.height - NAV_BAR_HEIGHT * screenScale; + if (targetWidth > cpWidth && targetHeight > cpHeight) { + await resizeWindow(); + await windowCur.center(); + } else if (targetHeight > cpHeight) { + const left = (screen.size.width - targetWidth) / 2; + await windowCur.setSize(new PhysicalSize(targetWidth, targetHeight)); + await windowCur.setPosition(new PhysicalPosition(left, 24)); + } else if (targetWidth > screen.size.width) { + const top = (screen.size.height - targetHeight) / 2; + await windowCur.setSize(new PhysicalSize(targetWidth, targetHeight)); + await windowCur.setPosition(new PhysicalPosition(24, top)); + } else { + await windowCur.setSize(new PhysicalSize(targetWidth, targetHeight)); + await windowCur.center(); + } + await windowCur.setZoom(1); } /**