Files
plezy/lib/mixins/deletion_aware.dart
edde746 352b88109b refactor: extract shared mixins and helpers, drop dead abstractions
Introduces shared seams for paginated views, D-pad reorder, media control
routing, async singletons and the device method channel, then points the
open-coded copies at them.

Also removes unused models and duplicated provider/server plumbing, folds
the twice-implemented artifact store in the server, and factors the
repeated Flutter toolchain prologue in CI into a composite action.
2026-07-26 06:09:48 +02:00

96 lines
3.0 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import '../utils/deletion_notifier.dart';
import 'event_aware.dart';
import 'watch_state_aware.dart';
/// Mixin for screens that need to react to deletion events.
///
/// Provides automatic subscription management and filtering based on
/// which items the screen cares about.
///
/// Example usage:
/// ```dart
/// class _MyScreenState extends State<MyScreen> with DeletionAware {
/// List<MediaItem> _items = [];
///
/// @override
/// Set<String>? get deletionIds =>
/// _items.map((e) => e.id).toSet();
///
/// @override
/// void onDeletionEvent(DeletionEvent event) {
/// setState(() {
/// _items.removeWhere((e) => e.id == event.itemId);
/// });
/// }
/// }
/// ```
mixin DeletionAware<T extends StatefulWidget> on State<T> {
StreamSubscription<DeletionEvent>? _deletionSubscription;
/// Override to scope events to a specific server.
///
/// Return null to receive events from all servers.
String? get deletionServerId => null;
/// Override to specify which global keys this screen cares about.
///
/// Use format `serverId:ratingKey`.
/// Return null to fall back to [deletionIds] matching.
Set<String>? get deletionGlobalKeys => null;
/// Override to specify which item ids this screen cares about.
///
/// Return null to receive ALL events (not recommended for performance).
/// Return an empty set to receive no events.
///
/// The set should include:
/// - Direct items displayed (e.g., episode ids in a season view)
/// - Parent items that affect display (e.g., show id for seasons)
Set<String>? get deletionIds;
/// Called when a relevant deletion event occurs.
///
/// Only called if [deletionIds] is null or contains an affected key.
void onDeletionEvent(DeletionEvent event);
@override
void initState() {
super.initState();
_deletionSubscription = subscribeToHierarchicalEvents<DeletionEvent>(
notifier: DeletionNotifier(),
mounted: () => mounted,
serverId: () => deletionServerId,
globalKeys: () => deletionGlobalKeys,
itemIds: () => deletionIds,
onEvent: onDeletionEvent,
);
}
@override
void dispose() {
_deletionSubscription?.cancel();
_deletionSubscription = null;
super.dispose();
}
}
/// Points [DeletionAware]'s filters at the [WatchStateAware] ones.
///
/// The usual case: a screen shows the same rows for both event families, so a
/// deleted show and a watched show affect exactly the same items. Mix this in
/// after both aware mixins instead of re-typing the three getters. A screen
/// that genuinely needs a different scope overrides the getter it cares about
/// (or skips this mixin entirely).
mixin DeletionMirrorsWatchState<T extends StatefulWidget> on WatchStateAware<T>, DeletionAware<T> {
@override
String? get deletionServerId => watchStateServerId;
@override
Set<String>? get deletionGlobalKeys => watchedGlobalKeys;
@override
Set<String>? get deletionIds => watchedIds;
}