Review everything shipped this weekend, and fix what the reviewers caught
Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
@@ -91,7 +91,17 @@ Column {
|
||||
property int draggingIndex: -1
|
||||
property var workingOrder: []
|
||||
|
||||
readonly property var displayed: root.draggingIndex >= 0 ? root.workingOrder : root.pinned
|
||||
// The order the strip is drawing, as rows the Repeater can identify. A
|
||||
// plain array of ids is a NEW model every time the order changes, and
|
||||
// reordering is the one thing this strip does: handing that to a Repeater
|
||||
// resets it and destroys the delegate the pointer is holding, mid-press, on
|
||||
// the first cell crossed. The gesture dies there and draggingIndex stays
|
||||
// set, which latches the strip. Keyed on the pin id -- the only thing a pin
|
||||
// is -- a reorder becomes a row move instead, and the delegate under the
|
||||
// hand survives it. One-property objects because ScriptModel identifies a
|
||||
// row by a property of it, which a bare string has none of.
|
||||
readonly property var displayed: (root.draggingIndex >= 0 ? root.workingOrder : root.pinned)
|
||||
.map(id => ({ id: id }))
|
||||
|
||||
function beginDrag(index: int): void {
|
||||
root.workingOrder = root.pinned.slice();
|
||||
@@ -119,12 +129,23 @@ Column {
|
||||
root.commit(next);
|
||||
}
|
||||
|
||||
// The drag let go of without a decision. Used when the cell being dragged
|
||||
// is destroyed under the pointer -- an unpin from somewhere else, a
|
||||
// settings file rewritten underneath -- where the working order is a
|
||||
// rearrangement of a list that no longer exists, and writing it back would
|
||||
// undo whatever really happened.
|
||||
function cancelDrag(): void {
|
||||
root.draggingIndex = -1;
|
||||
root.workingOrder = [];
|
||||
}
|
||||
|
||||
// ── Keyboard ────────────────────────────────────────────────────────────
|
||||
//
|
||||
// The Repeater's model is a plain array, so committing a move rebuilds
|
||||
// every delegate and the focused one is destroyed mid-keystroke. The
|
||||
// focused position is remembered here instead of in the delegate, and the
|
||||
// cell that lands on it takes focus back as it is created.
|
||||
// Which POSITION has the keyboard, remembered here rather than left to the
|
||||
// delegate that happens to hold focus. Unpinning really does destroy the
|
||||
// focused cell, and a keyed model still cannot keep focus on a row that is
|
||||
// gone; remembering the index means the cell that lands on it takes focus
|
||||
// back as it arrives, so Delete twice in a row deletes twice.
|
||||
|
||||
property int keyboardIndex: -1
|
||||
|
||||
@@ -159,7 +180,13 @@ Column {
|
||||
spacing: root.cellSpacing
|
||||
|
||||
Repeater {
|
||||
model: root.displayed
|
||||
// Keyed on the pin id: see `displayed`. This is the same reason
|
||||
// DockBody keys the dock's own icons.
|
||||
model: ScriptModel {
|
||||
values: root.displayed
|
||||
objectProp: "id"
|
||||
comparisonMode: ObjectComparison.Structure
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
id: cell
|
||||
@@ -167,9 +194,10 @@ Column {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
readonly property string appId: cell.modelData ? cell.modelData.id : ""
|
||||
readonly property bool dragging: root.draggingIndex === cell.index
|
||||
readonly property string appName: root.nameFor(cell.modelData)
|
||||
readonly property string iconSource: root.iconFor(cell.modelData)
|
||||
readonly property string appName: root.nameFor(cell.appId)
|
||||
readonly property string iconSource: root.iconFor(cell.appId)
|
||||
|
||||
width: root.cellSize
|
||||
height: root.cellSize
|
||||
@@ -194,6 +222,12 @@ Column {
|
||||
onActiveFocusChanged: if (cell.activeFocus) root.keyboardIndex = cell.index
|
||||
Component.onCompleted: if (root.keyboardIndex === cell.index) cell.forceActiveFocus()
|
||||
|
||||
// A cell that goes away while it is the one being dragged takes
|
||||
// the release with it -- there is no MouseArea left to report
|
||||
// one -- and the strip would sit there with draggingIndex still
|
||||
// set, refusing every later press.
|
||||
Component.onDestruction: if (cell.dragging) root.cancelDrag()
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onKeyboardIndexChanged(): void {
|
||||
|
||||
Reference in New Issue
Block a user