mirror of
https://mirror.ghproxy.com/https://github.com/StarCitizenToolBox/app.git
synced 2024-12-23 00:33:42 +08:00
新增信息流 (接入 Anicat G佬 新闻组+)
This commit is contained in:
parent
4f6623a4cd
commit
4d7f73ffc4
31
lib/api/rss.dart
Normal file
31
lib/api/rss.dart
Normal 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;
|
||||
}
|
||||
}
|
@ -34,6 +34,14 @@ class AppConf {
|
||||
|
||||
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 AppVersionData? networkVersionData;
|
||||
@ -90,8 +98,8 @@ class AppConf {
|
||||
/// init windows
|
||||
await windowManager.ensureInitialized();
|
||||
windowManager.waitUntilReadyToShow().then((_) async {
|
||||
await windowManager.setSize(const Size(1280, 820));
|
||||
await windowManager.setMinimumSize(const Size(1280, 820));
|
||||
await windowManager.setSize(const Size(1300, 830));
|
||||
await windowManager.setMinimumSize(const Size(1300, 830));
|
||||
await windowManager.center(animate: true);
|
||||
await windowManager.setSkipTaskbar(false);
|
||||
await windowManager.setTitleBarStyle(
|
||||
|
@ -1,11 +1,11 @@
|
||||
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_svg/flutter_svg.dart';
|
||||
import 'package:flutter_tilt/flutter_tilt.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:starcitizen_doctor/api/analytics.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:url_launcher/url_launcher_string.dart';
|
||||
|
||||
@ -18,6 +18,7 @@ class HomeUI extends BaseUI<HomeUIModel> {
|
||||
children: [
|
||||
Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.zero,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@ -36,7 +37,7 @@ class HomeUI extends BaseUI<HomeUIModel> {
|
||||
? null
|
||||
: () => model.closePlacard(),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
if (!model.isChecking &&
|
||||
model.checkResult != null &&
|
||||
@ -71,7 +72,7 @@ class HomeUI extends BaseUI<HomeUIModel> {
|
||||
}
|
||||
|
||||
List<Widget> makeIndex(BuildContext context, HomeUIModel model) {
|
||||
final width = MediaQuery.of(context).size.width * .21;
|
||||
const double width = 280;
|
||||
return [
|
||||
Stack(
|
||||
children: [
|
||||
@ -80,10 +81,17 @@ class HomeUI extends BaseUI<HomeUIModel> {
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Center(
|
||||
child: Image.asset(
|
||||
"assets/sc_logo.png",
|
||||
height: 256,
|
||||
fit: BoxFit.fitHeight,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
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(
|
||||
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,
|
||||
child: Column(
|
||||
children: [
|
||||
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),
|
||||
],
|
||||
child: Center(
|
||||
child: makeGameStatusCard(context, model, 320),
|
||||
))
|
||||
],
|
||||
),
|
||||
@ -315,9 +424,7 @@ class HomeUI extends BaseUI<HomeUIModel> {
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(model.lastScreenInfo, maxLines: 1),
|
||||
const SizedBox(height: 32),
|
||||
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,
|
||||
{required Widget icon,
|
||||
required String name,
|
||||
|
@ -2,11 +2,13 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dart_rss/dart_rss.dart';
|
||||
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:starcitizen_doctor/api/analytics.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/common/conf.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: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 'localization/localization_ui.dart';
|
||||
import 'performance/performance_ui.dart';
|
||||
@ -48,6 +53,9 @@ class HomeUIModel extends BaseUIModel {
|
||||
|
||||
bool get isCurGameRunning => _isGameRunning[scInstalledPath] ?? false;
|
||||
|
||||
List<RssItem>? rssVideoItems;
|
||||
List<RssItem>? rssTextItems;
|
||||
|
||||
set lastScreenInfo(String info) {
|
||||
_lastScreenInfo = info;
|
||||
notifyListeners();
|
||||
@ -98,6 +106,7 @@ class HomeUIModel extends BaseUIModel {
|
||||
.data));
|
||||
countdownFestivalListData = await Api.getFestivalCountdownList();
|
||||
notifyListeners();
|
||||
handleError(() => _loadRRS());
|
||||
} catch (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() {
|
||||
if (isChecking) return null;
|
||||
return () async {
|
||||
@ -573,4 +591,17 @@ class HomeUIModel extends BaseUIModel {
|
||||
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 "";
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ dependencies:
|
||||
path_provider: ^2.1.1
|
||||
dio: ^5.3.3
|
||||
markdown_widget: ^2.2.0
|
||||
extended_image: ^8.1.1
|
||||
extended_image: ^8.2.0
|
||||
device_info_plus: ^9.0.3
|
||||
file_picker: ^6.0.0
|
||||
file_sizes: ^1.0.6
|
||||
@ -62,6 +62,11 @@ dependencies:
|
||||
cryptography: ^2.7.0
|
||||
cryptography_flutter: ^2.3.2
|
||||
hexcolor: ^3.0.1
|
||||
dart_rss: ^3.0.1
|
||||
html: ^0.15.4
|
||||
|
||||
dependency_overrides:
|
||||
http: ^1.1.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user