You've already forked AstralRinth
forked from didirus/AstralRinth
Folder names (#318)
This commit is contained in:
@@ -49,7 +49,8 @@ mod safe_processes;
|
||||
pub use self::safe_processes::*;
|
||||
|
||||
// Global state
|
||||
static LAUNCHER_STATE: OnceCell<Arc<State>> = OnceCell::const_new();
|
||||
// RwLock on state only has concurrent reads, except for config dir change which takes control of the State
|
||||
static LAUNCHER_STATE: OnceCell<RwLock<State>> = OnceCell::const_new();
|
||||
pub struct State {
|
||||
/// Information on the location of files used in the launcher
|
||||
pub directories: DirectoryInfo,
|
||||
@@ -86,83 +87,97 @@ pub struct State {
|
||||
|
||||
impl State {
|
||||
/// Get the current launcher state, initializing it if needed
|
||||
pub async fn get(
|
||||
) -> crate::Result<Arc<tokio::sync::RwLockReadGuard<'static, Self>>> {
|
||||
Ok(Arc::new(
|
||||
LAUNCHER_STATE
|
||||
.get_or_try_init(Self::initialize_state)
|
||||
.await?
|
||||
.read()
|
||||
.await,
|
||||
))
|
||||
}
|
||||
|
||||
/// Get the current launcher state, initializing it if needed
|
||||
/// Takes writing control of the state, blocking all other uses of it
|
||||
/// Only used for state change such as changing the config directory
|
||||
pub async fn get_write(
|
||||
) -> crate::Result<tokio::sync::RwLockWriteGuard<'static, Self>> {
|
||||
Ok(LAUNCHER_STATE
|
||||
.get_or_try_init(Self::initialize_state)
|
||||
.await?
|
||||
.write()
|
||||
.await)
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
#[theseus_macros::debug_pin]
|
||||
pub async fn get() -> crate::Result<Arc<Self>> {
|
||||
LAUNCHER_STATE
|
||||
.get_or_try_init(|| {
|
||||
async {
|
||||
let loading_bar = init_loading_unsafe(
|
||||
LoadingBarType::StateInit,
|
||||
100.0,
|
||||
"Initializing launcher",
|
||||
)
|
||||
.await?;
|
||||
async fn initialize_state() -> crate::Result<RwLock<State>> {
|
||||
let loading_bar = init_loading_unsafe(
|
||||
LoadingBarType::StateInit,
|
||||
100.0,
|
||||
"Initializing launcher",
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut file_watcher = init_watcher().await?;
|
||||
// Settings
|
||||
let settings =
|
||||
Settings::init(&DirectoryInfo::get_initial_settings_file()?)
|
||||
.await?;
|
||||
|
||||
let directories = DirectoryInfo::init()?;
|
||||
emit_loading(&loading_bar, 10.0, None).await?;
|
||||
let directories = DirectoryInfo::init(&settings)?;
|
||||
|
||||
// Settings
|
||||
let settings =
|
||||
Settings::init(&directories.settings_file()).await?;
|
||||
let fetch_semaphore = FetchSemaphore(RwLock::new(
|
||||
Semaphore::new(settings.max_concurrent_downloads),
|
||||
));
|
||||
let io_semaphore = IoSemaphore(RwLock::new(
|
||||
Semaphore::new(settings.max_concurrent_writes),
|
||||
));
|
||||
emit_loading(&loading_bar, 10.0, None).await?;
|
||||
emit_loading(&loading_bar, 10.0, None).await?;
|
||||
|
||||
let metadata_fut =
|
||||
Metadata::init(&directories, &io_semaphore);
|
||||
let profiles_fut =
|
||||
Profiles::init(&directories, &mut file_watcher);
|
||||
let tags_fut = Tags::init(
|
||||
&directories,
|
||||
&io_semaphore,
|
||||
&fetch_semaphore,
|
||||
);
|
||||
let users_fut = Users::init(&directories, &io_semaphore);
|
||||
// Launcher data
|
||||
let (metadata, profiles, tags, users) = loading_join! {
|
||||
Some(&loading_bar), 70.0, Some("Loading metadata");
|
||||
metadata_fut,
|
||||
profiles_fut,
|
||||
tags_fut,
|
||||
users_fut,
|
||||
}?;
|
||||
let mut file_watcher = init_watcher().await?;
|
||||
|
||||
let children = Children::new();
|
||||
let auth_flow = AuthTask::new();
|
||||
let safety_processes = SafeProcesses::new();
|
||||
emit_loading(&loading_bar, 10.0, None).await?;
|
||||
let fetch_semaphore = FetchSemaphore(RwLock::new(Semaphore::new(
|
||||
settings.max_concurrent_downloads,
|
||||
)));
|
||||
let io_semaphore = IoSemaphore(RwLock::new(Semaphore::new(
|
||||
settings.max_concurrent_writes,
|
||||
)));
|
||||
emit_loading(&loading_bar, 10.0, None).await?;
|
||||
|
||||
Ok(Arc::new(Self {
|
||||
directories,
|
||||
fetch_semaphore,
|
||||
fetch_semaphore_max: RwLock::new(
|
||||
settings.max_concurrent_downloads as u32,
|
||||
),
|
||||
io_semaphore,
|
||||
io_semaphore_max: RwLock::new(
|
||||
settings.max_concurrent_writes as u32,
|
||||
),
|
||||
metadata: RwLock::new(metadata),
|
||||
settings: RwLock::new(settings),
|
||||
profiles: RwLock::new(profiles),
|
||||
users: RwLock::new(users),
|
||||
children: RwLock::new(children),
|
||||
auth_flow: RwLock::new(auth_flow),
|
||||
tags: RwLock::new(tags),
|
||||
safety_processes: RwLock::new(safety_processes),
|
||||
file_watcher: RwLock::new(file_watcher),
|
||||
}))
|
||||
}
|
||||
})
|
||||
.await
|
||||
.map(Arc::clone)
|
||||
let metadata_fut = Metadata::init(&directories, &io_semaphore);
|
||||
let profiles_fut = Profiles::init(&directories, &mut file_watcher);
|
||||
let tags_fut =
|
||||
Tags::init(&directories, &io_semaphore, &fetch_semaphore);
|
||||
let users_fut = Users::init(&directories, &io_semaphore);
|
||||
// Launcher data
|
||||
let (metadata, profiles, tags, users) = loading_join! {
|
||||
Some(&loading_bar), 70.0, Some("Loading metadata");
|
||||
metadata_fut,
|
||||
profiles_fut,
|
||||
tags_fut,
|
||||
users_fut,
|
||||
}?;
|
||||
|
||||
let children = Children::new();
|
||||
let auth_flow = AuthTask::new();
|
||||
let safety_processes = SafeProcesses::new();
|
||||
emit_loading(&loading_bar, 10.0, None).await?;
|
||||
|
||||
Ok::<RwLock<Self>, crate::Error>(RwLock::new(Self {
|
||||
directories,
|
||||
fetch_semaphore,
|
||||
fetch_semaphore_max: RwLock::new(
|
||||
settings.max_concurrent_downloads as u32,
|
||||
),
|
||||
io_semaphore,
|
||||
io_semaphore_max: RwLock::new(
|
||||
settings.max_concurrent_writes as u32,
|
||||
),
|
||||
metadata: RwLock::new(metadata),
|
||||
settings: RwLock::new(settings),
|
||||
profiles: RwLock::new(profiles),
|
||||
users: RwLock::new(users),
|
||||
children: RwLock::new(children),
|
||||
auth_flow: RwLock::new(auth_flow),
|
||||
tags: RwLock::new(tags),
|
||||
safety_processes: RwLock::new(safety_processes),
|
||||
file_watcher: RwLock::new(file_watcher),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Updates state with data from the web
|
||||
@@ -240,7 +255,7 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
async fn init_watcher() -> crate::Result<Debouncer<RecommendedWatcher>> {
|
||||
pub async fn init_watcher() -> crate::Result<Debouncer<RecommendedWatcher>> {
|
||||
let (mut tx, mut rx) = channel(1);
|
||||
|
||||
let file_watcher = new_debouncer(
|
||||
@@ -256,13 +271,19 @@ async fn init_watcher() -> crate::Result<Debouncer<RecommendedWatcher>> {
|
||||
tokio::task::spawn(async move {
|
||||
while let Some(res) = rx.next().await {
|
||||
match res {
|
||||
Ok(events) => {
|
||||
Ok(mut events) => {
|
||||
let mut visited_paths = Vec::new();
|
||||
// sort events by e.path
|
||||
events.sort_by(|a, b| a.path.cmp(&b.path));
|
||||
events.iter().for_each(|e| {
|
||||
tracing::debug!(
|
||||
"File watcher event: {:?}",
|
||||
serde_json::to_string(&e.path).unwrap()
|
||||
);
|
||||
let mut new_path = PathBuf::new();
|
||||
let mut components_iterator = e.path.components();
|
||||
let mut found = false;
|
||||
|
||||
for component in e.path.components() {
|
||||
for component in components_iterator.by_ref() {
|
||||
new_path.push(component);
|
||||
if found {
|
||||
break;
|
||||
@@ -271,6 +292,14 @@ async fn init_watcher() -> crate::Result<Debouncer<RecommendedWatcher>> {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
// if any remain, it's a subfile of the profile folder and not the profile folder itself
|
||||
let subfile = components_iterator.next().is_some();
|
||||
|
||||
// At this point, new_path is the path to the profile, and subfile is whether it's a subfile of the profile or not
|
||||
let profile_path_id =
|
||||
ProfilePathId::new(&PathBuf::from(
|
||||
new_path.file_name().unwrap_or_default(),
|
||||
));
|
||||
|
||||
if e.path
|
||||
.components()
|
||||
@@ -280,10 +309,16 @@ async fn init_watcher() -> crate::Result<Debouncer<RecommendedWatcher>> {
|
||||
.map(|x| x == "txt")
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Profile::crash_task(new_path);
|
||||
Profile::crash_task(profile_path_id);
|
||||
} else if !visited_paths.contains(&new_path) {
|
||||
Profile::sync_projects_task(new_path.clone());
|
||||
visited_paths.push(new_path);
|
||||
if subfile {
|
||||
Profile::sync_projects_task(profile_path_id);
|
||||
visited_paths.push(new_path);
|
||||
} else {
|
||||
Profiles::sync_available_profiles_task(
|
||||
profile_path_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user