From 59c16e41007257a91455eced7ca132344e202e5f Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 18 Mar 2026 22:51:00 +0800 Subject: Add sheet management methods to WorkspaceManager --- systems/_framework/src/space.rs | 6 ++ systems/workspace/src/workspace/manager.rs | 2 +- .../workspace/src/workspace/manager/sheet_state.rs | 67 +++++++++++++++++++--- .../src/workspace/manager/sheet_state/error.rs | 29 ++++++++++ 4 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 systems/workspace/src/workspace/manager/sheet_state/error.rs diff --git a/systems/_framework/src/space.rs b/systems/_framework/src/space.rs index 8a9b2ec..315bf2b 100644 --- a/systems/_framework/src/space.rs +++ b/systems/_framework/src/space.rs @@ -376,6 +376,12 @@ impl Space { let path = self.local_path(relative_path)?; Ok(tokio::fs::write(path, contents).await?) } + + /// Check if a file or directory exists at the given relative path within the space. + pub async fn exists(&self, relative_path: impl AsRef) -> Result { + let path = self.local_path(relative_path)?; + Ok(tokio::fs::try_exists(path).await?) + } } impl From for Space { diff --git a/systems/workspace/src/workspace/manager.rs b/systems/workspace/src/workspace/manager.rs index 58eb409..fef36ab 100644 --- a/systems/workspace/src/workspace/manager.rs +++ b/systems/workspace/src/workspace/manager.rs @@ -7,7 +7,7 @@ pub mod id_aliases; pub mod sheet_state; pub struct WorkspaceManager { - space: Space, + pub(crate) space: Space, } impl WorkspaceManager { diff --git a/systems/workspace/src/workspace/manager/sheet_state.rs b/systems/workspace/src/workspace/manager/sheet_state.rs index 5603adf..b7cd4fd 100644 --- a/systems/workspace/src/workspace/manager/sheet_state.rs +++ b/systems/workspace/src/workspace/manager/sheet_state.rs @@ -1,12 +1,17 @@ use std::path::PathBuf; -use crate::workspace::manager::WorkspaceManager; +use crate::workspace::manager::{WorkspaceManager, sheet_state::error::MakeSheetError}; use asset_system::asset::ReadOnlyAsset; -use constants::workspace::files::{workspace_file_current_sheet, workspace_file_sheet}; +use constants::workspace::{ + dirs::workspace_dir_local_sheets, + files::{workspace_file_current_sheet, workspace_file_sheet}, +}; use framework::space::error::SpaceError; use just_fmt::snake_case; use sheet_system::sheet::{Sheet, SheetData}; +pub mod error; + impl WorkspaceManager { /// Read the name of the currently active Sheet pub async fn using_sheet_name(&self) -> Result, SpaceError> { @@ -25,17 +30,17 @@ impl WorkspaceManager { } /// Set the name of the currently active Sheet - pub async fn edit_using_sheet_name(&self, name: &str) -> Result<(), SpaceError> { + pub async fn edit_using_sheet_name(&self, name: impl AsRef) -> Result<(), SpaceError> { self.space - .write(workspace_file_current_sheet(), name.as_bytes()) + .write(workspace_file_current_sheet(), name.as_ref().as_bytes()) .await } /// Read a sheet from the workspace space by name /// /// Simple read of Sheet data, no disk write operations involved - pub async fn read_sheet(&self, sheet_name: &str) -> Option { - let sheet_name = snake_case!(sheet_name); + pub async fn read_sheet(&self, sheet_name: impl AsRef) -> Option { + let sheet_name = snake_case!(sheet_name.as_ref()); let sheet_path = self.get_sheet_path(&sheet_name); let mut sheet_data = SheetData::empty(); @@ -51,8 +56,11 @@ impl WorkspaceManager { /// Get a resource pointing to local Sheet data by name /// /// Can be used to load content, edit, and transactionally write - pub fn get_sheet_data_asset(&self, sheet_name: &str) -> Option> { - let sheet_name = snake_case!(sheet_name); + pub fn get_sheet_data_asset( + &self, + sheet_name: impl AsRef, + ) -> Option> { + let sheet_name = snake_case!(sheet_name.as_ref()); let sheet_path = self.get_sheet_path(&sheet_name); if sheet_path.exists() { return Some(sheet_path.into()); @@ -70,4 +78,47 @@ impl WorkspaceManager { // execution should not continue, so we unwrap() .unwrap() } + + /// Get the names of all sheets in the workspace + pub async fn list_sheet_names(&self) -> Vec { + let mut sheet_names = Vec::new(); + if let Ok(mut read_dir) = self.space.read_dir(workspace_dir_local_sheets()).await { + while let Some(entry) = read_dir.next_entry().await.ok().flatten() { + let path = entry.path(); + if path.is_file() { + if let Some(file_name) = path.file_stem() { + if let Some(name_str) = file_name.to_str() { + sheet_names.push(name_str.to_string()); + } + } + } + } + } + sheet_names + } + + /// Create a new sheet in the workspace by name + pub async fn make_sheet(&self, sheet_name: impl AsRef) -> Result<(), MakeSheetError> { + let sheet_dir = workspace_dir_local_sheets(); + let sheet_path = workspace_file_sheet(sheet_name.as_ref()); + if self.space.exists(&sheet_path).await? { + return Err(MakeSheetError::SheetAlreadyExists); + } + self.space.create_dir_all(&sheet_dir).await?; + self.space + .write(sheet_path, SheetData::empty().as_bytes()) + .await?; + + Ok(()) + } + + /// Delete a sheet from the workspace by name + pub async fn drop_sheet(&self, sheet_name: impl AsRef) -> Result<(), MakeSheetError> { + let sheet_path = workspace_file_sheet(sheet_name.as_ref()); + if !self.space.exists(&sheet_path).await? { + return Err(MakeSheetError::SheetNotFound); + } + self.space.remove_file(sheet_path).await?; + Ok(()) + } } diff --git a/systems/workspace/src/workspace/manager/sheet_state/error.rs b/systems/workspace/src/workspace/manager/sheet_state/error.rs new file mode 100644 index 0000000..465431f --- /dev/null +++ b/systems/workspace/src/workspace/manager/sheet_state/error.rs @@ -0,0 +1,29 @@ +use framework::space::error::SpaceError; + +#[derive(thiserror::Error, Debug)] +pub enum MakeSheetError { + #[error("Sheet already exists")] + SheetAlreadyExists, + + #[error("Sheet not found")] + SheetNotFound, + + #[error("IO error: {0}")] + Io(#[from] std::io::Error), + + #[error("Other error: {0}")] + Other(String), +} + +impl From for MakeSheetError { + fn from(value: SpaceError) -> Self { + match value { + SpaceError::SpaceNotFound => Self::SheetNotFound, + SpaceError::PathFormatError(path_format_error) => { + Self::Other(format!("PathFormatError: {}", path_format_error)) + } + SpaceError::Io(error) => Self::Io(error), + SpaceError::Other(msg) => Self::Other(msg), + } + } +} -- cgit