refactor: codebase review cleanup
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../widgets/media_context_menu.dart';
|
||||
|
||||
/// Tracks tap position and exposes show-context-menu helpers for media cards
|
||||
/// that wrap their tappable area in a [MediaContextMenu].
|
||||
mixin ContextMenuTapMixin<T extends StatefulWidget> on State<T> {
|
||||
final GlobalKey<MediaContextMenuState> contextMenuKey = GlobalKey<MediaContextMenuState>();
|
||||
Offset? _tapPosition;
|
||||
|
||||
void storeTapPosition(TapDownDetails details) {
|
||||
_tapPosition = details.globalPosition;
|
||||
}
|
||||
|
||||
bool get isContextMenuOpen => contextMenuKey.currentState?.isContextMenuOpen ?? false;
|
||||
|
||||
/// Show at the last tap position (long-press, mouse).
|
||||
void showContextMenuFromTap() {
|
||||
contextMenuKey.currentState?.showContextMenu(context, position: _tapPosition);
|
||||
}
|
||||
|
||||
/// Show without a tap position (keyboard, gamepad).
|
||||
void showContextMenu() {
|
||||
contextMenuKey.currentState?.showContextMenu(context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// Adds [safeNotifyListeners] which no-ops after [dispose]. Use in providers
|
||||
/// that fire from async paths where a late callback could otherwise trip
|
||||
/// Flutter's debug-only "used after dispose" assert.
|
||||
mixin DisposableChangeNotifierMixin on ChangeNotifier {
|
||||
bool _disposed = false;
|
||||
|
||||
bool get isDisposed => _disposed;
|
||||
|
||||
bool safeNotifyListeners() {
|
||||
if (_disposed) return false;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,12 @@ mixin GridFocusNodeMixin<T extends StatefulWidget> on State<T> {
|
||||
return gridItemFocusNodes.putIfAbsent(index, () => FocusNode(debugLabel: '${prefix}_$index'));
|
||||
}
|
||||
|
||||
/// Get the focus node for [index], routing index 0 through [firstNode] when
|
||||
/// the grid pins a dedicated node for the first item (e.g. `firstItemFocusNode`).
|
||||
FocusNode focusNodeForIndex(int index, FocusNode firstNode, {required String prefix}) {
|
||||
return index == 0 ? firstNode : getGridItemFocusNode(index, prefix: prefix);
|
||||
}
|
||||
|
||||
/// Record that the item at [index] received focus.
|
||||
void trackGridItemFocus(int index, bool hasFocus) {
|
||||
if (hasFocus) {
|
||||
|
||||
Reference in New Issue
Block a user