kopia lustrzana https://gitlab.com/mysocialportal/relatica
327 wiersze
9.4 KiB
Dart
327 wiersze
9.4 KiB
Dart
import 'package:color_blindness/color_blindness.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:logging/logging.dart';
|
|
|
|
import '../controls/padding.dart';
|
|
import '../controls/responsive_max_width.dart';
|
|
import '../controls/standard_appbar.dart';
|
|
import '../globals.dart';
|
|
import '../riverpod_controllers/account_services.dart';
|
|
import '../riverpod_controllers/cache_clear_service.dart';
|
|
import '../riverpod_controllers/settings_services.dart';
|
|
import '../routes.dart';
|
|
import '../utils/known_network_extensions.dart';
|
|
import '../utils/theme_mode_extensions.dart';
|
|
|
|
class SettingsScreen extends ConsumerWidget {
|
|
const SettingsScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
return Scaffold(
|
|
appBar: StandardAppBar.build(context, 'Settings'),
|
|
body: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: ResponsiveMaxWidth(
|
|
child: ListView(
|
|
children: const [
|
|
_BuildVersionWidget(),
|
|
_LowBandwidthWidget(),
|
|
_NetworkTimeoutWidget(),
|
|
_NotificationGroupingWidget(),
|
|
_SpoilerHidingWidget(),
|
|
_ThemeWidget(),
|
|
if (!kReleaseMode) _ColorBlindnessWidget(),
|
|
_ClearCachesWidget(),
|
|
_LogPanelWidget(),
|
|
_NetworkCapabilitiesWidget(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _NetworkTimeoutWidget extends ConsumerWidget {
|
|
const _NetworkTimeoutWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final timeout = ref.watch(friendicaApiTimeoutSettingProvider);
|
|
return ListTile(
|
|
title: const Text('Network Request Timeout (seconds)'),
|
|
trailing: DropdownButton<int>(
|
|
value: timeout.inSeconds,
|
|
items: List.generate(100, (i) {
|
|
final timeout = (i + 1) * 10;
|
|
return DropdownMenuItem(value: timeout, child: Text('$timeout'));
|
|
}),
|
|
onChanged: (value) {
|
|
ref.read(friendicaApiTimeoutSettingProvider.notifier).value =
|
|
Duration(seconds: value!);
|
|
}),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _NetworkCapabilitiesWidget extends ConsumerWidget {
|
|
const _NetworkCapabilitiesWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final nc = ref.watch(networkCapabilitiesSettingProvider);
|
|
final rows = <DataRow>[];
|
|
|
|
for (int i = 0; i < nc.length; i++) {
|
|
final e = nc[i];
|
|
final r = DataRow(
|
|
cells: [
|
|
DataCell(
|
|
Text(
|
|
'${e.network.forkAwesomeUnicode} ${e.network.labelName}',
|
|
style: const TextStyle(fontFamily: 'ForkAwesome'),
|
|
),
|
|
),
|
|
DataCell(
|
|
Checkbox(
|
|
value: e.react,
|
|
onChanged: (bool? value) {
|
|
nc[i] = e.copyWith(react: value ?? false);
|
|
ref.read(networkCapabilitiesSettingProvider.notifier).value =
|
|
nc;
|
|
},
|
|
),
|
|
),
|
|
DataCell(
|
|
Checkbox(
|
|
value: e.reshare,
|
|
onChanged: (bool? value) {
|
|
nc[i] = e.copyWith(reshare: value ?? false);
|
|
ref.read(networkCapabilitiesSettingProvider.notifier).value =
|
|
nc;
|
|
},
|
|
),
|
|
),
|
|
DataCell(
|
|
Checkbox(
|
|
value: e.comment,
|
|
onChanged: (bool? value) {
|
|
nc[i] = e.copyWith(comment: value ?? false);
|
|
ref.read(networkCapabilitiesSettingProvider.notifier).value =
|
|
nc;
|
|
},
|
|
),
|
|
),
|
|
],
|
|
);
|
|
rows.add(r);
|
|
}
|
|
|
|
return ListTile(
|
|
title: const Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text('Network Capabilities'),
|
|
ElevatedButton(
|
|
onPressed: null,
|
|
child: Text('Reset to Defaults'),
|
|
),
|
|
],
|
|
),
|
|
subtitle: SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
child: DataTable(
|
|
columnSpacing: 10.0,
|
|
columns: const [
|
|
DataColumn(
|
|
label: Text('Network'),
|
|
),
|
|
DataColumn(label: Text('React')),
|
|
DataColumn(label: Text('Reshare')),
|
|
DataColumn(label: Text('Comment')),
|
|
],
|
|
rows: rows,
|
|
),
|
|
));
|
|
}
|
|
}
|
|
|
|
class _BuildVersionWidget extends StatelessWidget {
|
|
const _BuildVersionWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Center(
|
|
child: Text(
|
|
'Relatica $appVersion',
|
|
style: const TextStyle(
|
|
decoration: TextDecoration.underline,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _LowBandwidthWidget extends ConsumerWidget {
|
|
const _LowBandwidthWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final value = ref.watch(lowBandwidthModeSettingProvider);
|
|
return ListTile(
|
|
title: const Text('Low bandwidth mode'),
|
|
trailing: Switch(
|
|
onChanged: (value) {
|
|
ref.read(lowBandwidthModeSettingProvider.notifier).value = value;
|
|
},
|
|
value: value,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _NotificationGroupingWidget extends ConsumerWidget {
|
|
const _NotificationGroupingWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final notificationGrouping = ref.watch(notificationGroupingSettingProvider);
|
|
return ListTile(
|
|
title: const Text('Group notifications by type'),
|
|
trailing: Switch(
|
|
onChanged: (value) {
|
|
ref.read(notificationGroupingSettingProvider.notifier).value = value;
|
|
},
|
|
value: notificationGrouping,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _SpoilerHidingWidget extends ConsumerWidget {
|
|
const _SpoilerHidingWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final spoilingHidingEnabled = ref.watch(spoilerHidingSettingProvider);
|
|
return ListTile(
|
|
title: const Text('Spoiler/Content Warning Hiding'),
|
|
trailing: Switch(
|
|
onChanged: (value) {
|
|
ref.read(spoilerHidingSettingProvider.notifier).value = value;
|
|
},
|
|
value: spoilingHidingEnabled,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ThemeWidget extends ConsumerWidget {
|
|
const _ThemeWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final themeMode = ref.watch(themeModeSettingProvider);
|
|
return ListTile(
|
|
title: const Text('Dark Mode Theme:'),
|
|
trailing: DropdownButton<ThemeMode>(
|
|
value: themeMode,
|
|
items: ThemeMode.values
|
|
.map((m) => DropdownMenuItem(value: m, child: Text(m.toLabel())))
|
|
.toList(),
|
|
onChanged: (value) {
|
|
if (value != null) {
|
|
ref.read(themeModeSettingProvider.notifier).value = value;
|
|
}
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ColorBlindnessWidget extends ConsumerWidget {
|
|
const _ColorBlindnessWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final colorBlindnessType =
|
|
ref.watch(colorBlindnessTestingModeSettingProvider);
|
|
return ListTile(
|
|
title: const Text('Color Blindness Testing'),
|
|
trailing: DropdownButton<ColorBlindnessType>(
|
|
value: colorBlindnessType,
|
|
items: ColorBlindnessType.values
|
|
.map((c) => DropdownMenuItem(value: c, child: Text(c.name)))
|
|
.toList(),
|
|
onChanged: (value) {
|
|
ref.read(colorBlindnessTestingModeSettingProvider.notifier).value =
|
|
value ?? ColorBlindnessType.none;
|
|
}),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ClearCachesWidget extends ConsumerWidget {
|
|
const _ClearCachesWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final profile = ref.watch(activeProfileProvider);
|
|
return ListTile(
|
|
title: const Text('Clear local caches'),
|
|
subtitle: const Text('This does not affect server side data at all.'),
|
|
trailing: ElevatedButton(
|
|
onPressed: () async {
|
|
final confirm = await showYesNoDialog(context,
|
|
'Are you sure you want to clear all local data for this account?');
|
|
if (confirm != true) {
|
|
return;
|
|
}
|
|
|
|
ref
|
|
.read(clearCachesProvider.notifier)
|
|
.profileCacheClearService(profile);
|
|
},
|
|
child: const Text('Clear'),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _LogPanelWidget extends ConsumerWidget {
|
|
const _LogPanelWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final logLevel = ref.watch(logLevelSettingProvider);
|
|
return ListTile(
|
|
title: Wrap(
|
|
children: [
|
|
const Text('Log Level'),
|
|
const HorizontalPadding(),
|
|
ElevatedButton(
|
|
onPressed: () => context.pushNamed(ScreenPaths.logViewer),
|
|
child: const Text('Open Log Viewer'),
|
|
)
|
|
],
|
|
),
|
|
trailing: DropdownButton<Level>(
|
|
value: logLevel,
|
|
items: Level.LEVELS
|
|
.map((c) => DropdownMenuItem(value: c, child: Text(c.name)))
|
|
.toList(),
|
|
onChanged: (value) {
|
|
ref.read(logLevelSettingProvider.notifier).value =
|
|
value ?? Level.OFF;
|
|
}),
|
|
);
|
|
}
|
|
}
|