feat(tv-ui): add slideshow pattern mode and improve admin readability
This commit is contained in:
@@ -13,6 +13,27 @@ import 'data/services/sync_service.dart';
|
||||
// ──────────────────────────────────────────────
|
||||
final mockTimeOffsetProvider = StateProvider<Duration>((ref) => Duration.zero);
|
||||
|
||||
enum BackgroundRotateAction { next, previous, random }
|
||||
|
||||
class BackgroundRotateCommand {
|
||||
final int nonce;
|
||||
final BackgroundRotateAction action;
|
||||
|
||||
const BackgroundRotateCommand({
|
||||
required this.nonce,
|
||||
required this.action,
|
||||
});
|
||||
|
||||
const BackgroundRotateCommand.initial()
|
||||
: nonce = 0,
|
||||
action = BackgroundRotateAction.random;
|
||||
}
|
||||
|
||||
final backgroundRotateCommandProvider =
|
||||
StateProvider<BackgroundRotateCommand>(
|
||||
(ref) => const BackgroundRotateCommand.initial(),
|
||||
);
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// CLOCK PROVIDER — fires every second
|
||||
// ──────────────────────────────────────────────
|
||||
@@ -263,6 +284,22 @@ final rotationIndexProvider =
|
||||
return RotationNotifier(ref);
|
||||
});
|
||||
|
||||
bool _isMainPhaseForSettings(
|
||||
int phaseIndex,
|
||||
AppSettings settings, {
|
||||
required bool hasContent,
|
||||
}) {
|
||||
if (!hasContent) return true;
|
||||
if (settings.slideshowPatternMode == SlideshowPatternMode.burst) {
|
||||
final slidesBetweenMain = settings.slideshowSlidesPerMain.clamp(1, 20);
|
||||
final cycleLength = slidesBetweenMain + 1; // main + N slides
|
||||
return phaseIndex % cycleLength == 0;
|
||||
}
|
||||
|
||||
// Default alternating pattern.
|
||||
return phaseIndex % 2 == 0;
|
||||
}
|
||||
|
||||
class RotationNotifier extends StateNotifier<int> {
|
||||
final Ref _ref;
|
||||
Timer? _timer;
|
||||
@@ -301,7 +338,11 @@ class RotationNotifier extends StateNotifier<int> {
|
||||
return;
|
||||
}
|
||||
|
||||
final isMainScreen = state % 2 == 0;
|
||||
final isMainScreen = _isMainPhaseForSettings(
|
||||
state,
|
||||
settings,
|
||||
hasContent: hasContent,
|
||||
);
|
||||
final duration = isMainScreen
|
||||
? _resolveMainPhaseDuration(settings)
|
||||
: settings.slideDurationSec.clamp(1, 600);
|
||||
@@ -346,8 +387,5 @@ final isMainScreenProvider = Provider<bool>((ref) {
|
||||
final validSlides =
|
||||
settings.slideshowImages.where((i) => i.trim().isNotEmpty).toList();
|
||||
final hasContent = validSlides.isNotEmpty;
|
||||
if (!hasContent) return true; // always stay on main screen
|
||||
|
||||
// Even = main, Odd = slideshow
|
||||
return index % 2 == 0;
|
||||
return _isMainPhaseForSettings(index, settings, hasContent: hasContent);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user