Skip to content

fix(spaces): make rail reorder & folders work on touch#121

Merged
krazyjakee merged 3 commits into
masterfrom
claude/brave-nightingale-c5e511
Jun 12, 2026
Merged

fix(spaces): make rail reorder & folders work on touch#121
krazyjakee merged 3 commits into
masterfrom
claude/brave-nightingale-c5e511

Conversation

@krazyjakee

Copy link
Copy Markdown
Contributor

Summary

The space rail's folder/reorder feature was fully implemented (model, persistence, drag targets) but its gestures were bound in a way that broke it on mobile:

  • The management menu — new folder, move in/out of folders, leave — opened only on double-tap or right-click. Touch has no right-click, and double-tap-for-a-menu is non-standard and undiscoverable, so on Android creating a folder was effectively unreachable.
  • Long-press was consumed by drag instead of opening a menu, the opposite of the universal mobile "show actions" convention.
  • Desktop also leaned on a non-standard double-tap-for-menu.

This re-binds the rail gestures to platform conventions, Discord-style.

What changed

  • New _RailDraggable widget (replaces the old _railDraggable helper):
    • Touch: LongPressDraggable — long-press lifts the icon to drag (with haptic on pickup). A long-press released in place without dragging opens the item's management menu at that point — the discoverable home for it on touch.
    • Desktop: immediate click-drag, unchanged.
  • Dropping a space onto another space now creates a folder containing both (Discord grouping). Reordering still happens by dropping into the insertion gaps between tiles, which already existed.
  • Menus re-bound to conventions: long-press (touch) / right-click (desktop) across spaces, folders, and folder members. Double-tap dropped everywhere.
  • Simplified _DraggableSpace and _FolderMemberTile to StatelessWidget (the menu-anchor state now lives in _RailDraggable).

Why

Reported: on Android you can't long-press spaces to reorder, move them into folders, or create folders. Root cause was gesture binding, not missing functionality — this restores all three on touch while keeping desktop behavior intact.

Reviewer notes

  • flutter analyze --no-fatal-infos on both changed files: No issues found.
  • Not yet verified on a physical Android device. The long-press-drag vs. finger-scroll interaction inside the rail's ListView is worth a quick manual check on hardware before merge.

Test plan

  • Android: long-press a space → it lifts (haptic); drag to reorder via the gaps; drop one space onto another → folder is created
  • Android: long-press + release in place → management menu appears (New folder / Move / Leave)
  • Android: tap still selects a space; tapping a folder toggles collapse
  • Desktop: click-drag reorders; drop-on-space creates a folder; right-click opens the menu
  • Folder members: drag out onto a rail space leaves the folder; long-press/right-click opens the member menu

🤖 Generated with Claude Code

krazyjakee and others added 2 commits June 12, 2026 20:45
The space rail's folder/reorder feature was fully built but bound to
gestures that mismatched mobile: the management menu (new folder, move
in/out, leave) opened only on double-tap or right-click, so on Android
folder creation was effectively unreachable, and long-press was consumed
by drag instead of opening a menu.

Re-bind to platform conventions, Discord-style:
- New _RailDraggable: on touch, a long-press lifts the icon to drag (with
  haptic); a long-press released in place opens the management menu — the
  discoverable home for it on touch. Desktop keeps immediate click-drag.
- Dropping a space onto another space now groups them into a new folder;
  reordering happens via the existing insertion gaps between tiles.
- Menus open on long-press (touch) / right-click (desktop); double-tap
  dropped everywhere.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add HapticFeedback.mediumImpact() on drag start in _RailDraggableState
  (PR description promised "haptic on pickup" but it was not wired up)
- Reduce the _moved detection threshold from 24 px to 8 px so a short
  drag that misses all drop targets no longer accidentally opens the
  context menu (8 px is above typical touch jitter ~4 px and well below
  any intentional reorder movement)
- Add unit tests for createFolder, moveSpaceToFolder, and setSpaceOrder
  — all three are exercised by the new merge-on-drop behaviour and were
  previously untested

https://claude.ai/code/session_01Adf1XcJE5kgwZNYmzz3XHF

Copy link
Copy Markdown
Contributor Author

Code Review — findings & fixes (commit 44b908b)

All fixes were pushed directly to this branch. Findings ranked by severity:


🔴 HIGH — Missing haptic feedback on drag start

File: lib/features/spaces/views/accord_home_rail_tiles.dart_RailDraggableState

The PR description explicitly says "long-press lifts the icon to drag (with haptic on pickup)", but onDragStarted only reset _moved — no HapticFeedback call was present. Added HapticFeedback.mediumImpact() in onDragStarted.


🟡 MEDIUM — _moved threshold too large; short drag + miss opens menu

File: same — onDragUpdate

The condition (d.globalPosition - _downPos).distance > 24 meant a drag of ≤ 23 px that missed all drop targets (e.g. releasing slightly off a tile) would fall through to onDragEnd with !_moved && !wasAccepted — opening the context menu when the user clearly intended to drag. Touch jitter during a long-press-and-release is typically ≤ 4 px; any intentional reorder requires moving at least half a tile (~27 px). Reduced threshold from 24 → 8 px to close the false-positive window.


🟡 MEDIUM — No tests for createFolder, moveSpaceToFolder, setSpaceOrder

File: test/features/settings/settings_controller_test.dart

These three methods are directly exercised by the new merge-on-drop behaviour (the onMergeSpace callback calls createFolder(spaceIds: [target, dragged])), but had zero test coverage. Added 11 new unit tests covering:

  • setSpaceOrder — persists ordering; overwrites a previous order
  • createFolder — creates with name/ids; returns the id; strips spaces from any existing folder; merge scenario (target-first ordering); moving a space already in a folder
  • moveSpaceToFolder — appends; inserts before a member; removes to null; prunes empty folders; cross-folder move

ℹ️ Notes (no code change needed)

  • File sizes: both changed files are well under 1 000 lines (tiles: 775 lines, rail: 455 lines) — no split required.
  • No 3D/visual rendering changes in this PR — visual review step skipped.
  • Desktop path unchanged: _immediateDrag short-circuits to a plain Draggable with no onPressMenu wiring, so the right-click-only desktop flow is unaffected by the threshold/haptic changes.
  • The onMergeSpace argument order [space.id, movedId] (target first, dragged second) is correct — the target space anchors the new folder's first position, matching the Discord-style grouping intent described in the PR.

Generated by Claude Code

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@krazyjakee krazyjakee merged commit 1a5d853 into master Jun 12, 2026
2 checks passed
@krazyjakee krazyjakee deleted the claude/brave-nightingale-c5e511 branch June 12, 2026 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants