v1.8.0 #429

Merged
LukeGus merged 198 commits from dev-1.8.0 into main 2025-11-05 16:36:16 +00:00
6 changed files with 40 additions and 32 deletions
Showing only changes of commit 3937529d6b - Show all commits

View File

@@ -409,11 +409,10 @@ jobs:
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: | run: |
if [ "${{ steps.check_certs.outputs.has_certs }}" == "true" ]; then if [ "${{ steps.check_certs.outputs.has_certs }}" != "true" ]; then
npx electron-builder --mac dmg --universal --x64 --arm64 --publish never npm run build
else
npm run build && npx electron-builder --mac dmg --universal --x64 --arm64 --publish never
fi fi
npx electron-builder --mac dmg --universal --x64 --arm64 --publish never
- name: List release directory - name: List release directory
if: steps.check_certs.outputs.has_certs == 'true' if: steps.check_certs.outputs.has_certs == 'true'

View File

@@ -41,6 +41,10 @@ if (!gotTheLock) {
} }
function createWindow() { function createWindow() {
const appVersion = app.getVersion();
const electronVersion = process.versions.electron;
const platform = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 1200, width: 1200,
height: 800, height: 800,
@@ -63,6 +67,10 @@ function createWindow() {
mainWindow.setMenuBarVisibility(false); mainWindow.setMenuBarVisibility(false);
} }
mainWindow.webContents.setUserAgent(
`Termix-Desktop/${appVersion} (${platform}; Electron/${electronVersion})`
);
if (isDev) { if (isDev) {
mainWindow.loadURL("http:://localhost:5173"); mainWindow.loadURL("http:://localhost:5173");
mainWindow.webContents.openDevTools(); mainWindow.webContents.openDevTools();

View File

@@ -18,16 +18,13 @@
"build:backend": "tsc -p tsconfig.node.json", "build:backend": "tsc -p tsconfig.node.json",
"dev:backend": "tsc -p tsconfig.node.json && node ./dist/backend/backend/starter.js", "dev:backend": "tsc -p tsconfig.node.json && node ./dist/backend/backend/starter.js",
"preview": "vite preview", "preview": "vite preview",
"electron:dev": "concurrently \"npm run dev\" \"wait-on http://localhost:5173 && electron .\"", "electron:dev": "concurrently \"npm run dev\" \"powershell -c \\\"Start-Sleep -Seconds 5\\\" && electron .\"",
"build:win-portable": "npm run build && electron-builder --win --dir", "build:win-portable": "npm run build && electron-builder --win --dir",
"build:win-installer": "npm run build && electron-builder --win --publish=never", "build:win-installer": "npm run build && electron-builder --win --publish=never",
"build:linux-portable": "npm run build && electron-builder --linux --dir", "build:linux-portable": "npm run build && electron-builder --linux --dir",
"build:linux-appimage": "npm run build && electron-builder --linux AppImage", "build:linux-appimage": "npm run build && electron-builder --linux AppImage",
"build:linux-targz": "npm run build && electron-builder --linux tar.gz", "build:linux-targz": "npm run build && electron-builder --linux tar.gz",
"build:mac": "npm run build && electron-builder --mac --universal", "build:mac": "npm run build && electron-builder --mac --universal"
"test:encryption": "tsc -p tsconfig.node.json && node ./dist/backend/backend/utils/encryption-test.js",
"migrate:encryption": "tsc -p tsconfig.node.json && node ./dist/backend/backend/utils/encryption-migration.js",
"prepare": "husky"
}, },
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.18.7", "@codemirror/autocomplete": "^6.18.7",

View File

@@ -267,15 +267,6 @@ class AuthManager {
.limit(1); .limit(1);
if (sessionRecords.length === 0) { if (sessionRecords.length === 0) {
databaseLogger.warn(
"JWT token has no matching session in database",
{
operation: "jwt_verify_failed",
reason: "session_not_found",
sessionId: payload.sessionId,
userId: payload.userId,
},
);
return null; return null;
} }
} catch (dbError) { } catch (dbError) {

View File

@@ -14,7 +14,7 @@ export function detectPlatform(req: Request): DeviceType {
const userAgent = req.headers["user-agent"] || ""; const userAgent = req.headers["user-agent"] || "";
const electronHeader = req.headers["x-electron-app"]; const electronHeader = req.headers["x-electron-app"];
if (electronHeader === "true") { if (electronHeader === "true" || userAgent.includes("Termix-Desktop")) {
return "desktop"; return "desktop";
} }
@@ -44,22 +44,30 @@ function parseElectronUserAgent(userAgent: string): DeviceInfo {
let os = "Unknown OS"; let os = "Unknown OS";
let version = "Unknown"; let version = "Unknown";
if (userAgent.includes("Windows")) { const termixMatch = userAgent.match(/Termix-Desktop\/([\d.]+) \(([^;]+);/);
os = parseWindowsVersion(userAgent); if (termixMatch) {
} else if (userAgent.includes("Mac OS X")) { version = termixMatch[1];
os = parseMacVersion(userAgent); os = termixMatch[2];
} else if (userAgent.includes("Linux")) { } else {
os = "Linux"; if (userAgent.includes("Windows")) {
} os = parseWindowsVersion(userAgent);
} else if (userAgent.includes("Mac OS X")) {
os = parseMacVersion(userAgent);
} else if (userAgent.includes("macOS")) {
os = "macOS";
} else if (userAgent.includes("Linux")) {
os = "Linux";
}
const electronMatch = userAgent.match(/Electron\/([\d.]+)/); const electronMatch = userAgent.match(/Electron\/([\d.]+)/);
if (electronMatch) { if (electronMatch) {
version = electronMatch[1]; version = electronMatch[1];
}
} }
return { return {
type: "desktop", type: "desktop",
browser: "Electron", browser: "Termix Desktop",
version, version,
os, os,
deviceInfo: `Termix Desktop on ${os}`, deviceInfo: `Termix Desktop on ${os}`,

View File

@@ -23,6 +23,7 @@ export function ElectronLoginForm({
const iframeRef = useRef<HTMLIFrameElement>(null); const iframeRef = useRef<HTMLIFrameElement>(null);
const hasAuthenticatedRef = useRef(false); const hasAuthenticatedRef = useRef(false);
const [currentUrl, setCurrentUrl] = useState(serverUrl); const [currentUrl, setCurrentUrl] = useState(serverUrl);
const hasLoadedOnce = useRef(false);
useEffect(() => { useEffect(() => {
const handleMessage = async (event: MessageEvent) => { const handleMessage = async (event: MessageEvent) => {
@@ -52,7 +53,7 @@ export function ElectronLoginForm({
throw new Error("Failed to save JWT to localStorage"); throw new Error("Failed to save JWT to localStorage");
} }
await new Promise((resolve) => setTimeout(resolve, 200)); await new Promise((resolve) => setTimeout(resolve, 500));
onAuthSuccess(); onAuthSuccess();
} catch (err) { } catch (err) {
@@ -81,6 +82,8 @@ export function ElectronLoginForm({
const handleLoad = () => { const handleLoad = () => {
setLoading(false); setLoading(false);
hasLoadedOnce.current = true;
setError(null);
try { try {
if (iframe.contentWindow) { if (iframe.contentWindow) {
@@ -200,7 +203,9 @@ export function ElectronLoginForm({
const handleError = () => { const handleError = () => {
setLoading(false); setLoading(false);
setError(t("errors.failedToLoadServer")); if (hasLoadedOnce.current) {
setError(t("errors.failedToLoadServer"));
}
}; };
iframe.addEventListener("load", handleLoad); iframe.addEventListener("load", handleLoad);