mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-02 06:47: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
189 lines
6.6 KiB
C++
189 lines
6.6 KiB
C++
#include "NetworkAgentFactory.hpp"
|
|
#include "IPrinterAgent.hpp"
|
|
#include "ICloudServiceAgent.hpp"
|
|
#include "BBLPrinterAgent.hpp"
|
|
#include "OrcaPrinterAgent.hpp"
|
|
#include "QidiPrinterAgent.hpp"
|
|
#include "SnapmakerPrinterAgent.hpp"
|
|
#include "MoonrakerPrinterAgent.hpp"
|
|
#include <boost/log/trivial.hpp>
|
|
#include <map>
|
|
#include <mutex>
|
|
|
|
namespace Slic3r {
|
|
namespace {
|
|
|
|
static std::mutex s_registry_mutex;
|
|
|
|
std::map<std::string, PrinterAgentInfo>& get_printer_agents()
|
|
{
|
|
static std::map<std::string, PrinterAgentInfo> agents;
|
|
return agents;
|
|
}
|
|
|
|
std::map<std::string, std::shared_ptr<IPrinterAgent>>& get_printer_agent_cache()
|
|
{
|
|
static std::map<std::string, std::shared_ptr<IPrinterAgent>> cache;
|
|
return cache;
|
|
}
|
|
|
|
// Helper to register a printer agent type with the standard factory pattern.
|
|
// AgentTypes that take a log_dir constructor arg use the default; BBLPrinterAgent
|
|
// (no log_dir) is registered separately.
|
|
template<typename T>
|
|
void register_agent()
|
|
{
|
|
auto info = T::get_agent_info_static();
|
|
NetworkAgentFactory::register_printer_agent(
|
|
info.id, info.name,
|
|
[](std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
|
const std::string& log_dir) -> std::shared_ptr<IPrinterAgent> {
|
|
auto agent = std::make_shared<T>(log_dir);
|
|
if (cloud_agent)
|
|
agent->set_cloud_agent(cloud_agent);
|
|
return agent;
|
|
});
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
bool NetworkAgentFactory::register_printer_agent(const std::string& id, const std::string& display_name, PrinterAgentFactory factory)
|
|
{
|
|
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
|
auto& agents = get_printer_agents();
|
|
return agents.emplace(id, PrinterAgentInfo(id, display_name, std::move(factory))).second;
|
|
}
|
|
|
|
bool NetworkAgentFactory::is_printer_agent_registered(const std::string& id)
|
|
{
|
|
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
|
auto& agents = get_printer_agents();
|
|
return agents.find(id) != agents.end();
|
|
}
|
|
|
|
const PrinterAgentInfo* NetworkAgentFactory::get_printer_agent_info(const std::string& id)
|
|
{
|
|
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
|
auto& agents = get_printer_agents();
|
|
auto it = agents.find(id);
|
|
return (it != agents.end()) ? &it->second : nullptr;
|
|
}
|
|
|
|
std::vector<PrinterAgentInfo> NetworkAgentFactory::get_registered_printer_agents()
|
|
{
|
|
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
|
auto& agents = get_printer_agents();
|
|
std::vector<PrinterAgentInfo> result;
|
|
result.reserve(agents.size());
|
|
|
|
for (const auto& pair : agents) {
|
|
result.push_back(pair.second);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
std::shared_ptr<IPrinterAgent> NetworkAgentFactory::create_printer_agent_by_id(const std::string& id,
|
|
std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
|
const std::string& log_dir)
|
|
{
|
|
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
|
|
|
// Check cache first
|
|
auto& cache = get_printer_agent_cache();
|
|
auto cache_it = cache.find(id);
|
|
if (cache_it != cache.end()) {
|
|
BOOST_LOG_TRIVIAL(info) << "Reusing cached printer agent: " << id;
|
|
if (cloud_agent)
|
|
cache_it->second->set_cloud_agent(cloud_agent);
|
|
return cache_it->second;
|
|
}
|
|
|
|
// Not cached — create via factory
|
|
auto& agents = get_printer_agents();
|
|
auto it = agents.find(id);
|
|
|
|
if (it == agents.end()) {
|
|
BOOST_LOG_TRIVIAL(warning) << "Unknown printer agent ID: " << id;
|
|
return nullptr;
|
|
}
|
|
|
|
auto agent = it->second.factory(cloud_agent, log_dir);
|
|
if (agent) {
|
|
BOOST_LOG_TRIVIAL(info) << "Created and cached printer agent: " << id;
|
|
cache[id] = agent;
|
|
}
|
|
return agent;
|
|
}
|
|
|
|
void NetworkAgentFactory::clear_printer_agent_cache()
|
|
{
|
|
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
|
auto& cache = get_printer_agent_cache();
|
|
for (auto& pair : cache) {
|
|
if (pair.second)
|
|
pair.second->disconnect_printer();
|
|
}
|
|
cache.clear();
|
|
BOOST_LOG_TRIVIAL(info) << "Printer agent cache cleared";
|
|
}
|
|
|
|
void NetworkAgentFactory::register_all_agents()
|
|
{
|
|
register_agent<OrcaPrinterAgent>();
|
|
register_agent<QidiPrinterAgent>();
|
|
register_agent<SnapmakerPrinterAgent>();
|
|
register_agent<MoonrakerPrinterAgent>();
|
|
|
|
// BBLPrinterAgent takes no constructor args, so register manually
|
|
{
|
|
auto info = BBLPrinterAgent::get_agent_info_static();
|
|
register_printer_agent(info.id, info.name,
|
|
[](std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
|
const std::string& /*log_dir*/) -> std::shared_ptr<IPrinterAgent> {
|
|
auto agent = std::make_shared<BBLPrinterAgent>();
|
|
if (cloud_agent)
|
|
agent->set_cloud_agent(cloud_agent);
|
|
return agent;
|
|
});
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<NetworkAgent> create_agent_from_config(const std::string& log_dir, AppConfig* app_config)
|
|
{
|
|
if (!app_config)
|
|
return std::make_unique<NetworkAgent>(nullptr, nullptr);
|
|
|
|
// Always create Orca cloud agent as the primary provider
|
|
auto cloud_agent = NetworkAgentFactory::create_cloud_agent(ORCA_CLOUD_PROVIDER, log_dir);
|
|
if (!cloud_agent) {
|
|
BOOST_LOG_TRIVIAL(error) << "Failed to create cloud agent";
|
|
}
|
|
|
|
auto agent = std::make_unique<NetworkAgent>(std::move(cloud_agent), nullptr);
|
|
|
|
if (agent) {
|
|
// create orca cloud agent first
|
|
auto* orca_cloud = dynamic_cast<OrcaCloudServiceAgent*>(agent->get_cloud_agent().get());
|
|
if (orca_cloud) {
|
|
orca_cloud->configure_urls(app_config);
|
|
}
|
|
|
|
// Initialize third-party cloud agents from config
|
|
auto providers = app_config->get_cloud_providers();
|
|
for (const auto& provider : providers) {
|
|
if (provider == ORCA_CLOUD_PROVIDER)
|
|
continue; // Primary agent already created above
|
|
auto third_party_agent = NetworkAgentFactory::create_cloud_agent(provider, log_dir);
|
|
if (third_party_agent) {
|
|
agent->add_cloud_agent(provider, std::move(third_party_agent));
|
|
BOOST_LOG_TRIVIAL(info) << "Initialized third-party cloud agent: " << provider;
|
|
}
|
|
}
|
|
}
|
|
|
|
return agent;
|
|
}
|
|
|
|
} // namespace Slic3r
|