Release 3.8.2.6: perceived-speed UX — search, tray hide, core warm, SSE.
Server search/hotkeys; Windows close-to-tray; background EnsureCore; SSE status with rare poll fallback. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+39
-6
@@ -39,9 +39,11 @@ type App struct {
|
||||
Pings []netcheck.Result
|
||||
OpenURL func(string) error
|
||||
OnAfterUpdate func()
|
||||
OnQuit func()
|
||||
APIToken string
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
events *eventBroker
|
||||
}
|
||||
|
||||
type UIState struct {
|
||||
@@ -81,11 +83,12 @@ type PingBestResult struct {
|
||||
func New(mgr *core.Manager, cfgPath string, logBuf *logbuf.Buffer) *App {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return &App{
|
||||
Mgr: mgr,
|
||||
Mgr: mgr,
|
||||
CfgPath: cfgPath,
|
||||
LogBuf: logBuf,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
LogBuf: logBuf,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
events: newEventBroker(),
|
||||
UpdateStatus: update.Status{
|
||||
Current: update.DisplayVersion(),
|
||||
ManifestURL: update.DefaultManifestURL,
|
||||
@@ -257,8 +260,13 @@ func (a *App) CreateProfile(name, proxy string, systemProxy bool) error {
|
||||
|
||||
func (a *App) SelectProfile(name string) error {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
return a.Mgr.SetActiveProfile(name)
|
||||
err := a.Mgr.SetActiveProfile(name)
|
||||
a.mu.Unlock()
|
||||
if err == nil {
|
||||
go a.warmActiveCore()
|
||||
a.NotifyState("profile")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *App) DeleteProfile(name string) error {
|
||||
@@ -305,6 +313,7 @@ func (a *App) ConnectProfile(name string) error {
|
||||
for attempt := 0; attempt < 2; attempt++ {
|
||||
if _, err := a.Mgr.EnsureCore(""); err != nil {
|
||||
a.Mgr.SetLastError(err.Error())
|
||||
a.NotifyState("error")
|
||||
return err
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
|
||||
@@ -320,6 +329,7 @@ func (a *App) ConnectProfile(name string) error {
|
||||
pcancel()
|
||||
if perr == nil {
|
||||
dockicon.SetConnected(true)
|
||||
a.NotifyState("connected")
|
||||
return nil
|
||||
}
|
||||
last = fmt.Errorf("туннель не прошёл проверку: %w", perr)
|
||||
@@ -329,12 +339,14 @@ func (a *App) ConnectProfile(name string) error {
|
||||
time.Sleep(400 * time.Millisecond)
|
||||
}
|
||||
dockicon.SetConnected(false)
|
||||
a.NotifyState("error")
|
||||
return last
|
||||
}
|
||||
|
||||
func (a *App) Disconnect() error {
|
||||
err := a.Mgr.Disconnect()
|
||||
dockicon.SetConnected(false)
|
||||
a.NotifyState("disconnected")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -367,6 +379,7 @@ func (a *App) SavePrefs(connectOnLaunch, autoReconnect, systemProxy bool) error
|
||||
func (a *App) StartBackground() {
|
||||
go a.watchdogLoop()
|
||||
go a.dockIconLoop()
|
||||
go a.warmActiveCore()
|
||||
prefs := a.Mgr.Prefs()
|
||||
if prefs.ConnectOnLaunch {
|
||||
go func() {
|
||||
@@ -383,6 +396,20 @@ func (a *App) StartBackground() {
|
||||
}
|
||||
}
|
||||
|
||||
// warmActiveCore downloads/resolves the binary for the active profile protocol.
|
||||
// Non-blocking; Connect still EnsureCore if this has not finished yet.
|
||||
func (a *App) warmActiveCore() {
|
||||
select {
|
||||
case <-a.ctx.Done():
|
||||
return
|
||||
case <-time.After(350 * time.Millisecond):
|
||||
}
|
||||
if _, err := a.Mgr.EnsureCore(""); err != nil {
|
||||
// Soft fail — Connect will surface the error if the user tries.
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) dockIconLoop() {
|
||||
dockicon.SetConnected(false)
|
||||
var last bool
|
||||
@@ -620,6 +647,7 @@ func (a *App) Handler() http.Handler {
|
||||
}
|
||||
_, _ = io.WriteString(w, html)
|
||||
})
|
||||
mux.HandleFunc("/api/events", a.handleEvents)
|
||||
mux.HandleFunc("/api/", a.handleAPI)
|
||||
return mux
|
||||
}
|
||||
@@ -721,6 +749,11 @@ func (a *App) dispatch(name string, args []json.RawMessage) (any, error) {
|
||||
go func() {
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
_ = a.Mgr.Disconnect()
|
||||
a.Shutdown()
|
||||
if a.OnQuit != nil {
|
||||
a.OnQuit()
|
||||
return
|
||||
}
|
||||
os.Exit(0)
|
||||
}()
|
||||
return "ok", nil
|
||||
|
||||
Reference in New Issue
Block a user