feat: introduce Local Filters / Remote Filters terminology (#109)
- Rename 'Local email filters' → 'Local Filters' and 'Server email filters' → 'Remote Filters' in AppBar titles - Update banner text on each filter page to focus on the current type and mention that the other type exists separately - Add 'Remote Filters' and 'Local Filters' as two distinct drawer entries so both types are discoverable from the navigation - Add widget tests verifying titles and banner text for both pages Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
67880929bc
commit
dc8c1cb08d
@@ -138,7 +138,7 @@ class _SieveScriptsScreenState extends ConsumerState<SieveScriptsScreen> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
widget.isLocal ? 'Local email filters' : 'Server email filters',
|
||||
widget.isLocal ? 'Local Filters' : 'Remote Filters',
|
||||
),
|
||||
),
|
||||
body: _buildBody(),
|
||||
@@ -178,7 +178,7 @@ class _SieveScriptsScreenState extends ConsumerState<SieveScriptsScreen> {
|
||||
Expanded(
|
||||
child: scripts.isEmpty
|
||||
? const Center(
|
||||
child: Text('No Sieve scripts. Tap + to create one.'),
|
||||
child: Text('No filters yet. Tap + to create one.'),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: _load,
|
||||
@@ -208,10 +208,11 @@ class _SieveSourceBanner extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final text = isLocal
|
||||
? 'These scripts run locally on this device. '
|
||||
'Server email filters are separate and independent.'
|
||||
: 'These scripts run on the mail server (ManageSieve / JMAP). '
|
||||
'Local email filters are separate and independent.';
|
||||
? 'Local Filters run Sieve scripts directly on this device. '
|
||||
'Remote Filters, which run on the mail server, are configured separately.'
|
||||
: 'Remote Filters run Sieve scripts on the mail server '
|
||||
'(ManageSieve or JMAP). '
|
||||
'Local Filters, which run on this device, are configured separately.';
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
|
||||
@@ -70,13 +70,21 @@ class FolderDrawer extends ConsumerWidget {
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.filter_list),
|
||||
title: const Text('Email filters'),
|
||||
leading: const Icon(Icons.dns),
|
||||
title: const Text('Remote Filters'),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
unawaited(context.push('/accounts/$accountId/sieve'));
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.phone_android),
|
||||
title: const Text('Local Filters'),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
unawaited(context.push('/accounts/$accountId/sieve/local'));
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Expanded(
|
||||
child: StreamBuilder(
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:sharedinbox/core/models/sieve_script.dart';
|
||||
import 'package:sharedinbox/data/db/local_sieve_repository.dart';
|
||||
import 'package:sharedinbox/data/jmap/sieve_repository.dart';
|
||||
import 'package:sharedinbox/di.dart';
|
||||
import 'package:sharedinbox/ui/screens/sieve_scripts_screen.dart';
|
||||
|
||||
import '../unit/db_test_helper.dart';
|
||||
import 'helpers.dart';
|
||||
|
||||
class _FakeSieveRepository extends SieveRepository {
|
||||
_FakeSieveRepository() : super(FakeAccountRepository(), http.Client());
|
||||
|
||||
@override
|
||||
Future<List<SieveScript>> listScripts(String accountId) async => [];
|
||||
}
|
||||
|
||||
void main() {
|
||||
configureSqliteForTests();
|
||||
|
||||
testWidgets('Remote Filters page shows correct title and banner', (
|
||||
tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
sieveRepositoryProvider.overrideWith(
|
||||
(ref) => _FakeSieveRepository(),
|
||||
),
|
||||
],
|
||||
child: const MaterialApp(
|
||||
home: SieveScriptsScreen(accountId: 'acc-1'),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Remote Filters'), findsOneWidget);
|
||||
expect(
|
||||
find.textContaining('Remote Filters run Sieve scripts'),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.textContaining('Local Filters'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Local Filters page shows correct title and banner', (
|
||||
tester,
|
||||
) async {
|
||||
final db = openTestDatabase();
|
||||
addTearDown(db.close);
|
||||
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
localSieveRepositoryProvider.overrideWith(
|
||||
(ref) => LocalSieveRepository(db),
|
||||
),
|
||||
],
|
||||
child: const MaterialApp(
|
||||
home: SieveScriptsScreen(accountId: 'acc-1', isLocal: true),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Local Filters'), findsOneWidget);
|
||||
expect(
|
||||
find.textContaining('Local Filters run Sieve scripts'),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.textContaining('Remote Filters'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user