## Fixes
- Fix duplicate tray icon on macOS when hiding to tray - Fix tray not showing in background mode on macOS - Fix hide to tray broken on Windows/Linux - Fix Shutdown button in web UI not working
This commit is contained in:
parent
30ff4e3fb0
commit
593c788c75
6 changed files with 43 additions and 16 deletions
|
|
@ -1,3 +1,11 @@
|
||||||
|
# v0.4.50 (2026-05-16)
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
- Fix duplicate tray icon on macOS when hiding to tray
|
||||||
|
- Fix tray not showing in background mode on macOS
|
||||||
|
- Fix hide to tray broken on Windows/Linux
|
||||||
|
- Fix Shutdown button in web UI not working
|
||||||
|
|
||||||
# v0.4.49 (2026-05-16)
|
# v0.4.49 (2026-05-16)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
|
||||||
41
cli/cli.js
41
cli/cli.js
|
|
@ -694,29 +694,48 @@ function startServer(latestVersion) {
|
||||||
await startTerminalUI(port);
|
await startTerminalUI(port);
|
||||||
// Loop continues, show menu again
|
// Loop continues, show menu again
|
||||||
} else if (choice === "hide") {
|
} else if (choice === "hide") {
|
||||||
// Hide to tray: keep the CURRENT process alive (it already owns a
|
|
||||||
// macOS GUI session so NSStatusItem works). Spawning a detached child
|
|
||||||
// puts it outside the login session → systray silently fails on macOS.
|
|
||||||
const { clearScreen } = require("./src/cli/utils/display");
|
const { clearScreen } = require("./src/cli/utils/display");
|
||||||
clearScreen();
|
clearScreen();
|
||||||
|
|
||||||
// Survive terminal close — SIGHUP is sent when the launching shell exits
|
|
||||||
process.removeAllListeners("SIGHUP");
|
|
||||||
process.on("SIGHUP", () => {});
|
|
||||||
|
|
||||||
// Enable auto startup on OS boot
|
// Enable auto startup on OS boot
|
||||||
try {
|
try {
|
||||||
const { enableAutoStart } = require("./src/cli/tray/autostart");
|
const { enableAutoStart } = require("./src/cli/tray/autostart");
|
||||||
enableAutoStart(__filename);
|
enableAutoStart(__filename);
|
||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
|
|
||||||
console.log(`\n🔔 9Router is running in tray (PID: ${process.pid})`);
|
if (process.platform === "darwin") {
|
||||||
|
// macOS: keep current process alive — spawning a detached child puts
|
||||||
|
// it outside the login session so NSStatusItem silently fails.
|
||||||
|
process.removeAllListeners("SIGHUP");
|
||||||
|
process.on("SIGHUP", () => {});
|
||||||
|
|
||||||
|
console.log(`\n⏳ Switching to tray mode... (icon already visible in menu bar)`);
|
||||||
|
console.log(`🔔 9Router is running in tray (PID: ${process.pid})`);
|
||||||
|
console.log(` Server: http://${displayHost}:${port}`);
|
||||||
|
console.log(`\n💡 You can close this terminal. Right-click tray icon to quit.\n`);
|
||||||
|
|
||||||
|
// Tray already init'd at startup — just keep event loop alive.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Windows/Linux: spawn detached bgProcess (systray works fine in child)
|
||||||
|
console.log(`\n⏳ Starting background process... (tray icon will appear in ~3s)`);
|
||||||
|
|
||||||
|
const bgProcess = spawn(process.execPath, [__filename, "--tray", "--skip-update", "-p", port.toString()], {
|
||||||
|
detached: true,
|
||||||
|
stdio: "ignore",
|
||||||
|
windowsHide: true,
|
||||||
|
env: { ...process.env }
|
||||||
|
});
|
||||||
|
bgProcess.unref();
|
||||||
|
|
||||||
|
console.log(`🔔 9Router is now running in background (PID: ${bgProcess.pid})`);
|
||||||
console.log(` Server: http://${displayHost}:${port}`);
|
console.log(` Server: http://${displayHost}:${port}`);
|
||||||
console.log(`\n💡 You can close this terminal. Right-click tray icon to quit.\n`);
|
console.log(`\n💡 You can close this terminal. Right-click tray icon to quit.\n`);
|
||||||
|
|
||||||
// Tray icon already running (initTrayIcon was called above at startup).
|
// cleanup() kills server so bgProcess can claim the port fresh
|
||||||
// Nothing more to do — event loop keeps process alive via tray + server.
|
cleanup();
|
||||||
return;
|
process.exit(0);
|
||||||
} else if (choice === "exit") {
|
} else if (choice === "exit") {
|
||||||
isShuttingDown = true;
|
isShuttingDown = true;
|
||||||
console.log("\nExiting...");
|
console.log("\nExiting...");
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "9router",
|
"name": "9router",
|
||||||
"version": "0.4.49",
|
"version": "0.4.50",
|
||||||
"description": "9Router CLI - Start and manage 9Router server",
|
"description": "9Router CLI - Start and manage 9Router server",
|
||||||
"bin": {
|
"bin": {
|
||||||
"9router": "./cli.js"
|
"9router": "./cli.js"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "9router-app",
|
"name": "9router-app",
|
||||||
"version": "0.4.49",
|
"version": "0.4.50",
|
||||||
"description": "9Router web dashboard",
|
"description": "9Router web dashboard",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
|
|
@ -98,13 +98,13 @@
|
||||||
"Console Log": "Nhật ký Console",
|
"Console Log": "Nhật ký Console",
|
||||||
"System": "Hệ thống",
|
"System": "Hệ thống",
|
||||||
"Debug": "Gỡ lỗi",
|
"Debug": "Gỡ lỗi",
|
||||||
"Shutdown": "Tắt máy",
|
"Shutdown": "Tắt ứng dụng",
|
||||||
"Close Proxy": "Đóng Proxy",
|
"Close Proxy": "Đóng Proxy",
|
||||||
"Are you sure you want to close the proxy server?": "Bạn có chắc chắn muốn đóng máy chủ proxy không?",
|
"Are you sure you want to close the proxy server?": "Bạn có chắc chắn muốn đóng máy chủ proxy không?",
|
||||||
"Server Disconnected": "Máy chủ đã ngắt kết nối",
|
"Server Disconnected": "Máy chủ đã ngắt kết nối",
|
||||||
"The proxy server has been stopped.": "Máy chủ proxy đã bị dừng.",
|
"The proxy server has been stopped.": "Máy chủ proxy đã bị dừng.",
|
||||||
"Reload Page": "Tải lại trang",
|
"Reload Page": "Tải lại trang",
|
||||||
"Service is running in terminal. You can close this web page. Shutdown will stop the service.": "Dịch vụ đang chạy trong terminal. Bạn có thể đóng trang web này. Tắt máy sẽ dừng dịch vụ.",
|
"Service is running in terminal. You can close this web page. Shutdown will stop the service.": "Dịch vụ đang chạy trong terminal. Bạn có thể đóng trang web này. Tắt ứng dụng sẽ dừng dịch vụ.",
|
||||||
"Manage your AI provider connections": "Quản lý kết nối nhà cung cấp AI của bạn",
|
"Manage your AI provider connections": "Quản lý kết nối nhà cung cấp AI của bạn",
|
||||||
"Model combos with fallback": "Kết hợp mô hình với dự phòng",
|
"Model combos with fallback": "Kết hợp mô hình với dự phòng",
|
||||||
"Monitor your API usage, token consumption, and request logs": "Theo dõi việc sử dụng API, tiêu thụ token và nhật ký yêu cầu",
|
"Monitor your API usage, token consumption, and request logs": "Theo dõi việc sử dụng API, tiêu thụ token và nhật ký yêu cầu",
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ export default function Sidebar({ onClose }) {
|
||||||
const handleShutdown = async () => {
|
const handleShutdown = async () => {
|
||||||
setIsShuttingDown(true);
|
setIsShuttingDown(true);
|
||||||
try {
|
try {
|
||||||
await fetch("/api/shutdown", { method: "POST" });
|
await fetch("/api/version/shutdown", { method: "POST" });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Expected to fail as server shuts down; ignore error
|
// Expected to fail as server shuts down; ignore error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue