2.2.0 dev lxy 1218 (#73)

* Modification: Migrate login interface

* Change 'China' to 'Chinese Mainland'

* Add: wcp_networktestdialog

* Optimization: Main process freezing when connecting devices

* Add: wcp_gettimelapseinstance & wcp_defectdetactionconfig

* Change: network test level

* Optimization: U1 piece-by-piece printing alarm alert

* Optimization: Adjust the display order of brands for the selected models

* Fix: WebpresetDialog now loads presets synchronously to prevent crashes

* Add: wcp_sw_SubscribePageStateChange & wcp_sw_UnsubscribePageStateChange
This commit is contained in:
xiaoyeliu
2025-12-18 20:02:40 +08:00
committed by GitHub
parent e145435f6f
commit ece21860e7
11 changed files with 271 additions and 19 deletions

View File

@@ -7236,6 +7236,24 @@ void GUI_App::device_card_notify(const json& res)
}
}
void GUI_App::page_state_notify_webview(wxWebView* webview, const std::string& state)
{
if (!webview) return;
json notification_data;
notification_data["state"] = state;
for (const auto& instance : m_page_state_subscribers) {
if (instance.first == webview) {
auto ptr = instance.second.lock();
if (ptr) {
ptr->m_res_data = notification_data;
ptr->send_to_js();
}
}
}
}
void GUI_App::cache_notify(const std::string& key, const json& res)
{
for (const auto& instance : m_cache_subscribers) {

View File

@@ -833,6 +833,7 @@ public:
std::unordered_map<void*, std::weak_ptr<SSWCP_Instance>> m_recent_file_subscribers;
std::unordered_map<void*, std::weak_ptr<SSWCP_Instance>> m_user_login_subscribers;
std::unordered_map<void*, std::weak_ptr<SSWCP_Instance>> m_device_card_subscribers;
std::unordered_map<void*, std::weak_ptr<SSWCP_Instance>> m_page_state_subscribers;
struct CachePairCompare
{
@@ -847,6 +848,7 @@ public:
void recent_file_notify(const json& res);
void user_login_notify(const json& res);
void device_card_notify(const json& res);
void page_state_notify_webview(wxWebView* webview, const std::string& state);
void cache_notify(const std::string& key, const json& res);

View File

@@ -1058,6 +1058,46 @@ void MainFrame::init_tabpanel() {
}
#endif
// Notify WCP page state change subscribers
static int prev_monitored_tab = -1;
// Send "inactive" to previous tab if leaving a monitored tab
if (prev_monitored_tab == tpHome && sel != tpHome) {
// Leaving homepage
if (m_webview) {
wxWebView* home_webview = m_webview->getWebView();
wxGetApp().page_state_notify_webview(home_webview, "inactive");
}
} else if (prev_monitored_tab == tpMonitor && sel != tpMonitor) {
// Leaving device page (PrinterWebView)
if (m_printer_view) {
wxWebView* printer_webview = m_printer_view->get_browser();
wxGetApp().page_state_notify_webview(printer_webview, "inactive");
}
}
// Send "active" to current tab if entering a monitored tab
if (sel == tpHome) {
// Entering homepage
if (m_webview) {
wxWebView* home_webview = m_webview->getWebView();
wxGetApp().page_state_notify_webview(home_webview, "active");
}
prev_monitored_tab = tpHome;
} else if (sel == tpMonitor) {
// Entering device page (PrinterWebView)
if (m_printer_view) {
wxWebView* printer_webview = m_printer_view->get_browser();
wxGetApp().page_state_notify_webview(printer_webview, "active");
}
prev_monitored_tab = tpMonitor;
} else {
// Update prev_monitored_tab only when leaving a monitored tab
if (prev_monitored_tab != tpHome && prev_monitored_tab != tpMonitor) {
prev_monitored_tab = -1;
}
}
if (panel)
panel->SetFocus();

View File

@@ -773,15 +773,15 @@ void NetworkTestDialog::start_test_telnet(TestJob job, wxString name, wxString s
wxString grade_desc;
wxString grade_icon;
if (connect_time <= 100) {
if (connect_time <= 50) {
grade = 1;
grade_desc = "Excellent";
grade_icon = "[Level 1]";
} else if (connect_time <= 500) {
} else if (connect_time <= 100) {
grade = 2;
grade_desc = "Good";
grade_icon = "[Level 2]";
} else if (connect_time <= 1000) {
} else if (connect_time <= 400) {
grade = 3;
grade_desc = "Fair";
grade_icon = "[Level 3]";

View File

@@ -4930,6 +4930,30 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
}
}
if (!silence) wxGetApp().app_config->update_config_dir(path.parent_path().string());
// BBS: Check for Snapmaker U1 + Print by Object warning after loading 3mf config
if (load_config && is_project_file) {
auto print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
auto printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
auto print_seq_opt = print_config.option<ConfigOptionEnum<PrintSequence>>("print_sequence");
auto printer_model_opt = printer_config.option<ConfigOptionString>("printer_model");
if (print_seq_opt && printer_model_opt &&
print_seq_opt->value == PrintSequence::ByObject &&
!printer_model_opt->value.empty()) {
std::string printer_model = printer_model_opt->value;
bool is_snapmaker_u1 = boost::icontains(printer_model, "Snapmaker") &&
boost::icontains(printer_model, "U1");
if (is_snapmaker_u1) {
if (q->get_notification_manager()) {
std::string warning_text = _u8L("Warning: Printing by object with caution. This function may cause the print head to collide with printed parts during switching.");
q->get_notification_manager()->push_plater_error_notification(warning_text);
}
}
}
}
}
} else {
// BBS: add plate data related logic

View File

@@ -46,6 +46,7 @@ public:
void update_mode();
bool isSnapmakerPage();
void sendMessage(const std::string& msg);
wxWebView* get_browser() const { return m_browser; }
private:
void SendAPIKey();

View File

@@ -4282,6 +4282,66 @@ void SSWCP_MachineManage_Instance::sw_SubscribeLocalDevices()
}
}
// SSWCP_PageStateChange_Instance
void SSWCP_PageStateChange_Instance::process()
{
if (m_event_id != "") {
json header;
send_to_js();
m_header.clear();
m_header["event_id"] = m_event_id;
}
if (m_cmd == "sw_SubscribePageStateChange") {
sw_SubscribePageStateChange();
} else if (m_cmd == "sw_UnsubscribePageStateChange") {
sw_UnsubscribePageStateChange();
} else {
handle_general_fail();
}
}
void SSWCP_PageStateChange_Instance::sw_SubscribePageStateChange()
{
try {
auto self = shared_from_this();
wxGetApp().m_page_state_subscribers[m_webview] = self;
} catch (std::exception& e) {
handle_general_fail();
}
}
void SSWCP_PageStateChange_Instance::sw_UnsubscribePageStateChange()
{
try {
auto& page_state_map = wxGetApp().m_page_state_subscribers;
std::string event_id = m_param_data.count("event_id") ? m_param_data["event_id"].get<std::string>() : "";
for (auto iter = page_state_map.begin(); iter != page_state_map.end();) {
if (iter->first == m_webview) {
auto ptr = iter->second.lock();
if (ptr) {
if (event_id == "" || (event_id != "" && event_id == ptr->m_event_id)) {
iter = page_state_map.erase(iter);
} else {
iter++;
}
} else {
iter = page_state_map.erase(iter);
}
} else {
iter++;
}
}
send_to_js();
finish_job();
} catch (std::exception& e) {
handle_general_fail();
}
}
void SSWCP_MachineManage_Instance::sw_AddDevice()
{
try {
@@ -5608,6 +5668,10 @@ std::unordered_set<std::string> SSWCP::m_machine_manage_cmd_list = {
"sw_GetLocalDevices", "sw_AddDevice", "sw_SubscribeLocalDevices", "sw_RenameDevice", "sw_SwitchModel", "sw_DeleteDevices"
};
std::unordered_set<std::string> SSWCP::m_page_state_cmd_list = {
"sw_SubscribePageStateChange", "sw_UnsubscribePageStateChange"
};
std::unordered_set<std::string> SSWCP::m_mqtt_agent_cmd_list = {
"sw_create_mqtt_client", "sw_mqtt_connect", "sw_mqtt_disconnect", "sw_mqtt_subscribe", "sw_mqtt_unpublish", "sw_mqtt_publish", "sw_mqtt_set_engine"
};
@@ -5628,6 +5692,8 @@ std::shared_ptr<SSWCP_Instance> SSWCP::create_sswcp_instance(std::string cmd, co
instance = std::make_shared<SSWCP_UserLogin_Instance>(cmd, header, data, event_id, webview);
} else if (m_machine_manage_cmd_list.find(cmd) != m_machine_manage_cmd_list.end()) {
instance = std::make_shared<SSWCP_MachineManage_Instance>(cmd, header, data, event_id, webview);
} else if (m_page_state_cmd_list.find(cmd) != m_page_state_cmd_list.end()) {
instance = std::make_shared<SSWCP_PageStateChange_Instance>(cmd, header, data, event_id, webview);
} else if(m_mqtt_agent_cmd_list.find(cmd) != m_mqtt_agent_cmd_list.end()) {
instance = std::make_shared<SSWCP_MqttAgent_Instance>(cmd, header, data, event_id, webview);
}
@@ -5804,6 +5870,15 @@ void SSWCP::on_webview_delete(wxWebView* view)
iter++;
}
}
auto& page_state_map = wxGetApp().m_page_state_subscribers;
for (auto iter = page_state_map.begin(); iter != page_state_map.end();) {
if (iter->first == view) {
iter = page_state_map.erase(iter);
} else {
iter++;
}
}
}
std::string SSWCP::get_display_filename()

View File

@@ -482,6 +482,26 @@ private:
void sw_DeleteDevices();
};
// Instance class for page state change subscription
class SSWCP_PageStateChange_Instance : public SSWCP_Instance
{
public:
SSWCP_PageStateChange_Instance(std::string cmd, const json& header, const json& data,
std::string event_id, wxWebView* webview)
: SSWCP_Instance(cmd, header, data, event_id, webview)
{
m_type = COMMON;
}
~SSWCP_PageStateChange_Instance() {}
void process() override;
private:
void sw_SubscribePageStateChange();
void sw_UnsubscribePageStateChange();
};
// Instance class for Snapmaker user login
class SSWCP_UserLogin_Instance : public SSWCP_Instance
{
@@ -589,6 +609,7 @@ private:
static std::unordered_set<std::string> m_login_cmd_list; // homepage login commands
static std::unordered_set<std::string> m_machine_manage_cmd_list; // homepage machine manage commands;
static std::unordered_set<std::string> m_mqtt_agent_cmd_list; // mqtt-agent commands;
static std::unordered_set<std::string> m_page_state_cmd_list; // page state change commands;
static TimeoutMap<SSWCP_Instance*, std::shared_ptr<SSWCP_Instance>> m_instance_list; // Active instances
static constexpr std::chrono::milliseconds DEFAULT_INSTANCE_TIMEOUT{80000}; // Default timeout (8s)

View File

@@ -49,6 +49,7 @@
#include "Search.hpp"
#include "BedShapeDialog.hpp"
#include "libslic3r/GCode/Thumbnails.hpp"
#include "NotificationManager.hpp"
#include "BedShapeDialog.hpp"
// #include "BonjourDialog.hpp"
@@ -1548,6 +1549,38 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
}
}
// BBS: Add warning notification for Snapmaker U1 + Print by Object
if (opt_key == "print_sequence") {
PrintSequence print_seq = m_config->opt_enum<PrintSequence>("print_sequence");
if (print_seq == PrintSequence::ByObject) {
// Get current printer model
auto printer_model_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionString>("printer_model");
if (printer_model_opt && !printer_model_opt->value.empty()) {
std::string printer_model = printer_model_opt->value;
// Check if this is Snapmaker U1 printer
bool is_snapmaker_u1 = boost::icontains(printer_model, "Snapmaker") &&
boost::icontains(printer_model, "U1");
if (is_snapmaker_u1) {
// Show red warning notification
if (wxGetApp().plater() && wxGetApp().plater()->get_notification_manager()) {
std::string warning_text = _u8L("Warning: Printing by object with caution. This function may cause the print head to collide with printed parts during switching.");
wxGetApp().plater()->get_notification_manager()->push_plater_error_notification(warning_text);
}
}
}
} else {
// Clear warning when switching away from ByObject
if (wxGetApp().plater() && wxGetApp().plater()->get_notification_manager()) {
std::string warning_text = _u8L("Warning: Printing by object with caution. This function may cause the print head to collide with printed parts during switching.");
wxGetApp().plater()->get_notification_manager()->close_plater_error_notification(warning_text);
}
}
}
// BBS set support style to default when support type changes
// Orca: do this only in simple mode
if (opt_key == "support_type" && m_mode == comSimple) {