Preserve dashboard page across refreshes
This commit is contained in:
+25
-6
@@ -47,6 +47,14 @@ const ShellTerminal = lazy(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
type Screen = "loading" | "setup" | "login" | "dashboard" | "fatal";
|
type Screen = "loading" | "setup" | "login" | "dashboard" | "fatal";
|
||||||
|
type DashboardPage = "home" | "car" | "adb" | "network" | "settings";
|
||||||
|
|
||||||
|
const dashboardPages = new Set<DashboardPage>(["home", "car", "adb", "network", "settings"]);
|
||||||
|
|
||||||
|
function pageFromLocation(): DashboardPage {
|
||||||
|
const page = window.location.hash.replace(/^#\/?/, "");
|
||||||
|
return dashboardPages.has(page as DashboardPage) ? (page as DashboardPage) : "home";
|
||||||
|
}
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
const [screen, setScreen] = useState<Screen>("loading");
|
const [screen, setScreen] = useState<Screen>("loading");
|
||||||
@@ -171,7 +179,7 @@ function AccountScreen({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Dashboard({ auth, onLoggedOut }: { auth: AuthState; onLoggedOut: () => Promise<void> }) {
|
function Dashboard({ auth, onLoggedOut }: { auth: AuthState; onLoggedOut: () => Promise<void> }) {
|
||||||
const [page, setPage] = useState<"home" | "car" | "adb" | "network" | "settings">("home");
|
const [page, setPage] = useState<DashboardPage>(pageFromLocation);
|
||||||
const [status, setStatus] = useState<SystemStatus | null>(null);
|
const [status, setStatus] = useState<SystemStatus | null>(null);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [connection, setConnection] = useState<"connecting" | "live" | "offline">("connecting");
|
const [connection, setConnection] = useState<"connecting" | "live" | "offline">("connecting");
|
||||||
@@ -202,6 +210,17 @@ function Dashboard({ auth, onLoggedOut }: { auth: AuthState; onLoggedOut: () =>
|
|||||||
return () => events.close();
|
return () => events.close();
|
||||||
}, [refresh]);
|
}, [refresh]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const syncPageWithLocation = () => setPage(pageFromLocation());
|
||||||
|
window.addEventListener("hashchange", syncPageWithLocation);
|
||||||
|
return () => window.removeEventListener("hashchange", syncPageWithLocation);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function navigate(nextPage: DashboardPage) {
|
||||||
|
setPage(nextPage);
|
||||||
|
window.location.hash = `/${nextPage}`;
|
||||||
|
}
|
||||||
|
|
||||||
async function logout() {
|
async function logout() {
|
||||||
await post("/api/auth/logout", {}, auth.csrfToken);
|
await post("/api/auth/logout", {}, auth.csrfToken);
|
||||||
await onLoggedOut();
|
await onLoggedOut();
|
||||||
@@ -212,11 +231,11 @@ function Dashboard({ auth, onLoggedOut }: { auth: AuthState; onLoggedOut: () =>
|
|||||||
<aside className="sidebar">
|
<aside className="sidebar">
|
||||||
<div className="brand brand-compact"><Gauge size={30} weight="duotone" /><span>Pi Companion</span></div>
|
<div className="brand brand-compact"><Gauge size={30} weight="duotone" /><span>Pi Companion</span></div>
|
||||||
<nav aria-label="Primary navigation">
|
<nav aria-label="Primary navigation">
|
||||||
<button className={`nav-item ${page === "home" ? "active" : ""}`} onClick={() => setPage("home")}><House size={24} weight={page === "home" ? "fill" : "regular"} /><span>Home</span></button>
|
<button className={`nav-item ${page === "home" ? "active" : ""}`} onClick={() => navigate("home")}><House size={24} weight={page === "home" ? "fill" : "regular"} /><span>Home</span></button>
|
||||||
<button className={`nav-item ${page === "car" ? "active" : ""}`} onClick={() => setPage("car")}><CarProfile size={24} weight={page === "car" ? "fill" : "regular"} /><span>Car</span></button>
|
<button className={`nav-item ${page === "car" ? "active" : ""}`} onClick={() => navigate("car")}><CarProfile size={24} weight={page === "car" ? "fill" : "regular"} /><span>Car</span></button>
|
||||||
<button className={`nav-item ${page === "adb" ? "active" : ""}`} onClick={() => setPage("adb")}><AndroidLogo size={24} weight={page === "adb" ? "fill" : "regular"} /><span>ADB</span></button>
|
<button className={`nav-item ${page === "adb" ? "active" : ""}`} onClick={() => navigate("adb")}><AndroidLogo size={24} weight={page === "adb" ? "fill" : "regular"} /><span>ADB</span></button>
|
||||||
<button className={`nav-item ${page === "network" ? "active" : ""}`} onClick={() => setPage("network")}><WifiHigh size={24} weight={page === "network" ? "fill" : "regular"} /><span>Network</span></button>
|
<button className={`nav-item ${page === "network" ? "active" : ""}`} onClick={() => navigate("network")}><WifiHigh size={24} weight={page === "network" ? "fill" : "regular"} /><span>Network</span></button>
|
||||||
<button className={`nav-item ${page === "settings" ? "active" : ""}`} onClick={() => setPage("settings")}><Gear size={24} weight={page === "settings" ? "fill" : "regular"} /><span>Settings</span></button>
|
<button className={`nav-item ${page === "settings" ? "active" : ""}`} onClick={() => navigate("settings")}><Gear size={24} weight={page === "settings" ? "fill" : "regular"} /><span>Settings</span></button>
|
||||||
</nav>
|
</nav>
|
||||||
<button className="nav-item logout" onClick={() => void logout()}><SignOut size={24} /><span>Sign out</span></button>
|
<button className="nav-item logout" onClick={() => void logout()}><SignOut size={24} /><span>Sign out</span></button>
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
Reference in New Issue
Block a user