feat: preparations for upcoming 3.6 changes

Added support for the game files structure updating mechanism
form the latest launcher SDK. Also added
new progress bar statuses for applyign hdiff patches
and removing outdated files
This commit is contained in:
Observer KRypt0n_ 2023-04-11 20:08:54 +02:00
parent 4e173fe9b1
commit f66111f8e9
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
20 changed files with 171 additions and 73 deletions

8
Cargo.lock generated
View file

@ -40,8 +40,8 @@ dependencies = [
[[package]]
name = "anime-game-core"
version = "1.5.2"
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.5.2#002bed907fc47c53d18764fb87aec2398413f1a0"
version = "1.6.0"
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.6.0#e08cef50412928cca426534644142de0fe6a8499"
dependencies = [
"anyhow",
"bzip2",
@ -86,8 +86,8 @@ dependencies = [
[[package]]
name = "anime-launcher-sdk"
version = "0.5.14"
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=0.5.14#98de4c7d707ed7428257953526625e8f168f7d84"
version = "0.5.15"
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=0.5.15#5ebd018a5d5bd6fd0e06d0ab9459a7aec53dcd98"
dependencies = [
"anime-game-core",
"anyhow",

View file

@ -17,7 +17,7 @@ glib-build-tools = "0.17"
[dependencies.anime-launcher-sdk]
git = "https://github.com/an-anime-team/anime-launcher-sdk"
tag = "0.5.14"
tag = "0.5.15"
# path = "../anime-launcher-sdk" # ! for dev purposes only

View file

@ -55,7 +55,6 @@ This should be automatically enabled if you're using zh_cn (Chinese) as your sys
| Folder | Description |
| - | - |
| anime-launcher-sdk | Unified core functionality for the launcher |
| src | Rust source code |
| assets | App assets folder |
| assets/locales | App localizations |

View file

@ -40,12 +40,17 @@ downloading = Lade Herunter
unpacking = Entpacken
verifying-files = Verifiziere Dateien
repairing-files = Repariere Dateien
migrating-folders = Migrating folders
applying-hdiff = Applying hdiff patches
removing-outdated = Removing outdated files
components-index-updated = Kompontentenverzeichnis würde aktualisiert
launch = Starten
migrate-folders = Migrate folders
migrate-folders-tooltip = Update game folders structure
apply-patch = Patch anwenden
download-wine = Wine Herunterladen
create-prefix = Prefix erstellen

View file

@ -40,12 +40,17 @@ downloading = Downloading
unpacking = Unpacking
verifying-files = Verifying files
repairing-files = Repairing files
migrating-folders = Migrating folders
applying-hdiff = Applying hdiff patches
removing-outdated = Removing outdated files
components-index-updated = Components index was updated
launch = Launch
migrate-folders = Migrate folders
migrate-folders-tooltip = Update game folders structure
apply-patch = Apply patch
download-wine = Download wine
create-prefix = Create prefix

View file

@ -40,12 +40,17 @@ downloading = Descargando
unpacking = Descomprimiendo
verifying-files = Verificación de archivos
repairing-files = Reparación de archivos
migrating-folders = Migrating folders
applying-hdiff = Applying hdiff patches
removing-outdated = Removing outdated files
components-index-updated = Se actualizó el índice de componentes
launch = Iniciar
migrate-folders = Migrate folders
migrate-folders-tooltip = Update game folders structure
apply-patch = Aplicar parche
download-wine = Descargar wine
create-prefix = Crear prefijo

View file

@ -40,12 +40,17 @@ downloading = Téléchargement
unpacking = Décompression
verifying-files = Vérification des fichiers
repairing-files = Réparation des fichiers
migrating-folders = Migrating folders
applying-hdiff = Applying hdiff patches
removing-outdated = Removing outdated files
components-index-updated = L'index des composants a été mis à jour
launch = Lancer
migrate-folders = Migrate folders
migrate-folders-tooltip = Update game folders structure
apply-patch = Appliquer le patch
download-wine = Télécharger wine
create-prefix = Créer le préfix wine

View file

@ -46,12 +46,17 @@ downloading = Загрузка
unpacking = Распаковка
verifying-files = Проверка файлов
repairing-files = Починка файлов
migrating-folders = Перемещение папок
applying-hdiff = Применение патчей hdiff
removing-outdated = Удаление устаревших файлов
components-index-updated = Индекс компонентов был обновлен
launch = Запустить
migrate-folders = Переместить папки
migrate-folders-tooltip = Обновить структуру файлов игры
apply-patch = Применить патч
download-wine = Установить Wine
create-prefix = Создать префикс

View file

@ -40,12 +40,17 @@ downloading = İndiriliyor
unpacking = Paketten çıkartılıyor
verifying-files = Dosyalar Doğrulanıyor
repairing-files = Dosyalar tamir ediliyor
migrating-folders = Migrating folders
applying-hdiff = Applying hdiff patches
removing-outdated = Removing outdated files
components-index-updated = Components index was updated
launch = Çalıştır
migrate-folders = Migrate folders
migrate-folders-tooltip = Update game folders structure
apply-patch = Yamayı uygula
download-wine = Wine indir
create-prefix = Prefix oluştur

View file

@ -40,12 +40,17 @@ downloading = 正在下载
unpacking = 正在解压缩
verifying-files = 正在检验文件
repairing-files = 正在修复文件
migrating-folders = Migrating folders
applying-hdiff = Applying hdiff patches
removing-outdated = Removing outdated files
components-index-updated = 组件索引已更新
launch = 启动
migrate-folders = Migrate folders
migrate-folders-tooltip = Update game folders structure
apply-patch = 安装补丁
download-wine = 下载 Wine
create-prefix = 创建 Wine prefix

View file

@ -12,9 +12,10 @@ use tracing_subscriber::filter::*;
use std::path::PathBuf;
pub mod move_folder;
pub mod i18n;
pub mod ui;
pub mod background;
pub mod ui;
use ui::main::*;
use ui::first_run::main::*;

26
src/move_folder.rs Normal file
View file

@ -0,0 +1,26 @@
use std::path::Path;
pub fn move_folder(from: &Path, to: &Path) -> std::io::Result<()> {
if !to.exists() {
std::fs::create_dir_all(to)?;
}
for entry in from.read_dir()?.flatten() {
let to_path = to.join(entry.file_name());
if entry.metadata()?.is_dir() {
move_folder(&entry.path(), &to_path)?;
}
else if entry.metadata()?.is_file() {
std::fs::copy(entry.path(), to_path)?;
std::fs::remove_file(entry.path())?;
}
// TODO: symlinks?
}
std::fs::remove_dir_all(from)?;
Ok(())
}

View file

@ -3,8 +3,7 @@ use relm4::component::*;
use adw::prelude::*;
use anime_launcher_sdk::anime_game_core::installer::installer::Update as InstallerUpdate;
use anime_launcher_sdk::anime_game_core::prettify_bytes::prettify_bytes;
use anime_launcher_sdk::anime_game_core::prelude::*;
use crate::i18n::*;
@ -44,7 +43,7 @@ pub enum ProgressBarMsg {
/// (current bytes, total bytes)
UpdateProgress(u64, u64),
UpdateFromState(InstallerUpdate),
UpdateFromState(DiffUpdate),
SetVisible(bool)
}
@ -128,12 +127,36 @@ impl SimpleAsyncComponent for ProgressBar {
ProgressBarMsg::UpdateFromState(state) => {
match state {
InstallerUpdate::CheckingFreeSpace(_) => self.caption = Some(tr("checking-free-space")),
InstallerUpdate::DownloadingStarted(_) => self.caption = Some(tr("downloading")),
InstallerUpdate::UnpackingStarted(_) => self.caption = Some(tr("unpacking")),
DiffUpdate::InstallerUpdate(InstallerUpdate::CheckingFreeSpace(_)) => self.caption = Some(tr("checking-free-space")),
InstallerUpdate::DownloadingProgress(curr, total) |
InstallerUpdate::UnpackingProgress(curr, total) => {
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingStarted(_)) => {
self.caption = Some(tr("downloading"));
self.display_fraction = true;
}
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingStarted(_)) => {
self.caption = Some(tr("unpacking"));
self.display_fraction = true;
}
DiffUpdate::ApplyingHdiffStarted => {
self.caption = Some(tr("applying-hdiff"));
self.display_fraction = false;
}
DiffUpdate::RemovingOutdatedStarted => {
self.caption = Some(tr("removing-outdated"));
self.display_fraction = false;
}
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingProgress(curr, total)) |
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingProgress(curr, total)) |
DiffUpdate::ApplyingHdiffProgress(curr, total) |
DiffUpdate::RemovingOutdatedProgress(curr, total) => {
self.fraction = curr as f64 / total as f64;
self.downloaded = Some((
@ -142,11 +165,14 @@ impl SimpleAsyncComponent for ProgressBar {
));
}
InstallerUpdate::DownloadingFinished => tracing::info!("Downloading finished"),
InstallerUpdate::UnpackingFinished => tracing::info!("Unpacking finished"),
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingFinished) => tracing::info!("Downloading finished"),
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingFinished) => tracing::info!("Unpacking finished"),
InstallerUpdate::DownloadingError(err) => tracing::error!("Downloading error: {:?}", err),
InstallerUpdate::UnpackingError(err) => tracing::error!("Unpacking error: {:?}", err)
DiffUpdate::ApplyingHdiffFinished => tracing::info!("Applying hdiffs finished"),
DiffUpdate::RemovingOutdatedFinished => tracing::info!("Removing outdated files finished"),
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingError(err)) => tracing::error!("Downloading error: {:?}", err),
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingError(err)) => tracing::error!("Unpacking error: {:?}", err)
}
}

View file

@ -9,7 +9,7 @@ use gtk::glib::clone;
use super::progress_bar::ProgressBarMsg;
use anime_launcher_sdk::config;
use anime_launcher_sdk::anime_game_core::installer::installer::*;
use anime_launcher_sdk::anime_game_core::prelude::*;
use std::path::PathBuf;
@ -162,12 +162,12 @@ impl SimpleAsyncComponent for ComponentVersion {
installer.install(download_folder, move |state| {
match &state {
Update::UnpackingFinished |
Update::DownloadingError(_) |
Update::UnpackingError(_) => {
InstallerUpdate::UnpackingFinished |
InstallerUpdate::DownloadingError(_) |
InstallerUpdate::UnpackingError(_) => {
progress_bar_sender.send(ProgressBarMsg::SetVisible(false));
if let Update::UnpackingFinished = &state {
if let InstallerUpdate::UnpackingFinished = &state {
sender.input(AppMsg::SetState(VersionState::Downloaded));
sender.output(super::group::AppMsg::CallOnDownloaded);
}
@ -180,7 +180,7 @@ impl SimpleAsyncComponent for ComponentVersion {
_ => ()
}
progress_bar_sender.send(ProgressBarMsg::UpdateFromState(state));
progress_bar_sender.send(ProgressBarMsg::UpdateFromState(DiffUpdate::InstallerUpdate(state)));
});
}));
}

View file

@ -5,7 +5,7 @@ use adw::prelude::*;
use anime_launcher_sdk::config;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use crate::*;
use crate::i18n::*;
@ -381,30 +381,6 @@ impl SimpleAsyncComponent for DefaultPathsApp {
(old_config.game.enhancements.fps_unlocker.path, &self.fps_unlocker)
];
fn move_folder(from: &Path, to: &Path) -> std::io::Result<()> {
if !to.exists() {
std::fs::create_dir_all(to);
}
for entry in from.read_dir()?.flatten() {
let to_path = to.join(entry.file_name());
if entry.metadata()?.is_dir() {
move_folder(&entry.path(), &to_path)?;
}
else if entry.metadata()?.is_file() {
std::fs::copy(entry.path(), &to_path);
}
// TODO: symlinks?
}
std::fs::remove_dir_all(from)?;
Ok(())
}
#[allow(clippy::expect_fun_call)]
for (i, (from, to)) in folders.iter().enumerate() {
self.progress_bar.sender().send(ProgressBarMsg::UpdateCaption(Some(
@ -412,7 +388,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
)));
if &from != to && from.exists() {
move_folder(from, to).expect(&format!("Failed to move folder: {:?} -> {:?}", from, to));
move_folder::move_folder(from, to).expect(&format!("Failed to move folder: {:?} -> {:?}", from, to));
}
self.progress_bar.sender().send(ProgressBarMsg::UpdateProgress(i as u64 + 1, folders.len() as u64));

View file

@ -3,9 +3,9 @@ use relm4::component::*;
use adw::prelude::*;
use anime_launcher_sdk::anime_game_core::prelude::*;
use anime_launcher_sdk::components::*;
use anime_launcher_sdk::components::wine::WincompatlibWine;
use anime_launcher_sdk::anime_game_core::installer::prelude::*;
use anime_launcher_sdk::config;
use anime_launcher_sdk::wincompatlib::prelude::*;
@ -421,7 +421,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
_ => ()
}
progress_bar_input.send(ProgressBarMsg::UpdateFromState(update));
progress_bar_input.send(ProgressBarMsg::UpdateFromState(DiffUpdate::InstallerUpdate(update)));
});
}
@ -532,7 +532,7 @@ impl SimpleAsyncComponent for DownloadComponentsApp {
_ => ()
}
progress_bar_input.send(ProgressBarMsg::UpdateFromState(update));
progress_bar_input.send(ProgressBarMsg::UpdateFromState(DiffUpdate::InstallerUpdate(update)));
});
}

View file

@ -20,10 +20,9 @@ pub fn download_diff(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
let config = config::get().unwrap();
let game_path = config.game.path.for_edition(config.launcher.edition).to_path_buf();
#[allow(unused_must_use)]
let result = diff.install_to_by(game_path, config.launcher.temp, clone!(@strong sender => move |state| {
match &state {
InstallerUpdate::DownloadingError(err) => {
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingError(err)) => {
tracing::error!("Downloading failed: {err}");
sender.input(AppMsg::Toast {
@ -32,7 +31,7 @@ pub fn download_diff(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
});
}
InstallerUpdate::UnpackingError(err) => {
DiffUpdate::InstallerUpdate(InstallerUpdate::UnpackingError(err)) => {
tracing::error!("Unpacking failed: {err}");
sender.input(AppMsg::Toast {
@ -44,7 +43,9 @@ pub fn download_diff(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
_ => ()
}
progress_bar_input.send(ProgressBarMsg::UpdateFromState(state));
#[allow(unused_must_use)] {
progress_bar_input.send(ProgressBarMsg::UpdateFromState(state));
}
}));
let mut perform_on_download_needed = true;

View file

@ -55,7 +55,6 @@ pub fn download_wine(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
sender.input(AppMsg::SetDownloading(true));
std::thread::spawn(clone!(@strong sender => move || {
#[allow(unused_must_use)]
installer.install(&config.game.wine.builds, clone!(@strong sender => move |state| {
match &state {
InstallerUpdate::DownloadingError(err) => {
@ -79,7 +78,9 @@ pub fn download_wine(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
_ => ()
}
progress_bar_input.send(ProgressBarMsg::UpdateFromState(state));
#[allow(unused_must_use)] {
progress_bar_input.send(ProgressBarMsg::UpdateFromState(DiffUpdate::InstallerUpdate(state)));
}
}));
config.game.wine.selected = Some(wine.name.clone());

View file

@ -0,0 +1,25 @@
use relm4::prelude::*;
use std::path::PathBuf;
use crate::*;
use super::{App, AppMsg};
pub fn migrate_folder(sender: ComponentSender<App>, from: PathBuf, to: PathBuf, cleanup_folder: Option<PathBuf>) {
sender.input(AppMsg::DisableButtons(true));
std::thread::spawn(move || {
move_folder::move_folder(&from, &to).expect("Failed to perform migration");
if let Some(cleanup_folder) = cleanup_folder {
std::fs::remove_dir_all(cleanup_folder).expect("Failed to remove cleanup folder");
}
sender.input(AppMsg::DisableButtons(false));
sender.input(AppMsg::UpdateLauncherState {
perform_on_download_needed: false,
apply_patch_if_needed: false,
show_status_page: true
});
});
}

View file

@ -15,6 +15,7 @@ mod apply_patch;
mod download_wine;
mod create_prefix;
mod download_diff;
mod migrate_folder;
mod launch;
use anime_launcher_sdk::config::launcher::LauncherStyle;
@ -371,18 +372,19 @@ impl SimpleComponent for App {
gtk::Button {
#[watch]
set_label: &match model.state {
Some(LauncherState::Launch) => tr("launch"),
Some(LauncherState::PredownloadAvailable { .. }) => tr("launch"),
Some(LauncherState::UnityPlayerPatchAvailable(_)) => tr("apply-patch"),
Some(LauncherState::XluaPatchAvailable(_)) => tr("apply-patch"),
Some(LauncherState::WineNotInstalled) => tr("download-wine"),
Some(LauncherState::PrefixNotExists) => tr("create-prefix"),
Some(LauncherState::VoiceUpdateAvailable(_)) => tr("update"),
Some(LauncherState::VoiceOutdated(_)) => tr("update"),
Some(LauncherState::VoiceNotInstalled(_)) => tr("download"),
Some(LauncherState::GameUpdateAvailable(_)) => tr("update"),
Some(LauncherState::GameOutdated(_)) => tr("update"),
Some(LauncherState::GameNotInstalled(_)) => tr("download"),
Some(LauncherState::Launch) => tr("launch"),
Some(LauncherState::PredownloadAvailable { .. }) => tr("launch"),
Some(LauncherState::FolderMigrationRequired { .. }) => tr("migrate-folders"),
Some(LauncherState::UnityPlayerPatchAvailable(_)) => tr("apply-patch"),
Some(LauncherState::XluaPatchAvailable(_)) => tr("apply-patch"),
Some(LauncherState::WineNotInstalled) => tr("download-wine"),
Some(LauncherState::PrefixNotExists) => tr("create-prefix"),
Some(LauncherState::VoiceUpdateAvailable(_)) => tr("update"),
Some(LauncherState::VoiceOutdated(_)) => tr("update"),
Some(LauncherState::VoiceNotInstalled(_)) => tr("download"),
Some(LauncherState::GameUpdateAvailable(_)) => tr("update"),
Some(LauncherState::GameOutdated(_)) => tr("update"),
Some(LauncherState::GameNotInstalled(_)) => tr("download"),
None => String::from("...")
},
@ -432,6 +434,8 @@ impl SimpleComponent for App {
Some(LauncherState::GameOutdated { .. }) |
Some(LauncherState::VoiceOutdated(_)) => tr("main-window--version-outdated-tooltip"),
Some(LauncherState::FolderMigrationRequired { .. }) => tr("migrate-folders-tooltip"),
Some(LauncherState::UnityPlayerPatchAvailable(UnityPlayerPatch { status, .. })) |
Some(LauncherState::XluaPatchAvailable(XluaPatch { status, .. })) => match status {
PatchStatus::NotAvailable => tr("main-window--patch-unavailable-tooltip"),
@ -1006,6 +1010,9 @@ impl SimpleComponent for App {
LauncherState::PredownloadAvailable { .. } |
LauncherState::Launch => launch::launch(sender),
LauncherState::FolderMigrationRequired { from, to, cleanup_folder } =>
migrate_folder::migrate_folder(sender, from.to_owned(), to.to_owned(), cleanup_folder.to_owned()),
LauncherState::UnityPlayerPatchAvailable(patch) => apply_patch::apply_patch(sender, patch.to_owned()),
LauncherState::XluaPatchAvailable(patch) => apply_patch::apply_patch(sender, patch.to_owned()),
@ -1016,7 +1023,8 @@ impl SimpleComponent for App {
LauncherState::VoiceUpdateAvailable(diff) |
LauncherState::VoiceNotInstalled(diff) |
LauncherState::GameUpdateAvailable(diff) |
LauncherState::GameNotInstalled(diff) => download_diff::download_diff(sender, self.progress_bar.sender().to_owned(), diff.to_owned()),
LauncherState::GameNotInstalled(diff) =>
download_diff::download_diff(sender, self.progress_bar.sender().to_owned(), diff.to_owned()),
LauncherState::VoiceOutdated(_) |
LauncherState::GameOutdated(_) => ()