import 'package:flutter/material.dart'; import 'package:signals/signals_flutter.dart' show SignalBuilder; import '../../application/controllers/reader_settings_controller.dart'; import '../../application/internal_pages.dart'; import '../app.dart'; import 'reader_fonts.dart'; /// Opens the reader settings bottom sheet: fonts, text size, theme, colors, /// bookmark and subscription for the current page. void showReaderSettingsSheet(BuildContext context) { showModalBottomSheet( context: context, isScrollControlled: true, builder: (context) => const SettingsSheet(), ); } class SettingsSheet extends StatelessWidget { const SettingsSheet({super.key}); @override Widget build(BuildContext context) { final scope = AppScope.of(context); final deps = scope.deps; final strings = scope.strings; return SignalBuilder(builder: (context) { final settings = deps.settings; final library = deps.library; final page = deps.browser.currentPage.value; final url = page?.url; final percent = (settings.fontScale.value * 100).round(); return SafeArea( child: ListView( shrinkWrap: true, padding: const EdgeInsets.fromLTRB(0, 12, 0, 16), children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text( strings.t('settings-sheet-title'), style: Theme.of(context).textTheme.titleMedium, ), ), // The library pages are internal Mews pages; opening one joins // the walk history like any other page. ListTile( leading: const Icon(Icons.history), title: Text(strings.t('settings-history')), onTap: () => _openPage(context, InternalPages.historyUrl), ), ListTile( leading: const Icon(Icons.star_outline), title: Text(strings.t('settings-bookmarks')), onTap: () => _openPage(context, InternalPages.bookmarksUrl), ), ListTile( leading: const Icon(Icons.notifications_outlined), title: Text(strings.t('settings-subscriptions')), onTap: () => _openPage(context, InternalPages.subscriptionsUrl), ), const Divider(), _heading(context, strings.t('settings-font-heading')), RadioGroup( groupValue: settings.font.value, onChanged: (value) => settings.setFont(value!), child: Column( children: [ for (final font in readerFonts) RadioListTile( value: font.family, title: Text(strings.t(font.labelId)), ), ], ), ), _heading(context, strings.t('settings-size-heading')), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( tooltip: strings.t('settings-size-decrease'), onPressed: settings.fontScale.value > ReaderSettingsController.minScale ? settings.decreaseSize : null, icon: const Icon(Icons.remove), ), SizedBox( width: 56, child: Text( '$percent%', textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleMedium, ), ), IconButton( tooltip: strings.t('settings-size-increase'), onPressed: settings.fontScale.value < ReaderSettingsController.maxScale ? settings.increaseSize : null, icon: const Icon(Icons.add), ), ], ), _heading(context, strings.t('settings-theme-heading')), RadioGroup( groupValue: settings.themeMode.value, onChanged: (value) => settings.setThemeMode(value!), child: Column( children: [ for (final (mode, id) in [ ('light', 'settings-theme-light'), ('dark', 'settings-theme-dark'), ('system', 'settings-theme-system'), ]) RadioListTile( value: mode, title: Text(strings.t(id)), ), ], ), ), _heading(context, strings.t('settings-variant-heading')), RadioGroup( groupValue: settings.variant.value, onChanged: (value) => settings.setVariant(value!), child: Column( children: [ for (final (variant, id) in [ ('site', 'settings-variant-site'), ('warm', 'settings-variant-warm'), ('cool', 'settings-variant-cool'), ('green', 'settings-variant-green'), ('mono', 'settings-variant-mono'), ]) RadioListTile( value: variant, title: Text(strings.t(id)), ), ], ), ), const Divider(), if (url != null && !InternalPages.isInternal(url)) ...[ ListTile( leading: Icon(library.isBookmarked(url) ? Icons.star : Icons.star_border), title: Text( library.isBookmarked(url) ? strings.t('settings-bookmark-remove') : strings.t('settings-bookmark-add'), ), onTap: () => library.toggleBookmark(url, page?.title), ), ListTile( leading: Icon(library.isSubscribed(url) ? Icons.notifications_active : Icons.notifications_outlined), title: Text( library.isSubscribed(url) ? strings.t('settings-unsubscribe') : strings.t('settings-subscribe'), ), subtitle: library.isSubscribed(url) ? Text(strings.t('settings-subscribed-notice')) : null, onTap: () => library.toggleSubscription(url, page?.title, page?.entries ?? const []), ), ], ], ), ); }); } void _openPage(BuildContext context, String url) { Navigator.of(context).pop(); AppScope.of(context).deps.browser.open(url); } Widget _heading(BuildContext context, String text) => Padding( padding: const EdgeInsets.fromLTRB(16, 16, 16, 4), child: Text( text, style: Theme.of(context) .textTheme .labelLarge ?.copyWith(color: Theme.of(context).colorScheme.primary), ), ); }