diff --git a/lib/screens/transaction_history/cubits/filter/transaction_history_filter_cubit.dart b/lib/screens/transaction_history/cubits/filter/transaction_history_filter_cubit.dart index fbe743f1..69784c49 100644 --- a/lib/screens/transaction_history/cubits/filter/transaction_history_filter_cubit.dart +++ b/lib/screens/transaction_history/cubits/filter/transaction_history_filter_cubit.dart @@ -37,14 +37,20 @@ class TransactionHistoryFilterCubit extends Cubit } void changeFilter({DateTime? startDate, DateTime? endDate}) { + // Each date picker reports only the bound it changed, so resolve the + // effective window by merging the partial argument with the bound already + // in state. Using the merged values for BOTH the state and the filtered + // result keeps the other bound from being silently dropped (issue #657 P3). + final effectiveStartDate = startDate ?? state.startDate; + final effectiveEndDate = endDate ?? state.endDate; emit( state.copyWith( - startDate: startDate, - endDate: endDate, + startDate: effectiveStartDate, + endDate: effectiveEndDate, filtered: _applyFilter( state.all, - startDate: startDate, - endDate: endDate, + startDate: effectiveStartDate, + endDate: effectiveEndDate, ), ), ); diff --git a/test/screens/transaction_history/cubits/transaction_history_filter_cubit_test.dart b/test/screens/transaction_history/cubits/transaction_history_filter_cubit_test.dart index f73e82e9..0fe8a3f7 100644 --- a/test/screens/transaction_history/cubits/transaction_history_filter_cubit_test.dart +++ b/test/screens/transaction_history/cubits/transaction_history_filter_cubit_test.dart @@ -128,6 +128,32 @@ void main() { }, ); + blocTest( + 'changeFilter keeps the previously-set bound when only the other changes ' + '(issue #657 P3 regression)', + build: build, + act: (cubit) async { + stream.add([ + _tx(DateTime(2026, 1, 1)), + _tx(DateTime(2026, 3, 1)), + _tx(DateTime(2026, 5, 1)), + ]); + await Future.delayed(Duration.zero); + + // Two pickers, two separate partial updates — start first, then end. + cubit.changeFilter(startDate: DateTime(2026, 2, 1)); + cubit.changeFilter(endDate: DateTime(2026, 4, 1)); + }, + verify: (cubit) { + // Both bounds must survive: the window [Feb 1, Apr 1] leaves only Mar 1. + // Before the fix the second call dropped the start bound, leaking Jan 1. + expect(cubit.state.startDate, DateTime(2026, 2, 1)); + expect(cubit.state.endDate, DateTime(2026, 4, 1)); + expect(cubit.state.filtered, hasLength(1)); + expect(cubit.state.filtered.single.timestamp, DateTime(2026, 3, 1)); + }, + ); + test('close cancels the stream subscription (no emit after close)', () async { final cubit = build(); await cubit.close();