forked from akanyan/STARTLINER
132 lines
3.9 KiB
Rust
132 lines
3.9 KiB
Rust
use std::hash::{DefaultHasher, Hash, Hasher};
|
|
use crate::model::config::GlobalConfig;
|
|
use crate::model::patch::PatchFileVec;
|
|
use crate::pkg::{Feature, Status};
|
|
use crate::profiles::Profile;
|
|
use crate::{model::misc::Game, pkg::PkgKey};
|
|
use crate::pkg_store::PackageStore;
|
|
use crate::util;
|
|
use anyhow::{anyhow, Result};
|
|
use tauri::AppHandle;
|
|
|
|
pub struct GlobalState {
|
|
pub remain_open: bool,
|
|
}
|
|
|
|
pub struct AppData {
|
|
pub profile: Option<Profile>,
|
|
pub pkgs: PackageStore,
|
|
pub cfg: GlobalConfig,
|
|
pub state: GlobalState,
|
|
pub patch_set: PatchFileVec,
|
|
}
|
|
|
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
|
pub enum ToggleAction {
|
|
Disable,
|
|
EnableSelf,
|
|
EnableRecursive,
|
|
}
|
|
|
|
impl AppData {
|
|
pub fn new(apph: AppHandle) -> AppData {
|
|
let cfg = std::fs::read_to_string(util::config_dir().join("config.json"))
|
|
.and_then(|s| Ok(serde_json::from_str::<GlobalConfig>(&s)?))
|
|
.unwrap_or_default();
|
|
|
|
let profile = match cfg.recent_profile {
|
|
Some((game, ref name)) => Profile::load(game, name.clone()).ok(),
|
|
None => None
|
|
};
|
|
|
|
let patch_set = PatchFileVec::new(util::config_dir())
|
|
.map_err(|e| log::error!("unable to load patch set: {e}"))
|
|
.unwrap_or_default();
|
|
|
|
log::debug!("Recent profile: {:?}", profile);
|
|
|
|
AppData {
|
|
profile: profile,
|
|
pkgs: PackageStore::new(apph.clone()),
|
|
cfg,
|
|
state: GlobalState { remain_open: true },
|
|
patch_set
|
|
}
|
|
}
|
|
|
|
pub fn write(&self) -> Result<(), std::io::Error> {
|
|
std::fs::write(util::config_dir().join("config.json"), serde_json::to_string_pretty(&self.cfg)?)
|
|
}
|
|
|
|
pub fn switch_profile(&mut self, game: Game, name: String) -> Result<()> {
|
|
match Profile::load(game.clone(), name.clone()) {
|
|
Ok(profile) => {
|
|
self.profile = Some(profile);
|
|
self.cfg.recent_profile = Some((game, name));
|
|
self.write()?;
|
|
Ok(())
|
|
}
|
|
Err(e) => {
|
|
self.profile = None;
|
|
self.cfg.recent_profile = None;
|
|
Err(e)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn toggle_package(&mut self, key: PkgKey, action: ToggleAction) -> Result<()> {
|
|
log::debug!("toggle: {} {:?}", key, action);
|
|
|
|
let profile = self.profile.as_mut().ok_or_else(|| anyhow!("No profile"))?;
|
|
|
|
if action != ToggleAction::Disable {
|
|
let pkg = self.pkgs.get(&key)?;
|
|
let loc = pkg.loc
|
|
.clone()
|
|
.ok_or_else(|| anyhow!("Attempted to enable a non-existent package"))?;
|
|
|
|
if let Status::OK(feature_set) = loc.status {
|
|
log::debug!("{:?}", feature_set);
|
|
if feature_set.contains(Feature::Mod) {
|
|
profile.mod_pkgs_mut().insert(key);
|
|
}
|
|
}
|
|
if action == ToggleAction::EnableRecursive {
|
|
for d in &loc.dependencies {
|
|
_ = self.toggle_package(d.clone(), action);
|
|
}
|
|
}
|
|
} else {
|
|
profile.mod_pkgs_mut().remove(&key);
|
|
for (ckey, pkg) in self.pkgs.get_all() {
|
|
if let Some(loc) = pkg.loc {
|
|
if loc.dependencies.contains(&key) {
|
|
self.toggle_package(ckey, action)?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn sum_packages(&self, p: &Profile) -> String {
|
|
let mut hasher = DefaultHasher::new();
|
|
for key in p.mod_pkgs().into_iter() {
|
|
if let Ok(pkg) = self.pkgs.get(&key) {
|
|
if let Some(loc) = &pkg.loc {
|
|
key.hash(&mut hasher);
|
|
loc.version.hash(&mut hasher);
|
|
}
|
|
}
|
|
}
|
|
hasher.finish().to_string()
|
|
}
|
|
|
|
pub fn fix(&mut self) {
|
|
if let Some(p) = &mut self.profile {
|
|
p.fix(&self.pkgs);
|
|
}
|
|
}
|
|
}
|