diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index b1eb334..fa0fd0d 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -564,5 +564,6 @@ "newsReadingProviderSwap": "Swap", "newsReadingFromReader": "You're reading from HyperNet.Reader", "newsReadingFromOriginal": "You're reading the original article", - "newsDisclaimer": "This article is fetched from the Internet, we do not guarantee its authenticity, please judge for yourself. All content in this article belongs to the original author." + "newsDisclaimer": "This article is fetched from the Internet, we do not guarantee its authenticity, please judge for yourself. All content in this article belongs to the original author.", + "newsToday": "Today's News" } diff --git a/assets/translations/zh-CN.json b/assets/translations/zh-CN.json index 1fe8e4b..054209b 100644 --- a/assets/translations/zh-CN.json +++ b/assets/translations/zh-CN.json @@ -562,5 +562,6 @@ "newsReadingProviderSwap": "切换", "newsReadingFromReader": "你正在从 HyperNet.Reader 阅读文章", "newsReadingFromOriginal": "你正在阅读原始文章", - "newsDisclaimer": "本文由 HyperNet.Reader 从互联网上获取,我们不担保其内容的真实性,请自行判断。本文章的所有内容版权归原作者所有。" + "newsDisclaimer": "本文由 HyperNet.Reader 从互联网上获取,我们不担保其内容的真实性,请自行判断。本文章的所有内容版权归原作者所有。", + "newsToday": "快讯" } diff --git a/assets/translations/zh-HK.json b/assets/translations/zh-HK.json index 29177f2..068edd0 100644 --- a/assets/translations/zh-HK.json +++ b/assets/translations/zh-HK.json @@ -562,5 +562,6 @@ "newsReadingProviderSwap": "切換", "newsReadingFromReader": "你正在從 HyperNet.Reader 閲讀文章", "newsReadingFromOriginal": "你正在閲讀原始文章", - "newsDisclaimer": "本文由 HyperNet.Reader 從互聯網上獲取,我們不擔保其內容的真實性,請自行判斷。本文章的所有內容版權歸原作者所有。" + "newsDisclaimer": "本文由 HyperNet.Reader 從互聯網上獲取,我們不擔保其內容的真實性,請自行判斷。本文章的所有內容版權歸原作者所有。", + "newsToday": "快訊" } diff --git a/assets/translations/zh-TW.json b/assets/translations/zh-TW.json index f47c840..3da9a84 100644 --- a/assets/translations/zh-TW.json +++ b/assets/translations/zh-TW.json @@ -562,5 +562,6 @@ "newsReadingProviderSwap": "切換", "newsReadingFromReader": "你正在從 HyperNet.Reader 閱讀文章", "newsReadingFromOriginal": "你正在閱讀原始文章", - "newsDisclaimer": "本文由 HyperNet.Reader 從互聯網上獲取,我們不擔保其內容的真實性,請自行判斷。本文章的所有內容版權歸原作者所有。" + "newsDisclaimer": "本文由 HyperNet.Reader 從互聯網上獲取,我們不擔保其內容的真實性,請自行判斷。本文章的所有內容版權歸原作者所有。", + "newsToday": "快訊" } diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 841d768..d6a549f 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -9,6 +9,7 @@ import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:gap/gap.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:html/parser.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:provider/provider.dart'; import 'package:relative_time/relative_time.dart'; @@ -22,6 +23,7 @@ import 'package:surface/providers/special_day.dart'; import 'package:surface/providers/userinfo.dart'; import 'package:surface/providers/widget.dart'; import 'package:surface/types/check_in.dart'; +import 'package:surface/types/news.dart'; import 'package:surface/types/post.dart'; import 'package:surface/widgets/app_bar_leading.dart'; import 'package:surface/widgets/dialog.dart'; @@ -52,9 +54,13 @@ class _HomeScreenState extends State { static const List kCards = [ HomeScreenDashEntry( name: 'dashEntryRecommendation', - cols: 2, - rows: 2, child: _HomeDashRecommendationPostWidget(), + cols: 2, + ), + HomeScreenDashEntry( + name: 'dashEntryTodayNews', + child: _HomeDashTodayNews(), + cols: 2, ), HomeScreenDashEntry( name: 'dashEntryCheckIn', @@ -230,6 +236,107 @@ class _HomeDashSpecialDayWidgetState extends State<_HomeDashSpecialDayWidget> { } } +class _HomeDashTodayNews extends StatefulWidget { + const _HomeDashTodayNews(); + + @override + State<_HomeDashTodayNews> createState() => _HomeDashTodayNewsState(); +} + +class _HomeDashTodayNewsState extends State<_HomeDashTodayNews> { + SnNewsArticle? _article; + + Future _fetchArticle() async { + try { + final sn = context.read(); + final resp = await sn.client.get('/cgi/re/news/today'); + _article = SnNewsArticle.fromJson(resp.data['data']); + } catch (err) { + if (!mounted) return; + context.showErrorDialog(err); + rethrow; + } finally { + setState(() {}); + } + } + + @override + initState() { + super.initState(); + _fetchArticle(); + } + + @override + Widget build(BuildContext context) { + return Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + const Icon(Symbols.newspaper), + const Gap(8), + Text( + 'newsToday', + style: Theme.of(context).textTheme.titleLarge, + ).tr() + ], + ).padding(horizontal: 18, top: 12, bottom: 8), + if (_article != null) + Expanded( + child: InkWell( + borderRadius: BorderRadius.all(Radius.circular(8)), + child: Column( + spacing: 4, + children: [ + Text( + _article!.title, + style: Theme.of(context).textTheme.titleMedium!.copyWith(fontSize: 18), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + Text( + parse(_article!.description).children.map((e) => e.text.trim()).join(), + maxLines: 3, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.bodyMedium, + ), + Builder( + builder: (context) { + final date = _article!.publishedAt ?? _article!.createdAt; + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + spacing: 2, + children: [ + Text(DateFormat().format(date)).textStyle(Theme.of(context).textTheme.bodySmall!), + Text(' · ').textStyle(Theme.of(context).textTheme.bodySmall!).bold(), + Text(RelativeTime(context).format(date)).textStyle(Theme.of(context).textTheme.bodySmall!), + ], + ).opacity(0.75); + } + ), + ], + ).padding(horizontal: 16), + onTap: () { + GoRouter.of(context).pushNamed( + 'newsDetail', + pathParameters: {'hash': _article!.hash}, + ); + }, + ), + ) + else + Expanded( + child: Center( + child: CircularProgressIndicator(), + ), + ) + ], + ), + ); + } +} + class _HomeDashCheckInWidget extends StatefulWidget { const _HomeDashCheckInWidget();