From 19934b1101c177b58c3987a50c839a87ce112fc7 Mon Sep 17 00:00:00 2001 From: Hillium Date: Fri, 21 Jul 2023 10:13:48 +0800 Subject: [PATCH] News: updated. --- assets/hackernews_icon.jpeg | Bin 0 -> 9412 bytes lib/components/news.dart | 531 +++++++++++++++++++++++++++++++++--- lib/main.dart | 5 +- pubspec.yaml | 3 + 4 files changed, 502 insertions(+), 37 deletions(-) create mode 100644 assets/hackernews_icon.jpeg diff --git a/assets/hackernews_icon.jpeg b/assets/hackernews_icon.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..4311bc7ac2de525b3f217ac5ae17ec2d8a9603bd GIT binary patch literal 9412 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 literal 0 HcmV?d00001 diff --git a/lib/components/news.dart b/lib/components/news.dart index 9830e4b..7ea2f2c 100644 --- a/lib/components/news.dart +++ b/lib/components/news.dart @@ -1,94 +1,553 @@ +import 'dart:io'; + +import 'package:dual_screen/dual_screen.dart'; +import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; +import 'package:moyubie/components/chat_room.dart'; +import 'package:webview_flutter/webview_flutter.dart'; +import 'package:url_launcher/url_launcher.dart'; enum _NewsSource { HackerNews } class _News { _NewsSource source; + int id; String title; String content; + String url; - _News(this.source, this.title, this.content); + _News(this.source, this.id, this.url, this.title, this.content); } class _TestData { static final hackerNews = [ _News( _NewsSource.HackerNews, - "Bookwyrm – the federated social network for reading books", - "126 points by susanthenerd"), + 36799548, + "https://anytype.io/?hn", + "Anytype – open-source, local-first, P2P Notion alternative", + "104 scores by TTTZ"), + _News( + _NewsSource.HackerNews, + 36799776, + "https://github.com/bartobri/no-more-secrets", + "No-more-secrets: recreate the decryption effect seen in the 1992 movie Sneakers", + "66 scores by tambourine_man"), + _News( + _NewsSource.HackerNews, + 36795173, + "https://www.dignitymemorial.com/obituaries/las-vegas-nv/kevin-mitnick-11371668", + "Kevin Mitnick has died", + "2937 scores by thirtyseven"), + _News( + _NewsSource.HackerNews, + 36800041, + "https://www.projectaria.com/datasets/adt/", + "Project Aria 'Digital Twin' Dataset by Meta", + "20 scores by socratic1"), + _News( + _NewsSource.HackerNews, + 36798593, + "https://github.com/docusealco/docuseal", + "Docuseal: Open-source DocuSign alternative. Create, fill, sign digital documents", + "161 scores by thunderbong"), + _News( + _NewsSource.HackerNews, + 36798774, + "https://github.com/Swordfish90/cool-retro-term", + "Cool Retro Terminal", + "86 scores by qazpot"), + _News( + _NewsSource.HackerNews, + 36800151, + "https://www.jefftk.com/p/accidentally-load-bearing", + "Accidentally Load Bearing", + "11 scores by jamessun"), + _News( + _NewsSource.HackerNews, + 36798157, + "https://developer.mozilla.org/en-US/play", + "MDN Playground", + "127 scores by weinzierl"), + _News( + _NewsSource.HackerNews, + 36799283, + "https://up.codes/careers", + "UpCodes (YC S17) is hiring a Growth Marketer to make construction efficient", + "1 scores by Old_Thrashbarg"), + _News( + _NewsSource.HackerNews, + 36798864, + "https://github.com/Fadi002/unshackle", + "Unshackle: A tool to bypass windows password logins", + "42 scores by AdvDebug"), + _News( + _NewsSource.HackerNews, + 36798842, + "https://www.pathsensitive.com/2018/02/the-practice-is-not-performance-why.html", + "Why project-based learning fails (2018)", + "33 scores by jger15"), + _News( + _NewsSource.HackerNews, + 36799628, + "https://giannirosato.com/blog/post/jpegli-xyb/", + "XYB JPEG: Perceptual Color Encoding Tested", + "15 scores by computerbuster"), + _News( + _NewsSource.HackerNews, + 36798997, + "https://projects.osmocom.org/projects/foss-ims-client/wiki/Wiki", + "Open Source IMS Client", + "16 scores by McDyver"), + _News( + _NewsSource.HackerNews, + 36799073, + "https://viterbischool.usc.edu/news/2023/07/teaching-robots-to-teach-other-robots/", + "AI That Teaches Other AI", + "13 scores by geox"), + _News( + _NewsSource.HackerNews, + 36778309, + "https://en.wikipedia.org/wiki/Glossary_of_Japanese_words_of_Portuguese_origin", + "Japanese words of Portuguese origin", + "181 scores by lermontov"), + _News( + _NewsSource.HackerNews, + 36798092, + "https://dolphin-emu.org/blog/2023/07/20/what-happened-to-dolphin-on-steam/", + "What Happened to Dolphin on Steam?", + "116 scores by panic"), + _News( + _NewsSource.HackerNews, + 36791936, + "https://daily.jstor.org/delts-dont-lie/", + "Delts Don’t Lie", + "48 scores by fnubbly"), + _News( + _NewsSource.HackerNews, + 36798051, + "https://chromium.googlesource.com/chromiumos/docs/+/HEAD/development_basics.md#programming-languages-and-style", + "ChromiumOS Developer Guide, Programming languages and style", + "48 scores by pjmlp"), + _News(_NewsSource.HackerNews, 36799221, "https://taylor.town/secret-sauce", + "Spoil Your Secret Sauce", "9 scores by surprisetalk"), + _News(_NewsSource.HackerNews, 36798826, "https://pdfdiffer.com/", + "Show HN: PDF Differ", "20 scores by m4rc1e"), + _News(_NewsSource.HackerNews, 36798854, "https://sive.rs/pnt", + "The past is not true", "85 scores by swah"), + _News( + _NewsSource.HackerNews, + 36790301, + "https://stanforddaily.com/2023/07/19/stanford-president-resigns-over-manipulated-research-will-retract-at-least-3-papers/", + "Stanford president resigns over manipulated research, will retract 3 papers", + "1339 scores by dralley"), + _News( + _NewsSource.HackerNews, + 36768334, + "https://github.com/InderdeepBajwa/gitid", + "Use multiple Git SSH identities on a single computer", + "43 scores by inderdeepbajwa"), + _News( + _NewsSource.HackerNews, + 36799235, + "https://www.bloomberg.com/news/articles/2023-07-19/wall-street-shrinks-ranks-by-21-000-amid-deals-trading-slump", + "Wall Street Shrinks Headcount by 21,000 as Dealmaking and Trading Slump", + "37 scores by haltingproblem"), + _News( + _NewsSource.HackerNews, + 36794756, + "https://www.youtube.com/watch?v=6-3BFXpBcjc", + "The Danger of Popcorn Polymer: Incident at the TPC Group Chemical Plant [video]", + "172 scores by oatmeal1"), + _News( + _NewsSource.HackerNews, + 36794430, + "https://www.infoq.com/news/2023/07/linkedin-protocol-buffers-restli/", + "LinkedIn adopts protocol buffers and reduces latency up to 60%", + "164 scores by ijidak"), + _News( + _NewsSource.HackerNews, + 36799700, + "https://www.theguardian.com/us-news/2023/jul/20/toxic-flame-retardants-human-breast-milk", + "Flame retardant found in US breast milk", + "12 scores by geox"), + _News( + _NewsSource.HackerNews, + 36798850, + "https://www.washingtonpost.com/wellness/2023/07/19/hearing-loss-hearing-aids-dementia-study/", + "Hearing aids may cut risk of cognitive decline by nearly half", + "48 scores by maxutility"), + _News( + _NewsSource.HackerNews, + 36799600, + "https://www.nytimes.com/2023/07/19/business/google-artificial-intelligence-news-articles.html", + "Google Tests A.I. Tool That Is Able to Write News Articles", + "12 scores by asnyder"), + _News( + _NewsSource.HackerNews, + 36771331, + "https://www.infoq.com/news/2023/07/yelp-corrupted-cassandra-rebuild/", + "Yelp rebuilds corrupted Cassandra cluster using its data streaming architecture", + "83 scores by rgancarz"), + _News( + _NewsSource.HackerNews, + 36800196, + "https://www.theregister.com/2023/07/20/cerebras_condor_galaxy_supercomputer/", + "Cerebras's Condor Galaxy AI supercomputer takes flight carrying 36 exaFLOPS", + "4 scores by rntn"), + _News( + _NewsSource.HackerNews, + 36799059, + "https://asia.nikkei.com/Business/Tech/Semiconductors/TSMC-delays-U.S.-chip-plant-start-to-2025-due-to-labor-shortages", + "TSMC delays U.S. chip plant start to 2025 due to labor shortages", + "66 scores by ironyman"), _News( _NewsSource.HackerNews, - "NeetoCal, a calendly alternative, is a commodity and is priced accordingly", - "64 points by jasim"), + 36797079, + "https://github.com/Maknee/minigpt4.cpp", + "Minigpt4 Inference on CPU", + "89 scores by maknee"), _News( _NewsSource.HackerNews, - "Advanced Python Mastery – A Course by David Beazley", - "74 points by a_bonobo"), - _News(_NewsSource.HackerNews, "Tachyons – A CSS Toolkit", - "12 points by impoppy"), + 36771114, + "https://www.oreilly.com/radar/teaching-programming-in-the-age-of-chatgpt/", + "Teaching Programming in the Age of ChatGPT", + "135 scores by headalgorithm"), _News( _NewsSource.HackerNews, - "Kangaroo tendons could rebuild human knees better, stronger", - "39 points by geox"), + 36780999, + "https://phys.org/news/2023-07-tidal-disruption-event-chinese-astronomers.html", + "New tidal disruption event discovered by Chinese astronomers", + "23 scores by wglb"), _News( _NewsSource.HackerNews, - "The global fight for critical minerals is costly and damaging", - "32 points by headalgorithm"), + 36796422, + "https://github.com/mbnuqw/sidebery", + "Sidebery – A Firefox extension for managing tabs and bookmarks in sidebar", + "146 scores by BafS"), _News( _NewsSource.HackerNews, - "Senators to Propose Ban on U.S. Lawmakers, Executive Branch Members Owning Stock", - "116 points by mfiguiere"), + 36797178, + "https://lists.freebsd.org/archives/freebsd-announce/2023-July/000076.html", + "In Memoriam: Hans Petter William Sirevåg Selasky", + "100 scores by stargrave"), _News( _NewsSource.HackerNews, - "ASUS agrees to manufacture and sell Intel’s NUC products", - "424 points by mepian"), - _News(_NewsSource.HackerNews, "Netscape and Sun announce JavaScript (1995)", - "222 points by damethos"), + 36798395, + "https://en.wikipedia.org/wiki/Vacuum_airship", + "Vacuum airship", + "61 scores by guerrilla"), _News( _NewsSource.HackerNews, - "Lazygit: Simple terminal UI for Git commands", - "135 points by thunderbong") + 36777096, + "https://bigthink.com/the-past/kunga-first-hybrid-animal/", + "Kunga: Ancient Mesopotamians created the world’s first hybrid animal", + "34 scores by diodorus"), + _News( + _NewsSource.HackerNews, + 36797231, + "https://arstechnica.com/science/2023/07/new-slow-repeating-radio-source-we-have-no-idea-what-it-is/", + "Something in space has been lighting up every 20 minutes since 1988", + "120 scores by Brajeshwar"), + _News( + _NewsSource.HackerNews, + 36782638, + "https://www.transportation.gov/pnt/what-radio-spectrum", + "What Is Radio Spectrum?", + "46 scores by ZunarJ5"), + _News( + _NewsSource.HackerNews, + 36800009, + "https://arstechnica.com/information-technology/2023/07/ars-on-aws-01/", + "Behind the scenes: How we host Ars Technica, part 1", + "4 scores by pseudolus"), + _News( + _NewsSource.HackerNews, + 36799461, + "https://shkspr.mobi/blog/2023/07/keeping-a-side-project-alive-with-t-shirts-and-cash/", + "Keeping a side project alive with t-shirts and cash", + "8 scores by edent"), + _News( + _NewsSource.HackerNews, + 36793022, + "https://www.sharbonline.com/fun-stuff/card-games/complex-hearts/", + "Complex Hearts", + "21 scores by pcwalton"), + _News( + _NewsSource.HackerNews, + 36782201, + "https://jazz-library.com/articles/comping/", + "Jazz Comping (2021)", + "111 scores by RickHull"), + _News( + _NewsSource.HackerNews, + 36798408, + "https://hothardware.com/news/intel-14thgen-core-k-cpu-spec-leak", + "Intel's 14th Gen Core K-Series CPU Specs Break Cover with Speeds Up to 6GHz", + "25 scores by rbanffy"), + _News( + _NewsSource.HackerNews, + 36796685, + "https://acl2023-retrieval-lm.github.io/", + "ACL 2023 Tutorial: Retrieval-Based Language Models and Applications", + "17 scores by TalktoCrystal"), + _News( + _NewsSource.HackerNews, + 36798496, + "https://blog.google/technology/safety-security/googles-ai-red-team-the-ethical-hackers-making-ai-safer/", + "Google Introduces AI Red Team", + "5 scores by bhattmayurshiv"), + _News( + _NewsSource.HackerNews, + 36798863, + "https://www.theguardian.com/technology/2023/jul/20/tiktok-is-the-most-popular-news-source-for-12-to-15-year-olds-says-ofcom", + "TikTok is the most popular news source for 12 to 15-year-olds", + "16 scores by firstSpeaker") ]; static const hackerNewsIcon = - ImageIcon(AssetImage("hackernews_icon.jpeg"), color: Colors.transparent); + // ImageIcon(AssetImage("hackernews_icon.jpeg"), color: Colors.transparent); + Icon(Icons.newspaper); + + static const simplePrompted = [ + _Recommend(36799548, + "Anytype是一个开源的、本地优先的、P2P的Notion替代品。它提供了类似Notion的功能,但是数据存储在本地,而不是云端。这样可以增加数据的安全性和隐私保护。对于关注数据安全和隐私的用户来说,Anytype是一个很好的选择。"), + _Recommend(36795173, + "Kevin Mitnick是一位著名的黑客,据称他已经去世了。Kevin Mitnick以他的黑客技术和社会工程学见长,并因此被FBI通缉。他的离世无疑对黑客界产生了一定的影响,所以对关注黑客技术和网络安全的用户来说,这是一个可能感兴趣的新闻。"), + _Recommend(36791434, + "Twenty.com是一个开源的CRM系统,它提供了一个集成的客户关系管理解决方案。对于需要管理客户关系的企业或个人来说,Twenty.com是一个很好的选择。它的开源性质还意味着用户可以根据自己的需求进行定制和扩展。"), + _Recommend(36790301, + "斯坦福大学校长因操纵研究数据的行为辞职,并将撤销其发表的三篇论文。这件事引发了一场关于研究诚信和学术道德的讨论。对于关注科研诚信和学术道德的用户来说,这是一个可能感兴趣的新闻。"), + _Recommend(36794430, + "LinkedIn采用了Google开源的协议缓冲区(Protocol Buffers),并将延迟降低了高达60%。这意味着用户可以更快地访问LinkedIn的服务。对于经常使用LinkedIn的用户来说,这是一个可能感兴趣的新闻。") + ]; + + static List<_Promoted> getPromoted() { + return simplePrompted.mapMany((e) { + _News? item = hackerNews.firstWhereOrNull((element) { + return element.id == e.id; + }); + if (item == null) { + return <_Promoted>[]; + } + return [_Promoted(item, e.reason)]; + }).toList(); + } +} + +class _Recommend { + final int id; + final String reason; + + const _Recommend(this.id, this.reason); +} + +class _Promoted { + _News news; + String reason; + + _Promoted(this.news, this.reason); } class NewsWindow extends StatefulWidget { - const NewsWindow({super.key}); + ChatRoomType ty; + + NewsWindow({super.key, required this.ty}); @override State createState() => _NewsWindowState(); } class _NewsWindowState extends State { + String? _openedLink; + String? _err; + List<_News> _news = _TestData.hackerNews.toList(); + List<_Promoted> _promoted_news = []; + + final WebViewController? _webc = + Platform.isAndroid || Platform.isIOS ? WebViewController() : null; + int _web_load_progress = 0; + + @override + void initState() { + _webc?.setNavigationDelegate(NavigationDelegate( + onProgress: (i) { + setState(() {_web_load_progress = i;}); + } + )); + super.initState(); + } + @override Widget build(BuildContext context) { + var panePriority = widget.ty == ChatRoomType.tablet + ? TwoPanePriority.both + : (_openedLink == null ? TwoPanePriority.start : TwoPanePriority.end); + IconButton? goBack = null; + if (panePriority == TwoPanePriority.end) { + goBack = IconButton( + icon: Icon(Icons.arrow_back), + onPressed: () { + setState(() { + _openedLink = null; + _err = null; + }); + _webc?.loadHtmlString(""); + }, + ); + } return Scaffold( - appBar: AppBar(title: const Text("News")), - body: ListView( - padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), - children: _TestData.hackerNews.map((e) => _NewsCard(e)).toList()), - ); + appBar: AppBar( + leading: goBack, + title: Text("News"), + actions: useInlineWebView && _openedLink != null + ? [ + IconButton( + onPressed: () => { + launchUrl( + Uri.parse( + _openedLink!, + ), + mode: LaunchMode.externalApplication) + }, + icon: Icon(Icons.open_in_browser)) + ] + : [], + ), + body: TwoPane( + paneProportion: 0.3, + startPane: EasyRefresh( + onRefresh: () => promoteNews(), + child: ListView( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), + children: [ + ..._promoted_news.map((e) => _PromotedCard(e)), + ..._news.map( + (e) => _NewsCard(e, on_enter: (news) => {setUrl(news.url)})) + ], + ), + ), + endPane: contentForWeb(), + panePriority: panePriority, + )); + } + + bool get useInlineWebView => _webc != null; + + Widget contentForWeb() { + if (useInlineWebView) { + return WebViewWidget(controller: _webc!); + } + if (_err != null) { + return Center( + child: Container( + color: Colors.red, + child: Text("Error: $_err", + style: TextStyle( + color: Colors.white, fontWeight: FontWeight.bold)))); + } + return Center(child: Text("The URL will be open at external browser.")); + } + + Future openUrl(String link) async { + var url = Uri.parse(link); + if (useInlineWebView) { + _webc!.setJavaScriptMode(JavaScriptMode.unrestricted); + await _webc!.loadRequest(url); + return; + } + if (!await launchUrl(url)) { + throw Exception("failed to launch the message"); + } + } + + setUrl(String link) async { + try { + openUrl(link); + setState(() { + _openedLink = link; + }); + } catch (e) { + setState(() { + _err = e.toString(); + }); + } + } + + promoteNews() async { + await Future.delayed(Duration(seconds: 1)); + const promotedList = _TestData.simplePrompted; + var promotedFull = []; + _news.removeWhere((element) { + var recommend = + promotedList.firstWhereOrNull((rec) => rec.id == element.id); + if (recommend != null) { + promotedFull.add(_Promoted(element, recommend.reason)); + } + return recommend != null; + }); + setState(() { + _promoted_news = [...promotedFull, ..._promoted_news]; + _news = _news; + }); } } class _NewsCard extends StatelessWidget { final _News _news; + final void Function(_News)? on_enter; - const _NewsCard(this._news); + const _NewsCard(this._news, {this.on_enter}); @override Widget build(BuildContext context) { return Card( clipBehavior: Clip.antiAlias, child: InkWell( - onTap: () => {}, - child: ListTile( - leading: _TestData.hackerNewsIcon, - title: Text(_news.title), - subtitle: Text(_news.content), - ), - )); + onTap: () => {}, + onTapUp: (details) => {on_enter?.call(_news)}, + child: ListTile( + leading: _TestData.hackerNewsIcon, + title: Text(_news.title), + subtitle: Text(_news.content), + ), + )); + } +} + +class _PromotedCard extends StatelessWidget { + final _Promoted _promoted; + + const _PromotedCard(this._promoted); + + @override + Widget build(BuildContext context) { + var th = Theme.of(context); + return Card( + clipBehavior: Clip.antiAlias, + color: th.primaryColor, + child: InkWell( + onTap: () => {}, + child: Container( + padding: EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0), + child: ListTile( + isThreeLine: true, + leading: Icon( + Icons.star, + color: Colors.white, + ), + title: Text( + _promoted.news.title, + style: TextStyle(color: Colors.white), + ), + subtitle: Text( + _promoted.reason, + style: TextStyle(color: Colors.white), + ), + )), + )); } } diff --git a/lib/main.dart b/lib/main.dart index 8b250f3..b421bb7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,6 +16,7 @@ import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:moyubie/configs/translations.dart'; import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:webview_flutter/webview_flutter.dart'; import 'dart:io' show Platform; import 'components/chat_room.dart'; @@ -105,12 +106,14 @@ class MyApp extends StatelessWidget { debugShowCheckedModeBanner: false, home: DefaultTabController( length: 3, + child: Scaffold( bottomNavigationBar: menu(), body: TabBarView( + physics: const NeverScrollableScrollPhysics(), children: [ Container(child: ChatRoom(restorationId: "chat_room", type: type)), - Container(child: const NewsWindow()), + Container(child: NewsWindow(ty: type)), Container(child: SettingPage()), ], ), diff --git a/pubspec.yaml b/pubspec.yaml index e2c9a0c..329e6c8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -55,6 +55,9 @@ dependencies: html: ^0.15.4 sqflite_common_ffi_web: any dual_screen: ^1.0.4 + webview_flutter: ^4.2.2 + url_launcher: ^6.1.12 + easy_refresh: ^3.3.2+1 dev_dependencies: flutter_test: