新增图片画布项目页

新增 /project 项目页和我的页项目入口

补齐图片画布工程列表、重命名和删除 API

支持 /editor/canvas 按 projectid 加载指定工程

更新图片画布文档、TRACKING 和对应测试
This commit is contained in:
2026-06-14 00:11:36 +08:00
parent b2122481ff
commit 85834a423d
32 changed files with 1800 additions and 20 deletions

View File

@@ -70,6 +70,75 @@ impl SpacetimeClient {
.await
}
pub async fn list_editor_projects(
&self,
owner_user_id: String,
) -> Result<Vec<EditorProjectRecord>, SpacetimeClientError> {
let procedure_input = EditorProjectListInput { owner_user_id };
self.call_after_connect(
"list_editor_projects_and_return",
move |connection, sender| {
connection.procedures().list_editor_projects_and_return_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(map_editor_project_list_procedure_result);
send_once(&sender, mapped);
},
);
},
)
.await
}
pub async fn rename_editor_project(
&self,
input: EditorProjectRenameRecordInput,
) -> Result<EditorProjectRecord, SpacetimeClientError> {
let procedure_input = input.into();
self.call_after_connect(
"rename_editor_project_and_return",
move |connection, sender| {
connection.procedures().rename_editor_project_and_return_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(map_editor_project_required_procedure_result);
send_once(&sender, mapped);
},
);
},
)
.await
}
pub async fn delete_editor_project(
&self,
input: EditorProjectDeleteRecordInput,
) -> Result<String, SpacetimeClientError> {
let procedure_input = input.into();
self.call_after_connect(
"delete_editor_project_and_return",
move |connection, sender| {
connection.procedures().delete_editor_project_and_return_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(SpacetimeClientError::from_sdk_error)
.and_then(map_editor_project_delete_procedure_result);
send_once(&sender, mapped);
},
);
},
)
.await
}
pub async fn save_editor_project_layout(
&self,
input: EditorProjectLayoutSaveRecordInput,

View File

@@ -31,8 +31,9 @@ pub use mapper::{
CustomWorldPublishWorldRecordInput, CustomWorldPublishedProfileCompileRecord,
CustomWorldResultPreviewBlockerRecord, CustomWorldSupportedActionRecord,
CustomWorldWorkSummaryRecord, EditorCanvasRecord, EditorCanvasViewportRecord,
EditorProjectCreateRecordInput, EditorProjectGetRecordInput, EditorProjectLayoutSaveRecordInput,
EditorProjectRecord, EditorProjectResourceCreateRecordInput, EditorProjectResourceRecord,
EditorProjectCreateRecordInput, EditorProjectDeleteRecordInput, EditorProjectGetRecordInput,
EditorProjectLayoutSaveRecordInput, EditorProjectRecord, EditorProjectRenameRecordInput,
EditorProjectResourceCreateRecordInput, EditorProjectResourceRecord,
ExternalGenerationJobClaimRecordInput,
ExternalGenerationJobCompleteRecordInput, ExternalGenerationJobEnqueueRecordInput,
ExternalGenerationJobFailRecordInput, ExternalGenerationJobGetRecordInput,

View File

@@ -44,7 +44,8 @@ pub use self::combat::{
};
pub use self::editor_project::{
EditorCanvasRecord, EditorCanvasViewportRecord, EditorProjectCreateRecordInput,
EditorProjectGetRecordInput, EditorProjectLayoutSaveRecordInput, EditorProjectRecord,
EditorProjectDeleteRecordInput, EditorProjectGetRecordInput,
EditorProjectLayoutSaveRecordInput, EditorProjectRecord, EditorProjectRenameRecordInput,
EditorProjectResourceCreateRecordInput, EditorProjectResourceRecord,
};
pub use self::common::{
@@ -193,6 +194,7 @@ pub(crate) use self::custom_world::{
parse_rpg_agent_stage_record,
};
pub(crate) use self::editor_project::{
map_editor_project_delete_procedure_result, map_editor_project_list_procedure_result,
map_editor_project_optional_procedure_result, map_editor_project_required_procedure_result,
map_editor_project_resource_procedure_result,
};

View File

@@ -65,6 +65,20 @@ pub struct EditorProjectGetRecordInput {
pub owner_user_id: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EditorProjectRenameRecordInput {
pub project_id: String,
pub owner_user_id: String,
pub title: String,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EditorProjectDeleteRecordInput {
pub project_id: String,
pub owner_user_id: String,
}
#[derive(Clone, Debug, PartialEq)]
pub struct EditorProjectLayoutSaveRecordInput {
pub project_id: String,
@@ -114,6 +128,26 @@ impl From<EditorProjectGetRecordInput> for crate::module_bindings::EditorProject
}
}
impl From<EditorProjectRenameRecordInput> for crate::module_bindings::EditorProjectRenameInput {
fn from(input: EditorProjectRenameRecordInput) -> Self {
Self {
project_id: input.project_id,
owner_user_id: input.owner_user_id,
title: input.title,
updated_at_micros: input.updated_at_micros,
}
}
}
impl From<EditorProjectDeleteRecordInput> for crate::module_bindings::EditorProjectDeleteInput {
fn from(input: EditorProjectDeleteRecordInput) -> Self {
Self {
project_id: input.project_id,
owner_user_id: input.owner_user_id,
}
}
}
impl From<EditorProjectLayoutSaveRecordInput>
for crate::module_bindings::EditorProjectLayoutSaveInput
{
@@ -174,6 +208,33 @@ pub(crate) fn map_editor_project_required_procedure_result(
.ok_or_else(|| SpacetimeClientError::missing_snapshot("图片画布工程快照"))
}
pub(crate) fn map_editor_project_list_procedure_result(
result: EditorProjectListProcedureResult,
) -> Result<Vec<EditorProjectRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
result
.projects
.into_iter()
.map(map_editor_project_snapshot)
.collect()
}
pub(crate) fn map_editor_project_delete_procedure_result(
result: EditorProjectDeleteProcedureResult,
) -> Result<String, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
result
.deleted_project_id
.filter(|project_id| !project_id.trim().is_empty())
.ok_or_else(|| SpacetimeClientError::missing_snapshot("图片画布工程删除结果"))
}
pub(crate) fn map_editor_project_resource_procedure_result(
result: EditorProjectResourceProcedureResult,
) -> Result<EditorProjectResourceRecord, SpacetimeClientError> {

View File

@@ -338,6 +338,7 @@ pub mod delete_bark_battle_work_procedure;
pub mod delete_big_fish_work_procedure;
pub mod delete_custom_world_agent_session_procedure;
pub mod delete_custom_world_profile_and_return_procedure;
pub mod delete_editor_project_and_return_procedure;
pub mod delete_jump_hop_work_procedure;
pub mod delete_match_3_d_work_procedure;
pub mod delete_puzzle_work_procedure;
@@ -351,10 +352,15 @@ pub mod editor_canvas_snapshot_type;
pub mod editor_canvas_table;
pub mod editor_canvas_type;
pub mod editor_project_create_input_type;
pub mod editor_project_delete_input_type;
pub mod editor_project_delete_procedure_result_type;
pub mod editor_project_get_input_type;
pub mod editor_project_get_recent_input_type;
pub mod editor_project_layout_save_input_type;
pub mod editor_project_list_input_type;
pub mod editor_project_list_procedure_result_type;
pub mod editor_project_procedure_result_type;
pub mod editor_project_rename_input_type;
pub mod editor_project_resource_create_input_type;
pub mod editor_project_resource_procedure_result_type;
pub mod editor_project_resource_snapshot_type;
@@ -521,6 +527,7 @@ pub mod list_big_fish_works_procedure;
pub mod list_custom_world_gallery_entries_procedure;
pub mod list_custom_world_profiles_procedure;
pub mod list_custom_world_works_procedure;
pub mod list_editor_projects_and_return_procedure;
pub mod list_jump_hop_works_procedure;
pub mod list_match_3_d_works_procedure;
pub mod list_platform_browse_history_procedure;
@@ -817,6 +824,7 @@ pub mod release_puzzle_background_compile_task_procedure;
pub mod remix_big_fish_work_procedure;
pub mod remix_custom_world_profile_procedure;
pub mod remix_puzzle_work_procedure;
pub mod rename_editor_project_and_return_procedure;
pub mod renew_external_generation_job_lease_and_return_procedure;
pub mod resolve_combat_action_and_return_procedure;
pub mod resolve_combat_action_input_type;
@@ -1496,6 +1504,7 @@ pub use delete_bark_battle_work_procedure::delete_bark_battle_work;
pub use delete_big_fish_work_procedure::delete_big_fish_work;
pub use delete_custom_world_agent_session_procedure::delete_custom_world_agent_session;
pub use delete_custom_world_profile_and_return_procedure::delete_custom_world_profile_and_return;
pub use delete_editor_project_and_return_procedure::delete_editor_project_and_return;
pub use delete_jump_hop_work_procedure::delete_jump_hop_work;
pub use delete_match_3_d_work_procedure::delete_match_3_d_work;
pub use delete_puzzle_work_procedure::delete_puzzle_work;
@@ -1509,10 +1518,15 @@ pub use editor_canvas_snapshot_type::EditorCanvasSnapshot;
pub use editor_canvas_table::*;
pub use editor_canvas_type::EditorCanvas;
pub use editor_project_create_input_type::EditorProjectCreateInput;
pub use editor_project_delete_input_type::EditorProjectDeleteInput;
pub use editor_project_delete_procedure_result_type::EditorProjectDeleteProcedureResult;
pub use editor_project_get_input_type::EditorProjectGetInput;
pub use editor_project_get_recent_input_type::EditorProjectGetRecentInput;
pub use editor_project_layout_save_input_type::EditorProjectLayoutSaveInput;
pub use editor_project_list_input_type::EditorProjectListInput;
pub use editor_project_list_procedure_result_type::EditorProjectListProcedureResult;
pub use editor_project_procedure_result_type::EditorProjectProcedureResult;
pub use editor_project_rename_input_type::EditorProjectRenameInput;
pub use editor_project_resource_create_input_type::EditorProjectResourceCreateInput;
pub use editor_project_resource_procedure_result_type::EditorProjectResourceProcedureResult;
pub use editor_project_resource_snapshot_type::EditorProjectResourceSnapshot;
@@ -1679,6 +1693,7 @@ pub use list_big_fish_works_procedure::list_big_fish_works;
pub use list_custom_world_gallery_entries_procedure::list_custom_world_gallery_entries;
pub use list_custom_world_profiles_procedure::list_custom_world_profiles;
pub use list_custom_world_works_procedure::list_custom_world_works;
pub use list_editor_projects_and_return_procedure::list_editor_projects_and_return;
pub use list_jump_hop_works_procedure::list_jump_hop_works;
pub use list_match_3_d_works_procedure::list_match_3_d_works;
pub use list_platform_browse_history_procedure::list_platform_browse_history;
@@ -1975,6 +1990,7 @@ pub use release_puzzle_background_compile_task_procedure::release_puzzle_backgro
pub use remix_big_fish_work_procedure::remix_big_fish_work;
pub use remix_custom_world_profile_procedure::remix_custom_world_profile;
pub use remix_puzzle_work_procedure::remix_puzzle_work;
pub use rename_editor_project_and_return_procedure::rename_editor_project_and_return;
pub use renew_external_generation_job_lease_and_return_procedure::renew_external_generation_job_lease_and_return;
pub use resolve_combat_action_and_return_procedure::resolve_combat_action_and_return;
pub use resolve_combat_action_input_type::ResolveCombatActionInput;

View File

@@ -0,0 +1,59 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::editor_project_delete_input_type::EditorProjectDeleteInput;
use super::editor_project_delete_procedure_result_type::EditorProjectDeleteProcedureResult;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
struct DeleteEditorProjectAndReturnArgs {
pub input: EditorProjectDeleteInput,
}
impl __sdk::InModule for DeleteEditorProjectAndReturnArgs {
type Module = super::RemoteModule;
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the procedure `delete_editor_project_and_return`.
///
/// Implemented for [`super::RemoteProcedures`].
pub trait delete_editor_project_and_return {
fn delete_editor_project_and_return(&self, input: EditorProjectDeleteInput) {
self.delete_editor_project_and_return_then(input, |_, _| {});
}
fn delete_editor_project_and_return_then(
&self,
input: EditorProjectDeleteInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<EditorProjectDeleteProcedureResult, __sdk::InternalError>,
) + Send
+ 'static,
);
}
impl delete_editor_project_and_return for super::RemoteProcedures {
fn delete_editor_project_and_return_then(
&self,
input: EditorProjectDeleteInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<EditorProjectDeleteProcedureResult, __sdk::InternalError>,
) + Send
+ 'static,
) {
self.imp
.invoke_procedure_with_callback::<_, EditorProjectDeleteProcedureResult>(
"delete_editor_project_and_return",
DeleteEditorProjectAndReturnArgs { input },
__callback,
);
}
}

View File

@@ -0,0 +1,16 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct EditorProjectDeleteInput {
pub project_id: String,
pub owner_user_id: String,
}
impl __sdk::InModule for EditorProjectDeleteInput {
type Module = super::RemoteModule;
}

View File

@@ -0,0 +1,17 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct EditorProjectDeleteProcedureResult {
pub ok: bool,
pub deleted_project_id: Option<String>,
pub error_message: Option<String>,
}
impl __sdk::InModule for EditorProjectDeleteProcedureResult {
type Module = super::RemoteModule;
}

View File

@@ -0,0 +1,15 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct EditorProjectListInput {
pub owner_user_id: String,
}
impl __sdk::InModule for EditorProjectListInput {
type Module = super::RemoteModule;
}

View File

@@ -0,0 +1,19 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::editor_project_snapshot_type::EditorProjectSnapshot;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct EditorProjectListProcedureResult {
pub ok: bool,
pub projects: Vec<EditorProjectSnapshot>,
pub error_message: Option<String>,
}
impl __sdk::InModule for EditorProjectListProcedureResult {
type Module = super::RemoteModule;
}

View File

@@ -0,0 +1,18 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
pub struct EditorProjectRenameInput {
pub project_id: String,
pub owner_user_id: String,
pub title: String,
pub updated_at_micros: i64,
}
impl __sdk::InModule for EditorProjectRenameInput {
type Module = super::RemoteModule;
}

View File

@@ -0,0 +1,59 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::editor_project_list_input_type::EditorProjectListInput;
use super::editor_project_list_procedure_result_type::EditorProjectListProcedureResult;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
struct ListEditorProjectsAndReturnArgs {
pub input: EditorProjectListInput,
}
impl __sdk::InModule for ListEditorProjectsAndReturnArgs {
type Module = super::RemoteModule;
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the procedure `list_editor_projects_and_return`.
///
/// Implemented for [`super::RemoteProcedures`].
pub trait list_editor_projects_and_return {
fn list_editor_projects_and_return(&self, input: EditorProjectListInput) {
self.list_editor_projects_and_return_then(input, |_, _| {});
}
fn list_editor_projects_and_return_then(
&self,
input: EditorProjectListInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<EditorProjectListProcedureResult, __sdk::InternalError>,
) + Send
+ 'static,
);
}
impl list_editor_projects_and_return for super::RemoteProcedures {
fn list_editor_projects_and_return_then(
&self,
input: EditorProjectListInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<EditorProjectListProcedureResult, __sdk::InternalError>,
) + Send
+ 'static,
) {
self.imp
.invoke_procedure_with_callback::<_, EditorProjectListProcedureResult>(
"list_editor_projects_and_return",
ListEditorProjectsAndReturnArgs { input },
__callback,
);
}
}

View File

@@ -0,0 +1,59 @@
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
#![allow(unused, clippy::all)]
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
use super::editor_project_procedure_result_type::EditorProjectProcedureResult;
use super::editor_project_rename_input_type::EditorProjectRenameInput;
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
#[sats(crate = __lib)]
struct RenameEditorProjectAndReturnArgs {
pub input: EditorProjectRenameInput,
}
impl __sdk::InModule for RenameEditorProjectAndReturnArgs {
type Module = super::RemoteModule;
}
#[allow(non_camel_case_types)]
/// Extension trait for access to the procedure `rename_editor_project_and_return`.
///
/// Implemented for [`super::RemoteProcedures`].
pub trait rename_editor_project_and_return {
fn rename_editor_project_and_return(&self, input: EditorProjectRenameInput) {
self.rename_editor_project_and_return_then(input, |_, _| {});
}
fn rename_editor_project_and_return_then(
&self,
input: EditorProjectRenameInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<EditorProjectProcedureResult, __sdk::InternalError>,
) + Send
+ 'static,
);
}
impl rename_editor_project_and_return for super::RemoteProcedures {
fn rename_editor_project_and_return_then(
&self,
input: EditorProjectRenameInput,
__callback: impl FnOnce(
&super::ProcedureEventContext,
Result<EditorProjectProcedureResult, __sdk::InternalError>,
) + Send
+ 'static,
) {
self.imp
.invoke_procedure_with_callback::<_, EditorProjectProcedureResult>(
"rename_editor_project_and_return",
RenameEditorProjectAndReturnArgs { input },
__callback,
);
}
}