fix: Desktop app login issues and rename version check and host manager folder
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
|
||||
import { LeftSidebar } from "@/ui/desktop/navigation/LeftSidebar.tsx";
|
||||
import { Dashboard } from "@/ui/desktop/apps/dashboard/Dashboard.tsx";
|
||||
import { AppView } from "@/ui/desktop/navigation/AppView.tsx";
|
||||
import { HostManager } from "@/ui/desktop/apps/host manager/HostManager.tsx";
|
||||
import { HostManager } from "@/ui/desktop/apps/host-manager/HostManager.tsx";
|
||||
import {
|
||||
TabProvider,
|
||||
useTabs,
|
||||
@@ -11,7 +11,6 @@ import { TopNavbar } from "@/ui/desktop/navigation/TopNavbar.tsx";
|
||||
import { AdminSettings } from "@/ui/desktop/admin/AdminSettings.tsx";
|
||||
import { UserProfile } from "@/ui/desktop/user/UserProfile.tsx";
|
||||
import { Toaster } from "@/components/ui/sonner.tsx";
|
||||
import { VersionCheckModal } from "@/components/ui/version-check-modal.tsx";
|
||||
import { getUserInfo } from "@/ui/main-axios.ts";
|
||||
|
||||
function AppContent() {
|
||||
@@ -19,7 +18,6 @@ function AppContent() {
|
||||
const [username, setUsername] = useState<string | null>(null);
|
||||
const [isAdmin, setIsAdmin] = useState(false);
|
||||
const [authLoading, setAuthLoading] = useState(true);
|
||||
const [showVersionCheck, setShowVersionCheck] = useState(true);
|
||||
const [isTopbarOpen, setIsTopbarOpen] = useState<boolean>(() => {
|
||||
const saved = localStorage.getItem("topNavbarOpen");
|
||||
return saved !== null ? JSON.parse(saved) : true;
|
||||
@@ -31,9 +29,16 @@ function AppContent() {
|
||||
setAuthLoading(true);
|
||||
getUserInfo()
|
||||
.then((meRes) => {
|
||||
setIsAuthenticated(true);
|
||||
setIsAdmin(!!meRes.is_admin);
|
||||
setUsername(meRes.username || null);
|
||||
// Check if response is actually HTML (Vite dev server page)
|
||||
if (typeof meRes === "string" || !meRes.username) {
|
||||
setIsAuthenticated(false);
|
||||
setIsAdmin(false);
|
||||
setUsername(null);
|
||||
} else {
|
||||
setIsAuthenticated(true);
|
||||
setIsAdmin(!!meRes.is_admin);
|
||||
setUsername(meRes.username || null);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
setIsAuthenticated(false);
|
||||
@@ -45,7 +50,9 @@ function AppContent() {
|
||||
console.warn("Session expired - please log in again");
|
||||
}
|
||||
})
|
||||
.finally(() => setAuthLoading(false));
|
||||
.finally(() => {
|
||||
setAuthLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
checkAuth();
|
||||
@@ -84,35 +91,7 @@ function AppContent() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{showVersionCheck && (
|
||||
<VersionCheckModal
|
||||
onDismiss={() => setShowVersionCheck(false)}
|
||||
onContinue={() => setShowVersionCheck(false)}
|
||||
isAuthenticated={isAuthenticated}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isAuthenticated && !authLoading && !showVersionCheck && (
|
||||
<div>
|
||||
<div
|
||||
className="absolute inset-0"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(
|
||||
135deg,
|
||||
transparent 0%,
|
||||
transparent 49%,
|
||||
rgba(255, 255, 255, 0.03) 49%,
|
||||
rgba(255, 255, 255, 0.03) 51%,
|
||||
transparent 51%,
|
||||
transparent 100%
|
||||
)`,
|
||||
backgroundSize: "80px 80px",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isAuthenticated && !authLoading && !showVersionCheck && (
|
||||
{!isAuthenticated && !authLoading && (
|
||||
<div className="fixed inset-0 flex items-center justify-center z-[10000]">
|
||||
<Dashboard
|
||||
onSelectView={handleSelectView}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { HostManagerViewer } from "@/ui/desktop/apps/host manager/HostManagerViewer.tsx";
|
||||
import { HostManagerViewer } from "@/ui/desktop/apps/host-manager/HostManagerViewer.tsx";
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
TabsTrigger,
|
||||
} from "@/components/ui/tabs.tsx";
|
||||
import { Separator } from "@/components/ui/separator.tsx";
|
||||
import { HostManagerEditor } from "@/ui/desktop/apps/host manager/HostManagerEditor.tsx";
|
||||
import { HostManagerEditor } from "@/ui/desktop/apps/host-manager/HostManagerEditor.tsx";
|
||||
import { CredentialsManager } from "@/ui/desktop/apps/credentials/CredentialsManager.tsx";
|
||||
import { CredentialEditor } from "@/ui/desktop/apps/credentials/CredentialEditor.tsx";
|
||||
import { useSidebar } from "@/components/ui/sidebar.tsx";
|
||||
@@ -104,20 +104,12 @@ export function Auth({
|
||||
}, [loggedIn]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInElectronWebView()) {
|
||||
return;
|
||||
}
|
||||
|
||||
getRegistrationAllowed().then((res) => {
|
||||
setRegistrationAllowed(res.allowed);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInElectronWebView()) {
|
||||
return;
|
||||
}
|
||||
|
||||
getPasswordLoginAllowed()
|
||||
.then((res) => {
|
||||
setPasswordLoginAllowed(res.allowed);
|
||||
@@ -130,10 +122,6 @@ export function Auth({
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInElectronWebView()) {
|
||||
return;
|
||||
}
|
||||
|
||||
getOIDCConfig()
|
||||
.then((response) => {
|
||||
if (response) {
|
||||
|
||||
156
src/ui/desktop/user/ElectronVersionCheck.tsx
Normal file
156
src/ui/desktop/user/ElectronVersionCheck.tsx
Normal file
@@ -0,0 +1,156 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Button } from "@/components/ui/button.tsx";
|
||||
import { VersionAlert } from "@/components/ui/version-alert.tsx";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { checkElectronUpdate, isElectron } from "@/ui/main-axios.ts";
|
||||
|
||||
interface VersionCheckModalProps {
|
||||
onContinue: () => void;
|
||||
isAuthenticated?: boolean;
|
||||
}
|
||||
|
||||
export function ElectronVersionCheck({
|
||||
onContinue,
|
||||
isAuthenticated = false,
|
||||
}: VersionCheckModalProps) {
|
||||
const { t } = useTranslation();
|
||||
const [versionInfo, setVersionInfo] = useState<Record<
|
||||
string,
|
||||
unknown
|
||||
> | null>(null);
|
||||
const [versionChecking, setVersionChecking] = useState(false);
|
||||
const [versionDismissed] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isElectron()) {
|
||||
checkForUpdates();
|
||||
} else {
|
||||
onContinue();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const checkForUpdates = async () => {
|
||||
setVersionChecking(true);
|
||||
try {
|
||||
const updateInfo = await checkElectronUpdate();
|
||||
setVersionInfo(updateInfo);
|
||||
|
||||
// Get current app version
|
||||
const currentVersion = await (window as any).electronAPI?.getAppVersion();
|
||||
const dismissedVersion = localStorage.getItem(
|
||||
"electron-version-check-dismissed",
|
||||
);
|
||||
|
||||
// If this version was already dismissed, skip the modal
|
||||
if (dismissedVersion === currentVersion) {
|
||||
onContinue();
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateInfo?.status === "up_to_date") {
|
||||
// Store this version as checked (but don't show modal since up to date)
|
||||
if (currentVersion) {
|
||||
localStorage.setItem(
|
||||
"electron-version-check-dismissed",
|
||||
currentVersion,
|
||||
);
|
||||
}
|
||||
onContinue();
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to check for updates:", error);
|
||||
setVersionInfo({ success: false, error: "Check failed" });
|
||||
} finally {
|
||||
setVersionChecking(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownloadUpdate = () => {
|
||||
if (versionInfo?.latest_release?.html_url) {
|
||||
window.open(versionInfo.latest_release.html_url, "_blank");
|
||||
}
|
||||
};
|
||||
|
||||
const handleContinue = async () => {
|
||||
// Store the current version as dismissed
|
||||
const currentVersion = await (window as any).electronAPI?.getAppVersion();
|
||||
if (currentVersion) {
|
||||
localStorage.setItem("electron-version-check-dismissed", currentVersion);
|
||||
}
|
||||
onContinue();
|
||||
};
|
||||
|
||||
if (!isElectron()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (versionChecking && !versionInfo) {
|
||||
return (
|
||||
<div className="fixed inset-0 flex items-center justify-center z-50">
|
||||
<div className="bg-dark-bg border-2 border-dark-border rounded-lg p-6 max-w-md w-full mx-4 relative z-10">
|
||||
<div className="flex items-center justify-center mb-4">
|
||||
<div className="w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin" />
|
||||
</div>
|
||||
<p className="text-center text-muted-foreground">
|
||||
{t("versionCheck.checkingUpdates")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!versionInfo || versionDismissed) {
|
||||
return (
|
||||
<div className="fixed inset-0 flex items-center justify-center z-50">
|
||||
<div className="bg-dark-bg border-2 border-dark-border rounded-lg p-6 max-w-md w-full mx-4 relative z-10">
|
||||
<div className="mb-4">
|
||||
<h2 className="text-lg font-semibold">
|
||||
{t("versionCheck.checkUpdates")}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{versionInfo && !versionDismissed && (
|
||||
<div className="mb-4">
|
||||
<VersionAlert
|
||||
updateInfo={versionInfo}
|
||||
onDownload={handleDownloadUpdate}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button onClick={handleContinue} className="flex-1 h-10">
|
||||
{t("common.continue")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 flex items-center justify-center z-50">
|
||||
<div className="bg-dark-bg border-2 border-dark-border rounded-lg p-6 max-w-md w-full mx-4 relative z-10">
|
||||
<div className="mb-4">
|
||||
<h2 className="text-lg font-semibold">
|
||||
{t("versionCheck.updateRequired")}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<VersionAlert
|
||||
updateInfo={versionInfo}
|
||||
onDownload={handleDownloadUpdate}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button onClick={handleContinue} className="flex-1 h-10">
|
||||
{t("common.continue")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -484,12 +484,7 @@ function getApiUrl(path: string, defaultPort: number): string {
|
||||
const devMode = isDev();
|
||||
const electronMode = isElectron();
|
||||
|
||||
if (devMode) {
|
||||
const protocol = window.location.protocol === "https:" ? "https" : "http";
|
||||
const sslPort = protocol === "https" ? 8443 : defaultPort;
|
||||
const url = `${protocol}://${apiHost}:${sslPort}${path}`;
|
||||
return url;
|
||||
} else if (electronMode) {
|
||||
if (electronMode) {
|
||||
if (configuredServerUrl) {
|
||||
const baseUrl = configuredServerUrl.replace(/\/$/, "");
|
||||
const url = `${baseUrl}${path}`;
|
||||
@@ -497,6 +492,11 @@ function getApiUrl(path: string, defaultPort: number): string {
|
||||
}
|
||||
console.warn("Electron mode but no server configured!");
|
||||
return "http://no-server-configured";
|
||||
} else if (devMode) {
|
||||
const protocol = window.location.protocol === "https:" ? "https" : "http";
|
||||
const sslPort = protocol === "https" ? 8443 : defaultPort;
|
||||
const url = `${protocol}://${apiHost}:${sslPort}${path}`;
|
||||
return url;
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user