feat: add main features
Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
This commit is contained in:
6
crates/application/src/window/mod.rs
Normal file
6
crates/application/src/window/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
//! Window/tab use cases (ARCHITECTURE §6, §10; L10). Detaching a tab into a new
|
||||
//! OS window, persisting the workspace.
|
||||
|
||||
mod usecases;
|
||||
|
||||
pub use usecases::{MoveTabToNewWindow, MoveTabToNewWindowInput, MoveTabToNewWindowOutput};
|
||||
73
crates/application/src/window/usecases.rs
Normal file
73
crates/application/src/window/usecases.rs
Normal file
@ -0,0 +1,73 @@
|
||||
//! Window/tab use cases (ARCHITECTURE §6, §10; L10).
|
||||
//!
|
||||
//! [`MoveTabToNewWindow`] detaches a tab into a new OS window. The topology
|
||||
//! change is the pure [`Workspace::move_tab_to_new_window`] domain operation; the
|
||||
//! use case only loads/persists the workspace and mints the new window id.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::ids::{TabId, WindowId};
|
||||
use domain::layout::Workspace;
|
||||
use domain::ports::{IdGenerator, ProjectStore};
|
||||
|
||||
use crate::error::AppError;
|
||||
|
||||
/// Input for [`MoveTabToNewWindow::execute`].
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MoveTabToNewWindowInput {
|
||||
/// The tab to detach into its own new window.
|
||||
pub tab_id: TabId,
|
||||
}
|
||||
|
||||
/// Output of [`MoveTabToNewWindow::execute`].
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct MoveTabToNewWindowOutput {
|
||||
/// The id minted for the new window.
|
||||
pub new_window_id: WindowId,
|
||||
/// The resulting workspace (already persisted).
|
||||
pub workspace: Workspace,
|
||||
}
|
||||
|
||||
/// Detaches a tab into a freshly-created window and persists the workspace.
|
||||
pub struct MoveTabToNewWindow {
|
||||
store: Arc<dyn ProjectStore>,
|
||||
ids: Arc<dyn IdGenerator>,
|
||||
}
|
||||
|
||||
impl MoveTabToNewWindow {
|
||||
/// Builds the use case from its ports.
|
||||
#[must_use]
|
||||
pub fn new(store: Arc<dyn ProjectStore>, ids: Arc<dyn IdGenerator>) -> Self {
|
||||
Self { store, ids }
|
||||
}
|
||||
|
||||
/// Executes the detach.
|
||||
///
|
||||
/// # Errors
|
||||
/// - [`AppError::NotFound`] if the tab is not in the workspace,
|
||||
/// - [`AppError::Invalid`] if the resulting window is invalid,
|
||||
/// - [`AppError::Store`] on persistence failure.
|
||||
pub async fn execute(
|
||||
&self,
|
||||
input: MoveTabToNewWindowInput,
|
||||
) -> Result<MoveTabToNewWindowOutput, AppError> {
|
||||
let workspace = self.store.load_workspace().await?;
|
||||
let new_window_id = WindowId::from_uuid(self.ids.new_uuid());
|
||||
|
||||
let workspace = workspace
|
||||
.move_tab_to_new_window(input.tab_id, new_window_id)
|
||||
.map_err(|e| match e {
|
||||
domain::layout::LayoutError::TabNotFound(t) => {
|
||||
AppError::NotFound(format!("tab {t}"))
|
||||
}
|
||||
other => AppError::Invalid(other.to_string()),
|
||||
})?;
|
||||
|
||||
self.store.save_workspace(&workspace).await?;
|
||||
|
||||
Ok(MoveTabToNewWindowOutput {
|
||||
new_window_id,
|
||||
workspace,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user