新增信息流 (接入 Anicat G佬 新闻组+)

This commit is contained in:
xkeyC 2023-11-28 23:08:34 +08:00
parent 4f6623a4cd
commit 4d7f73ffc4
5 changed files with 214 additions and 105 deletions

31
lib/api/rss.dart Normal file
View File

@ -0,0 +1,31 @@
import 'dart:io';
import 'package:dart_rss/dart_rss.dart';
import 'package:dio/dio.dart';
import 'package:starcitizen_doctor/common/conf.dart';
class RSSApi {
static final _dio = Dio(BaseOptions(
connectTimeout: const Duration(seconds: 10),
responseType: ResponseType.plain));
static Future<List<RssItem>> getRssVideo() async {
final r = await _dio.get(AppConf.rssVideoUrl);
final f = RssFeed.parse(r.data);
return f.items.sublist(0, 8);
}
static Future<List<RssItem>> getRssText() async {
final r1 = await _dio.get(AppConf.rssTextUrl1);
final r1f = RssFeed.parse(r1.data);
final r2 = await _dio.get(AppConf.rssTextUrl2);
final r2f = RssFeed.parse(r2.data);
final items = r1f.items..addAll(r2f.items);
items.sort((a, b) {
final aDate = HttpDate.parse(a.pubDate ?? "").millisecondsSinceEpoch;
final bDate = HttpDate.parse(b.pubDate ?? "").millisecondsSinceEpoch;
return bDate - aDate;
});
return items;
}
}

View File

@ -34,6 +34,14 @@ class AppConf {
static const String xkeycApiUrl = "https://sctoolbox.xkeyc.com"; static const String xkeycApiUrl = "https://sctoolbox.xkeyc.com";
static const rssVideoUrl =
"https://rss.42kit.com/bilibili/user/channel/27976358/290653";
static const rssTextUrl1 =
"https://rss.42kit.com/bilibili/user/article/40102960";
static const rssTextUrl2 =
"https://rss.42kit.com/baidu/tieba/user/%E7%81%AC%E7%81%ACG%E7%81%AC%E7%81%AC&";
static late final String applicationSupportDir; static late final String applicationSupportDir;
static AppVersionData? networkVersionData; static AppVersionData? networkVersionData;
@ -90,8 +98,8 @@ class AppConf {
/// init windows /// init windows
await windowManager.ensureInitialized(); await windowManager.ensureInitialized();
windowManager.waitUntilReadyToShow().then((_) async { windowManager.waitUntilReadyToShow().then((_) async {
await windowManager.setSize(const Size(1280, 820)); await windowManager.setSize(const Size(1300, 830));
await windowManager.setMinimumSize(const Size(1280, 820)); await windowManager.setMinimumSize(const Size(1300, 830));
await windowManager.center(animate: true); await windowManager.center(animate: true);
await windowManager.setSkipTaskbar(false); await windowManager.setSkipTaskbar(false);
await windowManager.setTitleBarStyle( await windowManager.setTitleBarStyle(

View File

@ -1,11 +1,11 @@
import 'package:card_swiper/card_swiper.dart'; import 'package:card_swiper/card_swiper.dart';
import 'package:extended_image/extended_image.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_tilt/flutter_tilt.dart'; import 'package:flutter_tilt/flutter_tilt.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:starcitizen_doctor/api/analytics.dart'; import 'package:starcitizen_doctor/api/analytics.dart';
import 'package:starcitizen_doctor/base/ui.dart'; import 'package:starcitizen_doctor/base/ui.dart';
import 'package:starcitizen_doctor/widgets/cache_image.dart';
import 'package:starcitizen_doctor/widgets/countdown_time_text.dart'; import 'package:starcitizen_doctor/widgets/countdown_time_text.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
@ -18,6 +18,7 @@ class HomeUI extends BaseUI<HomeUIModel> {
children: [ children: [
Center( Center(
child: SingleChildScrollView( child: SingleChildScrollView(
padding: EdgeInsets.zero,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -36,7 +37,7 @@ class HomeUI extends BaseUI<HomeUIModel> {
? null ? null
: () => model.closePlacard(), : () => model.closePlacard(),
), ),
const SizedBox(height: 12), const SizedBox(height: 6),
], ],
if (!model.isChecking && if (!model.isChecking &&
model.checkResult != null && model.checkResult != null &&
@ -71,7 +72,7 @@ class HomeUI extends BaseUI<HomeUIModel> {
} }
List<Widget> makeIndex(BuildContext context, HomeUIModel model) { List<Widget> makeIndex(BuildContext context, HomeUIModel model) {
final width = MediaQuery.of(context).size.width * .21; const double width = 280;
return [ return [
Stack( Stack(
children: [ children: [
@ -80,10 +81,17 @@ class HomeUI extends BaseUI<HomeUIModel> {
child: SizedBox( child: SizedBox(
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
child: Center( child: Center(
child: Image.asset( child: Column(
"assets/sc_logo.png", children: [
height: 256, Padding(
fit: BoxFit.fitHeight, padding: const EdgeInsets.only(bottom: 30),
child: Image.asset(
"assets/sc_logo.png",
fit: BoxFit.fitHeight,
height: 260,
),
),
],
), ),
), ),
), ),
@ -222,27 +230,128 @@ class HomeUI extends BaseUI<HomeUIModel> {
), ),
), ),
Positioned( Positioned(
left: 24, left: 24,
bottom: 0,
child: SizedBox(
height: 420,
child: ScrollConfiguration(
behavior:
ScrollConfiguration.of(context).copyWith(scrollbars: false),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 200,
width: 316,
child: Tilt(
shadowConfig: const ShadowConfig(maxIntensity: .3),
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
),
child: model.rssVideoItems == null
? Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(.1)),
child: makeLoading(context),
)
: Swiper(
itemCount: model.rssVideoItems?.length ?? 0,
itemBuilder: (context, index) {
final item = model.rssVideoItems![index];
return GestureDetector(
onTap: () {
if (item.link != null) {
launchUrlString(item.link!);
}
},
child: CacheNetImage(
url: model.getRssImage(item),
fit: BoxFit.cover,
),
);
},
autoplay: true,
),
)),
SizedBox(
width: 316,
child: Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(.1),
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12))),
child: model.rssTextItems == null
? Padding(
padding: const EdgeInsets.only(
top: 24, bottom: 24),
child: makeLoading(context),
)
: Column(
children: [
const SizedBox(height: 12),
ListView.builder(
physics:
const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder:
(BuildContext context, int index) {
final item = model.rssTextItems![index];
return Tilt(
shadowConfig: const ShadowConfig(
maxIntensity: .3),
borderRadius:
BorderRadius.circular(12),
child: GestureDetector(
onTap: () {
if (item.link != null) {
launchUrlString(item.link!);
}
},
child: Padding(
padding: const EdgeInsets.only(
left: 12,
right: 12,
top: 4,
bottom: 4),
child: Row(
children: [
const Text("· "),
Expanded(
child: Text(
"${item.title}",
textAlign:
TextAlign.start,
maxLines: 1,
overflow: TextOverflow
.ellipsis,
style: const TextStyle(
fontSize: 12.2),
),
)
],
),
),
));
},
itemCount: model.rssTextItems?.length,
),
const SizedBox(height: 12),
],
)),
),
],
)),
),
),
),
Positioned(
left: 0,
right: 0,
bottom: 0, bottom: 0,
child: Column( child: Center(
children: [ child: makeGameStatusCard(context, model, 320),
const SizedBox(height: 12),
makeADCard(context, model,
bgURl:
"https://i2.hdslb.com/bfs/face/7582c8d46fc03004f4f8032c667c0ea4dbbb1088.jpg",
title: "Anicat",
subtitle: "高质量星际公民资讯UP主",
jumpUrl: "https://space.bilibili.com/27976358/video"),
const SizedBox(height: 12),
makeADCard(context, model,
bgURl:
"https://citizenwiki.cn/images/f/f2/890Jump_beach.jpg.webp",
title: "星际公民中文百科",
subtitle: "探索宇宙的好伙伴",
jumpUrl: "https://citizenwiki.cn"),
const SizedBox(height: 12),
makeGameStatusCard(context, model, width),
],
)) ))
], ],
), ),
@ -315,9 +424,7 @@ class HomeUI extends BaseUI<HomeUIModel> {
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text(model.lastScreenInfo, maxLines: 1), Text(model.lastScreenInfo, maxLines: 1),
const SizedBox(height: 32),
makeIndexActionLists(context, model), makeIndexActionLists(context, model),
const SizedBox(height: 32),
]; ];
} }
@ -480,79 +587,6 @@ class HomeUI extends BaseUI<HomeUIModel> {
); );
} }
Widget makeADCard(
BuildContext context,
HomeUIModel model, {
required String bgURl,
required String title,
required String subtitle,
required String jumpUrl,
}) {
final width = MediaQuery.of(context).size.width * .21;
return Tilt(
shadowConfig: const ShadowConfig(maxIntensity: .3),
borderRadius: BorderRadius.circular(12),
child: GestureDetector(
onTap: () {
launchUrlString(jumpUrl);
},
child: ClipRRect(
child: Container(
width: width,
height: 128,
decoration: BoxDecoration(
color: FluentTheme.of(context).cardColor,
),
child: Stack(
children: [
Padding(
padding: const EdgeInsets.all(.3),
child: ExtendedImage.network(
bgURl,
fit: BoxFit.cover,
width: width,
),
),
Container(
width: width,
decoration: BoxDecoration(
color: Colors.black.withOpacity(.7),
),
),
Positioned(
top: 0,
bottom: 0,
left: 0,
right: 0,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
title,
style: const TextStyle(
fontSize: 24,
),
),
const SizedBox(height: 6),
Text(
subtitle,
style: TextStyle(
color: Colors.white.withOpacity(.8),
fontSize: 14),
),
],
),
),
)
],
),
),
),
),
);
}
Widget makeWebViewButton(HomeUIModel model, Widget makeWebViewButton(HomeUIModel model,
{required Widget icon, {required Widget icon,
required String name, required String name,

View File

@ -2,11 +2,13 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:dart_rss/dart_rss.dart';
import 'package:desktop_webview_window/desktop_webview_window.dart'; import 'package:desktop_webview_window/desktop_webview_window.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:starcitizen_doctor/api/analytics.dart'; import 'package:starcitizen_doctor/api/analytics.dart';
import 'package:starcitizen_doctor/api/api.dart'; import 'package:starcitizen_doctor/api/api.dart';
import 'package:starcitizen_doctor/api/rss.dart';
import 'package:starcitizen_doctor/base/ui_model.dart'; import 'package:starcitizen_doctor/base/ui_model.dart';
import 'package:starcitizen_doctor/common/conf.dart'; import 'package:starcitizen_doctor/common/conf.dart';
import 'package:starcitizen_doctor/common/helper/log_helper.dart'; import 'package:starcitizen_doctor/common/helper/log_helper.dart';
@ -25,6 +27,9 @@ import 'package:starcitizen_doctor/ui/home/webview/webview.dart';
import 'package:starcitizen_doctor/ui/home/webview/webview_localization_capture_ui_model.dart'; import 'package:starcitizen_doctor/ui/home/webview/webview_localization_capture_ui_model.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
import 'package:html/parser.dart' as html;
import 'package:html/dom.dart' as htmlDom;
import 'countdown/countdown_dialog_ui.dart'; import 'countdown/countdown_dialog_ui.dart';
import 'localization/localization_ui.dart'; import 'localization/localization_ui.dart';
import 'performance/performance_ui.dart'; import 'performance/performance_ui.dart';
@ -48,6 +53,9 @@ class HomeUIModel extends BaseUIModel {
bool get isCurGameRunning => _isGameRunning[scInstalledPath] ?? false; bool get isCurGameRunning => _isGameRunning[scInstalledPath] ?? false;
List<RssItem>? rssVideoItems;
List<RssItem>? rssTextItems;
set lastScreenInfo(String info) { set lastScreenInfo(String info) {
_lastScreenInfo = info; _lastScreenInfo = info;
notifyListeners(); notifyListeners();
@ -98,6 +106,7 @@ class HomeUIModel extends BaseUIModel {
.data)); .data));
countdownFestivalListData = await Api.getFestivalCountdownList(); countdownFestivalListData = await Api.getFestivalCountdownList();
notifyListeners(); notifyListeners();
handleError(() => _loadRRS());
} catch (e) { } catch (e) {
dPrint(e); dPrint(e);
} }
@ -158,6 +167,15 @@ class HomeUIModel extends BaseUIModel {
} }
} }
Future _loadRRS() async {
final v = await RSSApi.getRssVideo();
rssVideoItems = v;
notifyListeners();
final t = await RSSApi.getRssText();
rssTextItems = t;
notifyListeners();
}
VoidCallback? doCheck() { VoidCallback? doCheck() {
if (isChecking) return null; if (isChecking) return null;
return () async { return () async {
@ -573,4 +591,17 @@ class HomeUIModel extends BaseUIModel {
CountdownDialogUIModel(countdownFestivalListData!)); CountdownDialogUIModel(countdownFestivalListData!));
}); });
} }
getRssImage(RssItem item) {
final h = html.parse(item.description ?? "");
if (h.body == null) return "";
for (var node in h.body!.nodes) {
if (node is htmlDom.Element) {
if (node.localName == "img") {
return node.attributes["src"]?.trim() ?? "";
}
}
}
return "";
}
} }

View File

@ -42,7 +42,7 @@ dependencies:
path_provider: ^2.1.1 path_provider: ^2.1.1
dio: ^5.3.3 dio: ^5.3.3
markdown_widget: ^2.2.0 markdown_widget: ^2.2.0
extended_image: ^8.1.1 extended_image: ^8.2.0
device_info_plus: ^9.0.3 device_info_plus: ^9.0.3
file_picker: ^6.0.0 file_picker: ^6.0.0
file_sizes: ^1.0.6 file_sizes: ^1.0.6
@ -62,6 +62,11 @@ dependencies:
cryptography: ^2.7.0 cryptography: ^2.7.0
cryptography_flutter: ^2.3.2 cryptography_flutter: ^2.3.2
hexcolor: ^3.0.1 hexcolor: ^3.0.1
dart_rss: ^3.0.1
html: ^0.15.4
dependency_overrides:
http: ^1.1.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: