Move layout reload policy into platform api
This commit is contained in:
@@ -212,6 +212,8 @@ target_link_libraries(pp_ui_core
|
|||||||
pp_project_warnings)
|
pp_project_warnings)
|
||||||
|
|
||||||
add_library(pp_platform_api STATIC
|
add_library(pp_platform_api STATIC
|
||||||
|
src/platform_api/asset_file_load_policy.cpp
|
||||||
|
src/platform_api/asset_file_load_policy.h
|
||||||
src/platform_api/network_tls_policy.cpp
|
src/platform_api/network_tls_policy.cpp
|
||||||
src/platform_api/network_tls_policy.h
|
src/platform_api/network_tls_policy.h
|
||||||
src/platform_api/platform_services.cpp
|
src/platform_api/platform_services.cpp
|
||||||
@@ -439,6 +441,7 @@ if(PP_BUILD_APP)
|
|||||||
pp_project_options
|
pp_project_options
|
||||||
PRIVATE
|
PRIVATE
|
||||||
pp_paint_renderer
|
pp_paint_renderer
|
||||||
|
pp_platform_api
|
||||||
pp_renderer_api
|
pp_renderer_api
|
||||||
pp_project_warnings)
|
pp_project_warnings)
|
||||||
if(TARGET pp_renderer_gl)
|
if(TARGET pp_renderer_gl)
|
||||||
@@ -475,6 +478,7 @@ if(PP_BUILD_APP)
|
|||||||
pp_legacy_ui_core
|
pp_legacy_ui_core
|
||||||
pp_project_options
|
pp_project_options
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
pp_platform_api
|
||||||
pp_renderer_api
|
pp_renderer_api
|
||||||
pp_project_warnings)
|
pp_project_warnings)
|
||||||
if(TARGET pp_renderer_gl)
|
if(TARGET pp_renderer_gl)
|
||||||
|
|||||||
@@ -583,6 +583,11 @@ Known local toolchain state:
|
|||||||
while non-Windows platforms still reach retained platform bridges through
|
while non-Windows platforms still reach retained platform bridges through
|
||||||
the debt-tracked adapter isolated in
|
the debt-tracked adapter isolated in
|
||||||
`src/platform_legacy/legacy_platform_services.*`.
|
`src/platform_legacy/legacy_platform_services.*`.
|
||||||
|
- `pp_platform_api` also owns `plan_asset_file_load`, the SDK-free file-load
|
||||||
|
policy consumed by `LayoutManager` for XML layout reload decisions. The
|
||||||
|
helper preserves desktop mtime-based reload behavior and non-desktop
|
||||||
|
already-loaded skip behavior while keeping direct platform guards out of the
|
||||||
|
shared layout parser.
|
||||||
- `pp_renderer_gl` owns the tested `OpenGlInitialState` startup depth/blend
|
- `pp_renderer_gl` owns the tested `OpenGlInitialState` startup depth/blend
|
||||||
policy and dispatch application consumed by `App::init`, tested runtime
|
policy and dispatch application consumed by `App::init`, tested runtime
|
||||||
version/vendor/renderer/GLSL string query dispatch, tested default clear
|
version/vendor/renderer/GLSL string query dispatch, tested default clear
|
||||||
@@ -660,8 +665,8 @@ Known local toolchain state:
|
|||||||
split persistence/runtime dispatch, and malformed startup-plan rejection.
|
split persistence/runtime dispatch, and malformed startup-plan rejection.
|
||||||
- `pp_platform_api_tests` covers service dispatch for clipboard read/write,
|
- `pp_platform_api_tests` covers service dispatch for clipboard read/write,
|
||||||
empty clipboard writes, cursor visibility, virtual-keyboard visibility,
|
empty clipboard writes, cursor visibility, virtual-keyboard visibility,
|
||||||
external file display, file sharing, VR lifecycle, and picker callbacks
|
external file display, file sharing, VR lifecycle, layout/asset file load
|
||||||
without platform SDK headers or a window.
|
policy, and picker callbacks without platform SDK headers or a window.
|
||||||
- `pp_app_core_document_cloud_tests` covers cloud upload no-canvas,
|
- `pp_app_core_document_cloud_tests` covers cloud upload no-canvas,
|
||||||
new-document warning, clean publish prompt, and dirty save-before-upload
|
new-document warning, clean publish prompt, and dirty save-before-upload
|
||||||
decisions, plus cloud browse no-canvas/show-browser and selected-download
|
decisions, plus cloud browse no-canvas/show-browser and selected-download
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ agent or engineer to remove them without reconstructing context from chat.
|
|||||||
| DEBT-0051 | Open | Modernization | Document browser search roots and Browse dialog working-directory picker visibility/path formatting now dispatch through `PlatformServices`, but iOS `Inbox` inclusion and macOS directory picker/display-path behavior still live in `src/platform_legacy/legacy_platform_services.*` | Preserve current iOS document import/browse and desktop browse picker behavior while Apple platform shells are extracted incrementally | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug`; Apple package smoke once root Apple builds exist | Document browse roots and browse-directory picker/display formatting are owned by injected Apple and desktop `pp_platform_*` services with no legacy adapter branch |
|
| DEBT-0051 | Open | Modernization | Document browser search roots and Browse dialog working-directory picker visibility/path formatting now dispatch through `PlatformServices`, but iOS `Inbox` inclusion and macOS directory picker/display-path behavior still live in `src/platform_legacy/legacy_platform_services.*` | Preserve current iOS document import/browse and desktop browse picker behavior while Apple platform shells are extracted incrementally | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug`; Apple package smoke once root Apple builds exist | Document browse roots and browse-directory picker/display formatting are owned by injected Apple and desktop `pp_platform_*` services with no legacy adapter branch |
|
||||||
| DEBT-0052 | Open | Modernization | Native UI/window state saving now dispatches through `PlatformServices`, but macOS execution still lives in `src/platform_legacy/legacy_platform_services.*` and forwards to the retained Objective-C app bridge | Preserve current Windows/macOS UI persistence while platform shells are extracted incrementally | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug`; Windows app build; Apple package smoke once root Apple builds exist | UI/window state persistence is owned by injected platform services with no legacy adapter branch |
|
| DEBT-0052 | Open | Modernization | Native UI/window state saving now dispatches through `PlatformServices`, but macOS execution still lives in `src/platform_legacy/legacy_platform_services.*` and forwards to the retained Objective-C app bridge | Preserve current Windows/macOS UI persistence while platform shells are extracted incrementally | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug`; Windows app build; Apple package smoke once root Apple builds exist | UI/window state persistence is owned by injected platform services with no legacy adapter branch |
|
||||||
| DEBT-0053 | Open | Modernization | Prepared-file writable target selection and prepared-file export-dialog policy now dispatch through `PlatformServices`, but iOS/Web target selection still lives in `src/platform_legacy/legacy_platform_services.*` | Preserve mobile/Web export handoff behavior while platform shells are extracted incrementally | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug`; Windows app build; Apple/Web package smoke once root package builds exist | Prepared-file target selection, export-dialog policy, and save/download handoff are owned by injected platform services with no legacy adapter branch |
|
| DEBT-0053 | Open | Modernization | Prepared-file writable target selection and prepared-file export-dialog policy now dispatch through `PlatformServices`, but iOS/Web target selection still lives in `src/platform_legacy/legacy_platform_services.*` | Preserve mobile/Web export handoff behavior while platform shells are extracted incrementally | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug`; Windows app build; Apple/Web package smoke once root package builds exist | Prepared-file target selection, export-dialog policy, and save/download handoff are owned by injected platform services with no legacy adapter branch |
|
||||||
|
| DEBT-0054 | Open | Modernization | Layout XML file read/reload decisions now consume `pp_platform_api::plan_asset_file_load`, but that helper still encodes the retained compile-time platform policy: Windows/macOS use `stat` mtime reload checks, while other platforms treat already-loaded layouts as successful no-op loads | Preserve current layout hot-reload and mobile/Web single-load behavior while removing platform guards from the shared `LayoutManager` parser | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests`; Windows app build | Layout reload decisions are owned by injected platform storage/file-watch services or an asset manager boundary with platform-specific file watching removed from compile-time helpers |
|
||||||
|
|
||||||
## Closed Debt
|
## Closed Debt
|
||||||
|
|
||||||
|
|||||||
@@ -650,6 +650,9 @@ file display, file sharing, recording file cleanup, live asset/layout reload
|
|||||||
policy, diagnostic stacktrace/crash hooks, SonarPen availability/startup,
|
policy, diagnostic stacktrace/crash hooks, SonarPen availability/startup,
|
||||||
VR mode start/stop,
|
VR mode start/stop,
|
||||||
image/file/save-file pickers, and directory pickers.
|
image/file/save-file pickers, and directory pickers.
|
||||||
|
It also owns the SDK-free layout/asset file load policy helper used by
|
||||||
|
`LayoutManager`, so XML layout hot-reload timestamp checks no longer live in
|
||||||
|
the shared UI parser.
|
||||||
Windows installs an injected `WindowsPlatformServices` implementation from
|
Windows installs an injected `WindowsPlatformServices` implementation from
|
||||||
`src/platform_windows/windows_platform_services.*` in `pp_platform_windows`;
|
`src/platform_windows/windows_platform_services.*` in `pp_platform_windows`;
|
||||||
other platforms still route through the debt-tracked legacy fallback adapter
|
other platforms still route through the debt-tracked legacy fallback adapter
|
||||||
@@ -786,6 +789,9 @@ guards from `App::rec_clear`.
|
|||||||
The UI loop now asks `PlatformServices` whether live shader/layout reloading
|
The UI loop now asks `PlatformServices` whether live shader/layout reloading
|
||||||
should run, preserving the previous Windows/macOS reload behavior while removing
|
should run, preserving the previous Windows/macOS reload behavior while removing
|
||||||
the direct `(_WIN32 || __OSX__)` guard from `App::ui_thread_main`.
|
the direct `(_WIN32 || __OSX__)` guard from `App::ui_thread_main`.
|
||||||
|
Layout XML reload read/skip decisions now go through `pp_platform_api` as well,
|
||||||
|
preserving desktop mtime-based reloads and non-desktop single-load behavior
|
||||||
|
while removing the direct Windows/macOS guard from `LayoutManager::load`.
|
||||||
`App::stacktrace` and `App::crash_test` now dispatch through `PlatformServices`,
|
`App::stacktrace` and `App::crash_test` now dispatch through `PlatformServices`,
|
||||||
with Windows retaining the debug-break crash hook and the legacy adapter
|
with Windows retaining the debug-break crash hook and the legacy adapter
|
||||||
preserving Apple stacktrace/crash and Android crash-test behavior.
|
preserving Apple stacktrace/crash and Android crash-test behavior.
|
||||||
@@ -1766,6 +1772,7 @@ Results:
|
|||||||
collection policy dispatch, network TLS verification policy dispatch,
|
collection policy dispatch, network TLS verification policy dispatch,
|
||||||
default network TLS policy coverage, PPBR export data-directory policy
|
default network TLS policy coverage, PPBR export data-directory policy
|
||||||
dispatch, SonarPen availability/startup dispatch, VR lifecycle dispatch,
|
dispatch, SonarPen availability/startup dispatch, VR lifecycle dispatch,
|
||||||
|
layout/asset file load policy coverage,
|
||||||
live asset/layout reload policy dispatch,
|
live asset/layout reload policy dispatch,
|
||||||
diagnostic hook dispatch, per-frame platform hook dispatch, picker callback
|
diagnostic hook dispatch, per-frame platform hook dispatch, picker callback
|
||||||
dispatch, and prepared-file save/download callback dispatch. The live Windows
|
dispatch, and prepared-file save/download callback dispatch. The live Windows
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "node_border.h"
|
#include "node_border.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
|
#include "platform_api/asset_file_load_policy.h"
|
||||||
|
|
||||||
void LayoutManager::unload()
|
void LayoutManager::unload()
|
||||||
{
|
{
|
||||||
@@ -22,17 +23,13 @@ void LayoutManager::create()
|
|||||||
bool LayoutManager::load(const char* path)
|
bool LayoutManager::load(const char* path)
|
||||||
{
|
{
|
||||||
auto abs_path = Asset::absolute(path);
|
auto abs_path = Asset::absolute(path);
|
||||||
#if _WIN32 || __OSX__
|
const auto file_load = pp::platform::plan_asset_file_load(
|
||||||
struct stat tmp_info;
|
abs_path,
|
||||||
if (stat(abs_path.c_str(), &tmp_info) != 0)
|
m_loaded,
|
||||||
return false;
|
m_file_last_write_time);
|
||||||
if (tmp_info.st_mtime <= m_file_info.st_mtime)
|
if (!file_load.should_read_file)
|
||||||
return false;
|
return file_load.skipped_load_result;
|
||||||
m_file_info = tmp_info;
|
m_file_last_write_time = file_load.last_write_time;
|
||||||
#else
|
|
||||||
if (m_loaded)
|
|
||||||
return true; // already loaded
|
|
||||||
#endif // __ANDROID__
|
|
||||||
|
|
||||||
if (!m_layouts.empty() && on_reloading)
|
if (!m_layouts.empty() && on_reloading)
|
||||||
on_reloading();
|
on_reloading();
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
class LayoutManager
|
class LayoutManager
|
||||||
{
|
{
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
struct stat m_file_info { 0 };
|
std::int64_t m_file_last_write_time = 0;
|
||||||
public:
|
public:
|
||||||
std::map<uint16_t, std::shared_ptr<class Node>> m_layouts;
|
std::map<uint16_t, std::shared_ptr<class Node>> m_layouts;
|
||||||
bool m_loaded = false;
|
bool m_loaded = false;
|
||||||
|
|||||||
33
src/platform_api/asset_file_load_policy.cpp
Normal file
33
src/platform_api/asset_file_load_policy.cpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#include "platform_api/asset_file_load_policy.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
namespace pp::platform {
|
||||||
|
|
||||||
|
AssetFileLoadDecision plan_asset_file_load(
|
||||||
|
std::string_view absolute_path,
|
||||||
|
bool already_loaded,
|
||||||
|
std::int64_t previous_last_write_time)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32) || defined(__OSX__)
|
||||||
|
struct stat file_info {};
|
||||||
|
const std::string path(absolute_path);
|
||||||
|
if (stat(path.c_str(), &file_info) != 0)
|
||||||
|
return { false, false, previous_last_write_time };
|
||||||
|
|
||||||
|
const auto current_last_write_time = static_cast<std::int64_t>(file_info.st_mtime);
|
||||||
|
if (current_last_write_time <= previous_last_write_time)
|
||||||
|
return { false, false, previous_last_write_time };
|
||||||
|
|
||||||
|
return { true, true, current_last_write_time };
|
||||||
|
#else
|
||||||
|
if (already_loaded)
|
||||||
|
return { false, true, previous_last_write_time };
|
||||||
|
|
||||||
|
(void)absolute_path;
|
||||||
|
return { true, true, previous_last_write_time };
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
19
src/platform_api/asset_file_load_policy.h
Normal file
19
src/platform_api/asset_file_load_policy.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace pp::platform {
|
||||||
|
|
||||||
|
struct AssetFileLoadDecision {
|
||||||
|
bool should_read_file = true;
|
||||||
|
bool skipped_load_result = true;
|
||||||
|
std::int64_t last_write_time = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] AssetFileLoadDecision plan_asset_file_load(
|
||||||
|
std::string_view absolute_path,
|
||||||
|
bool already_loaded,
|
||||||
|
std::int64_t previous_last_write_time);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
#include "test_harness.h"
|
#include "test_harness.h"
|
||||||
|
|
||||||
|
#include "platform_api/asset_file_load_policy.h"
|
||||||
#include "platform_api/network_tls_policy.h"
|
#include "platform_api/network_tls_policy.h"
|
||||||
#include "platform_api/platform_services.h"
|
#include "platform_api/platform_services.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -757,6 +760,36 @@ void default_network_tls_policy_matches_build_target(pp::tests::Harness& harness
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void asset_file_load_policy_preserves_platform_reload_behavior(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto temp_path = std::filesystem::temp_directory_path()
|
||||||
|
/ "panopainter-platform-api-file-policy.xml";
|
||||||
|
{
|
||||||
|
std::ofstream file(temp_path);
|
||||||
|
file << "<layouts />";
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto first_load = pp::platform::plan_asset_file_load(
|
||||||
|
temp_path.string(),
|
||||||
|
false,
|
||||||
|
0);
|
||||||
|
PP_EXPECT(harness, first_load.should_read_file);
|
||||||
|
PP_EXPECT(harness, first_load.skipped_load_result);
|
||||||
|
|
||||||
|
const auto repeated_load = pp::platform::plan_asset_file_load(
|
||||||
|
temp_path.string(),
|
||||||
|
true,
|
||||||
|
first_load.last_write_time);
|
||||||
|
PP_EXPECT(harness, !repeated_load.should_read_file);
|
||||||
|
#if defined(_WIN32) || defined(__OSX__)
|
||||||
|
PP_EXPECT(harness, !repeated_load.skipped_load_result);
|
||||||
|
#else
|
||||||
|
PP_EXPECT(harness, repeated_load.skipped_load_result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::filesystem::remove(temp_path);
|
||||||
|
}
|
||||||
|
|
||||||
void platform_services_dispatch_ppbr_export_directory_policy(pp::tests::Harness& harness)
|
void platform_services_dispatch_ppbr_export_directory_policy(pp::tests::Harness& harness)
|
||||||
{
|
{
|
||||||
FakePlatformServices fake("unused");
|
FakePlatformServices fake("unused");
|
||||||
@@ -833,6 +866,9 @@ int main()
|
|||||||
platform_services_dispatch_document_export_collection_policy);
|
platform_services_dispatch_document_export_collection_policy);
|
||||||
harness.run("platform services dispatch network tls policy", platform_services_dispatch_network_tls_policy);
|
harness.run("platform services dispatch network tls policy", platform_services_dispatch_network_tls_policy);
|
||||||
harness.run("default network tls policy matches build target", default_network_tls_policy_matches_build_target);
|
harness.run("default network tls policy matches build target", default_network_tls_policy_matches_build_target);
|
||||||
|
harness.run(
|
||||||
|
"asset file load policy preserves platform reload behavior",
|
||||||
|
asset_file_load_policy_preserves_platform_reload_behavior);
|
||||||
harness.run(
|
harness.run(
|
||||||
"platform services dispatch ppbr export directory policy",
|
"platform services dispatch ppbr export directory policy",
|
||||||
platform_services_dispatch_ppbr_export_directory_policy);
|
platform_services_dispatch_ppbr_export_directory_policy);
|
||||||
|
|||||||
Reference in New Issue
Block a user