Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.isSpecified
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowPosition
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.application
import com.openai.snapo.desktop.di.AppGraph
import com.openai.snapo.desktop.ui.SnapOContextMenuProviders
Expand Down Expand Up @@ -50,8 +55,12 @@ fun main() {
}
}

fun openNewWindow() {
windows.add(createInspectorWindow())
fun openNewWindow(parentState: WindowState?) {
val initialPosition = parentState
?.position
?.takeIf { it.isSpecified && it.x.isSpecified && it.y.isSpecified }
?.let { WindowPosition(it.x + NewWindowOffset, it.y + NewWindowOffset) }
windows.add(createInspectorWindow(initialPosition = initialPosition))
Comment on lines +59 to +63

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid persisting offset positions for new windows

Because every window still writes to the same preferences node, creating a new window with an offset initialPosition causes that offset to be persisted even if the user never moves the new window. Opening a new window a few times will overwrite the stored default position and make subsequent launches (and other windows) drift by 100dp per open, potentially ending up off-screen. Consider skipping persistence for secondary windows or storing per-window prefs so the offset is only a launch-time hint.

Useful? React with 👍 / 👎.

}

fun closeWindow(window: InspectorWindow) {
Expand All @@ -64,15 +73,15 @@ fun main() {

windows.forEach { window ->
key(window.id) {
val windowState = rememberPersistedWindowState()
val windowState = rememberPersistedWindowState(initialPosition = window.initialPosition)
Window(
onCloseRequest = { closeWindow(window) },
title = "Snap-O Network Inspector",
state = windowState,
) {
SnapOMenuBar(
controller = updateController,
onNewWindow = ::openNewWindow,
onNewWindow = { openNewWindow(windowState) },
onCheckForUpdates = {
scope.launch {
updateController.checkForUpdates(UpdateCheckSource.Manual)
Expand Down Expand Up @@ -118,8 +127,14 @@ private fun openSnapOUpdate() {
private data class InspectorWindow(
val id: String = UUID.randomUUID().toString(),
val graph: AppGraph,
val initialPosition: WindowPosition? = null,
)

private fun createInspectorWindow(): InspectorWindow {
return InspectorWindow(graph = createGraph<AppGraph>())
private fun createInspectorWindow(initialPosition: WindowPosition? = null): InspectorWindow {
return InspectorWindow(
graph = createGraph<AppGraph>(),
initialPosition = initialPosition,
)
}

private val NewWindowOffset: Dp = 100.dp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.ui.window.WindowPlacement
import androidx.compose.ui.window.WindowPosition
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.rememberWindowState
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import java.util.prefs.Preferences
Expand All @@ -30,18 +31,24 @@ private data class WindowPreferences(
)

@Composable
internal fun rememberPersistedWindowState(): WindowState {
internal fun rememberPersistedWindowState(initialPosition: WindowPosition? = null): WindowState {
val prefs = remember { Preferences.userRoot().node(WindowPrefNode) }
val storedPreferences = remember { loadWindowPreferences(prefs) }
val startingPosition = if (initialPosition != null && initialPosition.isSpecified) {
initialPosition
} else {
storedPreferences.position
}
val windowState = rememberWindowState(
placement = storedPreferences.placement,
position = storedPreferences.position,
position = startingPosition,
size = storedPreferences.size,
)
PersistWindowStateEffect(windowState = windowState, prefs = prefs)
return windowState
}

@OptIn(FlowPreview::class)
@Composable
private fun PersistWindowStateEffect(windowState: WindowState, prefs: Preferences) {
LaunchedEffect(windowState, prefs) {
Expand Down