Files
plezy/lib/focus/focusable_tile_mixin.dart
T
edde746 316a69a1de refactor: share the paginated grid tab, cached remote store, and tile focus
- PaginatedCardGridTabState: the collections and playlists tabs were 95%
  identical; they now supply only pageSize/fetchPage/idOf instead of each
  duplicating the grid, memo, inflation budget and focus wiring.
- EtagCachedRemoteStore: the anime-lists and fribb mapping stores now share
  one download/cache/isolate-parse/conditional-GET lifecycle.
- FocusableTileStateMixin manages its own initState/didUpdateWidget/dispose
  instead of requiring every caller to forward three lifecycle hooks.

Also drops unused ServerCapabilities entries and dead code in
focusable_list_tile and music/track_row.
2026-07-26 06:09:48 +02:00

47 lines
1.1 KiB
Dart

import 'package:flutter/material.dart';
import '../utils/scroll_utils.dart';
import 'owned_focus_node_binding.dart';
/// Manages the internal/external FocusNode lifecycle for list-tile widgets and
/// auto-scrolls the tile into view when it gains focus.
mixin FocusableTileStateMixin<T extends StatefulWidget> on State<T> {
final _focusNodeBinding = OwnedFocusNodeBinding();
FocusNode? _boundExternalNode;
FocusNode? get widgetFocusNode;
FocusNode get effectiveFocusNode => _focusNodeBinding.node;
@override
void initState() {
super.initState();
_bindFocusNode();
}
@override
void didUpdateWidget(T oldWidget) {
super.didUpdateWidget(oldWidget);
if (_boundExternalNode != widgetFocusNode) {
_bindFocusNode();
}
}
@override
void dispose() {
_focusNodeBinding.dispose();
super.dispose();
}
void _bindFocusNode() {
_boundExternalNode = widgetFocusNode;
_focusNodeBinding.bind(externalNode: widgetFocusNode, listener: _onFocusChange);
}
void _onFocusChange() {
if (effectiveFocusNode.hasFocus) {
scrollContextToCenter(context);
}
}
}