Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26504775c5 | ||
|
|
0fc81b9886 | ||
|
|
1c43c70d2f | ||
|
|
acb7023fff | ||
|
|
1d8619504c |
@@ -21,6 +21,7 @@ import 'package:sharedinbox/ui/screens/sieve_script_edit_screen.dart';
|
|||||||
import 'package:sharedinbox/ui/screens/sieve_scripts_screen.dart';
|
import 'package:sharedinbox/ui/screens/sieve_scripts_screen.dart';
|
||||||
import 'package:sharedinbox/ui/screens/sync_log_screen.dart';
|
import 'package:sharedinbox/ui/screens/sync_log_screen.dart';
|
||||||
import 'package:sharedinbox/ui/screens/thread_detail_screen.dart';
|
import 'package:sharedinbox/ui/screens/thread_detail_screen.dart';
|
||||||
|
import 'package:sharedinbox/ui/screens/trusted_image_senders_screen.dart';
|
||||||
import 'package:sharedinbox/ui/screens/undo_log_screen.dart';
|
import 'package:sharedinbox/ui/screens/undo_log_screen.dart';
|
||||||
import 'package:sharedinbox/ui/screens/user_preferences_screen.dart';
|
import 'package:sharedinbox/ui/screens/user_preferences_screen.dart';
|
||||||
import 'package:sharedinbox/ui/widgets/undo_shell.dart';
|
import 'package:sharedinbox/ui/widgets/undo_shell.dart';
|
||||||
@@ -67,6 +68,12 @@ final router = GoRouter(
|
|||||||
path: 'preferences',
|
path: 'preferences',
|
||||||
builder: (ctx, state) => const UserPreferencesScreen(),
|
builder: (ctx, state) => const UserPreferencesScreen(),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'trusted-senders',
|
||||||
|
builder: (ctx, state) => TrustedImageSendersScreen(
|
||||||
|
highlightedSender: state.extra as String?,
|
||||||
|
),
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: ':accountId/edit',
|
path: ':accountId/edit',
|
||||||
builder: (ctx, state) => EditAccountScreen(
|
builder: (ctx, state) => EditAccountScreen(
|
||||||
|
|||||||
@@ -229,11 +229,14 @@ class _EmailDetailScreenState extends ConsumerState<EmailDetailScreen> {
|
|||||||
'Images will be loaded automatically for this sender.',
|
'Images will be loaded automatically for this sender.',
|
||||||
),
|
),
|
||||||
action: SnackBarAction(
|
action: SnackBarAction(
|
||||||
label: 'Settings',
|
label: 'View',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
unawaited(
|
unawaited(
|
||||||
context.push('/accounts/preferences'),
|
context.push(
|
||||||
|
'/accounts/trusted-senders',
|
||||||
|
extra: senderEmail,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -217,11 +217,14 @@ class _EmailMessageCardState extends ConsumerState<_EmailMessageCard> {
|
|||||||
'Images will be loaded automatically for this sender.',
|
'Images will be loaded automatically for this sender.',
|
||||||
),
|
),
|
||||||
action: SnackBarAction(
|
action: SnackBarAction(
|
||||||
label: 'Settings',
|
label: 'View',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
unawaited(
|
unawaited(
|
||||||
context.push('/accounts/preferences'),
|
context.push(
|
||||||
|
'/accounts/trusted-senders',
|
||||||
|
extra: senderEmail,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
import 'package:sharedinbox/di.dart';
|
||||||
|
|
||||||
|
class TrustedImageSendersScreen extends ConsumerWidget {
|
||||||
|
const TrustedImageSendersScreen({super.key, this.highlightedSender});
|
||||||
|
|
||||||
|
final String? highlightedSender;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final trustedSendersAsync = ref.watch(trustedImageSendersProvider);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: const Text('Allowed addresses for images')),
|
||||||
|
body: trustedSendersAsync.when(
|
||||||
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
|
error: (_, __) =>
|
||||||
|
const Center(child: Text('Error loading trusted senders')),
|
||||||
|
data: (senders) {
|
||||||
|
if (senders.isEmpty) {
|
||||||
|
return const Padding(
|
||||||
|
padding: EdgeInsets.all(16),
|
||||||
|
child: Text(
|
||||||
|
'No addresses added yet. '
|
||||||
|
'Tap "Load remote images" in an email to add the sender.',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: senders.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final sender = senders[index];
|
||||||
|
final isHighlighted = sender == highlightedSender;
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
sender,
|
||||||
|
style: isHighlighted
|
||||||
|
? const TextStyle(fontWeight: FontWeight.bold)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: const Icon(Icons.delete_outline),
|
||||||
|
tooltip: 'Remove',
|
||||||
|
onPressed: () {
|
||||||
|
unawaited(
|
||||||
|
ref
|
||||||
|
.read(userPreferencesRepositoryProvider)
|
||||||
|
.removeTrustedImageSender(sender),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import 'package:sharedinbox/core/models/user_preferences.dart';
|
import 'package:sharedinbox/core/models/user_preferences.dart';
|
||||||
import 'package:sharedinbox/core/sync/background_sync.dart';
|
import 'package:sharedinbox/core/sync/background_sync.dart';
|
||||||
@@ -14,6 +15,7 @@ class UserPreferencesScreen extends ConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final prefsAsync = ref.watch(userPreferencesProvider);
|
final prefsAsync = ref.watch(userPreferencesProvider);
|
||||||
final trustedSendersAsync = ref.watch(trustedImageSendersProvider);
|
final trustedSendersAsync = ref.watch(trustedImageSendersProvider);
|
||||||
|
final trustedCount = trustedSendersAsync.value?.length ?? 0;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('Preferences')),
|
appBar: AppBar(title: const Text('Preferences')),
|
||||||
@@ -213,41 +215,16 @@ class UserPreferencesScreen extends ConsumerWidget {
|
|||||||
const Divider(),
|
const Divider(),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
'Trusted image senders',
|
'Allowed addresses for images',
|
||||||
style: Theme.of(context).textTheme.titleSmall,
|
style: Theme.of(context).textTheme.titleSmall,
|
||||||
),
|
),
|
||||||
subtitle: const Text(
|
subtitle: Text(
|
||||||
'Remote images are loaded automatically for these senders.',
|
trustedCount == 0
|
||||||
|
? 'No addresses added yet.'
|
||||||
|
: '$trustedCount address${trustedCount == 1 ? '' : 'es'}',
|
||||||
),
|
),
|
||||||
),
|
trailing: const Icon(Icons.chevron_right),
|
||||||
...trustedSendersAsync.when(
|
onTap: () => context.push('/accounts/trusted-senders'),
|
||||||
loading: () => const [],
|
|
||||||
error: (_, __) => const [],
|
|
||||||
data: (senders) => senders.isEmpty
|
|
||||||
? [
|
|
||||||
const Padding(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
||||||
child: Text('No trusted senders yet.'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
for (final sender in senders)
|
|
||||||
ListTile(
|
|
||||||
title: Text(sender),
|
|
||||||
trailing: IconButton(
|
|
||||||
icon: const Icon(Icons.delete_outline),
|
|
||||||
tooltip: 'Remove',
|
|
||||||
onPressed: () {
|
|
||||||
unawaited(
|
|
||||||
ref
|
|
||||||
.read(userPreferencesRepositoryProvider)
|
|
||||||
.removeTrustedImageSender(sender),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ const _excluded = {
|
|||||||
'lib/data/repositories/user_preferences_repository_impl.dart',
|
'lib/data/repositories/user_preferences_repository_impl.dart',
|
||||||
'lib/ui/screens/user_preferences_screen.dart',
|
'lib/ui/screens/user_preferences_screen.dart',
|
||||||
'lib/core/services/update_service.dart',
|
'lib/core/services/update_service.dart',
|
||||||
|
'lib/ui/screens/trusted_image_senders_screen.dart',
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|||||||
Reference in New Issue
Block a user