From d184738eff723d363c59600a0473abf80a85a735 Mon Sep 17 00:00:00 2001 From: AlaaElattar Date: Wed, 9 Oct 2024 17:29:58 +0300 Subject: [PATCH 1/4] Add news screen from the xlm endpoint && add endpoint in flagsmith server --- app/lib/app_config.dart | 1 + app/lib/apps/news/news.dart | 8 +- app/lib/apps/news/news_screen.dart | 251 +++++++++++++++++++++++++++++ app/lib/helpers/flags.dart | 2 + app/lib/helpers/globals.dart | 1 + app/pubspec.lock | 244 +++++++++++++++++++++++++++- app/pubspec.yaml | 3 + 7 files changed, 504 insertions(+), 6 deletions(-) create mode 100644 app/lib/apps/news/news_screen.dart diff --git a/app/lib/app_config.dart b/app/lib/app_config.dart index eae04122e..e7c14fc61 100644 --- a/app/lib/app_config.dart +++ b/app/lib/app_config.dart @@ -221,4 +221,5 @@ void setFallbackConfigs() { Globals().relayUrl = ''; Globals().termsAndConditionsUrl = ''; Globals().spendingLimit = 0; + Globals().newsUrl = ''; } diff --git a/app/lib/apps/news/news.dart b/app/lib/apps/news/news.dart index 33437a6e8..158dba4df 100644 --- a/app/lib/apps/news/news.dart +++ b/app/lib/apps/news/news.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; import 'package:threebotlogin/app.dart'; -import 'package:threebotlogin/apps/news/news_widget.dart'; +import 'package:threebotlogin/apps/news/news_screen.dart'; import 'package:threebotlogin/events/events.dart'; -import 'package:threebotlogin/apps/news/news_events.dart'; +import 'package:threebotlogin/events/go_home_event.dart'; class News implements App { static final News _singleton = News._internal(); - static const NewsWidget _newsWidget = NewsWidget(); + static const NewsScreen _newsWidget = NewsScreen(); factory News() { return _singleton; @@ -34,6 +34,6 @@ class News implements App { @override void back() { - Events().emit(NewsBackEvent()); + Events().emit(GoHomeEvent()); } } diff --git a/app/lib/apps/news/news_screen.dart b/app/lib/apps/news/news_screen.dart new file mode 100644 index 000000000..dd4827453 --- /dev/null +++ b/app/lib/apps/news/news_screen.dart @@ -0,0 +1,251 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; +import 'package:http/http.dart' as http; +import 'package:threebotlogin/helpers/globals.dart'; +import 'package:threebotlogin/widgets/layout_drawer.dart'; +import 'package:xml2json/xml2json.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:timeago/timeago.dart' as timeago; + +class NewsScreen extends StatefulWidget { + const NewsScreen({Key? key}) : super(key: key); + + @override + State createState() => _NewsScreenState(); +} + +class _NewsScreenState extends State { + final Xml2Json xml2json = Xml2Json(); + List topStories = []; + bool isLoading = false; + bool isInitialLoading = true; + int articlesPerPage = 5; + int currentPage = 0; + final ScrollController _scrollController = ScrollController(); + final newsUrl = Globals().newsUrl; + + + Future getArticles() async { + setState(() { + isLoading = true; + if (currentPage == 0) { + isInitialLoading = true; + } + }); + + final url = Uri.parse(newsUrl); + final response = await http.get(url); + + xml2json.parse(response.body); + + var jsondata = xml2json.toGData(); + var data = json.decode(jsondata); + + var allEntries = data['feed']['entry'] ?? []; + + setState(() { + topStories.addAll(allEntries + .skip(currentPage * articlesPerPage) + .take(articlesPerPage) + .toList()); + currentPage++; + isLoading = false; + if (currentPage > 0) { + isInitialLoading = false; + } + }); + } + + @override + void initState() { + super.initState(); + getArticles(); + _scrollController.addListener(() { + if (_scrollController.position.pixels == + _scrollController.position.maxScrollExtent) { + getArticles(); + } + }); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return LayoutDrawer( + titleText: 'News', + content: Column( + children: [ + Expanded( + child: ListView.builder( + controller: _scrollController, + itemCount: topStories.length + (isLoading ? 1 : 0), + itemBuilder: (context, index) { + if (index == topStories.length) { + return const Padding( + padding: EdgeInsets.all(8), + child: Center(child: CircularProgressIndicator()), + ); + } + var entry = topStories[index]; + + var title = entry['title']?['\$t'] ?? 'No Title'; + var content = entry['content']?['\$t'] ?? 'No Content'; + var link = entry['link'] is List + ? entry['link'].first['href'] + : entry['link']['href']; + + var publishedDateStr = entry['published']?['\$t'] ?? ''; + DateTime publishedDate; + try { + publishedDate = DateTime.parse(publishedDateStr); + } catch (e) { + publishedDate = DateTime.now(); + } + + String formattedDate = timeago.format(publishedDate); + + content = cleanHtmlContent(content); + + return Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 4.0), + child: Card( + color: Theme.of(context).colorScheme.background, + elevation: 4.0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12)), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Image.asset( + 'assets/tft_icon.png', + height: 20, + width: 20, + ), + const SizedBox(width: 2), + RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'THREEFOLD - ', + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith( + color: Theme.of(context) + .colorScheme + .onBackground, + )), + TextSpan( + text: formattedDate, + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith( + color: Theme.of(context) + .colorScheme + .onBackground, + )), + ], + ), + ), + ], + ), + const SizedBox( + height: 3, + ), + Text( + title, + style: Theme.of(context) + .textTheme + .titleLarge! + .copyWith( + fontWeight: FontWeight.bold, + color: Theme.of(context) + .colorScheme + .onBackground, + ), + ), + const SizedBox(height: 5), + HtmlWidget( + content.length > 200 + ? '${content.substring(0, 200)}...' + : content, + textStyle: TextStyle( + color: Theme.of(context).colorScheme.onBackground, + ), + onTapUrl: (url) { + if (url.isNotEmpty) { + _launchURL(url); + return true; + } + return false; + }, + ), + const SizedBox(height: 4), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () async { + _launchURL(link); + }, + style: TextButton.styleFrom( + backgroundColor: Colors.transparent, + ), + child: Text( + 'Read more', + style: Theme.of(context) + .textTheme + .bodyLarge! + .copyWith( + color: Theme.of(context) + .colorScheme + .primary, + ), + ), + ), + ], + ), + ], + ), + ), + ), + ); + }, + ), + ), + if (isLoading && !isInitialLoading) + const Center( + child: Padding( + padding: EdgeInsets.all(8.0), + child: CircularProgressIndicator(), + ), + ), + ], + ), + ); + } + + void _launchURL(String url) async { + if (await canLaunch(url)) { + await launch(url); + } else { + throw 'Could not launch $url'; + } + } + + String cleanHtmlContent(String content) { + return content.replaceAll(r'\\n', ''); + } +} diff --git a/app/lib/helpers/flags.dart b/app/lib/helpers/flags.dart index 54f1ed1e2..6b5f36c86 100644 --- a/app/lib/helpers/flags.dart +++ b/app/lib/helpers/flags.dart @@ -72,6 +72,8 @@ class Flags { (await Flags().getFlagValueByFeatureName('terms-conditions-url'))!; Globals().spendingLimit = int.parse( (await Flags().getFlagValueByFeatureName('spending-limit')).toString()); + Globals().newsUrl = + (await Flags().getFlagValueByFeatureName('news-url'))!; } Future hasFlagValueByFeatureName(String name) async { diff --git a/app/lib/helpers/globals.dart b/app/lib/helpers/globals.dart index 0921a5bca..cd8598684 100644 --- a/app/lib/helpers/globals.dart +++ b/app/lib/helpers/globals.dart @@ -59,6 +59,7 @@ class Globals { String activationUrl = ''; String relayUrl = ''; String termsAndConditionsUrl = ''; + String newsUrl = ''; bool isCacheClearedWallet = false; bool isCacheClearedFarmer = false; diff --git a/app/pubspec.lock b/app/pubspec.lock index 18ea86fb8..5267be3f2 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -57,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + audio_session: + dependency: transitive + description: + name: audio_session + sha256: "343e83bc7809fbda2591a49e525d6b63213ade10c76f15813be9aed6657b3261" + url: "https://pub.dev" + source: hosted + version: "0.1.21" base_x: dependency: transitive description: @@ -153,6 +161,30 @@ packages: url: "https://pub.dev" source: hosted version: "8.9.2" + cached_network_image: + dependency: transitive + description: + name: cached_network_image + sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f" + url: "https://pub.dev" + source: hosted + version: "3.3.1" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "205d6a9f1862de34b93184f22b9d2d94586b2f05c581d546695e3d8f6a805cd7" + url: "https://pub.dev" + source: hosted + version: "1.2.0" characters: dependency: transitive description: @@ -169,6 +201,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + chewie: + dependency: transitive + description: + name: chewie + sha256: "8bc4ac4cf3f316e50a25958c0f5eb9bb12cf7e8308bb1d74a43b230da2cfc144" + url: "https://pub.dev" + source: hosted + version: "1.7.5" clock: dependency: transitive description: @@ -229,10 +269,10 @@ packages: dependency: transitive description: name: csslib - sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "0.17.3" cupertino_icons: dependency: "direct main" description: @@ -249,6 +289,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.6" + dbus: + dependency: transitive + description: + name: dbus + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" + url: "https://pub.dev" + source: hosted + version: "0.7.10" decimal: dependency: transitive description: @@ -374,6 +422,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + url: "https://pub.dev" + source: hosted + version: "3.3.1" flutter_curve25519: dependency: transitive description: @@ -441,6 +497,22 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_widget_from_html: + dependency: "direct main" + description: + name: flutter_widget_from_html + sha256: "9e2a6201c4d2eb910b6b3ebb2a9f5c490fc61c9a1aa35eafdde38f0fc659cf4c" + url: "https://pub.dev" + source: hosted + version: "0.15.2" + flutter_widget_from_html_core: + dependency: transitive + description: + name: flutter_widget_from_html_core + sha256: b1048fd119a14762e2361bd057da608148a895477846d6149109b2151d2f7abf + url: "https://pub.dev" + source: hosted + version: "0.15.2" freezed_annotation: dependency: transitive description: @@ -457,6 +529,54 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + fwfh_cached_network_image: + dependency: transitive + description: + name: fwfh_cached_network_image + sha256: "8e44226801bfba27930673953afce8af44da7e92573be93f60385d9865a089dd" + url: "https://pub.dev" + source: hosted + version: "0.14.3" + fwfh_chewie: + dependency: transitive + description: + name: fwfh_chewie + sha256: "37bde9cedfb6dc5546176f7f0c56af1e814966cb33ec58f16c9565ed93ccb704" + url: "https://pub.dev" + source: hosted + version: "0.14.8" + fwfh_just_audio: + dependency: transitive + description: + name: fwfh_just_audio + sha256: "38dc2c55803bd3cef33042c473e0c40b891ad4548078424641a32032f6a1245f" + url: "https://pub.dev" + source: hosted + version: "0.15.2" + fwfh_svg: + dependency: transitive + description: + name: fwfh_svg + sha256: "550b1014d12b5528d8bdb6e3b44b58721f3fb1f65d7a852d1623a817008bdfc4" + url: "https://pub.dev" + source: hosted + version: "0.8.3" + fwfh_url_launcher: + dependency: transitive + description: + name: fwfh_url_launcher + sha256: b9f5d55a5ae2c2c07243ba33f7ba49ac9544bdb2f4c16d8139df9ccbebe3449c + url: "https://pub.dev" + source: hosted + version: "0.9.1" + fwfh_webview: + dependency: transitive + description: + name: fwfh_webview + sha256: f67890bc0d6278da98bd197469ae9511c859f7db327e92299fe0ea0cf46c4057 + url: "https://pub.dev" + source: hosted + version: "0.15.2" glob: dependency: transitive description: @@ -594,6 +714,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.4+9" + just_audio: + dependency: transitive + description: + name: just_audio + sha256: b41646a8241688f1d99c2e69c4da2bb26aa4b3a99795f6ff205c2a165e033fda + url: "https://pub.dev" + source: hosted + version: "0.9.41" + just_audio_platform_interface: + dependency: transitive + description: + name: just_audio_platform_interface + sha256: "0243828cce503c8366cc2090cefb2b3c871aa8ed2f520670d76fd47aa1ab2790" + url: "https://pub.dev" + source: hosted + version: "4.3.0" + just_audio_web: + dependency: transitive + description: + name: just_audio_web + sha256: "0edb481ad4aa1ff38f8c40f1a3576013c3420bf6669b686fe661627d49bc606c" + url: "https://pub.dev" + source: hosted + version: "0.4.11" lints: dependency: transitive description: @@ -682,6 +826,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" open_filex: dependency: "direct main" description: @@ -1232,6 +1384,22 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 + url: "https://pub.dev" + source: hosted + version: "2.3.2" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5" + url: "https://pub.dev" + source: hosted + version: "2.5.3" sr25519: dependency: transitive description: @@ -1354,6 +1522,14 @@ packages: url: "https://github.com/codescalers/tfgrid-sdk-dart" source: git version: "0.1.0" + timeago: + dependency: "direct main" + description: + name: timeago + sha256: "054cedf68706bb142839ba0ae6b135f6b68039f0b8301cbe8784ae653d5ff8de" + url: "https://pub.dev" + source: hosted + version: "3.7.0" timing: dependency: transitive description: @@ -1554,6 +1730,62 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + video_player: + dependency: transitive + description: + name: video_player + sha256: e30df0d226c4ef82e2c150ebf6834b3522cf3f654d8e2f9419d376cdc071425d + url: "https://pub.dev" + source: hosted + version: "2.9.1" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: "134e1ad410d67e18a19486ed9512c72dfc6d8ffb284d0e8f2e99e903d1ba8fa3" + url: "https://pub.dev" + source: hosted + version: "2.4.14" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: d1e9a824f2b324000dc8fb2dcb2a3285b6c1c7c487521c63306cc5b394f68a7c + url: "https://pub.dev" + source: hosted + version: "2.6.1" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + sha256: "236454725fafcacf98f0f39af0d7c7ab2ce84762e3b63f2cbb3ef9a7e0550bc6" + url: "https://pub.dev" + source: hosted + version: "6.2.2" + video_player_web: + dependency: transitive + description: + name: video_player_web + sha256: "34beb3a07d4331a24f7e7b2f75b8e2b103289038e07e65529699a671b6a6e2cb" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + wakelock_plus: + dependency: transitive + description: + name: wakelock_plus + sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d + url: "https://pub.dev" + source: hosted + version: "1.1.4" + wakelock_plus_platform_interface: + dependency: transitive + description: + name: wakelock_plus_platform_interface + sha256: "40fabed5da06caff0796dc638e1f07ee395fb18801fbff3255a2372db2d80385" + url: "https://pub.dev" + source: hosted + version: "1.1.0" watcher: dependency: transitive description: @@ -1642,6 +1874,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.3.0" + xml2json: + dependency: "direct main" + description: + name: xml2json + sha256: "52b7c8d350fdce09545b058982c26689ee89f1eb188cc9910d585665bfe27bc0" + url: "https://pub.dev" + source: hosted + version: "6.2.3" yaml: dependency: transitive description: diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 8ca35dbbd..2b31c896f 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -66,6 +66,9 @@ dependencies: screen_brightness: ^1.0.1 validators: ^3.0.0 lottie: ^3.1.2 + xml2json: ^6.2.3 + timeago: ^3.7.0 + flutter_widget_from_html: ^0.15.2 dev_dependencies: flutter_test: From c219fb8a0aabbaca48780c11a5a12a3e1c19f085 Mon Sep 17 00:00:00 2001 From: AlaaElattar Date: Wed, 9 Oct 2024 17:41:09 +0300 Subject: [PATCH 2/4] use T&C url from flagsmith server --- app/lib/screens/wizard/web_view.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/lib/screens/wizard/web_view.dart b/app/lib/screens/wizard/web_view.dart index 1815848d2..53066de81 100644 --- a/app/lib/screens/wizard/web_view.dart +++ b/app/lib/screens/wizard/web_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:threebotlogin/helpers/globals.dart'; import 'package:webview_flutter/webview_flutter.dart'; class WebView extends StatefulWidget { @@ -11,6 +12,7 @@ class WebView extends StatefulWidget { class _WebViewState extends State { bool isLoading = true; late WebViewController controller; + final termsAndConditionsUrl = Globals().termsAndConditionsUrl; @override void dispose() { @@ -34,7 +36,7 @@ class _WebViewState extends State { }, ), ) - ..loadRequest(Uri.parse('https://library.threefold.me/info/legal/')); + ..loadRequest(Uri.parse(termsAndConditionsUrl)); } @override From 111cbcb63a838846b267c1162d463038bb2cb3a0 Mon Sep 17 00:00:00 2001 From: AlaaElattar Date: Fri, 11 Oct 2024 15:13:24 +0300 Subject: [PATCH 3/4] handle pr comments --- app/lib/apps/news/news_screen.dart | 91 +++++++++++++++-------- app/pubspec.lock | 112 ++++++++++++++++++++++++++--- 2 files changed, 163 insertions(+), 40 deletions(-) diff --git a/app/lib/apps/news/news_screen.dart b/app/lib/apps/news/news_screen.dart index dd4827453..d6392e861 100644 --- a/app/lib/apps/news/news_screen.dart +++ b/app/lib/apps/news/news_screen.dart @@ -9,7 +9,7 @@ import 'package:url_launcher/url_launcher.dart'; import 'package:timeago/timeago.dart' as timeago; class NewsScreen extends StatefulWidget { - const NewsScreen({Key? key}) : super(key: key); + const NewsScreen({super.key}); @override State createState() => _NewsScreenState(); @@ -17,7 +17,8 @@ class NewsScreen extends StatefulWidget { class _NewsScreenState extends State { final Xml2Json xml2json = Xml2Json(); - List topStories = []; + List allArticles = []; + List visibleArticles = []; bool isLoading = false; bool isInitialLoading = true; int articlesPerPage = 5; @@ -25,7 +26,6 @@ class _NewsScreenState extends State { final ScrollController _scrollController = ScrollController(); final newsUrl = Globals().newsUrl; - Future getArticles() async { setState(() { isLoading = true; @@ -45,11 +45,9 @@ class _NewsScreenState extends State { var allEntries = data['feed']['entry'] ?? []; setState(() { - topStories.addAll(allEntries - .skip(currentPage * articlesPerPage) - .take(articlesPerPage) - .toList()); - currentPage++; + allArticles = allEntries; + loadMoreArticles(); + isLoading = false; if (currentPage > 0) { isInitialLoading = false; @@ -57,6 +55,22 @@ class _NewsScreenState extends State { }); } + void loadMoreArticles() { + final startIndex = currentPage * articlesPerPage; + final endIndex = startIndex + articlesPerPage; + + if (startIndex < allArticles.length) { + setState(() { + isLoading = true; + visibleArticles.addAll( + allArticles.sublist( + startIndex, endIndex.clamp(0, allArticles.length)), + ); + currentPage++; + }); + } + } + @override void initState() { super.initState(); @@ -64,7 +78,11 @@ class _NewsScreenState extends State { _scrollController.addListener(() { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { - getArticles(); + loadMoreArticles(); + } else { + setState(() { + isLoading = false; + }); } }); } @@ -84,15 +102,32 @@ class _NewsScreenState extends State { Expanded( child: ListView.builder( controller: _scrollController, - itemCount: topStories.length + (isLoading ? 1 : 0), + itemCount: visibleArticles.length + (isLoading ? 1 : 0), itemBuilder: (context, index) { - if (index == topStories.length) { - return const Padding( - padding: EdgeInsets.all(8), - child: Center(child: CircularProgressIndicator()), + if (index == visibleArticles.length && isInitialLoading) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only( + bottom: 4, + top: MediaQuery.of(context).size.height * 0.4), + child: const CircularProgressIndicator(), + ), + Text( + 'Loading Articles ...', + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ], ); } - var entry = topStories[index]; + var entry = visibleArticles[index]; var title = entry['title']?['\$t'] ?? 'No Title'; var content = entry['content']?['\$t'] ?? 'No Content'; @@ -103,7 +138,7 @@ class _NewsScreenState extends State { var publishedDateStr = entry['published']?['\$t'] ?? ''; DateTime publishedDate; try { - publishedDate = DateTime.parse(publishedDateStr); + publishedDate = DateTime.parse(publishedDateStr).toLocal(); } catch (e) { publishedDate = DateTime.now(); } @@ -116,12 +151,9 @@ class _NewsScreenState extends State { padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4.0), child: Card( - color: Theme.of(context).colorScheme.background, elevation: 4.0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12)), child: Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -129,6 +161,7 @@ class _NewsScreenState extends State { children: [ Image.asset( 'assets/tft_icon.png', + color: Theme.of(context).colorScheme.onSurface, height: 20, width: 20, ), @@ -144,7 +177,7 @@ class _NewsScreenState extends State { .copyWith( color: Theme.of(context) .colorScheme - .onBackground, + .onSurface, )), TextSpan( text: formattedDate, @@ -154,7 +187,7 @@ class _NewsScreenState extends State { .copyWith( color: Theme.of(context) .colorScheme - .onBackground, + .onSurface, )), ], ), @@ -171,9 +204,8 @@ class _NewsScreenState extends State { .titleLarge! .copyWith( fontWeight: FontWeight.bold, - color: Theme.of(context) - .colorScheme - .onBackground, + color: + Theme.of(context).colorScheme.onSurface, ), ), const SizedBox(height: 5), @@ -182,7 +214,7 @@ class _NewsScreenState extends State { ? '${content.substring(0, 200)}...' : content, textStyle: TextStyle( - color: Theme.of(context).colorScheme.onBackground, + color: Theme.of(context).colorScheme.onSurface, ), onTapUrl: (url) { if (url.isNotEmpty) { @@ -200,9 +232,6 @@ class _NewsScreenState extends State { onPressed: () async { _launchURL(link); }, - style: TextButton.styleFrom( - backgroundColor: Colors.transparent, - ), child: Text( 'Read more', style: Theme.of(context) @@ -238,8 +267,8 @@ class _NewsScreenState extends State { } void _launchURL(String url) async { - if (await canLaunch(url)) { - await launch(url); + if (await canLaunchUrl(Uri.parse(url))) { + await launchUrl(Uri.parse(url)); } else { throw 'Could not launch $url'; } diff --git a/app/pubspec.lock b/app/pubspec.lock index 1b04ed308..802876ee9 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -294,6 +294,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.7" + dbus: + dependency: transitive + description: + name: dbus + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" + url: "https://pub.dev" + source: hosted + version: "0.7.10" decimal: dependency: transitive description: @@ -601,9 +609,11 @@ packages: gridproxy_client: dependency: "direct main" description: - path: "../../../codescalers/tfgrid-sdk-dart/packages/gridproxy_client" - relative: true - source: path + path: "packages/gridproxy_client" + ref: tfchain_graphql + resolved-ref: bd83a0bb1778b78c1b0b3b6c34d93f2ca2b54d16 + url: "https://github.com/codescalers/tfgrid-sdk-dart" + source: git version: "1.0.0" hashlib: dependency: transitive @@ -709,6 +719,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.4+9" + just_audio: + dependency: transitive + description: + name: just_audio + sha256: b41646a8241688f1d99c2e69c4da2bb26aa4b3a99795f6ff205c2a165e033fda + url: "https://pub.dev" + source: hosted + version: "0.9.41" + just_audio_platform_interface: + dependency: transitive + description: + name: just_audio_platform_interface + sha256: "0243828cce503c8366cc2090cefb2b3c871aa8ed2f520670d76fd47aa1ab2790" + url: "https://pub.dev" + source: hosted + version: "4.3.0" + just_audio_web: + dependency: transitive + description: + name: just_audio_web + sha256: "0edb481ad4aa1ff38f8c40f1a3576013c3420bf6669b686fe661627d49bc606c" + url: "https://pub.dev" + source: hosted + version: "0.4.11" leak_tracker: dependency: transitive description: @@ -1430,9 +1464,11 @@ packages: stellar_client: dependency: "direct main" description: - path: "../../../codescalers/tfgrid-sdk-dart/packages/stellar_client" - relative: true - source: path + path: "packages/stellar_client" + ref: tfchain_graphql + resolved-ref: bd83a0bb1778b78c1b0b3b6c34d93f2ca2b54d16 + url: "https://github.com/codescalers/tfgrid-sdk-dart" + source: git version: "0.1.0" stellar_flutter_sdk: dependency: transitive @@ -1517,9 +1553,11 @@ packages: tfchain_client: dependency: "direct main" description: - path: "../../../codescalers/tfgrid-sdk-dart/packages/tfchain_client" - relative: true - source: path + path: "packages/tfchain_client" + ref: tfchain_graphql + resolved-ref: bd83a0bb1778b78c1b0b3b6c34d93f2ca2b54d16 + url: "https://github.com/codescalers/tfgrid-sdk-dart" + source: git version: "0.1.0" timeago: dependency: "direct main" @@ -1729,6 +1767,46 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + video_player: + dependency: transitive + description: + name: video_player + sha256: "4a8c3492d734f7c39c2588a3206707a05ee80cef52e8c7f3b2078d430c84bc17" + url: "https://pub.dev" + source: hosted + version: "2.9.2" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: e343701aa890b74a863fa460f5c0e628127ed06a975d7d9af6b697133fb25bdf + url: "https://pub.dev" + source: hosted + version: "2.7.1" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: cd5ab8a8bc0eab65ab0cea40304097edc46da574c8c1ecdee96f28cd8ef3792f + url: "https://pub.dev" + source: hosted + version: "2.6.2" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + sha256: "229d7642ccd9f3dc4aba169609dd6b5f3f443bb4cc15b82f7785fcada5af9bbb" + url: "https://pub.dev" + source: hosted + version: "6.2.3" + video_player_web: + dependency: transitive + description: + name: video_player_web + sha256: "8e9cb7fe94e49490e67bbc15149691792b58a0ade31b32e3f3688d104a0e057b" + url: "https://pub.dev" + source: hosted + version: "2.2.0" vm_service: dependency: transitive description: @@ -1737,6 +1815,22 @@ packages: url: "https://pub.dev" source: hosted version: "14.2.1" + wakelock_plus: + dependency: transitive + description: + name: wakelock_plus + sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d + url: "https://pub.dev" + source: hosted + version: "1.1.4" + wakelock_plus_platform_interface: + dependency: transitive + description: + name: wakelock_plus_platform_interface + sha256: "422d1cdbb448079a8a62a5a770b69baa489f8f7ca21aef47800c726d404f9d16" + url: "https://pub.dev" + source: hosted + version: "1.2.1" watcher: dependency: transitive description: From c27c0a4b39493db2ab0f93b30a47d026d6241227 Mon Sep 17 00:00:00 2001 From: AlaaElattar Date: Sun, 13 Oct 2024 11:30:40 +0300 Subject: [PATCH 4/4] remove space in loading articles text --- app/lib/apps/news/news_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/apps/news/news_screen.dart b/app/lib/apps/news/news_screen.dart index d6392e861..706f9436d 100644 --- a/app/lib/apps/news/news_screen.dart +++ b/app/lib/apps/news/news_screen.dart @@ -116,7 +116,7 @@ class _NewsScreenState extends State { child: const CircularProgressIndicator(), ), Text( - 'Loading Articles ...', + 'Loading Articles...', style: Theme.of(context) .textTheme .titleMedium!