From eb9899d0e2ced74873bb171686c72dfce35603f7 Mon Sep 17 00:00:00 2001 From: Scriptbash <98601298+Scriptbash@users.noreply.github.com> Date: Sun, 5 Oct 2025 17:14:55 -0400 Subject: [PATCH] Add paper count setting --- lib/l10n/app_en.arb | 8 ++ lib/screens/display_settings_screen.dart | 140 ++++++++++++++++------- lib/screens/home_screen.dart | 30 +++-- 3 files changed, 131 insertions(+), 47 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 80f129b1..fff4ee57 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -47,6 +47,14 @@ "@notificationTitleJournal": {}, "notificationTitleQuery": "Queries were updated", "@notificationTitleQuery": {}, + "numberPublications": "{count, plural, =0{No publications} =1{1 publication} other{{count} publications}}", + "@numberPublications": { + "placeholders": { + "count": {} + } + }, + "showPublicationCount": "Show publication count", + "@showPublicationCount":{}, "selectFeed": "Select a feed", "@selectFeed": {}, "createCustomFeed": "Create a custom feed", diff --git a/lib/screens/display_settings_screen.dart b/lib/screens/display_settings_screen.dart index 2cddf062..b9ec808e 100644 --- a/lib/screens/display_settings_screen.dart +++ b/lib/screens/display_settings_screen.dart @@ -9,14 +9,16 @@ class DisplaySettingsScreen extends StatefulWidget { const DisplaySettingsScreen({super.key}); @override - _DisplaySettingsScreenState createState() => _DisplaySettingsScreenState(); + DisplaySettingsScreenState createState() => DisplaySettingsScreenState(); } -class _DisplaySettingsScreenState extends State { +class DisplaySettingsScreenState extends State { int _publicationCardOption = 1; int _pdfThemeOption = 0; int _pdfOrientationOption = 0; + bool _showPublicationCount = false; + final Map _languageLabels = { 'en': 'English', 'fr': 'Français', @@ -57,6 +59,7 @@ class _DisplaySettingsScreenState extends State { _loadPublicationCardOption(); _loadPdfThemeOption(); _loadPdfOrientationOption(); + _loadShowPublicationCount(); } void _loadPublicationCardOption() async { @@ -91,6 +94,18 @@ class _DisplaySettingsScreenState extends State { prefs.setInt('pdfOrientationOption', value); } + void _loadShowPublicationCount() async { + final prefs = await SharedPreferences.getInstance(); + setState(() { + _showPublicationCount = prefs.getBool('showPublicationCount') ?? false; + }); + } + + void _saveShowPublicationCount(bool value) async { + final prefs = await SharedPreferences.getInstance(); + prefs.setBool('showPublicationCount', value); + } + @override Widget build(BuildContext context) { final items = [ @@ -115,6 +130,14 @@ class _DisplaySettingsScreenState extends State { "subtitle": _getPdfOrientationSubtitle(_pdfOrientationOption), "onTap": () => _showPdfOrientationDialog(context), }, + { + "icon": Icons.format_list_numbered, + "label": AppLocalizations.of(context)!.showPublicationCount, + "subtitle": _showPublicationCount + ? AppLocalizations.of(context)!.enabled + : AppLocalizations.of(context)!.disabled, + "onTap": () => {}, + }, { "icon": Icons.article_outlined, "label": AppLocalizations.of(context)!.publicationCard, @@ -148,52 +171,89 @@ class _DisplaySettingsScreenState extends State { final double minTileHeight = 100; return GridView.builder( - padding: const EdgeInsets.all(16), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: crossAxisCount, - mainAxisSpacing: 16, - crossAxisSpacing: 16, - childAspectRatio: tileWidth / minTileHeight, - ), - itemCount: items.length, - itemBuilder: (context, index) { - final item = items[index]; - return Card( - elevation: 2, - child: InkWell( - onTap: item["onTap"] as VoidCallback, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, vertical: 14), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( + padding: const EdgeInsets.all(16), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: crossAxisCount, + mainAxisSpacing: 16, + crossAxisSpacing: 16, + childAspectRatio: tileWidth / minTileHeight, + ), + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; + + // Publication count tile + if (item["label"] == + AppLocalizations.of(context)!.showPublicationCount) { + return Card( + elevation: 2, + child: InkWell( + onTap: () { + setState(() => + _showPublicationCount = !_showPublicationCount); + _saveShowPublicationCount(_showPublicationCount); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 14), + child: Row( children: [ Icon(item["icon"] as IconData), - const SizedBox(width: 8), - Expanded(child: Text(item["label"] as String)), + const SizedBox(width: 12), + Expanded( + child: Text( + item["label"] as String, + ), + ), + Switch( + value: _showPublicationCount, + onChanged: (value) { + setState(() => _showPublicationCount = value); + _saveShowPublicationCount(value); + }, + ), ], ), - if (item["subtitle"] != null) - Padding( - padding: const EdgeInsets.only(top: 8, left: 32), - child: Text( - item["subtitle"] as String, - style: const TextStyle( - fontSize: 13, - color: Colors.grey, + ), + ), + ); + } + + // Default tiles + return Card( + elevation: 2, + child: InkWell( + onTap: item["onTap"] as VoidCallback, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 14), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + children: [ + Icon(item["icon"] as IconData), + const SizedBox(width: 8), + Expanded(child: Text(item["label"] as String)), + ], + ), + if (item["subtitle"] != null) + Padding( + padding: + const EdgeInsets.only(top: 8, left: 32), + child: Text( + item["subtitle"] as String, + style: const TextStyle( + fontSize: 13, color: Colors.grey), ), ), - ), - ], + ], + ), ), ), - ), - ); - }, - ); + ); + }); }, ), ), diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index b40e68ca..26567262 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -20,10 +20,10 @@ class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override - _HomeScreenState createState() => _HomeScreenState(); + HomeScreenState createState() => HomeScreenState(); } -class _HomeScreenState extends State { +class HomeScreenState extends State { final logger = LogsService().logger; final DatabaseHelper dbHelper = DatabaseHelper(); final StreamController> _feedStreamController = @@ -34,6 +34,7 @@ class _HomeScreenState extends State { int sortOrder = 1; // Set the default sort order to descending int fetchIntervalInHours = 6; // Default to 6 hours for API fetch int _concurrentFetches = 3; // Default to 3 concurrent requests + bool _showPublicationCount = false; List _currentJournalNames = []; // Variables related to the search bar in the appbar @@ -47,7 +48,7 @@ class _HomeScreenState extends State { List> savedQueries = []; bool _feedLoaded = false; // Needed to avoid conflicts wih onAbstractChanged - bool _useAndFilter = true; + final bool _useAndFilter = true; @override void initState() { @@ -73,6 +74,7 @@ class _HomeScreenState extends State { setState(() { fetchIntervalInHours = prefs.getInt('fetchInterval') ?? 6; _concurrentFetches = prefs.getInt('concurrentFetches') ?? 3; + _showPublicationCount = prefs.getBool('showPublicationCount') ?? false; }); final lastFeedName = prefs.getString('lastSelectedFeed'); @@ -351,7 +353,7 @@ class _HomeScreenState extends State { .where((j) => j.dateFollowed == null) .map((j) => j.title) .toList(); - + if (!mounted) return; showModalBottomSheet( context: context, isScrollControlled: true, @@ -536,11 +538,25 @@ class _HomeScreenState extends State { ), ); } else { + final feedItems = snapshot.data!; + return ListView.builder( - itemCount: snapshot.data!.length, + itemCount: feedItems.length + (_showPublicationCount ? 1 : 0), cacheExtent: 1000.0, itemBuilder: (context, index) { - return snapshot.data![index]; + if (_showPublicationCount && index == 0) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Center( + child: Text( + AppLocalizations.of(context)! + .numberPublications(feedItems.length), + style: Theme.of(context).textTheme.titleMedium, + ), + ), + ); + } + return feedItems[index - (_showPublicationCount ? 1 : 0)]; }, ); } @@ -645,7 +661,7 @@ class _HomeScreenState extends State { ]; bool isEditing = false; - + if (!mounted) return; await showDialog( context: context, builder: (context) {