Navbar wireup (#98)

* Navbar wireup

* Fix height issue

* Fix syncing

* working branch

* Added root directories to breadcrumbs

* fix jre detect

---------

Co-authored-by: Jai A <jaiagr+gpg@pm.me>
This commit is contained in:
Adrian O.V
2023-04-26 23:19:37 -04:00
committed by GitHub
parent f0b8a708a3
commit bda63d5d64
29 changed files with 631 additions and 299 deletions

View File

@@ -1,6 +1,7 @@
//! Theseus metadata
use crate::data::DirectoryInfo;
use crate::util::fetch::{read_json, write};
use crate::State;
use daedalus::{
minecraft::{fetch_version_manifest, VersionManifest as MinecraftManifest},
modded::{
@@ -96,7 +97,7 @@ impl Metadata {
pub async fn update() {
let res = async {
let metadata_fetch = Metadata::fetch().await?;
let state = crate::State::get().await?;
let state = State::get().await?;
let metadata_path =
state.directories.caches_meta_dir().join("metadata.json");

View File

@@ -164,7 +164,8 @@ impl Profile {
let paths = self.get_profile_project_paths()?;
let projects = crate::state::infer_data_from_files(
&[(self.clone(), paths)],
self.clone(),
paths,
state.directories.caches_dir(),
&state.io_semaphore,
)
@@ -386,31 +387,28 @@ impl Profiles {
}
}
if !files.is_empty() {
let inferred = super::projects::infer_data_from_files(
&files,
state.directories.caches_dir(),
&state.io_semaphore,
)
.await?;
let mut wipe_profiles = Vec::new();
for (key, value) in inferred {
if let Some((profile, _)) =
files.iter().find(|(_, files)| files.contains(&key))
future::try_join_all(files.into_iter().map(
|(profile, files)| async {
let profile_path = profile.path.clone();
let inferred = super::projects::infer_data_from_files(
profile,
files,
state.directories.caches_dir(),
&state.io_semaphore,
)
.await?;
let mut new_profiles = state.profiles.write().await;
if let Some(profile) = new_profiles.0.get_mut(&profile_path)
{
let mut new_profiles = state.profiles.write().await;
if let Some(profile) =
new_profiles.0.get_mut(&profile.path)
{
if !wipe_profiles.contains(&profile.path) {
profile.projects = HashMap::new();
wipe_profiles.push(profile.path.clone());
}
profile.projects.insert(key, value);
}
profile.projects = inferred;
}
}
}
drop(new_profiles);
Ok::<(), crate::Error>(())
},
))
.await?;
Ok::<(), crate::Error>(())
}

View File

@@ -1,7 +1,6 @@
//! Project management + inference
use crate::config::MODRINTH_API_URL;
use crate::data::ModLoader;
use crate::state::Profile;
use crate::util::fetch::{fetch_json, write_cached_icon};
use async_zip::tokio::read::fs::ZipFileReader;
@@ -250,36 +249,51 @@ async fn read_icon_from_file(
}
pub async fn infer_data_from_files(
paths: &[(Profile, Vec<PathBuf>)],
profile: Profile,
paths: Vec<PathBuf>,
cache_dir: PathBuf,
io_semaphore: &RwLock<Semaphore>,
) -> crate::Result<HashMap<PathBuf, Project>> {
let mut file_path_hashes = HashMap::new();
// TODO: Make this concurrent and use progressive hashing to avoid loading each JAR in memory
for set in paths {
for path in &set.1 {
let mut file = tokio::fs::File::open(path.clone()).await?;
for path in paths {
let mut file = tokio::fs::File::open(path.clone()).await?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer).await?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer).await?;
let hash = format!("{:x}", sha2::Sha512::digest(&buffer));
file_path_hashes.insert(hash, path.clone());
}
let hash = format!("{:x}", sha2::Sha512::digest(&buffer));
file_path_hashes.insert(hash, path.clone());
}
let files: HashMap<String, ModrinthVersion> = fetch_json(
Method::POST,
&format!("{}version_files", MODRINTH_API_URL),
None,
Some(json!({
"hashes": file_path_hashes.keys().collect::<Vec<_>>(),
"algorithm": "sha512",
})),
io_semaphore,
)
.await?;
let files_url = format!("{}version_files", MODRINTH_API_URL);
let updates_url = format!("{}version_files/update", MODRINTH_API_URL);
let (files, update_versions) = tokio::try_join!(
fetch_json::<HashMap<String, ModrinthVersion>>(
Method::POST,
&files_url,
None,
Some(json!({
"hashes": file_path_hashes.keys().collect::<Vec<_>>(),
"algorithm": "sha512",
})),
io_semaphore,
),
fetch_json::<HashMap<String, ModrinthVersion>>(
Method::POST,
&updates_url,
None,
Some(json!({
"hashes": file_path_hashes.keys().collect::<Vec<_>>(),
"algorithm": "sha512",
"loaders": [profile.metadata.loader],
"game_versions": [profile.metadata.game_version]
})),
io_semaphore,
)
)?;
let projects: Vec<ModrinthProject> = fetch_json(
Method::GET,
&format!(
@@ -297,6 +311,7 @@ pub async fn infer_data_from_files(
io_semaphore,
)
.await?;
let teams: Vec<ModrinthTeamMember> = fetch_json::<
Vec<Vec<ModrinthTeamMember>>,
>(
@@ -317,26 +332,6 @@ pub async fn infer_data_from_files(
.flatten()
.collect();
let mut update_versions: Vec<ModrinthVersion> = fetch_json(
Method::GET,
&format!(
"{}versions?ids={}",
MODRINTH_API_URL,
serde_json::to_string(
&projects
.iter()
.flat_map(|x| x.versions.clone())
.collect::<Vec<String>>()
)?
),
None,
None,
io_semaphore,
)
.await?;
update_versions.sort_by(|a, b| b.date_published.cmp(&a.date_published));
let mut return_projects = HashMap::new();
let mut further_analyze_projects: Vec<(String, PathBuf)> = Vec::new();
@@ -345,8 +340,6 @@ pub async fn infer_data_from_files(
if let Some(project) =
projects.iter().find(|x| version.project_id == x.id)
{
let profile = paths.iter().find(|x| x.1.contains(&path));
let file_name = path
.file_name()
.unwrap_or_default()
@@ -356,7 +349,6 @@ pub async fn infer_data_from_files(
return_projects.insert(
path,
Project {
sha512: hash,
disabled: false,
metadata: ProjectMetadata::Modrinth {
project: Box::new(project.clone()),
@@ -366,48 +358,25 @@ pub async fn infer_data_from_files(
.filter(|x| x.team_id == project.team)
.cloned()
.collect::<Vec<_>>(),
update_version: if let Some((profile, _)) = &profile
update_version: if let Some(val) =
update_versions.get(&hash)
{
update_versions
.iter()
.find(|x| {
x.project_id == project.id
&& x.game_versions.contains(
&profile.metadata.game_version,
)
&& if profile.metadata.loader
== ModLoader::Vanilla
{
true
} else {
x.loaders.contains(
&profile
.metadata
.loader
.as_api_str()
.to_string(),
)
}
})
.cloned()
.map(Box::new)
Some(Box::new(val.clone()))
} else {
None
},
incompatible: if let Some((profile, _)) = &profile {
!version.loaders.contains(
&profile
.metadata
.loader
.as_api_str()
.to_string(),
) || version
.game_versions
.contains(&profile.metadata.game_version)
} else {
false
},
incompatible: !version.loaders.contains(
&profile
.metadata
.loader
.as_api_str()
.to_string(),
) || version
.game_versions
.contains(&profile.metadata.game_version),
},
sha512: hash,
file_name,
},
);