mirror of
https://mirror.ghproxy.com/https://github.com/StarCitizenToolBox/app.git
synced 2024-12-22 23:23:43 +08:00
初始化登录功能
This commit is contained in:
parent
59412db924
commit
6153bcf9c0
@ -24,6 +24,7 @@ linter:
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
dangling_library_doc_comments: false
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
|
@ -1,6 +1,6 @@
|
||||
/// https://github.com/CxJuice/Uex_Chinese_Translate
|
||||
|
||||
|
||||
/// ------- WebLocalization Script --------------
|
||||
let SCLocalizationReplaceLocalesMap = {};
|
||||
let enable_webview_localization_capture = false;
|
||||
let SCLocalizationEnableSplitMode = false;
|
||||
@ -216,4 +216,68 @@ function ReportUnTranslate(k, v) {
|
||||
}
|
||||
}
|
||||
|
||||
InitWebLocalization();
|
||||
InitWebLocalization();
|
||||
|
||||
|
||||
/// ----- Login Script ----
|
||||
async function getRSILauncherToken() {
|
||||
// check login
|
||||
let r = await fetch("api/launcher/v3/account/check", {
|
||||
method: 'POST', headers: {
|
||||
'x-rsi-token': $.cookie('Rsi-Token'),
|
||||
},
|
||||
});
|
||||
if (r.status !== 200) {
|
||||
// wait login
|
||||
return;
|
||||
}
|
||||
|
||||
// get claims
|
||||
let claimsR = await fetch("api/launcher/v3/games/claims", {
|
||||
method: 'POST', headers: {
|
||||
'x-rsi-token': $.cookie('Rsi-Token'),
|
||||
},
|
||||
});
|
||||
if (claimsR.status !== 200) return;
|
||||
let claimsData = (await claimsR.json())["data"];
|
||||
|
||||
let tokenFormData = new FormData();
|
||||
tokenFormData.append('claims', claimsData);
|
||||
tokenFormData.append('gameId', 'SC');
|
||||
let tokenR = await fetch("api/launcher/v3/games/token", {
|
||||
method: 'POST', headers: {
|
||||
'x-rsi-token': $.cookie('Rsi-Token'),
|
||||
},
|
||||
body: tokenFormData
|
||||
});
|
||||
|
||||
if (tokenR.status !== 200) return;
|
||||
let TokenData = (await tokenR.json())["data"];
|
||||
console.log(TokenData);
|
||||
|
||||
// get release Data
|
||||
let releaseFormData = new FormData();
|
||||
releaseFormData.append("channelId", "LIVE");
|
||||
releaseFormData.append("claims", claimsData);
|
||||
releaseFormData.append("gameId", "SC");
|
||||
releaseFormData.append("platformId", "prod");
|
||||
let releaseR = await fetch("api/launcher/v3/games/release", {
|
||||
method: 'POST', headers: {
|
||||
'x-rsi-token': $.cookie('Rsi-Token'),
|
||||
},
|
||||
body: releaseFormData
|
||||
});
|
||||
if (releaseR.status !== 200) return;
|
||||
let releaseDataJson = await releaseR.json();
|
||||
console.log(releaseDataJson);
|
||||
|
||||
// post message
|
||||
window.chrome.webview.postMessage({
|
||||
action: 'webview_rsi_login_success', data: {
|
||||
'webToken': $.cookie('Rsi-Token'),
|
||||
'claims': claimsData,
|
||||
'authToken': TokenData,
|
||||
'releaseInfo': releaseDataJson
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -16,8 +16,7 @@ class BaseUIContainer extends ConsumerStatefulWidget {
|
||||
final dynamic Function() modelCreate;
|
||||
|
||||
const BaseUIContainer(
|
||||
{Key? key, required this.uiCreate, required this.modelCreate})
|
||||
: super(key: key);
|
||||
{super.key, required this.uiCreate, required this.modelCreate});
|
||||
|
||||
@override
|
||||
// ignore: no_logic_in_create_state
|
||||
|
@ -51,7 +51,7 @@ class AppUI extends BaseUI {
|
||||
}
|
||||
|
||||
class WindowButtons extends StatelessWidget {
|
||||
const WindowButtons({Key? key}) : super(key: key);
|
||||
const WindowButtons({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -388,9 +388,12 @@ class HomeUIModel extends BaseUIModel {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
goWebView(String title, String url, {bool useLocalization = false}) async {
|
||||
goWebView(String title, String url,
|
||||
{bool useLocalization = false,
|
||||
bool loginMode = false,
|
||||
RsiLoginCallback? rsiLoginCallback}) async {
|
||||
if (useLocalization) {
|
||||
const tipVersion = 1;
|
||||
const tipVersion = 2;
|
||||
final box = await Hive.openBox("app_conf");
|
||||
final skip =
|
||||
await box.get("skip_web_localization_tip_version", defaultValue: 0);
|
||||
@ -399,15 +402,18 @@ class HomeUIModel extends BaseUIModel {
|
||||
context!,
|
||||
"星际公民官网汉化",
|
||||
const Text(
|
||||
"该汉化功能移植自星际公民汉化组的 Tampermonkey 浏览器插件(https://greasyfork.org/zh-CN/scripts/459084),文本内容由星际公民汉化组进行更新。"
|
||||
"\n\n移植后的脚本源代码随 StarCitizenDoctor 项目一起分发(https://jihulab.com/StarCitizenCN_Community/StarCitizenDoctor)。"
|
||||
"\n\n\n本插功能件仅供大致浏览使用,不对任何有关本功能产生的问题负责!在涉及账号操作前请注意确认网站的原本内容!"
|
||||
"\n\n\n使用此功能登录账号时请确保您的 StarCitizenDoctor 是从可信任的来源下载。",
|
||||
style: TextStyle(fontSize: 16),
|
||||
),
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context!).size.width * .6));
|
||||
if (!ok) return;
|
||||
if (!ok) {
|
||||
if (loginMode) {
|
||||
rsiLoginCallback?.call(null, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
await box.put("skip_web_localization_tip_version", tipVersion);
|
||||
}
|
||||
}
|
||||
@ -417,7 +423,8 @@ class HomeUIModel extends BaseUIModel {
|
||||
"https://developer.microsoft.com/en-us/microsoft-edge/webview2/");
|
||||
return;
|
||||
}
|
||||
final webViewModel = WebViewModel(context!);
|
||||
final webViewModel = WebViewModel(context!,
|
||||
loginMode: loginMode, loginCallback: rsiLoginCallback);
|
||||
if (useLocalization) {
|
||||
isFixingString = "正在初始化汉化资源...";
|
||||
isFixing = true;
|
||||
@ -431,7 +438,9 @@ class HomeUIModel extends BaseUIModel {
|
||||
isFixing = false;
|
||||
}
|
||||
|
||||
await webViewModel.initWebView(title: title);
|
||||
await webViewModel.initWebView(
|
||||
title: title,
|
||||
);
|
||||
if (await File(
|
||||
"${AppConf.applicationSupportDir}\\webview_data\\enable_webview_localization_capture")
|
||||
.exists()) {
|
||||
@ -453,17 +462,19 @@ class HomeUIModel extends BaseUIModel {
|
||||
launchRSI() async {
|
||||
isRsiLauncherStarting = true;
|
||||
notifyListeners();
|
||||
final rsiLauncherInstalledPath = await SystemHelper.getRSILauncherPath();
|
||||
if (rsiLauncherInstalledPath.isEmpty) {
|
||||
// final rsiLauncherInstalledPath = await SystemHelper.getRSILauncherPath();
|
||||
// if (rsiLauncherInstalledPath.isEmpty) {
|
||||
// isRsiLauncherStarting = false;
|
||||
// notifyListeners();
|
||||
// showToast(context!, "未找到 RSI 启动器目录");
|
||||
// return;
|
||||
// }
|
||||
// SystemHelper.checkAndLaunchRSILauncher(rsiLauncherInstalledPath);
|
||||
goWebView("登录 RSI 账户", "https://robertsspaceindustries.com/connect",
|
||||
loginMode: true, rsiLoginCallback: (data, ok) {
|
||||
isRsiLauncherStarting = false;
|
||||
notifyListeners();
|
||||
showToast(context!, "未找到 RSI 启动器目录");
|
||||
return;
|
||||
}
|
||||
SystemHelper.checkAndLaunchRSILauncher(rsiLauncherInstalledPath);
|
||||
await Future.delayed(const Duration(seconds: 3));
|
||||
isRsiLauncherStarting = false;
|
||||
notifyListeners();
|
||||
}, useLocalization: true);
|
||||
}
|
||||
|
||||
bool isRSIServerStatusOK(Map map) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||
@ -12,6 +13,8 @@ import 'package:starcitizen_doctor/data/app_web_localization_versions_data.dart'
|
||||
import '../../../api/api.dart';
|
||||
import '../../../base/ui.dart';
|
||||
|
||||
typedef RsiLoginCallback = void Function(Map? data, bool success);
|
||||
|
||||
class WebViewModel {
|
||||
late Webview webview;
|
||||
final BuildContext context;
|
||||
@ -20,7 +23,7 @@ class WebViewModel {
|
||||
|
||||
bool get isClosed => _isClosed;
|
||||
|
||||
WebViewModel(this.context);
|
||||
WebViewModel(this.context, {this.loginMode = false, this.loginCallback});
|
||||
|
||||
String url = "";
|
||||
bool canGoBack = false;
|
||||
@ -35,19 +38,27 @@ class WebViewModel {
|
||||
|
||||
Map<String, String>? get curReplaceWords => _curReplaceWords;
|
||||
|
||||
final bool loginMode;
|
||||
|
||||
bool _loginModeSuccess = false;
|
||||
|
||||
final RsiLoginCallback? loginCallback;
|
||||
|
||||
initWebView({String title = ""}) async {
|
||||
try {
|
||||
webview = await WebviewWindow.create(
|
||||
configuration: CreateConfiguration(
|
||||
windowWidth: 1920,
|
||||
windowHeight: 1080,
|
||||
windowWidth: loginMode ? 960 : 1920,
|
||||
windowHeight: loginMode ? 720 : 1080,
|
||||
userDataFolderWindows:
|
||||
"${AppConf.applicationSupportDir}/webview_data",
|
||||
title: title));
|
||||
|
||||
// webview.openDevToolsWindow();
|
||||
webview.isNavigating.addListener(() async {
|
||||
if (!webview.isNavigating.value && localizationResource.isNotEmpty) {
|
||||
final uri = Uri.parse(url);
|
||||
dPrint("webview Navigating uri === $uri");
|
||||
if (uri.host.contains("robertsspaceindustries.com")) {
|
||||
// SC 官网
|
||||
dPrint("load script");
|
||||
@ -103,6 +114,11 @@ class WebViewModel {
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
await webview.evaluateJavaScript(
|
||||
"WebLocalizationUpdateReplaceWords(${json.encode(replaceWords)},$enableCapture)");
|
||||
if (loginMode) {
|
||||
dPrint("--- do rsi login ---");
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
webview.evaluateJavaScript("getRSILauncherToken();");
|
||||
}
|
||||
} else if (uri.host.contains("www.erkul.games") ||
|
||||
uri.host.contains("uexcorp.space") ||
|
||||
uri.host.contains("ccugame.app")) {
|
||||
@ -121,9 +137,17 @@ class WebViewModel {
|
||||
dPrint("OnUrlRequestCallback === $url");
|
||||
this.url = url;
|
||||
});
|
||||
webview.onClose.whenComplete(() {
|
||||
_isClosed = true;
|
||||
});
|
||||
webview.onClose.whenComplete(dispose);
|
||||
if (loginMode) {
|
||||
webview.addOnWebMessageReceivedCallback((messageString) {
|
||||
final message = json.decode(messageString);
|
||||
if (message["action"] == "webview_rsi_login_success") {
|
||||
_loginModeSuccess = true;
|
||||
loginCallback?.call(message, true);
|
||||
webview.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
showToast(context, "初始化失败:$e");
|
||||
}
|
||||
@ -211,4 +235,11 @@ class WebViewModel {
|
||||
OnWebMessageReceivedCallback callback) {
|
||||
webview.removeOnWebMessageReceivedCallback(callback);
|
||||
}
|
||||
|
||||
FutureOr<void> dispose() {
|
||||
if (loginMode && !_loginModeSuccess) {
|
||||
loginCallback?.call(null, false);
|
||||
}
|
||||
_isClosed = true;
|
||||
}
|
||||
}
|
||||
|
@ -60,45 +60,45 @@ fastPadding(
|
||||
}
|
||||
|
||||
List<Widget> makeMarkdownView(String description) {
|
||||
return MarkdownGenerator(
|
||||
return MarkdownGenerator().buildWidgets(description,
|
||||
config: MarkdownConfig(configs: [
|
||||
LinkConfig(onTap: (url) {
|
||||
if (url.startsWith("/")) {
|
||||
url = "${AppConf.gitlabHomeUrl}/$url";
|
||||
}
|
||||
launchUrlString(url);
|
||||
}),
|
||||
ImgConfig(builder: (String url, Map<String, String> attributes) {
|
||||
return ExtendedImage.network(
|
||||
url,
|
||||
loadStateChanged: (ExtendedImageState state) {
|
||||
switch (state.extendedImageLoadState) {
|
||||
case LoadState.loading:
|
||||
return const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
ProgressRing(),
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Text("加载图片...")
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
case LoadState.completed:
|
||||
return ExtendedRawImage(
|
||||
image: state.extendedImageInfo?.image,
|
||||
);
|
||||
case LoadState.failed:
|
||||
return const Text("Loading Image error");
|
||||
LinkConfig(onTap: (url) {
|
||||
if (url.startsWith("/")) {
|
||||
url = "${AppConf.gitlabHomeUrl}/$url";
|
||||
}
|
||||
},
|
||||
);
|
||||
})
|
||||
])).buildWidgets(description);
|
||||
launchUrlString(url);
|
||||
}),
|
||||
ImgConfig(builder: (String url, Map<String, String> attributes) {
|
||||
return ExtendedImage.network(
|
||||
url,
|
||||
loadStateChanged: (ExtendedImageState state) {
|
||||
switch (state.extendedImageLoadState) {
|
||||
case LoadState.loading:
|
||||
return const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
ProgressRing(),
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Text("加载图片...")
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
case LoadState.completed:
|
||||
return ExtendedRawImage(
|
||||
image: state.extendedImageInfo?.image,
|
||||
);
|
||||
case LoadState.failed:
|
||||
return const Text("Loading Image error");
|
||||
}
|
||||
},
|
||||
);
|
||||
})
|
||||
]));
|
||||
}
|
||||
|
||||
class NoScrollBehavior extends ScrollBehavior {
|
||||
|
@ -44,7 +44,7 @@ dependencies:
|
||||
markdown_widget: ^2.2.0
|
||||
extended_image: ^8.1.1
|
||||
device_info_plus: ^9.0.3
|
||||
file_picker: ^5.5.0
|
||||
file_picker: ^6.0.0
|
||||
file_sizes: ^1.0.6
|
||||
desktop_webview_window: ^0.2.3
|
||||
flutter_svg: ^2.0.7
|
||||
@ -59,7 +59,7 @@ dev_dependencies:
|
||||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
# package. See that file for information about deactivating specific lint
|
||||
# rules and activating additional ones.
|
||||
flutter_lints: ^2.0.0
|
||||
flutter_lints: ^3.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
Loading…
Reference in New Issue
Block a user