Plan app dialog factories
This commit is contained in:
@@ -240,6 +240,7 @@ target_link_libraries(pp_platform_api
|
||||
|
||||
add_library(pp_app_core STATIC
|
||||
src/app_core/about_menu.h
|
||||
src/app_core/app_dialog.h
|
||||
src/app_core/app_frame.h
|
||||
src/app_core/app_input.h
|
||||
src/app_core/app_preferences.h
|
||||
|
||||
@@ -832,6 +832,10 @@ Known local toolchain state:
|
||||
timelapse start/stop/no-op decisions, VR mode success/failure dispatch,
|
||||
simple stored preferences, and `AppPreferenceServices` execution dispatch for
|
||||
options-menu side effects.
|
||||
- `pp_app_core_app_dialog_tests` covers app-level progress/message/input dialog
|
||||
metadata planning, progress initialization, negative progress-total clamping,
|
||||
message cancel-button policy, input OK-caption propagation, and malformed
|
||||
empty OK-caption rejection without requiring legacy `Node*` dialogs.
|
||||
- `pp_app_core_app_startup_tests` covers startup run-counter increment
|
||||
planning, optional auto-timelapse/license/VR-controller decisions, negative
|
||||
and overflow run-counter rejection, stable full startup dispatch ordering,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -198,6 +198,13 @@ and floating-point render targets; `App::title_update`,
|
||||
`App::update_memory_usage`, `App::update_rec_frames`, resolution helpers,
|
||||
`App::initLayout`, and `pano_cli plan-app-status` consume those contracts while
|
||||
legacy UI nodes still render the strings and status lights.
|
||||
App-level progress, message, and input dialog metadata now also lives in
|
||||
`pp_app_core` through `plan_app_progress_dialog`,
|
||||
`plan_app_message_dialog`, and `plan_app_input_dialog`; `App::show_progress`,
|
||||
`App::message_box`, `App::input_box`, and `pano_cli plan-app-dialog` consume
|
||||
those plans before retained `NodeProgressBar`, `NodeMessageBox`, and
|
||||
`NodeInputBox` creation. Legacy dialog node lifetime/layout ownership remains
|
||||
tracked under `DEBT-0058`.
|
||||
Frame-level app decisions for the initial surface size, redraw/animation update
|
||||
gating, layout ticking, resize render-target recreation, canvas-stroke drawing,
|
||||
VR UI drawing, main UI drawing, UI observer clipping/on-screen transition/scissor
|
||||
@@ -1691,6 +1698,15 @@ Results:
|
||||
- Focused preference CTest coverage passed for
|
||||
`pp_app_core_app_preferences_tests` and the app-preferences CLI smoke tests
|
||||
after the live bridge split, including VR mode failed-start status coverage.
|
||||
- `PanoPainter`, `pp_app_core_app_dialog_tests`, and `pano_cli` built after
|
||||
progress/message/input dialog metadata moved into `pp_app_core` while live
|
||||
`App` factories kept retained `Node*` creation.
|
||||
- Focused app-dialog CTest coverage passed for
|
||||
`pp_app_core_app_dialog_tests` and the `pano_cli_plan_app_dialog_*` smoke
|
||||
tests, including negative progress-total clamping and rejected empty
|
||||
input-dialog OK captions.
|
||||
- Android arm64 headless `pp_app_core`, `pano_cli`, and
|
||||
`pp_app_core_app_dialog_tests` built after the app-dialog planning slice.
|
||||
- `PanoPainter`, `pp_app_core_app_startup_tests`, and `pano_cli` built after
|
||||
startup preference/runtime execution and startup resource sequencing moved
|
||||
behind app startup services.
|
||||
|
||||
78
src/app_core/app_dialog.h
Normal file
78
src/app_core/app_dialog.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include "foundation/result.h"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace pp::app {
|
||||
|
||||
enum class AppDialogKind {
|
||||
progress,
|
||||
message,
|
||||
input,
|
||||
};
|
||||
|
||||
struct AppProgressDialogPlan {
|
||||
std::string title;
|
||||
int total = 0;
|
||||
int count = 0;
|
||||
float progress_fraction = 0.0F;
|
||||
};
|
||||
|
||||
struct AppMessageDialogPlan {
|
||||
std::string title;
|
||||
std::string message;
|
||||
std::string ok_caption = "Ok";
|
||||
bool show_cancel = false;
|
||||
};
|
||||
|
||||
struct AppInputDialogPlan {
|
||||
std::string title;
|
||||
std::string field_name;
|
||||
std::string ok_caption = "Ok";
|
||||
};
|
||||
|
||||
[[nodiscard]] inline AppProgressDialogPlan plan_app_progress_dialog(
|
||||
std::string_view title,
|
||||
int total) noexcept
|
||||
{
|
||||
return {
|
||||
std::string(title),
|
||||
total < 0 ? 0 : total,
|
||||
0,
|
||||
0.0F,
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] inline AppMessageDialogPlan plan_app_message_dialog(
|
||||
std::string_view title,
|
||||
std::string_view message,
|
||||
bool show_cancel)
|
||||
{
|
||||
return {
|
||||
std::string(title),
|
||||
std::string(message),
|
||||
"Ok",
|
||||
show_cancel,
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] inline pp::foundation::Result<AppInputDialogPlan> plan_app_input_dialog(
|
||||
std::string_view title,
|
||||
std::string_view field_name,
|
||||
std::string_view ok_caption)
|
||||
{
|
||||
if (ok_caption.empty()) {
|
||||
return pp::foundation::Result<AppInputDialogPlan>::failure(
|
||||
pp::foundation::Status::invalid_argument("input dialog ok caption must not be empty"));
|
||||
}
|
||||
|
||||
return pp::foundation::Result<AppInputDialogPlan>::success({
|
||||
std::string(title),
|
||||
std::string(field_name),
|
||||
std::string(ok_caption),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace pp::app
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "pch.h"
|
||||
#include "app.h"
|
||||
#include "app_core/app_dialog.h"
|
||||
#include "app_core/document_layer.h"
|
||||
#include "app_core/document_resize.h"
|
||||
#include "app_core/document_export.h"
|
||||
@@ -108,30 +109,32 @@ void start_document_export_collection(
|
||||
|
||||
std::shared_ptr<NodeProgressBar> App::show_progress(const std::string& title, int total /*= 0*/)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_progress_dialog(title, total);
|
||||
auto pb = std::make_shared<NodeProgressBar>();
|
||||
pb->set_manager(&layout);
|
||||
pb->init();
|
||||
pb->create();
|
||||
pb->loaded();
|
||||
pb->m_progress->SetWidthP(0);
|
||||
pb->m_title->set_text(title.c_str());
|
||||
pb->m_total = total;
|
||||
pb->m_count = 0;
|
||||
pb->m_progress->SetWidthP(plan.progress_fraction);
|
||||
pb->m_title->set_text(plan.title.c_str());
|
||||
pb->m_total = plan.total;
|
||||
pb->m_count = plan.count;
|
||||
layout[main_id]->add_child(pb);
|
||||
return pb;
|
||||
}
|
||||
|
||||
std::shared_ptr<NodeMessageBox> App::message_box(const std::string &title, const std::string& text, bool cancel_button)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_message_dialog(title, text, cancel_button);
|
||||
auto m = std::make_shared<NodeMessageBox>();
|
||||
m->set_manager(&layout);
|
||||
m->init();
|
||||
m->create();
|
||||
m->loaded();
|
||||
m->m_title->set_text(title.c_str());
|
||||
m->m_message->set_text(text.c_str());
|
||||
m->btn_ok->m_text->set_text("Ok");
|
||||
if (!cancel_button)
|
||||
m->m_title->set_text(plan.title.c_str());
|
||||
m->m_message->set_text(plan.message.c_str());
|
||||
m->btn_ok->m_text->set_text(plan.ok_caption.c_str());
|
||||
if (!plan.show_cancel)
|
||||
m->btn_cancel->destroy();
|
||||
layout[main_id]->add_child(m);
|
||||
return m;
|
||||
@@ -140,14 +143,20 @@ std::shared_ptr<NodeMessageBox> App::message_box(const std::string &title, const
|
||||
std::shared_ptr<NodeInputBox> App::input_box(const std::string& title,
|
||||
const std::string& field_name, const std::string& ok_caption /*= "Ok"*/)
|
||||
{
|
||||
const auto plan_result = pp::app::plan_app_input_dialog(title, field_name, ok_caption);
|
||||
if (!plan_result) {
|
||||
LOG("input dialog skipped: %s", plan_result.status().message);
|
||||
return nullptr;
|
||||
}
|
||||
const auto& plan = plan_result.value();
|
||||
auto m = std::make_shared<NodeInputBox>();
|
||||
m->set_manager(&layout);
|
||||
m->init();
|
||||
m->create();
|
||||
m->loaded();
|
||||
m->m_title->set_text(title.c_str());
|
||||
m->m_field_name->set_text(field_name.c_str());
|
||||
m->btn_ok->m_text->set_text(ok_caption.c_str());
|
||||
m->m_title->set_text(plan.title.c_str());
|
||||
m->m_field_name->set_text(plan.field_name.c_str());
|
||||
m->btn_ok->m_text->set_text(plan.ok_caption.c_str());
|
||||
layout[main_id]->add_child(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -545,6 +545,16 @@ add_test(NAME pp_app_core_app_status_tests COMMAND pp_app_core_app_status_tests)
|
||||
set_tests_properties(pp_app_core_app_status_tests PROPERTIES
|
||||
LABELS "app;desktop-fast;fuzz")
|
||||
|
||||
add_executable(pp_app_core_app_dialog_tests
|
||||
app_core/app_dialog_tests.cpp)
|
||||
target_link_libraries(pp_app_core_app_dialog_tests PRIVATE
|
||||
pp_app_core
|
||||
pp_test_harness)
|
||||
|
||||
add_test(NAME pp_app_core_app_dialog_tests COMMAND pp_app_core_app_dialog_tests)
|
||||
set_tests_properties(pp_app_core_app_dialog_tests PROPERTIES
|
||||
LABELS "app;desktop-fast;fuzz")
|
||||
|
||||
add_executable(pp_app_core_app_startup_tests
|
||||
app_core/app_startup_tests.cpp)
|
||||
target_link_libraries(pp_app_core_app_startup_tests PRIVATE
|
||||
@@ -948,6 +958,31 @@ if(TARGET pano_cli)
|
||||
LABELS "app;integration;desktop-fast;fuzz"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-cloud-transfer\".*\"action\":\"start-transfer\".*\"notify\":false.*\"fraction\":0")
|
||||
|
||||
add_test(NAME pano_cli_plan_app_dialog_progress_smoke
|
||||
COMMAND pano_cli plan-app-dialog --kind progress --title Saving --total -4)
|
||||
set_tests_properties(pano_cli_plan_app_dialog_progress_smoke PROPERTIES
|
||||
LABELS "app;integration;desktop-fast;fuzz"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-dialog\".*\"kind\":\"progress\".*\"title\":\"Saving\".*\"total\":0.*\"count\":0.*\"progressFraction\":0")
|
||||
|
||||
add_test(NAME pano_cli_plan_app_dialog_message_smoke
|
||||
COMMAND pano_cli plan-app-dialog --kind message --title Import --message Brushes --cancel)
|
||||
set_tests_properties(pano_cli_plan_app_dialog_message_smoke PROPERTIES
|
||||
LABELS "app;integration;desktop-fast"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-dialog\".*\"kind\":\"message\".*\"title\":\"Import\".*\"message\":\"Brushes\".*\"okCaption\":\"Ok\".*\"showCancel\":true")
|
||||
|
||||
add_test(NAME pano_cli_plan_app_dialog_input_smoke
|
||||
COMMAND pano_cli plan-app-dialog --kind input --title Rename --field-name Layer --ok-caption Save)
|
||||
set_tests_properties(pano_cli_plan_app_dialog_input_smoke PROPERTIES
|
||||
LABELS "app;integration;desktop-fast"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-dialog\".*\"kind\":\"input\".*\"title\":\"Rename\".*\"fieldName\":\"Layer\".*\"okCaption\":\"Save")
|
||||
|
||||
add_test(NAME pano_cli_plan_app_dialog_rejects_empty_ok_caption
|
||||
COMMAND pano_cli plan-app-dialog --kind input --ok-caption "")
|
||||
set_tests_properties(pano_cli_plan_app_dialog_rejects_empty_ok_caption PROPERTIES
|
||||
LABELS "app;integration;desktop-fast;fuzz"
|
||||
WILL_FAIL TRUE
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-dialog\".*\"message\":\"input dialog ok caption")
|
||||
|
||||
add_test(NAME pano_cli_plan_recording_session_stopped_smoke
|
||||
COMMAND pano_cli plan-recording-session --frame-count 12)
|
||||
set_tests_properties(pano_cli_plan_recording_session_stopped_smoke PROPERTIES
|
||||
|
||||
68
tests/app_core/app_dialog_tests.cpp
Normal file
68
tests/app_core/app_dialog_tests.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "app_core/app_dialog.h"
|
||||
#include "test_harness.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void progress_dialog_initializes_progress_state(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_progress_dialog("Saving", 12);
|
||||
PP_EXPECT(harness, plan.title == "Saving");
|
||||
PP_EXPECT(harness, plan.total == 12);
|
||||
PP_EXPECT(harness, plan.count == 0);
|
||||
PP_EXPECT(harness, plan.progress_fraction == 0.0F);
|
||||
}
|
||||
|
||||
void progress_dialog_clamps_negative_total(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_progress_dialog("Broken", -4);
|
||||
PP_EXPECT(harness, plan.total == 0);
|
||||
PP_EXPECT(harness, plan.count == 0);
|
||||
PP_EXPECT(harness, plan.progress_fraction == 0.0F);
|
||||
}
|
||||
|
||||
void message_dialog_preserves_cancel_policy(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_message_dialog("Import", "Import brushes?", true);
|
||||
PP_EXPECT(harness, plan.title == "Import");
|
||||
PP_EXPECT(harness, plan.message == "Import brushes?");
|
||||
PP_EXPECT(harness, plan.ok_caption == "Ok");
|
||||
PP_EXPECT(harness, plan.show_cancel);
|
||||
}
|
||||
|
||||
void message_dialog_defaults_to_no_cancel(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_message_dialog("License", "Disabled", false);
|
||||
PP_EXPECT(harness, plan.title == "License");
|
||||
PP_EXPECT(harness, plan.message == "Disabled");
|
||||
PP_EXPECT(harness, !plan.show_cancel);
|
||||
}
|
||||
|
||||
void input_dialog_preserves_ok_caption(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_input_dialog("Rename", "Layer", "Save");
|
||||
PP_EXPECT(harness, plan);
|
||||
PP_EXPECT(harness, plan.value().title == "Rename");
|
||||
PP_EXPECT(harness, plan.value().field_name == "Layer");
|
||||
PP_EXPECT(harness, plan.value().ok_caption == "Save");
|
||||
}
|
||||
|
||||
void input_dialog_rejects_empty_ok_caption(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_input_dialog("Rename", "Layer", "");
|
||||
PP_EXPECT(harness, !plan);
|
||||
PP_EXPECT(harness, plan.status().code == pp::foundation::StatusCode::invalid_argument);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
pp::tests::Harness harness;
|
||||
harness.run("progress dialog initializes progress state", progress_dialog_initializes_progress_state);
|
||||
harness.run("progress dialog clamps negative total", progress_dialog_clamps_negative_total);
|
||||
harness.run("message dialog preserves cancel policy", message_dialog_preserves_cancel_policy);
|
||||
harness.run("message dialog defaults to no cancel", message_dialog_defaults_to_no_cancel);
|
||||
harness.run("input dialog preserves ok caption", input_dialog_preserves_ok_caption);
|
||||
harness.run("input dialog rejects empty ok caption", input_dialog_rejects_empty_ok_caption);
|
||||
return harness.finish();
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "app_core/about_menu.h"
|
||||
#include "app_core/app_dialog.h"
|
||||
#include "app_core/app_preferences.h"
|
||||
#include "app_core/app_frame.h"
|
||||
#include "app_core/app_input.h"
|
||||
@@ -249,6 +250,16 @@ struct PlanAppPreferencesArgs {
|
||||
int cursor_mode = 0;
|
||||
};
|
||||
|
||||
struct PlanAppDialogArgs {
|
||||
pp::app::AppDialogKind kind = pp::app::AppDialogKind::progress;
|
||||
std::string title = "Saving";
|
||||
std::string message = "Done";
|
||||
std::string field_name = "Name";
|
||||
std::string ok_caption = "Ok";
|
||||
int total = 0;
|
||||
bool cancel = false;
|
||||
};
|
||||
|
||||
struct PlanAppStartupArgs {
|
||||
int run_counter = 0;
|
||||
bool auto_timelapse_enabled = true;
|
||||
@@ -1931,6 +1942,20 @@ const char* cloud_transfer_action_name(pp::app::CloudTransferAction action) noex
|
||||
return "reject-missing-source";
|
||||
}
|
||||
|
||||
const char* app_dialog_kind_name(pp::app::AppDialogKind kind) noexcept
|
||||
{
|
||||
switch (kind) {
|
||||
case pp::app::AppDialogKind::progress:
|
||||
return "progress";
|
||||
case pp::app::AppDialogKind::message:
|
||||
return "message";
|
||||
case pp::app::AppDialogKind::input:
|
||||
return "input";
|
||||
}
|
||||
|
||||
return "progress";
|
||||
}
|
||||
|
||||
const char* recording_start_action_name(pp::app::RecordingStartAction action) noexcept
|
||||
{
|
||||
switch (action) {
|
||||
@@ -2147,6 +2172,7 @@ void print_help()
|
||||
<< " plan-cloud-browse [--no-canvas] [--selected-file FILE]\n"
|
||||
<< " plan-cloud-upload-all [--file-count N] [--no-progress-ui]\n"
|
||||
<< " plan-cloud-transfer [--direction download|upload] [--source TEXT] [--destination FILE] [--progress] [--disable-tls-verification] [--progress-total N] [--progress-current N]\n"
|
||||
<< " plan-app-dialog --kind progress|message|input [--title TEXT] [--message TEXT] [--field-name TEXT] [--ok-caption TEXT] [--total N] [--cancel]\n"
|
||||
<< " plan-recording-session [--running] [--frame-count N] [--platform-deletes-recorded-files] [--no-encoder] [--no-canvas]\n"
|
||||
<< " plan-app-preferences [--ui-scale N] [--display-density N] [--current-scale N] [--scale-option N] [--viewport-scale N] [--rtl] [--timelapse-disabled] [--recording-running] [--vr-controllers-disabled] [--cursor-mode N]\n"
|
||||
<< " plan-app-startup [--run-counter N] [--auto-timelapse-disabled] [--vr-controllers-disabled] [--license-invalid]\n"
|
||||
@@ -3675,6 +3701,121 @@ int plan_cloud_transfer(int argc, char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
pp::foundation::Status parse_plan_app_dialog_args(
|
||||
int argc,
|
||||
char** argv,
|
||||
PlanAppDialogArgs& args)
|
||||
{
|
||||
for (int i = 2; i < argc; ++i) {
|
||||
const std::string_view key(argv[i]);
|
||||
if (key == "--kind") {
|
||||
if (i + 1 >= argc) {
|
||||
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||
}
|
||||
const std::string_view value(argv[++i]);
|
||||
if (value == "progress") {
|
||||
args.kind = pp::app::AppDialogKind::progress;
|
||||
} else if (value == "message") {
|
||||
args.kind = pp::app::AppDialogKind::message;
|
||||
} else if (value == "input") {
|
||||
args.kind = pp::app::AppDialogKind::input;
|
||||
} else {
|
||||
return pp::foundation::Status::invalid_argument("unknown app dialog kind");
|
||||
}
|
||||
} else if (key == "--title") {
|
||||
if (i + 1 >= argc) {
|
||||
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||
}
|
||||
args.title = argv[++i];
|
||||
} else if (key == "--message") {
|
||||
if (i + 1 >= argc) {
|
||||
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||
}
|
||||
args.message = argv[++i];
|
||||
} else if (key == "--field-name") {
|
||||
if (i + 1 >= argc) {
|
||||
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||
}
|
||||
args.field_name = argv[++i];
|
||||
} else if (key == "--ok-caption") {
|
||||
if (i + 1 >= argc) {
|
||||
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||
}
|
||||
args.ok_caption = argv[++i];
|
||||
} else if (key == "--total") {
|
||||
if (i + 1 >= argc) {
|
||||
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||
}
|
||||
const auto value = parse_i32_arg(argv[++i]);
|
||||
if (!value) {
|
||||
return value.status();
|
||||
}
|
||||
args.total = value.value();
|
||||
} else if (key == "--cancel") {
|
||||
args.cancel = true;
|
||||
} else {
|
||||
return pp::foundation::Status::invalid_argument("unknown option");
|
||||
}
|
||||
}
|
||||
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
int plan_app_dialog(int argc, char** argv)
|
||||
{
|
||||
PlanAppDialogArgs args;
|
||||
const auto status = parse_plan_app_dialog_args(argc, argv, args);
|
||||
if (!status.ok()) {
|
||||
print_error("plan-app-dialog", status.message);
|
||||
return 2;
|
||||
}
|
||||
|
||||
switch (args.kind) {
|
||||
case pp::app::AppDialogKind::progress:
|
||||
{
|
||||
const auto plan = pp::app::plan_app_progress_dialog(args.title, args.total);
|
||||
std::cout << "{\"ok\":true,\"command\":\"plan-app-dialog\""
|
||||
<< ",\"kind\":\"" << app_dialog_kind_name(args.kind)
|
||||
<< "\",\"plan\":{\"title\":\"" << json_escape(plan.title)
|
||||
<< "\",\"total\":" << plan.total
|
||||
<< ",\"count\":" << plan.count
|
||||
<< ",\"progressFraction\":" << plan.progress_fraction
|
||||
<< "}}\n";
|
||||
return 0;
|
||||
}
|
||||
case pp::app::AppDialogKind::message:
|
||||
{
|
||||
const auto plan = pp::app::plan_app_message_dialog(args.title, args.message, args.cancel);
|
||||
std::cout << "{\"ok\":true,\"command\":\"plan-app-dialog\""
|
||||
<< ",\"kind\":\"" << app_dialog_kind_name(args.kind)
|
||||
<< "\",\"plan\":{\"title\":\"" << json_escape(plan.title)
|
||||
<< "\",\"message\":\"" << json_escape(plan.message)
|
||||
<< "\",\"okCaption\":\"" << json_escape(plan.ok_caption)
|
||||
<< "\",\"showCancel\":" << json_bool(plan.show_cancel)
|
||||
<< "}}\n";
|
||||
return 0;
|
||||
}
|
||||
case pp::app::AppDialogKind::input:
|
||||
{
|
||||
const auto plan = pp::app::plan_app_input_dialog(args.title, args.field_name, args.ok_caption);
|
||||
if (!plan) {
|
||||
print_error("plan-app-dialog", plan.status().message);
|
||||
return 2;
|
||||
}
|
||||
std::cout << "{\"ok\":true,\"command\":\"plan-app-dialog\""
|
||||
<< ",\"kind\":\"" << app_dialog_kind_name(args.kind)
|
||||
<< "\",\"plan\":{\"title\":\"" << json_escape(plan.value().title)
|
||||
<< "\",\"fieldName\":\"" << json_escape(plan.value().field_name)
|
||||
<< "\",\"okCaption\":\"" << json_escape(plan.value().ok_caption)
|
||||
<< "}}\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
print_error("plan-app-dialog", "unknown app dialog kind");
|
||||
return 2;
|
||||
}
|
||||
|
||||
pp::foundation::Status parse_plan_recording_session_args(
|
||||
int argc,
|
||||
char** argv,
|
||||
@@ -10879,6 +11020,10 @@ int main(int argc, char** argv)
|
||||
return plan_cloud_transfer(argc, argv);
|
||||
}
|
||||
|
||||
if (command == "plan-app-dialog") {
|
||||
return plan_app_dialog(argc, argv);
|
||||
}
|
||||
|
||||
if (command == "plan-recording-session") {
|
||||
return plan_recording_session(argc, argv);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user