Skip to content
This repository has been archived by the owner on Jun 28, 2023. It is now read-only.

Commit

Permalink
新功能:版本檢測、下載新版本(自動更新尚未實裝)
Browse files Browse the repository at this point in the history
  • Loading branch information
SiongSng committed Sep 12, 2021
1 parent be9b030 commit c7f4c04
Show file tree
Hide file tree
Showing 8 changed files with 372 additions and 26 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/Build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ on:
push:
branches:
- main
pull_request:
branches:
- main

workflow_dispatch:

Expand Down
2 changes: 2 additions & 0 deletions lang/zh_tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@
"settings.advanced.title": "進階設定",
"settings.advanced.assets.check": "檢查資源檔案完整性",
"settings.advanced.max.log": "遊戲日誌紀錄最大行數",
"settings.advanced.channel.stable": "穩定版更新通道",
"settings.advanced.channel.dev": "開發版更新通道",
"edit.instance.title": "編輯安裝檔",
"edit.instance.homepage.instance.name": "安裝檔名稱: ",
"edit.instance.homepage.instance.enter": "請輸入安裝檔名稱",
Expand Down
71 changes: 48 additions & 23 deletions lib/Screen/Settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:rpmlauncher/Launcher/GameRepository.dart';
import 'package:rpmlauncher/Model/JvmArgs.dart';
import 'package:rpmlauncher/Utility/Config.dart';
import 'package:rpmlauncher/Utility/Theme.dart';
import 'package:rpmlauncher/Utility/Updater.dart';
import 'package:rpmlauncher/Utility/i18n.dart';
import 'package:rpmlauncher/Utility/utility.dart';
import 'package:dynamic_themes/dynamic_themes.dart';
Expand Down Expand Up @@ -224,29 +225,26 @@ class SettingScreen_ extends State<SettingScreen> {
i18n.Format("settings.appearance.theme"),
style: title_,
),
Center(
child: DropdownButton(
value: ThemeValue,
items: [
DropdownMenuItem(
value: ThemeUtility.Light,
child:
Text(ThemeUtility.toI18nString(ThemeUtility.Light)),
),
DropdownMenuItem(
value: ThemeUtility.Dark,
child:
Text(ThemeUtility.toI18nString(ThemeUtility.Dark)),
),
],
onChanged: (dynamic themeId) async {
await DynamicTheme.of(context)!.setTheme(themeId);
setState(() {
ThemeValue = themeId;
Config.Change('theme_id', themeId);
});
}),
),
DropdownButton(
value: ThemeValue,
items: [
DropdownMenuItem(
value: ThemeUtility.Light,
child:
Text(ThemeUtility.toI18nString(ThemeUtility.Light)),
),
DropdownMenuItem(
value: ThemeUtility.Dark,
child: Text(ThemeUtility.toI18nString(ThemeUtility.Dark)),
),
],
onChanged: (dynamic themeId) async {
await DynamicTheme.of(context)!.setTheme(themeId);
setState(() {
ThemeValue = themeId;
Config.Change('theme_id', themeId);
});
}),
Text(
i18n.Format("settings.appearance.window.size.title"),
style: title_,
Expand Down Expand Up @@ -366,6 +364,31 @@ class SettingScreen_ extends State<SettingScreen> {
Config.Change("auto_dependencies", AutoDependencies);
});
}),
Text("RPMLauncher 更新通道", style: title_, textAlign: TextAlign.center),
Center(
child: DropdownButton(
value: UpdateChannel,
items: [
DropdownMenuItem(
value: UpdateChannels.stable,
child: Text(Updater.toI18nString(UpdateChannels.stable)),
),
DropdownMenuItem(
value: UpdateChannels.dev,
child: Text(Updater.toI18nString(UpdateChannels.dev)),
),
],
onChanged: (dynamic Channel) async {
setState(() {
UpdateChannel = Channel;
Config.Change(
'update_channel', Updater.toStringFromChannelType(Channel));
});
}),
),
SizedBox(
height: 12,
),
Row(
children: [
SizedBox(
Expand Down Expand Up @@ -535,6 +558,8 @@ class SettingScreen_ extends State<SettingScreen> {
}

int ThemeValue = Config.GetValue('theme_id');
UpdateChannels UpdateChannel =
Updater.getChannelFromString(Config.GetValue('update_channel'));

class SettingScreen extends StatefulWidget {
@override
Expand Down
1 change: 1 addition & 0 deletions lib/Utility/Config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Config {
"show_log": false,
"auto_dependencies": true,
"theme_id": 0,
"update_channel": "stable"
};

static void Change(String key, value) {
Expand Down
227 changes: 227 additions & 0 deletions lib/Utility/Updater.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import 'dart:convert';
import 'dart:io';

import 'package:archive/archive.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:http/http.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart';
import 'package:rpmlauncher/LauncherInfo.dart';
import 'package:rpmlauncher/Utility/i18n.dart';
import 'package:rpmlauncher/path.dart';

enum UpdateChannels { stable, dev }

class Updater {
static final String _updateUrl =
"https://raw.githubusercontent.com/RPMTW/RPMTW-website-data/main/data/RPMLauncher/update.json";

static String toI18nString(UpdateChannels channel) {
switch (channel) {
case UpdateChannels.stable:
return i18n.Format('settings.advanced.channel.stable');
case UpdateChannels.dev:
return i18n.Format('settings.advanced.channel.dev');
default:
return "stable";
}
}

static String toStringFromChannelType(UpdateChannels channel) {
switch (channel) {
case UpdateChannels.stable:
return "stable";
case UpdateChannels.dev:
return "dev";
default:
return "stable";
}
}

static UpdateChannels getChannelFromString(String channel) {
switch (channel) {
case "stable":
return UpdateChannels.stable;
case "dev":
return UpdateChannels.dev;
default:
return UpdateChannels.stable;
}
}

static bool isStable(UpdateChannels channel) {
return channel == UpdateChannels.stable;
}

static bool isDev(UpdateChannels channel) {
return channel == UpdateChannels.dev;
}

static bool versionCompareTo(String a, String b) {
int aInt = int.parse(a.split(".").join(""));
int bInt = int.parse(b.split(".").join(""));
return (aInt > bInt) || (aInt == bInt);
}

static bool versionCodeCompareTo(String a, int b) {
return int.parse(a) > b;
}

static Future<VersionInfo> checkForUpdate(UpdateChannels channel) async {
http.Response response = await http.get(Uri.parse(_updateUrl));
Map data = json.decode(response.body);
Map VersionList = data['version_list'];

bool needUpdate(Map data) {
String latestVersion = data['latest_version'];
String latestVersionCode = data['latest_version_code'];
bool mainVersionCheck =
versionCompareTo(latestVersion, LauncherInfo.getVersion());

bool versionCodeCheck = versionCodeCompareTo(
latestVersionCode, LauncherInfo.getVersionCode());

bool needUpdate =
mainVersionCheck || (mainVersionCheck && versionCodeCheck);

return needUpdate;
}

VersionInfo getVersionInfo(Map data) {
String latestVersion = data['latest_version'];
String latestVersionCode = data['latest_version_code'];
return VersionInfo.fromJson(VersionList[latestVersion][latestVersionCode],
latestVersionCode, latestVersion, VersionList, needUpdate(data));
}

if (isStable(channel)) {
Map stable = data['stable'];
return getVersionInfo(stable);
} else if (isDev(channel)) {
Map dev = data['dev'];
return getVersionInfo(dev);
} else {
return VersionInfo(needUpdate: false);
}
}

static Future<void> update(VersionInfo info) async {
Directory updateDir = Directory(join(dataHome.absolute.path, "update"));

String operatingSystem = Platform.operatingSystem;
String downloadUrl;

switch (operatingSystem) {
case "linux":
downloadUrl = info.downloadUrl!.linux;
break;
case "windows":
String OSVersion = Platform.operatingSystemVersion;
if (OSVersion.contains('10') || OSVersion.contains('11')) {
//Windows 10/11
downloadUrl = info.downloadUrl!.windows_10_11;
} else if (OSVersion.contains('7')) {
//Windows 7
downloadUrl = info.downloadUrl!.windows_7;
} else {
throw Exception("Unsupported OS");
}
break;
case "macos":
downloadUrl = info.downloadUrl!.macos;
break;
default:
throw Exception("Unknown operating system");
}
Dio dio = Dio();
File updateFile = File(join(updateDir.absolute.path, "update.zip"));
await dio.download(downloadUrl, updateFile.absolute.path,
onReceiveProgress: (count, total) {
print((count / total * 100).toStringAsFixed(2) + "%");
});
Archive archive = ZipDecoder().decodeBytes(updateFile.readAsBytesSync());

for (ArchiveFile file in archive) {
if (file.isFile) {
File(join(updateDir.absolute.path, "unziped", file.name))
..createSync(recursive: true)
..writeAsBytesSync(file.content as List<int>);
} else {
Directory(join(updateDir.absolute.path, "unziped", file.name))
..createSync(recursive: true);
}
}
}
}

class VersionInfo {
final DownloadUrl? downloadUrl;
final UpdateChannels? type;
final String? changelog;
final List<Widget>? changelogWidgets;
final String? versionCode;
final String? version;
final bool needUpdate;

const VersionInfo({
this.downloadUrl,
this.type,
this.versionCode,
this.version,
this.changelog,
this.changelogWidgets,
required this.needUpdate,
});
factory VersionInfo.fromJson(Map json, String version_code, String version,
Map VersionList, bool needUpdate) {
List<String> changelogs = [];
List<Widget> _changelogWidgets = [];
VersionList.keys.forEach((_version) {
VersionList[_version].keys.forEach((_versionCode) {
bool mainVersionCheck = Updater.versionCompareTo(_version, version);
bool versionCodeCheck =
Updater.versionCodeCompareTo(_versionCode, int.parse(version_code));
if (mainVersionCheck || (mainVersionCheck && versionCodeCheck)) {
String _changelog = VersionList[_version][_versionCode]['changelog'];
changelogs.add("\\- " + _changelog);
}
});
});

return VersionInfo(
downloadUrl: DownloadUrl.fromJson(json['download_url']),
changelog: changelogs.join(" \n"),
type: Updater.getChannelFromString(json['type']),
versionCode: version_code,
version: version,
needUpdate: needUpdate,
changelogWidgets: _changelogWidgets);
}

Map<String, dynamic> toJson() => {
'download_url': downloadUrl,
'type': type,
};
}

class DownloadUrl {
final String windows_10_11;
final String windows_7;
final String linux;
final String macos;

const DownloadUrl({
required this.windows_10_11,
required this.windows_7,
required this.linux,
required this.macos,
});
factory DownloadUrl.fromJson(Map json) => DownloadUrl(
windows_10_11: json['windows_10_11'],
windows_7: json['windows_7'],
linux: json['linux'],
macos: json['macos'],
);
}
Loading

0 comments on commit c7f4c04

Please sign in to comment.