From 4e01bedf55dbc2ae087b51283b8e8c304c99dc14 Mon Sep 17 00:00:00 2001 From: Kshitij B Date: Tue, 9 Apr 2024 15:48:17 +0530 Subject: [PATCH] fixes #6 and quint search issue (#7) * fix quint search * format / optimize imports * add 0.8.2 * update gitignore * fix scroll issue in category popup --- .gitignore | 125 +------- changelog.md | 7 +- lib/brain/article_provider.dart | 1 - .../general/national/india/thequint.dart | 6 +- lib/extractor/general/world/apnews.dart | 4 - lib/extractor/general/world/cnn.dart | 3 +- lib/extractor/general/world/theguardian.dart | 4 - lib/pages/category_selector.dart | 276 ++++++++++++++++++ lib/pages/feed.dart | 1 - lib/pages/subscription.dart | 270 ++--------------- pubspec.yaml | 2 +- test/extractor/common.dart | 32 +- .../general/national/india/thequint_test.dart | 3 +- .../general/national/india/thewire_test.dart | 3 +- .../general/world/theguardian_test.dart | 1 - .../technology/bleepingcomputer_test.dart | 4 +- 16 files changed, 339 insertions(+), 403 deletions(-) create mode 100644 lib/pages/category_selector.dart diff --git a/.gitignore b/.gitignore index c21169b..29a3a50 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,5 @@ -# Do not remove or rename entries in this file, only add new ones -# See https://github.com/flutter/flutter/issues/128635 for more context. - # Miscellaneous *.class -*.lock *.log *.pyc *.swp @@ -12,6 +8,7 @@ .buildlog/ .history .svn/ +migrate_working_dir/ # IntelliJ related *.iml @@ -19,120 +16,28 @@ *.iws .idea/ -# Visual Studio Code related -.classpath -.project -.settings/ -.vscode/* - -# Flutter repo-specific -/bin/cache/ -/bin/internal/bootstrap.bat -/bin/internal/bootstrap.sh -/bin/mingit/ -/dev/benchmarks/mega_gallery/ -/dev/bots/.recipe_deps -/dev/bots/android_tools/ -/dev/devicelab/ABresults*.json -/dev/docs/doc/ -/dev/docs/api_docs.zip -/dev/docs/flutter.docs.zip -/dev/docs/lib/ -/dev/docs/pubspec.yaml -/dev/integration_tests/**/xcuserdata -/dev/integration_tests/**/Pods -/packages/flutter/coverage/ -version -analysis_benchmark.json - -# packages file containing multi-root paths -.packages.generated +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ # Flutter/Dart/Pub related **/doc/api/ +**/ios/Flutter/.last_build_id .dart_tool/ .flutter-plugins .flutter-plugins-dependencies -**/generated_plugin_registrant.dart -.packages -.pub-preload-cache/ .pub-cache/ .pub/ -build/ -flutter_*.png -linked_*.ds -unlinked.ds -unlinked_spec.ds - -# Android related -**/android/**/gradle-wrapper.jar -.gradle/ -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -*.jks - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/.last_build_id -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/ephemeral -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# macOS -**/Flutter/ephemeral/ -**/Pods/ -**/macos/Flutter/GeneratedPluginRegistrant.swift -**/macos/Flutter/ephemeral -**/xcuserdata/ - -# Windows -**/windows/flutter/generated_plugin_registrant.cc -**/windows/flutter/generated_plugin_registrant.h -**/windows/flutter/generated_plugins.cmake +/build/ -# Linux -**/linux/flutter/generated_plugin_registrant.cc -**/linux/flutter/generated_plugin_registrant.h -**/linux/flutter/generated_plugins.cmake - -# Coverage -coverage/ - -# Symbols +# Symbolication related app.*.symbols -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -!/dev/ci/**/Gemfile.lock -!.vscode/settings.json +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/changelog.md b/changelog.md index 8dbf6e9..5598d2b 100644 --- a/changelog.md +++ b/changelog.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.8.1] - 2024-03-31 +## [0.8.2] - 2024-04-07 + +Fdroid release + +## [0.8.1] - 2024-04-07 ### Added: - Source: AP News @@ -112,6 +116,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### First Release [unreleased]: https://github.com/ksh-b/raven/compare/v0.8.1...HEAD +[0.8.2]: https://github.com/ksh-b/raven/compare/v0.8.1...v0.8.2 [0.8.1]: https://github.com/ksh-b/raven/compare/v0.7.1...v0.8.1 [0.7.1]: https://github.com/ksh-b/raven/compare/v0.6.0...v0.7.1 [0.6.0]: https://github.com/ksh-b/raven/compare/v0.5.2...v0.6.0 diff --git a/lib/brain/article_provider.dart b/lib/brain/article_provider.dart index 8a28443..0b0eae5 100644 --- a/lib/brain/article_provider.dart +++ b/lib/brain/article_provider.dart @@ -1,5 +1,4 @@ import 'dart:collection'; -import 'dart:developer'; import 'package:raven/model/article.dart'; import 'package:raven/model/publisher.dart'; import 'package:raven/model/user_subscription.dart'; diff --git a/lib/extractor/general/national/india/thequint.dart b/lib/extractor/general/national/india/thequint.dart index 5a7f30d..10c5565 100644 --- a/lib/extractor/general/national/india/thequint.dart +++ b/lib/extractor/general/national/india/thequint.dart @@ -1,7 +1,3 @@ -// ignore_for_file: unused_import - -import 'dart:collection'; - import 'package:html/dom.dart'; import 'package:raven/model/article.dart'; import 'package:raven/model/publisher.dart'; @@ -125,7 +121,7 @@ class TheQuint extends Publisher { "https://images.thequint.com/${element['hero-image-s3-key']}"; var time = element["last-published-at"]; var articleUrl = element["url"]; - var sections = element['story']["sections"]; + var sections = element["sections"]; for (var section in sections) { tags.add(section["name"]); } diff --git a/lib/extractor/general/world/apnews.dart b/lib/extractor/general/world/apnews.dart index 74c550a..313a5b9 100644 --- a/lib/extractor/general/world/apnews.dart +++ b/lib/extractor/general/world/apnews.dart @@ -1,12 +1,9 @@ -// ignore_for_file: unused_import - import 'package:intl/intl.dart'; import 'package:raven/model/article.dart'; import 'package:raven/model/publisher.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:html/parser.dart' as html_parser; -import 'package:raven/utils/string.dart'; import 'package:raven/utils/time.dart'; class APNews extends Publisher { @@ -29,7 +26,6 @@ class APNews extends Publisher { var document = html_parser.parse(utf8.decode(response.bodyBytes)); document .querySelectorAll('.Page-header-navigation .AnClick-MainNav') - .take(5) .forEach((element) { map.putIfAbsent( element.text, diff --git a/lib/extractor/general/world/cnn.dart b/lib/extractor/general/world/cnn.dart index 3fcc0e4..d103f69 100644 --- a/lib/extractor/general/world/cnn.dart +++ b/lib/extractor/general/world/cnn.dart @@ -81,7 +81,8 @@ class CNN extends Publisher { int convertToUnixTimestamp(String dateString) { DateFormat dateFormat = DateFormat("h:mm a 'EDT', EEE MMMM d, yyyy", 'en_US'); - DateTime dateTime = dateFormat.parse(dateString.trim()); + DateTime dateTime = + dateFormat.tryParse(dateString.trim()) ?? DateTime.timestamp(); return dateTime.millisecondsSinceEpoch ~/ 1000; } diff --git a/lib/extractor/general/world/theguardian.dart b/lib/extractor/general/world/theguardian.dart index c424247..8b7c656 100644 --- a/lib/extractor/general/world/theguardian.dart +++ b/lib/extractor/general/world/theguardian.dart @@ -1,12 +1,8 @@ -// ignore_for_file: unused_import - -import 'package:intl/intl.dart'; import 'package:raven/model/article.dart'; import 'package:raven/model/publisher.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:html/parser.dart' as html_parser; -import 'package:raven/utils/string.dart'; import 'package:raven/utils/time.dart'; class TheGuardian extends Publisher { diff --git a/lib/pages/category_selector.dart b/lib/pages/category_selector.dart new file mode 100644 index 0000000..6179130 --- /dev/null +++ b/lib/pages/category_selector.dart @@ -0,0 +1,276 @@ +import 'package:flutter/material.dart'; +import 'package:raven/model/publisher.dart'; +import 'package:raven/model/user_subscription.dart'; +import 'package:raven/utils/store.dart'; + +class CategorySelector extends StatefulWidget { + final Map publishers; + final String newsSource; + final VoidCallback callback; + + const CategorySelector(this.publishers, this.newsSource, + {super.key, required this.callback}); + + @override + State createState() => _CategorySelectorState(); +} + +class _CategorySelectorState extends State { + List selectedSubscriptions = []; // List + List customSubscriptions = []; // List + String customCategory = ""; + TextEditingController customCategoryController = TextEditingController(); + Future>? future; + + @override + void initState() { + setState(() { + selectedSubscriptions = Store.selectedSubscriptions; + customSubscriptions = Store.customSubscriptions + .where((element) => element.publisher == widget.newsSource) + .toList(); + }); + super.initState(); + future = widget.publishers[widget.newsSource]?.categories; + } + + String convertString(String input) { + List parts = input.split('/'); + parts.removeWhere((part) => part.isEmpty); + List capitalizedParts = parts.map((part) { + return capitalize(part); + }).toList(); + String result = capitalizedParts.join('/'); + return result; + } + + String capitalize(String string) { + return "${string[0].toUpperCase()}${string.substring(1)}"; + } + + @override + Widget build(BuildContext context) { + int customSubsSize = customSubscriptions + .where((element) => element.publisher == widget.newsSource) + .length; + return Scaffold( + appBar: AppBar( + title: Text("${widget.newsSource} categories"), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: FutureBuilder( + future: future, + builder: (context, snapshot) { + if (snapshot.hasData) { + return ListView.builder( + shrinkWrap: true, + itemCount: snapshot.data!.length + 3 + customSubsSize, + itemBuilder: (context, index) { + var subCategoryKey = "All"; + var subCategoryValue = "/"; + var userSubscription = + UserSubscription(widget.newsSource, subCategoryValue); + if (index == 0) { + return _buildAllCheckbox(subCategoryKey, userSubscription); + } + if (index - 1 < snapshot.data!.length) { + subCategoryKey = snapshot.data!.keys.toList()[index - 1]; + subCategoryValue = snapshot.data!.values.toList()[index - 1]; + userSubscription = + UserSubscription(widget.newsSource, subCategoryValue); + return _buildCategorySelector( + subCategoryKey, userSubscription); + } else if (index > snapshot.data!.length && + index < customSubsSize + snapshot.data!.length + 1) { + return customCategorySaved(index, snapshot); + } else if (index == + (snapshot.data!.length + 1 + customSubsSize)) { + return Flex( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + direction: Axis.horizontal, + children: [ + _buildCustomSourceSelector(), + if (customCategory.isEmpty) + const Flexible(child: SizedBox.shrink()) + else + _buildCustomTester() + ], + ); + } else { + return SaveButton( + selectedSubscriptions: selectedSubscriptions, + widget: widget, + ); + } + }, + ); + } else if (snapshot.hasError) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Text(snapshot.error.toString()), + ); + } + return const Center( + child: CircularProgressIndicator(), + ); + }, + ), + ), + ); + } + + CheckboxListTile _buildAllCheckbox( + String subCategoryKey, UserSubscription userSubscription) { + return CheckboxListTile( + title: Text(subCategoryKey), + value: selectedSubscriptions.contains(userSubscription), + onChanged: (value) { + if (value!) { + selectedSubscriptions.removeWhere((element) { + return element.publisher == userSubscription.publisher; + }); + } + updateList(value, userSubscription); + }, + ); + } + + CheckboxListTile _buildCategorySelector( + String subCategoryKey, UserSubscription userSubscription) { + return CheckboxListTile( + title: Text(subCategoryKey), + value: selectedSubscriptions.contains(userSubscription), + onChanged: selectedSubscriptions + .where((element) => + element.publisher == userSubscription.publisher && + element.category == "/") + .isNotEmpty + ? null + : (value) { + updateList(value, userSubscription); + }, + ); + } + + CheckboxListTile customCategorySaved( + int index, AsyncSnapshot> snapshot) { + return CheckboxListTile( + secondary: IconButton( + icon: const Icon(Icons.delete_forever), + onPressed: () { + var subscription = + customSubscriptions[index - (snapshot.data!.length + 1)]; + setState(() { + customSubscriptions.remove(subscription); + selectedSubscriptions.remove(subscription); + }); + var cs = Store.customSubscriptions; + cs.remove(subscription); + Store.customSubscriptions = cs; + var ss = Store.selectedSubscriptions; + ss.remove(subscription); + Store.selectedSubscriptions = ss; + }), + title: Text(convertString( + (customSubscriptions[index - (snapshot.data!.length + 1)] + as UserSubscription) + .category)), + value: selectedSubscriptions + .contains(customSubscriptions[index - (snapshot.data!.length + 1)]), + onChanged: (value) { + updateList( + value, customSubscriptions[index - (snapshot.data!.length + 1)]); + }, + ); + } + + Widget _buildCustomSourceSelector() { + return Flexible( + flex: 3, + fit: FlexFit.tight, + child: TextField( + controller: customCategoryController, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: "Custom category", + ), + onEditingComplete: () { + setState(() { + customCategory = customCategoryController.text; + }); + }, + )); + } + + Flexible _buildCustomTester() { + return Flexible( + flex: 1, + child: FutureBuilder( + future: widget.publishers[widget.newsSource] + ?.articles(category: customCategory), + builder: (context, snapshot) { + if (snapshot.hasData) { + return snapshot.data!.isNotEmpty + ? IconButton( + onPressed: () { + setState(() { + customSubscriptions.add(UserSubscription( + widget.newsSource, + customCategory, + )); + }); + Store.customSubscriptions += [ + UserSubscription( + widget.newsSource, + customCategory, + ) + ]; + }, + icon: const Icon(Icons.save_alt)) + : const Icon(Icons.cancel); + } else if (snapshot.hasError) { + const Icon(Icons.cancel); + } + return const CircularProgressIndicator(); + }, + ), + ); + } + + void updateList(bool? value, UserSubscription userSubscription) { + setState(() { + if (value!) { + selectedSubscriptions.add(userSubscription); + } else { + selectedSubscriptions.remove(userSubscription); + } + }); + } +} + +class SaveButton extends StatelessWidget { + const SaveButton({ + super.key, + required this.selectedSubscriptions, + required this.widget, + }); + + final List selectedSubscriptions; + final CategorySelector widget; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: FilledButton( + onPressed: () { + Store.selectedSubscriptions = selectedSubscriptions; + Navigator.of(context).pop(); + widget.callback(); + }, + child: const Text("SAVE"), + ), + ); + } +} diff --git a/lib/pages/feed.dart b/lib/pages/feed.dart index 612907c..a6a6fdd 100644 --- a/lib/pages/feed.dart +++ b/lib/pages/feed.dart @@ -13,7 +13,6 @@ class _FeedPageState extends State with AutomaticKeepAliveClientMixin { @override Widget build(BuildContext context) { - super.build(context); return SafeArea( child: Scaffold( diff --git a/lib/pages/subscription.dart b/lib/pages/subscription.dart index 38ea347..6bb91db 100644 --- a/lib/pages/subscription.dart +++ b/lib/pages/subscription.dart @@ -3,9 +3,10 @@ import 'dart:core'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:raven/model/publisher.dart'; -import 'package:raven/model/user_subscription.dart'; import 'package:raven/utils/store.dart'; +import 'category_selector.dart'; + class SubscriptionsPage extends StatefulWidget { const SubscriptionsPage({super.key}); @@ -20,6 +21,7 @@ class _SubscriptionsPageState extends State TextEditingController searchController = TextEditingController(); bool _isSearching = false; int? _value = 0; + @override void initState() { filteredNewsSources = newsSources; @@ -116,16 +118,20 @@ class _SubscriptionsPageState extends State ? SizedBox.shrink() : Icon(Icons.check_circle), onTap: () { - showDialog( - context: context, - builder: (context) { - return CategoryPopup(publishers, newsSource, - callback: () { - setState(() { - categories = getSelectedCategories(newsSource); - }); - }); - }, + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => CategorySelector( + publishers, + newsSource, + callback: () { + setState( + () { + categories = getSelectedCategories(newsSource); + }, + ); + }, + ), + ), ); }, ); @@ -158,245 +164,3 @@ class _SubscriptionsPageState extends State @override bool get wantKeepAlive => true; } - -class CategoryPopup extends StatefulWidget { - final Map publishers; - final String newsSource; - final VoidCallback callback; - - const CategoryPopup(this.publishers, this.newsSource, - {super.key, required this.callback}); - - @override - State createState() => _CategoryPopupState(); -} - -class _CategoryPopupState extends State { - List selectedSubscriptions = []; // List - List customSubscriptions = []; // List - String customCategory = ""; - TextEditingController customCategoryController = TextEditingController(); - Future>? future; - - @override - void initState() { - setState(() { - selectedSubscriptions = Store.selectedSubscriptions; - customSubscriptions = Store.customSubscriptions - .where((element) => element.publisher == widget.newsSource) - .toList(); - }); - super.initState(); - future = widget.publishers[widget.newsSource]?.categories; - } - - String convertString(String input) { - List parts = input.split('/'); - parts.removeWhere((part) => part.isEmpty); - List capitalizedParts = parts.map((part) { - return capitalize(part); - }).toList(); - String result = capitalizedParts.join('/'); - return result; - } - - String capitalize(String string) { - return "${string[0].toUpperCase()}${string.substring(1)}"; - } - - @override - Widget build(BuildContext context) { - return Dialog( - child: FutureBuilder( - future: future, - builder: (context, snapshot) { - if (snapshot.hasData) { - return Padding( - padding: const EdgeInsets.all(16.0), - child: ListView( - shrinkWrap: true, - children: [ - const Padding( - padding: EdgeInsets.all(8.0), - child: Text( - "Categories", - style: - TextStyle(fontSize: 18, fontWeight: FontWeight.w500), - ), - ), - ListView.builder( - shrinkWrap: true, - itemCount: snapshot.data!.length + 1, - itemBuilder: (context, categoryIndex) { - var subCategoryKey = "All"; - var subCategoryValue = "/"; - var userSubscription = - UserSubscription(widget.newsSource, subCategoryValue); - if (categoryIndex == 0) { - // All checkbox - return CheckboxListTile( - title: Text(subCategoryKey), - value: - selectedSubscriptions.contains(userSubscription), - onChanged: (value) { - if (value!) { - selectedSubscriptions.removeWhere((element) { - return element.publisher == - userSubscription.publisher; - }); - } - updateList(value, userSubscription); - }, - ); - } - subCategoryKey = - snapshot.data!.keys.toList()[categoryIndex - 1]; - subCategoryValue = - snapshot.data!.values.toList()[categoryIndex - 1]; - userSubscription = - UserSubscription(widget.newsSource, subCategoryValue); - // category checkbox - return CheckboxListTile( - title: Text(subCategoryKey), - value: selectedSubscriptions.contains(userSubscription), - onChanged: selectedSubscriptions - .where((element) => - element.publisher == - userSubscription.publisher && - element.category == "/") - .isNotEmpty - ? null - : (value) { - updateList(value, userSubscription); - }, - ); - }, - ), - ListView.builder( - shrinkWrap: true, - itemCount: customSubscriptions - .where( - (element) => element.publisher == widget.newsSource) - .length, - itemBuilder: (context, index) { - return CheckboxListTile( - secondary: IconButton( - icon: const Icon(Icons.delete_forever), - onPressed: () { - var subscription = customSubscriptions[index]; - setState(() { - customSubscriptions.remove(subscription); - selectedSubscriptions.remove(subscription); - }); - var cs = Store.customSubscriptions; - cs.remove(subscription); - Store.customSubscriptions = cs; - var ss = Store.selectedSubscriptions; - ss.remove(subscription); - Store.selectedSubscriptions = ss; - }), - title: Text(convertString( - (customSubscriptions[index] as UserSubscription) - .category)), - value: selectedSubscriptions - .contains(customSubscriptions[index]), - onChanged: (value) { - updateList(value, customSubscriptions[index]); - }, - ); - }, - ), - Flex( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - direction: Axis.horizontal, - children: [ - Flexible( - flex: 3, - child: TextField( - controller: customCategoryController, - decoration: const InputDecoration( - hintText: "Custom category"), - onEditingComplete: () { - setState(() { - customCategory = customCategoryController.text; - }); - }, - )), - if (customCategory.isEmpty) - const Flexible(child: SizedBox.shrink()) - else - Flexible( - flex: 1, - child: FutureBuilder( - future: widget.publishers[widget.newsSource] - ?.articles(category: customCategory), - builder: (context, snapshot) { - if (snapshot.hasData) { - return snapshot.data!.isNotEmpty - ? IconButton( - onPressed: () { - setState(() { - customSubscriptions - .add(UserSubscription( - widget.newsSource, - customCategory, - )); - }); - Store.customSubscriptions += [ - UserSubscription( - widget.newsSource, - customCategory, - ) - ]; - }, - icon: const Icon(Icons.save_alt)) - : const Icon(Icons.cancel); - } else if (snapshot.hasError) { - const Icon(Icons.cancel); - } - return const CircularProgressIndicator(); - }, - ), - ) - ], - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: FilledButton( - onPressed: () { - Store.selectedSubscriptions = selectedSubscriptions; - Navigator.of(context).pop(); - widget.callback(); - }, - child: const Text("SAVE"), - ), - ), - ], - ), - ); - } else if (snapshot.hasError) { - return Padding( - padding: const EdgeInsets.all(8.0), - child: Text(snapshot.error.toString()), - ); - } - return const Padding( - padding: EdgeInsets.all(8.0), - child: Text("Loading"), - ); - }, - ), - ); - } - - void updateList(bool? value, UserSubscription userSubscription) { - setState(() { - if (value!) { - selectedSubscriptions.add(userSubscription); - } else { - selectedSubscriptions.remove(userSubscription); - } - }); - } -} diff --git a/pubspec.yaml b/pubspec.yaml index d72fd14..e1d959f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: raven description: "News aggregator" publish_to: 'none' -version: 0.8.2+20 +version: 0.8.3+21 environment: sdk: '>=3.2.1 <4.0.0' diff --git a/test/extractor/common.dart b/test/extractor/common.dart index 59b797c..8084ad8 100644 --- a/test/extractor/common.dart +++ b/test/extractor/common.dart @@ -10,50 +10,54 @@ class ExtractorTest { expect(categories.isNotEmpty, true); } - static Future categoryArticlesTest(Publisher publisher, {String? category}) async { - if(category==null) { + static Future categoryArticlesTest(Publisher publisher, + {String? category}) async { + if (category == null) { final Map categories = await publisher.categories; - for(String category in categories.values) { + for (String category in categories.values) { expect(category, isNotNull); - final categoryArticles = await publisher.categoryArticles(category: category, page: 1); + final categoryArticles = + await publisher.categoryArticles(category: category, page: 1); expect(categoryArticles, isNotEmpty, reason: category); var article = categoryArticles.first; + print("<<<$article>>>"); expect(article, isNotNull); expect(article, isA()); expect(article.title, isNotEmpty); - if (article.publishedAt.key==0){ - print("date format issue ${article.publishedAt.key}"); + if (article.publishedAt.key == 0) { + print("date format issue<<<${article.publishedAt.key}>>>"); } var articleFull = await publisher.article(article); expect(articleFull, isNotNull); - if(articleFull.content.isEmpty) { - print("Content was empty\n$article"); + if (articleFull.content.isEmpty) { + print("Content was empty<<<\n$article>>>"); } } - } - } - static Future searchedArticlesTest(Publisher publisher, String query) async { + static Future searchedArticlesTest( + Publisher publisher, String query) async { if (publisher.hasSearchSupport) { final searchArticles = - await publisher.searchedArticles(searchQuery: query, page: 1); + await publisher.searchedArticles(searchQuery: query, page: 1); expect(searchArticles, isNotEmpty); var article = searchArticles.first; + print("<<<$article>>>"); expect(article, isA()); expect(article.title, isNotEmpty); - expect(article.publishedAt.key, isNot(0), reason: article.publishedAt.value); + expect(article.publishedAt.key, isNot(0), + reason: article.publishedAt.value); var articleFull = await publisher.article(article); expect(articleFull, isNotNull); expect(articleFull.content, isNotEmpty); } } -} \ No newline at end of file +} diff --git a/test/extractor/general/national/india/thequint_test.dart b/test/extractor/general/national/india/thequint_test.dart index 83e8919..adf656e 100644 --- a/test/extractor/general/national/india/thequint_test.dart +++ b/test/extractor/general/national/india/thequint_test.dart @@ -6,7 +6,7 @@ import '../../../common.dart'; void main() { Publisher publisher = TheQuint(); - + test('Extract Categories Test', () async { await ExtractorTest.categoriesTest(publisher); }); @@ -19,4 +19,3 @@ void main() { await ExtractorTest.searchedArticlesTest(publisher, 'politics'); }); } - diff --git a/test/extractor/general/national/india/thewire_test.dart b/test/extractor/general/national/india/thewire_test.dart index e8c1ae6..2c7cd5d 100644 --- a/test/extractor/general/national/india/thewire_test.dart +++ b/test/extractor/general/national/india/thewire_test.dart @@ -6,7 +6,7 @@ import '../../../common.dart'; void main() { Publisher publisher = TheWire(); - + test('Extract Categories Test', () async { await ExtractorTest.categoriesTest(publisher); }); @@ -19,4 +19,3 @@ void main() { await ExtractorTest.searchedArticlesTest(publisher, 'world'); }); } - diff --git a/test/extractor/general/world/theguardian_test.dart b/test/extractor/general/world/theguardian_test.dart index 2e3a76b..14e8b44 100644 --- a/test/extractor/general/world/theguardian_test.dart +++ b/test/extractor/general/world/theguardian_test.dart @@ -1,5 +1,4 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:raven/extractor/general/world/reuters.dart'; import 'package:raven/extractor/general/world/theguardian.dart'; import 'package:raven/model/publisher.dart'; diff --git a/test/extractor/technology/bleepingcomputer_test.dart b/test/extractor/technology/bleepingcomputer_test.dart index 271c8f8..a35ed4b 100644 --- a/test/extractor/technology/bleepingcomputer_test.dart +++ b/test/extractor/technology/bleepingcomputer_test.dart @@ -7,9 +7,7 @@ import '../common.dart'; void main() { Publisher publisher = BleepingComputer(); - test('Extract Categories Test', () async { - - }); + test('Extract Categories Test', () async {}); test('Category Articles Test', () async { await ExtractorTest.categoryArticlesTest(publisher, category: '');