앱 버전표시
This commit is contained in:
@@ -4,12 +4,24 @@ use tauri::{
|
||||
AppHandle, Manager, RunEvent,
|
||||
};
|
||||
|
||||
fn format_main_window_title(version: &str) -> String {
|
||||
format!("GoldenChart (v{version})")
|
||||
}
|
||||
|
||||
fn apply_main_window_title(app: &AppHandle) {
|
||||
let title = format_main_window_title(&app.package_info().version.to_string());
|
||||
if let Some(w) = app.get_webview_window("main") {
|
||||
let _ = w.set_title(&title);
|
||||
}
|
||||
}
|
||||
|
||||
fn show_main_window(app: &AppHandle) {
|
||||
if let Some(w) = app.get_webview_window("main") {
|
||||
let _ = w.show();
|
||||
let _ = w.unminimize();
|
||||
let _ = w.set_focus();
|
||||
}
|
||||
apply_main_window_title(app);
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
@@ -21,11 +33,7 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_process::init())
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.setup(|app| {
|
||||
let version = app.package_info().version.to_string();
|
||||
let main_title = format!("GoldenChart (v{version})");
|
||||
if let Some(w) = app.get_webview_window("main") {
|
||||
let _ = w.set_title(&main_title);
|
||||
}
|
||||
apply_main_window_title(app.handle());
|
||||
|
||||
let show_i = MenuItemBuilder::with_id("show", "GoldenChart 열기").build(app)?;
|
||||
let quit_i = MenuItemBuilder::with_id("quit", "종료").build(app)?;
|
||||
@@ -63,10 +71,19 @@ pub fn run() {
|
||||
show_main_window(app.handle());
|
||||
Ok(())
|
||||
})
|
||||
.on_page_load(|webview, _payload| {
|
||||
if webview.label() != "main" {
|
||||
return;
|
||||
}
|
||||
apply_main_window_title(webview.app_handle());
|
||||
})
|
||||
.on_window_event(|window, event| {
|
||||
if window.label() != "main" {
|
||||
return;
|
||||
}
|
||||
if matches!(event, tauri::WindowEvent::Focused(true)) {
|
||||
apply_main_window_title(window.app_handle());
|
||||
}
|
||||
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
|
||||
api.prevent_close();
|
||||
let _ = window.hide();
|
||||
@@ -75,6 +92,7 @@ pub fn run() {
|
||||
.build(tauri::generate_context!())
|
||||
.expect("error while building tauri application")
|
||||
.run(|app_handle, event| match event {
|
||||
RunEvent::Ready => apply_main_window_title(&app_handle),
|
||||
#[cfg(target_os = "macos")]
|
||||
RunEvent::Reopen { .. } => show_main_window(&app_handle),
|
||||
RunEvent::ExitRequested { api, .. } => {
|
||||
|
||||
@@ -1,32 +1,60 @@
|
||||
import { getVersion } from '@tauri-apps/api/app';
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||
import {
|
||||
formatDesktopWindowTitle,
|
||||
readBakedDesktopAppVersion,
|
||||
} from '@frontend/utils/desktopAppVersion';
|
||||
|
||||
const APP_NAME = 'GoldenChart';
|
||||
|
||||
export function formatDesktopWindowTitle(version: string): string {
|
||||
const v = version.trim();
|
||||
return v ? `${APP_NAME} (v${v})` : APP_NAME;
|
||||
}
|
||||
export { formatDesktopWindowTitle } from '@frontend/utils/desktopAppVersion';
|
||||
|
||||
/** macOS/Windows 네이티브 창 타이틀 — GoldenChart (vX.Y.Z) */
|
||||
export async function syncMainWindowTitle(): Promise<string> {
|
||||
try {
|
||||
const version = await getVersion();
|
||||
const version = (await getVersion()) || readBakedDesktopAppVersion() || '';
|
||||
const title = formatDesktopWindowTitle(version);
|
||||
await getCurrentWindow().setTitle(title);
|
||||
if (typeof document !== 'undefined') {
|
||||
if (typeof document !== 'undefined' && document.title !== title) {
|
||||
document.title = title;
|
||||
}
|
||||
return title;
|
||||
} catch (e) {
|
||||
const fallback = formatDesktopWindowTitle(readBakedDesktopAppVersion());
|
||||
if (typeof document !== 'undefined') {
|
||||
document.title = fallback;
|
||||
}
|
||||
console.warn('[desktop] syncMainWindowTitle failed:', e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
let titleGuardInstalled = false;
|
||||
|
||||
/** macOS WebKit — document.title 변경 시 네이티브 타이틀을 다시 맞춤 */
|
||||
export function installDocumentTitleGuard(): void {
|
||||
if (titleGuardInstalled || typeof document === 'undefined') return;
|
||||
titleGuardInstalled = true;
|
||||
|
||||
const rebalance = () => {
|
||||
void syncMainWindowTitle().catch(() => {});
|
||||
};
|
||||
|
||||
const titleEl = document.querySelector('title');
|
||||
if (titleEl) {
|
||||
const observer = new MutationObserver(() => {
|
||||
if (!document.title.includes('(v')) rebalance();
|
||||
});
|
||||
observer.observe(titleEl, { childList: true, characterData: true, subtree: true });
|
||||
}
|
||||
|
||||
window.setInterval(() => {
|
||||
if (!document.title.includes('(v')) rebalance();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
/** WebView 로드 후 macOS가 document.title로 타이틀을 덮어쓸 수 있어 재시도 */
|
||||
export function scheduleMainWindowTitleSync(): void {
|
||||
const delays = [0, 150, 600, 2000];
|
||||
installDocumentTitleGuard();
|
||||
const delays = [0, 50, 150, 400, 1000, 2500, 5000];
|
||||
for (const ms of delays) {
|
||||
window.setTimeout(() => {
|
||||
void syncMainWindowTitle().catch(() => {});
|
||||
|
||||
+19
-1
@@ -20,6 +20,24 @@ function readDesktopAppVersion(): string {
|
||||
}
|
||||
}
|
||||
|
||||
const desktopVersion = readDesktopAppVersion();
|
||||
const desktopWindowTitle = `GoldenChart (v${desktopVersion})`;
|
||||
|
||||
function desktopHtmlTitlePlugin() {
|
||||
return {
|
||||
name: 'desktop-html-title',
|
||||
transformIndexHtml(html: string, ctx: { filename: string }) {
|
||||
if (!ctx.filename.endsWith('index.html')) return html;
|
||||
return html
|
||||
.replace(/<title>[^<]*<\/title>/i, `<title>${desktopWindowTitle}</title>`)
|
||||
.replace(
|
||||
'<script>var global = globalThis;</script>',
|
||||
`<script>var global = globalThis;window.__GC_APP_VERSION__="${desktopVersion}";</script>`,
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
/** Tauri 패키지 앱 — 절대 경로(/assets) 사용 시 빈 화면 */
|
||||
base: './',
|
||||
@@ -32,7 +50,7 @@ export default defineConfig({
|
||||
__DESKTOP_APP_VERSION__: JSON.stringify(readDesktopAppVersion()),
|
||||
},
|
||||
envDir: __dirname,
|
||||
plugins: [react()],
|
||||
plugins: [react(), desktopHtmlTitlePlugin()],
|
||||
resolve: {
|
||||
dedupe: ['react', 'react-dom', 'lightweight-charts'],
|
||||
alias: {
|
||||
|
||||
Reference in New Issue
Block a user