From bcc9d61c2f201af6e15fd74ebb0a6a57fa48df78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8F=98=E8=8F=98?= Date: Thu, 16 Sep 2021 17:57:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9ADebug=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E9=A1=9E=E5=9E=8B=EF=BC=8C=E4=BD=9C=E7=82=BA=E9=96=8B?= =?UTF-8?q?=E7=99=BC=E4=BA=BA=E5=93=A1=E9=99=A4=E9=8C=AF=E7=89=88=E5=B0=88?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/launch.json | 12 +- lang/zh_tw.json | 5 +- lib/LauncherInfo.dart | 22 +- lib/Screen/About.dart | 2 +- lib/Screen/CurseForgeModVersion.dart | 290 +++++++++++++++++++++++++++ lib/Screen/DownloadCurseModPack.dart | 260 ++++++++++++++++++++++++ lib/Screen/FabricVersion.dart | 65 ++++++ lib/Screen/ForgeVersion.dart | 67 +++++++ lib/Screen/Settings.dart | 14 +- lib/Utility/Updater.dart | 48 +++-- lib/main.dart | 4 +- 11 files changed, 746 insertions(+), 43 deletions(-) create mode 100644 lib/Screen/CurseForgeModVersion.dart create mode 100644 lib/Screen/DownloadCurseModPack.dart create mode 100644 lib/Screen/FabricVersion.dart create mode 100644 lib/Screen/ForgeVersion.dart diff --git a/.vscode/launch.json b/.vscode/launch.json index d25faaf1..b53a8121 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,9 +10,9 @@ "type": "dart", "args": [ "--dart-define", - "build_id=10000000", + "build_id=none", "--dart-define", - "version_type=alpha", + "version_type=debug", "--dart-define", "version=1.0.0" ] @@ -24,9 +24,9 @@ "flutterMode": "profile", "args": [ "--dart-define", - "build_id=10000000", + "build_id=none", "--dart-define", - "version_type=alpha", + "version_type=debug", "--dart-define", "version=1.0.0" ] @@ -38,9 +38,9 @@ "flutterMode": "release", "args": [ "--dart-define", - "build_id=10000000", + "build_id=none", "--dart-define", - "version_type=alpha", + "version_type=debug", "--dart-define", "version=1.0.0" ] diff --git a/lang/zh_tw.json b/lang/zh_tw.json index ac483559..5be79758 100644 --- a/lang/zh_tw.json +++ b/lang/zh_tw.json @@ -88,8 +88,9 @@ "settings.advanced.title": "進階設定", "settings.advanced.assets.check": "檢查資源檔案完整性", "settings.advanced.max.log": "遊戲日誌紀錄最大行數", - "settings.advanced.channel.stable": "穩定版更新通道", - "settings.advanced.channel.dev": "開發版更新通道", + "settings.advanced.channel.stable": "穩定版", + "settings.advanced.channel.dev": "開發版", + "settings.advanced.channel.debug":"開發人員除錯版", "edit.instance.title": "編輯安裝檔", "edit.instance.homepage.instance.name": "安裝檔名稱: ", "edit.instance.homepage.instance.enter": "請輸入安裝檔名稱", diff --git a/lib/LauncherInfo.dart b/lib/LauncherInfo.dart index 898c706b..eb3d0b5d 100644 --- a/lib/LauncherInfo.dart +++ b/lib/LauncherInfo.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import 'package:rpmlauncher/Utility/Updater.dart'; import 'package:rpmlauncher/Utility/i18n.dart'; class LauncherInfo { @@ -22,21 +23,28 @@ class LauncherInfo { return "RWL"; } - static Text getVersionType() { + static VersionTypes getVersionType() { String type = const String.fromEnvironment('version_type'); - if (type == "release") { - return Text(i18n.Format("edit.instance.mods.release"), + VersionTypes ChannelType = Updater.getVersionTypeFromString(type); + return ChannelType; + } + + static Text getVersionTypeText() { + String type = const String.fromEnvironment('version_type'); + + if (type == "stable") { + return Text(i18n.Format("settings.advanced.channel.stable"), style: TextStyle( color: Colors.lightGreen, ), textAlign: TextAlign.center); - } else if (type == "beta") { - return Text(i18n.Format("edit.instance.mods.beta"), + } else if (type == "dev") { + return Text(i18n.Format("settings.advanced.channel.dev"), style: TextStyle(color: Colors.lightBlue, fontSize: 20), textAlign: TextAlign.center); - } else if (type == "alpha") { - return Text(i18n.Format("edit.instance.mods.alpha"), + } else if (type == "debug") { + return Text(i18n.Format("settings.advanced.channel.debug"), style: TextStyle(color: Colors.red, fontSize: 20), textAlign: TextAlign.center); } else { diff --git a/lib/Screen/About.dart b/lib/Screen/About.dart index d6014e5d..99951e26 100644 --- a/lib/Screen/About.dart +++ b/lib/Screen/About.dart @@ -43,7 +43,7 @@ class AboutScreen_ extends State { children: [ Text(i18n.Format("about.version.type") + " ", style: title_, textAlign: TextAlign.center), - LauncherInfo.getVersionType(), + LauncherInfo.getVersionTypeText(), ], ), Text( diff --git a/lib/Screen/CurseForgeModVersion.dart b/lib/Screen/CurseForgeModVersion.dart new file mode 100644 index 00000000..5ce6eb98 --- /dev/null +++ b/lib/Screen/CurseForgeModVersion.dart @@ -0,0 +1,290 @@ +import 'dart:io'; +import 'dart:isolate'; + +import 'package:rpmlauncher/Mod/CurseForge/Handler.dart'; +import 'package:rpmlauncher/Utility/Config.dart'; +import 'package:rpmlauncher/Utility/i18n.dart'; +import 'package:rpmlauncher/Utility/utility.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:path/path.dart'; +import 'package:rpmlauncher/main.dart'; + +class CurseForgeModVersion extends StatefulWidget { + late List Files; + late int CurseID; + late Directory ModDir; + late Map InstanceConfig; + + CurseForgeModVersion(Files_, CurseID_, ModDir_, InstanceConfig_) { + Files = Files_; + CurseID = CurseID_; + ModDir = ModDir_; + InstanceConfig = InstanceConfig_; + } + + @override + CurseForgeModVersion_ createState() => + CurseForgeModVersion_(Files, CurseID, ModDir, InstanceConfig); +} + +class CurseForgeModVersion_ extends State { + late List Files; + late int CurseID; + late Directory ModDir; + late Map InstanceConfig; + late List ModFileList; + + List InstalledFiles = []; + + CurseForgeModVersion_(Files_, CurseID_, Directory ModDir_, InstanceConfig_) { + Files = Files_; + CurseID = CurseID_; + ModDir = ModDir_; + InstanceConfig = InstanceConfig_; + ModFileList = ModDir_.listSync().where((file) => file is File).toList(); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(i18n.Format("edit.instance.mods.download.select.version")), + content: Container( + height: MediaQuery.of(context).size.height / 3, + width: MediaQuery.of(context).size.width / 3, + child: ListView.builder( + itemCount: Files.length, + itemBuilder: (BuildContext FileBuildContext, int FileIndex) { + return FutureBuilder( + future: CurseForgeHandler.getFileInfoByVersion( + CurseID, + InstanceConfig["version"], + InstanceConfig["loader"], + Files[FileIndex]["modLoader"], + Files[FileIndex]["projectFileId"]), + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.data == null) { + return Container(); + } else if (snapshot.hasData) { + Map FileInfo = snapshot.data; + + bool IsInstalled = ModFileList.any((file) { + if (utility.murmurhash2(File(file.absolute.path)) == + FileInfo["packageFingerLogger.send"]) { + InstalledFiles.add(file); + return true; + } else { + return false; + } + }); + late Widget InstalledWidget; + + if (IsInstalled) { + InstalledWidget = Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.check), + Text(i18n.Format("edit.instance.mods.installed"), + textAlign: TextAlign.center) + ], + ); + } else { + InstalledWidget = Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.close), + Text( + i18n.Format("edit.instance.mods.uninstalled"), + textAlign: TextAlign.center) + ], + ); + } + + return ListTile( + leading: InstalledWidget, + title: Text( + FileInfo["displayName"].replaceAll(".jar", "")), + subtitle: CurseForgeHandler.ParseReleaseType( + FileInfo["releaseType"]), + onTap: () { + InstalledFiles.forEach((file) { + file.deleteSync(recursive: true); + }); + showDialog( + barrierDismissible: false, + context: context, + builder: (context) => Task( + FileInfo, + ModDir, + InstanceConfig["version"], + InstanceConfig["loader"], + Files[FileIndex]["modLoader"]), + ); + }, + ); + } else { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [CircularProgressIndicator()], + ); + } + }); + })), + actions: [ + IconButton( + icon: Icon(Icons.close_sharp), + tooltip: i18n.Format("gui.close"), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + } +} + +class Task extends StatefulWidget { + late var FileInfo; + late Directory ModDir; + late var VersionID; + late var Loader; + late var FileLoader; + + Task(FileInfo_, ModDir_, VersionID_, Loader_, FileLoader_) { + FileInfo = FileInfo_; + ModDir = ModDir_; + VersionID = VersionID_; + Loader = Loader_; + FileLoader = FileLoader_; + } + + @override + Task_ createState() => Task_(FileInfo, ModDir, VersionID, Loader, FileLoader); +} + +class Task_ extends State { + late var FileInfo; + late Directory ModDir; + late var VersionID; + late var Loader; + late var FileLoader; + + Task_(FileInfo_, ModDir_, VersionID_, Loader_, FileLoader_) { + FileInfo = FileInfo_; + ModDir = ModDir_; + VersionID = VersionID_; + Loader = Loader_; + FileLoader = FileLoader_; + } + + @override + void initState() { + super.initState(); + + File ModFile = File(join(ModDir.absolute.path, FileInfo["fileName"])); + + final url = FileInfo["downloadUrl"]; + Thread(url, ModFile); + + if (Config.GetValue("auto_dependencies")) { + DownloadDependenciesFileInfo(); + } + } + + static double _progress = 0; + static int downloadedLength = 0; + static int contentLength = 0; + + DownloadDependenciesFileInfo() async { + if (FileInfo.containsKey("dependencies")) { + for (var Dependency in FileInfo["dependencies"]) { + List DependencyFileInfo = + await CurseForgeHandler.getAddonFilesByVersion( + Dependency["addonId"], VersionID, Loader, FileLoader); + if (DependencyFileInfo.length < 1) return; + File ModFile = + File(join(ModDir.absolute.path, DependencyFileInfo[0]["fileName"])); + final url = DependencyFileInfo[0]["downloadUrl"]; + Thread(url, ModFile); + } + } + } + + Thread(url, ModFile) async { + var port = ReceivePort(); + var isolate = + await Isolate.spawn(Downloading, [url, ModFile, port.sendPort]); + var exit = ReceivePort(); + isolate.addOnExitListener(exit.sendPort); + exit.listen((message) { + if (message == null) { + // A null message means the isolate exited + } + }); + port.listen((message) { + setState(() { + _progress = message; + }); + }); + } + + static Downloading(List args) async { + String url = args[0]; + File ModFile = args[1]; + SendPort port = args[2]; + final request = Request('GET', Uri.parse(url)); + final StreamedResponse response = await Client().send(request); + contentLength += response.contentLength!; + List bytes = []; + response.stream.listen( + (List newBytes) { + bytes.addAll(newBytes); + downloadedLength += newBytes.length; + port.send(downloadedLength / contentLength); + }, + onDone: () async { + await ModFile.writeAsBytes(bytes); + }, + onError: (e) { + logger.send(e); + }, + cancelOnError: true, + ); + } + + @override + Widget build(BuildContext context) { + if (_progress == 1) { + return AlertDialog( + title: Text(i18n.Format("gui.download.done")), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + }, + child: Text(i18n.Format("gui.close"))) + ], + ); + } else { + return AlertDialog( + title: Text( + "${i18n.Format("gui.download.ing")} ${FileInfo["displayName"].replaceAll(".jar", "")}"), + content: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Text("${(_progress * 100).toStringAsFixed(3)}%"), + LinearProgressIndicator(value: _progress) + ], + ), + ); + } + } +} diff --git a/lib/Screen/DownloadCurseModPack.dart b/lib/Screen/DownloadCurseModPack.dart new file mode 100644 index 00000000..5d26079c --- /dev/null +++ b/lib/Screen/DownloadCurseModPack.dart @@ -0,0 +1,260 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:rpmlauncher/Launcher/GameRepository.dart'; +import 'package:rpmlauncher/Launcher/MinecraftClient.dart'; +import 'package:rpmlauncher/Mod/CurseForge/Handler.dart'; +import 'package:rpmlauncher/Mod/CurseForge/ModPackClient.dart'; +import 'package:rpmlauncher/Utility/ModLoader.dart'; +import 'package:rpmlauncher/Utility/i18n.dart'; +import 'package:archive/archive.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:http/http.dart'; +import 'package:path/path.dart'; + +import '../main.dart'; + +class DownloadCurseModPack extends StatefulWidget { + late Archive PackArchive; + late var ModPackIconUrl; + + DownloadCurseModPack(Archive PackArchive_, ModPackIconUrl_) { + PackArchive = PackArchive_; + ModPackIconUrl = ModPackIconUrl_; + } + + @override + DownloadCurseModPack_ createState() => + DownloadCurseModPack_(PackArchive, ModPackIconUrl); +} + +class DownloadCurseModPack_ extends State { + late Archive PackArchive; + late var ModPackIconUrl; + late Map PackMeta; + Color BorderColour = Colors.red; + TextEditingController NameController = TextEditingController(); + Directory InstanceDir = GameRepository.getInstanceRootDir(); + + DownloadCurseModPack_(Archive PackArchive_, ModPackIconUrl_) { + PackArchive = PackArchive_; + ModPackIconUrl = ModPackIconUrl_; + } + + @override + void initState() { + super.initState(); + for (final archiveFile in PackArchive) { + if (archiveFile.isFile && archiveFile.name == "manifest.json") { + final data = archiveFile.content as List; + PackMeta = json.decode(Utf8Decoder(allowMalformed: true).convert(data)); + NameController.text = PackMeta["name"]; + } + } + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + scrollable: true, + title: Text("新增模組包", textAlign: TextAlign.center), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Text(i18n.Format("edit.instance.homepage.instance.name"), + style: TextStyle(fontSize: 18, color: Colors.amberAccent)), + Expanded( + child: TextField( + decoration: InputDecoration( + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: BorderColour, width: 5.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: BorderColour, width: 3.0), + ), + ), + controller: NameController, + textAlign: TextAlign.center, + onChanged: (value) { + if (value == "" && + File(join(InstanceDir.absolute.path, value, + "instance.json")) + .existsSync()) { + BorderColour = Colors.red; + } else { + BorderColour = Colors.lightBlue; + } + setState(() {}); + }, + ), + ) + ], + ), + SizedBox( + height: 12, + ), + Text("模組包名稱: ${PackMeta["name"]}"), + Text("模組包版本: ${PackMeta["version"]}"), + Text("模組包遊戲版本: ${PackMeta["minecraft"]["version"]}"), + Text("模組包作者: ${PackMeta["author"]}"), + ], + ), + actions: [ + TextButton( + child: Text(i18n.Format("gui.cancel")), + onPressed: () { + BorderColour = Colors.lightBlue; + Navigator.of(context).pop(); + }, + ), + TextButton( + child: Text(i18n.Format("gui.confirm")), + onPressed: () async { + String LoaderID = PackMeta["minecraft"]["modLoaders"][0]["id"]; + bool isFabric = LoaderID.startsWith(ModLoader().Fabric); + + String VersionID = PackMeta["minecraft"]["version"]; + String LoaderVersionID = LoaderID.split( + "${isFabric ? ModLoader().Fabric : ModLoader().Forge}-") + .join(""); + + final url = Uri.parse( + await CurseForgeHandler.getMCVersionMetaUrl(VersionID)); + Response response = await get(url); + Map Meta = jsonDecode(response.body); + var NewInstanceConfig = { + "name": NameController.text, + "version": VersionID, + "loader": isFabric ? ModLoader().Fabric : ModLoader().Forge, + "java_version": Meta.containsKey('javaVersion') + ? Meta["javaVersion"]["majorVersion"] + : 8, + "loader_version": LoaderVersionID, + 'play_time': 0 + }; + File(join(InstanceDir.absolute.path, NameController.text, + "instance.json")) + ..createSync(recursive: true) + ..writeAsStringSync(json.encode(NewInstanceConfig)); + + if (ModPackIconUrl != "") { + await http + .get(Uri.parse(ModPackIconUrl)) + .then((response) async { + await File(join(InstanceDir.absolute.path, + NameController.text, "icon.png")) + .writeAsBytes(response.bodyBytes); + }); + } + + Navigator.of(context).pop(); + Navigator.push( + context, + new MaterialPageRoute(builder: (context) => LauncherHome()), + ); + + showDialog( + context: context, + builder: (BuildContext context) { + return Task(Meta, VersionID, LoaderVersionID, + NameController.text, PackMeta, PackArchive); + }); + }) + ], + ); + } +} + +class Task extends StatefulWidget { + late var Meta; + late var VersionID; + late var LoaderVersionID; + late var InstanceDirName; + late var PackMeta; + late var PackArchive; + + Task(Meta_, VersionID_, LoaderVersionID_, InstanceDirName_, PackMeta_, + PackArchive_) { + Meta = Meta_; + VersionID = VersionID_; + LoaderVersionID = LoaderVersionID_; + InstanceDirName = InstanceDirName_; + PackMeta = PackMeta_; + PackArchive = PackArchive_; + } + + @override + Task_ createState() => Task_( + Meta, VersionID, LoaderVersionID, InstanceDirName, PackMeta, PackArchive); +} + +class Task_ extends State { + late var Meta; + late var VersionID; + late var LoaderVersionID; + late var InstanceDirName; + late var PackMeta; + late var PackArchive; + + Task_(Meta_, VersionID_, LoaderVersionID_, InstanceDirName_, PackMeta_, + PackArchive_) { + Meta = Meta_; + VersionID = VersionID_; + LoaderVersionID = LoaderVersionID_; + InstanceDirName = InstanceDirName_; + PackMeta = PackMeta_; + PackArchive = PackArchive_; + } + + @override + void initState() { + super.initState(); + CurseModPackClient.createClient( + setState: setState, + Meta: Meta, + VersionID: VersionID, + LoaderVersion: LoaderVersionID, + InstanceDirName: InstanceDirName, + PackMeta: PackMeta, + PackArchive: PackArchive); + } + + @override + Widget build(BuildContext context) { + if (Progress == 1) { + return AlertDialog( + contentPadding: const EdgeInsets.all(16.0), + title: Text(i18n.Format("gui.download.done")), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(i18n.Format("gui.close"))) + ], + ); + } else { + return WillPopScope( + onWillPop: () => Future.value(false), + child: AlertDialog( + contentPadding: const EdgeInsets.all(16.0), + title: Text(NowEvent, textAlign: TextAlign.center), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + LinearProgressIndicator( + value: Progress, + ), + Text("${(Progress * 100).toStringAsFixed(2)}%") + ], + ), + actions: [], + ), + ); + } + } +} diff --git a/lib/Screen/FabricVersion.dart b/lib/Screen/FabricVersion.dart new file mode 100644 index 00000000..cc83a296 --- /dev/null +++ b/lib/Screen/FabricVersion.dart @@ -0,0 +1,65 @@ +import 'package:rpmlauncher/Launcher/Fabric/FabricAPI.dart'; +import 'package:rpmlauncher/Utility/ModLoader.dart'; +import 'package:rpmlauncher/Utility/i18n.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:rpmlauncher/Widget/AddInstance.dart'; + + +FabricVersion(BorderColour, NameController, Data, ModLoaderName, context) { + return AlertDialog( + title: Text(i18n.Format("version.list.mod.loader.fabric.version"), + textAlign: TextAlign.center), + content: Container( + height: MediaQuery.of(context).size.height / 3, + width: MediaQuery.of(context).size.width / 3, + child: FutureBuilder( + future: FabricAPI().GetLoaderVersions(Data["id"]), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + return ListView.builder( + shrinkWrap: true, + itemCount: snapshot.data.length, + itemBuilder: (BuildContext context, int index) { + Map FabricMeta = snapshot.data[index]; + late Text SubtitleText; + bool IsStable = FabricMeta["loader"]["stable"]; + if (IsStable) { + SubtitleText = Text( + i18n.Format("edit.instance.mods.release"), + textAlign: TextAlign.center, + style: TextStyle(color: Colors.lightBlue)); + } else { + SubtitleText = Text( + i18n.Format("edit.instance.mods.beta"), + textAlign: TextAlign.center, + style: TextStyle(color: Colors.red)); + } + + return Material( + child: ListTile( + title: Text(FabricMeta["loader"]["version"], + textAlign: TextAlign.center), + subtitle: SubtitleText, + onTap: () { + showDialog( + context: context, + builder: (context) => AddInstanceDialog( + BorderColour, + NameController, + Data, + ModLoader().Fabric, + FabricMeta["loader"]["version"], + ), + ); + }, + ), + ); + }); + } else { + return Center(child: CircularProgressIndicator()); + } + }, + ), + )); +} diff --git a/lib/Screen/ForgeVersion.dart b/lib/Screen/ForgeVersion.dart new file mode 100644 index 00000000..7ebbf959 --- /dev/null +++ b/lib/Screen/ForgeVersion.dart @@ -0,0 +1,67 @@ +import 'package:rpmlauncher/Launcher/Forge/ForgeAPI.dart'; +import 'package:rpmlauncher/Utility/ModLoader.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:rpmlauncher/Utility/i18n.dart'; +import 'package:rpmlauncher/Utility/utility.dart'; +import 'package:rpmlauncher/Widget/AddInstance.dart'; + + +ForgeVersion(BorderColour, NameController, Data, ModLoaderName, context) { + return AlertDialog( + title: Text(i18n.Format('version.list.mod.loader.forge.version'), + textAlign: TextAlign.center), + content: Container( + height: MediaQuery.of(context).size.height / 3, + width: MediaQuery.of(context).size.width / 3, + child: FutureBuilder( + future: ForgeAPI.getAllLoaderVersion(Data["id"]), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + return ListView.builder( + shrinkWrap: true, + itemCount: snapshot.data.length, + itemBuilder: (BuildContext context, int index) { + String ForgeVersionID = snapshot.data[index] + .toString() + .split("${Data["id"]}-") + .join(""); + + return Material( + child: ListTile( + title: + Text(ForgeVersionID, textAlign: TextAlign.center), + subtitle: Builder(builder: (context) { + if (index == 0) { + return Text( + i18n.Format( + 'version.list.mod.loader.forge.version.latest'), + textAlign: TextAlign.center, + style: + TextStyle(color: Colors.lightGreenAccent)); + } else { + return Container(); + } + }), + onTap: () { + showDialog( + context: context, + builder: (context) => AddInstanceDialog( + BorderColour, + NameController, + Data, + ModLoader().Forge, + ForgeVersionID, + ), + ); + }, + ), + ); + }); + } else { + return Center(child: CircularProgressIndicator()); + } + }, + ), + )); +} diff --git a/lib/Screen/Settings.dart b/lib/Screen/Settings.dart index 6bca7cf6..c9b88e27 100644 --- a/lib/Screen/Settings.dart +++ b/lib/Screen/Settings.dart @@ -370,19 +370,19 @@ class SettingScreen_ extends State { value: UpdateChannel, items: [ DropdownMenuItem( - value: UpdateChannels.stable, - child: Text(Updater.toI18nString(UpdateChannels.stable)), + value: VersionTypes.stable, + child: Text(Updater.toI18nString(VersionTypes.stable)), ), DropdownMenuItem( - value: UpdateChannels.dev, - child: Text(Updater.toI18nString(UpdateChannels.dev)), + value: VersionTypes.dev, + child: Text(Updater.toI18nString(VersionTypes.dev)), ), ], onChanged: (dynamic Channel) async { setState(() { UpdateChannel = Channel; Config.Change( - 'update_channel', Updater.toStringFromChannelType(Channel)); + 'update_channel', Updater.toStringFromVersionType(Channel)); }); }), ), @@ -558,8 +558,8 @@ class SettingScreen_ extends State { } int ThemeValue = Config.GetValue('theme_id'); -UpdateChannels UpdateChannel = - Updater.getChannelFromString(Config.GetValue('update_channel')); +VersionTypes UpdateChannel = + Updater.getVersionTypeFromString(Config.GetValue('update_channel')); class SettingScreen extends StatefulWidget { @override diff --git a/lib/Utility/Updater.dart b/lib/Utility/Updater.dart index 06b2f306..501da82b 100644 --- a/lib/Utility/Updater.dart +++ b/lib/Utility/Updater.dart @@ -14,7 +14,7 @@ import 'package:rpmlauncher/Utility/i18n.dart'; import 'package:rpmlauncher/Widget/OkClose.dart'; import 'package:rpmlauncher/path.dart'; -enum UpdateChannels { stable, dev } +enum VersionTypes { stable, dev, debug } extension WindowsPaser on Platform { bool isWindows10() => Platform.operatingSystemVersion.contains('10'); @@ -27,58 +27,70 @@ class Updater { static final String _updateUrl = "https://raw.githubusercontent.com/RPMTW/RPMTW-website-data/main/data/RPMLauncher/update.json"; - static String toI18nString(UpdateChannels channel) { + static String toI18nString(VersionTypes channel) { switch (channel) { - case UpdateChannels.stable: + case VersionTypes.stable: return i18n.Format('settings.advanced.channel.stable'); - case UpdateChannels.dev: + case VersionTypes.dev: return i18n.Format('settings.advanced.channel.dev'); + case VersionTypes.debug: + return i18n.Format('settings.advanced.channel.debug'); default: return "stable"; } } - static String toStringFromChannelType(UpdateChannels channel) { + static String toStringFromVersionType(VersionTypes channel) { switch (channel) { - case UpdateChannels.stable: + case VersionTypes.stable: return "stable"; - case UpdateChannels.dev: + case VersionTypes.dev: return "dev"; + case VersionTypes.debug: + return "debug"; default: return "stable"; } } - static UpdateChannels getChannelFromString(String channel) { + static VersionTypes getVersionTypeFromString(String channel) { switch (channel) { case "stable": - return UpdateChannels.stable; + return VersionTypes.stable; case "dev": - return UpdateChannels.dev; + return VersionTypes.dev; default: - return UpdateChannels.stable; + return VersionTypes.stable; } } - static bool isStable(UpdateChannels channel) { - return channel == UpdateChannels.stable; + static bool isStable(VersionTypes channel) { + return channel == VersionTypes.stable; } - static bool isDev(UpdateChannels channel) { - return channel == UpdateChannels.dev; + static bool isDev(VersionTypes channel) { + return channel == VersionTypes.dev; } static bool versionCompareTo(String a, String b) { + if (LauncherInfo.getVersionType() == VersionTypes.debug) { + return false; + } + int aInt = int.parse(a.split(".").join("")); int bInt = int.parse(b.split(".").join("")); return aInt > bInt; } static bool versionCodeCompareTo(String a, int b) { + if (LauncherInfo.getVersionType() == VersionTypes.debug) { + return false; + } + return int.parse(a) > b; } - static Future checkForUpdate(UpdateChannels channel) async { + static Future checkForUpdate(VersionTypes channel) async { http.Response response = await http.get(Uri.parse(_updateUrl)); Map data = json.decode(response.body); Map VersionList = data['version_list']; @@ -289,7 +301,7 @@ class Updater { class VersionInfo { final DownloadUrl? downloadUrl; - final UpdateChannels? type; + final VersionTypes? type; final String? changelog; final List? changelogWidgets; final String? versionCode; @@ -325,7 +337,7 @@ class VersionInfo { return VersionInfo( downloadUrl: DownloadUrl.fromJson(json['download_url']), changelog: changelogs.reversed.toList().join(" \n"), - type: Updater.getChannelFromString(json['type']), + type: Updater.getVersionTypeFromString(json['type']), versionCode: version_code, version: version, needUpdate: needUpdate, diff --git a/lib/main.dart b/lib/main.dart index 51f52315..0baf4b19 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -159,8 +159,8 @@ class _HomePageState extends State { })); }); } else { - UpdateChannels UpdateChannel = - Updater.getChannelFromString(Config.GetValue('update_channel')); + VersionTypes UpdateChannel = + Updater.getVersionTypeFromString(Config.GetValue('update_channel')); Updater.checkForUpdate(UpdateChannel).then((VersionInfo info) { if (info.needUpdate == true) {