mirror of
https://github.com/modrinth/code.git
synced 2026-08-31 12:05:53 +00:00
feat: instances v2 (#6431)
* feat: base of instances v2 * feat: use old profiles with compat layer * prototype: instances v2 * fix: install_from using profile * fix: skins migration fix * fix: frontend still using profile path * fix: add update proj multiselect guard * fix: cargo fmt * fix: content missing fields * feat: break up app-lib/api/instance.rs * fix: check_content_updates mismatch * fix: updater modal cleanup w/new structure * feat: better update all handling * fix: remove preview_update_all * fix: feedback on bulk update + lint * fix: rem transitions * fix: change to jsonb * feat: app db backup after update * fix: lint * fix: sqlx prepare + use sqlx macros * fix: lint * fix: bugs * feat: defuck the installing process up * fix: bug of hell * fix: shear * fix: fmt * fix: install progress spacing + change mc/content/overrides to bytes * fix: lint * fix: prepr * fix: navtabs anim not working in app * fix: worlds.vue improvements + browse page fixes * feat: optimise queries + adapter fns * fix: lint * fix: lint * feat: shared modrinth-content-management crate (#6469) * feat: disable warnings setting * feat: add instances shortcuts (#6329) * Add modrinth://launch deep link to start a profile Support external profile launching via modrinth://launch/{profile_path} for integrations such as Stream Deck. * Change route to /launch/profile/{id} for future extensibility * fix: ensure profile path is url decoded * fix: URL-decode profile path from deep link * fix: use urlencoding crate for URL decoding * feat: implement app instance shortcuts * feat: change windows shortcut creation to use windows api instead * feat: implement creating a shortcut launching world/server * format * fmt * fix multiline inline tables * pnpm prepr * feat: move create shortcut to last item * refactor: split up shortcuts.rs for individual platforms * refactor: turn profile launch url into url type * use string literal and add safety comment * pt2 * refactor: rename anything that's profile into instance * update mac shortcut --------- Co-authored-by: DJCheesusReal <134006619+DJCheesusReal@users.noreply.github.com> --------- Co-authored-by: Truman Gao <106889354+tdgao@users.noreply.github.com> Co-authored-by: DJCheesusReal <134006619+DJCheesusReal@users.noreply.github.com>
This commit is contained in:
co-authored by
DJCheesusReal
Truman Gao
parent
ef4044534f
commit
734720e11e
+170
-23
@@ -1,11 +1,19 @@
|
||||
//! Authentication flow interface
|
||||
use crate::event::emit::{emit_loading, init_loading};
|
||||
use crate::install::{
|
||||
InstallJavaStep, InstallPhaseDetails, InstallPhaseId, InstallProgress,
|
||||
InstallProgressReporter,
|
||||
};
|
||||
use crate::state::JavaVersion;
|
||||
use crate::util::fetch::{fetch_advanced, fetch_json};
|
||||
use crate::util::fetch::{
|
||||
FetchProgressFn, fetch_advanced, fetch_advanced_with_progress, fetch_json,
|
||||
};
|
||||
use dashmap::DashMap;
|
||||
use reqwest::Method;
|
||||
use serde::Deserialize;
|
||||
use std::future::Future;
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
use sysinfo::{MemoryRefreshKind, RefreshKind};
|
||||
|
||||
use crate::util::io;
|
||||
@@ -52,16 +60,77 @@ pub async fn find_filtered_jres(
|
||||
}
|
||||
|
||||
pub async fn auto_install_java(java_version: u32) -> crate::Result<PathBuf> {
|
||||
auto_install_java_with_loading(java_version, true).await
|
||||
}
|
||||
|
||||
pub async fn auto_install_java_with_loading(
|
||||
java_version: u32,
|
||||
show_loading: bool,
|
||||
) -> crate::Result<PathBuf> {
|
||||
auto_install_java_inner(java_version, show_loading, None).await
|
||||
}
|
||||
|
||||
pub async fn auto_install_java_with_reporter(
|
||||
java_version: u32,
|
||||
reporter: InstallProgressReporter,
|
||||
) -> crate::Result<PathBuf> {
|
||||
auto_install_java_inner(java_version, false, Some(reporter)).await
|
||||
}
|
||||
|
||||
const JAVA_INSTALL_STEPS: u64 = 4;
|
||||
const JAVA_DOWNLOAD_PROGRESS_MIN_BYTES: u64 = 256 * 1024;
|
||||
|
||||
async fn update_java_install_progress(
|
||||
reporter: Option<&InstallProgressReporter>,
|
||||
java_version: u32,
|
||||
step: InstallJavaStep,
|
||||
progress: Option<InstallProgress>,
|
||||
) -> crate::Result<()> {
|
||||
if let Some(reporter) = reporter {
|
||||
reporter
|
||||
.update(
|
||||
InstallPhaseId::PreparingJava,
|
||||
progress,
|
||||
InstallPhaseDetails::Java {
|
||||
major_version: java_version,
|
||||
step,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn java_step_progress(current: u64) -> InstallProgress {
|
||||
InstallProgress {
|
||||
current,
|
||||
total: JAVA_INSTALL_STEPS,
|
||||
secondary: None,
|
||||
}
|
||||
}
|
||||
|
||||
async fn auto_install_java_inner(
|
||||
java_version: u32,
|
||||
show_loading: bool,
|
||||
reporter: Option<InstallProgressReporter>,
|
||||
) -> crate::Result<PathBuf> {
|
||||
let state = State::get().await?;
|
||||
|
||||
let loading_bar = init_loading(
|
||||
LoadingBarType::JavaDownload {
|
||||
version: java_version,
|
||||
},
|
||||
100.0,
|
||||
"Downloading java version",
|
||||
)
|
||||
.await?;
|
||||
let loading_bar = if show_loading {
|
||||
Some(
|
||||
init_loading(
|
||||
LoadingBarType::JavaDownload {
|
||||
version: java_version,
|
||||
},
|
||||
100.0,
|
||||
"Downloading java version",
|
||||
)
|
||||
.await?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Package {
|
||||
@@ -69,7 +138,16 @@ pub async fn auto_install_java(java_version: u32) -> crate::Result<PathBuf> {
|
||||
pub name: PathBuf,
|
||||
}
|
||||
|
||||
emit_loading(&loading_bar, 0.0, Some("Fetching java version"))?;
|
||||
if let Some(loading_bar) = &loading_bar {
|
||||
emit_loading(loading_bar, 0.0, Some("Fetching java version"))?;
|
||||
}
|
||||
update_java_install_progress(
|
||||
reporter.as_ref(),
|
||||
java_version,
|
||||
InstallJavaStep::FetchingMetadata,
|
||||
Some(java_step_progress(1)),
|
||||
)
|
||||
.await?;
|
||||
let packages = fetch_json::<Vec<Package>>(
|
||||
Method::GET,
|
||||
&format!(
|
||||
@@ -82,22 +160,80 @@ pub async fn auto_install_java(java_version: u32) -> crate::Result<PathBuf> {
|
||||
&state.fetch_semaphore,
|
||||
&state.pool,
|
||||
).await?;
|
||||
emit_loading(&loading_bar, 10.0, Some("Downloading java version"))?;
|
||||
if let Some(loading_bar) = &loading_bar {
|
||||
emit_loading(loading_bar, 10.0, Some("Downloading java version"))?;
|
||||
}
|
||||
|
||||
if let Some(download) = packages.first() {
|
||||
let file = fetch_advanced(
|
||||
Method::GET,
|
||||
&download.download_url,
|
||||
update_java_install_progress(
|
||||
reporter.as_ref(),
|
||||
java_version,
|
||||
InstallJavaStep::Downloading,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some((&loading_bar, 80.0)),
|
||||
None,
|
||||
&state.fetch_semaphore,
|
||||
&state.pool,
|
||||
)
|
||||
.await?;
|
||||
let file = if reporter.is_some() {
|
||||
let mut last_reported_bytes = 0_u64;
|
||||
let download_reporter = reporter.clone();
|
||||
let mut progress = move |current: u64,
|
||||
total: u64|
|
||||
-> Pin<
|
||||
Box<dyn Future<Output = crate::Result<()>> + Send>,
|
||||
> {
|
||||
let min_delta =
|
||||
(total / 200).max(JAVA_DOWNLOAD_PROGRESS_MIN_BYTES);
|
||||
if current < total
|
||||
&& current.saturating_sub(last_reported_bytes) < min_delta
|
||||
{
|
||||
return Box::pin(async { Ok(()) });
|
||||
}
|
||||
|
||||
last_reported_bytes = current;
|
||||
let reporter = download_reporter.clone();
|
||||
Box::pin(async move {
|
||||
update_java_install_progress(
|
||||
reporter.as_ref(),
|
||||
java_version,
|
||||
InstallJavaStep::Downloading,
|
||||
Some(InstallProgress {
|
||||
current,
|
||||
total,
|
||||
secondary: None,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
})
|
||||
};
|
||||
|
||||
fetch_advanced_with_progress(
|
||||
Method::GET,
|
||||
&download.download_url,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
loading_bar.as_ref().map(|loading_bar| (loading_bar, 80.0)),
|
||||
None,
|
||||
&state.fetch_semaphore,
|
||||
&state.pool,
|
||||
Some(&mut progress as &mut FetchProgressFn<'_>),
|
||||
)
|
||||
.await?
|
||||
} else {
|
||||
fetch_advanced(
|
||||
Method::GET,
|
||||
&download.download_url,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
loading_bar.as_ref().map(|loading_bar| (loading_bar, 80.0)),
|
||||
None,
|
||||
&state.fetch_semaphore,
|
||||
&state.pool,
|
||||
)
|
||||
.await?
|
||||
};
|
||||
|
||||
let path = state.directories.java_versions_dir();
|
||||
|
||||
@@ -119,13 +255,24 @@ pub async fn auto_install_java(java_version: u32) -> crate::Result<PathBuf> {
|
||||
}
|
||||
}
|
||||
|
||||
emit_loading(&loading_bar, 0.0, Some("Extracting java"))?;
|
||||
if let Some(loading_bar) = &loading_bar {
|
||||
emit_loading(loading_bar, 0.0, Some("Extracting java"))?;
|
||||
}
|
||||
update_java_install_progress(
|
||||
reporter.as_ref(),
|
||||
java_version,
|
||||
InstallJavaStep::Extracting,
|
||||
Some(java_step_progress(3)),
|
||||
)
|
||||
.await?;
|
||||
archive.extract(&path).map_err(|_| {
|
||||
crate::Error::from(crate::ErrorKind::InputError(
|
||||
"Failed to extract java zip".to_string(),
|
||||
))
|
||||
})?;
|
||||
emit_loading(&loading_bar, 10.0, Some("Done extracting java"))?;
|
||||
if let Some(loading_bar) = &loading_bar {
|
||||
emit_loading(loading_bar, 10.0, Some("Done extracting java"))?;
|
||||
}
|
||||
let mut base_path = path.join(
|
||||
download
|
||||
.name
|
||||
|
||||
Reference in New Issue
Block a user