Add Supa account and search changes

This commit is contained in:
Fabian Freund
2026-05-22 18:10:22 +02:00
parent 3a19865b2e
commit 51289f1266
374 changed files with 54061 additions and 5013 deletions
@@ -22,6 +22,7 @@ import 'package:flutter_material_design_icons/flutter_material_design_icons.dart
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:nullability/nullability.dart';
import 'package:weblibre/features/settings/presentation/controllers/save_settings.dart';
import 'package:weblibre/features/settings/presentation/widgets/settings_detail.dart';
import 'package:weblibre/features/user/data/models/engine_settings.dart';
import 'package:weblibre/features/user/domain/entities/fingerprint_overrides.dart';
import 'package:weblibre/features/user/domain/providers.dart';
@@ -35,146 +36,172 @@ class FingerprintSettingsScreen extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final targetsAsync = ref.watch(fingerprintTargetsProvider);
final settingsAsync = ref.watch(fingerprintOverrideSettingsProvider);
final search = useSettingsSearch();
return Scaffold(
appBar: AppBar(
title: const Text('Fingerprint Protection'),
actions: [
MenuAnchor(
builder: (context, controller, child) {
return IconButton(
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
icon: const Icon(Icons.more_vert),
);
},
menuChildren: [
MenuItemButton(
leadingIcon: const Icon(MdiIcons.restore),
child: const Text('Load Defaults'),
onPressed: () async {
await ref
.read(saveEngineSettingsControllerProvider.notifier)
.save(
(currentSettings) => currentSettings.copyWith
.fingerprintingProtectionOverrides(
FingerprintOverrides.defaults().toString(),
),
);
},
),
MenuItemButton(
leadingIcon: const Icon(MdiIcons.restore),
child: const Text('Load Hardened Defaults'),
onPressed: () async {
await ref
.read(saveEngineSettingsControllerProvider.notifier)
.save(
(currentSettings) => currentSettings.copyWith
.fingerprintingProtectionOverrides(
FingerprintOverrides.hardenedDefaults()
.toString(),
),
);
},
),
],
),
],
),
body: SafeArea(
child: settingsAsync.when(
skipLoadingOnReload: true,
data: (result) {
return result.fold(
(overrides) {
return targetsAsync.when(
skipLoadingOnReload: true,
data: (targets) {
return ListView.builder(
itemCount: targets.length,
itemBuilder: (context, index) {
final target = targets[index];
final state = overrides.targets[target.name];
return CheckboxListTile.adaptive(
value:
(overrides.allTargets == true &&
state != false) ||
state == true,
onChanged: (value) async {
if (value != null) {
final newOverrides = overrides
.copyWithTarget(target.name, value)
.toString();
await ref
.read(
saveEngineSettingsControllerProvider
.notifier,
)
.save(
(currentSettings) => currentSettings
.copyWith
.fingerprintingProtectionOverrides(
newOverrides,
),
);
}
},
title: Text(target.name),
subtitle: target.description.mapNotNull(
(desc) => Text(desc),
return SettingsCustomScrollScaffold(
title: 'Fingerprint Protection',
searchController: search.controller,
searchHintText: 'Search fingerprint override targets',
actions: [
MenuAnchor(
builder: (context, controller, child) {
return IconButton(
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
icon: const Icon(Icons.more_vert),
);
},
menuChildren: [
MenuItemButton(
leadingIcon: const Icon(MdiIcons.restore),
child: const Text('Load Defaults'),
onPressed: () async {
await ref
.read(saveEngineSettingsControllerProvider.notifier)
.save(
(currentSettings) => currentSettings.copyWith
.fingerprintingProtectionOverrides(
FingerprintOverrides.defaults().toString(),
),
);
},
),
MenuItemButton(
leadingIcon: const Icon(MdiIcons.restore),
child: const Text('Load Hardened Defaults'),
onPressed: () async {
await ref
.read(saveEngineSettingsControllerProvider.notifier)
.save(
(currentSettings) => currentSettings.copyWith
.fingerprintingProtectionOverrides(
FingerprintOverrides.hardenedDefaults().toString(),
),
);
},
),
],
),
],
slivers: [
SliverPadding(
padding: const EdgeInsets.fromLTRB(16, 24, 16, 20),
sliver: SliverToBoxAdapter(
child: settingsAsync.when(
skipLoadingOnReload: true,
data: (result) {
return result.fold(
(overrides) {
return targetsAsync.when(
skipLoadingOnReload: true,
data: (targets) {
final filteredTargets = targets.where((target) {
if (search.normalizedQuery.isEmpty) return true;
return matchesSettingsSearch(search.normalizedQuery, [
target.name,
if (target.description != null) target.description!,
]);
}).toList();
return SettingsSectionList(
sections: filteredTargets.isEmpty
? const []
: [
SettingsSectionDefinition(
title: 'Override Targets',
entries: [
for (final target in filteredTargets)
SettingsEntryDefinition(
title: target.name,
subtitle: target.description,
child: CheckboxListTile.adaptive(
value:
(overrides.allTargets == true &&
overrides.targets[target
.name] !=
false) ||
overrides.targets[target
.name] ==
true,
onChanged: (value) async {
if (value != null) {
final newOverrides = overrides
.copyWithTarget(
target.name,
value,
)
.toString();
await ref
.read(
saveEngineSettingsControllerProvider
.notifier,
)
.save(
(
currentSettings,
) => currentSettings
.copyWith
.fingerprintingProtectionOverrides(
newOverrides,
),
);
}
},
title: Text(target.name),
subtitle: target.description
.mapNotNull(
(desc) => Text(desc),
),
),
),
],
),
],
query: search.rawQuery,
);
},
error: (error, stackTrace) {
return FailureWidget(
exception: error,
onRetry: () {
ref.invalidate(fingerprintTargetsProvider);
},
);
},
loading: () =>
const Center(child: CircularProgressIndicator()),
);
},
onFailure: (errorMessage) {
return FailureWidget(
title: errorMessage.message,
exception: errorMessage.details,
onRetry: () {
ref.invalidate(fingerprintOverrideSettingsProvider);
},
);
},
error: (error, stackTrace) {
return Center(
child: FailureWidget(
exception: error,
onRetry: () {
ref.invalidate(fingerprintTargetsProvider);
},
),
);
);
},
error: (error, stackTrace) {
return FailureWidget(
exception: error,
onRetry: () {
ref.invalidate(fingerprintOverrideSettingsProvider);
},
loading: () =>
const Center(child: CircularProgressIndicator()),
);
},
onFailure: (errorMessage) {
return Center(
child: FailureWidget(
title: errorMessage.message,
exception: errorMessage.details,
onRetry: () {
ref.invalidate(fingerprintOverrideSettingsProvider);
},
),
);
},
);
},
error: (error, stackTrace) {
return Center(
child: FailureWidget(
exception: error,
onRetry: () {
ref.invalidate(fingerprintOverrideSettingsProvider);
},
),
);
},
loading: () => const Center(child: CircularProgressIndicator()),
loading: () => const Center(child: CircularProgressIndicator()),
),
),
),
),
],
);
}
}