Skip to content

Crabwalking - Bringing back horizontal library navigation#398

Open
mattsigal wants to merge 3 commits into
Moonfin-Client:mainfrom
mattsigal:feat/horizontal-library-navigation
Open

Crabwalking - Bringing back horizontal library navigation#398
mattsigal wants to merge 3 commits into
Moonfin-Client:mainfrom
mattsigal:feat/horizontal-library-navigation

Conversation

@mattsigal

Copy link
Copy Markdown
Contributor

Re-incorporates horizontal library views for people with those wide monitors.

Summary

Reintroduces horizontal scroll direction as a per-library display option. Each library independently remembers its scroll direction preference. When horizontal mode is active, the grid scrolls left-to-right (columns fill top-to-bottom first), the mouse wheel is remapped to horizontal, and desktop users get ‹/› chevron controls matching the home-screen row style. And I remembered localization!

Related Issues

Link related issues or tickets separated by commas.

Discord observation.

  • Closes #
  • Fixes #
  • Related to #

Type of Change

  • Bug fix
  • New feature
  • Refactor
  • Performance improvement
  • UI/UX update
  • Documentation update
  • Build/CI change
  • Other (describe):

Changes Made

List the key changes included in this PR.

  • Added LibraryScrollDirection enum (vertical / horizontal) to preference_constants.dart
  • Added libraryScrollDirection(libraryId) per-library EnumPreference factory to user_preferences.dart (key: library_scroll_dir_, default: vertical)
  • Wired _scrollDirection field, getter, constructor init, and setScrollDirection() into LibraryBrowseViewModel
  • Added Scroll Direction as the first section in the library Display Settings cog (above Image Type), with Vertical/Horizontal radio tiles styled to match existing options
  • Split _buildGrid() into _buildVerticalGrid() (unchanged behaviour) and _buildHorizontalGrid() (new horizontal CustomScrollView):
    • Card dimensions match vertical mode exactly (_cardWidth() / ar for image height, correct childAspectRatio = height/width for horizontal SliverGrid)
    • Mouse wheel vertical delta is remapped to horizontal scroll via a Listener
    • ClampingScrollPhysics preserves the leading padding when scrolling back to the start
    • Desktop (non-TV) shows ‹/› IconButton chevrons above the grid, right-aligned, matching the home-screen row pattern
  • Added scrollDirection, scrollDirectionVertical, scrollDirectionHorizontal l10n keys to app_en.arb; all locale stubs auto-generated

Platform

  • Android
  • iOS
  • macOS
  • Windows
  • Linux
  • All / Shared code

Testing

Tested via Windows installer build on desktop.

  • Tested on emulator / simulator
  • Tested on physical device
  • Manual testing completed
  • Not tested (explain why):

Test Steps

  1. Open any non-book, non-music library → tap the ⚙️ gear icon → confirm Scroll Direction appears as the first section with Vertical selected by default
  2. Select Horizontal
  3. Scroll right with the mouse wheel and should scroll horizontally
  4. Scroll back left and confirm the left padding is preserved
  5. Confirm ‹ and › chevron buttons appear in the upper-right area above the grid and scroll the view in 480 px increments
  6. Open a different library — confirm it independently defaults to Vertical (setting is per-library, not global)
  7. Switch back to Vertical — confirm normal grid resumes with no visual artifacts

Screenshots (if applicable)

Include screenshots or recordings for UI changes.

2026-06-06_11-23-55_moonfin 2026-06-06_11-23-47_moonfin 2026-06-06_11-24-01_moonfin 2026-06-06_11-24-18_moonfin

Checklist

  • Code builds successfully
  • Code follows project style and conventions
  • No unnecessary commented-out code
  • No new warnings introduced

mattsigal added 3 commits June 6, 2026 11:14
…lay settings

- Add LibraryScrollDirection enum (vertical/horizontal) to preference_constants.dart
- Add libraryScrollDirection() per-library preference factory to user_preferences.dart (key: library_scroll_dir_<libraryId>, default: vertical)
- Wire _scrollDirection field, getter, constructor init, and setScrollDirection() into LibraryBrowseViewModel
- Add 'Scroll Direction' section as first option in the library Display Settings cog, above Image Type, with Vertical/Horizontal radio tiles matching existing style
- Split _buildGrid() into _buildVerticalGrid() (existing behavior) and _buildHorizontalGrid() (new Axis.horizontal CustomScrollView with auto row count calculated from available height)
- Add scrollDirection, scrollDirectionVertical, scrollDirectionHorizontal l10n keys to app_en.arb; auto-generated all locale stubs
…el, chevrons, padding

- Fix Moonfin-Client#1 (card sizing): use _cardWidth() as target cell HEIGHT instead of image width
  so poster-size preference scales correctly for all aspect ratios (Poster/Thumb/Banner)
- Fix Moonfin-Client#2 (scroll wheel): wrap horizontal CustomScrollView in Listener that redirects
  vertical PointerScrollEvent.scrollDelta.dy to horizontal scroll offset
- Fix Moonfin-Client#3 (chevrons): overlay left/right _HorizontalScrollChevron buttons on desktop
  (non-TV) matching home-screen row pattern; fade out when at scroll boundary
- Fix Moonfin-Client#4 (leading padding): ClampingScrollPhysics() prevents rubber-banding past
  offset 0 so SliverPadding leading gap is preserved on scroll-back
- Add missing package:flutter/gestures.dart import for PointerScrollEvent
…evron style

- Poster sizing: use _cardWidth()/ar as target image height so cards match
  vertical-mode dimensions exactly; fix childAspectRatio to height/width
  (correct formula for horizontal SliverGrid where cross=height, main=width)
- Gray overlay: remove Stack/Positioned/Opacity chevron overlay from inside
  _buildHorizontalGrid() which was causing the translucent gray tint
- Chevrons: move to _buildBody() as a simple right-aligned Row with
  Icons.chevron_left/chevron_right + VisualDensity.compact, matching the
  home-screen _buildTitledRow pattern exactly; shown only when horizontal
  mode is active on desktop (non-TV)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant