docs: expand dartdocs and add compliance hooks

This commit is contained in:
Ashley Venn 2026-07-01 13:36:12 -07:00
parent 2485e10873
commit ec19dd498d
571 changed files with 7637 additions and 30 deletions

15
.githooks/pre-commit Executable file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: 2026 FocusFlow contributors
# SPDX-License-Identifier: AGPL-3.0-only
# Blocks commits that do not meet the repository's formatting, analyzer,
# documentation, or SPDX/REUSE metadata gates.
set -euo pipefail
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$root_dir"
dart format --set-exit-if-changed packages apps scripts tool test
dart analyze
dart run tool/check_reuse.dart
dart run tool/check_docs.dart --skip-dartdoc

View file

@ -1,3 +1,6 @@
# SPDX-FileCopyrightText: 2026 FocusFlow contributors
# SPDX-License-Identifier: AGPL-3.0-only
# Runs analyzer, tests, coverage, docs, and tagged desktop packaging. # Runs analyzer, tests, coverage, docs, and tagged desktop packaging.
name: CI name: CI

17
REUSE.toml Normal file
View file

@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2026 FocusFlow contributors
# SPDX-License-Identifier: AGPL-3.0-only
version = 1
# The project license text is intentionally kept in the repository root as
# LICENSE.md. These annotations cover package and app files that cannot safely
# carry inline SPDX comments, such as generated platform files, binary icons,
# JSON manifests, Xcode project files, and XML/plist resources.
[[annotations]]
path = [
"packages/**",
"apps/focus_flow_flutter/**",
]
precedence = "aggregate"
SPDX-FileCopyrightText = "2026 FocusFlow contributors"
SPDX-License-Identifier = "AGPL-3.0-only"

17
analysis_options.yaml Normal file
View file

@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2026 FocusFlow contributors
# SPDX-License-Identifier: AGPL-3.0-only
include: package:lints/recommended.yaml
analyzer:
language:
strict-casts: true
strict-inference: true
strict-raw-types: true
linter:
rules:
public_member_api_docs: true
prefer_final_locals: true
prefer_final_fields: true
avoid_print: true

View file

@ -0,0 +1,6 @@
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# License
This app uses the repository-level license at [../../LICENSE.md](../../LICENSE.md).

View file

@ -1,3 +1,6 @@
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# FocusFlow Flutter # FocusFlow Flutter
Flutter desktop app target for the FocusFlow UI work. Flutter desktop app target for the FocusFlow UI work.

View file

@ -1,3 +1,6 @@
# SPDX-FileCopyrightText: 2026 FocusFlow contributors
# SPDX-License-Identifier: AGPL-3.0-only
# This file configures the analyzer, which statically analyzes Dart code to # This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints. # check for errors, warnings, and lints.
# #
@ -9,6 +12,12 @@
# packages, and plugins designed to encourage good coding practices. # packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml include: package:flutter_lints/flutter.yaml
analyzer:
language:
strict-casts: true
strict-inference: true
strict-raw-types: true
linter: linter:
# The lint rules applied to this project can be customized in the # The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml` # section below to disable rules from the `package:flutter_lints/flutter.yaml`
@ -22,6 +31,9 @@ linter:
# producing the lint. # producing the lint.
rules: rules:
public_member_api_docs: true public_member_api_docs: true
prefer_final_locals: true
prefer_final_fields: true
avoid_print: true
# avoid_print: false # Uncomment to disable the `avoid_print` rule # avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Exports the FocusFlow Flutter application entry points. /// Exports the FocusFlow Flutter application entry points.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../demo_scheduler_composition.dart'; part of '../demo_scheduler_composition.dart';
/// Formats a civil date as a long month/day/year label. /// Formats a civil date as a long month/day/year label.
@ -19,6 +22,8 @@ String _formatDateLabel(CivilDate date) {
return '${months[date.month - 1]} ${date.day}, ${date.year}'; return '${months[date.month - 1]} ${date.day}, ${date.year}';
} }
/// Top-level helper that performs the `_instant` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
DateTime _instant(CivilDate date, int hour, [int minute = 0]) { DateTime _instant(CivilDate date, int hour, [int minute = 0]) {
return DateTime.utc(date.year, date.month, date.day, hour, minute); return DateTime.utc(date.year, date.month, date.day, hour, minute);
} }

View file

@ -1,5 +1,10 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../demo_scheduler_composition.dart'; part of '../demo_scheduler_composition.dart';
/// Top-level helper that performs the `_todaySeedTasks` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
List<Task> _todaySeedTasks(CivilDate date, DateTime createdAt) { List<Task> _todaySeedTasks(CivilDate date, DateTime createdAt) {
return [ return [
_seedTask( _seedTask(
@ -118,6 +123,8 @@ List<Task> _todaySeedTasks(CivilDate date, DateTime createdAt) {
]; ];
} }
/// Top-level helper that performs the `_seedTask` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Task _seedTask({ Task _seedTask({
required String id, required String id,
required String title, required String title,

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Composes the FocusFlow Flutter application around Demo Scheduler Composition. /// Composes the FocusFlow Flutter application around Demo Scheduler Composition.
library; library;
@ -12,6 +15,8 @@ part 'demo/demo_seed_tasks.dart';
/// Wires the Flutter demo UI to in-memory scheduler application use cases. /// Wires the Flutter demo UI to in-memory scheduler application use cases.
class DemoSchedulerComposition { class DemoSchedulerComposition {
/// Creates a `DemoSchedulerComposition._` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
DemoSchedulerComposition._({ DemoSchedulerComposition._({
required this.store, required this.store,
required this.todayQuery, required this.todayQuery,

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Composes the FocusFlow Flutter application around Focus Flow App. /// Composes the FocusFlow Flutter application around Focus Flow App.
library; library;
@ -30,6 +33,8 @@ class FocusFlowApp extends StatelessWidget {
/// Factory and controller bundle used by the app tree. /// Factory and controller bundle used by the app tree.
final DemoSchedulerComposition composition; final DemoSchedulerComposition composition;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../focus_flow_app.dart'; part of '../focus_flow_app.dart';
/// Stateful home screen that owns the Today controller lifecycle. /// Stateful home screen that owns the Today controller lifecycle.
@ -8,6 +11,8 @@ class FocusFlowHome extends StatefulWidget {
/// Factory and controller bundle used by the home screen. /// Factory and controller bundle used by the home screen.
final DemoSchedulerComposition composition; final DemoSchedulerComposition composition;
/// 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 @override
State<FocusFlowHome> createState() => _FocusFlowHomeState(); State<FocusFlowHome> createState() => _FocusFlowHomeState();
} }

View file

@ -1,9 +1,21 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../focus_flow_app.dart'; part of '../focus_flow_app.dart';
/// Private implementation type for `_FocusFlowHomeState` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _FocusFlowHomeState extends State<FocusFlowHome> { class _FocusFlowHomeState extends State<FocusFlowHome> {
/// Stores the `controller` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
late final TodayScreenController controller; late final TodayScreenController controller;
/// Stores the `commandController` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
late final SchedulerCommandController commandController; late final SchedulerCommandController commandController;
/// Initializes state owned by this object before the first build.
/// Use this lifecycle point for controller setup, initial reads, and listener wiring that must happen once per mounted instance.
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -14,6 +26,8 @@ class _FocusFlowHomeState extends State<FocusFlowHome> {
controller.load(); controller.load();
} }
/// Releases resources owned by this object before it leaves the tree.
/// Controllers, listeners, and other disposable collaborators should be cleaned up here to avoid stale callbacks.
@override @override
void dispose() { void dispose() {
commandController.dispose(); commandController.dispose();
@ -21,6 +35,8 @@ class _FocusFlowHomeState extends State<FocusFlowHome> {
super.dispose(); super.dispose();
} }
/// Runs the `_toggleCardCompletion` operation and completes after its asynchronous work finishes.
/// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
Future<void> _toggleCardCompletion(TimelineCardModel card) async { Future<void> _toggleCardCompletion(TimelineCardModel card) async {
if (!card.canToggleCompletion) { if (!card.canToggleCompletion) {
return; return;
@ -35,6 +51,8 @@ class _FocusFlowHomeState extends State<FocusFlowHome> {
} }
} }
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(

View file

@ -1,10 +1,21 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../focus_flow_app.dart'; part of '../focus_flow_app.dart';
/// Private implementation type for `_PlanIssue` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _PlanIssue extends StatelessWidget { class _PlanIssue extends StatelessWidget {
/// Creates a `_PlanIssue` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _PlanIssue({required this.message}); const _PlanIssue({required this.message});
/// Stores the `message` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final String message; final String message;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Center( return Center(

View file

@ -1,6 +1,13 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../focus_flow_app.dart'; part of '../focus_flow_app.dart';
/// Private implementation type for `_TodayScreenScaffold` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _TodayScreenScaffold extends StatefulWidget { class _TodayScreenScaffold extends StatefulWidget {
/// Creates a `_TodayScreenScaffold` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _TodayScreenScaffold({ const _TodayScreenScaffold({
required this.data, required this.data,
required this.selectedCard, required this.selectedCard,
@ -9,12 +16,28 @@ class _TodayScreenScaffold extends StatefulWidget {
required this.onClearSelection, required this.onClearSelection,
}); });
/// Stores the `data` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TodayScreenData data; final TodayScreenData data;
/// Stores the `selectedCard` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TimelineCardModel? selectedCard; final TimelineCardModel? selectedCard;
/// Stores the `onSelectCard` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final ValueChanged<TimelineCardModel> onSelectCard; final ValueChanged<TimelineCardModel> onSelectCard;
/// Stores the `onCompleteCard` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Future<void> Function(TimelineCardModel card) onCompleteCard; final Future<void> Function(TimelineCardModel card) onCompleteCard;
/// Stores the `onClearSelection` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final VoidCallback onClearSelection; final VoidCallback onClearSelection;
/// 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 @override
State<_TodayScreenScaffold> createState() => _TodayScreenScaffoldState(); State<_TodayScreenScaffold> createState() => _TodayScreenScaffoldState();
} }

View file

@ -1,9 +1,21 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../focus_flow_app.dart'; part of '../focus_flow_app.dart';
/// Private implementation type for `_TodayScreenScaffoldState` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _TodayScreenScaffoldState extends State<_TodayScreenScaffold> { class _TodayScreenScaffoldState extends State<_TodayScreenScaffold> {
/// Private state stored as `_timelineScrollTargetCardId` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
String? _timelineScrollTargetCardId; String? _timelineScrollTargetCardId;
/// Private state stored as `_timelineScrollRequest` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
var _timelineScrollRequest = 0; var _timelineScrollRequest = 0;
/// Runs the `_showUpcomingRequiredTask` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
void _showUpcomingRequiredTask() { void _showUpcomingRequiredTask() {
final targetCardId = widget.data.requiredBanner?.timelineCardId; final targetCardId = widget.data.requiredBanner?.timelineCardId;
if (targetCardId == null) { if (targetCardId == null) {
@ -15,6 +27,8 @@ class _TodayScreenScaffoldState extends State<_TodayScreenScaffold> {
}); });
} }
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Stack( return Stack(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Provides compatibility composition exports for FocusFlow Flutter. /// Provides compatibility composition exports for FocusFlow Flutter.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../scheduler_command_controller.dart'; part of '../scheduler_command_controller.dart';
/// Builds an application operation context for a UI command operation. /// Builds an application operation context for a UI command operation.

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../scheduler_command_controller.dart'; part of '../scheduler_command_controller.dart';
/// Runs scheduler write commands and exposes command state to widgets. /// Runs scheduler write commands and exposes command state to widgets.
@ -25,7 +28,13 @@ class SchedulerCommandController extends ChangeNotifier {
/// Clock used by direct UI commands such as marking a task complete. /// Clock used by direct UI commands such as marking a task complete.
final DateTime Function() now; final DateTime Function() now;
/// Private state stored as `_sequence` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
var _sequence = 0; var _sequence = 0;
/// Private state stored as `_state` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
SchedulerCommandState _state = const SchedulerCommandIdle(); SchedulerCommandState _state = const SchedulerCommandIdle();
/// Current command execution state. /// Current command execution state.
@ -146,6 +155,8 @@ class SchedulerCommandController extends ChangeNotifier {
); );
} }
/// Runs the `_run` operation and completes after its asynchronous work finishes.
/// Callers should await the returned future so repository writes, UI refreshes, and failure handling happen in a predictable order.
Future<void> _run({ Future<void> _run({
required String label, required String label,
required String successMessage, required String successMessage,
@ -173,15 +184,21 @@ class SchedulerCommandController extends ChangeNotifier {
} }
} }
/// Runs the `_nextOperationId` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
String _nextOperationId() { String _nextOperationId() {
_sequence += 1; _sequence += 1;
return 'ui-command-$_sequence'; return 'ui-command-$_sequence';
} }
/// Runs the `_setState` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
void _setState(SchedulerCommandState next) { void _setState(SchedulerCommandState next) {
_state = next; _state = next;
notifyListeners(); notifyListeners();
} }
/// Runs the `_utcNow` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
static DateTime _utcNow() => DateTime.now().toUtc(); static DateTime _utcNow() => DateTime.now().toUtc();
} }

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../scheduler_command_controller.dart'; part of '../scheduler_command_controller.dart';
/// Base state for scheduler command execution in the UI. /// Base state for scheduler command execution in the UI.

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Coordinates Scheduler Command Controller state for the FocusFlow Flutter UI. /// Coordinates Scheduler Command Controller state for the FocusFlow Flutter UI.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Coordinates Scheduler Read Controller state for the FocusFlow Flutter UI. /// Coordinates Scheduler Read Controller state for the FocusFlow Flutter UI.
library; library;
@ -84,6 +87,8 @@ class ApplicationReadController<T> extends UiReadController<T> {
/// Predicate used to classify a successful value as empty or populated. /// Predicate used to classify a successful value as empty or populated.
final EmptyPredicate<T> isEmpty; final EmptyPredicate<T> isEmpty;
/// Private state stored as `_state` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
SchedulerReadState<T> _state = SchedulerReadLoading<T>(); SchedulerReadState<T> _state = SchedulerReadLoading<T>();
/// Current read state. /// Current read state.
@ -116,6 +121,8 @@ class ApplicationReadController<T> extends UiReadController<T> {
@override @override
Future<void> retry() => load(); Future<void> retry() => load();
/// Runs the `_setState` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
void _setState(SchedulerReadState<T> next) { void _setState(SchedulerReadState<T> next) {
_state = next; _state = next;
notifyListeners(); notifyListeners();

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Coordinates Today Screen Controller state for the FocusFlow Flutter UI. /// Coordinates Today Screen Controller state for the FocusFlow Flutter UI.
library; library;
@ -53,7 +56,12 @@ class TodayScreenController extends ChangeNotifier {
/// Callback used to read Today state. /// Callback used to read Today state.
final TodayStateReader read; final TodayStateReader read;
/// Private state stored as `_state` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
TodayScreenState _state = const TodayScreenLoading(); TodayScreenState _state = const TodayScreenLoading();
/// Private state stored as `_selectedCard` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
TimelineCardModel? _selectedCard; TimelineCardModel? _selectedCard;
/// Current Today screen loading/data/failure state. /// Current Today screen loading/data/failure state.
@ -105,6 +113,8 @@ class TodayScreenController extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
/// Runs the `_syncSelectedCard` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
void _syncSelectedCard(TodayScreenData data) { void _syncSelectedCard(TodayScreenData data) {
final selected = _selectedCard; final selected = _selectedCard;
if (selected == null) { if (selected == null) {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Launches the FocusFlow Flutter desktop application. /// Launches the FocusFlow Flutter desktop application.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../today_screen_models.dart'; part of '../today_screen_models.dart';
/// Presentation model for the next-required-task banner. /// Presentation model for the next-required-task banner.

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../today_screen_models.dart'; part of '../today_screen_models.dart';
/// Visual category used to style timeline cards. /// Visual category used to style timeline cards.

View file

@ -1,5 +1,10 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../today_screen_models.dart'; part of '../../today_screen_models.dart';
/// Top-level helper that performs the `_dateLabel` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
String _dateLabel(CivilDate date) { String _dateLabel(CivilDate date) {
const months = [ const months = [
'January', 'January',
@ -18,6 +23,8 @@ String _dateLabel(CivilDate date) {
return '${months[date.month - 1]} ${date.day}, ${date.year}'; return '${months[date.month - 1]} ${date.day}, ${date.year}';
} }
/// Top-level helper that performs the `_minutesSinceMidnight` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
int _minutesSinceMidnight(DateTime? value) { int _minutesSinceMidnight(DateTime? value) {
if (value == null) { if (value == null) {
return 0; return 0;
@ -25,6 +32,8 @@ int _minutesSinceMidnight(DateTime? value) {
return value.hour * 60 + value.minute; return value.hour * 60 + value.minute;
} }
/// Top-level helper that performs the `_formatTime` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
String _formatTime(DateTime? value) { String _formatTime(DateTime? value) {
if (value == null) { if (value == null) {
return ''; return '';

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../today_screen_models.dart'; part of '../today_screen_models.dart';
/// Presentation model for a single compact timeline card. /// Presentation model for a single compact timeline card.

View file

@ -1,5 +1,10 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../today_screen_models.dart'; part of '../today_screen_models.dart';
/// Top-level helper that performs the `_visualKindFor` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
TaskVisualKind _visualKindFor(TodayTimelineItem item) { TaskVisualKind _visualKindFor(TodayTimelineItem item) {
if (item.taskStatus == TaskStatus.completed || if (item.taskStatus == TaskStatus.completed ||
(item.taskType == TaskType.surprise && (item.taskType == TaskType.surprise &&
@ -16,6 +21,8 @@ TaskVisualKind _visualKindFor(TodayTimelineItem item) {
}; };
} }
/// Top-level helper that performs the `_typeLabelFor` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
String _typeLabelFor(TaskType taskType, TaskVisualKind visualKind) { String _typeLabelFor(TaskType taskType, TaskVisualKind visualKind) {
if (visualKind == TaskVisualKind.completedSurprise) { if (visualKind == TaskVisualKind.completedSurprise) {
return 'Completed'; return 'Completed';
@ -30,6 +37,8 @@ String _typeLabelFor(TaskType taskType, TaskVisualKind visualKind) {
}; };
} }
/// Top-level helper that performs the `_subtitleFor` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
String _subtitleFor( String _subtitleFor(
TodayTimelineItem item, TodayTimelineItem item,
TaskVisualKind visualKind, TaskVisualKind visualKind,

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../today_screen_models.dart'; part of '../today_screen_models.dart';
/// Visible timeline range expressed as minutes since midnight. /// Visible timeline range expressed as minutes since midnight.

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../today_screen_models.dart'; part of '../today_screen_models.dart';
/// Presentation model for the compact Today screen. /// Presentation model for the compact Today screen.

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Defines Today Screen Models models for the FocusFlow Flutter UI. /// Defines Today Screen Models models for the FocusFlow Flutter UI.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Defines Focus Flow Theme styling for the FocusFlow Flutter UI. /// Defines Focus Flow Theme styling for the FocusFlow Flutter UI.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Defines Focus Flow Tokens styling for the FocusFlow Flutter UI. /// Defines Focus Flow Tokens styling for the FocusFlow Flutter UI.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Defines Scheduler Visual Tokens styling for the FocusFlow Flutter UI. /// Defines Scheduler Visual Tokens styling for the FocusFlow Flutter UI.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders the App Shell widget for the FocusFlow Flutter UI. /// Renders the App Shell widget for the FocusFlow Flutter UI.
library; library;
@ -16,6 +19,8 @@ class AppShell extends StatelessWidget {
/// Primary content widget displayed beside the sidebar. /// Primary content widget displayed beside the sidebar.
final Widget child; final Widget child;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ColoredBox( return ColoredBox(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders the Backlog Pane widget for the FocusFlow Flutter UI. /// Renders the Backlog Pane widget for the FocusFlow Flutter UI.
library; library;
@ -24,6 +27,8 @@ class BacklogPane extends StatelessWidget {
/// Optional command controller for mutating backlog items. /// Optional command controller for mutating backlog items.
final SchedulerCommandController? commandController; final SchedulerCommandController? commandController;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ReadStateView<BacklogQueryResult>( return ReadStateView<BacklogQueryResult>(
@ -52,6 +57,8 @@ class BacklogContent extends StatelessWidget {
/// Optional command controller for capture and scheduling actions. /// Optional command controller for capture and scheduling actions.
final SchedulerCommandController? commandController; final SchedulerCommandController? commandController;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListView( return ListView(
@ -91,19 +98,29 @@ class QuickCaptureForm extends StatefulWidget {
/// Command controller used to submit captured task titles. /// Command controller used to submit captured task titles.
final SchedulerCommandController commandController; final SchedulerCommandController commandController;
/// 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 @override
State<QuickCaptureForm> createState() => _QuickCaptureFormState(); State<QuickCaptureForm> createState() => _QuickCaptureFormState();
} }
/// Private implementation type for `_QuickCaptureFormState` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _QuickCaptureFormState extends State<QuickCaptureForm> { class _QuickCaptureFormState extends State<QuickCaptureForm> {
/// Stores the `titleController` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final titleController = TextEditingController(); final titleController = TextEditingController();
/// Releases resources owned by this object before it leaves the tree.
/// Controllers, listeners, and other disposable collaborators should be cleaned up here to avoid stale callbacks.
@override @override
void dispose() { void dispose() {
titleController.dispose(); titleController.dispose();
super.dispose(); super.dispose();
} }
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Row(
@ -142,6 +159,8 @@ class CommandStatusBanner extends StatelessWidget {
/// Command controller whose state should be rendered. /// Command controller whose state should be rendered.
final SchedulerCommandController controller; final SchedulerCommandController controller;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AnimatedBuilder( return AnimatedBuilder(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders the Read State View widget for the FocusFlow Flutter UI. /// Renders the Read State View widget for the FocusFlow Flutter UI.
library; library;
@ -32,6 +35,8 @@ class ReadStateView<T> extends StatelessWidget {
/// Builds the populated content for a read value. /// Builds the populated content for a read value.
final Widget Function(BuildContext context, T value) dataBuilder; final Widget Function(BuildContext context, T value) dataBuilder;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AnimatedBuilder( return AnimatedBuilder(
@ -82,6 +87,8 @@ class EmptyStatePanel extends StatelessWidget {
/// Optional content shown alongside the empty-state panel. /// Optional content shown alongside the empty-state panel.
final Widget? child; final Widget? child;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final panel = Padding( final panel = Padding(
@ -138,6 +145,8 @@ class FailureStatePanel extends StatelessWidget {
/// Callback invoked when the user retries the read. /// Callback invoked when the user retries the read.
final Future<void> Function() onRetry; final Future<void> Function() onRetry;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Center( return Center(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders the Required Banner widget for the FocusFlow Flutter UI. /// Renders the Required Banner widget for the FocusFlow Flutter UI.
library; library;
@ -17,6 +20,8 @@ class RequiredBanner extends StatelessWidget {
/// Callback invoked when the highlighted required task should be shown. /// Callback invoked when the highlighted required task should be shown.
final VoidCallback? onShowUpcoming; final VoidCallback? onShowUpcoming;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final banner = model; final banner = model;
@ -97,44 +102,115 @@ class RequiredBanner extends StatelessWidget {
} }
} }
/// Private implementation type for `_RequiredBannerMetrics` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _RequiredBannerMetrics { class _RequiredBannerMetrics {
/// Creates a `_RequiredBannerMetrics` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _RequiredBannerMetrics(this.scale); const _RequiredBannerMetrics(this.scale);
/// Shared constant value for `referenceHeight`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const referenceHeight = 72.0; static const referenceHeight = 72.0;
/// Shared constant value for `_referenceWidth`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _referenceWidth = 760.0; static const _referenceWidth = 760.0;
/// Shared constant value for `_minimumScale`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _minimumScale = 0.5; static const _minimumScale = 0.5;
/// Creates a `_RequiredBannerMetrics.fromWidth` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
factory _RequiredBannerMetrics.fromWidth(double width) { factory _RequiredBannerMetrics.fromWidth(double width) {
final safeWidth = width.isFinite ? width : _referenceWidth; final safeWidth = width.isFinite ? width : _referenceWidth;
final scale = (safeWidth / _referenceWidth).clamp(_minimumScale, 1.0); final scale = (safeWidth / _referenceWidth).clamp(_minimumScale, 1.0);
return _RequiredBannerMetrics(scale.toDouble()); return _RequiredBannerMetrics(scale.toDouble());
} }
/// Stores the `scale` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final double scale; final double scale;
/// Returns the derived `horizontalPadding` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get horizontalPadding => 18 * scale; double get horizontalPadding => 18 * scale;
/// Returns the derived `bannerRadius` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get bannerRadius => FocusFlowTokens.bannerRadius * scale; double get bannerRadius => FocusFlowTokens.bannerRadius * scale;
/// Returns the derived `borderWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get borderWidth => scale < 0.7 ? 0.8 : 1; double get borderWidth => scale < 0.7 ? 0.8 : 1;
/// Returns the derived `iconCircleSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get iconCircleSize => 48 * scale; double get iconCircleSize => 48 * scale;
/// Returns the derived `iconSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get iconSize => 24 * scale; double get iconSize => 24 * scale;
/// Returns the derived `iconGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get iconGap => 26 * scale; double get iconGap => 26 * scale;
/// Returns the derived `buttonGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get buttonGap => 20 * scale; double get buttonGap => 20 * scale;
/// Returns the derived `textSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get textSize => (19 * scale).clamp(13.0, 14.0).toDouble(); double get textSize => (19 * scale).clamp(13.0, 14.0).toDouble();
/// Returns the derived `buttonWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get buttonWidth => 176 * scale; double get buttonWidth => 176 * scale;
/// Returns the derived `buttonHeight` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get buttonHeight => 46 * scale; double get buttonHeight => 46 * scale;
/// Returns the derived `buttonRadius` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get buttonRadius => FocusFlowTokens.smallButtonRadius * scale; double get buttonRadius => FocusFlowTokens.smallButtonRadius * scale;
/// Returns the derived `buttonTextSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get buttonTextSize => (16 * scale).clamp(11.0, 12.5).toDouble(); double get buttonTextSize => (16 * scale).clamp(11.0, 12.5).toDouble();
/// Returns the derived `buttonIconSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get buttonIconSize => 20 * scale; double get buttonIconSize => 20 * scale;
/// Returns the derived `buttonTextGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get buttonTextGap => 6 * scale; double get buttonTextGap => 6 * scale;
/// Returns the derived `buttonPadding` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
EdgeInsets get buttonPadding => EdgeInsets.symmetric(horizontal: 12 * scale); EdgeInsets get buttonPadding => EdgeInsets.symmetric(horizontal: 12 * scale);
} }
/// Private implementation type for `_UpcomingButton` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _UpcomingButton extends StatelessWidget { class _UpcomingButton extends StatelessWidget {
/// Creates a `_UpcomingButton` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _UpcomingButton({required this.metrics, required this.onPressed}); const _UpcomingButton({required this.metrics, required this.onPressed});
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _RequiredBannerMetrics metrics; final _RequiredBannerMetrics metrics;
/// Stores the `onPressed` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final VoidCallback? onPressed; final VoidCallback? onPressed;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return OutlinedButton( return OutlinedButton(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders the Schedule Components widget for the FocusFlow Flutter UI. /// Renders the Schedule Components widget for the FocusFlow Flutter UI.
library; library;
@ -14,6 +17,8 @@ class CompactPanel extends StatelessWidget {
/// Timeline items to display in compact form. /// Timeline items to display in compact form.
final List<TodayTimelineItem> items; final List<TodayTimelineItem> items;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (items.isEmpty) { if (items.isEmpty) {
@ -42,6 +47,8 @@ class TimelineRow extends StatelessWidget {
/// Optional completion callback for eligible tasks. /// Optional completion callback for eligible tasks.
final Future<void> Function()? onDone; final Future<void> Function()? onDone;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme; final scheme = Theme.of(context).colorScheme;
@ -104,19 +111,29 @@ class BacklogRow extends StatefulWidget {
/// Optional callback that schedules the item for a duration in minutes. /// Optional callback that schedules the item for a duration in minutes.
final Future<void> Function(int durationMinutes)? onSchedule; final Future<void> Function(int durationMinutes)? onSchedule;
/// 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 @override
State<BacklogRow> createState() => _BacklogRowState(); State<BacklogRow> createState() => _BacklogRowState();
} }
/// Private implementation type for `_BacklogRowState` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _BacklogRowState extends State<BacklogRow> { class _BacklogRowState extends State<BacklogRow> {
/// Stores the `durationController` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final durationController = TextEditingController(); final durationController = TextEditingController();
/// Releases resources owned by this object before it leaves the tree.
/// Controllers, listeners, and other disposable collaborators should be cleaned up here to avoid stale callbacks.
@override @override
void dispose() { void dispose() {
durationController.dispose(); durationController.dispose();
super.dispose(); super.dispose();
} }
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme; final scheme = Theme.of(context).colorScheme;
@ -175,6 +192,8 @@ class StalenessMarker extends StatelessWidget {
/// Staleness marker value to render. /// Staleness marker value to render.
final BacklogStalenessMarker marker; final BacklogStalenessMarker marker;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Icon( return Icon(
@ -192,6 +211,8 @@ class NoticeBanner extends StatelessWidget {
/// Notice message to display. /// Notice message to display.
final String message; final String message;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
@ -216,6 +237,8 @@ String timeText(TimelineItem item) {
return '${_clockText(start)}-${_clockText(end)}'; return '${_clockText(start)}-${_clockText(end)}';
} }
/// Top-level helper that performs the `_clockText` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
String _clockText(DateTime value) { String _clockText(DateTime value) {
final hour = value.hour.toString().padLeft(2, '0'); final hour = value.hour.toString().padLeft(2, '0');
final minute = value.minute.toString().padLeft(2, '0'); final minute = value.minute.toString().padLeft(2, '0');

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders the Sidebar widget for the FocusFlow Flutter UI. /// Renders the Sidebar widget for the FocusFlow Flutter UI.
library; library;
@ -10,6 +13,8 @@ class Sidebar extends StatelessWidget {
/// Creates the FocusFlow sidebar. /// Creates the FocusFlow sidebar.
const Sidebar({super.key}); const Sidebar({super.key});
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DecoratedBox( return DecoratedBox(
@ -46,9 +51,15 @@ class Sidebar extends StatelessWidget {
} }
} }
/// Private implementation type for `_WindowControls` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _WindowControls extends StatelessWidget { class _WindowControls extends StatelessWidget {
/// Creates a `_WindowControls` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _WindowControls(); const _WindowControls();
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const Row( return const Row(
@ -63,11 +74,19 @@ class _WindowControls extends StatelessWidget {
} }
} }
/// Private implementation type for `_WindowDot` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _WindowDot extends StatelessWidget { class _WindowDot extends StatelessWidget {
/// Creates a `_WindowDot` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _WindowDot({required this.color}); const _WindowDot({required this.color});
/// Stores the `color` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color color; final Color color;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DecoratedBox( return DecoratedBox(
@ -77,9 +96,15 @@ class _WindowDot extends StatelessWidget {
} }
} }
/// Private implementation type for `_BrandRow` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _BrandRow extends StatelessWidget { class _BrandRow extends StatelessWidget {
/// Creates a `_BrandRow` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _BrandRow(); const _BrandRow();
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Row(
@ -111,7 +136,11 @@ class _BrandRow extends StatelessWidget {
} }
} }
/// Private implementation type for `_NavItem` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _NavItem extends StatelessWidget { class _NavItem extends StatelessWidget {
/// Creates a `_NavItem` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _NavItem({ const _NavItem({
required this.label, required this.label,
required this.icon, required this.icon,
@ -119,11 +148,24 @@ class _NavItem extends StatelessWidget {
this.active = false, this.active = false,
}); });
/// Stores the `label` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final String label; final String label;
/// Stores the `icon` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final IconData icon; final IconData icon;
/// Stores the `onTap` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final VoidCallback onTap; final VoidCallback onTap;
/// Stores the `active` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final bool active; final bool active;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final color = active final color = active

View file

@ -1,11 +1,25 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_selection_modal.dart'; part of '../task_selection_modal.dart';
/// Private implementation type for `_ActionButton` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _ActionButton extends StatelessWidget { class _ActionButton extends StatelessWidget {
/// Creates a `_ActionButton` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _ActionButton({required this.icon, required this.label}); const _ActionButton({required this.icon, required this.label});
/// Stores the `icon` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final IconData icon; final IconData icon;
/// Stores the `label` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final String label; final String label;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return OutlinedButton.icon( return OutlinedButton.icon(

View file

@ -1,10 +1,21 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_selection_modal.dart'; part of '../task_selection_modal.dart';
/// Private implementation type for `_HeaderMetadata` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _HeaderMetadata extends StatelessWidget { class _HeaderMetadata extends StatelessWidget {
/// Creates a `_HeaderMetadata` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _HeaderMetadata({required this.card}); const _HeaderMetadata({required this.card});
/// Stores the `card` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TimelineCardModel card; final TimelineCardModel card;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
const metadataStyle = TextStyle( const metadataStyle = TextStyle(

View file

@ -1,11 +1,25 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_selection_modal.dart'; part of '../task_selection_modal.dart';
/// Private implementation type for `_InfoTile` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _InfoTile extends StatelessWidget { class _InfoTile extends StatelessWidget {
/// Creates a `_InfoTile` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _InfoTile({required this.child, required this.label}); const _InfoTile({required this.child, required this.label});
/// Stores the `child` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Widget child; final Widget child;
/// Stores the `label` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final String label; final String label;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(

View file

@ -1,5 +1,10 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_selection_modal.dart'; part of '../task_selection_modal.dart';
/// Top-level helper that performs the `_accentFor` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Color _accentFor(TaskVisualKind kind) { Color _accentFor(TaskVisualKind kind) {
return switch (kind) { return switch (kind) {
TaskVisualKind.flexible => FocusFlowTokens.flexibleGreen, TaskVisualKind.flexible => FocusFlowTokens.flexibleGreen,

View file

@ -1,16 +1,33 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_selection_modal.dart'; part of '../task_selection_modal.dart';
/// Private implementation type for `_ModalStatusButton` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _ModalStatusButton extends StatelessWidget { class _ModalStatusButton extends StatelessWidget {
/// Creates a `_ModalStatusButton` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _ModalStatusButton({ const _ModalStatusButton({
required this.card, required this.card,
required this.color, required this.color,
required this.onPressed, required this.onPressed,
}); });
/// Stores the `card` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TimelineCardModel card; final TimelineCardModel card;
/// Stores the `color` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color color; final Color color;
/// Stores the `onPressed` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final VoidCallback? onPressed; final VoidCallback? onPressed;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ring = Container( final ring = Container(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders the Task Selection Modal widget for the FocusFlow Flutter UI. /// Renders the Task Selection Modal widget for the FocusFlow Flutter UI.
library; library;
@ -33,6 +36,8 @@ class TaskSelectionModal extends StatelessWidget {
/// Callback invoked when the status circle should toggle completion. /// Callback invoked when the status circle should toggle completion.
final VoidCallback? onStatusPressed; final VoidCallback? onStatusPressed;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final accent = _accentFor(card.visualKind); final accent = _accentFor(card.visualKind);

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../timeline_axis.dart'; part of '../timeline_axis.dart';
/// Background grid aligned to timeline tick marks. /// Background grid aligned to timeline tick marks.
@ -11,6 +14,8 @@ class TimelineGrid extends StatelessWidget {
/// Vertical inset before the first timeline tick. /// Vertical inset before the first timeline tick.
final double topInset; final double topInset;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return CustomPaint( return CustomPaint(

View file

@ -1,11 +1,25 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../timeline_axis.dart'; part of '../timeline_axis.dart';
/// Private implementation type for `_TimelineGridPainter` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _TimelineGridPainter extends CustomPainter { class _TimelineGridPainter extends CustomPainter {
/// Creates a `_TimelineGridPainter` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _TimelineGridPainter({required this.geometry, required this.topInset}); const _TimelineGridPainter({required this.geometry, required this.topInset});
/// Stores the `geometry` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TimelineGeometry geometry; final TimelineGeometry geometry;
/// Stores the `topInset` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final double topInset; final double topInset;
/// Performs the `paint` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
@override @override
void paint(Canvas canvas, Size size) { void paint(Canvas canvas, Size size) {
final paint = Paint() final paint = Paint()
@ -23,6 +37,8 @@ class _TimelineGridPainter extends CustomPainter {
} }
} }
/// Performs the `shouldRepaint` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
@override @override
bool shouldRepaint(covariant _TimelineGridPainter oldDelegate) { bool shouldRepaint(covariant _TimelineGridPainter oldDelegate) {
return oldDelegate.geometry != geometry || oldDelegate.topInset != topInset; return oldDelegate.geometry != geometry || oldDelegate.topInset != topInset;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders Difficulty Bars pieces for the FocusFlow Flutter timeline. /// Renders Difficulty Bars pieces for the FocusFlow Flutter timeline.
library; library;
@ -49,6 +52,8 @@ class DifficultyBars extends StatelessWidget {
}; };
} }
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return CustomPaint( return CustomPaint(
@ -61,15 +66,26 @@ class DifficultyBars extends StatelessWidget {
} }
} }
/// Private implementation type for `_DifficultyBarsPainter` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _DifficultyBarsPainter extends CustomPainter { class _DifficultyBarsPainter extends CustomPainter {
/// Creates a `_DifficultyBarsPainter` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _DifficultyBarsPainter({ const _DifficultyBarsPainter({
required this.filledCount, required this.filledCount,
required this.color, required this.color,
}); });
/// Stores the `filledCount` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final int filledCount; final int filledCount;
/// Stores the `color` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color color; final Color color;
/// Performs the `paint` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
@override @override
void paint(Canvas canvas, Size size) { void paint(Canvas canvas, Size size) {
final gap = size.width * 0.08; final gap = size.width * 0.08;
@ -98,6 +114,8 @@ class _DifficultyBarsPainter extends CustomPainter {
} }
} }
/// Performs the `shouldRepaint` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
@override @override
bool shouldRepaint(covariant _DifficultyBarsPainter oldDelegate) { bool shouldRepaint(covariant _DifficultyBarsPainter oldDelegate) {
return oldDelegate.filledCount != filledCount || oldDelegate.color != color; return oldDelegate.filledCount != filledCount || oldDelegate.color != color;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders Reward Icon pieces for the FocusFlow Flutter timeline. /// Renders Reward Icon pieces for the FocusFlow Flutter timeline.
library; library;
@ -20,6 +23,8 @@ class RewardIcon extends StatelessWidget {
/// Square size of the painted icon. /// Square size of the painted icon.
final double size; final double size;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return CustomPaint( return CustomPaint(
@ -29,11 +34,19 @@ class RewardIcon extends StatelessWidget {
} }
} }
/// Private implementation type for `_RewardIconPainter` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _RewardIconPainter extends CustomPainter { class _RewardIconPainter extends CustomPainter {
/// Creates a `_RewardIconPainter` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _RewardIconPainter(this.color); const _RewardIconPainter(this.color);
/// Stores the `color` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color color; final Color color;
/// Performs the `paint` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
@override @override
void paint(Canvas canvas, Size size) { void paint(Canvas canvas, Size size) {
final paint = Paint() final paint = Paint()
@ -59,6 +72,8 @@ class _RewardIconPainter extends CustomPainter {
); );
} }
/// Runs the `_drawSparkle` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
void _drawSparkle(Canvas canvas, Paint paint, Offset center, double radius) { void _drawSparkle(Canvas canvas, Paint paint, Offset center, double radius) {
final path = Path() final path = Path()
..moveTo(center.dx, center.dy - radius) ..moveTo(center.dx, center.dy - radius)
@ -73,6 +88,8 @@ class _RewardIconPainter extends CustomPainter {
canvas.drawPath(path, paint); canvas.drawPath(path, paint);
} }
/// Performs the `shouldRepaint` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
@override @override
bool shouldRepaint(covariant _RewardIconPainter oldDelegate) { bool shouldRepaint(covariant _RewardIconPainter oldDelegate) {
return oldDelegate.color != color; return oldDelegate.color != color;

View file

@ -1,16 +1,33 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_timeline_card.dart'; part of '../task_timeline_card.dart';
/// Private implementation type for `_CardColors` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _CardColors { class _CardColors {
/// Creates a `_CardColors` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _CardColors({ const _CardColors({
required this.accent, required this.accent,
required this.background, required this.background,
required this.reward, required this.reward,
}); });
/// Stores the `accent` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color accent; final Color accent;
/// Stores the `background` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color background; final Color background;
/// Stores the `reward` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color reward; final Color reward;
/// Creates a `_CardColors.forKind` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
factory _CardColors.forKind(TaskVisualKind kind) { factory _CardColors.forKind(TaskVisualKind kind) {
return switch (kind) { return switch (kind) {
TaskVisualKind.flexible => const _CardColors( TaskVisualKind.flexible => const _CardColors(

View file

@ -1,14 +1,37 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_timeline_card.dart'; part of '../task_timeline_card.dart';
/// Private implementation type for `_CardMetrics` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _CardMetrics { class _CardMetrics {
/// Creates a `_CardMetrics` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _CardMetrics({required this.scale, required this.height}); const _CardMetrics({required this.scale, required this.height});
/// Shared constant value for `_referenceWidth`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _referenceWidth = 640.0; static const _referenceWidth = 640.0;
/// Shared constant value for `_referenceHeight`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _referenceHeight = 88.0; static const _referenceHeight = 88.0;
/// Shared constant value for `_freeSlotReferenceHeight`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _freeSlotReferenceHeight = 108.0; static const _freeSlotReferenceHeight = 108.0;
/// Shared constant value for `_compactHeightThreshold`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _compactHeightThreshold = 56.0; static const _compactHeightThreshold = 56.0;
/// Shared constant value for `_minimumScale`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _minimumScale = 0.16; static const _minimumScale = 0.16;
/// Creates a `_CardMetrics.fromConstraints` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
factory _CardMetrics.fromConstraints( factory _CardMetrics.fromConstraints(
BoxConstraints constraints, { BoxConstraints constraints, {
required TaskVisualKind kind, required TaskVisualKind kind,
@ -29,42 +52,122 @@ class _CardMetrics {
return _CardMetrics(scale: scale.toDouble(), height: height); return _CardMetrics(scale: scale.toDouble(), height: height);
} }
/// Stores the `scale` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final double scale; final double scale;
/// Stores the `height` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final double height; final double height;
/// Returns the derived `isCompact` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
bool get isCompact => height < _compactHeightThreshold; bool get isCompact => height < _compactHeightThreshold;
/// Returns the derived `cardRadius` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get cardRadius => double get cardRadius =>
math.min(FocusFlowTokens.cardRadius * scale, height / 2); math.min(FocusFlowTokens.cardRadius * scale, height / 2);
/// Returns the derived `borderWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get borderWidth => math.max(0.75, 1.2 * scale); double get borderWidth => math.max(0.75, 1.2 * scale);
/// Returns the derived `shadowBlur` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get shadowBlur => isCompact ? 0 : 18 * scale; double get shadowBlur => isCompact ? 0 : 18 * scale;
/// Returns the derived `shadowSpread` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get shadowSpread => isCompact ? 0 : scale; double get shadowSpread => isCompact ? 0 : scale;
/// Returns the derived `statusRingSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get statusRingSize { double get statusRingSize {
final availableHeight = math.max(8, height - padding.vertical); final availableHeight = math.max(8, height - padding.vertical);
return math.min(24, availableHeight * 0.78).toDouble(); return math.min(24, availableHeight * 0.78).toDouble();
} }
/// Returns the derived `statusBorderWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get statusBorderWidth => math.max(1.4, statusRingSize * 0.08); double get statusBorderWidth => math.max(1.4, statusRingSize * 0.08);
/// Returns the derived `statusIconSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get statusIconSize => statusRingSize * 0.58; double get statusIconSize => statusRingSize * 0.58;
/// Returns the derived `statusGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get statusGap => isCompact ? 7 : 22 * scale; double get statusGap => isCompact ? 7 : 22 * scale;
/// Returns the derived `actionButtonSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get actionButtonSize => (30 * scale).clamp(14.0, 22.0).toDouble(); double get actionButtonSize => (30 * scale).clamp(14.0, 22.0).toDouble();
/// Returns the derived `actionIconSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get actionIconSize => (16 * scale).clamp(9.0, 13.0).toDouble(); double get actionIconSize => (16 * scale).clamp(9.0, 13.0).toDouble();
/// Returns the derived `actionGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get actionGap => math.max(3, 5 * scale); double get actionGap => math.max(3, 5 * scale);
/// Returns the derived `actionsWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get actionsWidth => actionButtonSize * 4 + actionGap; double get actionsWidth => actionButtonSize * 4 + actionGap;
/// Returns the derived `indicatorTop` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get indicatorTop => isCompact ? 0 : math.max(1, 2 * scale); double get indicatorTop => isCompact ? 0 : math.max(1, 2 * scale);
/// Returns the derived `indicatorGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get indicatorGap => math.max(3, 5 * scale); double get indicatorGap => math.max(3, 5 * scale);
/// Returns the derived `rewardIconSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get rewardIconSize => 14; double get rewardIconSize => 14;
/// Returns the derived `titleSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get titleSize => 10; double get titleSize => 10;
/// Returns the derived `metaSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get metaSize => 7; double get metaSize => 7;
/// Returns the derived `titleMetaGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get titleMetaGap => 4 * scale; double get titleMetaGap => 4 * scale;
/// Returns the derived `freeSlotTimeGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get freeSlotTimeGap => 10 * scale; double get freeSlotTimeGap => 10 * scale;
/// Returns the derived `compactTextGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get compactTextGap => math.max(3, 8 * scale); double get compactTextGap => math.max(3, 8 * scale);
/// Returns the derived `indicatorWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get indicatorWidth => double get indicatorWidth =>
rewardIconSize + indicatorGap + difficultySize.width; rewardIconSize + indicatorGap + difficultySize.width;
/// Returns the derived `expandedTrailingReserve` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get expandedTrailingReserve => double get expandedTrailingReserve =>
indicatorWidth + math.max(8, 12 * scale); indicatorWidth + math.max(8, 12 * scale);
/// Returns the derived `compactTrailingReserve` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get compactTrailingReserve => indicatorWidth + math.max(6, 8 * scale); double get compactTrailingReserve => indicatorWidth + math.max(6, 8 * scale);
/// Returns the derived `difficultySize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
Size get difficultySize => Size(26, 14); Size get difficultySize => Size(26, 14);
/// Returns the derived `padding` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
EdgeInsets get padding { EdgeInsets get padding {
if (isCompact) { if (isCompact) {
return EdgeInsets.symmetric( return EdgeInsets.symmetric(

View file

@ -1,16 +1,33 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_timeline_card.dart'; part of '../task_timeline_card.dart';
/// Private implementation type for `_CardText` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _CardText extends StatelessWidget { class _CardText extends StatelessWidget {
/// Creates a `_CardText` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _CardText({ const _CardText({
required this.card, required this.card,
required this.color, required this.color,
required this.metrics, required this.metrics,
}); });
/// Stores the `card` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TimelineCardModel card; final TimelineCardModel card;
/// Stores the `color` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color color; final Color color;
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _CardMetrics metrics; final _CardMetrics metrics;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final titleStyle = TextStyle( final titleStyle = TextStyle(

View file

@ -1,6 +1,13 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_timeline_card.dart'; part of '../task_timeline_card.dart';
/// Private implementation type for `_CompactCardText` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _CompactCardText extends StatelessWidget { class _CompactCardText extends StatelessWidget {
/// Creates a `_CompactCardText` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _CompactCardText({ const _CompactCardText({
required this.card, required this.card,
required this.color, required this.color,
@ -8,11 +15,24 @@ class _CompactCardText extends StatelessWidget {
required this.onStatusPressed, required this.onStatusPressed,
}); });
/// Stores the `card` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TimelineCardModel card; final TimelineCardModel card;
/// Stores the `color` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color color; final Color color;
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _CardMetrics metrics; final _CardMetrics metrics;
/// Stores the `onStatusPressed` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final VoidCallback? onStatusPressed; final VoidCallback? onStatusPressed;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final metaText = _compactMetaText(card); final metaText = _compactMetaText(card);
@ -83,6 +103,8 @@ class _CompactCardText extends StatelessWidget {
); );
} }
/// Runs the `_compactMetaText` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
String _compactMetaText(TimelineCardModel card) { String _compactMetaText(TimelineCardModel card) {
if (card.visualKind == TaskVisualKind.freeSlot && if (card.visualKind == TaskVisualKind.freeSlot &&
card.timeText.isNotEmpty) { card.timeText.isNotEmpty) {

View file

@ -1,6 +1,13 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_timeline_card.dart'; part of '../task_timeline_card.dart';
/// Private implementation type for `_ExpandedCardContent` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _ExpandedCardContent extends StatelessWidget { class _ExpandedCardContent extends StatelessWidget {
/// Creates a `_ExpandedCardContent` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _ExpandedCardContent({ const _ExpandedCardContent({
required this.card, required this.card,
required this.colors, required this.colors,
@ -8,11 +15,24 @@ class _ExpandedCardContent extends StatelessWidget {
required this.onStatusPressed, required this.onStatusPressed,
}); });
/// Stores the `card` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TimelineCardModel card; final TimelineCardModel card;
/// Stores the `colors` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _CardColors colors; final _CardColors colors;
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _CardMetrics metrics; final _CardMetrics metrics;
/// Stores the `onStatusPressed` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final VoidCallback? onStatusPressed; final VoidCallback? onStatusPressed;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Row(

View file

@ -1,16 +1,33 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_timeline_card.dart'; part of '../task_timeline_card.dart';
/// Private implementation type for `_NoOpIcon` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _NoOpIcon extends StatelessWidget { class _NoOpIcon extends StatelessWidget {
/// Creates a `_NoOpIcon` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _NoOpIcon({ const _NoOpIcon({
required this.icon, required this.icon,
required this.color, required this.color,
required this.metrics, required this.metrics,
}); });
/// Stores the `icon` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final IconData icon; final IconData icon;
/// Stores the `color` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color color; final Color color;
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _CardMetrics metrics; final _CardMetrics metrics;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Tooltip( return Tooltip(

View file

@ -1,6 +1,13 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_timeline_card.dart'; part of '../task_timeline_card.dart';
/// Private implementation type for `_QuickActions` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _QuickActions extends StatelessWidget { class _QuickActions extends StatelessWidget {
/// Creates a `_QuickActions` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _QuickActions({ const _QuickActions({
required this.color, required this.color,
required this.backgroundColor, required this.backgroundColor,
@ -8,11 +15,24 @@ class _QuickActions extends StatelessWidget {
required this.visible, required this.visible,
}); });
/// Stores the `color` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color color; final Color color;
/// Stores the `backgroundColor` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color backgroundColor; final Color backgroundColor;
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _CardMetrics metrics; final _CardMetrics metrics;
/// Stores the `visible` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final bool visible; final bool visible;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ExcludeSemantics( return ExcludeSemantics(

View file

@ -1,6 +1,13 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_timeline_card.dart'; part of '../task_timeline_card.dart';
/// Private implementation type for `_StatusRing` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _StatusRing extends StatelessWidget { class _StatusRing extends StatelessWidget {
/// Creates a `_StatusRing` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _StatusRing({ const _StatusRing({
required this.card, required this.card,
required this.color, required this.color,
@ -8,11 +15,24 @@ class _StatusRing extends StatelessWidget {
this.onPressed, this.onPressed,
}); });
/// Stores the `card` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TimelineCardModel card; final TimelineCardModel card;
/// Stores the `color` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final Color color; final Color color;
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _CardMetrics metrics; final _CardMetrics metrics;
/// Stores the `onPressed` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final VoidCallback? onPressed; final VoidCallback? onPressed;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final border = Border.all(color: color, width: metrics.statusBorderWidth); final border = Border.all(color: color, width: metrics.statusBorderWidth);

View file

@ -1,8 +1,17 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_timeline_card.dart'; part of '../task_timeline_card.dart';
/// Private implementation type for `_TaskTimelineCardState` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _TaskTimelineCardState extends State<TaskTimelineCard> { class _TaskTimelineCardState extends State<TaskTimelineCard> {
/// Private state stored as `_isHovered` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
bool _isHovered = false; bool _isHovered = false;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final card = widget.card; final card = widget.card;

View file

@ -1,6 +1,13 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../task_timeline_card.dart'; part of '../task_timeline_card.dart';
/// Private implementation type for `_TrailingControls` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _TrailingControls extends StatelessWidget { class _TrailingControls extends StatelessWidget {
/// Creates a `_TrailingControls` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _TrailingControls({ const _TrailingControls({
required this.card, required this.card,
required this.colors, required this.colors,
@ -8,11 +15,24 @@ class _TrailingControls extends StatelessWidget {
required this.actionsVisible, required this.actionsVisible,
}); });
/// Stores the `card` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TimelineCardModel card; final TimelineCardModel card;
/// Stores the `colors` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _CardColors colors; final _CardColors colors;
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _CardMetrics metrics; final _CardMetrics metrics;
/// Stores the `actionsVisible` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final bool actionsVisible; final bool actionsVisible;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Row(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders Task Timeline Card pieces for the FocusFlow Flutter timeline. /// Renders Task Timeline Card pieces for the FocusFlow Flutter timeline.
library; library;
@ -40,6 +43,8 @@ class TaskTimelineCard extends StatefulWidget {
/// Callback invoked when the left status control is clicked. /// Callback invoked when the left status control is clicked.
final VoidCallback? onStatusPressed; final VoidCallback? onStatusPressed;
/// 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 @override
State<TaskTimelineCard> createState() => _TaskTimelineCardState(); State<TaskTimelineCard> createState() => _TaskTimelineCardState();
} }

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders Timeline Axis pieces for the FocusFlow Flutter timeline. /// Renders Timeline Axis pieces for the FocusFlow Flutter timeline.
library; library;
@ -20,6 +23,8 @@ class TimelineAxis extends StatelessWidget {
/// Vertical inset before the first timeline tick. /// Vertical inset before the first timeline tick.
final double topInset; final double topInset;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ticks = geometry.ticks(); final ticks = geometry.ticks();

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders Timeline Geometry pieces for the FocusFlow Flutter timeline. /// Renders Timeline Geometry pieces for the FocusFlow Flutter timeline.
library; library;
@ -60,6 +63,8 @@ class TimelineGeometry {
]; ];
} }
/// Performs the `operator ==` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || return identical(this, other) ||
@ -70,6 +75,8 @@ class TimelineGeometry {
other.minCardHeight == minCardHeight; other.minCardHeight == minCardHeight;
} }
/// Returns the derived `hashCode` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
@override @override
int get hashCode { int get hashCode {
return Object.hash( return Object.hash(
@ -80,6 +87,8 @@ class TimelineGeometry {
); );
} }
/// Runs the `_labelFor` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
static String _labelFor(int minutes) { static String _labelFor(int minutes) {
final hour24 = (minutes ~/ 60) % 24; final hour24 = (minutes ~/ 60) % 24;
final minute = minutes % 60; final minute = minutes % 60;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders Timeline View pieces for the FocusFlow Flutter timeline. /// Renders Timeline View pieces for the FocusFlow Flutter timeline.
library; library;
@ -49,6 +52,8 @@ class TimelineView extends StatefulWidget {
/// Monotonic request number that allows repeated jumps to the same card. /// Monotonic request number that allows repeated jumps to the same card.
final int scrollRequest; 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 @override
State<TimelineView> createState() => _TimelineViewState(); State<TimelineView> createState() => _TimelineViewState();
} }

View file

@ -1,6 +1,13 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../timeline_view.dart'; part of '../timeline_view.dart';
/// Private implementation type for `_TimelineCardPlacement` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _TimelineCardPlacement { class _TimelineCardPlacement {
/// Creates a `_TimelineCardPlacement` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _TimelineCardPlacement({ const _TimelineCardPlacement({
required this.card, required this.card,
required this.lane, required this.lane,
@ -9,14 +16,32 @@ class _TimelineCardPlacement {
required this.height, required this.height,
}); });
/// Shared constant value for `_laneGap`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _laneGap = 8.0; static const _laneGap = 8.0;
/// Stores the `card` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final TimelineCardModel card; final TimelineCardModel card;
/// Stores the `lane` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final int lane; final int lane;
/// Stores the `laneCount` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final int laneCount; final int laneCount;
/// Stores the `top` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final double top; final double top;
/// Stores the `height` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final double height; final double height;
/// Performs the `withCard` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
_TimelineCardPlacement withCard(TimelineCardModel nextCard) { _TimelineCardPlacement withCard(TimelineCardModel nextCard) {
if (identical(card, nextCard)) { if (identical(card, nextCard)) {
return this; return this;
@ -30,6 +55,8 @@ class _TimelineCardPlacement {
); );
} }
/// Performs the `pack` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
static List<_TimelineCardPlacement> pack( static List<_TimelineCardPlacement> pack(
List<TimelineCardModel> cards, { List<TimelineCardModel> cards, {
required TimelineGeometry geometry, required TimelineGeometry geometry,
@ -74,6 +101,8 @@ class _TimelineCardPlacement {
return placements; return placements;
} }
/// Runs the `_packGroup` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
static List<_TimelineCardPlacement> _packGroup( static List<_TimelineCardPlacement> _packGroup(
List<TimelineCardModel> group, { List<TimelineCardModel> group, {
required TimelineGeometry geometry, required TimelineGeometry geometry,
@ -113,6 +142,8 @@ class _TimelineCardPlacement {
]; ];
} }
/// Runs the `_visualStart` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
static double _visualStart( static double _visualStart(
TimelineCardModel card, TimelineCardModel card,
TimelineGeometry geometry, TimelineGeometry geometry,
@ -120,21 +151,29 @@ class _TimelineCardPlacement {
return geometry.yForMinutesSinceMidnight(card.startMinutes); return geometry.yForMinutesSinceMidnight(card.startMinutes);
} }
/// Runs the `_visualEnd` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
static double _visualEnd(TimelineCardModel card, TimelineGeometry geometry) { static double _visualEnd(TimelineCardModel card, TimelineGeometry geometry) {
final duration = card.endMinutes - card.startMinutes; final duration = card.endMinutes - card.startMinutes;
return _visualStart(card, geometry) + geometry.heightForDuration(duration); return _visualStart(card, geometry) + geometry.heightForDuration(duration);
} }
/// Performs the `left` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
double left(double trackWidth) { double left(double trackWidth) {
final laneWidth = _laneWidth(trackWidth); final laneWidth = _laneWidth(trackWidth);
final laneGap = _laneGapForWidth(trackWidth); final laneGap = _laneGapForWidth(trackWidth);
return FocusFlowTokens.cardHorizontalPadding + lane * (laneWidth + laneGap); return FocusFlowTokens.cardHorizontalPadding + lane * (laneWidth + laneGap);
} }
/// Performs the `width` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
double width(double trackWidth) { double width(double trackWidth) {
return _laneWidth(trackWidth); return _laneWidth(trackWidth);
} }
/// Runs the `_availableWidth` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
double _availableWidth(double trackWidth) { double _availableWidth(double trackWidth) {
final availableWidth = trackWidth - FocusFlowTokens.cardHorizontalPadding; final availableWidth = trackWidth - FocusFlowTokens.cardHorizontalPadding;
if (availableWidth < 0) { if (availableWidth < 0) {
@ -143,12 +182,16 @@ class _TimelineCardPlacement {
return availableWidth; return availableWidth;
} }
/// Runs the `_laneWidth` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
double _laneWidth(double trackWidth) { double _laneWidth(double trackWidth) {
final availableWidth = _availableWidth(trackWidth); final availableWidth = _availableWidth(trackWidth);
final laneGap = _laneGapForWidth(trackWidth); final laneGap = _laneGapForWidth(trackWidth);
return (availableWidth - laneGap * (laneCount - 1)) / laneCount; return (availableWidth - laneGap * (laneCount - 1)) / laneCount;
} }
/// Runs the `_laneGapForWidth` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
double _laneGapForWidth(double trackWidth) { double _laneGapForWidth(double trackWidth) {
if (laneCount == 1) { if (laneCount == 1) {
return 0; return 0;

View file

@ -1,8 +1,17 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../timeline_view.dart'; part of '../timeline_view.dart';
/// Private implementation type for `_TimelineScrollBehavior` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _TimelineScrollBehavior extends MaterialScrollBehavior { class _TimelineScrollBehavior extends MaterialScrollBehavior {
/// Creates a `_TimelineScrollBehavior` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _TimelineScrollBehavior(); const _TimelineScrollBehavior();
/// Returns the derived `dragDevices` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
@override @override
Set<PointerDeviceKind> get dragDevices { Set<PointerDeviceKind> get dragDevices {
return {...super.dragDevices, PointerDeviceKind.mouse}; return {...super.dragDevices, PointerDeviceKind.mouse};

View file

@ -1,22 +1,53 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../timeline_view.dart'; part of '../timeline_view.dart';
/// Private implementation type for `_TimelineViewState` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _TimelineViewState extends State<TimelineView> { class _TimelineViewState extends State<TimelineView> {
/// Shared constant value for `_topInset`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _topInset = 12.0; static const _topInset = 12.0;
/// Private state stored as `_scrollController` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
final _scrollController = ScrollController(); final _scrollController = ScrollController();
/// Private state stored as `_didSetInitialScroll` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
bool _didSetInitialScroll = false; bool _didSetInitialScroll = false;
/// Private state stored as `_handledScrollRequest` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
var _handledScrollRequest = 0; var _handledScrollRequest = 0;
/// Private state stored as `_geometry` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
late TimelineGeometry _geometry; late TimelineGeometry _geometry;
/// Private state stored as `_contentHeight` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
late double _contentHeight; late double _contentHeight;
/// Private state stored as `_placements` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
late List<_TimelineCardPlacement> _placements; late List<_TimelineCardPlacement> _placements;
/// Private state stored as `_cardsLayoutHash` for this implementation.
/// The field is intentionally scoped to this library so only the owning type can change the related scheduler or UI behavior.
late int _cardsLayoutHash; late int _cardsLayoutHash;
/// Initializes state owned by this object before the first build.
/// Use this lifecycle point for controller setup, initial reads, and listener wiring that must happen once per mounted instance.
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_updateLayoutCache(); _updateLayoutCache();
} }
/// Performs the `didUpdateWidget` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
@override @override
void didUpdateWidget(covariant TimelineView oldWidget) { void didUpdateWidget(covariant TimelineView oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
@ -34,12 +65,16 @@ class _TimelineViewState extends State<TimelineView> {
} }
} }
/// Releases resources owned by this object before it leaves the tree.
/// Controllers, listeners, and other disposable collaborators should be cleaned up here to avoid stale callbacks.
@override @override
void dispose() { void dispose() {
_scrollController.dispose(); _scrollController.dispose();
super.dispose(); super.dispose();
} }
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return LayoutBuilder( return LayoutBuilder(
@ -111,6 +146,8 @@ class _TimelineViewState extends State<TimelineView> {
); );
} }
/// Runs the `_updateLayoutCache` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
void _updateLayoutCache() { void _updateLayoutCache() {
_geometry = TimelineGeometry( _geometry = TimelineGeometry(
startMinutes: widget.range.startMinutes, startMinutes: widget.range.startMinutes,
@ -125,6 +162,8 @@ class _TimelineViewState extends State<TimelineView> {
_cardsLayoutHash = _layoutHashFor(widget.cards); _cardsLayoutHash = _layoutHashFor(widget.cards);
} }
/// Runs the `_layoutHashFor` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
int _layoutHashFor(List<TimelineCardModel> cards) { int _layoutHashFor(List<TimelineCardModel> cards) {
return Object.hashAll( return Object.hashAll(
cards.map( cards.map(
@ -133,6 +172,8 @@ class _TimelineViewState extends State<TimelineView> {
); );
} }
/// Runs the `_refreshPlacementCards` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
void _refreshPlacementCards() { void _refreshPlacementCards() {
final cardsById = {for (final card in widget.cards) card.id: card}; final cardsById = {for (final card in widget.cards) card.id: card};
_placements = [ _placements = [
@ -141,6 +182,8 @@ class _TimelineViewState extends State<TimelineView> {
]; ];
} }
/// Runs the `_scheduleInitialScroll` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
void _scheduleInitialScroll( void _scheduleInitialScroll(
TimelineGeometry geometry, TimelineGeometry geometry,
double viewportHeight, double viewportHeight,
@ -168,6 +211,8 @@ class _TimelineViewState extends State<TimelineView> {
}); });
} }
/// Runs the `_scheduleTargetScroll` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
void _scheduleTargetScroll(TimelineGeometry geometry) { void _scheduleTargetScroll(TimelineGeometry geometry) {
final targetCardId = widget.scrollTargetCardId; final targetCardId = widget.scrollTargetCardId;
if (targetCardId == null || widget.scrollRequest == _handledScrollRequest) { if (targetCardId == null || widget.scrollRequest == _handledScrollRequest) {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders the Today Pane widget for the FocusFlow Flutter UI. /// Renders the Today Pane widget for the FocusFlow Flutter UI.
library; library;
@ -24,6 +27,8 @@ class TodayPane extends StatelessWidget {
/// Optional command controller for Today actions. /// Optional command controller for Today actions.
final SchedulerCommandController? commandController; final SchedulerCommandController? commandController;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ReadStateView<TodayState>( return ReadStateView<TodayState>(
@ -48,6 +53,8 @@ class TodayContent extends StatelessWidget {
/// Optional command controller for completing tasks. /// Optional command controller for completing tasks.
final SchedulerCommandController? commandController; final SchedulerCommandController? commandController;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListView( return ListView(
@ -75,6 +82,8 @@ class TodayContent extends StatelessWidget {
); );
} }
/// Runs the `_canComplete` helper used inside this library.
/// The helper centralizes a small piece of transformation or validation so higher-level scheduler flow remains easier to read.
bool _canComplete(TodayTimelineItem item) { bool _canComplete(TodayTimelineItem item) {
return item.taskType == TaskType.flexible && return item.taskType == TaskType.flexible &&
item.taskStatus == TaskStatus.planned && item.taskStatus == TaskStatus.planned &&

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Renders the Top Bar widget for the FocusFlow Flutter UI. /// Renders the Top Bar widget for the FocusFlow Flutter UI.
library; library;
@ -18,6 +21,8 @@ class TopBar extends StatelessWidget {
/// Date label shown beside the date navigation controls. /// Date label shown beside the date navigation controls.
final String dateLabel; final String dateLabel;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return LayoutBuilder( return LayoutBuilder(

View file

@ -1,16 +1,33 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../top_bar.dart'; part of '../top_bar.dart';
/// Private implementation type for `_IconButton` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _IconButton extends StatelessWidget { class _IconButton extends StatelessWidget {
/// Creates a `_IconButton` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _IconButton({ const _IconButton({
required this.icon, required this.icon,
required this.metrics, required this.metrics,
required this.onPressed, required this.onPressed,
}); });
/// Stores the `icon` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final IconData icon; final IconData icon;
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _TopBarMetrics metrics; final _TopBarMetrics metrics;
/// Stores the `onPressed` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final VoidCallback onPressed; final VoidCallback onPressed;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return IconButton( return IconButton(

View file

@ -1,38 +1,116 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../top_bar.dart'; part of '../top_bar.dart';
/// Private implementation type for `_TopBarMetrics` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _TopBarMetrics { class _TopBarMetrics {
/// Creates a `_TopBarMetrics` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _TopBarMetrics(this.scale); const _TopBarMetrics(this.scale);
/// Shared constant value for `referenceHeight`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const referenceHeight = 48.0; static const referenceHeight = 48.0;
/// Shared constant value for `_referenceWidth`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _referenceWidth = 900.0; static const _referenceWidth = 900.0;
/// Shared constant value for `_minimumScale`.
/// The constant gives this repeated scheduler or UI value one documented source of truth instead of scattering literals across call sites.
static const _minimumScale = 0.44; static const _minimumScale = 0.44;
/// Creates a `_TopBarMetrics.fromWidth` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
factory _TopBarMetrics.fromWidth(double width) { factory _TopBarMetrics.fromWidth(double width) {
final safeWidth = width.isFinite ? width : _referenceWidth; final safeWidth = width.isFinite ? width : _referenceWidth;
final scale = (safeWidth / _referenceWidth).clamp(_minimumScale, 1.0); final scale = (safeWidth / _referenceWidth).clamp(_minimumScale, 1.0);
return _TopBarMetrics(scale.toDouble()); return _TopBarMetrics(scale.toDouble());
} }
/// Stores the `scale` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final double scale; final double scale;
/// Returns the derived `titleWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get titleWidth => 112 * scale; double get titleWidth => 112 * scale;
/// Returns the derived `titleSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get titleSize => FocusFlowTokens.pageTitleSize * scale; double get titleSize => FocusFlowTokens.pageTitleSize * scale;
/// Returns the derived `titleGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get titleGap => 30 * scale; double get titleGap => 30 * scale;
/// Returns the derived `controlHeight` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get controlHeight => referenceHeight * scale; double get controlHeight => referenceHeight * scale;
/// Returns the derived `iconButtonSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get iconButtonSize => referenceHeight * scale; double get iconButtonSize => referenceHeight * scale;
/// Returns the derived `iconSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get iconSize => 24 * scale; double get iconSize => 24 * scale;
/// Returns the derived `dateWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get dateWidth => 144 * scale; double get dateWidth => 144 * scale;
/// Returns the derived `dateSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get dateSize => 17 * scale; double get dateSize => 17 * scale;
/// Returns the derived `modeWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get modeWidth => 220 * scale; double get modeWidth => 220 * scale;
/// Returns the derived `modeHeight` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get modeHeight => referenceHeight * scale; double get modeHeight => referenceHeight * scale;
/// Returns the derived `modeLabelSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get modeLabelSize => 17 * scale; double get modeLabelSize => 17 * scale;
/// Returns the derived `settingsGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get settingsGap => 28 * scale; double get settingsGap => 28 * scale;
/// Returns the derived `settingsWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get settingsWidth => 136 * scale; double get settingsWidth => 136 * scale;
/// Returns the derived `settingsHeight` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get settingsHeight => referenceHeight * scale; double get settingsHeight => referenceHeight * scale;
/// Returns the derived `settingsIconSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get settingsIconSize => 20 * scale; double get settingsIconSize => 20 * scale;
/// Returns the derived `settingsTextSize` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get settingsTextSize => 15 * scale; double get settingsTextSize => 15 * scale;
/// Returns the derived `settingsTextGap` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get settingsTextGap => 8 * scale; double get settingsTextGap => 8 * scale;
/// Returns the derived `borderRadius` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get borderRadius => FocusFlowTokens.smallButtonRadius * scale; double get borderRadius => FocusFlowTokens.smallButtonRadius * scale;
/// Returns the derived `borderWidth` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
double get borderWidth => scale < 0.7 ? 0.8 : 1; double get borderWidth => scale < 0.7 ? 0.8 : 1;
/// Returns the derived `buttonPadding` value for this object.
/// Keeping this as an accessor gives callers a stable read surface while the owning type controls how the value is calculated.
EdgeInsets get buttonPadding => EdgeInsets.symmetric(horizontal: 12 * scale); EdgeInsets get buttonPadding => EdgeInsets.symmetric(horizontal: 12 * scale);
} }

View file

@ -1,10 +1,21 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../top_bar.dart'; part of '../top_bar.dart';
/// Private implementation type for `_ModeToggle` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _ModeToggle extends StatelessWidget { class _ModeToggle extends StatelessWidget {
/// Creates a `_ModeToggle` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _ModeToggle({required this.metrics}); const _ModeToggle({required this.metrics});
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _TopBarMetrics metrics; final _TopBarMetrics metrics;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(

View file

@ -1,10 +1,21 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../top_bar.dart'; part of '../top_bar.dart';
/// Private implementation type for `_SettingsButton` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _SettingsButton extends StatelessWidget { class _SettingsButton extends StatelessWidget {
/// Creates a `_SettingsButton` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _SettingsButton({required this.metrics}); const _SettingsButton({required this.metrics});
/// Stores the `metrics` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final _TopBarMetrics metrics; final _TopBarMetrics metrics;
/// Builds the widget subtree for this component.
/// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return OutlinedButton( return OutlinedButton(

View file

@ -1,3 +1,6 @@
# SPDX-FileCopyrightText: 2026 FocusFlow contributors
# SPDX-License-Identifier: AGPL-3.0-only
name: focus_flow_flutter name: focus_flow_flutter
description: Provisional Flutter UI foundation for FocusFlow. description: Provisional Flutter UI foundation for FocusFlow.
publish_to: 'none' publish_to: 'none'

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Tests Forbidden Imports behavior in the FocusFlow Flutter app. /// Tests Forbidden Imports behavior in the FocusFlow Flutter app.
library; library;
@ -33,6 +36,8 @@ void main() {
}); });
} }
/// Top-level helper that performs the `_dartFiles` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Iterable<File> _dartFiles(Directory directory) { Iterable<File> _dartFiles(Directory directory) {
if (!directory.existsSync()) { if (!directory.existsSync()) {
return const <File>[]; return const <File>[];
@ -43,6 +48,8 @@ Iterable<File> _dartFiles(Directory directory) {
.where((file) => file.path.endsWith('.dart')); .where((file) => file.path.endsWith('.dart'));
} }
/// Top-level helper that performs the `_forbiddenImportsFor` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
List<_ForbiddenImport> _forbiddenImportsFor(String relativePath) { List<_ForbiddenImport> _forbiddenImportsFor(String relativePath) {
return [ return [
const _ForbiddenImport( const _ForbiddenImport(
@ -69,12 +76,23 @@ List<_ForbiddenImport> _forbiddenImportsFor(String relativePath) {
]; ];
} }
/// Private implementation type for `_ForbiddenImport` in this library.
/// It keeps supporting state and behavior scoped to the owning file so the public API stays focused on the scheduler concepts that callers use directly.
class _ForbiddenImport { class _ForbiddenImport {
/// Creates a `_ForbiddenImport` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const _ForbiddenImport(this.pattern, this.label); const _ForbiddenImport(this.pattern, this.label);
/// Stores the `pattern` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final String pattern; final String pattern;
/// Stores the `label` value for this object.
/// This field is part of the explicit state that downstream scheduling, persistence, or UI code reads when composing behavior.
final String label; final String label;
/// Performs the `matches` behavior for this scheduler component.
/// The method provides a named entry point for this operation so callers do not need to know the lower-level state or persistence steps involved.
bool matches(String contents) { bool matches(String contents) {
return RegExp( return RegExp(
r'''import\s+['"]''' + RegExp.escape(pattern), r'''import\s+['"]''' + RegExp.escape(pattern),

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Tests Widget behavior in the FocusFlow Flutter app. /// Tests Widget behavior in the FocusFlow Flutter app.
library; library;
@ -625,6 +628,8 @@ void main() {
}); });
} }
/// Top-level helper that performs the `_pumpPlanApp` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Future<void> _pumpPlanApp( Future<void> _pumpPlanApp(
WidgetTester tester, { WidgetTester tester, {
DemoSchedulerComposition? composition, DemoSchedulerComposition? composition,
@ -637,10 +642,14 @@ Future<void> _pumpPlanApp(
await tester.pumpAndSettle(); await tester.pumpAndSettle();
} }
/// Top-level helper that performs the `_composition` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
DemoSchedulerComposition _composition() { DemoSchedulerComposition _composition() {
return DemoSchedulerComposition.seeded(selectedDate: CivilDate(2025, 5, 20)); return DemoSchedulerComposition.seeded(selectedDate: CivilDate(2025, 5, 20));
} }
/// Top-level helper that performs the `_readSeededToday` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Future<TodayState> _readSeededToday() async { Future<TodayState> _readSeededToday() async {
final composition = _composition(); final composition = _composition();
final result = await composition.todayQuery.execute( final result = await composition.todayQuery.execute(
@ -652,15 +661,21 @@ Future<TodayState> _readSeededToday() async {
return result.requireValue; return result.requireValue;
} }
/// Top-level helper that performs the `_kindFor` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
TaskVisualKind _kindFor(TodayScreenData data, String id) { TaskVisualKind _kindFor(TodayScreenData data, String id) {
return data.cards.singleWhere((card) => card.id == id).visualKind; return data.cards.singleWhere((card) => card.id == id).visualKind;
} }
/// Top-level helper that performs the `_scrollIntoView` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Future<void> _scrollIntoView(WidgetTester tester, ValueKey<String> key) async { Future<void> _scrollIntoView(WidgetTester tester, ValueKey<String> key) async {
await tester.ensureVisible(find.byKey(key)); await tester.ensureVisible(find.byKey(key));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
} }
/// Top-level helper that performs the `_pumpTimelineCard` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Future<void> _pumpTimelineCard( Future<void> _pumpTimelineCard(
WidgetTester tester, { WidgetTester tester, {
required TimelineCardModel card, required TimelineCardModel card,
@ -688,6 +703,8 @@ Future<void> _pumpTimelineCard(
await tester.pumpAndSettle(); await tester.pumpAndSettle();
} }
/// Top-level helper that performs the `_pumpConstrainedWidget` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Future<void> _pumpConstrainedWidget( Future<void> _pumpConstrainedWidget(
WidgetTester tester, { WidgetTester tester, {
required Size size, required Size size,
@ -708,6 +725,8 @@ Future<void> _pumpConstrainedWidget(
await tester.pumpAndSettle(); await tester.pumpAndSettle();
} }
/// Top-level helper that performs the `_timelineCard` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
TimelineCardModel _timelineCard({ TimelineCardModel _timelineCard({
required String id, required String id,
required String title, required String title,

View file

@ -0,0 +1,6 @@
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# License
This package uses the repository-level license at [../../LICENSE.md](../../LICENSE.md).

View file

@ -1 +1,4 @@
include: package:lints/recommended.yaml # SPDX-FileCopyrightText: 2026 FocusFlow contributors
# SPDX-License-Identifier: AGPL-3.0-only
include: ../../analysis_options.yaml

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Runs the Backup command for the Scheduler Backup package. /// Runs the Backup command for the Scheduler Backup package.
library; library;
@ -5,6 +8,8 @@ import 'dart:io';
import 'package:scheduler_backup/backup.dart'; import 'package:scheduler_backup/backup.dart';
/// Entry point for this executable Dart file.
/// It wires the local command, test, or application behavior needed by this repository without exposing additional public API.
Future<void> main(List<String> arguments) async { Future<void> main(List<String> arguments) async {
final passphrase = _option(arguments, '--passphrase') ?? final passphrase = _option(arguments, '--passphrase') ??
Platform.environment['SCHEDULER_BACKUP_PASSPHRASE']; Platform.environment['SCHEDULER_BACKUP_PASSPHRASE'];
@ -25,6 +30,8 @@ Future<void> main(List<String> arguments) async {
} }
} }
/// Top-level helper that performs the `_option` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
String? _option(List<String> arguments, String name) { String? _option(List<String> arguments, String name) {
final index = arguments.indexOf(name); final index = arguments.indexOf(name);
if (index == -1 || index + 1 >= arguments.length) { if (index == -1 || index + 1 >= arguments.length) {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Encrypted SQLite backup helpers. /// Encrypted SQLite backup helpers.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Package-name entry point for scheduler backup helpers. /// Package-name entry point for scheduler backup helpers.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Implements Encrypted Backup behavior for the Scheduler Backup package. /// Implements Encrypted Backup behavior for the Scheduler Backup package.
library; library;
@ -23,11 +26,30 @@ const defaultSchedulerDatabaseFileName = 'scheduler.sqlite';
/// Default encrypted backup directory name under the scheduler data directory. /// Default encrypted backup directory name under the scheduler data directory.
const defaultSchedulerBackupDirectoryName = 'backups'; const defaultSchedulerBackupDirectoryName = 'backups';
/// Private file-level value for `_formatMagic`.
/// Keeping this value near the helpers that use it avoids hidden global configuration while still preventing duplicate literals.
const _formatMagic = 'ADHD_SCHEDULER_BACKUP_V1'; const _formatMagic = 'ADHD_SCHEDULER_BACKUP_V1';
/// Private file-level value for `_fileExtension`.
/// Keeping this value near the helpers that use it avoids hidden global configuration while still preventing duplicate literals.
const _fileExtension = '.db.enc'; const _fileExtension = '.db.enc';
/// Private file-level value for `_kdfIterations`.
/// Keeping this value near the helpers that use it avoids hidden global configuration while still preventing duplicate literals.
const _kdfIterations = 200000; const _kdfIterations = 200000;
/// Private file-level value for `_saltLength`.
/// Keeping this value near the helpers that use it avoids hidden global configuration while still preventing duplicate literals.
const _saltLength = 16; const _saltLength = 16;
/// Private file-level value for `_nonceLength`.
/// Keeping this value near the helpers that use it avoids hidden global configuration while still preventing duplicate literals.
const _nonceLength = 12; const _nonceLength = 12;
/// Private file-level value for `_keyLength`.
/// Keeping this value near the helpers that use it avoids hidden global configuration while still preventing duplicate literals.
const _keyLength = 32; const _keyLength = 32;
/// Private file-level value for `_utf8`.
/// Keeping this value near the helpers that use it avoids hidden global configuration while still preventing duplicate literals.
final _utf8 = utf8.encoder; final _utf8 = utf8.encoder;

View file

@ -1,5 +1,10 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../encrypted_backup.dart'; part of '../../encrypted_backup.dart';
/// Top-level helper that performs the `_encryptBytes` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Future<List<int>> _encryptBytes({ Future<List<int>> _encryptBytes({
required String passphrase, required String passphrase,
required List<int> plaintext, required List<int> plaintext,
@ -26,6 +31,8 @@ Future<List<int>> _encryptBytes({
return _utf8.convert(jsonEncode(envelope)); return _utf8.convert(jsonEncode(envelope));
} }
/// Top-level helper that performs the `_decryptBytes` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Future<List<int>> _decryptBytes({ Future<List<int>> _decryptBytes({
required String passphrase, required String passphrase,
required List<int> encoded, required List<int> encoded,
@ -56,6 +63,8 @@ Future<List<int>> _decryptBytes({
} }
} }
/// Top-level helper that performs the `_deriveKey` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Future<SecretKey> _deriveKey({ Future<SecretKey> _deriveKey({
required String passphrase, required String passphrase,
required List<int> salt, required List<int> salt,
@ -71,6 +80,8 @@ Future<SecretKey> _deriveKey({
); );
} }
/// Top-level helper that performs the `_randomBytes` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
List<int> _randomBytes(int length) { List<int> _randomBytes(int length) {
final random = Random.secure(); final random = Random.secure();
return Uint8List.fromList( return Uint8List.fromList(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../encrypted_backup.dart'; part of '../../encrypted_backup.dart';
/// Thrown when an encrypted backup cannot be decrypted with the passphrase. /// Thrown when an encrypted backup cannot be decrypted with the passphrase.
@ -10,6 +13,8 @@ final class BackupDecryptionException implements Exception {
/// Diagnostic text for logs and tests. /// Diagnostic text for logs and tests.
final String message; final String message;
/// Converts scheduler data for `toString` without changing the source object.
/// Conversion helpers keep persistence and export shapes explicit so domain models do not depend on storage-specific details.
@override @override
String toString() => 'BackupDecryptionException: $message'; String toString() => 'BackupDecryptionException: $message';
} }

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../encrypted_backup.dart'; part of '../../encrypted_backup.dart';
/// Thrown when backup input paths or file contents are invalid. /// Thrown when backup input paths or file contents are invalid.
@ -8,6 +11,8 @@ final class BackupException implements Exception {
/// Diagnostic text for logs and tests. /// Diagnostic text for logs and tests.
final String message; final String message;
/// Converts scheduler data for `toString` without changing the source object.
/// Conversion helpers keep persistence and export shapes explicit so domain models do not depend on storage-specific details.
@override @override
String toString() => 'BackupException: $message'; String toString() => 'BackupException: $message';
} }

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../encrypted_backup.dart'; part of '../../encrypted_backup.dart';
/// Create an encrypted backup of the scheduler SQLite file. /// Create an encrypted backup of the scheduler SQLite file.

View file

@ -1,5 +1,10 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../encrypted_backup.dart'; part of '../../encrypted_backup.dart';
/// Top-level helper that performs the `_nextAvailableBackupFile` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Future<File> _nextAvailableBackupFile(Directory directory, String name) async { Future<File> _nextAvailableBackupFile(Directory directory, String name) async {
final preferred = File(_joinPath(directory.path, name)); final preferred = File(_joinPath(directory.path, name));
if (!await preferred.exists()) { if (!await preferred.exists()) {
@ -19,12 +24,18 @@ Future<File> _nextAvailableBackupFile(Directory directory, String name) async {
} }
} }
/// Top-level helper that performs the `_backupTimestamp` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
String _backupTimestamp(DateTime value) { String _backupTimestamp(DateTime value) {
final local = value.toLocal(); final local = value.toLocal();
return '${_four(local.year)}${_two(local.month)}${_two(local.day)}_' return '${_four(local.year)}${_two(local.month)}${_two(local.day)}_'
'${_two(local.hour)}${_two(local.minute)}'; '${_two(local.hour)}${_two(local.minute)}';
} }
/// Top-level helper that performs the `_four` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
String _four(int value) => value.toString().padLeft(4, '0'); String _four(int value) => value.toString().padLeft(4, '0');
/// Top-level helper that performs the `_two` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
String _two(int value) => value.toString().padLeft(2, '0'); String _two(int value) => value.toString().padLeft(2, '0');

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../encrypted_backup.dart'; part of '../../encrypted_backup.dart';
/// Default scheduler SQLite database path. /// Default scheduler SQLite database path.
@ -18,6 +21,8 @@ Directory defaultSchedulerBackupDirectory() {
)); ));
} }
/// Top-level helper that performs the `_homeDirectory` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
Directory _homeDirectory() { Directory _homeDirectory() {
final home = Platform.environment['HOME'] ?? final home = Platform.environment['HOME'] ??
Platform.environment['USERPROFILE'] ?? Platform.environment['USERPROFILE'] ??
@ -28,6 +33,8 @@ Directory _homeDirectory() {
return Directory(home); return Directory(home);
} }
/// Top-level helper that performs the `_joinPath` operation for this file.
/// Keeping the helper private makes the surrounding flow easier to read while preventing unrelated libraries from depending on implementation detail.
String _joinPath(String first, String second, [String? third]) { String _joinPath(String first, String second, [String? third]) {
final separator = Platform.pathSeparator; final separator = Platform.pathSeparator;
final left = first.endsWith(separator) final left = first.endsWith(separator)

View file

@ -1,3 +1,6 @@
# SPDX-FileCopyrightText: 2026 FocusFlow contributors
# SPDX-License-Identifier: AGPL-3.0-only
name: scheduler_backup name: scheduler_backup
description: Encrypted SQLite backup and restore helpers for the ADHD scheduler. description: Encrypted SQLite backup and restore helpers for the ADHD scheduler.
version: 0.1.0 version: 0.1.0

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Tests Encrypted Backup behavior for the Scheduler Backup package. /// Tests Encrypted Backup behavior for the Scheduler Backup package.
library; library;
@ -7,6 +10,8 @@ import 'dart:io';
import 'package:scheduler_backup/backup.dart'; import 'package:scheduler_backup/backup.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
/// Entry point for this executable Dart file.
/// It wires the local command, test, or application behavior needed by this repository without exposing additional public API.
void main() { void main() {
test('encrypted backup round trips a SQLite file using temp paths', () async { test('encrypted backup round trips a SQLite file using temp paths', () async {
final temp = final temp =

View file

@ -0,0 +1,6 @@
<!-- SPDX-FileCopyrightText: 2026 FocusFlow contributors -->
<!-- SPDX-License-Identifier: AGPL-3.0-only -->
# License
This package uses the repository-level license at [../../LICENSE.md](../../LICENSE.md).

View file

@ -1,13 +1,4 @@
include: package:lints/recommended.yaml # SPDX-FileCopyrightText: 2026 FocusFlow contributors
# SPDX-License-Identifier: AGPL-3.0-only
analyzer: include: ../../analysis_options.yaml
language:
strict-casts: true
strict-inference: true
strict-raw-types: true
linter:
rules:
prefer_final_locals: true
prefer_final_fields: true
avoid_print: true

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Defines the Scheduler Core public library for the Scheduler Core package. /// Defines the Scheduler Core public library for the Scheduler Core package.
library; library;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
/// Implements Application Commands behavior for the Scheduler Core package. /// Implements Application Commands behavior for the Scheduler Core package.
library; library;

View file

@ -1,22 +1,75 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../application_commands.dart'; part of '../../application_commands.dart';
/// Stable V1 application command identifiers. /// Stable V1 application command identifiers.
enum ApplicationCommandCode { enum ApplicationCommandCode {
/// Selects the `quickCaptureToBacklog` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
quickCaptureToBacklog, quickCaptureToBacklog,
/// Selects the `quickCaptureToNextAvailableSlot` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
quickCaptureToNextAvailableSlot, quickCaptureToNextAvailableSlot,
/// Selects the `scheduleBacklogItemToNextAvailableSlot` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
scheduleBacklogItemToNextAvailableSlot, scheduleBacklogItemToNextAvailableSlot,
/// Selects the `pushFlexibleToNextAvailableSlot` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
pushFlexibleToNextAvailableSlot, pushFlexibleToNextAvailableSlot,
/// Selects the `pushFlexibleToTomorrowTopOfQueue` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
pushFlexibleToTomorrowTopOfQueue, pushFlexibleToTomorrowTopOfQueue,
/// Selects the `moveFlexibleToBacklog` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
moveFlexibleToBacklog, moveFlexibleToBacklog,
/// Selects the `completeFlexibleTask` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
completeFlexibleTask, completeFlexibleTask,
/// Selects the `uncompleteTask` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
uncompleteTask, uncompleteTask,
/// Selects the `applyRequiredTaskAction` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
applyRequiredTaskAction, applyRequiredTaskAction,
/// Selects the `logSurpriseTask` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
logSurpriseTask, logSurpriseTask,
/// Selects the `createProtectedFreeSlot` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
createProtectedFreeSlot, createProtectedFreeSlot,
/// Selects the `updateProtectedFreeSlot` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
updateProtectedFreeSlot, updateProtectedFreeSlot,
/// Selects the `removeProtectedFreeSlot` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
removeProtectedFreeSlot, removeProtectedFreeSlot,
/// Selects the `breakUpTask` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
breakUpTask, breakUpTask,
/// Selects the `completeChildTask` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
completeChildTask, completeChildTask,
/// Selects the `completeParentTask` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
completeParentTask, completeParentTask,
/// Selects the `completeParentFromChild` option from this enum.
/// Code should use this named value when it needs this exact scheduler state, presentation token, or persistence meaning.
completeParentFromChild, completeParentFromChild,
} }

View file

@ -1,7 +1,12 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../application_commands.dart'; part of '../../application_commands.dart';
/// Draft row for creating one child task from an application command. /// Draft row for creating one child task from an application command.
class ApplicationChildTaskDraft { class ApplicationChildTaskDraft {
/// Creates a `ApplicationChildTaskDraft` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
const ApplicationChildTaskDraft({ const ApplicationChildTaskDraft({
required this.title, required this.title,
this.priority, this.priority,

View file

@ -1,7 +1,12 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../application_commands.dart'; part of '../../application_commands.dart';
/// Hint for read models that should be refreshed after a command. /// Hint for read models that should be refreshed after a command.
class ApplicationCommandReadHint { class ApplicationCommandReadHint {
/// Creates a `ApplicationCommandReadHint` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
ApplicationCommandReadHint({ ApplicationCommandReadHint({
CivilDate? localDate, CivilDate? localDate,
Iterable<CivilDate> affectedDates = const <CivilDate>[], Iterable<CivilDate> affectedDates = const <CivilDate>[],

View file

@ -1,7 +1,12 @@
// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only
part of '../../application_commands.dart'; part of '../../application_commands.dart';
/// Structured result returned by V1 application commands. /// Structured result returned by V1 application commands.
class ApplicationCommandResult { class ApplicationCommandResult {
/// Creates a `ApplicationCommandResult` instance with the values required by its invariants.
/// Callers should pass already-normalized scheduler data because validation and defaulting belong at the model or service boundary, not in arbitrary UI code.
ApplicationCommandResult({ ApplicationCommandResult({
required this.commandCode, required this.commandCode,
required String operationId, required String operationId,

Some files were not shown because too many files have changed in this diff Show more