feat(details): segmented Description/Steps/Files header

Replace the static DETAILS label and its dead space with a segment switcher; the card body now shows one section at a time. Step/file counts sit in the tab labels, the edit/preview toggle is scoped to Description, and drag-and-drop or add jumps to the Files tab. Tab labels localized (en/de).
This commit is contained in:
Mika Kuns
2026-06-23 08:34:03 +02:00
parent 637886f33a
commit 9301bbc81a
4 changed files with 171 additions and 130 deletions

View File

@@ -117,23 +117,30 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
[RelayCommand]
private void ToggleDescriptionExpanded() => IsDescriptionExpanded = !IsDescriptionExpanded;
[ObservableProperty] private bool _isStepsExpanded;
// Which section of the details card is shown (header acts as a segment switcher).
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsDescriptionSection))]
[NotifyPropertyChangedFor(nameof(IsStepsSection))]
[NotifyPropertyChangedFor(nameof(IsFilesSection))]
private string _detailSection = "description";
public bool IsDescriptionSection => DetailSection == "description";
public bool IsStepsSection => DetailSection == "steps";
public bool IsFilesSection => DetailSection == "files";
[RelayCommand]
private void ToggleStepsExpanded() => IsStepsExpanded = !IsStepsExpanded;
private void SelectDetailSection(string? section) => DetailSection = section ?? "description";
public int TotalStepCount => Subtasks.Count;
public int OpenStepCount => Subtasks.Count(s => !s.Done);
public string StepsSummary =>
TotalStepCount == 0 ? "no steps yet"
: OpenStepCount == 0 ? $"all done · {TotalStepCount} total"
: $"{OpenStepCount} open · {TotalStepCount} total";
public int DoneStepCount => Subtasks.Count(s => s.Done);
public string StepsBadge => TotalStepCount > 0 ? $"{DoneStepCount}/{TotalStepCount}" : "";
public string FilesBadge => Attachments.Count > 0 ? Attachments.Count.ToString() : "";
private void NotifyStepsChanged()
{
OnPropertyChanged(nameof(TotalStepCount));
OnPropertyChanged(nameof(OpenStepCount));
OnPropertyChanged(nameof(StepsSummary));
OnPropertyChanged(nameof(DoneStepCount));
OnPropertyChanged(nameof(StepsBadge));
OnPropertyChanged(nameof(ComposedPreview));
}
@@ -425,6 +432,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
Notes = new NotesEditorViewModel(_notesApi);
Subtasks.CollectionChanged += (_, _) => NotifyStepsChanged();
Subtasks.CollectionChanged += (_, _) => Merge.SyncChildOutcomes(HasChildOutcomes, Subtasks.Count);
Attachments.CollectionChanged += (_, _) => OnPropertyChanged(nameof(FilesBadge));
AgentSettings.PropertyChanged += (_, e) =>
{
@@ -1233,6 +1241,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
public async System.Threading.Tasks.Task AddFilesAsync(IReadOnlyList<(string FileName, Stream Content)> files)
{
DetailSection = "files";
if (Task is null || Task.IsRunning)
{
DropStatus = Loc.T("details.attachments.selectIdleTask");