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 @@ -1309,24 +1309,34 @@ class GameViewModel(

fun changeWindowPositions(
location: WindowLocation,
fromIndex: Int,
name: String,
toIndex: Int,
) {
val windowUiStates = getWindowUiStatesForLocation(location)
var reordered: List<WindowUiState> = emptyList()
var reordered: List<WindowUiState>? = null
windowUiStates.update { states ->
// Reset on entry: update{} may retry.
reordered = null
// The gesture's indices are snapshots, and the dock can change under a drag (the
// game closing a panel mid-drag is the everyday case): resolve the dragged window
// by name against the current list and clamp the drop index. A stale index crashed
// here on a shrunken dock, and a stale-but-in-bounds one would have moved whatever
// window sits at it now.
val fromIndex = states.indexOfFirst { it.name == name }
if (fromIndex == -1) return@update states
val mutableStates = states.toMutableList()
val item = mutableStates.removeAt(fromIndex)
val adjustedToIndex = if (toIndex > fromIndex) toIndex - 1 else toIndex
val adjustedToIndex = (if (toIndex > fromIndex) toIndex - 1 else toIndex).coerceIn(0, mutableStates.size)
mutableStates.add(adjustedToIndex, item)
reordered = mutableStates
mutableStates
}
// The dock's whole order, captured before suspending and written in one transaction:
// per-row writes from the live list could interleave with another reorder and leave
// duplicate positions behind. A transient panel takes part in the reorder on screen but
// records nothing.
val names = reordered.filter { canSaveWindow(it.name) }.map { it.name }
// records nothing, so a dock holding only those has no saved order to rewrite.
val names = reordered?.filter { canSaveWindow(it.name) }?.map { it.name }
if (names.isNullOrEmpty()) return
viewModelScope.launch {
client.characterId.value?.let { characterId ->
logger.d { "Reordering $location: $names" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ class DragDropState {
private set
var sourceLocation: WindowLocation? by mutableStateOf(null)
private set
var sourceIndex: Int by mutableIntStateOf(-1)
private set

var dragOffset: Offset by mutableStateOf(Offset.Zero)
private set

Expand All @@ -32,12 +29,10 @@ class DragDropState {
fun startDrag(
item: WindowUiState,
location: WindowLocation,
index: Int,
offset: Offset,
) {
draggedItem = item
sourceLocation = location
sourceIndex = index
dragOffset = offset
dropTarget = null
}
Expand All @@ -57,7 +52,6 @@ class DragDropState {
DropResult(
name = item.name,
sourceLocation = source,
sourceIndex = sourceIndex,
target = target,
)
} else {
Expand Down Expand Up @@ -124,7 +118,6 @@ class DragDropState {
private fun clearState() {
draggedItem = null
sourceLocation = null
sourceIndex = -1
dragOffset = Offset.Zero
dropTarget = null
}
Expand All @@ -144,6 +137,5 @@ data class SectionInfo(
data class DropResult(
val name: String,
val sourceLocation: WindowLocation,
val sourceIndex: Int,
val target: DropTarget,
)
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ fun DesktopGameView(
if (result.sourceLocation == result.target.location) {
viewModel.changeWindowPositions(
result.sourceLocation,
result.sourceIndex,
result.name,
result.target.insertionIndex,
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,6 @@ private fun DockableSection(
modifier = itemModifier,
uiState = uiState,
location = location,
index = index,
defaultStyle = defaultStyle,
openWindows = openWindows,
isLast = index == windowUiStates.lastIndex,
Expand Down Expand Up @@ -286,7 +285,6 @@ private fun DockableSection(
private fun WindowViewSlot(
uiState: WindowUiState,
location: WindowLocation,
index: Int,
defaultStyle: StyleDefinition,
openWindows: List<String>,
isLast: Boolean,
Expand All @@ -311,12 +309,15 @@ private fun WindowViewSlot(
val headerModifier =
Modifier
.onGloballyPositioned { headerCoordinates.value = it }
.pointerInput(uiState.name, location, index) {
// Keyed on identity only. Keying on the window's index would restart this block -
// cancelling an in-flight drag - whenever a window ahead of it leaves the dock,
// which is exactly when a drag is most likely to be in flight.
.pointerInput(uiState.name, location) {
detectDragGestures(
onDragStart = { offset ->
val coords = headerCoordinates.value ?: return@detectDragGestures
val rootOffset = coords.localToRoot(offset)
dragDropState.startDrag(uiState, location, index, rootOffset)
dragDropState.startDrag(uiState, location, rootOffset)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
},
onDrag = { change, _ ->
change.consume()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ internal fun GameViewModel.onWindowDrop(result: DropResult) {
if (result.sourceLocation == result.target.location) {
changeWindowPositions(
result.sourceLocation,
result.sourceIndex,
result.name,
result.target.insertionIndex,
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ private fun DockableSection(
modifier = itemModifier,
uiState = uiState,
location = location,
index = index,
defaultStyle = defaultStyle,
openWindows = openWindows,
isLast = index == windowUiStates.lastIndex,
Expand Down Expand Up @@ -278,7 +277,6 @@ private fun DockableSection(
private fun WindowViewSlot(
uiState: WindowUiState,
location: WindowLocation,
index: Int,
defaultStyle: StyleDefinition,
openWindows: List<String>,
isLast: Boolean,
Expand All @@ -303,12 +301,15 @@ private fun WindowViewSlot(
val headerModifier =
Modifier
.onGloballyPositioned { headerCoordinates.value = it }
.pointerInput(uiState.name, location, index) {
// Keyed on identity only. Keying on the window's index would restart this block -
// cancelling an in-flight drag - whenever a window ahead of it leaves the dock,
// which is exactly when a drag is most likely to be in flight.
.pointerInput(uiState.name, location) {
detectDragGestures(
onDragStart = { offset ->
val coords = headerCoordinates.value ?: return@detectDragGestures
val rootOffset = coords.localToRoot(offset)
dragDropState.startDrag(uiState, location, index, rootOffset)
dragDropState.startDrag(uiState, location, rootOffset)
},
onDrag = { change, _ ->
change.consume()
Expand Down