feat: build v1 Mews client: reader UI, gestures, Drift store, fetch actor
This commit is contained in:
parent
d5a0fcbf48
commit
01a36e8aee
56 changed files with 7287 additions and 2 deletions
169
app/lib/presentation/reader/settings_sheet.dart
Normal file
169
app/lib/presentation/reader/settings_sheet.dart
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:signals/signals_flutter.dart' show SignalBuilder;
|
||||
|
||||
import '../../application/controllers/reader_settings_controller.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<void>(
|
||||
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,
|
||||
),
|
||||
),
|
||||
_heading(context, strings.t('settings-font-heading')),
|
||||
RadioGroup<String>(
|
||||
groupValue: settings.font.value,
|
||||
onChanged: (value) => settings.setFont(value!),
|
||||
child: Column(
|
||||
children: [
|
||||
for (final font in readerFonts)
|
||||
RadioListTile<String>(
|
||||
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<String>(
|
||||
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<String>(
|
||||
value: mode,
|
||||
title: Text(strings.t(id)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_heading(context, strings.t('settings-variant-heading')),
|
||||
RadioGroup<String>(
|
||||
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<String>(
|
||||
value: variant,
|
||||
title: Text(strings.t(id)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
if (url != null) ...[
|
||||
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 []),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
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),
|
||||
),
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue