Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
9d1eeae
flutter: Share→SharePlus migration step 1 — switch to SharePlus.insta…
zensgit Sep 27, 2025
6301183
flutter: clean QR widget placeholder + remove local Share stub; use s…
zensgit Sep 27, 2025
c1a00d2
flutter: fix use_build_context_synchronously in AcceptInvitationDialo…
zensgit Sep 27, 2025
139d958
flutter: context cleanup batch 1 (right_click_copy, custom_theme_edit…
zensgit Sep 28, 2025
cb8f290
flutter: context safety fixes in ThemeShareDialog and DeleteFamilyDialog
zensgit Sep 28, 2025
f187d07
flutter: context cleanup batch 2 (admin template page + batch op bar)
zensgit Sep 28, 2025
741b89f
flutter: fix AuditLogsScreen statistics type; continue context-safety…
zensgit Sep 28, 2025
51c6be6
flutter: context cleanup batch 3 prep — refine messenger/navigator ca…
zensgit Sep 28, 2025
39c2f5f
flutter: context cleanup batch 3 — move captures post-await + scoped …
zensgit Sep 28, 2025
a1e7950
flutter: context cleanup batch 3 — ThemeManagementScreen messenger/na…
zensgit Sep 28, 2025
d4124c3
flutter: add User Assets overview screen + route; fix analyzer blocke…
zensgit Sep 28, 2025
3973474
flutter: transactions Phase A scaffold — add search/filter bar and gr…
zensgit Sep 28, 2025
bff7320
flutter: wire Dashboard RecentTransactions filter button to open Tran…
zensgit Sep 28, 2025
927ac93
fix: add missing onFilter parameter to GroupedRecentTransactions
zensgit Oct 8, 2025
7a4f9ce
Merge branch 'main' into feature/transactions-phase-a
zensgit Oct 8, 2025
9824fca
test: fix transaction tests for updated TransactionController signature
zensgit Oct 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions jive-flutter/.dart_tool/package_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@
},
{
"name": "flutter",
"rootUri": "file:///opt/homebrew/share/flutter/packages/flutter",
"rootUri": "file:///Users/huazhou/flutter-sdk/packages/flutter",
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Environment-specific absolute path in generated .dart_tool file should not be committed; revert this file and add/ensure .dart_tool is excluded from version control to avoid local path churn and leaking local usernames. Other similar lines (288, 312, 318, 792, 1057) should also be reverted.

Copilot uses AI. Check for mistakes.
"packageUri": "lib/",
"languageVersion": "3.8"
},
Expand All @@ -285,7 +285,7 @@
},
{
"name": "flutter_localizations",
"rootUri": "file:///opt/homebrew/share/flutter/packages/flutter_localizations",
"rootUri": "file:///Users/huazhou/flutter-sdk/packages/flutter_localizations",
"packageUri": "lib/",
"languageVersion": "3.8"
},
Expand All @@ -309,13 +309,13 @@
},
{
"name": "flutter_test",
"rootUri": "file:///opt/homebrew/share/flutter/packages/flutter_test",
"rootUri": "file:///Users/huazhou/flutter-sdk/packages/flutter_test",
"packageUri": "lib/",
"languageVersion": "3.8"
},
{
"name": "flutter_web_plugins",
"rootUri": "file:///opt/homebrew/share/flutter/packages/flutter_web_plugins",
"rootUri": "file:///Users/huazhou/flutter-sdk/packages/flutter_web_plugins",
"packageUri": "lib/",
"languageVersion": "3.8"
},
Expand Down Expand Up @@ -789,7 +789,7 @@
},
{
"name": "sky_engine",
"rootUri": "file:///opt/homebrew/share/flutter/bin/cache/pkg/sky_engine",
"rootUri": "file:///Users/huazhou/flutter-sdk/bin/cache/pkg/sky_engine",
"packageUri": "lib/",
"languageVersion": "3.8"
},
Expand Down Expand Up @@ -1054,7 +1054,7 @@
],
"generator": "pub",
"generatorVersion": "3.9.2",
"flutterRoot": "file:///opt/homebrew/share/flutter",
"flutterRoot": "file:///Users/huazhou/flutter-sdk",
"flutterVersion": "3.35.3",
"pubCache": "file:///Users/huazhou/.pub-cache"
}
67 changes: 64 additions & 3 deletions jive-flutter/lib/ui/components/transactions/transaction_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
typedef TransactionData = Transaction;

class TransactionList extends ConsumerWidget {
// Phase A: lightweight search/group controls
final ValueChanged<String>? onSearch;
final VoidCallback? onClearSearch;
final VoidCallback? onToggleGroup;
Comment on lines +14 to +17
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New public callback properties lack doc comments. Add Dart doc comments (///) describing when each callback is invoked and expected side effects to aid maintainability and API clarity.

Copilot uses AI. Check for mistakes.
final List<TransactionData> transactions;
final bool groupByDate;
final bool showSearchBar;
Expand All @@ -36,6 +40,9 @@ class TransactionList extends ConsumerWidget {
this.onTransactionLongPress,
this.scrollController,
this.isLoading = false,
this.onSearch,
this.onClearSearch,
this.onToggleGroup,
this.formatAmount,
this.transactionItemBuilder,
});
Expand All @@ -50,9 +57,14 @@ class TransactionList extends ConsumerWidget {
return _buildEmptyState(context);
}

final content = groupByDate
? _buildGroupedList(context, ref)
: _buildSimpleList(context, ref);
final listContent = groupByDate ? _buildGroupedList(context, ref) : _buildSimpleList(context, ref);

final content = Column(
children: [
if (showSearchBar) _buildSearchBar(context),
Expanded(child: listContent),
],
);

if (onRefresh != null) {
return RefreshIndicator(
Expand All @@ -64,6 +76,55 @@ class TransactionList extends ConsumerWidget {
return content;
}



Widget _buildSearchBar(BuildContext context) {
final theme = Theme.of(context);
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
color: theme.colorScheme.surfaceContainerHighest.withValues(alpha: 0.3),
child: Row(
children: [
Expanded(
child: TextField(
decoration: InputDecoration(
hintText: '搜索 描述/备注/收款方…',
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded user-facing string should use the app's localization mechanism (e.g., AppLocalizations) instead of a literal to support i18n.

Copilot uses AI. Check for mistakes.
prefixIcon: const Icon(Icons.search),
suffixIcon: onClearSearch != null
? IconButton(icon: const Icon(Icons.clear), onPressed: onClearSearch)
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clear IconButton lacks a tooltip or semantic label, which can hinder screen reader users. Wrap with Tooltip and/or set semantic properties (e.g., Tooltip + Semantics(label: ...)).

Suggested change
? IconButton(icon: const Icon(Icons.clear), onPressed: onClearSearch)
? IconButton(
icon: const Icon(Icons.clear),
onPressed: onClearSearch,
tooltip: '清除搜索',
)

Copilot uses AI. Check for mistakes.
: null,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide.none,
),
filled: true,
fillColor: theme.colorScheme.surface,
isDense: true,
),
textInputAction: TextInputAction.search,
onSubmitted: onSearch,
),
),
const SizedBox(width: 8),
IconButton(
tooltip: groupByDate ? '切换为平铺' : '按日期分组',
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded tooltip string should be localized via the project's localization system.

Copilot uses AI. Check for mistakes.
onPressed: onToggleGroup,
icon: Icon(groupByDate ? Icons.view_agenda_outlined : Icons.calendar_today_outlined),
),
IconButton(
tooltip: '筛选',
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded tooltip string should be localized for internationalization consistency.

Copilot uses AI. Check for mistakes.
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('筛选功能开发中')),
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded SnackBar message should be localized to maintain consistency with internationalization practices.

Copilot uses AI. Check for mistakes.
);
},
icon: const Icon(Icons.filter_list),
),
],
),
);
}

Widget _buildEmptyState(BuildContext context) {
final theme = Theme.of(context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import 'dart:async';

import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:jive_money/providers/transaction_provider.dart';
import 'package:jive_money/services/api/transaction_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
Expand All @@ -11,7 +12,7 @@ class _DummyTransactionService extends TransactionService {}

/// Test controller that skips network loading on init.
class _TestTransactionController extends TransactionController {
_TestTransactionController() : super(_DummyTransactionService());
_TestTransactionController(Ref ref) : super(ref, _DummyTransactionService());

@override
Future<void> loadTransactions() async {
Expand All @@ -28,6 +29,12 @@ class _TestTransactionController extends TransactionController {
}
}

// Test provider for creating controllers in tests
final testControllerProvider =
StateNotifierProvider<_TestTransactionController, TransactionState>((ref) {
return _TestTransactionController(ref);
});

void main() {
TestWidgetsFlutterBinding.ensureInitialized();

Expand All @@ -38,7 +45,9 @@ void main() {
});

test('setGrouping persists to SharedPreferences', () async {
final controller = _TestTransactionController();
final container = ProviderContainer();
addTearDown(container.dispose);
final controller = container.read(testControllerProvider.notifier);

// Default should be date
expect(controller.state.grouping, TransactionGrouping.date);
Expand All @@ -54,7 +63,9 @@ void main() {
});

test('toggleGroupCollapse persists collapsed keys', () async {
final controller = _TestTransactionController();
final container = ProviderContainer();
addTearDown(container.dispose);
final controller = container.read(testControllerProvider.notifier);
const key = 'category:未分类';

// Toggle on (collapse)
Expand Down