diff --git a/CHANGELOG.md b/CHANGELOG.md
index 79299ff1c..8c4489007 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -58,6 +58,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix deco dead air fallback selection and duration on mirror channels
- Fix fallback filler duration on mirror channels
+### Changed
+- Filler presets: use separate text fields for `hours`, `minutes` and `seconds` duration
+
## [25.6.0] - 2025-09-14
### Added
- Classic schedules: allow selecting multiple graphics elements on schedule items
diff --git a/ErsatzTV/Pages/FillerPresetEditor.razor b/ErsatzTV/Pages/FillerPresetEditor.razor
index d808aa2ed..68fbb176b 100644
--- a/ErsatzTV/Pages/FillerPresetEditor.razor
+++ b/ErsatzTV/Pages/FillerPresetEditor.razor
@@ -56,7 +56,27 @@
Duration
-
+
+
+
+
+
+
+
+
+
diff --git a/ErsatzTV/ViewModels/FillerPresetEditViewModel.cs b/ErsatzTV/ViewModels/FillerPresetEditViewModel.cs
index f915483af..f4f75929f 100644
--- a/ErsatzTV/ViewModels/FillerPresetEditViewModel.cs
+++ b/ErsatzTV/ViewModels/FillerPresetEditViewModel.cs
@@ -13,6 +13,9 @@ public class FillerPresetEditViewModel
private CollectionType _collectionType;
private int? _count;
private TimeSpan? _duration;
+ private int _durationHours;
+ private int _durationMinutes;
+ private int _durationSeconds;
private FillerKind _fillerKind;
private FillerMode _fillerMode;
private int? _padToNearestMinute;
@@ -52,7 +55,44 @@ public class FillerPresetEditViewModel
public TimeSpan? Duration
{
get => FillerMode == FillerMode.Duration ? _duration : null;
- set => _duration = value;
+ set
+ {
+ _duration = value;
+ CheckDuration();
+ }
+ }
+
+ public int DurationHours
+ {
+ get => _durationHours;
+ set
+ {
+ _duration = TimeSpan.FromHours(value) + TimeSpan.FromMinutes(_duration?.Minutes ?? 0) +
+ TimeSpan.FromSeconds(_duration?.Seconds ?? 0);
+ CheckDuration();
+ }
+ }
+
+ public int DurationMinutes
+ {
+ get => _durationMinutes;
+ set
+ {
+ _duration = TimeSpan.FromHours(_duration?.Hours ?? 0) + TimeSpan.FromMinutes(value) +
+ TimeSpan.FromSeconds(_duration?.Seconds ?? 0);
+ CheckDuration();
+ }
+ }
+
+ public int DurationSeconds
+ {
+ get => _durationSeconds;
+ set
+ {
+ _duration = TimeSpan.FromHours(_duration?.Hours ?? 0) + TimeSpan.FromMinutes(_duration?.Minutes ?? 0) +
+ TimeSpan.FromSeconds(value);
+ CheckDuration();
+ }
}
public int? Count
@@ -106,7 +146,7 @@ public class FillerPresetEditViewModel
Name,
FillerKind,
FillerMode,
- Duration.Map(FixDuration),
+ Duration,
Count,
PadToNearestMinute,
AllowWatermarks,
@@ -124,7 +164,7 @@ public class FillerPresetEditViewModel
Name,
FillerKind,
FillerMode,
- Duration.Map(FixDuration),
+ Duration,
Count,
PadToNearestMinute,
AllowWatermarks,
@@ -137,6 +177,32 @@ public class FillerPresetEditViewModel
Expression,
UseChaptersAsMediaItems);
- private static TimeSpan FixDuration(TimeSpan duration) =>
- duration > TimeSpan.FromDays(1) ? duration.Subtract(TimeSpan.FromDays(1)) : duration;
+ private void CheckDuration()
+ {
+ if (_fillerMode is FillerMode.Duration)
+ {
+ _duration ??= TimeSpan.Zero;
+
+ if (_duration > TimeSpan.FromHours(24))
+ {
+ _duration = TimeSpan.FromHours(24);
+ }
+
+ if (_duration < TimeSpan.FromSeconds(1))
+ {
+ _duration = TimeSpan.FromSeconds(1);
+ }
+
+ _durationHours = (int)_duration.Value.TotalHours;
+ _durationMinutes = _duration.Value.Minutes;
+ _durationSeconds = _duration.Value.Seconds;
+ }
+ else
+ {
+ _duration = null;
+ _durationHours = 0;
+ _durationMinutes = 0;
+ _durationSeconds = 0;
+ }
+ }
}