mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-03 12:09:09 +02:00
add os detection
This commit is contained in:
@@ -27,7 +27,7 @@ React 18 + TS 5.7 (`strict`, `noImplicitAny: false`) + Vite 6 + Tailwind 3 (`dar
|
||||
| `/dialog/install-progress` | `UpdateInProgressDialog` (modules/auto-update/) | none | Auxiliary window (Go `WindowManager.OpenInstallProgress(version)`, always-on-top). Owns the install-result polling + 5s daemon-down-grace; calls `Update.Quit()` on success. Opened by `ClientVersionContext.triggerUpdate` (enforced user-driven branch) and on the `installing` flip from `netbird:update:state` (force-install branch). |
|
||||
| `/dialog/session-expired` | `SessionExpiredDialog` (modules/session/) | none | Auxiliary window (Go `WindowManager.OpenSessionExpired`, always-on-top) |
|
||||
| `/dialog/session-about-to-expire` | `SessionAboutToExpireDialog` (modules/session/) | none | Auxiliary window (Go `WindowManager.OpenSessionAboutToExpire(seconds)`, always-on-top, mm:ss countdown via `?seconds=`) |
|
||||
| `/settings` | `SettingsPage` (modules/settings/) | `AppLayout` | Auxiliary window (Go `WindowManager.OpenSettings(tab)`). Inherits the shared provider stack from `AppLayout`; the page itself adds the draggable strip + tabs. The `Profiles` tab (`modules/profiles/ProfilesTab.tsx`, `UserCircle` icon, between Security and SSH) lists profiles in a table with Deregister/Delete in a per-row kebab and an Add Profile button. The header `ProfileDropdown`'s "Manage Profiles" entry calls `OpenSettings("profiles")` — `Settings.tsx` reads `?tab=` via `useSearchParams` so the window opens at that tab. |
|
||||
| `/settings` | `SettingsPage` (modules/settings/) | `AppLayout` | Auxiliary window (Go `WindowManager.OpenSettings(tab)`). Inherits the shared provider stack from `AppLayout`; the page itself adds the draggable strip + tabs. The `Profiles` tab (`modules/profiles/ProfilesTab.tsx`, `UserCircle` icon, between Security and SSH) lists profiles in a table with Deregister/Delete in a per-row kebab and an Add Profile button. The header `ProfileDropdown`'s "Manage Profiles" entry calls `OpenSettings("profiles")`. The window stays at `/#/settings` for its whole lifetime — no `SetURL` between opens, so `AppLayout`'s providers never remount. Tab is React local state, driven by the `netbird:settings:open` event Go emits before `Show`. Reset-to-General on close is handled in React via `document.visibilitychange` (Page Visibility API), which fires *before* WebKit throttles the hidden page, unlike Wails events from the Go close hook which race `Hide` and leave the previous tab visible for one frame on the next open. |
|
||||
| `*` | `<Navigate to="/">` | `AppLayout` | Catch-all |
|
||||
|
||||
In `app.tsx` the four dialog routes are nested under a parent `<Route path="dialog">` so the table reads as a tree, not a flat list. The Go side mirrors the prefix — `WindowManager` opens windows at `/#/dialog/<name>`. The `dialog` group has no shared layout component; it's purely a URL grouping.
|
||||
@@ -84,6 +84,7 @@ Subscribe with `Events.On(name, handler)`. The handler receives `{ data: <typed
|
||||
| `netbird:update:state` | `UpdateState` | `services/peers.go fanOutUpdateEvents` + the updater's `progress_window:show` translator | `modules/auto-update/ClientVersionContext` — single source of truth for `updateAvailable / version / enforced / installing`. |
|
||||
| `browser-login:cancel` | (no payload) | `BrowserLogin` page (frontend) when user clicks Cancel **or** Go `services/windowmanager.go` when user closes the BrowserLogin window | `pages/main/ConnectionStatusSwitch.tsx`'s `startLogin()` to abort the in-flight `WaitSSOLogin` |
|
||||
| `trigger-login` | (no payload) | Reserved (`services.EventTriggerLogin`); `pages/main/ConnectionStatusSwitch.tsx` subscribes and runs `startLogin()` when fired. No Go-side emitter today. |
|
||||
| `netbird:settings:open` | `string` (tab id, e.g. `"general"`, `"profiles"`) | `services/windowmanager.go OpenSettings` (before Go calls `Show`) | `modules/settings/SettingsPage.tsx` — just `setActive(e.data)`. Reset-on-close is **not** driven by this event — see the `visibilitychange` listener in the same file. |
|
||||
|
||||
If you wire a new daemon-event subscriber on the TS side, prefer subscribing once at the context level rather than per-screen — the Wails event bus is process-wide and each `Events.On` adds an emit-time fan-out.
|
||||
|
||||
|
||||
@@ -13,16 +13,21 @@ import "react-loading-skeleton/dist/skeleton.css";
|
||||
import { welcome } from "@/lib/welcome";
|
||||
import LoginWaitingForBrowserDialog from "@/modules/login/LoginWaitingForBrowserDialog.tsx";
|
||||
import { initI18n } from "@/lib/i18n";
|
||||
import { initPlatform } from "@/lib/platform";
|
||||
|
||||
welcome();
|
||||
|
||||
initI18n()
|
||||
.catch((e) => {
|
||||
Promise.all([
|
||||
initI18n().catch((e) => {
|
||||
// Surface init failures in the console so a misconfigured glob
|
||||
// doesn't quietly blank the UI; render anyway with i18next in
|
||||
// whatever state it ended up in (t() will fall back to keys).
|
||||
console.error("i18n init failed:", e);
|
||||
})
|
||||
}),
|
||||
initPlatform().catch((e) => {
|
||||
console.error("platform init failed:", e);
|
||||
}),
|
||||
])
|
||||
.finally(() => {
|
||||
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { System } from "@wailsio/runtime";
|
||||
|
||||
export type Platform = {
|
||||
isWindows11: boolean;
|
||||
isMacOS: boolean;
|
||||
isOtherOS: boolean;
|
||||
};
|
||||
|
||||
let cached: Platform | null = null;
|
||||
|
||||
// Windows 11 is Windows NT 10.0 with build number >= 22000.
|
||||
function parseWindows11(version: string): boolean {
|
||||
const match = version.match(/(\d+)\.(\d+)\.(\d+)/);
|
||||
if (!match) return false;
|
||||
return parseInt(match[3], 10) >= 22000;
|
||||
}
|
||||
|
||||
export async function initPlatform(): Promise<void> {
|
||||
if (cached) return;
|
||||
const isMacOS = System.IsMac();
|
||||
const isWindows = System.IsWindows();
|
||||
let isWindows11 = false;
|
||||
if (isWindows) {
|
||||
const env = await System.Environment();
|
||||
isWindows11 = parseWindows11(env.OSInfo?.Version ?? "");
|
||||
}
|
||||
cached = {
|
||||
isWindows11,
|
||||
isMacOS,
|
||||
isOtherOS: !isMacOS && !isWindows11,
|
||||
};
|
||||
}
|
||||
|
||||
function get(): Platform {
|
||||
if (!cached) {
|
||||
throw new Error("platform: initPlatform() must complete before sync getters are used");
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
|
||||
export const getPlatform = (): Platform => get();
|
||||
export const isWindows11 = (): boolean => get().isWindows11;
|
||||
export const isMacOS = (): boolean => get().isMacOS;
|
||||
export const isOtherOS = (): boolean => get().isOtherOS;
|
||||
Reference in New Issue
Block a user