diff --git a/Tactility/Source/app/selectiondialog/SelectionDialog.cpp b/Tactility/Source/app/selectiondialog/SelectionDialog.cpp index 2d97472e..c8edf4a7 100644 --- a/Tactility/Source/app/selectiondialog/SelectionDialog.cpp +++ b/Tactility/Source/app/selectiondialog/SelectionDialog.cpp @@ -73,7 +73,7 @@ static void onShow(AppContext& app, lv_obj_t* parent) { lv_obj_set_flex_grow(list, 1); auto parameters = app.getParameters(); - tt_check(parameters != nullptr, "No parameters"); + tt_check(parameters != nullptr, "Parameters missing"); std::string items_concatenated; if (parameters->optString(PARAMETER_BUNDLE_KEY_ITEMS, items_concatenated)) { std::vector items = string_split(items_concatenated, PARAMETER_ITEM_CONCATENATION_TOKEN); diff --git a/Tactility/Source/app/textviewer/TextViewer.cpp b/Tactility/Source/app/textviewer/TextViewer.cpp index 5a0636cb..4c8e5801 100644 --- a/Tactility/Source/app/textviewer/TextViewer.cpp +++ b/Tactility/Source/app/textviewer/TextViewer.cpp @@ -23,7 +23,7 @@ static void onShow(AppContext& app, lv_obj_t* parent) { lv_obj_t* label = lv_label_create(wrapper); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); auto parameters = app.getParameters(); - tt_check(parameters != nullptr, "No parameters"); + tt_check(parameters != nullptr, "Parameters missing"); std::string file_argument; if (parameters->optString(TEXT_VIEWER_FILE_ARGUMENT, file_argument)) { TT_LOG_I(TAG, "Opening %s", file_argument.c_str()); diff --git a/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp b/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp index 3ea572aa..142e5c1f 100644 --- a/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp +++ b/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp @@ -13,6 +13,16 @@ namespace tt::app::wifiapsettings { extern const AppManifest manifest; +/** Returns the app data if the app is active. Note that this could clash if the same app is started twice and a background thread is slow. */ +const AppContext* _Nullable optWifiApSettingsApp() { + app::AppContext* app = service::loader::getCurrentApp(); + if (app->getManifest().id == manifest.id) { + return app; + } else { + return nullptr; + } +} + void start(const std::string& ssid) { auto bundle = std::shared_ptr(new Bundle()); bundle->putString("ssid", ssid); @@ -21,11 +31,19 @@ void start(const std::string& ssid) { static void onToggleAutoConnect(lv_event_t* event) { lv_event_code_t code = lv_event_get_code(event); - const Bundle& parameters = *(const Bundle*)lv_event_get_user_data(event); + + auto* app = optWifiApSettingsApp(); + if (app == nullptr) { + return; + } + + auto parameters = app->getParameters(); + tt_check(parameters != nullptr, "Parameters missing"); + if (code == LV_EVENT_VALUE_CHANGED) { auto* enable_switch = static_cast(lv_event_get_target(event)); bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED); - std::string ssid = parameters.getString("ssid"); + std::string ssid = parameters->getString("ssid"); service::wifi::settings::WifiApSettings settings {}; if (service::wifi::settings::load(ssid.c_str(), &settings)) { @@ -41,7 +59,7 @@ static void onToggleAutoConnect(lv_event_t* event) { static void onShow(AppContext& app, lv_obj_t* parent) { auto paremeters = app.getParameters(); - tt_check(paremeters != nullptr, "No parameters"); + tt_check(paremeters != nullptr, "Parameters missing"); std::string ssid = paremeters->getString("ssid"); lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); diff --git a/Tactility/Source/app/wificonnect/View.cpp b/Tactility/Source/app/wificonnect/View.cpp index 91923c0e..3a2a971b 100644 --- a/Tactility/Source/app/wificonnect/View.cpp +++ b/Tactility/Source/app/wificonnect/View.cpp @@ -14,14 +14,16 @@ namespace tt::app::wificonnect { #define TAG "wifi_connect" +std::shared_ptr _Nullable optWifiConnect(); + void View::resetErrors() { lv_obj_add_flag(password_error, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(ssid_error, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(connection_error, LV_OBJ_FLAG_HIDDEN); } -static void onConnect(lv_event_t* event) { - auto* wifi = (WifiConnect*)lv_event_get_user_data(event); +static void onConnect(TT_UNUSED lv_event_t* event) { + auto wifi = optWifiConnect(); auto& view = wifi->getView(); wifi->getState().setConnectionError(false); @@ -78,7 +80,7 @@ void View::setLoading(bool loading) { } } -void View::createBottomButtons(WifiConnect* wifi, lv_obj_t* parent) { +void View::createBottomButtons(lv_obj_t* parent) { lv_obj_t* button_container = lv_obj_create(parent); lv_obj_set_width(button_container, LV_PCT(100)); lv_obj_set_height(button_container, LV_SIZE_CONTENT); @@ -103,11 +105,11 @@ void View::createBottomButtons(WifiConnect* wifi, lv_obj_t* parent) { lv_obj_t* connect_label = lv_label_create(connect_button); lv_label_set_text(connect_label, "Connect"); lv_obj_align(connect_button, LV_ALIGN_RIGHT_MID, 0, 0); - lv_obj_add_event_cb(connect_button, &onConnect, LV_EVENT_CLICKED, wifi); + lv_obj_add_event_cb(connect_button, &onConnect, LV_EVENT_CLICKED, nullptr); } // TODO: Standardize dialogs -void View::init(AppContext& app, WifiConnect* wifiConnect, lv_obj_t* parent) { +void View::init(AppContext& app, lv_obj_t* parent) { lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); lvgl::toolbar_create(parent, app); @@ -180,7 +182,7 @@ void View::init(AppContext& app, WifiConnect* wifiConnect, lv_obj_t* parent) { lv_obj_add_flag(connection_error, LV_OBJ_FLAG_HIDDEN); // Bottom buttons - createBottomButtons(wifiConnect, wrapper); + createBottomButtons(wrapper); // Keyboard bindings service::gui::keyboardAddTextArea(ssid_textarea); @@ -201,10 +203,7 @@ void View::init(AppContext& app, WifiConnect* wifiConnect, lv_obj_t* parent) { } } -void View::update( - TT_UNUSED Bindings* bindings, - State* state -) { +void View::update() { if (state->hasConnectionError()) { setLoading(false); resetErrors(); diff --git a/Tactility/Source/app/wificonnect/View.h b/Tactility/Source/app/wificonnect/View.h index e723c55b..61774272 100644 --- a/Tactility/Source/app/wificonnect/View.h +++ b/Tactility/Source/app/wificonnect/View.h @@ -12,6 +12,11 @@ class WifiConnect; class View { +private: + + Bindings* bindings; + State* state; + public: lv_obj_t* ssid_textarea = nullptr; @@ -19,16 +24,20 @@ public: lv_obj_t* password_textarea = nullptr; lv_obj_t* password_error = nullptr; lv_obj_t* connect_button = nullptr; - lv_obj_t* cancel_button = nullptr; lv_obj_t* remember_switch = nullptr; lv_obj_t* connecting_spinner = nullptr; lv_obj_t* connection_error = nullptr; lv_group_t* group = nullptr; - void init(AppContext& app, WifiConnect* wifiConnect, lv_obj_t* parent); - void update(Bindings* bindings, State* state); + View(Bindings* bindings, State* state) : + bindings(bindings), + state(state) + {} - void createBottomButtons(WifiConnect* wifi, lv_obj_t* parent); + void init(AppContext& app, lv_obj_t* parent); + void update(); + + void createBottomButtons(lv_obj_t* parent); void setLoading(bool loading); void resetErrors(); }; diff --git a/Tactility/Source/app/wificonnect/WifiConnect.cpp b/Tactility/Source/app/wificonnect/WifiConnect.cpp index 88775f71..03ea1424 100644 --- a/Tactility/Source/app/wificonnect/WifiConnect.cpp +++ b/Tactility/Source/app/wificonnect/WifiConnect.cpp @@ -79,7 +79,7 @@ void WifiConnect::requestViewUpdate() { lock(); if (view_enabled) { if (lvgl::lock(1000)) { - view.update(&bindings, &state); + view.update(); lvgl::unlock(); } else { TT_LOG_E(TAG, "Failed to lock lvgl"); @@ -91,12 +91,12 @@ void WifiConnect::requestViewUpdate() { void WifiConnect::onShow(AppContext& app, lv_obj_t* parent) { lock(); view_enabled = true; - view.init(app, this, parent); - view.update(&bindings, &state); + view.init(app, parent); + view.update(); unlock(); } -void WifiConnect::onHide(AppContext& app) { +void WifiConnect::onHide(TT_UNUSED AppContext& app) { // No need to lock view, as this is called from within Gui's LVGL context lock(); view_enabled = false; diff --git a/Tactility/Source/app/wificonnect/WifiConnect.h b/Tactility/Source/app/wificonnect/WifiConnect.h index fbd10f52..c169d6d6 100644 --- a/Tactility/Source/app/wificonnect/WifiConnect.h +++ b/Tactility/Source/app/wificonnect/WifiConnect.h @@ -10,15 +10,15 @@ namespace tt::app::wificonnect { class WifiConnect { - PubSubSubscription* wifiSubscription; Mutex mutex; State state; - View view; - bool view_enabled = false; Bindings bindings = { .onConnectSsid = nullptr, .onConnectSsidContext = nullptr }; + View view = View(&bindings, &state); + PubSubSubscription* wifiSubscription; + bool view_enabled = false; public: diff --git a/Tactility/Source/app/wifimanage/View.cpp b/Tactility/Source/app/wifimanage/View.cpp index e57ba307..ad8eb983 100644 --- a/Tactility/Source/app/wifimanage/View.cpp +++ b/Tactility/Source/app/wifimanage/View.cpp @@ -1,7 +1,7 @@ #include "View.h" +#include "WifiManage.h" #include "Log.h" -#include "State.h" #include "service/statusbar/Statusbar.h" #include "service/wifi/Wifi.h" #include "lvgl/Style.h" @@ -14,13 +14,18 @@ namespace tt::app::wifimanage { #define TAG "wifi_main_view" +std::shared_ptr _Nullable optWifiManage(); + static void on_enable_switch_changed(lv_event_t* event) { lv_event_code_t code = lv_event_get_code(event); auto* enable_switch = static_cast(lv_event_get_target(event)); if (code == LV_EVENT_VALUE_CHANGED) { bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED); - auto* bindings = static_cast(lv_event_get_user_data(event)); - bindings->onWifiToggled(is_on); + + auto wifi = optWifiManage(); + auto bindings = wifi->getBindings(); + + bindings.onWifiToggled(is_on); } } @@ -33,11 +38,6 @@ static void on_enable_on_boot_switch_changed(lv_event_t* event) { } } -static void on_disconnect_pressed(lv_event_t* event) { - auto* bindings = static_cast(lv_event_get_user_data(event)); - bindings->onDisconnect(); -} - // region Secondary updates static void connect(lv_event_t* event) { @@ -63,7 +63,7 @@ static void showDetails(lv_event_t* event) { bindings->onShowApSettings(ssid); } -void View::createSsidListItem(Bindings* bindings, const service::wifi::WifiApRecord& record, bool isConnecting) { +void View::createSsidListItem(const service::wifi::WifiApRecord& record, bool isConnecting) { lv_obj_t* wrapper = lv_obj_create(networks_list); lv_obj_add_event_cb(wrapper, &connect, LV_EVENT_CLICKED, bindings); lv_obj_set_user_data(wrapper, bindings); @@ -109,7 +109,7 @@ void View::createSsidListItem(Bindings* bindings, const service::wifi::WifiApRec } } -void View::updateNetworkList(State* state, Bindings* bindings) { +void View::updateNetworkList() { lv_obj_clean(networks_list); switch (state->getRadioState()) { @@ -129,7 +129,7 @@ void View::updateNetworkList(State* state, Bindings* bindings) { for (auto &record : ap_records) { if (record.ssid == connection_target) { lv_list_add_text(networks_list, "Connected"); - createSsidListItem(bindings, record, false); + createSsidListItem(record, false); added_connected = true; break; } @@ -148,7 +148,7 @@ void View::updateNetworkList(State* state, Bindings* bindings) { !connection_target.empty(); bool skip = connection_target_match && added_connected; if (!skip) { - createSsidListItem(bindings, record, is_connecting); + createSsidListItem(record, is_connecting); } used_ssids.insert(record.ssid); } @@ -172,7 +172,7 @@ void View::updateNetworkList(State* state, Bindings* bindings) { } } -void View::updateScanning(State* state) { +void View::updateScanning() { if (state->getRadioState() == service::wifi::WIFI_RADIO_ON && state->isScanning()) { lv_obj_clear_flag(scanning_spinner, LV_OBJ_FLAG_HIDDEN); } else { @@ -180,7 +180,7 @@ void View::updateScanning(State* state) { } } -void View::updateWifiToggle(State* state) { +void View::updateWifiToggle() { lv_obj_clear_state(enable_switch, LV_STATE_ANY); switch (state->getRadioState()) { case service::wifi::WIFI_RADIO_ON: @@ -214,7 +214,7 @@ void View::updateEnableOnBootToggle() { // region Main -void View::init(const AppContext& app, Bindings* bindings, lv_obj_t* parent) { +void View::init(const AppContext& app, lv_obj_t* parent) { root = parent; // Toolbar @@ -263,11 +263,11 @@ void View::init(const AppContext& app, Bindings* bindings, lv_obj_t* parent) { lv_obj_align(networks_list, LV_ALIGN_TOP_LEFT, 0, 44); } -void View::update(Bindings* bindings, State* state) { - updateWifiToggle(state); +void View::update() { + updateWifiToggle(); updateEnableOnBootToggle(); - updateScanning(state); - updateNetworkList(state, bindings); + updateScanning(); + updateNetworkList(); } } // namespace diff --git a/Tactility/Source/app/wifimanage/View.h b/Tactility/Source/app/wifimanage/View.h index 2da3ea88..1a52db23 100644 --- a/Tactility/Source/app/wifimanage/View.h +++ b/Tactility/Source/app/wifimanage/View.h @@ -8,24 +8,29 @@ namespace tt::app::wifimanage { class View { + private: + + Bindings* bindings; + State* state; lv_obj_t* root = nullptr; lv_obj_t* enable_switch = nullptr; lv_obj_t* enable_on_boot_switch = nullptr; lv_obj_t* scanning_spinner = nullptr; lv_obj_t* networks_list = nullptr; -public: - View() {} - void init(const AppContext& app, Bindings* bindings, lv_obj_t* parent); - void update(Bindings* bindings, State* state); -private: - - void updateWifiToggle(State* state); + void updateWifiToggle(); void updateEnableOnBootToggle(); - void updateScanning(State* state); - void updateNetworkList(State* state, Bindings* bindings); - void createSsidListItem(Bindings* bindings, const service::wifi::WifiApRecord& record, bool isConnecting); + void updateScanning(); + void updateNetworkList(); + void createSsidListItem(const service::wifi::WifiApRecord& record, bool isConnecting); + +public: + + View(Bindings* bindings, State* state) : bindings(bindings), state(state) {} + + void init(const AppContext& app, lv_obj_t* parent); + void update(); }; diff --git a/Tactility/Source/app/wifimanage/WifiManage.cpp b/Tactility/Source/app/wifimanage/WifiManage.cpp index 2890560b..ad964bb3 100644 --- a/Tactility/Source/app/wifimanage/WifiManage.cpp +++ b/Tactility/Source/app/wifimanage/WifiManage.cpp @@ -14,6 +14,18 @@ namespace tt::app::wifimanage { #define TAG "wifi_manage" +extern const AppManifest manifest; + +/** Returns the app data if the app is active. Note that this could clash if the same app is started twice and a background thread is slow. */ +std::shared_ptr _Nullable optWifiManage() { + app::AppContext* app = service::loader::getCurrentApp(); + if (app->getManifest().id == manifest.id) { + return std::static_pointer_cast(app->getData()); + } else { + return nullptr; + } +} + static void onConnect(const char* ssid) { service::wifi::settings::WifiApSettings settings; if (service::wifi::settings::load(ssid, &settings)) { @@ -61,7 +73,7 @@ void WifiManage::requestViewUpdate() { lock(); if (isViewEnabled) { if (lvgl::lock(1000)) { - view.update(&bindings, &state); + view.update(); lvgl::unlock(); } else { TT_LOG_E(TAG, "failed to lock lvgl"); @@ -108,8 +120,8 @@ void WifiManage::onShow(AppContext& app, lv_obj_t* parent) { lock(); isViewEnabled = true; state.setConnectSsid("Connected"); // TODO update with proper SSID - view.init(app, &bindings, parent); - view.update(&bindings, &state); + view.init(app, parent); + view.update(); unlock(); service::wifi::WifiRadioState radio_state = service::wifi::getRadioState(); diff --git a/Tactility/Source/app/wifimanage/WifiManage.h b/Tactility/Source/app/wifimanage/WifiManage.h index ff2b8f47..51183834 100644 --- a/Tactility/Source/app/wifimanage/WifiManage.h +++ b/Tactility/Source/app/wifimanage/WifiManage.h @@ -11,9 +11,9 @@ class WifiManage { PubSubSubscription* wifiSubscription = nullptr; Mutex mutex; - tt::app::wifimanage::State state; - tt::app::wifimanage::View view; Bindings bindings = { }; + State state; + View view = View(&bindings, &state); bool isViewEnabled = false; public: @@ -26,6 +26,7 @@ public: void onShow(AppContext& app, lv_obj_t* parent); void onHide(AppContext& app); + Bindings& getBindings() { return bindings; } State& getState() { return state; } void requestViewUpdate();