mirror of
https://mirror.ghproxy.com/https://github.com/StarCitizenToolBox/app.git
synced 2024-12-23 11:13:46 +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 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(
|
||||||
|
@ -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,
|
||||||
|
@ -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 "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user