Enable scroll in lock mode + fix Android storage path - #4755
Conversation
- Home.qml: Added autoScrollTimer (50ms interval) that scrolls the GridView when dragging a tile near the top or bottom viewport edge, with speed proportional to proximity to the edge. - Home.qml: Added indexAtMouse() helper that accounts for contentY offset when computing which tile is under the cursor during drag, fixing incorrect target index when the grid has scrolled. - Home.qml: Fixed active tile visual position to include gridView.contentY so the dragged tile stays visually anchored to the cursor while scrolling. - Home.qml: Track startIndex and tileName at long-press time to correctly identify source tile and compare against drop position at release. - homeform.cpp: Fixed moveTile() edge case where inserting a tile at the last position never wrote its order setting because i only reached newIndex after the loop ended. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Test videoAuto-scroll during tile drag — recorded on Android emulator (pixel6_api34, API 34) with fake treadmill device enabled. The test drags the Speed tile from position 0 (top-left) to the bottom of the screen. The GridView auto-scrolls revealing tiles that were previously below the fold, and Speed is correctly placed at the last position after release. |
Test Video: Tile Auto-Scroll During DragTested on Android emulator (Pixel 6, API 34) with fake treadmill device enabled. What was tested:
DemoTest scenario:
|
1 similar comment
Test Video: Tile Auto-Scroll During DragTested on Android emulator (Pixel 6, API 34) with fake treadmill device enabled. What was tested:
DemoTest scenario:
|
Fix: le altre tile non scompaiono più durante il dragBug risolto: nella versione precedente le tile sparivano durante il drag perché il Soluzione: invece di spostare il tile originale, viene dimmerato (opacity 0.3) e viene mostrato un "ghost tile" separato (esterno al GridView) che segue il cursore. Demo (con fix applicato)Comportamento verificato:
|
Moving the dragged tile's y position within GridView's contentItem coordinate system confused the GridView's virtualization, causing other tiles to disappear during drag. Fix by: - Keeping the source tile in place (just dimming it to opacity 0.3) - Showing a separate ghost Item outside GridView that follows the mouse Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…uring drag The OutBack easing on delegates caused newly-virtualized tiles to animate from y=0 (above the viewport when contentY > 0) to their target position, making them invisible for 400ms during auto-scroll. Since moveTile() rebuilds the entire model via sortTiles() on release (not appModel.move()), these animations served no useful purpose. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix v3: Rimossi Behavior on x/y dal delegateProblema risoltoIl
FixRimossi completamente i Video test(Auto-scroll verso il basso + tile piazzata oltre il viewport — nessuna tile scompare durante il drag) |
|
Video test (fix v3): drag_test_v3.mp4 |
Demo finale: entrambi i bug risoltiVideo pulito (senza debug overlay) che mostra:
Testato su emulatore Android (Pixel 6 API 34) con fake treadmill abilitato. 25 tile attive, drag dall'AVG Watt Lap verso il fondo della lista (grid scrollato da 0 a ~900dp di contentY). |
moveTile() constructed settings keys as "tile_" + m_id.toLower() + "_order",
but several DataObjects use camelCase m_ids (e.g. "avgWattLap") that don't
match the actual QZSettings key ("tile_avg_watt_lap_order"). As a result,
the moved tile's order was written to the wrong settings key and sortTiles()
ignored it, leaving the tile in its original position after drag-and-drop.
Fixed with a static lookup table in moveTile() mapping the mismatched m_ids
to their correct QZSettings order key. Affected tiles:
- avgWattLap → tile_avg_watt_lap_order
- joul → tile_jouls_order
- steeringangle → tile_steering_angle_order
- stride_length → tile_instantaneous_stride_length_order
- external_inclination → tile_ext_incline_order
- target_inclination → tile_target_incline_order
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix v4: moveTile scriveva sulla chiave settings sbagliataBug trovato e risolto
Risultato: la tile veniva "spostata" (il ghost tile seguiva il cursore, l'auto-scroll funzionava) ma dopo il rilascio Fix (commit
|
|
I can't move tiles that are placed out of the screen because the top bar with the unlock button is hiding. Maybe we can add the scroll when you are on unlock mode so we can select other tiles |
In lock mode (lockTiles=true) the GridView's built-in interactive scrolling is disabled to prevent accidental tile drags. This meant any tiles beyond the visible viewport could never be reached. Fix: set `interactive: !window.lockTiles` so built-in scrolling is active only in normal mode, and add a manual scroll handler in the MouseArea's onPositionChanged that moves gridView.contentY when no drag is in progress (currentId === -1). An `isSwiping` flag suppresses long-press-to-drag when the gesture starts as a swipe. Also fix getAndroidDataAppDir() to handle Waydroid/emulator environments where isExternalStorageRemovable() throws IllegalArgumentException: clear the pending JNI exception and fall back to internal storage if external storage resolution fails entirely. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |


Summary
Bug 4 — Scroll in lock mode: In lock mode (
lockTiles=true),GridView.interactiveis set tofalseto prevent accidental drag-to-rearrange during a workout. This had the side-effect of also disabling touch-scrolling, making any tiles beyond the viewport permanently unreachable.interactive: !window.lockTilesso built-in scrolling is only active in normal (drag) mode.onPositionChanged: when no drag is in progress (currentId === -1), each pointer movement adjustsgridView.contentYdirectly, clamped to valid bounds.isSwipingflag so a gesture that starts as a vertical swipe doesn't accidentally triggeronPressAndHolddrag initiation.Android storage fix:
getAndroidDataAppDir()calledisExternalStorageRemovable()which throwsIllegalArgumentExceptionon Waydroid/emulators wherevoldcannot resolve the storage volume. Fix: checkExceptionCheck()after the JNI call, clear any pending exception, and fall back to internal storage if external storage is unavailable.Test plan
Demo video
https://github.com/cagnulein/qdomyos-zwift/releases/download/nightly-2026-07-02/demo_scroll.mp4
🤖 Generated with Claude Code