Move project save post-commit planning to app core
This commit is contained in:
@@ -307,7 +307,10 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.p
|
|||||||
the app-core commit plan for direct saves, successful temporary swaps,
|
the app-core commit plan for direct saves, successful temporary swaps,
|
||||||
target-remove failures, and rename-after-remove failures. It is covered by
|
target-remove failures, and rename-after-remove failures. It is covered by
|
||||||
forward-slash, Windows backslash, existing-target, remove-failure,
|
forward-slash, Windows backslash, existing-target, remove-failure,
|
||||||
rename-failure, and invalid-path smokes.
|
rename-failure, and invalid-path smokes. The same command now reports the
|
||||||
|
app-core post-commit side-effect plan for clean/new-document metadata
|
||||||
|
updates, timelapse sidecar gating, platform flush, progress cleanup, and
|
||||||
|
title refresh.
|
||||||
- Live equirectangular, layer, animation-frame, and cube-face export adapters
|
- Live equirectangular, layer, animation-frame, and cube-face export adapters
|
||||||
now prepare and log the same payload-bearing canvas document snapshot plus
|
now prepare and log the same payload-bearing canvas document snapshot plus
|
||||||
shared paint-renderer export-readiness report.
|
shared paint-renderer export-readiness report.
|
||||||
@@ -1191,7 +1194,10 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.p
|
|||||||
delegating to retained `Canvas::project_save`. Direct save, successful
|
delegating to retained `Canvas::project_save`. Direct save, successful
|
||||||
temporary swap, remove-failure, and rename-after-remove commit outcomes are
|
temporary swap, remove-failure, and rename-after-remove commit outcomes are
|
||||||
now classified by the same app-core planner before retained success metadata
|
now classified by the same app-core planner before retained success metadata
|
||||||
mutation.
|
mutation. Post-commit clean/new-document metadata, timelapse sidecar,
|
||||||
|
platform flush, progress cleanup, and title-refresh decisions also come from
|
||||||
|
`pp_app_core`, while retained code still performs the mutations and sidecar
|
||||||
|
serialization.
|
||||||
Retained legacy UI/canvas
|
Retained legacy UI/canvas
|
||||||
execution and actual live save serialization remain tracked by `DEBT-0040`,
|
execution and actual live save serialization remain tracked by `DEBT-0040`,
|
||||||
`DEBT-0041`, and `DEBT-0042`; the pure snapshot-to-PPI export handoff is
|
`DEBT-0041`, and `DEBT-0042`; the pure snapshot-to-PPI export handoff is
|
||||||
|
|||||||
@@ -559,6 +559,15 @@ agent or engineer to remove them without reconstructing context from chat.
|
|||||||
Actual PPI serialization, filesystem remove/rename execution,
|
Actual PPI serialization, filesystem remove/rename execution,
|
||||||
progress/threading, timelapse sidecar serialization, and app metadata
|
progress/threading, timelapse sidecar serialization, and app metadata
|
||||||
mutation remain retained.
|
mutation remain retained.
|
||||||
|
- 2026-06-06: DEBT-0040/DEBT-0042 were narrowed again. `pp_app_core` now owns
|
||||||
|
the retained project-save post-commit side-effect policy: successful saves
|
||||||
|
mark the document clean, commit new-document state, flush platform storage,
|
||||||
|
optionally write a timelapse sidecar when an encoder exists, and always
|
||||||
|
dismiss visible progress UI plus refresh the title. Live
|
||||||
|
`Canvas::project_save_thread` consumes that plan, and
|
||||||
|
`pano_cli plan-canvas-project-save-target` reports it in JSON. Actual state
|
||||||
|
mutation, progress UI destruction, platform flush execution, title update,
|
||||||
|
and timelapse sidecar serialization remain retained.
|
||||||
- 2026-06-05: DEBT-0010/DEBT-0013 were narrowed again. `pp_app_core` now
|
- 2026-06-05: DEBT-0010/DEBT-0013 were narrowed again. `pp_app_core` now
|
||||||
exports payload-complete or metadata-only canvas document snapshots through
|
exports payload-complete or metadata-only canvas document snapshots through
|
||||||
the pure `pp_document` PPI writer and rejects snapshots that still require
|
the pure `pp_document` PPI writer and rejects snapshots that still require
|
||||||
|
|||||||
@@ -715,8 +715,11 @@ and preserving the legacy direct-write fallback when the temporary file cannot
|
|||||||
be opened. The same app-core boundary now also classifies the post-write
|
be opened. The same app-core boundary now also classifies the post-write
|
||||||
commit result for direct writes, successful temporary swaps, remove failures,
|
commit result for direct writes, successful temporary swaps, remove failures,
|
||||||
and rename-after-remove failures before retained save metadata mutation
|
and rename-after-remove failures before retained save metadata mutation
|
||||||
continues. The same automation now feeds payload-complete snapshots through the
|
continues. Post-save side effects are now planned there too: mark-clean,
|
||||||
shared
|
new-document commitment, timelapse sidecar gating, platform flush, progress
|
||||||
|
cleanup, and title refresh are reported before retained execution performs the
|
||||||
|
actual mutations and sidecar serialization. The same automation now feeds
|
||||||
|
payload-complete snapshots through the shared
|
||||||
`pp_paint_renderer::prepare_document_frame_export_readiness` report, which
|
`pp_paint_renderer::prepare_document_frame_export_readiness` report, which
|
||||||
records renderer-neutral six-face texture upload commands and encodes the
|
records renderer-neutral six-face texture upload commands and encodes the
|
||||||
active document frame's six composited faces to PNG bytes. This gives CLI
|
active document frame's six composited faces to PNG bytes. This gives CLI
|
||||||
@@ -2326,6 +2329,9 @@ Results:
|
|||||||
The command now reports the app-core commit plan for direct saves, successful
|
The command now reports the app-core commit plan for direct saves, successful
|
||||||
temporary swaps, target-remove failures, and rename-after-remove failures,
|
temporary swaps, target-remove failures, and rename-after-remove failures,
|
||||||
including whether the target may be missing after a failed swap.
|
including whether the target may be missing after a failed swap.
|
||||||
|
It also reports the app-core post-commit side-effect plan, including
|
||||||
|
clean/new-document metadata updates, timelapse sidecar gating, platform
|
||||||
|
flush, progress cleanup, and title refresh.
|
||||||
- The same payload-complete snapshot automation now uploads the active document
|
- The same payload-complete snapshot automation now uploads the active document
|
||||||
frame through `pp_paint_renderer::upload_document_frame_faces` and the
|
frame through `pp_paint_renderer::upload_document_frame_faces` and the
|
||||||
`RecordingRenderDevice`, emitting `rendererUpload` JSON with texture,
|
`RecordingRenderDevice`, emitting `rendererUpload` JSON with texture,
|
||||||
|
|||||||
@@ -135,6 +135,21 @@ struct DocumentCanvasProjectSaveCommitPlan {
|
|||||||
std::string_view log_message;
|
std::string_view log_message;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DocumentCanvasProjectSavePostCommitInput {
|
||||||
|
bool save_succeeded = false;
|
||||||
|
bool timelapse_encoder_available = false;
|
||||||
|
bool progress_ui_visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DocumentCanvasProjectSavePostCommitPlan {
|
||||||
|
bool marks_document_clean = false;
|
||||||
|
bool marks_new_document_committed = false;
|
||||||
|
bool saves_timelapse_sidecar = false;
|
||||||
|
bool flushes_platform_storage = false;
|
||||||
|
bool dismisses_progress_ui = false;
|
||||||
|
bool updates_title = true;
|
||||||
|
};
|
||||||
|
|
||||||
class DocumentCanvasClearServices {
|
class DocumentCanvasClearServices {
|
||||||
public:
|
public:
|
||||||
virtual ~DocumentCanvasClearServices() = default;
|
virtual ~DocumentCanvasClearServices() = default;
|
||||||
@@ -444,6 +459,23 @@ plan_document_canvas_project_save_write(
|
|||||||
return plan;
|
return plan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr DocumentCanvasProjectSavePostCommitPlan plan_document_canvas_project_save_post_commit(
|
||||||
|
DocumentCanvasProjectSavePostCommitInput input) noexcept
|
||||||
|
{
|
||||||
|
DocumentCanvasProjectSavePostCommitPlan plan;
|
||||||
|
plan.dismisses_progress_ui = input.progress_ui_visible;
|
||||||
|
|
||||||
|
if (!input.save_succeeded) {
|
||||||
|
return plan;
|
||||||
|
}
|
||||||
|
|
||||||
|
plan.marks_document_clean = true;
|
||||||
|
plan.marks_new_document_committed = true;
|
||||||
|
plan.saves_timelapse_sidecar = input.timelapse_encoder_available;
|
||||||
|
plan.flushes_platform_storage = true;
|
||||||
|
return plan;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline pp::foundation::Result<DocumentCanvasClearPlan> plan_document_canvas_clear(
|
[[nodiscard]] inline pp::foundation::Result<DocumentCanvasClearPlan> plan_document_canvas_clear(
|
||||||
bool has_canvas,
|
bool has_canvas,
|
||||||
float r = 0.0F,
|
float r = 0.0F,
|
||||||
|
|||||||
@@ -2577,13 +2577,23 @@ bool Canvas::project_save_thread(std::string file_path, bool show_progress)
|
|||||||
LOG("project saved to %s", file_path.c_str());
|
LOG("project saved to %s", file_path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
const auto post_commit_plan = pp::app::plan_document_canvas_project_save_post_commit(
|
||||||
|
pp::app::DocumentCanvasProjectSavePostCommitInput {
|
||||||
|
.save_succeeded = success,
|
||||||
|
.timelapse_encoder_available = Canvas::I->m_encoder != nullptr,
|
||||||
|
.progress_ui_visible = show_progress,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (post_commit_plan.marks_document_clean)
|
||||||
{
|
{
|
||||||
m_unsaved = false;
|
m_unsaved = false;
|
||||||
|
}
|
||||||
|
if (post_commit_plan.marks_new_document_committed)
|
||||||
|
{
|
||||||
m_newdoc = false;
|
m_newdoc = false;
|
||||||
|
}
|
||||||
|
|
||||||
// save timelapse
|
if (post_commit_plan.saves_timelapse_sidecar)
|
||||||
if (Canvas::I->m_encoder)
|
|
||||||
{
|
{
|
||||||
BinaryStreamWriter sw;
|
BinaryStreamWriter sw;
|
||||||
sw.init(BinaryStream::ByteOrder::LittleEndian);
|
sw.init(BinaryStream::ByteOrder::LittleEndian);
|
||||||
@@ -2597,12 +2607,20 @@ bool Canvas::project_save_thread(std::string file_path, bool show_progress)
|
|||||||
if (!sw.save(lapse_path))
|
if (!sw.save(lapse_path))
|
||||||
LOG("cannot save timelase to %s", lapse_path.c_str());
|
LOG("cannot save timelase to %s", lapse_path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (post_commit_plan.flushes_platform_storage)
|
||||||
|
{
|
||||||
App::I->flush_platform_storage();
|
App::I->flush_platform_storage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_progress)
|
if (post_commit_plan.dismisses_progress_ui)
|
||||||
|
{
|
||||||
pb->destroy();
|
pb->destroy();
|
||||||
|
}
|
||||||
|
if (post_commit_plan.updates_title)
|
||||||
|
{
|
||||||
App::I->title_update();
|
App::I->title_update();
|
||||||
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1530,7 +1530,7 @@ if(TARGET pano_cli)
|
|||||||
COMMAND pano_cli plan-canvas-project-save-target --data-dir D:/Paint/data --path D:/Paint/projects/demo.ppi)
|
COMMAND pano_cli plan-canvas-project-save-target --data-dir D:/Paint/data --path D:/Paint/projects/demo.ppi)
|
||||||
set_tests_properties(pano_cli_plan_canvas_project_save_target_smoke PROPERTIES
|
set_tests_properties(pano_cli_plan_canvas_project_save_target_smoke PROPERTIES
|
||||||
LABELS "app;document;integration;desktop-fast"
|
LABELS "app;document;integration;desktop-fast"
|
||||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-project-save-target\".*\"dataDirectory\":\"D:/Paint/data\".*\"targetPath\":\"D:/Paint/projects/demo.ppi\".*\"fileName\":\"demo\".*\"temporaryPath\":\"D:/Paint/data/demo.tmp.ppi\".*\"timelapsePath\":\"D:/Paint/data/demo.pptl\".*\"writePlan\":\\{\"action\":\"write-direct-to-target\",\"targetExists\":false,\"usesTemporary\":false,\"writePath\":\"D:/Paint/projects/demo.ppi\",\"fallbackDirectOnTemporaryOpenFailure\":false\\}.*\"commitPlan\":\\{\"saved\":true,\"usedTemporary\":false,\"targetRemoved\":false,\"temporaryRenamed\":false,\"targetMayBeMissing\":false,\"message\":\"project saved to target\"\\}")
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-project-save-target\".*\"dataDirectory\":\"D:/Paint/data\".*\"targetPath\":\"D:/Paint/projects/demo.ppi\".*\"fileName\":\"demo\".*\"temporaryPath\":\"D:/Paint/data/demo.tmp.ppi\".*\"timelapsePath\":\"D:/Paint/data/demo.pptl\".*\"writePlan\":\\{\"action\":\"write-direct-to-target\",\"targetExists\":false,\"usesTemporary\":false,\"writePath\":\"D:/Paint/projects/demo.ppi\",\"fallbackDirectOnTemporaryOpenFailure\":false\\}.*\"commitPlan\":\\{\"saved\":true,\"usedTemporary\":false,\"targetRemoved\":false,\"temporaryRenamed\":false,\"targetMayBeMissing\":false,\"message\":\"project saved to target\"\\}.*\"postCommitPlan\":\\{\"marksDocumentClean\":true,\"marksNewDocumentCommitted\":true,\"savesTimelapseSidecar\":false,\"flushesPlatformStorage\":true,\"dismissesProgressUi\":false,\"updatesTitle\":true\\}")
|
||||||
|
|
||||||
add_test(NAME pano_cli_plan_canvas_project_save_target_backslash_smoke
|
add_test(NAME pano_cli_plan_canvas_project_save_target_backslash_smoke
|
||||||
COMMAND pano_cli plan-canvas-project-save-target --data-dir D:/Paint/data --path "D:\\Paint\\projects\\demo.ppi")
|
COMMAND pano_cli plan-canvas-project-save-target --data-dir D:/Paint/data --path "D:\\Paint\\projects\\demo.ppi")
|
||||||
@@ -1539,10 +1539,10 @@ if(TARGET pano_cli)
|
|||||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-project-save-target\".*\"fileName\":\"demo\".*\"temporaryPath\":\"D:/Paint/data/demo.tmp.ppi\".*\"timelapsePath\":\"D:/Paint/data/demo.pptl\"")
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-project-save-target\".*\"fileName\":\"demo\".*\"temporaryPath\":\"D:/Paint/data/demo.tmp.ppi\".*\"timelapsePath\":\"D:/Paint/data/demo.pptl\"")
|
||||||
|
|
||||||
add_test(NAME pano_cli_plan_canvas_project_save_target_existing_smoke
|
add_test(NAME pano_cli_plan_canvas_project_save_target_existing_smoke
|
||||||
COMMAND pano_cli plan-canvas-project-save-target --data-dir D:/Paint/data --path D:/Paint/projects/demo.ppi --target-exists)
|
COMMAND pano_cli plan-canvas-project-save-target --data-dir D:/Paint/data --path D:/Paint/projects/demo.ppi --target-exists --encoder --progress)
|
||||||
set_tests_properties(pano_cli_plan_canvas_project_save_target_existing_smoke PROPERTIES
|
set_tests_properties(pano_cli_plan_canvas_project_save_target_existing_smoke PROPERTIES
|
||||||
LABELS "app;document;integration;desktop-fast"
|
LABELS "app;document;integration;desktop-fast"
|
||||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-project-save-target\".*\"targetPath\":\"D:/Paint/projects/demo.ppi\".*\"writePlan\":\\{\"action\":\"write-temporary-then-swap\",\"targetExists\":true,\"usesTemporary\":true,\"writePath\":\"D:/Paint/data/demo.tmp.ppi\",\"fallbackDirectOnTemporaryOpenFailure\":true\\}.*\"commitPlan\":\\{\"saved\":true,\"usedTemporary\":true,\"targetRemoved\":true,\"temporaryRenamed\":true,\"targetMayBeMissing\":false,\"message\":\"temporary project swapped successfully\"\\}")
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-project-save-target\".*\"targetPath\":\"D:/Paint/projects/demo.ppi\".*\"writePlan\":\\{\"action\":\"write-temporary-then-swap\",\"targetExists\":true,\"usesTemporary\":true,\"writePath\":\"D:/Paint/data/demo.tmp.ppi\",\"fallbackDirectOnTemporaryOpenFailure\":true\\}.*\"commitPlan\":\\{\"saved\":true,\"usedTemporary\":true,\"targetRemoved\":true,\"temporaryRenamed\":true,\"targetMayBeMissing\":false,\"message\":\"temporary project swapped successfully\"\\}.*\"postCommitPlan\":\\{\"marksDocumentClean\":true,\"marksNewDocumentCommitted\":true,\"savesTimelapseSidecar\":true,\"flushesPlatformStorage\":true,\"dismissesProgressUi\":true,\"updatesTitle\":true\\}")
|
||||||
|
|
||||||
add_test(NAME pano_cli_plan_canvas_project_save_target_remove_failure_smoke
|
add_test(NAME pano_cli_plan_canvas_project_save_target_remove_failure_smoke
|
||||||
COMMAND pano_cli plan-canvas-project-save-target --data-dir D:/Paint/data --path D:/Paint/projects/demo.ppi --target-exists --remove-fails)
|
COMMAND pano_cli plan-canvas-project-save-target --data-dir D:/Paint/data --path D:/Paint/projects/demo.ppi --target-exists --remove-fails)
|
||||||
@@ -1554,7 +1554,7 @@ if(TARGET pano_cli)
|
|||||||
COMMAND pano_cli plan-canvas-project-save-target --data-dir D:/Paint/data --path D:/Paint/projects/demo.ppi --target-exists --rename-fails)
|
COMMAND pano_cli plan-canvas-project-save-target --data-dir D:/Paint/data --path D:/Paint/projects/demo.ppi --target-exists --rename-fails)
|
||||||
set_tests_properties(pano_cli_plan_canvas_project_save_target_rename_failure_smoke PROPERTIES
|
set_tests_properties(pano_cli_plan_canvas_project_save_target_rename_failure_smoke PROPERTIES
|
||||||
LABELS "app;document;integration;desktop-fast;fuzz"
|
LABELS "app;document;integration;desktop-fast;fuzz"
|
||||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-project-save-target\".*\"commitPlan\":\\{\"saved\":false,\"usedTemporary\":true,\"targetRemoved\":true,\"temporaryRenamed\":false,\"targetMayBeMissing\":true,\"message\":\"temporary project not swapped after original removal\"\\}")
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-canvas-project-save-target\".*\"commitPlan\":\\{\"saved\":false,\"usedTemporary\":true,\"targetRemoved\":true,\"temporaryRenamed\":false,\"targetMayBeMissing\":true,\"message\":\"temporary project not swapped after original removal\"\\}.*\"postCommitPlan\":\\{\"marksDocumentClean\":false,\"marksNewDocumentCommitted\":false,\"savesTimelapseSidecar\":false,\"flushesPlatformStorage\":false,\"dismissesProgressUi\":false,\"updatesTitle\":true\\}")
|
||||||
|
|
||||||
add_test(NAME pano_cli_plan_canvas_project_save_target_rejects_empty_path
|
add_test(NAME pano_cli_plan_canvas_project_save_target_rejects_empty_path
|
||||||
COMMAND pano_cli plan-canvas-project-save-target --path "")
|
COMMAND pano_cli plan-canvas-project-save-target --path "")
|
||||||
|
|||||||
@@ -425,6 +425,57 @@ void project_save_commit_plan_flags_missing_target_after_rename_failure(pp::test
|
|||||||
PP_EXPECT(harness, plan.log_message == "temporary project not swapped after original removal");
|
PP_EXPECT(harness, plan.log_message == "temporary project not swapped after original removal");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void project_save_post_commit_plan_records_success_side_effects(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto plan = pp::app::plan_document_canvas_project_save_post_commit(
|
||||||
|
pp::app::DocumentCanvasProjectSavePostCommitInput {
|
||||||
|
.save_succeeded = true,
|
||||||
|
.timelapse_encoder_available = true,
|
||||||
|
.progress_ui_visible = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
PP_EXPECT(harness, plan.marks_document_clean);
|
||||||
|
PP_EXPECT(harness, plan.marks_new_document_committed);
|
||||||
|
PP_EXPECT(harness, plan.saves_timelapse_sidecar);
|
||||||
|
PP_EXPECT(harness, plan.flushes_platform_storage);
|
||||||
|
PP_EXPECT(harness, plan.dismisses_progress_ui);
|
||||||
|
PP_EXPECT(harness, plan.updates_title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void project_save_post_commit_plan_skips_timelapse_without_encoder(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto plan = pp::app::plan_document_canvas_project_save_post_commit(
|
||||||
|
pp::app::DocumentCanvasProjectSavePostCommitInput {
|
||||||
|
.save_succeeded = true,
|
||||||
|
.timelapse_encoder_available = false,
|
||||||
|
.progress_ui_visible = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
PP_EXPECT(harness, plan.marks_document_clean);
|
||||||
|
PP_EXPECT(harness, plan.marks_new_document_committed);
|
||||||
|
PP_EXPECT(harness, !plan.saves_timelapse_sidecar);
|
||||||
|
PP_EXPECT(harness, plan.flushes_platform_storage);
|
||||||
|
PP_EXPECT(harness, !plan.dismisses_progress_ui);
|
||||||
|
PP_EXPECT(harness, plan.updates_title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void project_save_post_commit_plan_preserves_state_after_failure(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto plan = pp::app::plan_document_canvas_project_save_post_commit(
|
||||||
|
pp::app::DocumentCanvasProjectSavePostCommitInput {
|
||||||
|
.save_succeeded = false,
|
||||||
|
.timelapse_encoder_available = true,
|
||||||
|
.progress_ui_visible = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
PP_EXPECT(harness, !plan.marks_document_clean);
|
||||||
|
PP_EXPECT(harness, !plan.marks_new_document_committed);
|
||||||
|
PP_EXPECT(harness, !plan.saves_timelapse_sidecar);
|
||||||
|
PP_EXPECT(harness, !plan.flushes_platform_storage);
|
||||||
|
PP_EXPECT(harness, plan.dismisses_progress_ui);
|
||||||
|
PP_EXPECT(harness, plan.updates_title);
|
||||||
|
}
|
||||||
|
|
||||||
void snapshot_plan_rejects_invalid_canvas_state(pp::tests::Harness& harness)
|
void snapshot_plan_rejects_invalid_canvas_state(pp::tests::Harness& harness)
|
||||||
{
|
{
|
||||||
const std::uint32_t frames[] { 100U };
|
const std::uint32_t frames[] { 100U };
|
||||||
@@ -616,6 +667,9 @@ int main()
|
|||||||
harness.run("project save commit plan succeeds for temporary swap", project_save_commit_plan_succeeds_for_temporary_swap);
|
harness.run("project save commit plan succeeds for temporary swap", project_save_commit_plan_succeeds_for_temporary_swap);
|
||||||
harness.run("project save commit plan fails when target remove fails", project_save_commit_plan_fails_when_target_remove_fails);
|
harness.run("project save commit plan fails when target remove fails", project_save_commit_plan_fails_when_target_remove_fails);
|
||||||
harness.run("project save commit plan flags missing target after rename failure", project_save_commit_plan_flags_missing_target_after_rename_failure);
|
harness.run("project save commit plan flags missing target after rename failure", project_save_commit_plan_flags_missing_target_after_rename_failure);
|
||||||
|
harness.run("project save post commit plan records success side effects", project_save_post_commit_plan_records_success_side_effects);
|
||||||
|
harness.run("project save post commit plan skips timelapse without encoder", project_save_post_commit_plan_skips_timelapse_without_encoder);
|
||||||
|
harness.run("project save post commit plan preserves state after failure", project_save_post_commit_plan_preserves_state_after_failure);
|
||||||
harness.run("snapshot plan rejects invalid canvas state", snapshot_plan_rejects_invalid_canvas_state);
|
harness.run("snapshot plan rejects invalid canvas state", snapshot_plan_rejects_invalid_canvas_state);
|
||||||
harness.run("clear plan records legacy canvas effects", clear_plan_records_legacy_canvas_effects);
|
harness.run("clear plan records legacy canvas effects", clear_plan_records_legacy_canvas_effects);
|
||||||
harness.run("clear plan noops without canvas", clear_plan_noops_without_canvas);
|
harness.run("clear plan noops without canvas", clear_plan_noops_without_canvas);
|
||||||
|
|||||||
@@ -416,6 +416,8 @@ struct PlanCanvasProjectSaveTargetArgs {
|
|||||||
bool target_exists = false;
|
bool target_exists = false;
|
||||||
bool remove_fails = false;
|
bool remove_fails = false;
|
||||||
bool rename_fails = false;
|
bool rename_fails = false;
|
||||||
|
bool encoder_available = false;
|
||||||
|
bool progress_visible = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlanCanvasDocumentSnapshotArgs {
|
struct PlanCanvasDocumentSnapshotArgs {
|
||||||
@@ -2562,7 +2564,7 @@ void print_help()
|
|||||||
<< " plan-canvas-view-density [--density N] [--bad-float]\n"
|
<< " plan-canvas-view-density [--density N] [--bad-float]\n"
|
||||||
<< " plan-canvas-view-cursor-mode [--mode N]\n"
|
<< " plan-canvas-view-cursor-mode [--mode N]\n"
|
||||||
<< " plan-canvas-cursor [--mode draw|erase|line|camera|grid|copy|cut|fill|mask-free|mask-line|bucket] [--visibility never|small-brush|not-painting|always] [--brush-size N] [--no-brush] [--drawing] [--alt] [--resizing] [--picking] [--bad-size]\n"
|
<< " plan-canvas-cursor [--mode draw|erase|line|camera|grid|copy|cut|fill|mask-free|mask-line|bucket] [--visibility never|small-brush|not-painting|always] [--brush-size N] [--no-brush] [--drawing] [--alt] [--resizing] [--picking] [--bad-size]\n"
|
||||||
<< " plan-canvas-project-save-target [--data-dir DIR] [--path FILE] [--target-exists] [--remove-fails] [--rename-fails]\n"
|
<< " plan-canvas-project-save-target [--data-dir DIR] [--path FILE] [--target-exists] [--remove-fails] [--rename-fails] [--encoder] [--progress]\n"
|
||||||
<< " plan-grid-operation --kind pick|load|reload|clear|render|commit [--path FILE] [--no-heightmap] [--no-canvas] [--float32] [--float16] [--texture-resolution N] [--samples N]\n"
|
<< " plan-grid-operation --kind pick|load|reload|clear|render|commit [--path FILE] [--no-heightmap] [--no-canvas] [--float32] [--float16] [--texture-resolution N] [--samples N]\n"
|
||||||
<< " plan-history-operation --kind undo|redo|clear [--undo-count N] [--redo-count N] [--memory-bytes N]\n"
|
<< " plan-history-operation --kind undo|redo|clear [--undo-count N] [--redo-count N] [--memory-bytes N]\n"
|
||||||
<< " plan-main-toolbar --command open|save|undo|redo|clear-history|clear-canvas|message-box|settings [--undo-count N] [--redo-count N] [--memory-bytes N] [--no-canvas]\n"
|
<< " plan-main-toolbar --command open|save|undo|redo|clear-history|clear-canvas|message-box|settings [--undo-count N] [--redo-count N] [--memory-bytes N] [--no-canvas]\n"
|
||||||
@@ -6097,6 +6099,10 @@ pp::foundation::Status parse_plan_canvas_project_save_target_args(
|
|||||||
args.remove_fails = true;
|
args.remove_fails = true;
|
||||||
} else if (key == "--rename-fails") {
|
} else if (key == "--rename-fails") {
|
||||||
args.rename_fails = true;
|
args.rename_fails = true;
|
||||||
|
} else if (key == "--encoder") {
|
||||||
|
args.encoder_available = true;
|
||||||
|
} else if (key == "--progress") {
|
||||||
|
args.progress_visible = true;
|
||||||
} else {
|
} else {
|
||||||
return pp::foundation::Status::invalid_argument("unknown option");
|
return pp::foundation::Status::invalid_argument("unknown option");
|
||||||
}
|
}
|
||||||
@@ -6144,6 +6150,12 @@ int plan_canvas_project_save_target(int argc, char** argv)
|
|||||||
.temporary_rename_attempted = temporary_rename_attempted,
|
.temporary_rename_attempted = temporary_rename_attempted,
|
||||||
.temporary_rename_succeeded = temporary_rename_succeeded,
|
.temporary_rename_succeeded = temporary_rename_succeeded,
|
||||||
});
|
});
|
||||||
|
const auto post_commit_plan = pp::app::plan_document_canvas_project_save_post_commit(
|
||||||
|
pp::app::DocumentCanvasProjectSavePostCommitInput {
|
||||||
|
.save_succeeded = commit_plan.saved,
|
||||||
|
.timelapse_encoder_available = args.encoder_available,
|
||||||
|
.progress_ui_visible = args.progress_visible,
|
||||||
|
});
|
||||||
std::cout << "{\"ok\":true,\"command\":\"plan-canvas-project-save-target\""
|
std::cout << "{\"ok\":true,\"command\":\"plan-canvas-project-save-target\""
|
||||||
<< ",\"dataDirectory\":\"" << json_escape(args.data_directory)
|
<< ",\"dataDirectory\":\"" << json_escape(args.data_directory)
|
||||||
<< "\",\"targetPath\":\"" << json_escape(value.target_path)
|
<< "\",\"targetPath\":\"" << json_escape(value.target_path)
|
||||||
@@ -6163,7 +6175,18 @@ int plan_canvas_project_save_target(int argc, char** argv)
|
|||||||
<< ",\"temporaryRenamed\":" << json_bool(commit_plan.temporary_renamed)
|
<< ",\"temporaryRenamed\":" << json_bool(commit_plan.temporary_renamed)
|
||||||
<< ",\"targetMayBeMissing\":" << json_bool(commit_plan.target_may_be_missing)
|
<< ",\"targetMayBeMissing\":" << json_bool(commit_plan.target_may_be_missing)
|
||||||
<< ",\"message\":\"" << json_escape(std::string(commit_plan.log_message))
|
<< ",\"message\":\"" << json_escape(std::string(commit_plan.log_message))
|
||||||
<< "\"}"
|
<< "\"},\"postCommitPlan\":{\"marksDocumentClean\":"
|
||||||
|
<< json_bool(post_commit_plan.marks_document_clean)
|
||||||
|
<< ",\"marksNewDocumentCommitted\":"
|
||||||
|
<< json_bool(post_commit_plan.marks_new_document_committed)
|
||||||
|
<< ",\"savesTimelapseSidecar\":"
|
||||||
|
<< json_bool(post_commit_plan.saves_timelapse_sidecar)
|
||||||
|
<< ",\"flushesPlatformStorage\":"
|
||||||
|
<< json_bool(post_commit_plan.flushes_platform_storage)
|
||||||
|
<< ",\"dismissesProgressUi\":"
|
||||||
|
<< json_bool(post_commit_plan.dismisses_progress_ui)
|
||||||
|
<< ",\"updatesTitle\":" << json_bool(post_commit_plan.updates_title)
|
||||||
|
<< "}"
|
||||||
<< "}\n";
|
<< "}\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user