mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-14 00:52:04 +00:00
* Add OrcaCloud sync platform and preset bundle sharing system Introduce OrcaCloud, a cloud sync platform for user presets, alongside a preset bundle system that enables sharing printer/filament/process profiles as local exportable bundles or subscribed cloud bundles. OrcaCloud platform: - Auth to Orca Cloud - Encrypted token storage (file-based or system keychain) - User preset sync with - Profile migration from default/bambu folders on first login - Homepage integration with entrance to cloud.orcaslicer.com Preset bundles: - Local bundle import/export with bundle_structure.json metadata - Subscribed cloud bundles with version-based update checking - Thread-safe concurrent bundle access with read-write mutex - Canonical bundle preset naming (_local/<id>/... and _subscribed/<id>/...) - Bundle presets are read-only; grouped under subheaders in combo boxes - PresetBundleDialog with auto-sync toggle, refresh, update notifications - Hyperlinked bundle names to cloud bundle pages Co-authored-by: Sabriel Koh <sabrielkcr@gmail.com> Co-authored-by: Derrick <derrick992110@gmail.com> Co-authored-by: Mykola Nahirnyi <mnahirnyi@amcbridge.com> Co-authored-by: Ian Chua <iancrb00@gmail.com> Co-authored-by: Draginraptor <draginraptor@gmail.com> Co-authored-by: ExPikaPaka <112851715+ExPikaPaka@users.noreply.github.com> Co-authored-by: Ian Bassi <ian.bassi@outlook.com> Co-authored-by: Ocraftyone <Ocraftyone@users.noreply.github.com> Co-authored-by: yw4z <ywsyildiz@gmail.com> Co-authored-by: peterm-m <101202951+peterm-m@users.noreply.github.com> * Fixed an issue on Windows it failed to login Orca Cloud with Google account
103 lines
4.1 KiB
C++
103 lines
4.1 KiB
C++
#include <catch2/catch_all.hpp>
|
|
|
|
#include <boost/filesystem.hpp>
|
|
|
|
#include "libslic3r/PresetBundle.hpp"
|
|
|
|
using namespace Slic3r;
|
|
|
|
namespace {
|
|
|
|
namespace fs = boost::filesystem;
|
|
|
|
struct TempPresetDir {
|
|
fs::path path;
|
|
|
|
TempPresetDir()
|
|
{
|
|
path = fs::temp_directory_path() / fs::unique_path("orcaslicer-preset-%%%%-%%%%-%%%%");
|
|
fs::create_directories(path);
|
|
}
|
|
|
|
~TempPresetDir()
|
|
{
|
|
boost::system::error_code ec;
|
|
fs::remove_all(path, ec);
|
|
}
|
|
};
|
|
|
|
void write_print_preset(const DynamicPrintConfig &default_config, const fs::path &file, const std::string &name, const std::string &inherits = {})
|
|
{
|
|
DynamicPrintConfig config(default_config);
|
|
config.option<ConfigOptionString>("print_settings_id", true)->value = name;
|
|
config.option<ConfigOptionString>(BBL_JSON_KEY_INHERITS, true)->value = inherits;
|
|
|
|
fs::create_directories(file.parent_path());
|
|
config.save_to_json(file.string(), name, "User", "1.0.0");
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST_CASE("Preset identity is canonicalized from load path", "[Preset][Identity]")
|
|
{
|
|
TempPresetDir temp_dir;
|
|
PresetBundle bundle;
|
|
PresetsConfigSubstitutions substitutions;
|
|
|
|
write_print_preset(bundle.prints.default_preset().config, temp_dir.path / PRESET_PRINT_NAME / "User.json", "User");
|
|
write_print_preset(bundle.prints.default_preset().config, temp_dir.path / PRESET_LOCAL_DIR / "bundle-1" / PRESET_PRINT_NAME / "LocalBundle.json", "LocalBundle");
|
|
write_print_preset(bundle.prints.default_preset().config, temp_dir.path / PRESET_SUBSCRIBED_DIR / "remote-1" / PRESET_PRINT_NAME / "Subscribed.json", "Subscribed");
|
|
|
|
bundle.prints.load_presets(temp_dir.path.string(), PRESET_PRINT_NAME, substitutions, ForwardCompatibilitySubstitutionRule::Disable);
|
|
bundle.prints.load_presets((temp_dir.path / PRESET_LOCAL_DIR / "bundle-1").string(), PRESET_PRINT_NAME, substitutions, ForwardCompatibilitySubstitutionRule::Disable);
|
|
bundle.prints.load_presets((temp_dir.path / PRESET_SUBSCRIBED_DIR / "remote-1").string(), PRESET_PRINT_NAME, substitutions, ForwardCompatibilitySubstitutionRule::Disable);
|
|
|
|
const Preset *root_user = bundle.prints.find_preset("User");
|
|
REQUIRE(root_user != nullptr);
|
|
CHECK(root_user->name == "User");
|
|
CHECK_FALSE(root_user->is_from_bundle());
|
|
|
|
const Preset *local_bundle = bundle.prints.find_preset("_local/bundle-1/LocalBundle");
|
|
REQUIRE(local_bundle != nullptr);
|
|
CHECK(local_bundle->name == "_local/bundle-1/LocalBundle");
|
|
CHECK(local_bundle->is_from_bundle());
|
|
|
|
const Preset *subscribed = bundle.prints.find_preset("_subscribed/remote-1/Subscribed");
|
|
REQUIRE(subscribed != nullptr);
|
|
CHECK(subscribed->name == "_subscribed/remote-1/Subscribed");
|
|
CHECK(subscribed->is_from_bundle());
|
|
}
|
|
|
|
TEST_CASE("Legacy bundle import without bundle metadata stays in the user preset directory", "[Preset][Identity]")
|
|
{
|
|
TempPresetDir temp_dir;
|
|
PresetBundle bundle;
|
|
|
|
PresetsConfigSubstitutions substitutions;
|
|
std::vector<std::string> result;
|
|
int overwrite = 0;
|
|
std::string file = (temp_dir.path / "legacy-bundle" / "Imported.json").string();
|
|
const fs::path user_root = temp_dir.path / "user";
|
|
|
|
write_print_preset(bundle.prints.default_preset().config, file, "Imported");
|
|
fs::create_directories(user_root);
|
|
bundle.prints.update_user_presets_directory(user_root.string(), PRESET_PRINT_NAME);
|
|
|
|
REQUIRE(bundle.import_json_presets(
|
|
substitutions,
|
|
file,
|
|
[](std::string const &) { return 1; },
|
|
ForwardCompatibilitySubstitutionRule::Disable,
|
|
overwrite,
|
|
result));
|
|
|
|
const Preset *imported = bundle.prints.find_preset("Imported");
|
|
REQUIRE(imported != nullptr);
|
|
CHECK(imported->name == "Imported");
|
|
CHECK(imported->bundle_id.empty());
|
|
CHECK_FALSE(imported->is_from_bundle());
|
|
// Detached user presets (no inherits) are saved in the "base" subfolder of the user preset root.
|
|
CHECK(fs::equivalent(fs::path(imported->file).parent_path().parent_path(), user_root / PRESET_PRINT_NAME));
|
|
}
|
|
|