focus-flow/apps/focus_flow_flutter/lib/widgets/timeline/timeline_view.dart

63 lines
2 KiB
Dart

// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders Timeline View pieces for the FocusFlow Flutter timeline.
library;
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import '../../models/today_screen_models.dart';
import '../../theme/focus_flow_tokens.dart';
import 'task_timeline_card.dart';
import 'timeline_axis.dart';
import 'timeline_geometry.dart';
part 'timeline_view/timeline_card_placement.dart';
part 'timeline_view/timeline_scroll_behavior.dart';
part 'timeline_view/timeline_view_state.dart';
/// Scrollable compact timeline view for Today cards.
class TimelineView extends StatefulWidget {
/// Creates a timeline view.
const TimelineView({
required this.cards,
required this.range,
required this.onCardSelected,
this.onAddTask,
this.onCardCompleted,
this.now,
this.scrollTargetCardId,
this.scrollRequest = 0,
super.key,
});
/// Cards to position on the timeline.
final List<TimelineCardModel> cards;
/// Visible range used to build the timeline geometry.
final TimelineRangeModel range;
/// Callback invoked when a card is selected.
final ValueChanged<TimelineCardModel> onCardSelected;
/// Callback invoked when the timeline context menu requests a new task.
final Future<void> Function()? onAddTask;
/// Callback invoked when a task card status control requests completion.
final ValueChanged<TimelineCardModel>? onCardCompleted;
/// Clock used to center the initial scroll position.
final DateTime Function()? now;
/// Card id requested by another surface, such as the required banner.
final String? scrollTargetCardId;
/// Monotonic request number that allows repeated jumps to the same card.
final int scrollRequest;
/// Creates the mutable state object used by this stateful widget.
/// Flutter calls this once for each mounted widget instance before lifecycle callbacks and builds begin.
@override
State<TimelineView> createState() => _TimelineViewState();
}