refactor: codebase review cleanup

This commit is contained in:
edde746
2026-04-25 03:16:11 +02:00
parent 1949c22b85
commit d0a93d57dd
83 changed files with 763 additions and 419 deletions
+26
View File
@@ -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();
}
}
+6
View File
@@ -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) {