import 'package:color_blindness/color_blindness.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; import '../controls/padding.dart'; import '../controls/responsive_max_width.dart'; import '../controls/standard_appbar.dart'; import '../di_initialization.dart'; import '../globals.dart'; import '../routes.dart'; import '../services/setting_service.dart'; import '../utils/known_network_extensions.dart'; import '../utils/theme_mode_extensions.dart'; class SettingsScreen extends StatelessWidget { const SettingsScreen({super.key}); @override Widget build(BuildContext context) { final settings = context.watch(); return Scaffold( appBar: StandardAppBar.build(context, 'Settings'), body: Center( child: Padding( padding: const EdgeInsets.all(8.0), child: ResponsiveMaxWidth( child: ListView( children: [ buildVersionString(), buildLowBandwidthWidget(settings), buildNotificationGroupingWidget(settings), buildSpoilerHidingEnabledWidget(settings), buildThemeWidget(settings), if (!kReleaseMode) buildColorBlindnessTestSettings(settings), buildClearCaches(context), buildLogPanel(context, settings), const NetworkCapabilitiesWidget(), ], ), ), ), )); } Widget buildVersionString() { return Center( child: Text( 'Relatica $appVersion', style: const TextStyle( decoration: TextDecoration.underline, fontWeight: FontWeight.bold, ), ), ); } Widget buildLowBandwidthWidget(SettingsService settings) { return ListTile( title: const Text('Low bandwidth mode'), trailing: Switch( onChanged: (value) { settings.lowBandwidthMode = value; }, value: settings.lowBandwidthMode, ), ); } Widget buildNotificationGroupingWidget(SettingsService settings) { return ListTile( title: const Text('Group notifications by type'), trailing: Switch( onChanged: (value) { settings.notificationGrouping = value; }, value: settings.notificationGrouping, ), ); } Widget buildSpoilerHidingEnabledWidget(SettingsService settings) { return ListTile( title: const Text('Spoiler/Content Warning Hiding'), trailing: Switch( onChanged: (value) { settings.spoilerHidingEnabled = value; }, value: settings.spoilerHidingEnabled, ), ); } Widget buildThemeWidget(SettingsService settings) { return ListTile( title: const Text('Dark Mode Theme:'), trailing: DropdownButton( value: settings.themeMode, items: ThemeMode.values .map((m) => DropdownMenuItem(value: m, child: Text(m.toLabel()))) .toList(), onChanged: (value) { if (value != null) { settings.themeMode = value; } }, ), ); } Widget buildColorBlindnessTestSettings(SettingsService settings) { return ListTile( title: const Text('Color Blindness Testing'), trailing: DropdownButton( value: settings.colorBlindnessType, items: ColorBlindnessType.values .map((c) => DropdownMenuItem(value: c, child: Text(c.name))) .toList(), onChanged: (value) { settings.colorBlindnessType = value ?? ColorBlindnessType.none; }), ); } Widget buildClearCaches(BuildContext context) { 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; } clearCaches(); }, child: const Text('Clear'), ), ); } Widget buildLogPanel(BuildContext context, SettingsService settings) { 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( value: settings.logLevel, items: Level.LEVELS .map((c) => DropdownMenuItem(value: c, child: Text(c.name))) .toList(), onChanged: (value) { settings.logLevel = value ?? Level.OFF; }), ); } } class NetworkCapabilitiesWidget extends StatelessWidget { const NetworkCapabilitiesWidget({super.key}); @override Widget build(BuildContext context) { final settings = context.watch(); final nc = settings.networkCapabilities; final rows = []; 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); settings.networkCapabilities = nc; }, ), ), DataCell( Checkbox( value: e.reshare, onChanged: (bool? value) { nc[i] = e.copyWith(reshare: value ?? false); settings.networkCapabilities = nc; }, ), ), DataCell( Checkbox( value: e.comment, onChanged: (bool? value) { nc[i] = e.copyWith(comment: value ?? false); settings.networkCapabilities = 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, ), )); } }