build method

  1. @override
Widget build(
  1. BuildContext context
)
override

Describes the part of the UI represented by this widget.

Implementation

@override
Widget build(BuildContext context) {
  final theme = ThemeScope.of(context);
  final filteredEvents = events
      .where((event) => _matchesFilter(event))
      .toList(growable: false);
  final effectiveMaxItems = expanded ? filteredEvents.length : maxItems;
  final visibleEvents = filteredEvents
      .take(effectiveMaxItems)
      .toList(growable: false);
  final groupedEvents = _groupEvents(visibleEvents);
  final typeCounts = _typeCounts(filteredEvents);
  final canExpand = filteredEvents.length > maxItems;
  final hiddenCount = filteredEvents.length - visibleEvents.length;
  final hiddenGroupedCount = _groupEvents(
    filteredEvents.skip(effectiveMaxItems).toList(growable: false),
  ).length;
  final totalGroupedCount = _groupEvents(filteredEvents).length;

  return PanelBox(
    title: title,
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      gap: 1,
      children: [
        if (showFilterChips)
          Wrap(
            spacing: 1,
            runSpacing: 1,
            children: [
              for (final candidate in ReplayEventHistoryFilter.values)
                ChoiceChip(
                  key: ValueKey('replay-history-filter-${candidate.name}'),
                  label: Text(_filterLabel(candidate)),
                  selected: candidate == filter,
                  onSelected: onFilterSelected == null
                      ? null
                      : (selected) {
                          if (!selected) return null;
                          return onFilterSelected?.call(candidate);
                        },
                ),
            ],
          ),
        if (showModeChips)
          Wrap(
            spacing: 1,
            runSpacing: 1,
            children: [
              for (final candidate in ReplayEventHistoryMode.values)
                ChoiceChip(
                  key: ValueKey('replay-history-mode-${candidate.name}'),
                  label: Text(_modeLabel(candidate)),
                  selected: candidate == mode,
                  onSelected: onModeSelected == null
                      ? null
                      : (selected) {
                          if (!selected) return null;
                          return onModeSelected?.call(candidate);
                        },
                ),
            ],
          ),
        if (showFilterSummary && filter != ReplayEventHistoryFilter.all)
          Text('filter: ${_filterLabel(filter)}', style: theme.labelSmall),
        if (showModeSummary && mode != ReplayEventHistoryMode.flat)
          Text('mode: ${_modeLabel(mode)}', style: theme.labelSmall),
        if (showTypeChips && typeCounts.isNotEmpty)
          Wrap(
            spacing: 1,
            runSpacing: 1,
            children: [
              for (final entry in typeCounts.entries)
                Chip(label: Text('${entry.key} ${entry.value}')),
            ],
          ),
        if (showExpandToggle && canExpand)
          Row(
            gap: 1,
            children: [
              ActionChip(
                key: const ValueKey('replay-history-expand-toggle'),
                label: Text(
                  _expandLabel(
                    totalEventCount: filteredEvents.length,
                    totalGroupedCount: totalGroupedCount,
                  ),
                ),
                onPressed: onExpandedChanged == null
                    ? null
                    : () => onExpandedChanged?.call(!expanded),
              ),
              if (!expanded && hiddenCount > 0)
                Text(
                  _hiddenSummaryLabel(
                    hiddenCount: hiddenCount,
                    hiddenGroupedCount: hiddenGroupedCount,
                  ),
                  style: theme.labelSmall,
                ),
            ],
          ),
        if (visibleEvents.isEmpty)
          Text(
            events.isEmpty
                ? 'No replay events yet.'
                : 'No matching replay events.',
            style: theme.bodySmall,
          )
        else if (mode == ReplayEventHistoryMode.flat)
          ...visibleEvents.map(
            (event) => Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              gap: 0,
              children: [
                Text(event.summary, style: theme.bodySmall),
                Text(event.statusHint, style: theme.labelSmall),
              ],
            ),
          )
        else
          ...groupedEvents.map(
            (group) => Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              gap: 0,
              children: [
                Text(
                  '${group.count}x ${group.summary}',
                  style: theme.bodySmall,
                ),
                Text(group.statusHint, style: theme.labelSmall),
              ],
            ),
          ),
      ],
    ),
  );
}