Merge commit '01af298c' into codex/cache-view-procedure-hotpaths
# Conflicts: # server-rs/crates/spacetime-client/src/mapper.rs # server-rs/crates/spacetime-client/src/module_bindings/big_fish_work_summary_snapshot_type.rs # server-rs/crates/spacetime-module/src/square_hole/types.rs
This commit is contained in:
@@ -33,8 +33,8 @@ pub(crate) fn build_ai_task_snapshot_from_row(
|
||||
let mut stages = ctx
|
||||
.db
|
||||
.ai_task_stage()
|
||||
.iter()
|
||||
.filter(|stage| stage.task_id == row.task_id)
|
||||
.by_ai_task_stage_task_id()
|
||||
.filter(&row.task_id)
|
||||
.map(|stage| build_ai_task_stage_snapshot_from_row(&stage))
|
||||
.collect::<Vec<_>>();
|
||||
stages.sort_by_key(|stage| stage.order);
|
||||
@@ -42,8 +42,8 @@ pub(crate) fn build_ai_task_snapshot_from_row(
|
||||
let mut result_references = ctx
|
||||
.db
|
||||
.ai_result_reference()
|
||||
.iter()
|
||||
.filter(|reference| reference.task_id == row.task_id)
|
||||
.by_ai_result_reference_task_id()
|
||||
.filter(&row.task_id)
|
||||
.map(|reference| build_ai_result_reference_snapshot_from_row(&reference))
|
||||
.collect::<Vec<_>>();
|
||||
result_references.sort_by_key(|reference| reference.created_at_micros);
|
||||
|
||||
@@ -318,8 +318,8 @@ pub(crate) fn replace_ai_task_stages(
|
||||
let stage_ids = ctx
|
||||
.db
|
||||
.ai_task_stage()
|
||||
.iter()
|
||||
.filter(|row| row.task_id == task_id)
|
||||
.by_ai_task_stage_task_id()
|
||||
.filter(task_id)
|
||||
.map(|row| row.task_stage_id.clone())
|
||||
.collect::<Vec<_>>();
|
||||
for stage_id in stage_ids {
|
||||
@@ -341,7 +341,8 @@ pub(crate) fn collect_ai_stage_text_output(
|
||||
let mut chunks = ctx
|
||||
.db
|
||||
.ai_text_chunk()
|
||||
.iter()
|
||||
.by_ai_text_chunk_task_id()
|
||||
.filter(task_id)
|
||||
.filter(|row| row.task_id == task_id && row.stage_kind == stage_kind)
|
||||
.map(|row| build_ai_text_chunk_snapshot_from_row(&row))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -66,12 +66,16 @@ fn upsert_asset_entity_binding(
|
||||
return Err("asset_entity_binding.asset_object_id 对应的 asset_object 不存在".to_string());
|
||||
}
|
||||
|
||||
// 首版绑定按 entity_kind + entity_id + slot 幂等定位,后续访问量明确后再改为组合索引扫描。
|
||||
let current = ctx.db.asset_entity_binding().iter().find(|row| {
|
||||
row.entity_kind == input.entity_kind
|
||||
&& row.entity_id == input.entity_id
|
||||
&& row.slot == input.slot
|
||||
});
|
||||
let current = ctx
|
||||
.db
|
||||
.asset_entity_binding()
|
||||
.by_entity_slot()
|
||||
.filter((
|
||||
input.entity_kind.as_str(),
|
||||
input.entity_id.as_str(),
|
||||
input.slot.as_str(),
|
||||
))
|
||||
.next();
|
||||
|
||||
let snapshot = match current {
|
||||
Some(existing) => {
|
||||
|
||||
@@ -128,12 +128,12 @@ pub(crate) fn upsert_asset_object(
|
||||
)
|
||||
.map_err(|error| error.to_string())?;
|
||||
|
||||
// 这里先保持最小可发布实现:查重语义已经冻结,后续再把实现优化回组合索引扫描。
|
||||
let current = ctx
|
||||
.db
|
||||
.asset_object()
|
||||
.iter()
|
||||
.find(|row| row.bucket == input.bucket && row.object_key == input.object_key);
|
||||
.by_bucket_object_key()
|
||||
.filter((input.bucket.as_str(), input.object_key.as_str()))
|
||||
.next();
|
||||
|
||||
let snapshot = match current {
|
||||
Some(existing) => {
|
||||
@@ -196,8 +196,9 @@ pub(crate) fn upsert_asset_object(
|
||||
pub(crate) fn has_asset_object(ctx: &ReducerContext, asset_object_id: &str) -> bool {
|
||||
ctx.db
|
||||
.asset_object()
|
||||
.iter()
|
||||
.any(|row| row.asset_object_id == asset_object_id)
|
||||
.asset_object_id()
|
||||
.find(&asset_object_id.to_string())
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn list_asset_history(
|
||||
@@ -224,8 +225,8 @@ fn list_asset_history(
|
||||
let mut entries = ctx
|
||||
.db
|
||||
.asset_object()
|
||||
.iter()
|
||||
.filter(|row| row.asset_kind == asset_kind)
|
||||
.asset_kind()
|
||||
.filter(&asset_kind.to_string())
|
||||
.map(|row| AssetHistoryEntrySnapshot {
|
||||
asset_object_id: row.asset_object_id,
|
||||
asset_kind: row.asset_kind,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::*;
|
||||
use serde::Serialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
pub(crate) mod tables;
|
||||
@@ -15,7 +14,7 @@ pub fn create_bark_battle_draft(
|
||||
input: BarkBattleDraftCreateInput,
|
||||
) -> BarkBattleProcedureResult {
|
||||
match ctx.try_with_tx(|tx| create_bark_battle_draft_tx(tx, input.clone())) {
|
||||
Ok(snapshot) => bark_battle_json_result(&snapshot),
|
||||
Ok(snapshot) => bark_battle_draft_config_result(snapshot),
|
||||
Err(error) => bark_battle_error_result(error),
|
||||
}
|
||||
}
|
||||
@@ -26,7 +25,7 @@ pub fn update_bark_battle_draft_config(
|
||||
input: BarkBattleDraftConfigUpsertInput,
|
||||
) -> BarkBattleProcedureResult {
|
||||
match ctx.try_with_tx(|tx| update_bark_battle_draft_config_tx(tx, input.clone())) {
|
||||
Ok(snapshot) => bark_battle_json_result(&snapshot),
|
||||
Ok(snapshot) => bark_battle_draft_config_result(snapshot),
|
||||
Err(error) => bark_battle_error_result(error),
|
||||
}
|
||||
}
|
||||
@@ -37,7 +36,7 @@ pub fn publish_bark_battle_work(
|
||||
input: BarkBattleWorkPublishInput,
|
||||
) -> BarkBattleProcedureResult {
|
||||
match ctx.try_with_tx(|tx| publish_bark_battle_work_tx(tx, input.clone())) {
|
||||
Ok(snapshot) => bark_battle_json_result(&snapshot),
|
||||
Ok(snapshot) => bark_battle_runtime_config_result(snapshot),
|
||||
Err(error) => bark_battle_error_result(error),
|
||||
}
|
||||
}
|
||||
@@ -48,7 +47,7 @@ pub fn get_bark_battle_runtime_config(
|
||||
input: BarkBattleRuntimeConfigGetInput,
|
||||
) -> BarkBattleProcedureResult {
|
||||
match ctx.try_with_tx(|tx| get_bark_battle_runtime_config_tx(tx, input.clone())) {
|
||||
Ok(snapshot) => bark_battle_json_result(&snapshot),
|
||||
Ok(snapshot) => bark_battle_runtime_config_result(snapshot),
|
||||
Err(error) => bark_battle_error_result(error),
|
||||
}
|
||||
}
|
||||
@@ -59,7 +58,7 @@ pub fn start_bark_battle_run(
|
||||
input: BarkBattleRunStartInput,
|
||||
) -> BarkBattleProcedureResult {
|
||||
match ctx.try_with_tx(|tx| start_bark_battle_run_tx(tx, input.clone())) {
|
||||
Ok(snapshot) => bark_battle_json_result(&snapshot),
|
||||
Ok(snapshot) => bark_battle_run_result(snapshot),
|
||||
Err(error) => bark_battle_error_result(error),
|
||||
}
|
||||
}
|
||||
@@ -70,7 +69,7 @@ pub fn finish_bark_battle_run(
|
||||
input: BarkBattleRunFinishInput,
|
||||
) -> BarkBattleProcedureResult {
|
||||
match ctx.try_with_tx(|tx| finish_bark_battle_run_tx(tx, input.clone())) {
|
||||
Ok(snapshot) => bark_battle_json_result(&snapshot),
|
||||
Ok(snapshot) => bark_battle_run_result(snapshot),
|
||||
Err(error) => bark_battle_error_result(error),
|
||||
}
|
||||
}
|
||||
@@ -81,7 +80,7 @@ pub fn get_bark_battle_run(
|
||||
input: BarkBattleRunGetInput,
|
||||
) -> BarkBattleProcedureResult {
|
||||
match ctx.try_with_tx(|tx| get_bark_battle_run_tx(tx, input.clone())) {
|
||||
Ok(snapshot) => bark_battle_json_result(&snapshot),
|
||||
Ok(snapshot) => bark_battle_run_result(snapshot),
|
||||
Err(error) => bark_battle_error_result(error),
|
||||
}
|
||||
}
|
||||
@@ -584,10 +583,36 @@ fn validate_json<T: DeserializeOwned>(value: &str, field_name: &str) -> Result<(
|
||||
.map_err(|error| format!("bark_battle {field_name} JSON 无效: {error}"))
|
||||
}
|
||||
|
||||
fn bark_battle_json_result<T: Serialize>(value: &T) -> BarkBattleProcedureResult {
|
||||
fn bark_battle_draft_config_result(
|
||||
draft_config: BarkBattleDraftConfigSnapshot,
|
||||
) -> BarkBattleProcedureResult {
|
||||
BarkBattleProcedureResult {
|
||||
ok: true,
|
||||
row_json: Some(to_json_string(value)),
|
||||
draft_config: Some(draft_config),
|
||||
runtime_config: None,
|
||||
run: None,
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn bark_battle_runtime_config_result(
|
||||
runtime_config: BarkBattleRuntimeConfigSnapshot,
|
||||
) -> BarkBattleProcedureResult {
|
||||
BarkBattleProcedureResult {
|
||||
ok: true,
|
||||
draft_config: None,
|
||||
runtime_config: Some(runtime_config),
|
||||
run: None,
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn bark_battle_run_result(run: BarkBattleRunSnapshot) -> BarkBattleProcedureResult {
|
||||
BarkBattleProcedureResult {
|
||||
ok: true,
|
||||
draft_config: None,
|
||||
runtime_config: None,
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -595,7 +620,9 @@ fn bark_battle_json_result<T: Serialize>(value: &T) -> BarkBattleProcedureResult
|
||||
fn bark_battle_error_result(error: String) -> BarkBattleProcedureResult {
|
||||
BarkBattleProcedureResult {
|
||||
ok: false,
|
||||
row_json: None,
|
||||
draft_config: None,
|
||||
runtime_config: None,
|
||||
run: None,
|
||||
error_message: Some(error),
|
||||
}
|
||||
}
|
||||
@@ -850,7 +877,21 @@ mod tests {
|
||||
|
||||
let result = BarkBattleProcedureResult {
|
||||
ok: true,
|
||||
row_json: Some(input.config_json.clone()),
|
||||
draft_config: Some(BarkBattleDraftConfigSnapshot {
|
||||
draft_id: input.draft_id.clone(),
|
||||
owner_user_id: input.owner_user_id.clone(),
|
||||
work_id: input.work_id.clone(),
|
||||
config_version: input.config_version,
|
||||
ruleset_version: input.ruleset_version.clone(),
|
||||
difficulty_preset: input.difficulty_preset.clone(),
|
||||
leaderboard_enabled: input.leaderboard_enabled,
|
||||
config_json: input.config_json.clone(),
|
||||
editor_state_json: "{}".to_string(),
|
||||
created_at_micros: 1_700_000,
|
||||
updated_at_micros: input.updated_at_micros,
|
||||
}),
|
||||
runtime_config: None,
|
||||
run: None,
|
||||
error_message: None,
|
||||
};
|
||||
|
||||
|
||||
@@ -102,14 +102,16 @@ pub struct BarkBattleRunGetInput {
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct BarkBattleProcedureResult {
|
||||
pub ok: bool,
|
||||
pub row_json: Option<String>,
|
||||
pub draft_config: Option<BarkBattleDraftConfigSnapshot>,
|
||||
pub runtime_config: Option<BarkBattleRuntimeConfigSnapshot>,
|
||||
pub run: Option<BarkBattleRunSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BarkBattleEditorConfigSnapshot {
|
||||
pub title: String,
|
||||
@@ -121,7 +123,7 @@ pub struct BarkBattleEditorConfigSnapshot {
|
||||
pub leaderboard_enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BarkBattleDraftConfigSnapshot {
|
||||
pub draft_id: String,
|
||||
@@ -137,7 +139,7 @@ pub struct BarkBattleDraftConfigSnapshot {
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BarkBattleRuntimeConfigSnapshot {
|
||||
pub work_id: String,
|
||||
@@ -153,7 +155,7 @@ pub struct BarkBattleRuntimeConfigSnapshot {
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BarkBattleRunSnapshot {
|
||||
pub run_id: String,
|
||||
|
||||
@@ -222,8 +222,8 @@ pub(crate) fn list_big_fish_asset_slots(
|
||||
let mut slots = ctx
|
||||
.db
|
||||
.big_fish_asset_slot()
|
||||
.iter()
|
||||
.filter(|slot| slot.session_id == session_id)
|
||||
.by_big_fish_asset_session_id()
|
||||
.filter(&session_id.to_string())
|
||||
.map(|slot| BigFishAssetSlotSnapshot {
|
||||
slot_id: slot.slot_id,
|
||||
session_id: slot.session_id,
|
||||
|
||||
@@ -16,12 +16,12 @@ pub fn start_big_fish_run(
|
||||
match ctx.try_with_tx(|tx| start_big_fish_run_tx(tx, input.clone())) {
|
||||
Ok(run) => BigFishRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_big_fish_run_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => BigFishRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -35,12 +35,12 @@ pub fn get_big_fish_run(
|
||||
match ctx.try_with_tx(|tx| get_big_fish_run_tx(tx, input.clone())) {
|
||||
Ok(run) => BigFishRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_big_fish_run_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => BigFishRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -54,12 +54,12 @@ pub fn submit_big_fish_input(
|
||||
match ctx.try_with_tx(|tx| submit_big_fish_input_tx(tx, input.clone())) {
|
||||
Ok(run) => BigFishRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_big_fish_run_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => BigFishRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -225,7 +225,3 @@ fn replace_big_fish_runtime_run(
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_big_fish_run_json(run: &BigFishRuntimeSnapshot) -> String {
|
||||
serialize_runtime_snapshot(run).unwrap_or_else(|_| "{}".to_string())
|
||||
}
|
||||
|
||||
@@ -88,21 +88,14 @@ pub fn list_big_fish_works(
|
||||
input: BigFishWorksListInput,
|
||||
) -> BigFishWorksProcedureResult {
|
||||
match ctx.try_with_tx(|tx| list_big_fish_works_tx(tx, input.clone())) {
|
||||
Ok(items) => match serde_json::to_string(&items) {
|
||||
Ok(items_json) => BigFishWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(items_json),
|
||||
error_message: None,
|
||||
},
|
||||
Err(error) => BigFishWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
error_message: Some(error.to_string()),
|
||||
},
|
||||
Ok(items) => BigFishWorksProcedureResult {
|
||||
ok: true,
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => BigFishWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -114,21 +107,14 @@ pub fn delete_big_fish_work(
|
||||
input: BigFishWorkDeleteInput,
|
||||
) -> BigFishWorksProcedureResult {
|
||||
match ctx.try_with_tx(|tx| delete_big_fish_work_tx(tx, input.clone())) {
|
||||
Ok(items) => match serde_json::to_string(&items) {
|
||||
Ok(items_json) => BigFishWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(items_json),
|
||||
error_message: None,
|
||||
},
|
||||
Err(error) => BigFishWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
error_message: Some(error.to_string()),
|
||||
},
|
||||
Ok(items) => BigFishWorksProcedureResult {
|
||||
ok: true,
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => BigFishWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -140,21 +126,14 @@ pub fn record_big_fish_play(
|
||||
input: BigFishPlayRecordInput,
|
||||
) -> BigFishWorksProcedureResult {
|
||||
match ctx.try_with_tx(|tx| record_big_fish_play_tx(tx, input.clone())) {
|
||||
Ok(items) => match serde_json::to_string(&items) {
|
||||
Ok(items_json) => BigFishWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(items_json),
|
||||
error_message: None,
|
||||
},
|
||||
Err(error) => BigFishWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
error_message: Some(error.to_string()),
|
||||
},
|
||||
Ok(items) => BigFishWorksProcedureResult {
|
||||
ok: true,
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => BigFishWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -166,21 +145,14 @@ pub fn record_big_fish_like(
|
||||
input: BigFishWorkLikeRecordInput,
|
||||
) -> BigFishWorksProcedureResult {
|
||||
match ctx.try_with_tx(|tx| record_big_fish_like_tx(tx, input.clone())) {
|
||||
Ok(items) => match serde_json::to_string(&items) {
|
||||
Ok(items_json) => BigFishWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(items_json),
|
||||
error_message: None,
|
||||
},
|
||||
Err(error) => BigFishWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
error_message: Some(error.to_string()),
|
||||
},
|
||||
Ok(items) => BigFishWorksProcedureResult {
|
||||
ok: true,
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => BigFishWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -354,16 +326,20 @@ pub(crate) fn list_big_fish_works_tx(
|
||||
validate_works_list_input(&input).map_err(|error| error.to_string())?;
|
||||
let now_micros = ctx.timestamp.to_micros_since_unix_epoch();
|
||||
|
||||
let mut items = ctx
|
||||
let rows = ctx
|
||||
.db
|
||||
.big_fish_creation_session()
|
||||
.by_big_fish_session_owner_user_id()
|
||||
.filter(&input.owner_user_id)
|
||||
.collect::<Vec<_>>();
|
||||
let mut items = rows
|
||||
.iter()
|
||||
.filter(|row| {
|
||||
if input.published_only {
|
||||
return row.stage == BigFishCreationStage::Published;
|
||||
}
|
||||
|
||||
row.owner_user_id == input.owner_user_id && should_include_big_fish_work(ctx, row)
|
||||
should_include_big_fish_work(ctx, row)
|
||||
})
|
||||
.map(|row| build_big_fish_work_summary(ctx, &row, now_micros))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
@@ -382,10 +358,11 @@ fn should_include_big_fish_work(ctx: &ReducerContext, row: &BigFishCreationSessi
|
||||
return true;
|
||||
}
|
||||
|
||||
ctx.db.big_fish_agent_message().iter().any(|message| {
|
||||
message.session_id == row.session_id
|
||||
&& matches!(message.role, BigFishAgentMessageRole::User)
|
||||
})
|
||||
ctx.db
|
||||
.big_fish_agent_message()
|
||||
.by_big_fish_message_session_id()
|
||||
.filter(&row.session_id)
|
||||
.any(|message| matches!(message.role, BigFishAgentMessageRole::User))
|
||||
}
|
||||
|
||||
fn big_fish_session_has_direct_work_content(row: &BigFishCreationSession) -> bool {
|
||||
@@ -420,8 +397,8 @@ pub(crate) fn delete_big_fish_work_tx(
|
||||
for message in ctx
|
||||
.db
|
||||
.big_fish_agent_message()
|
||||
.iter()
|
||||
.filter(|row| row.session_id == input.session_id)
|
||||
.by_big_fish_message_session_id()
|
||||
.filter(&input.session_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
ctx.db
|
||||
@@ -432,8 +409,8 @@ pub(crate) fn delete_big_fish_work_tx(
|
||||
for slot in ctx
|
||||
.db
|
||||
.big_fish_asset_slot()
|
||||
.iter()
|
||||
.filter(|row| row.session_id == input.session_id)
|
||||
.by_big_fish_asset_session_id()
|
||||
.filter(&input.session_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
ctx.db.big_fish_asset_slot().slot_id().delete(&slot.slot_id);
|
||||
@@ -441,8 +418,8 @@ pub(crate) fn delete_big_fish_work_tx(
|
||||
for run in ctx
|
||||
.db
|
||||
.big_fish_runtime_run()
|
||||
.iter()
|
||||
.filter(|row| row.session_id == input.session_id)
|
||||
.by_big_fish_run_session_id()
|
||||
.filter(&input.session_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
ctx.db.big_fish_runtime_run().run_id().delete(&run.run_id);
|
||||
@@ -985,8 +962,8 @@ pub(crate) fn build_big_fish_session_snapshot(
|
||||
let mut messages = ctx
|
||||
.db
|
||||
.big_fish_agent_message()
|
||||
.iter()
|
||||
.filter(|message| message.session_id == row.session_id)
|
||||
.by_big_fish_message_session_id()
|
||||
.filter(&row.session_id)
|
||||
.map(|message| BigFishAgentMessageSnapshot {
|
||||
message_id: message.message_id,
|
||||
session_id: message.session_id,
|
||||
|
||||
@@ -436,7 +436,8 @@ fn delete_custom_world_agent_session_tx(
|
||||
let published_profile = ctx
|
||||
.db
|
||||
.custom_world_profile()
|
||||
.iter()
|
||||
.by_custom_world_profile_owner_user_id()
|
||||
.filter(&input.owner_user_id)
|
||||
.find(|row| {
|
||||
row.owner_user_id == input.owner_user_id
|
||||
&& row.source_agent_session_id.as_deref() == Some(input.session_id.as_str())
|
||||
@@ -471,8 +472,8 @@ fn delete_custom_world_agent_session_tx(
|
||||
for message in ctx
|
||||
.db
|
||||
.custom_world_agent_message()
|
||||
.iter()
|
||||
.filter(|row| row.session_id == input.session_id)
|
||||
.by_custom_world_agent_message_session_id()
|
||||
.filter(&input.session_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
ctx.db
|
||||
@@ -483,8 +484,8 @@ fn delete_custom_world_agent_session_tx(
|
||||
for operation in ctx
|
||||
.db
|
||||
.custom_world_agent_operation()
|
||||
.iter()
|
||||
.filter(|row| row.session_id == input.session_id)
|
||||
.by_custom_world_agent_operation_session_id()
|
||||
.filter(&input.session_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
ctx.db
|
||||
@@ -495,8 +496,8 @@ fn delete_custom_world_agent_session_tx(
|
||||
for card in ctx
|
||||
.db
|
||||
.custom_world_draft_card()
|
||||
.iter()
|
||||
.filter(|row| row.session_id == input.session_id)
|
||||
.by_custom_world_draft_card_session_id()
|
||||
.filter(&input.session_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
ctx.db
|
||||
@@ -1184,9 +1185,17 @@ fn upsert_custom_world_profile_record(
|
||||
.source_agent_session_id
|
||||
.as_ref()
|
||||
.and_then(|session_id| {
|
||||
ctx.db.custom_world_profile().iter().find(|row| {
|
||||
is_same_agent_draft_profile_candidate(row, &input.owner_user_id, session_id)
|
||||
})
|
||||
ctx.db
|
||||
.custom_world_profile()
|
||||
.by_custom_world_profile_owner_user_id()
|
||||
.filter(&input.owner_user_id)
|
||||
.find(|row| {
|
||||
is_same_agent_draft_profile_candidate(
|
||||
row,
|
||||
&input.owner_user_id,
|
||||
session_id,
|
||||
)
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1534,8 +1543,9 @@ fn list_custom_world_profile_snapshots(
|
||||
let mut entries = ctx
|
||||
.db
|
||||
.custom_world_profile()
|
||||
.iter()
|
||||
.filter(|row| row.owner_user_id == input.owner_user_id && row.deleted_at.is_none())
|
||||
.by_custom_world_profile_owner_user_id()
|
||||
.filter(&input.owner_user_id)
|
||||
.filter(|row| row.deleted_at.is_none())
|
||||
.map(|row| build_custom_world_profile_snapshot(&row))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -1676,8 +1686,9 @@ fn get_custom_world_gallery_detail_record_by_code(
|
||||
let gallery_entry = ctx
|
||||
.db
|
||||
.custom_world_gallery_entry()
|
||||
.iter()
|
||||
.find(|row| row.public_work_code == normalized_public_work_code);
|
||||
.by_custom_world_gallery_public_work_code()
|
||||
.filter(&normalized_public_work_code)
|
||||
.next();
|
||||
|
||||
let profile = gallery_entry.as_ref().and_then(|row| {
|
||||
ctx.db
|
||||
@@ -1974,9 +1985,14 @@ fn list_custom_world_work_snapshots(
|
||||
let mut items = Vec::new();
|
||||
let mut active_agent_session_ids = HashSet::new();
|
||||
|
||||
for session in ctx.db.custom_world_agent_session().iter().filter(|row| {
|
||||
row.owner_user_id == input.owner_user_id
|
||||
&& row.stage != RpgAgentStage::Published
|
||||
let sessions = ctx
|
||||
.db
|
||||
.custom_world_agent_session()
|
||||
.by_custom_world_agent_session_owner_user_id()
|
||||
.filter(&input.owner_user_id)
|
||||
.collect::<Vec<_>>();
|
||||
for session in sessions.iter().filter(|row| {
|
||||
row.stage != RpgAgentStage::Published
|
||||
&& should_include_custom_world_agent_session_work(ctx, row)
|
||||
}) {
|
||||
active_agent_session_ids.insert(session.session_id.clone());
|
||||
@@ -2021,8 +2037,9 @@ fn list_custom_world_work_snapshots(
|
||||
for profile in ctx
|
||||
.db
|
||||
.custom_world_profile()
|
||||
.iter()
|
||||
.filter(|row| row.owner_user_id == input.owner_user_id && row.deleted_at.is_none())
|
||||
.by_custom_world_profile_owner_user_id()
|
||||
.filter(&input.owner_user_id)
|
||||
.filter(|row| row.deleted_at.is_none())
|
||||
.filter(|row| should_include_custom_world_profile_work(row, &active_agent_session_ids))
|
||||
{
|
||||
items.push(CustomWorldWorkSummarySnapshot {
|
||||
@@ -2086,16 +2103,20 @@ fn should_include_custom_world_agent_session_work(
|
||||
return true;
|
||||
}
|
||||
|
||||
if ctx.db.custom_world_agent_message().iter().any(|message| {
|
||||
message.session_id == session.session_id
|
||||
&& matches!(message.role, RpgAgentMessageRole::User)
|
||||
}) {
|
||||
if ctx
|
||||
.db
|
||||
.custom_world_agent_message()
|
||||
.by_custom_world_agent_message_session_id()
|
||||
.filter(&session.session_id)
|
||||
.any(|message| matches!(message.role, RpgAgentMessageRole::User))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ctx.db
|
||||
.custom_world_draft_card()
|
||||
.iter()
|
||||
.by_custom_world_draft_card_session_id()
|
||||
.filter(&session.session_id)
|
||||
.any(|card| card.session_id == session.session_id)
|
||||
}
|
||||
|
||||
@@ -3446,10 +3467,12 @@ fn update_role_asset_cards(
|
||||
label: &str,
|
||||
updated_at_micros: i64,
|
||||
) {
|
||||
for card in
|
||||
ctx.db.custom_world_draft_card().iter().filter(|row| {
|
||||
row.session_id == session_id && row.kind == RpgAgentDraftCardKind::Character
|
||||
})
|
||||
for card in ctx
|
||||
.db
|
||||
.custom_world_draft_card()
|
||||
.by_custom_world_draft_card_session_id()
|
||||
.filter(&session_id.to_string())
|
||||
.filter(|row| row.kind == RpgAgentDraftCardKind::Character)
|
||||
{
|
||||
replace_custom_world_draft_card(
|
||||
ctx,
|
||||
@@ -4590,8 +4613,8 @@ fn resolve_session_work_counts(
|
||||
for card in ctx
|
||||
.db
|
||||
.custom_world_draft_card()
|
||||
.iter()
|
||||
.filter(|row| row.session_id == session.session_id)
|
||||
.by_custom_world_draft_card_session_id()
|
||||
.filter(&session.session_id)
|
||||
{
|
||||
match card.kind {
|
||||
RpgAgentDraftCardKind::Character => {
|
||||
@@ -4827,11 +4850,9 @@ fn sync_missing_custom_world_gallery_entries(ctx: &ReducerContext) -> Result<(),
|
||||
let published_profiles = ctx
|
||||
.db
|
||||
.custom_world_profile()
|
||||
.iter()
|
||||
.filter(|profile| {
|
||||
profile.publication_status == CustomWorldPublicationStatus::Published
|
||||
&& profile.deleted_at.is_none()
|
||||
})
|
||||
.by_custom_world_profile_publication_status()
|
||||
.filter(CustomWorldPublicationStatus::Published)
|
||||
.filter(|profile| profile.deleted_at.is_none())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for profile in published_profiles {
|
||||
@@ -4973,8 +4994,8 @@ fn build_custom_world_agent_session_snapshot(
|
||||
let mut messages = ctx
|
||||
.db
|
||||
.custom_world_agent_message()
|
||||
.iter()
|
||||
.filter(|message| message.session_id == row.session_id)
|
||||
.by_custom_world_agent_message_session_id()
|
||||
.filter(&row.session_id)
|
||||
.map(|message| build_custom_world_agent_message_snapshot(&message))
|
||||
.collect::<Vec<_>>();
|
||||
messages.sort_by_key(|message| (message.created_at_micros, message.message_id.clone()));
|
||||
@@ -4982,8 +5003,8 @@ fn build_custom_world_agent_session_snapshot(
|
||||
let mut draft_cards = ctx
|
||||
.db
|
||||
.custom_world_draft_card()
|
||||
.iter()
|
||||
.filter(|card| card.session_id == row.session_id)
|
||||
.by_custom_world_draft_card_session_id()
|
||||
.filter(&row.session_id)
|
||||
.map(|card| build_custom_world_draft_card_snapshot(&card))
|
||||
.collect::<Vec<_>>();
|
||||
draft_cards.sort_by_key(|card| (card.created_at_micros, card.card_id.clone()));
|
||||
@@ -4991,8 +5012,8 @@ fn build_custom_world_agent_session_snapshot(
|
||||
let mut operations = ctx
|
||||
.db
|
||||
.custom_world_agent_operation()
|
||||
.iter()
|
||||
.filter(|operation| operation.session_id == row.session_id)
|
||||
.by_custom_world_agent_operation_session_id()
|
||||
.filter(&row.session_id)
|
||||
.map(|operation| build_custom_world_agent_operation_snapshot(&operation))
|
||||
.collect::<Vec<_>>();
|
||||
operations
|
||||
|
||||
@@ -415,11 +415,9 @@ fn apply_inventory_mutation_tx(
|
||||
let current_slots = ctx
|
||||
.db
|
||||
.inventory_slot()
|
||||
.iter()
|
||||
.filter(|slot| {
|
||||
slot.runtime_session_id == input.runtime_session_id
|
||||
&& slot.actor_user_id == input.actor_user_id
|
||||
})
|
||||
.by_inventory_runtime_session_id()
|
||||
.filter(&input.runtime_session_id)
|
||||
.filter(|slot| slot.actor_user_id == input.actor_user_id)
|
||||
.map(|row| build_inventory_slot_snapshot_from_row(&row))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -587,11 +585,9 @@ fn get_runtime_inventory_state_tx(
|
||||
let slots = ctx
|
||||
.db
|
||||
.inventory_slot()
|
||||
.iter()
|
||||
.filter(|row| {
|
||||
row.runtime_session_id == validated_input.runtime_session_id
|
||||
&& row.actor_user_id == validated_input.actor_user_id
|
||||
})
|
||||
.by_inventory_runtime_session_id()
|
||||
.filter(&validated_input.runtime_session_id)
|
||||
.filter(|row| row.actor_user_id == validated_input.actor_user_id)
|
||||
.map(|row| build_inventory_slot_snapshot_from_row(&row))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -926,8 +922,8 @@ fn get_story_session_state_tx(
|
||||
let mut events = ctx
|
||||
.db
|
||||
.story_event()
|
||||
.iter()
|
||||
.filter(|row| row.story_session_id == input.story_session_id)
|
||||
.by_story_session_id()
|
||||
.filter(&input.story_session_id)
|
||||
.map(|row| build_story_event_snapshot_from_row(&row))
|
||||
.collect::<Vec<_>>();
|
||||
events.sort_by_key(|event| (event.created_at_micros, event.event_id.clone()));
|
||||
@@ -1439,11 +1435,9 @@ fn inventory_reward_source_already_granted(
|
||||
|
||||
ctx.db
|
||||
.inventory_slot()
|
||||
.iter()
|
||||
.filter(|row| {
|
||||
row.runtime_session_id == first_mutation.runtime_session_id
|
||||
&& row.actor_user_id == first_mutation.actor_user_id
|
||||
})
|
||||
.by_inventory_runtime_session_id()
|
||||
.filter(&first_mutation.runtime_session_id)
|
||||
.filter(|row| row.actor_user_id == first_mutation.actor_user_id)
|
||||
.any(|row| row.source_reference_id.as_deref() == Some(source_reference_id))
|
||||
}
|
||||
|
||||
|
||||
@@ -161,12 +161,12 @@ pub fn list_match3d_works(
|
||||
match ctx.try_with_tx(|tx| list_match3d_works_tx(tx, input.clone())) {
|
||||
Ok(items) => Match3DWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(to_json_string(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => Match3DWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -191,12 +191,12 @@ pub fn delete_match3d_work(
|
||||
match ctx.try_with_tx(|tx| delete_match3d_work_tx(tx, input.clone())) {
|
||||
Ok(items) => Match3DWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(to_json_string(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => Match3DWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -234,7 +234,7 @@ pub fn click_match3d_item(
|
||||
Err(message) => Match3DClickItemProcedureResult {
|
||||
ok: false,
|
||||
status: MATCH3D_CLICK_REJECTED_NOT_CLICKABLE.to_string(),
|
||||
run_json: None,
|
||||
run: None,
|
||||
accepted_item_instance_id: None,
|
||||
cleared_item_instance_ids: Vec::new(),
|
||||
failure_reason: None,
|
||||
@@ -690,17 +690,22 @@ fn list_match3d_works_tx(
|
||||
ctx: &ReducerContext,
|
||||
input: Match3DWorksListInput,
|
||||
) -> Result<Vec<Match3DWorkSnapshot>, String> {
|
||||
let mut items = ctx
|
||||
.db
|
||||
.match3d_work_profile()
|
||||
let rows = if input.published_only {
|
||||
ctx.db
|
||||
.match3d_work_profile()
|
||||
.by_match3d_work_publication_status()
|
||||
.filter(&MATCH3D_PUBLICATION_PUBLISHED.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
require_non_empty(&input.owner_user_id, "match3d owner_user_id")?;
|
||||
ctx.db
|
||||
.match3d_work_profile()
|
||||
.by_match3d_work_owner_user_id()
|
||||
.filter(&input.owner_user_id)
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
let mut items = rows
|
||||
.iter()
|
||||
.filter(|row| {
|
||||
if input.published_only {
|
||||
row.publication_status == MATCH3D_PUBLICATION_PUBLISHED
|
||||
} else {
|
||||
row.owner_user_id == input.owner_user_id
|
||||
}
|
||||
})
|
||||
.map(|row| build_work_snapshot(&row))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
items.sort_by(|left, right| {
|
||||
@@ -741,10 +746,9 @@ fn delete_match3d_work_tx(
|
||||
for run in ctx
|
||||
.db
|
||||
.match3d_runtime_run()
|
||||
.iter()
|
||||
.filter(|row| {
|
||||
row.profile_id == input.profile_id && row.owner_user_id == input.owner_user_id
|
||||
})
|
||||
.by_match3d_run_profile_id()
|
||||
.filter(&input.profile_id)
|
||||
.filter(|row| row.owner_user_id == input.owner_user_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
ctx.db.match3d_runtime_run().run_id().delete(&run.run_id);
|
||||
@@ -987,8 +991,8 @@ fn build_session_snapshot(
|
||||
let mut messages = ctx
|
||||
.db
|
||||
.match3d_agent_message()
|
||||
.iter()
|
||||
.filter(|message| message.session_id == row.session_id)
|
||||
.by_match3d_agent_message_session_id()
|
||||
.filter(&row.session_id)
|
||||
.map(|message| Match3DAgentMessageSnapshot {
|
||||
message_id: message.message_id,
|
||||
session_id: message.session_id,
|
||||
@@ -1241,10 +1245,10 @@ fn click_result(
|
||||
Match3DClickItemProcedureResult {
|
||||
ok: true,
|
||||
status: status.to_string(),
|
||||
run_json: Some(to_json_string(&snapshot)),
|
||||
failure_reason: snapshot.failure_reason.clone(),
|
||||
run: Some(snapshot),
|
||||
accepted_item_instance_id,
|
||||
cleared_item_instance_ids,
|
||||
failure_reason: snapshot.failure_reason,
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -1802,7 +1806,7 @@ fn to_json_string<T: Serialize>(value: &T) -> String {
|
||||
fn session_result(session: Match3DAgentSessionSnapshot) -> Match3DAgentSessionProcedureResult {
|
||||
Match3DAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(to_json_string(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -1810,7 +1814,7 @@ fn session_result(session: Match3DAgentSessionSnapshot) -> Match3DAgentSessionPr
|
||||
fn session_error(message: String) -> Match3DAgentSessionProcedureResult {
|
||||
Match3DAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
}
|
||||
}
|
||||
@@ -1818,7 +1822,7 @@ fn session_error(message: String) -> Match3DAgentSessionProcedureResult {
|
||||
fn work_result(work: Match3DWorkSnapshot) -> Match3DWorkProcedureResult {
|
||||
Match3DWorkProcedureResult {
|
||||
ok: true,
|
||||
work_json: Some(to_json_string(&work)),
|
||||
work: Some(work),
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -1826,7 +1830,7 @@ fn work_result(work: Match3DWorkSnapshot) -> Match3DWorkProcedureResult {
|
||||
fn work_error(message: String) -> Match3DWorkProcedureResult {
|
||||
Match3DWorkProcedureResult {
|
||||
ok: false,
|
||||
work_json: None,
|
||||
work: None,
|
||||
error_message: Some(message),
|
||||
}
|
||||
}
|
||||
@@ -1834,7 +1838,7 @@ fn work_error(message: String) -> Match3DWorkProcedureResult {
|
||||
fn run_result(run: Match3DRunSnapshot) -> Match3DRunProcedureResult {
|
||||
Match3DRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(to_json_string(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -1842,7 +1846,7 @@ fn run_result(run: Match3DRunSnapshot) -> Match3DRunProcedureResult {
|
||||
fn run_error(message: String) -> Match3DRunProcedureResult {
|
||||
Match3DRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,43 +182,43 @@ pub struct Match3DRunTimeUpInput {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub struct Match3DAgentSessionProcedureResult {
|
||||
pub ok: bool,
|
||||
pub session_json: Option<String>,
|
||||
pub session: Option<Match3DAgentSessionSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub struct Match3DWorkProcedureResult {
|
||||
pub ok: bool,
|
||||
pub work_json: Option<String>,
|
||||
pub work: Option<Match3DWorkSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub struct Match3DWorksProcedureResult {
|
||||
pub ok: bool,
|
||||
pub items_json: Option<String>,
|
||||
pub items: Vec<Match3DWorkSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct Match3DRunProcedureResult {
|
||||
pub ok: bool,
|
||||
pub run_json: Option<String>,
|
||||
pub run: Option<Match3DRunSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct Match3DClickItemProcedureResult {
|
||||
pub ok: bool,
|
||||
pub status: String,
|
||||
pub run_json: Option<String>,
|
||||
pub run: Option<Match3DRunSnapshot>,
|
||||
pub accepted_item_instance_id: Option<String>,
|
||||
pub cleared_item_instance_ids: Vec<String>,
|
||||
pub failure_reason: Option<String>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Match3DCreatorConfigSnapshot {
|
||||
pub theme_text: String,
|
||||
@@ -235,7 +235,7 @@ pub struct Match3DCreatorConfigSnapshot {
|
||||
pub generate_click_sound: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Match3DAgentMessageSnapshot {
|
||||
pub message_id: String,
|
||||
@@ -246,7 +246,7 @@ pub struct Match3DAgentMessageSnapshot {
|
||||
pub created_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Match3DDraftSnapshot {
|
||||
pub profile_id: String,
|
||||
@@ -260,7 +260,7 @@ pub struct Match3DDraftSnapshot {
|
||||
pub generated_item_assets_json: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Match3DAgentSessionSnapshot {
|
||||
pub session_id: String,
|
||||
@@ -278,7 +278,7 @@ pub struct Match3DAgentSessionSnapshot {
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Match3DWorkSnapshot {
|
||||
pub profile_id: String,
|
||||
@@ -302,7 +302,7 @@ pub struct Match3DWorkSnapshot {
|
||||
pub generated_item_assets_json: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Match3DItemSnapshot {
|
||||
pub item_instance_id: String,
|
||||
@@ -316,7 +316,7 @@ pub struct Match3DItemSnapshot {
|
||||
pub clickable: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Match3DTraySlotSnapshot {
|
||||
pub slot_index: u32,
|
||||
@@ -325,7 +325,7 @@ pub struct Match3DTraySlotSnapshot {
|
||||
pub visual_key: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Match3DRunSnapshot {
|
||||
pub run_id: String,
|
||||
|
||||
@@ -125,19 +125,17 @@ pub fn puzzle_gallery_view(ctx: &AnonymousViewContext) -> Vec<PuzzleWorkProfile>
|
||||
.puzzle_work_profile()
|
||||
.by_puzzle_work_publication_status()
|
||||
.filter(PuzzlePublicationStatus::Published)
|
||||
.filter_map(
|
||||
|row| match build_puzzle_work_profile_from_row_without_recent_count(&row) {
|
||||
Ok(profile) => Some(profile),
|
||||
Err(error) => {
|
||||
log::warn!(
|
||||
"拼图广场 view 跳过损坏的作品投影 profile_id={}: {}",
|
||||
row.profile_id,
|
||||
error
|
||||
);
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
.filter_map(|row| match build_puzzle_work_profile_from_row_without_recent_count(&row) {
|
||||
Ok(profile) => Some(profile),
|
||||
Err(error) => {
|
||||
log::warn!(
|
||||
"拼图广场 view 跳过损坏的作品投影 profile_id={}: {}",
|
||||
row.profile_id,
|
||||
error
|
||||
);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
items.sort_by(|left, right| right.updated_at_micros.cmp(&left.updated_at_micros));
|
||||
items
|
||||
@@ -218,12 +216,12 @@ pub fn create_puzzle_agent_session(
|
||||
match ctx.try_with_tx(|tx| create_puzzle_agent_session_tx(tx, input.clone())) {
|
||||
Ok(session) => PuzzleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(serialize_json(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -237,12 +235,12 @@ pub fn get_puzzle_agent_session(
|
||||
match ctx.try_with_tx(|tx| get_puzzle_agent_session_tx(tx, input.clone())) {
|
||||
Ok(session) => PuzzleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(serialize_json(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -256,12 +254,12 @@ pub fn submit_puzzle_agent_message(
|
||||
match ctx.try_with_tx(|tx| submit_puzzle_agent_message_tx(tx, input.clone())) {
|
||||
Ok(session) => PuzzleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(serialize_json(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -275,12 +273,12 @@ pub fn finalize_puzzle_agent_message_turn(
|
||||
match ctx.try_with_tx(|tx| finalize_puzzle_agent_message_turn_tx(tx, input.clone())) {
|
||||
Ok(session) => PuzzleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(serialize_json(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -294,12 +292,12 @@ pub fn compile_puzzle_agent_draft(
|
||||
match ctx.try_with_tx(|tx| compile_puzzle_agent_draft_tx(tx, input.clone())) {
|
||||
Ok(session) => PuzzleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(serialize_json(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -315,12 +313,12 @@ pub fn save_puzzle_form_draft(
|
||||
match ctx.try_with_tx(|tx| save_puzzle_form_draft_tx(tx, input.clone())) {
|
||||
Ok(session) => PuzzleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(serialize_json(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -334,12 +332,12 @@ pub fn save_puzzle_generated_images(
|
||||
match ctx.try_with_tx(|tx| save_puzzle_generated_images_tx(tx, input.clone())) {
|
||||
Ok(session) => PuzzleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(serialize_json(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -353,12 +351,12 @@ pub fn save_puzzle_ui_background(
|
||||
match ctx.try_with_tx(|tx| save_puzzle_ui_background_tx(tx, input.clone())) {
|
||||
Ok(session) => PuzzleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(serialize_json(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -372,12 +370,12 @@ pub fn select_puzzle_cover_image(
|
||||
match ctx.try_with_tx(|tx| select_puzzle_cover_image_tx(tx, input.clone())) {
|
||||
Ok(session) => PuzzleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(serialize_json(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -391,12 +389,12 @@ pub fn publish_puzzle_work(
|
||||
match ctx.try_with_tx(|tx| publish_puzzle_work_tx(tx, input.clone())) {
|
||||
Ok(item) => PuzzleWorkProcedureResult {
|
||||
ok: true,
|
||||
item_json: Some(serialize_json(&item)),
|
||||
item: Some(item),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleWorkProcedureResult {
|
||||
ok: false,
|
||||
item_json: None,
|
||||
item: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -410,12 +408,12 @@ pub fn list_puzzle_works(
|
||||
match ctx.try_with_tx(|tx| list_puzzle_works_tx(tx, input.clone())) {
|
||||
Ok(items) => PuzzleWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(serialize_json(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -429,12 +427,12 @@ pub fn get_puzzle_work_detail(
|
||||
match ctx.try_with_tx(|tx| get_puzzle_work_detail_tx(tx, input.clone())) {
|
||||
Ok(item) => PuzzleWorkProcedureResult {
|
||||
ok: true,
|
||||
item_json: Some(serialize_json(&item)),
|
||||
item: Some(item),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleWorkProcedureResult {
|
||||
ok: false,
|
||||
item_json: None,
|
||||
item: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -448,12 +446,12 @@ pub fn update_puzzle_work(
|
||||
match ctx.try_with_tx(|tx| update_puzzle_work_tx(tx, input.clone())) {
|
||||
Ok(item) => PuzzleWorkProcedureResult {
|
||||
ok: true,
|
||||
item_json: Some(serialize_json(&item)),
|
||||
item: Some(item),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleWorkProcedureResult {
|
||||
ok: false,
|
||||
item_json: None,
|
||||
item: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -467,12 +465,12 @@ pub fn delete_puzzle_work(
|
||||
match ctx.try_with_tx(|tx| delete_puzzle_work_tx(tx, input.clone())) {
|
||||
Ok(items) => PuzzleWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(serialize_json(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -483,12 +481,12 @@ pub fn list_puzzle_gallery(ctx: &mut ProcedureContext) -> PuzzleWorksProcedureRe
|
||||
match ctx.try_with_tx(|tx| list_puzzle_gallery_tx(tx)) {
|
||||
Ok(items) => PuzzleWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(serialize_json(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -502,12 +500,12 @@ pub fn get_puzzle_gallery_detail(
|
||||
match ctx.try_with_tx(|tx| get_puzzle_gallery_detail_tx(tx, input.clone())) {
|
||||
Ok(item) => PuzzleWorkProcedureResult {
|
||||
ok: true,
|
||||
item_json: Some(serialize_json(&item)),
|
||||
item: Some(item),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleWorkProcedureResult {
|
||||
ok: false,
|
||||
item_json: None,
|
||||
item: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -521,12 +519,12 @@ pub fn record_puzzle_work_like(
|
||||
match ctx.try_with_tx(|tx| record_puzzle_work_like_tx(tx, input.clone())) {
|
||||
Ok(item) => PuzzleWorkProcedureResult {
|
||||
ok: true,
|
||||
item_json: Some(serialize_json(&item)),
|
||||
item: Some(item),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleWorkProcedureResult {
|
||||
ok: false,
|
||||
item_json: None,
|
||||
item: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -540,12 +538,12 @@ pub fn remix_puzzle_work(
|
||||
match ctx.try_with_tx(|tx| remix_puzzle_work_tx(tx, input.clone())) {
|
||||
Ok(session) => PuzzleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(serialize_json(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -559,12 +557,12 @@ pub fn start_puzzle_run(
|
||||
match ctx.try_with_tx(|tx| start_puzzle_run_tx(tx, input.clone())) {
|
||||
Ok(run) => PuzzleRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -578,12 +576,12 @@ pub fn get_puzzle_run(
|
||||
match ctx.try_with_tx(|tx| get_puzzle_run_tx(tx, input.clone())) {
|
||||
Ok(run) => PuzzleRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -597,12 +595,12 @@ pub fn swap_puzzle_pieces(
|
||||
match ctx.try_with_tx(|tx| swap_puzzle_pieces_tx(tx, input.clone())) {
|
||||
Ok(run) => PuzzleRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -616,12 +614,12 @@ pub fn drag_puzzle_piece_or_group(
|
||||
match ctx.try_with_tx(|tx| drag_puzzle_piece_or_group_tx(tx, input.clone())) {
|
||||
Ok(run) => PuzzleRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -635,12 +633,12 @@ pub fn advance_puzzle_next_level(
|
||||
match ctx.try_with_tx(|tx| advance_puzzle_next_level_tx(tx, input.clone())) {
|
||||
Ok(run) => PuzzleRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -654,12 +652,12 @@ pub fn update_puzzle_run_pause(
|
||||
match ctx.try_with_tx(|tx| update_puzzle_run_pause_tx(tx, input.clone())) {
|
||||
Ok(run) => PuzzleRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -673,12 +671,12 @@ pub fn use_puzzle_runtime_prop(
|
||||
match ctx.try_with_tx(|tx| use_puzzle_runtime_prop_tx(tx, input.clone())) {
|
||||
Ok(run) => PuzzleRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -692,12 +690,12 @@ pub fn claim_puzzle_work_point_incentive(
|
||||
match ctx.try_with_tx(|tx| claim_puzzle_work_point_incentive_tx(tx, input.clone())) {
|
||||
Ok(item) => PuzzleWorkProcedureResult {
|
||||
ok: true,
|
||||
item_json: Some(serialize_json(&item)),
|
||||
item: Some(item),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleWorkProcedureResult {
|
||||
ok: false,
|
||||
item_json: None,
|
||||
item: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -711,12 +709,12 @@ pub fn submit_puzzle_leaderboard_entry(
|
||||
match ctx.try_with_tx(|tx| submit_puzzle_leaderboard_entry_tx(tx, input.clone())) {
|
||||
Ok(run) => PuzzleRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(serialize_json(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => PuzzleRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -901,10 +899,7 @@ fn compile_puzzle_agent_draft_tx(
|
||||
}
|
||||
let anchor_pack = infer_anchor_pack(&row.seed_text, Some(&row.seed_text));
|
||||
let messages = list_session_messages(ctx, &row.session_id);
|
||||
let draft = mark_puzzle_draft_generation_status(
|
||||
compile_result_draft_from_seed(&anchor_pack, &messages, Some(&row.seed_text)),
|
||||
"generating",
|
||||
);
|
||||
let draft = compile_result_draft_from_seed(&anchor_pack, &messages, Some(&row.seed_text));
|
||||
// 创作中心的拼图草稿卡只是 Agent session 的列表投影,
|
||||
// 每次编译结果页时同步 upsert,保证后续能按 source_session_id 恢复聊天。
|
||||
upsert_puzzle_draft_work_profile(
|
||||
@@ -2505,52 +2500,10 @@ fn profile_for_single_level(
|
||||
level: &module_puzzle::PuzzleDraftLevel,
|
||||
) -> PuzzleWorkProfile {
|
||||
let mut next_profile = profile.clone();
|
||||
let ui_background_carrier = profile.levels.iter().find(|candidate| {
|
||||
candidate
|
||||
.ui_background_image_src
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.map(|value| !value.is_empty())
|
||||
.unwrap_or(false)
|
||||
|| candidate
|
||||
.ui_background_image_object_key
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.map(|value| !value.is_empty())
|
||||
.unwrap_or(false)
|
||||
});
|
||||
let mut single_level = level.clone();
|
||||
if single_level
|
||||
.ui_background_image_src
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.unwrap_or("")
|
||||
.is_empty()
|
||||
&& single_level
|
||||
.ui_background_image_object_key
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.unwrap_or("")
|
||||
.is_empty()
|
||||
&& let Some(carrier) = ui_background_carrier
|
||||
{
|
||||
single_level.ui_background_image_src = carrier
|
||||
.ui_background_image_src
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.map(str::to_string);
|
||||
single_level.ui_background_image_object_key = carrier
|
||||
.ui_background_image_object_key
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.map(|value| value.trim_start_matches('/').to_string());
|
||||
}
|
||||
next_profile.level_name = level.level_name.clone();
|
||||
next_profile.cover_image_src = level.cover_image_src.clone();
|
||||
next_profile.cover_asset_id = level.cover_asset_id.clone();
|
||||
next_profile.levels = vec![single_level];
|
||||
next_profile.levels = vec![level.clone()];
|
||||
next_profile
|
||||
}
|
||||
|
||||
@@ -2571,17 +2524,6 @@ fn micros_to_millis(value: i64) -> u64 {
|
||||
(value as u64).saturating_div(1_000)
|
||||
}
|
||||
|
||||
fn mark_puzzle_draft_generation_status(
|
||||
mut draft: PuzzleResultDraft,
|
||||
generation_status: &str,
|
||||
) -> PuzzleResultDraft {
|
||||
draft.generation_status = generation_status.to_string();
|
||||
for level in &mut draft.levels {
|
||||
level.generation_status = generation_status.to_string();
|
||||
}
|
||||
draft
|
||||
}
|
||||
|
||||
fn upsert_puzzle_draft_work_profile(
|
||||
ctx: &TxContext,
|
||||
session_id: &str,
|
||||
@@ -3552,37 +3494,6 @@ mod tests {
|
||||
assert!(preview.publish_ready);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn puzzle_draft_generation_status_updates_all_levels() {
|
||||
let anchor_pack = infer_anchor_pack("蒸汽城市雨夜猫咪", Some("蒸汽城市雨夜猫咪"));
|
||||
let mut draft = compile_result_draft(&anchor_pack, &[]);
|
||||
draft.levels.push(module_puzzle::PuzzleDraftLevel {
|
||||
level_id: "puzzle-level-2".to_string(),
|
||||
level_name: "第二关".to_string(),
|
||||
picture_description: "第二关画面".to_string(),
|
||||
picture_reference: None,
|
||||
ui_background_prompt: None,
|
||||
ui_background_image_src: None,
|
||||
ui_background_image_object_key: None,
|
||||
background_music: None,
|
||||
candidates: Vec::new(),
|
||||
selected_candidate_id: None,
|
||||
cover_image_src: None,
|
||||
cover_asset_id: None,
|
||||
generation_status: "idle".to_string(),
|
||||
});
|
||||
|
||||
let draft = mark_puzzle_draft_generation_status(draft, "generating");
|
||||
|
||||
assert_eq!(draft.generation_status, "generating");
|
||||
assert!(
|
||||
draft
|
||||
.levels
|
||||
.iter()
|
||||
.all(|level| level.generation_status == "generating")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn puzzle_generated_images_replace_existing_candidate() {
|
||||
let anchor_pack = infer_anchor_pack("蒸汽城市雨夜猫咪", Some("蒸汽城市雨夜猫咪"));
|
||||
|
||||
@@ -95,8 +95,8 @@ fn list_platform_browse_history_rows(
|
||||
let mut entries = ctx
|
||||
.db
|
||||
.user_browse_history()
|
||||
.iter()
|
||||
.filter(|row| row.user_id == validated_input.user_id)
|
||||
.by_browse_history_user_id()
|
||||
.filter(&validated_input.user_id)
|
||||
.map(|row| build_runtime_browse_history_snapshot_from_row(&row))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -165,8 +165,8 @@ fn clear_platform_browse_history_rows(
|
||||
let row_ids = ctx
|
||||
.db
|
||||
.user_browse_history()
|
||||
.iter()
|
||||
.filter(|row| row.user_id == validated_input.user_id)
|
||||
.by_browse_history_user_id()
|
||||
.filter(&validated_input.user_id)
|
||||
.map(|row| row.browse_history_id.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
||||
@@ -1079,8 +1079,8 @@ pub(crate) fn list_profile_save_archive_rows(
|
||||
let mut entries = ctx
|
||||
.db
|
||||
.profile_save_archive()
|
||||
.iter()
|
||||
.filter(|row| row.user_id == validated_input.user_id)
|
||||
.by_profile_save_archive_user_id()
|
||||
.filter(&validated_input.user_id)
|
||||
.map(|row| build_profile_save_archive_snapshot_from_row(&row))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -1104,10 +1104,12 @@ pub(crate) fn resume_profile_save_archive_record(
|
||||
let archive = ctx
|
||||
.db
|
||||
.profile_save_archive()
|
||||
.iter()
|
||||
.find(|row| {
|
||||
row.user_id == validated_input.user_id && row.world_key == validated_input.world_key
|
||||
})
|
||||
.by_profile_save_archive_user_world_key()
|
||||
.filter((
|
||||
validated_input.user_id.as_str(),
|
||||
validated_input.world_key.as_str(),
|
||||
))
|
||||
.next()
|
||||
.ok_or_else(|| "profile_save_archive 对应 world_key 不存在".to_string())?;
|
||||
|
||||
let existing_snapshot = ctx
|
||||
@@ -2052,8 +2054,8 @@ fn get_profile_dashboard_snapshot(
|
||||
let played_world_count = ctx
|
||||
.db
|
||||
.profile_played_world()
|
||||
.iter()
|
||||
.filter(|row| row.user_id == validated_input.user_id)
|
||||
.by_profile_played_world_user_id()
|
||||
.filter(&validated_input.user_id)
|
||||
.count() as u32;
|
||||
|
||||
Ok(match state {
|
||||
@@ -2084,8 +2086,8 @@ fn list_profile_wallet_ledger_entries(
|
||||
let mut entries = ctx
|
||||
.db
|
||||
.profile_wallet_ledger()
|
||||
.iter()
|
||||
.filter(|row| row.user_id == validated_input.user_id)
|
||||
.by_profile_wallet_ledger_user_id()
|
||||
.filter(&validated_input.user_id)
|
||||
.map(|row| build_profile_wallet_ledger_snapshot_from_row(&row))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -2114,8 +2116,8 @@ fn get_profile_play_stats_snapshot(
|
||||
let mut played_works = ctx
|
||||
.db
|
||||
.profile_played_world()
|
||||
.iter()
|
||||
.filter(|row| row.user_id == validated_input.user_id)
|
||||
.by_profile_played_world_user_id()
|
||||
.filter(&validated_input.user_id)
|
||||
.map(|row| build_profile_played_world_snapshot_from_row(&row))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -2727,17 +2729,16 @@ fn build_profile_referral_invite_center_snapshot(
|
||||
let code = ensure_profile_invite_code(ctx, user_id);
|
||||
let today_inviter_reward_count =
|
||||
count_today_profile_referral_inviter_rewards(ctx, user_id, ctx.timestamp);
|
||||
let invited_count = ctx
|
||||
let invited_relations = ctx
|
||||
.db
|
||||
.profile_referral_relation()
|
||||
.by_profile_referral_inviter_user_id()
|
||||
.filter(user_id)
|
||||
.collect::<Vec<_>>();
|
||||
let invited_count = invited_relations.len() as u32;
|
||||
let rewarded_invite_count = invited_relations
|
||||
.iter()
|
||||
.filter(|row| row.inviter_user_id == user_id)
|
||||
.count() as u32;
|
||||
let rewarded_invite_count = ctx
|
||||
.db
|
||||
.profile_referral_relation()
|
||||
.iter()
|
||||
.filter(|row| row.inviter_user_id == user_id && row.inviter_reward_granted)
|
||||
.filter(|row| row.inviter_reward_granted)
|
||||
.count() as u32;
|
||||
let bound_relation = ctx
|
||||
.db
|
||||
@@ -2918,7 +2919,8 @@ fn count_today_profile_referral_inviter_rewards(
|
||||
let day_start_micros = runtime_profile_day_start_micros(now.to_micros_since_unix_epoch());
|
||||
ctx.db
|
||||
.profile_wallet_ledger()
|
||||
.iter()
|
||||
.by_profile_wallet_ledger_user_id()
|
||||
.filter(user_id)
|
||||
.filter(|row| {
|
||||
row.user_id == user_id
|
||||
&& row.source_type == RuntimeProfileWalletLedgerSourceType::InviteInviterReward
|
||||
@@ -3422,7 +3424,11 @@ fn query_analytics_metric_buckets(
|
||||
let stats = ctx
|
||||
.db
|
||||
.tracking_daily_stat()
|
||||
.iter()
|
||||
.by_tracking_daily_stat_scope_day()
|
||||
.filter((
|
||||
validated_input.scope_kind,
|
||||
validated_input.scope_id.as_str(),
|
||||
))
|
||||
.filter(|row| {
|
||||
row.event_key.trim() == validated_input.event_key
|
||||
&& row.scope_kind == validated_input.scope_kind
|
||||
@@ -4023,27 +4029,39 @@ fn apply_profile_wallet_signed_delta(
|
||||
}
|
||||
|
||||
fn has_profile_points_recharged(ctx: &ReducerContext, user_id: &str) -> bool {
|
||||
ctx.db.profile_recharge_order().iter().any(|row| {
|
||||
row.user_id == user_id
|
||||
&& row.kind == RuntimeProfileRechargeProductKind::Points
|
||||
&& row.status == RuntimeProfileRechargeOrderStatus::Paid
|
||||
})
|
||||
ctx.db
|
||||
.profile_recharge_order()
|
||||
.by_profile_recharge_order_user_id()
|
||||
.filter(user_id)
|
||||
.any(|row| {
|
||||
row.user_id == user_id
|
||||
&& row.kind == RuntimeProfileRechargeProductKind::Points
|
||||
&& row.status == RuntimeProfileRechargeOrderStatus::Paid
|
||||
})
|
||||
}
|
||||
|
||||
fn has_profile_product_recharged(ctx: &ReducerContext, user_id: &str, product_id: &str) -> bool {
|
||||
ctx.db.profile_recharge_order().iter().any(|row| {
|
||||
row.user_id == user_id
|
||||
&& row.product_id == product_id
|
||||
&& row.kind == RuntimeProfileRechargeProductKind::Points
|
||||
&& row.status == RuntimeProfileRechargeOrderStatus::Paid
|
||||
})
|
||||
ctx.db
|
||||
.profile_recharge_order()
|
||||
.by_profile_recharge_order_user_id()
|
||||
.filter(user_id)
|
||||
.any(|row| {
|
||||
row.user_id == user_id
|
||||
&& row.product_id == product_id
|
||||
&& row.kind == RuntimeProfileRechargeProductKind::Points
|
||||
&& row.status == RuntimeProfileRechargeOrderStatus::Paid
|
||||
})
|
||||
}
|
||||
|
||||
fn has_profile_business_wallet_ledger(ctx: &ReducerContext, user_id: &str) -> bool {
|
||||
ctx.db.profile_wallet_ledger().iter().any(|row| {
|
||||
row.user_id == user_id
|
||||
&& row.source_type != RuntimeProfileWalletLedgerSourceType::SnapshotSync
|
||||
})
|
||||
ctx.db
|
||||
.profile_wallet_ledger()
|
||||
.by_profile_wallet_ledger_user_id()
|
||||
.filter(user_id)
|
||||
.any(|row| {
|
||||
row.user_id == user_id
|
||||
&& row.source_type != RuntimeProfileWalletLedgerSourceType::SnapshotSync
|
||||
})
|
||||
}
|
||||
|
||||
fn latest_profile_recharge_order(
|
||||
@@ -4053,8 +4071,8 @@ fn latest_profile_recharge_order(
|
||||
let mut orders = ctx
|
||||
.db
|
||||
.profile_recharge_order()
|
||||
.iter()
|
||||
.filter(|row| row.user_id == user_id)
|
||||
.by_profile_recharge_order_user_id()
|
||||
.filter(user_id)
|
||||
.collect::<Vec<_>>();
|
||||
orders.sort_by(|left, right| {
|
||||
right
|
||||
|
||||
@@ -171,12 +171,12 @@ pub fn list_square_hole_works(
|
||||
match ctx.try_with_tx(|tx| list_square_hole_works_tx(tx, input.clone())) {
|
||||
Ok(items) => SquareHoleWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(to_json_string(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => SquareHoleWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -201,12 +201,12 @@ pub fn delete_square_hole_work(
|
||||
match ctx.try_with_tx(|tx| delete_square_hole_work_tx(tx, input.clone())) {
|
||||
Ok(items) => SquareHoleWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(to_json_string(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => SquareHoleWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -244,8 +244,8 @@ pub fn drop_square_hole_shape(
|
||||
Err(message) => SquareHoleDropShapeProcedureResult {
|
||||
ok: false,
|
||||
status: SQUARE_HOLE_DROP_REJECTED.to_string(),
|
||||
run_json: None,
|
||||
feedback_json: None,
|
||||
run: None,
|
||||
feedback: None,
|
||||
failure_reason: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
@@ -802,10 +802,8 @@ fn drop_square_hole_shape_tx(
|
||||
Ok(SquareHoleDropShapeProcedureResult {
|
||||
ok: true,
|
||||
status: status.to_string(),
|
||||
run_json: Some(to_json_string(&next)),
|
||||
feedback_json: Some(to_json_string(&feedback_from_domain(
|
||||
&confirmation.feedback,
|
||||
))),
|
||||
run: Some(next),
|
||||
feedback: Some(feedback_from_domain(&confirmation.feedback)),
|
||||
failure_reason: confirmation
|
||||
.feedback
|
||||
.reject_reason
|
||||
@@ -1593,7 +1591,7 @@ fn session_result(
|
||||
) -> SquareHoleAgentSessionProcedureResult {
|
||||
SquareHoleAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(to_json_string(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -1601,7 +1599,7 @@ fn session_result(
|
||||
fn session_error(message: String) -> SquareHoleAgentSessionProcedureResult {
|
||||
SquareHoleAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
}
|
||||
}
|
||||
@@ -1609,7 +1607,7 @@ fn session_error(message: String) -> SquareHoleAgentSessionProcedureResult {
|
||||
fn work_result(work: SquareHoleWorkSnapshot) -> SquareHoleWorkProcedureResult {
|
||||
SquareHoleWorkProcedureResult {
|
||||
ok: true,
|
||||
work_json: Some(to_json_string(&work)),
|
||||
work: Some(work),
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -1617,7 +1615,7 @@ fn work_result(work: SquareHoleWorkSnapshot) -> SquareHoleWorkProcedureResult {
|
||||
fn work_error(message: String) -> SquareHoleWorkProcedureResult {
|
||||
SquareHoleWorkProcedureResult {
|
||||
ok: false,
|
||||
work_json: None,
|
||||
work: None,
|
||||
error_message: Some(message),
|
||||
}
|
||||
}
|
||||
@@ -1625,7 +1623,7 @@ fn work_error(message: String) -> SquareHoleWorkProcedureResult {
|
||||
fn run_result(run: SquareHoleRunSnapshot) -> SquareHoleRunProcedureResult {
|
||||
SquareHoleRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(to_json_string(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -1633,7 +1631,7 @@ fn run_result(run: SquareHoleRunSnapshot) -> SquareHoleRunProcedureResult {
|
||||
fn run_error(message: String) -> SquareHoleRunProcedureResult {
|
||||
SquareHoleRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,42 +168,42 @@ pub struct SquareHoleRunTimeUpInput {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub struct SquareHoleAgentSessionProcedureResult {
|
||||
pub ok: bool,
|
||||
pub session_json: Option<String>,
|
||||
pub session: Option<SquareHoleAgentSessionSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub struct SquareHoleWorkProcedureResult {
|
||||
pub ok: bool,
|
||||
pub work_json: Option<String>,
|
||||
pub work: Option<SquareHoleWorkSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub struct SquareHoleWorksProcedureResult {
|
||||
pub ok: bool,
|
||||
pub items_json: Option<String>,
|
||||
pub items: Vec<SquareHoleWorkSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct SquareHoleRunProcedureResult {
|
||||
pub ok: bool,
|
||||
pub run_json: Option<String>,
|
||||
pub run: Option<SquareHoleRunSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct SquareHoleDropShapeProcedureResult {
|
||||
pub ok: bool,
|
||||
pub status: String,
|
||||
pub run_json: Option<String>,
|
||||
pub feedback_json: Option<String>,
|
||||
pub run: Option<SquareHoleRunSnapshot>,
|
||||
pub feedback: Option<SquareHoleDropFeedbackSnapshot>,
|
||||
pub failure_reason: Option<String>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleCreatorConfigSnapshot {
|
||||
pub theme_text: String,
|
||||
@@ -222,7 +222,7 @@ pub struct SquareHoleCreatorConfigSnapshot {
|
||||
pub background_image_src: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleShapeOptionSnapshot {
|
||||
pub option_id: String,
|
||||
@@ -235,7 +235,7 @@ pub struct SquareHoleShapeOptionSnapshot {
|
||||
pub image_src: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleHoleOptionSnapshot {
|
||||
pub hole_id: String,
|
||||
@@ -247,7 +247,7 @@ pub struct SquareHoleHoleOptionSnapshot {
|
||||
pub image_src: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleAgentMessageSnapshot {
|
||||
pub message_id: String,
|
||||
@@ -258,7 +258,7 @@ pub struct SquareHoleAgentMessageSnapshot {
|
||||
pub created_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleDraftSnapshot {
|
||||
pub profile_id: String,
|
||||
@@ -281,7 +281,7 @@ pub struct SquareHoleDraftSnapshot {
|
||||
pub difficulty: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleAgentSessionSnapshot {
|
||||
pub session_id: String,
|
||||
@@ -299,7 +299,7 @@ pub struct SquareHoleAgentSessionSnapshot {
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleWorkSnapshot {
|
||||
pub work_id: String,
|
||||
@@ -331,7 +331,7 @@ pub struct SquareHoleWorkSnapshot {
|
||||
pub published_at_micros: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleShapeSnapshot {
|
||||
pub shape_id: String,
|
||||
@@ -344,7 +344,7 @@ pub struct SquareHoleShapeSnapshot {
|
||||
pub image_src: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleHoleSnapshot {
|
||||
pub hole_id: String,
|
||||
@@ -356,7 +356,7 @@ pub struct SquareHoleHoleSnapshot {
|
||||
pub image_src: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleDropFeedbackSnapshot {
|
||||
pub accepted: bool,
|
||||
@@ -364,7 +364,7 @@ pub struct SquareHoleDropFeedbackSnapshot {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SquareHoleRunSnapshot {
|
||||
pub run_id: String,
|
||||
|
||||
@@ -379,49 +379,65 @@ pub struct VisualNovelRuntimeEventRecordInput {
|
||||
pub occurred_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct VisualNovelAgentSessionProcedureResult {
|
||||
pub ok: bool,
|
||||
pub session_json: Option<String>,
|
||||
pub session: Option<VisualNovelAgentSessionSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct VisualNovelWorkProcedureResult {
|
||||
pub ok: bool,
|
||||
pub work_json: Option<String>,
|
||||
pub work: Option<VisualNovelWorkSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct VisualNovelWorksProcedureResult {
|
||||
pub ok: bool,
|
||||
pub items_json: Option<String>,
|
||||
pub items: Vec<VisualNovelWorkSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct VisualNovelRunProcedureResult {
|
||||
pub ok: bool,
|
||||
pub run_json: Option<String>,
|
||||
pub run: Option<VisualNovelRunSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct VisualNovelHistoryProcedureResult {
|
||||
pub ok: bool,
|
||||
pub items_json: Option<String>,
|
||||
pub items: Vec<VisualNovelRuntimeHistoryEntrySnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct VisualNovelRuntimeEventProcedureResult {
|
||||
pub ok: bool,
|
||||
pub event_json: Option<String>,
|
||||
pub event: Option<VisualNovelRuntimeEventSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, SpacetimeType)]
|
||||
pub struct VisualNovelJsonField {
|
||||
pub key: String,
|
||||
pub value: VisualNovelJsonValue,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, SpacetimeType)]
|
||||
pub enum VisualNovelJsonValue {
|
||||
Null,
|
||||
Bool(bool),
|
||||
Number(f64),
|
||||
String(String),
|
||||
Array(Vec<VisualNovelJsonValue>),
|
||||
Object(Vec<VisualNovelJsonField>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VisualNovelAgentMessageSnapshot {
|
||||
pub message_id: String,
|
||||
@@ -432,7 +448,7 @@ pub struct VisualNovelAgentMessageSnapshot {
|
||||
pub created_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VisualNovelAgentSessionSnapshot {
|
||||
pub session_id: String,
|
||||
@@ -444,15 +460,15 @@ pub struct VisualNovelAgentSessionSnapshot {
|
||||
pub current_turn: u32,
|
||||
pub progress_percent: u32,
|
||||
pub messages: Vec<VisualNovelAgentMessageSnapshot>,
|
||||
pub draft: Option<JsonValue>,
|
||||
pub pending_action: Option<JsonValue>,
|
||||
pub draft: Option<VisualNovelJsonValue>,
|
||||
pub pending_action: Option<VisualNovelJsonValue>,
|
||||
pub last_assistant_reply: Option<String>,
|
||||
pub published_profile_id: Option<String>,
|
||||
pub created_at_micros: i64,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VisualNovelWorkSnapshot {
|
||||
pub work_id: String,
|
||||
@@ -465,7 +481,7 @@ pub struct VisualNovelWorkSnapshot {
|
||||
pub tags: Vec<String>,
|
||||
pub cover_image_src: Option<String>,
|
||||
pub source_asset_ids: Vec<String>,
|
||||
pub draft: JsonValue,
|
||||
pub draft: VisualNovelJsonValue,
|
||||
pub publication_status: String,
|
||||
pub publish_ready: bool,
|
||||
pub play_count: u32,
|
||||
@@ -474,7 +490,7 @@ pub struct VisualNovelWorkSnapshot {
|
||||
pub published_at_micros: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VisualNovelRuntimeHistoryEntrySnapshot {
|
||||
pub entry_id: String,
|
||||
@@ -484,13 +500,13 @@ pub struct VisualNovelRuntimeHistoryEntrySnapshot {
|
||||
pub turn_index: u32,
|
||||
pub source: String,
|
||||
pub action_text: Option<String>,
|
||||
pub steps: JsonValue,
|
||||
pub steps: VisualNovelJsonValue,
|
||||
pub snapshot_before_hash: Option<String>,
|
||||
pub snapshot_after_hash: Option<String>,
|
||||
pub created_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VisualNovelRunSnapshot {
|
||||
pub run_id: String,
|
||||
@@ -501,16 +517,16 @@ pub struct VisualNovelRunSnapshot {
|
||||
pub current_scene_id: Option<String>,
|
||||
pub current_phase_id: Option<String>,
|
||||
pub visible_character_ids: Vec<String>,
|
||||
pub flags: JsonValue,
|
||||
pub metrics: JsonValue,
|
||||
pub flags: VisualNovelJsonValue,
|
||||
pub metrics: VisualNovelJsonValue,
|
||||
pub history: Vec<VisualNovelRuntimeHistoryEntrySnapshot>,
|
||||
pub available_choices: JsonValue,
|
||||
pub available_choices: VisualNovelJsonValue,
|
||||
pub text_mode_enabled: bool,
|
||||
pub created_at_micros: i64,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, SpacetimeType)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VisualNovelRuntimeEventSnapshot {
|
||||
pub event_id: String,
|
||||
@@ -520,7 +536,7 @@ pub struct VisualNovelRuntimeEventSnapshot {
|
||||
pub event_kind: String,
|
||||
pub client_event_id: Option<String>,
|
||||
pub history_entry_id: Option<String>,
|
||||
pub payload: JsonValue,
|
||||
pub payload: VisualNovelJsonValue,
|
||||
pub occurred_at_micros: i64,
|
||||
}
|
||||
|
||||
@@ -609,12 +625,12 @@ pub fn list_visual_novel_works(
|
||||
match ctx.try_with_tx(|tx| list_visual_novel_works_tx(tx, input.clone())) {
|
||||
Ok(items) => VisualNovelWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(to_json_string(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => VisualNovelWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -639,12 +655,12 @@ pub fn delete_visual_novel_work(
|
||||
match ctx.try_with_tx(|tx| delete_visual_novel_work_tx(tx, input.clone())) {
|
||||
Ok(items) => VisualNovelWorksProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(to_json_string(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => VisualNovelWorksProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -691,12 +707,12 @@ pub fn append_visual_novel_runtime_history_entry(
|
||||
match ctx.try_with_tx(|tx| append_visual_novel_runtime_history_entry_tx(tx, input.clone())) {
|
||||
Ok(items) => VisualNovelHistoryProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(to_json_string(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => VisualNovelHistoryProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -710,12 +726,12 @@ pub fn list_visual_novel_runtime_history(
|
||||
match ctx.try_with_tx(|tx| list_visual_novel_runtime_history_tx(tx, input.clone())) {
|
||||
Ok(items) => VisualNovelHistoryProcedureResult {
|
||||
ok: true,
|
||||
items_json: Some(to_json_string(&items)),
|
||||
items,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => VisualNovelHistoryProcedureResult {
|
||||
ok: false,
|
||||
items_json: None,
|
||||
items: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -729,12 +745,12 @@ pub fn record_visual_novel_runtime_event(
|
||||
match ctx.try_with_tx(|tx| record_visual_novel_runtime_event_tx(tx, input.clone())) {
|
||||
Ok(event) => VisualNovelRuntimeEventProcedureResult {
|
||||
ok: true,
|
||||
event_json: Some(to_json_string(&event)),
|
||||
event: Some(event),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => VisualNovelRuntimeEventProcedureResult {
|
||||
ok: false,
|
||||
event_json: None,
|
||||
event: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
@@ -1105,17 +1121,22 @@ fn list_visual_novel_works_tx(
|
||||
ctx: &ReducerContext,
|
||||
input: VisualNovelWorksListInput,
|
||||
) -> Result<Vec<VisualNovelWorkSnapshot>, String> {
|
||||
let mut items = ctx
|
||||
.db
|
||||
.visual_novel_work_profile()
|
||||
let rows = if input.published_only {
|
||||
ctx.db
|
||||
.visual_novel_work_profile()
|
||||
.by_visual_novel_work_publication_status()
|
||||
.filter(&VISUAL_NOVEL_PUBLICATION_PUBLISHED.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
require_non_empty(&input.owner_user_id, "visual_novel owner_user_id")?;
|
||||
ctx.db
|
||||
.visual_novel_work_profile()
|
||||
.by_visual_novel_work_owner_user_id()
|
||||
.filter(&input.owner_user_id)
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
let mut items = rows
|
||||
.iter()
|
||||
.filter(|row| {
|
||||
if input.published_only {
|
||||
row.publication_status == VISUAL_NOVEL_PUBLICATION_PUBLISHED
|
||||
} else {
|
||||
row.owner_user_id == input.owner_user_id
|
||||
}
|
||||
})
|
||||
.map(|row| build_work_snapshot(&row))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
items.sort_by(|left, right| {
|
||||
@@ -1156,10 +1177,9 @@ fn delete_visual_novel_work_tx(
|
||||
for run in ctx
|
||||
.db
|
||||
.visual_novel_runtime_run()
|
||||
.iter()
|
||||
.filter(|row| {
|
||||
row.profile_id == input.profile_id && row.owner_user_id == input.owner_user_id
|
||||
})
|
||||
.by_visual_novel_run_profile_id()
|
||||
.filter(&input.profile_id)
|
||||
.filter(|row| row.owner_user_id == input.owner_user_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
delete_run_children(ctx, &run.run_id, &input.owner_user_id);
|
||||
@@ -1438,8 +1458,8 @@ fn build_session_snapshot(
|
||||
let mut messages = ctx
|
||||
.db
|
||||
.visual_novel_agent_message()
|
||||
.iter()
|
||||
.filter(|message| message.session_id == row.session_id)
|
||||
.by_visual_novel_agent_message_session_id()
|
||||
.filter(&row.session_id)
|
||||
.map(|message| VisualNovelAgentMessageSnapshot {
|
||||
message_id: message.message_id,
|
||||
session_id: message.session_id,
|
||||
@@ -1465,8 +1485,9 @@ fn build_session_snapshot(
|
||||
current_turn: row.current_turn,
|
||||
progress_percent: row.progress_percent,
|
||||
messages,
|
||||
draft: parse_optional_json_value(&row.draft_json)?,
|
||||
pending_action: parse_optional_json_value(&row.pending_action_json)?,
|
||||
draft: parse_optional_json_value(&row.draft_json)?.map(visual_novel_json_from_serde),
|
||||
pending_action: parse_optional_json_value(&row.pending_action_json)?
|
||||
.map(visual_novel_json_from_serde),
|
||||
last_assistant_reply: empty_to_none(&row.last_assistant_reply),
|
||||
published_profile_id: empty_to_none(&row.published_profile_id),
|
||||
created_at_micros: row.created_at.to_micros_since_unix_epoch(),
|
||||
@@ -1486,7 +1507,7 @@ fn build_work_snapshot(row: &VisualNovelWorkProfileRow) -> Result<VisualNovelWor
|
||||
tags: parse_string_vec_or_empty(&row.tags_json)?,
|
||||
cover_image_src: empty_to_none(&row.cover_image_src),
|
||||
source_asset_ids: parse_string_vec_or_empty(&row.source_asset_ids_json)?,
|
||||
draft: parse_json_value(&row.draft_json)?,
|
||||
draft: visual_novel_json_from_serde(parse_json_value(&row.draft_json)?),
|
||||
publication_status: row.publication_status.clone(),
|
||||
publish_ready: row.publish_ready,
|
||||
play_count: row.play_count,
|
||||
@@ -1536,10 +1557,12 @@ fn build_run_snapshot(
|
||||
current_scene_id: empty_to_none(&row.current_scene_id),
|
||||
current_phase_id: empty_to_none(&row.current_phase_id),
|
||||
visible_character_ids: parse_string_vec_or_empty(&row.visible_character_ids_json)?,
|
||||
flags: parse_json_value_or_object(&row.flags_json)?,
|
||||
metrics: parse_json_value_or_object(&row.metrics_json)?,
|
||||
flags: visual_novel_json_from_serde(parse_json_value_or_object(&row.flags_json)?),
|
||||
metrics: visual_novel_json_from_serde(parse_json_value_or_object(&row.metrics_json)?),
|
||||
history: build_history_snapshots(ctx, &row.run_id, &row.owner_user_id)?,
|
||||
available_choices: parse_json_value_or_array(&row.available_choices_json)?,
|
||||
available_choices: visual_novel_json_from_serde(parse_json_value_or_array(
|
||||
&row.available_choices_json,
|
||||
)?),
|
||||
text_mode_enabled: row.text_mode_enabled,
|
||||
created_at_micros: row.created_at.to_micros_since_unix_epoch(),
|
||||
updated_at_micros: row.updated_at.to_micros_since_unix_epoch(),
|
||||
@@ -1554,8 +1577,9 @@ fn build_history_snapshots(
|
||||
let mut items = ctx
|
||||
.db
|
||||
.visual_novel_runtime_history_entry()
|
||||
.iter()
|
||||
.filter(|row| row.run_id == run_id && row.owner_user_id == owner_user_id)
|
||||
.by_visual_novel_history_run_id()
|
||||
.filter(&run_id.to_string())
|
||||
.filter(|row| row.owner_user_id == owner_user_id)
|
||||
.map(|row| build_history_snapshot(&row))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
items.sort_by(|left, right| {
|
||||
@@ -1578,7 +1602,7 @@ fn build_history_snapshot(
|
||||
turn_index: row.turn_index,
|
||||
source: row.source.clone(),
|
||||
action_text: empty_to_none(&row.action_text),
|
||||
steps: parse_json_value_or_array(&row.steps_json)?,
|
||||
steps: visual_novel_json_from_serde(parse_json_value_or_array(&row.steps_json)?),
|
||||
snapshot_before_hash: empty_to_none(&row.snapshot_before_hash),
|
||||
snapshot_after_hash: empty_to_none(&row.snapshot_after_hash),
|
||||
created_at_micros: row.created_at.to_micros_since_unix_epoch(),
|
||||
@@ -1596,7 +1620,7 @@ fn build_event_snapshot(
|
||||
event_kind: row.event_kind.clone(),
|
||||
client_event_id: empty_to_none(&row.client_event_id),
|
||||
history_entry_id: empty_to_none(&row.history_entry_id),
|
||||
payload: parse_json_value_or_object(&row.payload_json)?,
|
||||
payload: visual_novel_json_from_serde(parse_json_value_or_object(&row.payload_json)?),
|
||||
occurred_at_micros: row.occurred_at.to_micros_since_unix_epoch(),
|
||||
})
|
||||
}
|
||||
@@ -1657,8 +1681,9 @@ fn delete_run_children(ctx: &ReducerContext, run_id: &str, owner_user_id: &str)
|
||||
for history in ctx
|
||||
.db
|
||||
.visual_novel_runtime_history_entry()
|
||||
.iter()
|
||||
.filter(|row| row.run_id == run_id && row.owner_user_id == owner_user_id)
|
||||
.by_visual_novel_history_run_id()
|
||||
.filter(&run_id.to_string())
|
||||
.filter(|row| row.owner_user_id == owner_user_id)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
ctx.db
|
||||
@@ -1836,6 +1861,30 @@ fn parse_json_value_or_array(value: &str) -> Result<JsonValue, String> {
|
||||
parse_json_value(value)
|
||||
}
|
||||
|
||||
fn visual_novel_json_from_serde(value: JsonValue) -> VisualNovelJsonValue {
|
||||
match value {
|
||||
JsonValue::Null => VisualNovelJsonValue::Null,
|
||||
JsonValue::Bool(value) => VisualNovelJsonValue::Bool(value),
|
||||
JsonValue::Number(value) => VisualNovelJsonValue::Number(value.as_f64().unwrap_or(0.0)),
|
||||
JsonValue::String(value) => VisualNovelJsonValue::String(value),
|
||||
JsonValue::Array(items) => VisualNovelJsonValue::Array(
|
||||
items
|
||||
.into_iter()
|
||||
.map(visual_novel_json_from_serde)
|
||||
.collect(),
|
||||
),
|
||||
JsonValue::Object(object) => VisualNovelJsonValue::Object(
|
||||
object
|
||||
.into_iter()
|
||||
.map(|(key, value)| VisualNovelJsonField {
|
||||
key,
|
||||
value: visual_novel_json_from_serde(value),
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn draft_string_field(draft: &JsonValue, key: &str) -> Option<String> {
|
||||
draft
|
||||
.get(key)
|
||||
@@ -1931,7 +1980,7 @@ fn session_result(
|
||||
) -> VisualNovelAgentSessionProcedureResult {
|
||||
VisualNovelAgentSessionProcedureResult {
|
||||
ok: true,
|
||||
session_json: Some(to_json_string(&session)),
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -1939,7 +1988,7 @@ fn session_result(
|
||||
fn session_error(message: String) -> VisualNovelAgentSessionProcedureResult {
|
||||
VisualNovelAgentSessionProcedureResult {
|
||||
ok: false,
|
||||
session_json: None,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
}
|
||||
}
|
||||
@@ -1947,7 +1996,7 @@ fn session_error(message: String) -> VisualNovelAgentSessionProcedureResult {
|
||||
fn work_result(work: VisualNovelWorkSnapshot) -> VisualNovelWorkProcedureResult {
|
||||
VisualNovelWorkProcedureResult {
|
||||
ok: true,
|
||||
work_json: Some(to_json_string(&work)),
|
||||
work: Some(work),
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -1955,7 +2004,7 @@ fn work_result(work: VisualNovelWorkSnapshot) -> VisualNovelWorkProcedureResult
|
||||
fn work_error(message: String) -> VisualNovelWorkProcedureResult {
|
||||
VisualNovelWorkProcedureResult {
|
||||
ok: false,
|
||||
work_json: None,
|
||||
work: None,
|
||||
error_message: Some(message),
|
||||
}
|
||||
}
|
||||
@@ -1963,7 +2012,7 @@ fn work_error(message: String) -> VisualNovelWorkProcedureResult {
|
||||
fn run_result(run: VisualNovelRunSnapshot) -> VisualNovelRunProcedureResult {
|
||||
VisualNovelRunProcedureResult {
|
||||
ok: true,
|
||||
run_json: Some(to_json_string(&run)),
|
||||
run: Some(run),
|
||||
error_message: None,
|
||||
}
|
||||
}
|
||||
@@ -1971,7 +2020,7 @@ fn run_result(run: VisualNovelRunSnapshot) -> VisualNovelRunProcedureResult {
|
||||
fn run_error(message: String) -> VisualNovelRunProcedureResult {
|
||||
VisualNovelRunProcedureResult {
|
||||
ok: false,
|
||||
run_json: None,
|
||||
run: None,
|
||||
error_message: Some(message),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user