fix: bug keeping location and size of the window
This commit is contained in:
@@ -1010,12 +1010,18 @@ func (a *App) startup(ctx context.Context) {
|
|||||||
go a.liveStatusLoop() // multi-op: heartbeat current activity to shared MySQL
|
go a.liveStatusLoop() // multi-op: heartbeat current activity to shared MySQL
|
||||||
go a.chatLoop() // multi-op: poll the shared chat + heartbeat presence
|
go a.chatLoop() // multi-op: poll the shared chat + heartbeat presence
|
||||||
|
|
||||||
// Reopen where the window was last left (size + position).
|
|
||||||
a.restoreWindowState()
|
|
||||||
|
|
||||||
fmt.Println("OpsLog: db ready at", a.dbPath)
|
fmt.Println("OpsLog: db ready at", a.dbPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// domReady fires once the frontend has painted. The window was created hidden
|
||||||
|
// (StartHidden), so we place it at its saved geometry FIRST and only then show
|
||||||
|
// it — it appears already sized and positioned, never jumping into place after
|
||||||
|
// launch. Show is unconditional: whatever happens above, the window must appear.
|
||||||
|
func (a *App) domReady(ctx context.Context) {
|
||||||
|
a.restoreWindowPosition()
|
||||||
|
wruntime.WindowShow(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
// StartupStatus returns a diagnostic snapshot for the frontend.
|
// StartupStatus returns a diagnostic snapshot for the frontend.
|
||||||
// dbPath is always populated; err is empty when the app is healthy.
|
// dbPath is always populated; err is empty when the app is healthy.
|
||||||
type StartupStatus struct {
|
type StartupStatus struct {
|
||||||
@@ -1353,24 +1359,22 @@ func (a *App) saveWindowState() {
|
|||||||
writeWindowState(a.dataDir, ws)
|
writeWindowState(a.dataDir, ws)
|
||||||
}
|
}
|
||||||
|
|
||||||
// restoreWindowState reopens the window where it was last left. The window is
|
// restoreWindowPosition places the window at its saved X/Y. Size and maximised
|
||||||
// CREATED maximised (WindowStartState in main.go), which is also the first-run
|
// state are already applied at creation (main.go, from options), so only the
|
||||||
// default — so we only act when a windowed geometry was saved, leaving the
|
// position — which options can't express — remains, and it is set here while the
|
||||||
// maximised majority untouched and flash-free.
|
// window is still hidden, so there is no visible jump. Nothing to do for a
|
||||||
func (a *App) restoreWindowState() {
|
// maximised or first-run window.
|
||||||
|
func (a *App) restoreWindowPosition() {
|
||||||
if a.ctx == nil {
|
if a.ctx == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ws, ok := readWindowState(a.dataDir)
|
ws, ok := readWindowState(a.dataDir)
|
||||||
if !ok || ws.Maximised {
|
if !ok || ws.Maximised {
|
||||||
return // first run, or last closed maximised — the default already covers it
|
|
||||||
}
|
|
||||||
// Guard against a corrupt / absurd size that would open an unusable window.
|
|
||||||
if ws.Width < normalMinW || ws.Height < normalMinH || ws.Width > maxW || ws.Height > maxH {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
wruntime.WindowUnmaximise(a.ctx)
|
if ws.Width < normalMinW || ws.Height < normalMinH || ws.Width > maxW || ws.Height > maxH {
|
||||||
wruntime.WindowSetSize(a.ctx, ws.Width, ws.Height)
|
return // corrupt / absurd — leave the default placement
|
||||||
|
}
|
||||||
wruntime.WindowSetPosition(a.ctx, ws.X, ws.Y)
|
wruntime.WindowSetPosition(a.ctx, ws.X, ws.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,19 +49,40 @@ func main() {
|
|||||||
app := NewApp()
|
app := NewApp()
|
||||||
app.startupProfile = profileArg(os.Args[1:])
|
app.startupProfile = profileArg(os.Args[1:])
|
||||||
|
|
||||||
|
// Restore the window's SIZE and maximised state at CREATION, from the geometry
|
||||||
|
// saved on last close. Doing it here (not after startup) is what makes the
|
||||||
|
// window open already at the right size instead of maximising then snapping
|
||||||
|
// smaller. Position can't be set through options, so it is applied while the
|
||||||
|
// window is still hidden (domReady) — invisible, so no jump. First run, or a
|
||||||
|
// window closed maximised, keeps the historical maximised default.
|
||||||
|
width, height := 1400, 900
|
||||||
|
startState := options.Maximised
|
||||||
|
if dataDir, err := userDataDir(); err == nil {
|
||||||
|
if ws, ok := readWindowState(dataDir); ok && !ws.Maximised &&
|
||||||
|
ws.Width >= 1100 && ws.Height >= 700 && ws.Width <= 8000 && ws.Height <= 6000 {
|
||||||
|
width, height = ws.Width, ws.Height
|
||||||
|
startState = options.Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create application with options
|
// Create application with options
|
||||||
err := wails.Run(&options.App{
|
err := wails.Run(&options.App{
|
||||||
Title: "OpsLog",
|
Title: "OpsLog",
|
||||||
Width: 1400,
|
Width: width,
|
||||||
Height: 900,
|
Height: height,
|
||||||
MinWidth: 1100,
|
MinWidth: 1100,
|
||||||
MinHeight: 700,
|
MinHeight: 700,
|
||||||
WindowStartState: options.Maximised,
|
WindowStartState: startState,
|
||||||
|
// Start hidden and reveal only once the saved position has been applied and
|
||||||
|
// the DOM has painted (OnDomReady → domReady) — so the window appears
|
||||||
|
// already at its final size and position, with no post-launch jump.
|
||||||
|
StartHidden: true,
|
||||||
AssetServer: &assetserver.Options{
|
AssetServer: &assetserver.Options{
|
||||||
Assets: assets,
|
Assets: assets,
|
||||||
},
|
},
|
||||||
BackgroundColour: &options.RGBA{R: 250, G: 250, B: 249, A: 1},
|
BackgroundColour: &options.RGBA{R: 250, G: 250, B: 249, A: 1},
|
||||||
OnStartup: app.startup,
|
OnStartup: app.startup,
|
||||||
|
OnDomReady: app.domReady,
|
||||||
OnBeforeClose: app.beforeClose,
|
OnBeforeClose: app.beforeClose,
|
||||||
OnShutdown: app.shutdown,
|
OnShutdown: app.shutdown,
|
||||||
Bind: []interface{}{
|
Bind: []interface{}{
|
||||||
|
|||||||
Reference in New Issue
Block a user