mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-28 03:11:47 +00:00
Introducing Orca Cloud: https://cloud.orcaslicer.com (#13414)
* 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
This commit is contained in:
@@ -29,6 +29,11 @@
|
||||
#define PRESET_TEMPLATE_DIR "Template"
|
||||
#define PRESET_CUSTOM_VENDOR "Custom"
|
||||
|
||||
// Orca: bundle import directories
|
||||
#define PRESET_LOCAL_DIR "_local"
|
||||
#define PRESET_SUBSCRIBED_DIR "_subscribed"
|
||||
#define PRESET_BUNDLE_METADATA "bundle_metadata.json"
|
||||
|
||||
//BBS: iot preset type strings
|
||||
#define PRESET_IOT_PRINTER_TYPE "printer"
|
||||
#define PRESET_IOT_FILAMENT_TYPE "filament"
|
||||
@@ -228,7 +233,8 @@ public:
|
||||
//BBS: add type for project-embedded
|
||||
bool is_project_embedded = false;
|
||||
ConfigSubstitutions *loading_substitutions{nullptr};
|
||||
bool is_user() const { return ! this->is_default && ! this->is_system && ! this->is_project_embedded; }
|
||||
bool is_user() const { return ! this->is_default && ! this->is_system && ! this->is_project_embedded && ! this->is_from_bundle(); }
|
||||
bool can_overwrite() const { return ! this->is_default && ! this->is_system && ! this->is_from_bundle(); }
|
||||
//bool is_user() const { return ! this->is_default && ! this->is_system; }
|
||||
|
||||
// Name of the preset, usually derived form the file name.
|
||||
@@ -261,6 +267,11 @@ public:
|
||||
// Orca: flag to indicate if this preset is from Orca Filament Library
|
||||
bool m_from_orca_filament_lib = false;
|
||||
|
||||
// Orca: bundle tracking - imported preset bundles. Bundle ID: UUID (OrcaCloud) or name+timestamp (external).
|
||||
// Presence of bundle_id is the source of truth for "came from a bundle".
|
||||
std::string bundle_id;
|
||||
bool is_from_bundle() const { return ! bundle_id.empty(); }
|
||||
|
||||
//BBS
|
||||
Semver version; // version of preset
|
||||
std::string ini_str; // ini string of preset
|
||||
@@ -279,7 +290,7 @@ public:
|
||||
static Preset::Type get_type_from_string(std::string type_str);
|
||||
void load_info(const std::string& file);
|
||||
void save_info(std::string file = "");
|
||||
void remove_files();
|
||||
void remove_files(bool cloud_already_deleted = false);
|
||||
|
||||
//BBS: add logic for only difference save
|
||||
//if parent_config is null, save all keys, otherwise, only save difference
|
||||
@@ -395,6 +406,28 @@ bool is_compatible_with_print (const PresetWithVendorProfile &preset, const Pre
|
||||
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer, const DynamicPrintConfig *extra_config);
|
||||
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer);
|
||||
|
||||
// Where a preset is being loaded from. `Auto` lets load_presets() infer from the directory path.
|
||||
struct PresetOrigin {
|
||||
enum class Kind { Auto, User, LocalBundle, SubscribedBundle };
|
||||
|
||||
Kind kind { Kind::Auto };
|
||||
std::string bundle_id;
|
||||
|
||||
PresetOrigin() = default;
|
||||
PresetOrigin(Kind kind, std::string bundle_id = {}) : kind(kind), bundle_id(std::move(bundle_id)) {}
|
||||
|
||||
bool is_bundle() const { return kind == Kind::LocalBundle || kind == Kind::SubscribedBundle; }
|
||||
};
|
||||
|
||||
// Prepend the bundle folder to `preset_bare_name` based on `origin`. No-op for non-bundle origins.
|
||||
std::string get_preset_canonical_name(const std::string &preset_bare_name, const PresetOrigin &origin);
|
||||
|
||||
// Tail segment of a canonical name — what's written to the bundle's .json filename and JSON "name" field.
|
||||
std::string get_preset_bare_name(const std::string &canonical_name);
|
||||
|
||||
// Resolve an origin from a directory path when the caller passes Kind::Auto.
|
||||
PresetOrigin detect_origin_from_path(const boost::filesystem::path &path, const PresetOrigin &explicit_origin = PresetOrigin());
|
||||
|
||||
enum class PresetSelectCompatibleType {
|
||||
// Never select a compatible preset if the newly selected profile is not compatible.
|
||||
Never,
|
||||
@@ -471,12 +504,12 @@ public:
|
||||
void add_default_preset(const std::vector<std::string> &keys, const Slic3r::StaticPrintConfig &defaults, const std::string &preset_name);
|
||||
|
||||
// Load ini files of the particular type from the provided directory path.
|
||||
void load_presets(const std::string &dir_path, const std::string &subdir, PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule rule);
|
||||
void load_presets(const std::string &dir_path, const std::string &subdir, PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule rule, std::function<void(Preset&)> preset_loaded_fn = nullptr, const PresetOrigin &load_origin = PresetOrigin());
|
||||
|
||||
//BBS: update user presets directory
|
||||
void update_user_presets_directory(const std::string& dir_path, const std::string& type);
|
||||
void save_user_presets(const std::string& dir_path, const std::string& type, std::vector<std::string>& need_to_delete_list);
|
||||
bool load_user_preset(std::string name, std::map<std::string, std::string> preset_values, PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule rule);
|
||||
void save_user_presets(const std::string& dir_path, const std::string& type, std::map<std::string, std::string>& need_to_delete_list);
|
||||
bool load_user_preset(std::string name, std::map<std::string, std::string> preset_values, PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule rule, const PresetOrigin &load_origin = PresetOrigin(PresetOrigin::Kind::User));
|
||||
void update_after_user_presets_loaded();
|
||||
//BBS: get user presets
|
||||
int get_user_presets(PresetBundle *preset_bundle, std::vector<Preset> &result_presets);
|
||||
@@ -550,7 +583,11 @@ public:
|
||||
bool delete_current_preset();
|
||||
// Delete the current preset, activate the first visible preset.
|
||||
// returns true if the preset was deleted successfully.
|
||||
bool delete_preset(const std::string& name);
|
||||
// When force=true, bypasses the can_overwrite() check (used for bundle preset cleanup).
|
||||
bool delete_preset(const std::string& name, bool force = false);
|
||||
|
||||
// Verify and correct the sync metadata for the preset to ensure proper cloud synchronization.
|
||||
void check_and_fix_syncinfo(Preset& preset, const std::string& user_id);
|
||||
|
||||
// Enable / disable the "- default -" preset.
|
||||
void set_default_suppressed(bool default_suppressed);
|
||||
@@ -637,6 +674,7 @@ public:
|
||||
{
|
||||
return const_cast<PresetCollection*>(this)->find_preset2(name, auto_match);
|
||||
}
|
||||
|
||||
size_t first_visible_idx() const;
|
||||
// Return the index of the first visible, compatible, system base preset
|
||||
// matching the given filament_type. Falls back to base type, then any visible.
|
||||
@@ -774,6 +812,8 @@ protected:
|
||||
void set_custom_preset_alias(Preset &preset);
|
||||
|
||||
private:
|
||||
std::string canonical_preset_name(const std::string &name, const PresetOrigin &load_origin = PresetOrigin()) const;
|
||||
|
||||
// Comparator that sorts "Generic " prefixed presets before others, then alphabetically within each group.
|
||||
static bool filament_preset_less(const Preset &a, const Preset &b) {
|
||||
bool a_generic = boost::starts_with(a.name, GENERIC_PREFIX);
|
||||
@@ -795,6 +835,7 @@ private:
|
||||
// The "-- default -- " preset is always the first, so it needs
|
||||
// to be handled differently.
|
||||
// If a preset does not exist, an iterator is returned indicating where to insert a preset with the same name.
|
||||
// `name` must already be canonical — callers canonicalize via find_preset / canonical_preset_name.
|
||||
std::deque<Preset>::iterator find_preset_internal(const std::string &name, bool from_orca_lib_only = false)
|
||||
{
|
||||
auto it = Slic3r::lower_bound_by_predicate(m_presets.begin() + m_num_default_presets, m_presets.end(),
|
||||
@@ -864,7 +905,7 @@ private:
|
||||
friend class PresetBundle;
|
||||
|
||||
//BBS: mutex
|
||||
std::mutex m_mutex;
|
||||
std::recursive_mutex m_mutex;
|
||||
|
||||
// Orca: used for validation only
|
||||
int m_errors = 0;
|
||||
|
||||
Reference in New Issue
Block a user