Make the ProjectSelector multi-window aware

That way it will not allow to open a project if it's known to be open already.
This commit is contained in:
Sebastian Thiel 2024-07-11 10:36:49 +02:00
parent 38f800d877
commit eaa18da9d0
No known key found for this signature in database
GPG Key ID: 9CB5EE7895E8268B
4 changed files with 39 additions and 4 deletions

View File

@ -29,6 +29,9 @@ export class Project {
use_new_locking!: boolean;
ignore_project_semaphore!: boolean;
// Produced just for the frontend
is_open!: boolean;
get vscodePath() {
return this.path.includes('\\') ? '/' + this.path.replace('\\', '/') : this.path;
}

View File

@ -105,7 +105,9 @@
<ScrollableContainer maxHeight="20rem">
<div class="popup__projects">
{#each $projects as project}
{@const selected = project.id === $page.params.projectId}
{@const selected =
project.id === $page.params.projectId ||
$projects.some((p) => p.is_open && p.id === project.id)}
{@render itemSnippet({
label: project.title,
selected,

View File

@ -1,3 +1,5 @@
use gitbutler_project::Project;
pub mod commands {
use anyhow::Context;
use std::path;
@ -8,6 +10,7 @@ pub mod commands {
use tracing::instrument;
use crate::error::Error;
use crate::projects::ProjectForFrontend;
use crate::{window, WindowState};
#[tauri::command(async)]
@ -38,11 +41,21 @@ pub mod commands {
}
#[tauri::command(async)]
#[instrument(skip(controller), err(Debug))]
#[instrument(skip(controller, window_state), err(Debug))]
pub async fn list_projects(
window_state: State<'_, WindowState>,
controller: State<'_, Controller>,
) -> Result<Vec<projects::Project>, Error> {
controller.list().map_err(Into::into)
) -> Result<Vec<ProjectForFrontend>, Error> {
let open_projects = window_state.open_projects();
controller.list().map_err(Into::into).map(|projects| {
projects
.into_iter()
.map(|project| ProjectForFrontend {
is_open: open_projects.contains(&project.id),
inner: project,
})
.collect()
})
}
/// This trigger is the GUI telling us that the project with `id` is now displayed.
@ -88,3 +101,11 @@ pub mod commands {
controller.delete(id).await.map_err(Into::into)
}
}
#[derive(serde::Deserialize, serde::Serialize)]
pub struct ProjectForFrontend {
#[serde(flatten)]
pub inner: Project,
/// Tell if the project is known to be open in a Window in the frontend.
pub is_open: bool,
}

View File

@ -205,6 +205,15 @@ pub(super) mod state {
let mut state_by_label = block_on(self.state.lock());
state_by_label.remove(window);
}
/// Return the list of project ids that are currently open.
pub fn open_projects(&self) -> Vec<ProjectId> {
let state_by_label = block_on(self.state.lock());
state_by_label
.values()
.map(|state| state.project_id)
.collect()
}
}
}