look aheead limit defined by user

This commit is contained in:
davmar
2026-09-10 09:31:11 +02:00
parent 200ff72e2e
commit 7437cc90ce
5 changed files with 92 additions and 24 deletions
+47 -24
View File
@@ -7,6 +7,7 @@ import 'package:provider/provider.dart';
import '../models/bank.dart';
import '../models/transaction_meta.dart';
import '../providers/bank_provider.dart';
import '../providers/preferences_provider.dart';
import '../providers/tx_meta_provider.dart';
import '../screens/transaction_detail_screen.dart';
import '../utils/app_theme.dart';
@@ -37,8 +38,6 @@ class _LookAheadScreenState extends State<LookAheadScreen> {
List<RecurringItem>? _cachedItems;
int? _itemsCacheKey;
static const _maxYearsAhead = 5;
@override
void initState() {
super.initState();
@@ -51,11 +50,6 @@ class _LookAheadScreenState extends State<LookAheadScreen> {
DateTime get _minMonth => monthStart(_today);
DateTime get _maxMonth {
final t = _today;
return DateTime(t.year + _maxYearsAhead, t.month);
}
/// Inclusive end date for the selected period.
DateTime get _through {
if (_period == _PeriodMode.yearly) {
@@ -69,50 +63,67 @@ class _LookAheadScreenState extends State<LookAheadScreen> {
return formatMonthYear(_cursor);
}
bool get _canGoBack {
DateTime _maxMonthFor(int maxYears) {
final t = _today;
return DateTime(t.year + maxYears, t.month);
}
bool _canGoBack() {
if (_period == _PeriodMode.yearly) {
return _cursor.year > _today.year;
}
return monthStart(_cursor).isAfter(_minMonth);
}
bool get _canGoForward {
bool _canGoForward(int maxYears) {
if (_period == _PeriodMode.yearly) {
return _cursor.year < _today.year + _maxYearsAhead;
return _cursor.year < _today.year + maxYears;
}
return monthStart(_cursor).isBefore(_maxMonth);
return monthStart(_cursor).isBefore(_maxMonthFor(maxYears));
}
void _setPeriod(_PeriodMode mode) {
void _clampCursor(int maxYears) {
if (_period == _PeriodMode.yearly) {
if (_cursor.year > _today.year + maxYears) {
_cursor = DateTime(_today.year + maxYears);
}
} else {
final maxMonth = _maxMonthFor(maxYears);
if (_cursor.isAfter(maxMonth)) _cursor = maxMonth;
}
}
void _setPeriod(_PeriodMode mode, int maxYears) {
if (mode == _period) return;
setState(() {
_period = mode;
if (mode == _PeriodMode.yearly) {
_cursor = DateTime(_cursor.year);
if (_cursor.year < _today.year) _cursor = DateTime(_today.year);
if (_cursor.year > _today.year + _maxYearsAhead) {
_cursor = DateTime(_today.year + _maxYearsAhead);
if (_cursor.year > _today.year + maxYears) {
_cursor = DateTime(_today.year + maxYears);
}
} else {
final month = DateTime(_cursor.year, _today.month);
_cursor = month.isBefore(_minMonth) ? _minMonth : monthStart(month);
if (_cursor.isAfter(_maxMonth)) _cursor = _maxMonth;
final maxMonth = _maxMonthFor(maxYears);
if (_cursor.isAfter(maxMonth)) _cursor = maxMonth;
}
});
}
void _go(int delta) {
void _go(int delta, int maxYears) {
setState(() {
if (_period == _PeriodMode.yearly) {
final next = DateTime(_cursor.year + delta);
if (next.year < _today.year ||
next.year > _today.year + _maxYearsAhead) {
if (next.year < _today.year || next.year > _today.year + maxYears) {
return;
}
_cursor = next;
} else {
final next = addMonths(monthStart(_cursor), delta);
if (next.isBefore(_minMonth) || next.isAfter(_maxMonth)) return;
final maxMonth = _maxMonthFor(maxYears);
if (next.isBefore(_minMonth) || next.isAfter(maxMonth)) return;
_cursor = next;
}
});
@@ -131,6 +142,18 @@ class _LookAheadScreenState extends State<LookAheadScreen> {
Widget _buildContent(BuildContext context) {
final bank = context.watch<BankController>();
final meta = context.watch<TxMetaController>();
final maxYears =
context.watch<PreferencesController>().lookAheadMaxYears;
final maxMonth = _maxMonthFor(maxYears);
final needsClamp = _period == _PeriodMode.yearly
? _cursor.year > _today.year + maxYears
: _cursor.isAfter(maxMonth);
if (needsClamp) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
setState(() => _clampCursor(maxYears));
});
}
final theme = Theme.of(context);
final colors = theme.colorScheme;
@@ -202,15 +225,15 @@ class _LookAheadScreenState extends State<LookAheadScreen> {
children: [
_PeriodToolbar(
period: _period,
onPeriodChanged: _setPeriod,
onPeriodChanged: (mode) => _setPeriod(mode, maxYears),
),
const SizedBox(height: 10),
_PeriodNavigator(
title: _periodTitle,
canGoBack: _canGoBack,
canGoForward: _canGoForward,
onBack: () => _go(-1),
onForward: () => _go(1),
canGoBack: _canGoBack(),
canGoForward: _canGoForward(maxYears),
onBack: () => _go(-1, maxYears),
onForward: () => _go(1, maxYears),
backTooltip:
_period == _PeriodMode.yearly ? 'Previous year' : 'Previous month',
forwardTooltip: