mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-29 20:19:56 +00:00
fix connect flow in tray
This commit is contained in:
@@ -51,7 +51,7 @@ All services live in `services/` and assume a build tag `!android && !ios && !fr
|
||||
|
||||
`main.go` registers five typed events for the frontend: `netbird:status` (`Status`), `netbird:event` (`SystemEvent`), `netbird:profile:changed` (`ProfileRef`), `netbird:update:available` (`UpdateAvailable`), `netbird:update:progress` (`UpdateProgress`). `netbird:profile:changed` fires from `ProfileSwitcher.SwitchActive` after a successful daemon-side switch — both the React `ProfileContext` and the tray subscribe so a flip driven from one surface paints in the others (the daemon itself does not emit a profile event). Plus three plain-string events:
|
||||
|
||||
- `EventTriggerLogin = "trigger-login"` — tray asking the frontend's `startLogin()` to begin an SSO flow.
|
||||
- `EventTriggerLogin = "trigger-login"` — tray asking the frontend's `startLogin()` to begin an SSO flow. The tray does **not** show the main window when emitting — the hidden webview is alive and subscribed, so `startLogin` runs and the only visible surface is the BrowserLogin popup it opens.
|
||||
- `EventBrowserLoginCancel = "browser-login:cancel"` — the `BrowserLogin` window's Cancel button or red-X close. `startLogin()` listens and tears down the daemon's pending `WaitSSOLogin`.
|
||||
- `preferences.EventPreferencesChanged = "netbird:preferences:changed"` — emitted after every successful `SetLanguage` (payload `{language}`). Both the tray menu rebuild and the React `i18next.changeLanguage` subscribe so a flip from any window paints everywhere.
|
||||
|
||||
|
||||
@@ -132,8 +132,8 @@ The SSO flow is centralised in a module-level `startLogin()` with a `loginInFlig
|
||||
|
||||
1. `Connection.Login({})` with empty fields — Go fills in active profile + OS user.
|
||||
2. If the daemon needs SSO (`needsSsoLogin`):
|
||||
- `Connection.OpenURL(uri)` opens the verification page in the system browser (honors `$BROWSER`).
|
||||
- `WindowManager.OpenBrowserLogin(uri)` opens the auxiliary "waiting for sign-in" window.
|
||||
- `WindowManager.OpenBrowserLogin(uri)` opens the auxiliary "waiting for sign-in" window (Hidden until React mounts and `useAutoSizeWindow` calls `Window.Show`).
|
||||
- `WaitingForBrowserDialog` mounts, gets shown by `useAutoSizeWindow`, then fires `Connection.OpenURL(uri)` from its mount effect — opens the verification page in the system browser (honors `$BROWSER`). Done from the dialog (not `startLogin`) so the browser doesn't race the still-hidden NetBird popup and land on top.
|
||||
- `Promise.race(WaitSSOLogin, EVENT_BROWSER_LOGIN_CANCEL)` — whichever resolves first.
|
||||
- On cancel: `Connection.Down()` to dislodge the daemon's pending `WaitSSOLogin` so the next Login starts fresh (see `services/connection.go:74`).
|
||||
3. `Connection.Up({})` to bring the new session up.
|
||||
|
||||
@@ -62,16 +62,15 @@ async function startLogin(): Promise<void> {
|
||||
if (result.needsSsoLogin) {
|
||||
const uri = result.verificationUriComplete || result.verificationUri;
|
||||
if (uri) {
|
||||
// Open the in-app sign-in popup first so it's already on
|
||||
// screen when the system browser steals focus; otherwise
|
||||
// the browser lands on top and the user has to dig the
|
||||
// NetBird window back out.
|
||||
// Open the in-app sign-in popup first; the dialog itself
|
||||
// fires Connection.OpenURL after it's actually on screen
|
||||
// (see WaitingForBrowserDialog) so the system browser
|
||||
// doesn't land on top of a still-hidden NetBird window.
|
||||
try {
|
||||
await WindowManager.OpenBrowserLogin(uri);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
Connection.OpenURL(uri).catch(console.error);
|
||||
}
|
||||
|
||||
const cancelPromise = new Promise<void>((resolve) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback } from "react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { Events } from "@wailsio/runtime";
|
||||
@@ -21,6 +21,15 @@ export default function WaitingForBrowserDialog() {
|
||||
const uri = params.get("uri") ?? "";
|
||||
const contentRef = useAutoSizeWindow<HTMLDivElement>(WINDOW_WIDTH);
|
||||
|
||||
// Open the system browser only after the dialog has mounted (which
|
||||
// means useAutoSizeWindow has called Window.Show). startLogin used to
|
||||
// fire OpenURL itself but the browser typically beat React's mount
|
||||
// and landed on top of the still-hidden NetBird popup.
|
||||
useEffect(() => {
|
||||
if (!uri) return;
|
||||
Connection.OpenURL(uri).catch(console.error);
|
||||
}, [uri]);
|
||||
|
||||
const tryAgain = useCallback(() => {
|
||||
if (!uri) return;
|
||||
Connection.OpenURL(uri).catch(console.error);
|
||||
|
||||
@@ -426,18 +426,17 @@ func (t *Tray) openRoute(route string) {
|
||||
func (t *Tray) handleConnect() {
|
||||
// NeedsLogin/SessionExpired/LoginFailed mean the daemon won't honor a
|
||||
// plain Up RPC ("up already in progress: current status NeedsLogin") —
|
||||
// it needs the Login → WaitSSOLogin → Up sequence instead. Hand off
|
||||
// to the React-side startLogin() (which owns the browser-login window
|
||||
// and SSO orchestration) by showing the main window and emitting
|
||||
// EventTriggerLogin. The frontend subscribes in
|
||||
// layouts/ConnectionStatusSwitch.tsx.
|
||||
// it needs the Login → WaitSSOLogin → Up sequence instead. Emit
|
||||
// EventTriggerLogin so the React-side startLogin() (which owns the
|
||||
// BrowserLogin popup) drives the flow. The main window's webview is
|
||||
// alive even while hidden, so we don't surface it — only the popup
|
||||
// appears.
|
||||
t.mu.Lock()
|
||||
needsLogin := strings.EqualFold(t.lastStatus, services.StatusNeedsLogin) ||
|
||||
strings.EqualFold(t.lastStatus, services.StatusSessionExpired) ||
|
||||
strings.EqualFold(t.lastStatus, services.StatusLoginFailed)
|
||||
t.mu.Unlock()
|
||||
if needsLogin {
|
||||
t.ShowWindow()
|
||||
t.app.Event.Emit(services.EventTriggerLogin)
|
||||
return
|
||||
}
|
||||
@@ -625,7 +624,6 @@ func (t *Tray) applyStatus(st services.Status) {
|
||||
t.mu.Unlock()
|
||||
|
||||
if triggerLogin {
|
||||
t.ShowWindow()
|
||||
t.app.Event.Emit(services.EventTriggerLogin)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user