refactored settings & added content blocking

This commit is contained in:
Fabian Freund
2024-06-19 21:09:54 +02:00
parent 2bacbbffd2
commit d3e30613c9
11 changed files with 385 additions and 215 deletions
@@ -0,0 +1,50 @@
import 'package:bang_navigator/features/bangs/data/models/bang.dart';
import 'package:bang_navigator/features/bangs/domain/providers.dart';
import 'package:bang_navigator/features/bangs/domain/repositories/sync.dart';
import 'package:bang_navigator/features/settings/presentation/widgets/custom_list_tile.dart';
import 'package:bang_navigator/features/settings/presentation/widgets/sync_details_table.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class BangGroupListTile extends HookConsumerWidget {
final BangGroup group;
final String title;
final String subtitle;
const BangGroupListTile({
required this.group,
required this.title,
required this.subtitle,
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final lastSync = ref.watch(
lastSyncOfGroupProvider(group).select((value) => value.valueOrNull),
);
final count = ref.watch(
bangCountOfGroupProvider(group).select((value) => value.valueOrNull),
);
return CustomListTile(
title: title,
subtitle: subtitle,
content: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: SyncDetailsTable(count, lastSync),
),
suffix: FilledButton.icon(
onPressed: () async {
await ref
.read(bangSyncRepositoryProvider.notifier)
.syncBangGroup(group, null);
},
icon: const Icon(Icons.sync),
label: const Text('Sync'),
),
);
}
}
@@ -1,18 +1,23 @@
import 'package:flutter/material.dart';
class ButtonListTile extends StatelessWidget {
class CustomListTile extends StatelessWidget {
final bool enabled;
final String title;
final String subtitle;
final Widget? content;
final Widget button;
final Widget? prefix;
final Widget suffix;
const ButtonListTile({
const CustomListTile({
super.key,
required this.title,
required this.subtitle,
this.content,
required this.button,
this.prefix,
required this.suffix,
this.enabled = true,
});
@override
@@ -23,6 +28,7 @@ class ButtonListTile extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
child: Row(
children: [
if (prefix != null) prefix!,
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
@@ -30,17 +36,23 @@ class ButtonListTile extends StatelessWidget {
children: [
Text(
title,
style: theme.textTheme.bodyLarge,
style: enabled
? theme.textTheme.bodyLarge
: theme.textTheme.bodyLarge
?.copyWith(color: theme.disabledColor),
),
Text(
subtitle,
style: theme.textTheme.bodyMedium,
style: enabled
? theme.textTheme.bodyMedium
: theme.textTheme.bodyMedium
?.copyWith(color: theme.disabledColor),
),
if (content != null) content!,
],
),
),
button,
suffix,
],
),
);
@@ -0,0 +1,83 @@
import 'package:bang_navigator/features/content_block/data/models/host.dart';
import 'package:bang_navigator/features/content_block/domain/providers.dart';
import 'package:bang_navigator/features/content_block/domain/repositories/sync.dart';
import 'package:bang_navigator/features/settings/data/models/settings.dart';
import 'package:bang_navigator/features/settings/presentation/controllers/save_settings.dart';
import 'package:bang_navigator/features/settings/presentation/widgets/custom_list_tile.dart';
import 'package:bang_navigator/features/settings/presentation/widgets/sync_details_table.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class HostListTile extends HookConsumerWidget {
final bool enabled;
final bool enableContentBlocking;
final Set<HostSource> enableHostLists;
final HostSource source;
final String title;
final String subtitle;
const HostListTile({
required this.enableContentBlocking,
required this.enableHostLists,
required this.source,
required this.title,
required this.subtitle,
this.enabled = true,
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final enabled = enableHostLists.contains(source);
final lastSync = ref.watch(
lastSyncOfSourceProvider(source).select((value) => value.valueOrNull),
);
final count = ref.watch(
hostCountOfSourceProvider(source).select((value) => value.valueOrNull),
);
Future<void> toggleHostLists(HostSource source) async {
final lists = enabled
? ({...enableHostLists}..remove(source))
: {...enableHostLists, source};
await ref.read(saveSettingsControllerProvider.notifier).save(
(currentSettings) => currentSettings.copyWith.enableHostList(lists),
);
}
return CustomListTile(
enabled: enableContentBlocking,
title: title,
subtitle: subtitle,
prefix: Checkbox.adaptive(
value: enableHostLists.contains(source),
onChanged: enableContentBlocking
? (_) async {
await toggleHostLists(source);
}
: null,
),
suffix: FilledButton.icon(
onPressed: (enabled && enableContentBlocking)
? () async {
await ref
.read(hostSyncRepositoryProvider.notifier)
.syncHostSource(source, null);
}
: null,
icon: const Icon(Icons.sync),
label: const Text('Sync'),
),
content: (enabled && enableContentBlocking)
? Padding(
padding: const EdgeInsets.only(top: 8.0),
child: SyncDetailsTable(count, lastSync),
)
: null,
);
}
}
@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:timeago/timeago.dart' as timeago;
class SyncDetailsTable extends StatelessWidget {
final int? count;
final DateTime? lastSync;
const SyncDetailsTable(this.count, this.lastSync);
@override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: GoogleFonts.robotoMono(),
child: Table(
columnWidths: const {0: FixedColumnWidth(100)},
children: [
TableRow(
children: [
const Text('Entries'),
Text(count?.toString() ?? 'N/A'),
],
),
TableRow(
children: [
const Text('Last Sync'),
Text(
(lastSync != null) ? timeago.format(lastSync!) : 'N/A',
),
],
),
],
),
);
}
}