mirror of
https://mirror.ghproxy.com/https://github.com/StarCitizenToolBox/app.git
synced 2024-12-23 04:13:43 +08:00
launch game
This commit is contained in:
parent
0640761299
commit
e465bc913d
@ -1,5 +1,3 @@
|
|||||||
/// https://github.com/CxJuice/Uex_Chinese_Translate
|
|
||||||
|
|
||||||
/// ------- WebLocalization Script --------------
|
/// ------- WebLocalization Script --------------
|
||||||
let SCLocalizationReplaceLocalesMap = {};
|
let SCLocalizationReplaceLocalesMap = {};
|
||||||
let enable_webview_localization_capture = false;
|
let enable_webview_localization_capture = false;
|
||||||
@ -220,7 +218,7 @@ InitWebLocalization();
|
|||||||
|
|
||||||
|
|
||||||
/// ----- Login Script ----
|
/// ----- Login Script ----
|
||||||
async function getRSILauncherToken() {
|
async function getRSILauncherToken(channelId) {
|
||||||
// check login
|
// check login
|
||||||
let r = await fetch("api/launcher/v3/account/check", {
|
let r = await fetch("api/launcher/v3/account/check", {
|
||||||
method: 'POST', headers: {
|
method: 'POST', headers: {
|
||||||
@ -253,12 +251,12 @@ async function getRSILauncherToken() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (tokenR.status !== 200) return;
|
if (tokenR.status !== 200) return;
|
||||||
let TokenData = (await tokenR.json())["data"];
|
let TokenData = (await tokenR.json())["data"]["token"];
|
||||||
console.log(TokenData);
|
console.log(TokenData);
|
||||||
|
|
||||||
// get release Data
|
// get release Data
|
||||||
let releaseFormData = new FormData();
|
let releaseFormData = new FormData();
|
||||||
releaseFormData.append("channelId", "LIVE");
|
releaseFormData.append("channelId", channelId);
|
||||||
releaseFormData.append("claims", claimsData);
|
releaseFormData.append("claims", claimsData);
|
||||||
releaseFormData.append("gameId", "SC");
|
releaseFormData.append("gameId", "SC");
|
||||||
releaseFormData.append("platformId", "prod");
|
releaseFormData.append("platformId", "prod");
|
||||||
@ -271,6 +269,9 @@ async function getRSILauncherToken() {
|
|||||||
if (releaseR.status !== 200) return;
|
if (releaseR.status !== 200) return;
|
||||||
let releaseDataJson = (await releaseR.json())['data'];
|
let releaseDataJson = (await releaseR.json())['data'];
|
||||||
console.log(releaseDataJson);
|
console.log(releaseDataJson);
|
||||||
|
// get user avatar
|
||||||
|
let $avatarElement = $(".c-account-sidebar__profile-metas-avatar");
|
||||||
|
let avatarUrl = $avatarElement.css("background-image");
|
||||||
|
|
||||||
// post message
|
// post message
|
||||||
window.chrome.webview.postMessage({
|
window.chrome.webview.postMessage({
|
||||||
@ -278,7 +279,8 @@ async function getRSILauncherToken() {
|
|||||||
'webToken': $.cookie('Rsi-Token'),
|
'webToken': $.cookie('Rsi-Token'),
|
||||||
'claims': claimsData,
|
'claims': claimsData,
|
||||||
'authToken': TokenData,
|
'authToken': TokenData,
|
||||||
'releaseInfo': releaseDataJson
|
'releaseInfo': releaseDataJson,
|
||||||
|
"avatar": avatarUrl
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -237,10 +237,10 @@ class HomeUI extends BaseUI<HomeUIModel> {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: Icon(
|
child: Icon(
|
||||||
FontAwesomeIcons.solidCircle,
|
FontAwesomeIcons.solidCircle,
|
||||||
color:
|
color: model
|
||||||
model.isRSIServerStatusOK(item)
|
.isRSIServerStatusOK(item)
|
||||||
? Colors.green
|
? Colors.green
|
||||||
: Colors.red,
|
: Colors.red,
|
||||||
size: 12,
|
size: 12,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -296,14 +296,14 @@ class HomeUI extends BaseUI<HomeUIModel> {
|
|||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
AnimatedSize(
|
AnimatedSize(
|
||||||
duration: const Duration(milliseconds: 130),
|
duration: const Duration(milliseconds: 130),
|
||||||
child: model.isRsiLauncherStarting
|
child: Button(
|
||||||
? makeLoading(context, width: 28)
|
child: Padding(
|
||||||
: Button(
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: const Padding(
|
child: Icon(model.isCurGameRunning
|
||||||
padding: EdgeInsets.all(8.0),
|
? FluentIcons.stop_solid
|
||||||
child: Icon(FluentIcons.play),
|
: FluentIcons.play),
|
||||||
),
|
),
|
||||||
onPressed: () => model.launchRSI()),
|
onPressed: () => model.launchRSI()),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Button(
|
Button(
|
||||||
|
@ -13,6 +13,8 @@ import 'package:starcitizen_doctor/data/app_placard_data.dart';
|
|||||||
import 'package:starcitizen_doctor/ui/home/dialogs/md_content_dialog_ui.dart';
|
import 'package:starcitizen_doctor/ui/home/dialogs/md_content_dialog_ui.dart';
|
||||||
import 'package:starcitizen_doctor/ui/home/dialogs/md_content_dialog_ui_model.dart';
|
import 'package:starcitizen_doctor/ui/home/dialogs/md_content_dialog_ui_model.dart';
|
||||||
import 'package:starcitizen_doctor/ui/home/localization/localization_ui_model.dart';
|
import 'package:starcitizen_doctor/ui/home/localization/localization_ui_model.dart';
|
||||||
|
import 'package:starcitizen_doctor/ui/home/login/login_dialog_ui.dart';
|
||||||
|
import 'package:starcitizen_doctor/ui/home/login/login_dialog_ui_model.dart';
|
||||||
import 'package:starcitizen_doctor/ui/home/performance/performance_ui_model.dart';
|
import 'package:starcitizen_doctor/ui/home/performance/performance_ui_model.dart';
|
||||||
import 'package:starcitizen_doctor/ui/home/webview/webview.dart';
|
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';
|
||||||
@ -36,6 +38,10 @@ class HomeUIModel extends BaseUIModel {
|
|||||||
bool isFixing = false;
|
bool isFixing = false;
|
||||||
String isFixingString = "";
|
String isFixingString = "";
|
||||||
|
|
||||||
|
final Map<String, bool> _isGameRunning = {};
|
||||||
|
|
||||||
|
bool get isCurGameRunning => _isGameRunning[scInstalledPath] ?? false;
|
||||||
|
|
||||||
set lastScreenInfo(String info) {
|
set lastScreenInfo(String info) {
|
||||||
_lastScreenInfo = info;
|
_lastScreenInfo = info;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -58,8 +64,6 @@ class HomeUIModel extends BaseUIModel {
|
|||||||
"Arena Commander": "竞技场指挥官"
|
"Arena Commander": "竞技场指挥官"
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isRsiLauncherStarting = false;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future loadData() async {
|
Future loadData() async {
|
||||||
if (AppConf.networkVersionData == null) return;
|
if (AppConf.networkVersionData == null) return;
|
||||||
@ -110,7 +114,7 @@ class HomeUIModel extends BaseUIModel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scInstallPaths = await SCLoggerHelper.getGameInstallPath(listData,
|
scInstallPaths = await SCLoggerHelper.getGameInstallPath(listData,
|
||||||
withVersion: ["LIVE", "PTU", "EPTU"], checkExists: true);
|
withVersion: ["LIVE", "PTU", "EVO"], checkExists: true);
|
||||||
if (scInstallPaths.isNotEmpty) {
|
if (scInstallPaths.isNotEmpty) {
|
||||||
scInstalledPath = scInstallPaths.first;
|
scInstalledPath = scInstallPaths.first;
|
||||||
}
|
}
|
||||||
@ -402,8 +406,8 @@ class HomeUIModel extends BaseUIModel {
|
|||||||
context!,
|
context!,
|
||||||
"星际公民官网汉化",
|
"星际公民官网汉化",
|
||||||
const Text(
|
const Text(
|
||||||
"\n\n\n本插功能件仅供大致浏览使用,不对任何有关本功能产生的问题负责!在涉及账号操作前请注意确认网站的原本内容!"
|
"本插功能件仅供大致浏览使用,不对任何有关本功能产生的问题负责!在涉及账号操作前请注意确认网站的原本内容!"
|
||||||
"\n\n\n使用此功能登录账号时请确保您的 StarCitizenDoctor 是从可信任的来源下载。",
|
"\n\n\n使用此功能登录账号时请确保您的 星际公民盒子 是从可信任的来源下载。",
|
||||||
style: TextStyle(fontSize: 16),
|
style: TextStyle(fontSize: 16),
|
||||||
),
|
),
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
@ -460,25 +464,39 @@ class HomeUIModel extends BaseUIModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
launchRSI() async {
|
launchRSI() async {
|
||||||
isRsiLauncherStarting = true;
|
if (scInstalledPath == "not_install") {
|
||||||
notifyListeners();
|
showToast(context!, "该功能需要一个有效的安装位置");
|
||||||
// final rsiLauncherInstalledPath = await SystemHelper.getRSILauncherPath();
|
return;
|
||||||
// if (rsiLauncherInstalledPath.isEmpty) {
|
}
|
||||||
// isRsiLauncherStarting = false;
|
if (isCurGameRunning) {
|
||||||
// notifyListeners();
|
await Process.run("powershell.exe", ["ps \"StarCitizen\" | kill"]);
|
||||||
// showToast(context!, "未找到 RSI 启动器目录");
|
return;
|
||||||
// return;
|
}
|
||||||
// }
|
showDialog(
|
||||||
// SystemHelper.checkAndLaunchRSILauncher(rsiLauncherInstalledPath);
|
context: context!,
|
||||||
goWebView("登录 RSI 账户", "https://robertsspaceindustries.com/connect",
|
dismissWithEsc: false,
|
||||||
loginMode: true, rsiLoginCallback: (data, ok) {
|
builder: (context) {
|
||||||
dPrint("======rsiLoginCallback=== $ok =====\n$data}");
|
return BaseUIContainer(
|
||||||
isRsiLauncherStarting = false;
|
uiCreate: () => LoginDialog(),
|
||||||
notifyListeners();
|
modelCreate: () => LoginDialogModel(scInstalledPath, this));
|
||||||
}, useLocalization: true);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isRSIServerStatusOK(Map map) {
|
bool isRSIServerStatusOK(Map map) {
|
||||||
return (map["status"] == "ok" || map["status"] == "operational");
|
return (map["status"] == "ok" || map["status"] == "operational");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doLaunchGame(String launchExe, List<String> args, String installPath) async {
|
||||||
|
_isGameRunning[installPath] = true;
|
||||||
|
notifyListeners();
|
||||||
|
try {
|
||||||
|
await Process.run(launchExe, args);
|
||||||
|
final launchFile = File("$installPath\\loginData.json");
|
||||||
|
if (await launchFile.exists()) {
|
||||||
|
await launchFile.delete();
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
_isGameRunning[installPath] = false;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
106
lib/ui/home/login/login_dialog_ui.dart
Normal file
106
lib/ui/home/login/login_dialog_ui.dart
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import 'package:starcitizen_doctor/base/ui.dart';
|
||||||
|
import 'package:starcitizen_doctor/widgets/cache_image.dart';
|
||||||
|
|
||||||
|
import 'login_dialog_ui_model.dart';
|
||||||
|
|
||||||
|
class LoginDialog extends BaseUI<LoginDialogModel> {
|
||||||
|
@override
|
||||||
|
Widget? buildBody(BuildContext context, LoginDialogModel model) {
|
||||||
|
return ContentDialog(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: MediaQuery.of(context).size.width * .56,
|
||||||
|
),
|
||||||
|
title: (model.loginStatus == 2) ? null : const Text("一键启动"),
|
||||||
|
content: AnimatedSize(
|
||||||
|
duration: const Duration(milliseconds: 230),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Row(),
|
||||||
|
if (model.loginStatus == 0) ...[
|
||||||
|
const Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text("登录中..."),
|
||||||
|
SizedBox(height: 12),
|
||||||
|
ProgressRing()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
] else if (model.loginStatus == 1) ...[
|
||||||
|
Text("请输入RSI账户 [${model.nickname}] 的邮箱,以保存登录状态(输入错误会导致无法进入游戏!)"),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
TextFormBox(
|
||||||
|
controller: model.emailCtrl,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(
|
||||||
|
"*该操作同一账号只需执行一次,输入错误请在盒子设置中清理,切换账号请在汉化浏览器中操作。",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color: Colors.white.withOpacity(.6),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
] else if (model.loginStatus == 2) ...[
|
||||||
|
Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
const Text(
|
||||||
|
"欢迎回来!",
|
||||||
|
style: TextStyle(fontSize: 20),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
if (model.avatarUrl != null)
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(1000),
|
||||||
|
child: CacheNetImage(
|
||||||
|
url: model.avatarUrl!,
|
||||||
|
width: 128,
|
||||||
|
height: 128,
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Text(
|
||||||
|
model.nickname,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 24, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
const Text("正在为您启动游戏..."),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
const ProgressRing(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
if (model.loginStatus == 1) ...[
|
||||||
|
Button(
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
child: Text("取消"),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}),
|
||||||
|
const SizedBox(width: 80),
|
||||||
|
FilledButton(
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
child: Text("保存"),
|
||||||
|
),
|
||||||
|
onPressed: () => model.onSaveEmail()),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String getUITitle(BuildContext context, LoginDialogModel model) => "";
|
||||||
|
}
|
174
lib/ui/home/login/login_dialog_ui_model.dart
Normal file
174
lib/ui/home/login/login_dialog_ui_model.dart
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:jwt_decode/jwt_decode.dart';
|
||||||
|
import 'package:starcitizen_doctor/base/ui_model.dart';
|
||||||
|
import 'package:starcitizen_doctor/ui/home/home_ui_model.dart';
|
||||||
|
import 'package:starcitizen_doctor/ui/home/webview/webview.dart';
|
||||||
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
|
class LoginDialogModel extends BaseUIModel {
|
||||||
|
int loginStatus = 0;
|
||||||
|
|
||||||
|
String nickname = "";
|
||||||
|
String? avatarUrl;
|
||||||
|
String? authToken;
|
||||||
|
String? webToken;
|
||||||
|
Map? releaseInfo;
|
||||||
|
|
||||||
|
final String installPath;
|
||||||
|
|
||||||
|
final HomeUIModel homeUIModel;
|
||||||
|
|
||||||
|
TextEditingController emailCtrl = TextEditingController();
|
||||||
|
|
||||||
|
LoginDialogModel(this.installPath, this.homeUIModel);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initModel() {
|
||||||
|
_launchWebLogin();
|
||||||
|
super.initModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _launchWebLogin() {
|
||||||
|
goWebView("登录 RSI 账户", "https://robertsspaceindustries.com/connect",
|
||||||
|
loginMode: true, rsiLoginCallback: (message, ok) async {
|
||||||
|
dPrint(
|
||||||
|
"======rsiLoginCallback=== $ok ===== data==\n${json.encode(message)}");
|
||||||
|
if (message == null || !ok) {
|
||||||
|
Navigator.pop(context!);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final emailBox = await Hive.openBox("quick_login_email");
|
||||||
|
final data = message["data"];
|
||||||
|
authToken = data["authToken"];
|
||||||
|
webToken = data["webToken"];
|
||||||
|
releaseInfo = data["releaseInfo"];
|
||||||
|
avatarUrl = data["avatar"]
|
||||||
|
?.toString()
|
||||||
|
.replaceAll("url(\"", "")
|
||||||
|
.replaceAll("\")", "");
|
||||||
|
Map<String, dynamic> payload = Jwt.parseJwt(authToken!);
|
||||||
|
nickname = payload["nickname"] ?? "";
|
||||||
|
if (emailBox.get(nickname, defaultValue: "") == "") {
|
||||||
|
loginStatus = 1;
|
||||||
|
notifyListeners();
|
||||||
|
} else {
|
||||||
|
emailCtrl.text = emailBox.get(nickname, defaultValue: "");
|
||||||
|
_readyForLaunch();
|
||||||
|
}
|
||||||
|
}, useLocalization: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
goWebView(String title, String url,
|
||||||
|
{bool useLocalization = false,
|
||||||
|
bool loginMode = false,
|
||||||
|
RsiLoginCallback? rsiLoginCallback}) async {
|
||||||
|
if (useLocalization) {
|
||||||
|
const tipVersion = 2;
|
||||||
|
final box = await Hive.openBox("app_conf");
|
||||||
|
final skip = await box.get("skip_web_login_version", defaultValue: 0);
|
||||||
|
if (skip != tipVersion) {
|
||||||
|
final ok = await showConfirmDialogs(
|
||||||
|
context!,
|
||||||
|
"星际公民盒子一键启动",
|
||||||
|
const Text(
|
||||||
|
"本功能可以帮您更加便利的启动游戏。\n\n为确保账户安全 ,本功能使用汉化浏览器保留登录状态,且不会保存您的密码信息,与 RSI 启动器行为一致。"
|
||||||
|
"\n\n使用此功能登录账号时请确保您的 星际公民盒子 是从可信任的来源下载。",
|
||||||
|
style: TextStyle(fontSize: 16),
|
||||||
|
),
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: MediaQuery.of(context!).size.width * .6));
|
||||||
|
if (!ok) {
|
||||||
|
if (loginMode) {
|
||||||
|
rsiLoginCallback?.call(null, false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await box.put("skip_web_login_version", tipVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!await WebviewWindow.isWebviewAvailable()) {
|
||||||
|
await showToast(context!, "需要安装 WebView2 Runtime");
|
||||||
|
await launchUrlString(
|
||||||
|
"https://developer.microsoft.com/en-us/microsoft-edge/webview2/");
|
||||||
|
Navigator.pop(context!);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final webViewModel = WebViewModel(context!,
|
||||||
|
loginMode: loginMode,
|
||||||
|
loginCallback: rsiLoginCallback,
|
||||||
|
loginChannel: getChannelID());
|
||||||
|
if (useLocalization) {
|
||||||
|
try {
|
||||||
|
await webViewModel.initLocalization();
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
await webViewModel.initWebView(
|
||||||
|
title: title,
|
||||||
|
);
|
||||||
|
await webViewModel.launch(url);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSaveEmail() async {
|
||||||
|
final RegExp emailRegex = RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$');
|
||||||
|
if (!emailRegex.hasMatch(emailCtrl.text.trim())) {
|
||||||
|
showToast(context!, "邮箱输入有误!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final emailBox = await Hive.openBox("quick_login_email");
|
||||||
|
await emailBox.put(nickname, emailCtrl.text.trim());
|
||||||
|
_readyForLaunch();
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _readyForLaunch() async {
|
||||||
|
loginStatus = 2;
|
||||||
|
notifyListeners();
|
||||||
|
final launchData = {
|
||||||
|
"username": emailCtrl.text.trim(),
|
||||||
|
"token": webToken,
|
||||||
|
"auth_token": authToken,
|
||||||
|
"star_network": {
|
||||||
|
"services_endpoint": releaseInfo?["servicesEndpoint"],
|
||||||
|
"hostname": releaseInfo?["universeHost"],
|
||||||
|
"port": releaseInfo?["universePort"],
|
||||||
|
},
|
||||||
|
"TMid": const Uuid().v4(),
|
||||||
|
};
|
||||||
|
final executable = releaseInfo?["executable"];
|
||||||
|
final launchOptions = releaseInfo?["launchOptions"];
|
||||||
|
dPrint("----------launch data ====== -----------\n$launchData");
|
||||||
|
dPrint(
|
||||||
|
"----------executable data ====== -----------\n$installPath\\$executable $launchOptions");
|
||||||
|
final launchFile = File("$installPath\\loginData.json");
|
||||||
|
if (await launchFile.exists()) {
|
||||||
|
await launchFile.delete();
|
||||||
|
}
|
||||||
|
await launchFile.create();
|
||||||
|
await launchFile.writeAsString(json.encode(launchData));
|
||||||
|
notifyListeners();
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
homeUIModel.doLaunchGame(
|
||||||
|
'$installPath\\$executable',
|
||||||
|
["-no_login_dialog", ...launchOptions.toString().split(" ")],
|
||||||
|
installPath);
|
||||||
|
await Future.delayed(const Duration(seconds: 3));
|
||||||
|
Navigator.pop(context!);
|
||||||
|
}
|
||||||
|
|
||||||
|
String getChannelID() {
|
||||||
|
if (installPath.endsWith("\\LIVE")) {
|
||||||
|
return "LIVE";
|
||||||
|
} else if (installPath.endsWith("\\PTU")) {
|
||||||
|
return "PTU";
|
||||||
|
} else if (installPath.endsWith("\\EVO")) {
|
||||||
|
return "EVO";
|
||||||
|
}
|
||||||
|
return "LIVE";
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,8 @@ class WebViewModel {
|
|||||||
|
|
||||||
bool get isClosed => _isClosed;
|
bool get isClosed => _isClosed;
|
||||||
|
|
||||||
WebViewModel(this.context, {this.loginMode = false, this.loginCallback});
|
WebViewModel(this.context,
|
||||||
|
{this.loginMode = false, this.loginCallback, this.loginChannel = "LIVE"});
|
||||||
|
|
||||||
String url = "";
|
String url = "";
|
||||||
bool canGoBack = false;
|
bool canGoBack = false;
|
||||||
@ -39,6 +40,7 @@ class WebViewModel {
|
|||||||
Map<String, String>? get curReplaceWords => _curReplaceWords;
|
Map<String, String>? get curReplaceWords => _curReplaceWords;
|
||||||
|
|
||||||
final bool loginMode;
|
final bool loginMode;
|
||||||
|
final String loginChannel;
|
||||||
|
|
||||||
bool _loginModeSuccess = false;
|
bool _loginModeSuccess = false;
|
||||||
|
|
||||||
@ -56,7 +58,6 @@ class WebViewModel {
|
|||||||
if (loginMode) {
|
if (loginMode) {
|
||||||
await webview.setWebviewWindowVisibility(false);
|
await webview.setWebviewWindowVisibility(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// webview.openDevToolsWindow();
|
// webview.openDevToolsWindow();
|
||||||
webview.isNavigating.addListener(() async {
|
webview.isNavigating.addListener(() async {
|
||||||
if (!webview.isNavigating.value && localizationResource.isNotEmpty) {
|
if (!webview.isNavigating.value && localizationResource.isNotEmpty) {
|
||||||
@ -117,10 +118,14 @@ class WebViewModel {
|
|||||||
await Future.delayed(const Duration(milliseconds: 100));
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
await webview.evaluateJavaScript(
|
await webview.evaluateJavaScript(
|
||||||
"WebLocalizationUpdateReplaceWords(${json.encode(replaceWords)},$enableCapture)");
|
"WebLocalizationUpdateReplaceWords(${json.encode(replaceWords)},$enableCapture)");
|
||||||
|
|
||||||
|
/// loginMode
|
||||||
if (loginMode) {
|
if (loginMode) {
|
||||||
dPrint("--- do rsi login ---");
|
dPrint(
|
||||||
|
"--- do rsi login ---\n run === getRSILauncherToken(\"$loginChannel\");");
|
||||||
await Future.delayed(const Duration(milliseconds: 200));
|
await Future.delayed(const Duration(milliseconds: 200));
|
||||||
webview.evaluateJavaScript("getRSILauncherToken();");
|
webview.evaluateJavaScript(
|
||||||
|
"getRSILauncherToken(\"$loginChannel\");");
|
||||||
}
|
}
|
||||||
} else if (uri.host.contains("www.erkul.games") ||
|
} else if (uri.host.contains("www.erkul.games") ||
|
||||||
uri.host.contains("uexcorp.space") ||
|
uri.host.contains("uexcorp.space") ||
|
||||||
@ -163,8 +168,7 @@ class WebViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initLocalization() async {
|
initLocalization() async {
|
||||||
localizationScript =
|
localizationScript = await rootBundle.loadString('assets/web_script.js');
|
||||||
await rootBundle.loadString('assets/localization_web_script.js');
|
|
||||||
|
|
||||||
/// https://github.com/CxJuice/Uex_Chinese_Translate
|
/// https://github.com/CxJuice/Uex_Chinese_Translate
|
||||||
// get versions
|
// get versions
|
||||||
@ -172,6 +176,7 @@ class WebViewModel {
|
|||||||
|
|
||||||
final v = AppWebLocalizationVersionsData.fromJson(
|
final v = AppWebLocalizationVersionsData.fromJson(
|
||||||
await _getJson("$hostUrl/versions.json"));
|
await _getJson("$hostUrl/versions.json"));
|
||||||
|
|
||||||
dPrint("AppWebLocalizationVersionsData === ${v.toJson()}");
|
dPrint("AppWebLocalizationVersionsData === ${v.toJson()}");
|
||||||
|
|
||||||
localizationResource["zh-CN"] = await _getJson("$hostUrl/zh-CN-rsi.json",
|
localizationResource["zh-CN"] = await _getJson("$hostUrl/zh-CN-rsi.json",
|
||||||
|
@ -183,7 +183,7 @@ class ToolsUIModel extends BaseUIModel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scInstallPaths = await SCLoggerHelper.getGameInstallPath(listData,
|
scInstallPaths = await SCLoggerHelper.getGameInstallPath(listData,
|
||||||
checkExists: false, withVersion: ["LIVE", "PTU", "EPTU"]);
|
checkExists: false, withVersion: ["LIVE", "PTU", "EVO"]);
|
||||||
if (scInstallPaths.isNotEmpty) {
|
if (scInstallPaths.isNotEmpty) {
|
||||||
scInstalledPath = scInstallPaths.first;
|
scInstalledPath = scInstallPaths.first;
|
||||||
}
|
}
|
||||||
|
41
lib/widgets/cache_image.dart
Normal file
41
lib/widgets/cache_image.dart
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import 'package:extended_image/extended_image.dart';
|
||||||
|
import 'package:fluent_ui/fluent_ui.dart';
|
||||||
|
|
||||||
|
class CacheNetImage extends StatelessWidget {
|
||||||
|
final String url;
|
||||||
|
final double? width;
|
||||||
|
final double? height;
|
||||||
|
final BoxFit? fit;
|
||||||
|
|
||||||
|
const CacheNetImage(
|
||||||
|
{super.key, required this.url, this.width, this.height, this.fit});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ExtendedImage.network(
|
||||||
|
url,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: fit,
|
||||||
|
loadStateChanged: (ExtendedImageState state) {
|
||||||
|
switch (state.extendedImageLoadState) {
|
||||||
|
case LoadState.loading:
|
||||||
|
return const Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
ProgressRing(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
case LoadState.failed:
|
||||||
|
return const Text("Loading Image error");
|
||||||
|
case LoadState.completed:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,9 @@ dependencies:
|
|||||||
desktop_webview_window: ^0.2.3
|
desktop_webview_window: ^0.2.3
|
||||||
flutter_svg: ^2.0.7
|
flutter_svg: ^2.0.7
|
||||||
archive: ^3.4.4
|
archive: ^3.4.4
|
||||||
|
jwt_decode: ^0.3.1
|
||||||
|
html: ^0.15.4
|
||||||
|
uuid: ^4.1.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
Reference in New Issue
Block a user