어린이날 기념 커밋

This commit is contained in:
2026-05-05 00:50:11 +09:00
parent e40a2a568e
commit 960163dad8
29 changed files with 4399 additions and 463 deletions

View File

@@ -15,6 +15,7 @@ public sealed class ChannelScheduleItem : ObservableObject
private DateTimeOffset? _lastPlayedAt;
private string _currentRegionLabel = string.Empty;
private double _defaultCutDurationSeconds;
private double _draftCutDurationSeconds;
private int _totalCuts;
private double _thumbnailWidth = 160;
private double _thumbnailHeight = 90;
@@ -35,7 +36,33 @@ public sealed class ChannelScheduleItem : ObservableObject
public required double DefaultCutDurationSeconds
{
get => _defaultCutDurationSeconds;
set => SetProperty(ref _defaultCutDurationSeconds, value);
set
{
var hadPendingDurationChange = HasPendingDurationChange;
var normalized = ScheduleTemplatePolicy.NormalizeCutDurationSeconds(value, Channel, FormatName);
if (SetProperty(ref _defaultCutDurationSeconds, normalized))
{
if (!hadPendingDurationChange || _draftCutDurationSeconds <= 0)
{
SetProperty(ref _draftCutDurationSeconds, normalized, nameof(DraftCutDurationSeconds));
}
OnDurationStateChanged();
}
}
}
public double DraftCutDurationSeconds
{
get => _draftCutDurationSeconds <= 0 ? DefaultCutDurationSeconds : _draftCutDurationSeconds;
set
{
var normalized = ScheduleTemplatePolicy.NormalizeCutDurationSeconds(value, Channel, FormatName);
if (SetProperty(ref _draftCutDurationSeconds, normalized))
{
OnDurationStateChanged();
}
}
}
public required int TotalCuts
@@ -117,6 +144,15 @@ public sealed class ChannelScheduleItem : ObservableObject
[JsonIgnore]
public bool CanDelete => State is not ScheduleQueueItemState.OnAir and not ScheduleQueueItemState.Sending;
[JsonIgnore]
public double MinimumDurationSeconds => ScheduleTemplatePolicy.GetMinimumCutDurationSeconds(Channel, FormatName);
[JsonIgnore]
public bool HasPendingDurationChange => Math.Abs(DraftCutDurationSeconds - DefaultCutDurationSeconds) >= 0.001d;
[JsonIgnore]
public string DurationApplyStatusLabel => HasPendingDurationChange ? "미적용" : "적용됨";
[JsonIgnore]
public string LastPlayedLabel => LastPlayedAt?.ToString("HH:mm:ss") ?? "아직 송출 전";
@@ -125,6 +161,7 @@ public sealed class ChannelScheduleItem : ObservableObject
{
ScheduleRegionScope.All => "전체",
ScheduleRegionScope.StationRegions => "선택권역",
ScheduleRegionScope.RegionGroup => string.IsNullOrWhiteSpace(RegionLabel) ? "시도" : RegionLabel,
_ => string.IsNullOrWhiteSpace(RegionLabel) ? "개별 지역" : RegionLabel
};
@@ -173,6 +210,23 @@ public sealed class ChannelScheduleItem : ObservableObject
ThumbnailHeight = metrics.Height;
}
public void StepDraftDuration(double deltaSeconds)
{
DraftCutDurationSeconds = DraftCutDurationSeconds + deltaSeconds;
}
public void ApplyDraftDuration()
{
DefaultCutDurationSeconds = DraftCutDurationSeconds;
OnDurationStateChanged();
}
private void OnDurationStateChanged()
{
OnPropertyChanged(nameof(HasPendingDurationChange));
OnPropertyChanged(nameof(DurationApplyStatusLabel));
}
public static ChannelScheduleItem FromTemplate(FormatTemplateDefinition template, ScheduleRegionOption? regionOption = null)
{
var selectedRegion = regionOption ?? new ScheduleRegionOption
@@ -192,7 +246,9 @@ public sealed class ChannelScheduleItem : ObservableObject
TotalCuts = template.Cuts.Count,
RegionScope = selectedRegion.Scope,
ScheduleElectionType = selectedRegion.ElectionType,
RegionLabel = selectedRegion.Scope == ScheduleRegionScope.Single ? selectedRegion.Label : string.Empty,
RegionLabel = selectedRegion.Scope is ScheduleRegionScope.Single or ScheduleRegionScope.RegionGroup
? selectedRegion.Label
: string.Empty,
RegionCode = selectedRegion.DistrictCode
};
}