UI/UX improvements for small screen devices (#340)
- Improved UI/UX of various WiFi apps to make it compatible with Cardputer. - Improved UI/UX of Serial Console to make it compatible with Cardputer. - Boot app now shows a smaller logo on Cardputer - CrashDiagnostics app: Use different text if no touch screen is present
This commit is contained in:
parent
faab6d825f
commit
41ad569154
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
Data/system/app/Boot/assets/logo_small.png
Normal file
BIN
Data/system/app/Boot/assets/logo_small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 688 B After Width: | Height: | Size: 688 B |
@ -77,6 +77,14 @@ private:
|
|||||||
view->onConnect();
|
view->onConnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static lv_obj_t* createRowWrapper(lv_obj_t* parent) {
|
||||||
|
auto* wrapper = lv_obj_create(parent);
|
||||||
|
lv_obj_set_size(wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
||||||
|
lv_obj_set_style_border_width(wrapper, 0, LV_STATE_DEFAULT);
|
||||||
|
lv_obj_set_style_pad_all(wrapper, 0, LV_STATE_DEFAULT);
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit ConnectView(OnConnectedFunction onConnected) : onConnected(std::move(onConnected)) {}
|
explicit ConnectView(OnConnectedFunction onConnected) : onConnected(std::move(onConnected)) {}
|
||||||
@ -85,46 +93,55 @@ public:
|
|||||||
uartNames = hal::uart::getNames();
|
uartNames = hal::uart::getNames();
|
||||||
|
|
||||||
auto* wrapper = lv_obj_create(parent);
|
auto* wrapper = lv_obj_create(parent);
|
||||||
lv_obj_set_size(wrapper, LV_PCT(100), LV_PCT(100));
|
lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
|
||||||
lv_obj_set_style_pad_ver(wrapper, 0, 0);
|
lv_obj_set_size(wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
||||||
lv_obj_set_style_border_width(wrapper, 0, 0);
|
lv_obj_set_style_border_width(wrapper, 0, LV_STATE_DEFAULT);
|
||||||
lvgl::obj_set_style_bg_invisible(wrapper);
|
lvgl::obj_set_style_bg_invisible(wrapper);
|
||||||
|
|
||||||
busDropdown = lv_dropdown_create(wrapper);
|
// Bus selection
|
||||||
|
|
||||||
|
auto* bus_wrapper = createRowWrapper(wrapper);
|
||||||
|
|
||||||
|
busDropdown = lv_dropdown_create(bus_wrapper);
|
||||||
|
|
||||||
auto bus_options = string::join(uartNames, "\n");
|
auto bus_options = string::join(uartNames, "\n");
|
||||||
lv_dropdown_set_options(busDropdown, bus_options.c_str());
|
lv_dropdown_set_options(busDropdown, bus_options.c_str());
|
||||||
lv_obj_align(busDropdown, LV_ALIGN_TOP_RIGHT, 0, 0);
|
lv_obj_align(busDropdown, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||||
lv_obj_set_width(busDropdown, LV_PCT(50));
|
lv_obj_set_width(busDropdown, LV_PCT(50));
|
||||||
lv_obj_set_style_border_color(busDropdown, lv_color_hex(0xFAFAFA), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_border_width(busDropdown, 1, LV_PART_MAIN);
|
|
||||||
int32_t bus_index = 0;
|
int32_t bus_index = 0;
|
||||||
preferences.optInt32("bus", bus_index);
|
preferences.optInt32("bus", bus_index);
|
||||||
if (bus_index < uartNames.size()) {
|
if (bus_index < uartNames.size()) {
|
||||||
lv_dropdown_set_selected(busDropdown, bus_index);
|
lv_dropdown_set_selected(busDropdown, bus_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* bus_label = lv_label_create(wrapper);
|
auto* bus_label = lv_label_create(bus_wrapper);
|
||||||
lv_obj_align(bus_label, LV_ALIGN_TOP_LEFT, 0, 10);
|
lv_obj_align(bus_label, LV_ALIGN_LEFT_MID, 0, 0);
|
||||||
lv_label_set_text(bus_label, "Bus");
|
lv_label_set_text(bus_label, "Bus");
|
||||||
|
|
||||||
|
// Baud rate selection
|
||||||
|
auto* baud_wrapper = createRowWrapper(wrapper);
|
||||||
|
|
||||||
int32_t speed = 115200;
|
int32_t speed = 115200;
|
||||||
preferences.optInt32("speed", speed);
|
preferences.optInt32("speed", speed);
|
||||||
speedTextarea = lv_textarea_create(wrapper);
|
speedTextarea = lv_textarea_create(baud_wrapper);
|
||||||
lv_textarea_set_text(speedTextarea, std::to_string(speed).c_str());
|
lv_textarea_set_text(speedTextarea, std::to_string(speed).c_str());
|
||||||
lv_textarea_set_one_line(speedTextarea, true);
|
lv_textarea_set_one_line(speedTextarea, true);
|
||||||
lv_obj_set_width(speedTextarea, LV_PCT(50));
|
lv_obj_set_width(speedTextarea, LV_PCT(50));
|
||||||
lv_obj_align(speedTextarea, LV_ALIGN_TOP_RIGHT, 0, 40);
|
lv_obj_align(speedTextarea, LV_ALIGN_TOP_RIGHT, 0, 0);
|
||||||
|
|
||||||
auto* baud_rate_label = lv_label_create(wrapper);
|
auto* baud_rate_label = lv_label_create(baud_wrapper);
|
||||||
lv_obj_align(baud_rate_label, LV_ALIGN_TOP_LEFT, 0, 50);
|
lv_obj_align(baud_rate_label, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||||
lv_label_set_text(baud_rate_label, "Baud");
|
lv_label_set_text(baud_rate_label, "Baud");
|
||||||
|
|
||||||
auto* connect_button = lv_button_create(wrapper);
|
// Connect
|
||||||
|
auto* connect_wrapper = createRowWrapper(wrapper);
|
||||||
|
|
||||||
|
auto* connect_button = lv_button_create(connect_wrapper);
|
||||||
|
lv_obj_align(connect_button, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_add_event_cb(connect_button, onConnectCallback, LV_EVENT_SHORT_CLICKED, this);
|
||||||
auto* connect_label = lv_label_create(connect_button);
|
auto* connect_label = lv_label_create(connect_button);
|
||||||
lv_label_set_text(connect_label, "Connect");
|
lv_label_set_text(connect_label, "Connect");
|
||||||
lv_obj_align(connect_button, LV_ALIGN_TOP_MID, 0, 90);
|
|
||||||
lv_obj_add_event_cb(connect_button, onConnectCallback, LV_EVENT_SHORT_CLICKED, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onStop() override {
|
void onStop() override {
|
||||||
|
|||||||
@ -20,7 +20,7 @@ class WifiConnect final : public App {
|
|||||||
};
|
};
|
||||||
View view = View(&bindings, &state);
|
View view = View(&bindings, &state);
|
||||||
PubSub<service::wifi::WifiEvent>::SubscriptionHandle wifiSubscription;
|
PubSub<service::wifi::WifiEvent>::SubscriptionHandle wifiSubscription;
|
||||||
bool view_enabled = false;
|
bool viewEnabled = false;
|
||||||
|
|
||||||
void onWifiEvent(service::wifi::WifiEvent event);
|
void onWifiEvent(service::wifi::WifiEvent event);
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace tt::app::wifimanage {
|
namespace tt::app::wifimanage {
|
||||||
|
|
||||||
typedef void (*OnWifiToggled)(bool enable);
|
typedef void (*OnWifiToggled)(bool enable);
|
||||||
typedef void (*OnConnectSsid)(const char* ssid);
|
typedef void (*OnConnectSsid)(const std::string& ssid);
|
||||||
typedef void (*OnDisconnect)();
|
typedef void (*OnDisconnect)();
|
||||||
typedef void (*OnShowApSettings)(const char* ssid);
|
typedef void (*OnShowApSettings)(const std::string& ssid);
|
||||||
typedef void (*OnConnectToHidden)();
|
typedef void (*OnConnectToHidden)();
|
||||||
|
|
||||||
struct Bindings{
|
struct Bindings{
|
||||||
|
|||||||
@ -37,6 +37,12 @@ public:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<service::wifi::ApRecord> getApRecords() const {
|
||||||
|
auto lock = mutex.asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
return apRecords;
|
||||||
|
}
|
||||||
|
|
||||||
void setConnectSsid(const std::string& ssid);
|
void setConnectSsid(const std::string& ssid);
|
||||||
std::string getConnectSsid() const;
|
std::string getConnectSsid() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -26,7 +26,10 @@ class View final {
|
|||||||
void updateScanning();
|
void updateScanning();
|
||||||
void updateNetworkList();
|
void updateNetworkList();
|
||||||
void updateConnectToHidden();
|
void updateConnectToHidden();
|
||||||
void createSsidListItem(const service::wifi::ApRecord& record, bool isConnecting);
|
void createSsidListItem(const service::wifi::ApRecord& record, bool isConnecting, size_t index);
|
||||||
|
|
||||||
|
static void showDetails(lv_event_t* event);
|
||||||
|
static void connect(lv_event_t* event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@ -130,6 +130,13 @@ class BootApp : public App {
|
|||||||
service::loader::startApp(boot_properties.launcherAppId);
|
service::loader::startApp(boot_properties.launcherAppId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int getSmallestDimension() {
|
||||||
|
auto* display = lv_display_get_default();
|
||||||
|
int width = lv_display_get_horizontal_resolution(display);
|
||||||
|
int height = lv_display_get_vertical_resolution(display);
|
||||||
|
return std::min(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void onCreate(AppContext& app) override {
|
void onCreate(AppContext& app) override {
|
||||||
@ -153,7 +160,13 @@ public:
|
|||||||
lv_obj_align(image, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(image, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
|
||||||
const auto paths = app.getPaths();
|
const auto paths = app.getPaths();
|
||||||
const char* logo = hal::usb::isUsbBootMode() ? "logo_usb.png" : "logo.png";
|
const char* logo;
|
||||||
|
// TODO: Replace with automatic asset buckets like on Android
|
||||||
|
if (getSmallestDimension() < 150) { // e.g. Cardputer
|
||||||
|
logo = hal::usb::isUsbBootMode() ? "assets/logo_usb.png" : "assets/logo_small.png";
|
||||||
|
} else {
|
||||||
|
logo = hal::usb::isUsbBootMode() ? "assets/logo_usb.png" : "assets/logo.png";
|
||||||
|
}
|
||||||
const auto logo_path = paths->getSystemPathLvgl(logo);
|
const auto logo_path = paths->getSystemPathLvgl(logo);
|
||||||
TT_LOG_I(TAG, "%s", logo_path.c_str());
|
TT_LOG_I(TAG, "%s", logo_path.c_str());
|
||||||
lv_image_set_src(image, logo_path.c_str());
|
lv_image_set_src(image, logo_path.c_str());
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
|
#include "Tactility/hal/Device.h"
|
||||||
|
|
||||||
#include <Tactility/app/crashdiagnostics/QrHelpers.h>
|
#include <Tactility/app/crashdiagnostics/QrHelpers.h>
|
||||||
#include <Tactility/app/crashdiagnostics/QrUrl.h>
|
#include <Tactility/app/crashdiagnostics/QrUrl.h>
|
||||||
#include <Tactility/app/launcher/Launcher.h>
|
#include <Tactility/app/launcher/Launcher.h>
|
||||||
@ -32,7 +34,11 @@ public:
|
|||||||
lv_obj_align(top_label, LV_ALIGN_TOP_MID, 0, 2);
|
lv_obj_align(top_label, LV_ALIGN_TOP_MID, 0, 2);
|
||||||
|
|
||||||
auto* bottom_label = lv_label_create(parent);
|
auto* bottom_label = lv_label_create(parent);
|
||||||
|
if (hal::hasDevice(hal::Device::Type::Touch)) {
|
||||||
lv_label_set_text(bottom_label, "Tap screen to continue");
|
lv_label_set_text(bottom_label, "Tap screen to continue");
|
||||||
|
} else {
|
||||||
|
lv_label_set_text(bottom_label, "Reboot device to continue");
|
||||||
|
}
|
||||||
lv_obj_align(bottom_label, LV_ALIGN_BOTTOM_MID, 0, -2);
|
lv_obj_align(bottom_label, LV_ALIGN_BOTTOM_MID, 0, -2);
|
||||||
|
|
||||||
std::string url = getUrlFromCrashData();
|
std::string url = getUrlFromCrashData();
|
||||||
|
|||||||
@ -93,8 +93,6 @@ public:
|
|||||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||||
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
|
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
|
||||||
|
|
||||||
// Toolbar
|
|
||||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
|
||||||
lv_obj_t* toolbar = lvgl::toolbar_create(parent, app);
|
lv_obj_t* toolbar = lvgl::toolbar_create(parent, app);
|
||||||
|
|
||||||
enableSwitch = lvgl::toolbar_add_switch_action(toolbar);
|
enableSwitch = lvgl::toolbar_add_switch_action(toolbar);
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
#include "Tactility/lvgl/LvglSync.h"
|
||||||
|
|
||||||
#include <Tactility/service/wifi/WifiApSettings.h>
|
#include <Tactility/service/wifi/WifiApSettings.h>
|
||||||
#include <Tactility/service/wifi/Wifi.h>
|
#include <Tactility/service/wifi/Wifi.h>
|
||||||
#include <Tactility/app/App.h>
|
#include <Tactility/app/App.h>
|
||||||
@ -22,28 +24,30 @@ void start(const std::string& ssid) {
|
|||||||
app::start(manifest.id, bundle);
|
app::start(manifest.id, bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onPressForget(TT_UNUSED lv_event_t* event) {
|
class WifiApSettings : public App {
|
||||||
|
|
||||||
|
bool viewEnabled = false;
|
||||||
|
lv_obj_t* busySpinner = nullptr;
|
||||||
|
lv_obj_t* connectButton = nullptr;
|
||||||
|
lv_obj_t* disconnectButton = nullptr;
|
||||||
|
std::string ssid;
|
||||||
|
PubSub<service::wifi::WifiEvent>::SubscriptionHandle wifiSubscription = nullptr;
|
||||||
|
|
||||||
|
static void onPressForget(TT_UNUSED lv_event_t* event) {
|
||||||
std::vector<std::string> choices = {
|
std::vector<std::string> choices = {
|
||||||
"Yes",
|
"Yes",
|
||||||
"No"
|
"No"
|
||||||
};
|
};
|
||||||
alertdialog::start("Confirmation", "Forget the Wi-Fi access point?", choices);
|
alertdialog::start("Confirmation", "Forget the Wi-Fi access point?", choices);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onToggleAutoConnect(lv_event_t* event) {
|
static void onToggleAutoConnect(lv_event_t* event) {
|
||||||
lv_event_code_t code = lv_event_get_code(event);
|
auto* self = static_cast<WifiApSettings*>(lv_event_get_user_data(event));
|
||||||
|
|
||||||
auto app = getCurrentAppContext();
|
|
||||||
auto parameters = app->getParameters();
|
|
||||||
tt_check(parameters != nullptr, "Parameters missing");
|
|
||||||
|
|
||||||
if (code == LV_EVENT_VALUE_CHANGED) {
|
|
||||||
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
||||||
bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED);
|
bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED);
|
||||||
std::string ssid = parameters->getString("ssid");
|
|
||||||
|
|
||||||
service::wifi::settings::WifiApSettings settings;
|
service::wifi::settings::WifiApSettings settings;
|
||||||
if (service::wifi::settings::load(ssid.c_str(), settings)) {
|
if (service::wifi::settings::load(self->ssid.c_str(), settings)) {
|
||||||
settings.autoConnect = is_on;
|
settings.autoConnect = is_on;
|
||||||
if (!service::wifi::settings::save(settings)) {
|
if (!service::wifi::settings::save(settings)) {
|
||||||
TT_LOG_E(TAG, "Failed to save settings");
|
TT_LOG_E(TAG, "Failed to save settings");
|
||||||
@ -52,52 +56,134 @@ static void onToggleAutoConnect(lv_event_t* event) {
|
|||||||
TT_LOG_E(TAG, "Failed to load settings");
|
TT_LOG_E(TAG, "Failed to load settings");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class WifiApSettings : public App {
|
static void onPressConnect(lv_event_t* event) {
|
||||||
|
auto app = getCurrentAppContext();
|
||||||
|
auto parameters = app->getParameters();
|
||||||
|
tt_check(parameters != nullptr, "Parameters missing");
|
||||||
|
|
||||||
|
std::string ssid = parameters->getString("ssid");
|
||||||
|
service::wifi::settings::WifiApSettings settings;
|
||||||
|
if (service::wifi::settings::load(ssid.c_str(), settings)) {
|
||||||
|
auto* button = lv_event_get_target_obj(event);
|
||||||
|
lv_obj_add_state(button, LV_STATE_DISABLED);
|
||||||
|
service::wifi::connect(settings, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onPressDisconnect(lv_event_t* event) {
|
||||||
|
if (service::wifi::getRadioState() == service::wifi::RadioState::ConnectionActive) {
|
||||||
|
auto* button = lv_event_get_target_obj(event);
|
||||||
|
lv_obj_add_state(button, LV_STATE_DISABLED);
|
||||||
|
service::wifi::disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onWifiEvent(service::wifi::WifiEvent event) const {
|
||||||
|
requestViewUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void requestViewUpdate() const {
|
||||||
|
if (viewEnabled) {
|
||||||
|
if (lvgl::lock(1000)) {
|
||||||
|
updateViews();
|
||||||
|
lvgl::unlock();
|
||||||
|
} else {
|
||||||
|
TT_LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "LVGL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateConnectButton() const {
|
||||||
|
if (service::wifi::getConnectionTarget() == ssid && service::wifi::getRadioState() == service::wifi::RadioState::ConnectionActive) {
|
||||||
|
lv_obj_remove_flag(disconnectButton, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_add_flag(connectButton, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_remove_state(disconnectButton, LV_STATE_DISABLED);
|
||||||
|
} else {
|
||||||
|
lv_obj_add_flag(disconnectButton, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_remove_flag(connectButton, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_remove_state(connectButton, LV_STATE_DISABLED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBusySpinner() const {
|
||||||
|
if (service::wifi::getRadioState() == service::wifi::RadioState::ConnectionPending) {
|
||||||
|
lv_obj_remove_flag(busySpinner, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
} else {
|
||||||
|
lv_obj_add_flag(busySpinner, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateViews() const {
|
||||||
|
updateConnectButton();
|
||||||
|
updateBusySpinner();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void onCreate(AppContext& app) override {
|
||||||
|
const auto parameters = app.getParameters();
|
||||||
|
tt_check(parameters != nullptr, "Parameters missing");
|
||||||
|
ssid = parameters->getString("ssid");
|
||||||
|
}
|
||||||
|
|
||||||
void onShow(AppContext& app, lv_obj_t* parent) override {
|
void onShow(AppContext& app, lv_obj_t* parent) override {
|
||||||
auto paremeters = app.getParameters();
|
wifiSubscription = service::wifi::getPubsub()->subscribe([this](auto event) {
|
||||||
tt_check(paremeters != nullptr, "Parameters missing");
|
requestViewUpdate();
|
||||||
std::string ssid = paremeters->getString("ssid");
|
});
|
||||||
|
|
||||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||||
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
|
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
|
||||||
|
|
||||||
lvgl::toolbar_create(parent, ssid);
|
auto* toolbar = lvgl::toolbar_create(parent, ssid);
|
||||||
|
busySpinner = lvgl::toolbar_add_spinner_action(toolbar);
|
||||||
// Wrappers
|
|
||||||
|
|
||||||
auto* wrapper = lv_obj_create(parent);
|
auto* wrapper = lv_obj_create(parent);
|
||||||
lv_obj_set_width(wrapper, LV_PCT(100));
|
lv_obj_set_width(wrapper, LV_PCT(100));
|
||||||
lv_obj_set_flex_grow(wrapper, 1);
|
lv_obj_set_flex_grow(wrapper, 1);
|
||||||
lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
|
lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lv_obj_set_style_border_width(wrapper, 0, LV_STATE_DEFAULT);
|
||||||
lvgl::obj_set_style_bg_invisible(wrapper);
|
lvgl::obj_set_style_bg_invisible(wrapper);
|
||||||
|
|
||||||
// Auto-connect toggle
|
disconnectButton = lv_button_create(wrapper);
|
||||||
|
lv_obj_set_width(disconnectButton, LV_PCT(100));
|
||||||
|
lv_obj_add_event_cb(disconnectButton, onPressDisconnect, LV_EVENT_SHORT_CLICKED, nullptr);
|
||||||
|
auto* disconnect_label = lv_label_create(disconnectButton);
|
||||||
|
lv_obj_align(disconnect_label, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_label_set_text(disconnect_label, "Disconnect");
|
||||||
|
|
||||||
auto* auto_connect_wrapper = lv_obj_create(wrapper);
|
connectButton = lv_button_create(wrapper);
|
||||||
lv_obj_set_size(auto_connect_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
lv_obj_set_width(connectButton, LV_PCT(100));
|
||||||
lv_obj_set_style_pad_all(auto_connect_wrapper, 0, LV_STATE_DEFAULT);
|
lv_obj_add_event_cb(connectButton, onPressConnect, LV_EVENT_SHORT_CLICKED, nullptr);
|
||||||
lv_obj_set_style_pad_gap(auto_connect_wrapper, 0, LV_STATE_DEFAULT);
|
auto* connect_label = lv_label_create(connectButton);
|
||||||
lv_obj_set_style_border_width(auto_connect_wrapper, 0, LV_STATE_DEFAULT);
|
lv_obj_align(connect_label, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_label_set_text(connect_label, "Connect");
|
||||||
|
|
||||||
auto* auto_connect_label = lv_label_create(auto_connect_wrapper);
|
// Forget
|
||||||
lv_label_set_text(auto_connect_label, "Auto-connect");
|
|
||||||
lv_obj_align(auto_connect_label, LV_ALIGN_TOP_LEFT, 0, 6);
|
|
||||||
|
|
||||||
auto* auto_connect_switch = lv_switch_create(auto_connect_wrapper);
|
|
||||||
lv_obj_add_event_cb(auto_connect_switch, onToggleAutoConnect, LV_EVENT_VALUE_CHANGED, &paremeters);
|
|
||||||
lv_obj_align(auto_connect_switch, LV_ALIGN_TOP_RIGHT, 0, 0);
|
|
||||||
|
|
||||||
auto* forget_button = lv_button_create(wrapper);
|
auto* forget_button = lv_button_create(wrapper);
|
||||||
lv_obj_set_width(forget_button, LV_PCT(100));
|
lv_obj_set_width(forget_button, LV_PCT(100));
|
||||||
lv_obj_align_to(forget_button, auto_connect_wrapper, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
|
|
||||||
lv_obj_add_event_cb(forget_button, onPressForget, LV_EVENT_SHORT_CLICKED, nullptr);
|
lv_obj_add_event_cb(forget_button, onPressForget, LV_EVENT_SHORT_CLICKED, nullptr);
|
||||||
auto* forget_button_label = lv_label_create(forget_button);
|
auto* forget_button_label = lv_label_create(forget_button);
|
||||||
lv_obj_align(forget_button_label, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(forget_button_label, LV_ALIGN_CENTER, 0, 0);
|
||||||
lv_label_set_text(forget_button_label, "Forget");
|
lv_label_set_text(forget_button_label, "Forget");
|
||||||
|
|
||||||
|
// Auto-connect
|
||||||
|
|
||||||
|
auto* auto_connect_wrapper = lv_obj_create(wrapper);
|
||||||
|
lv_obj_set_size(auto_connect_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
||||||
|
lvgl::obj_set_style_bg_invisible(auto_connect_wrapper);
|
||||||
|
lv_obj_set_style_pad_all(auto_connect_wrapper, 0, LV_STATE_DEFAULT);
|
||||||
|
lv_obj_set_style_border_width(auto_connect_wrapper, 0, LV_STATE_DEFAULT);
|
||||||
|
|
||||||
|
auto* auto_connect_label = lv_label_create(auto_connect_wrapper);
|
||||||
|
lv_label_set_text(auto_connect_label, "Auto-connect");
|
||||||
|
lv_obj_align(auto_connect_label, LV_ALIGN_LEFT_MID, 0, 0);
|
||||||
|
|
||||||
|
auto* auto_connect_switch = lv_switch_create(auto_connect_wrapper);
|
||||||
|
lv_obj_add_event_cb(auto_connect_switch, onToggleAutoConnect, LV_EVENT_VALUE_CHANGED, this);
|
||||||
|
lv_obj_align(auto_connect_switch, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||||
|
|
||||||
service::wifi::settings::WifiApSettings settings;
|
service::wifi::settings::WifiApSettings settings;
|
||||||
if (service::wifi::settings::load(ssid.c_str(), settings)) {
|
if (service::wifi::settings::load(ssid.c_str(), settings)) {
|
||||||
if (settings.autoConnect) {
|
if (settings.autoConnect) {
|
||||||
@ -110,19 +196,38 @@ class WifiApSettings : public App {
|
|||||||
lv_obj_add_flag(forget_button, LV_OBJ_FLAG_HIDDEN);
|
lv_obj_add_flag(forget_button, LV_OBJ_FLAG_HIDDEN);
|
||||||
lv_obj_add_flag(auto_connect_wrapper, LV_OBJ_FLAG_HIDDEN);
|
lv_obj_add_flag(auto_connect_wrapper, LV_OBJ_FLAG_HIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewEnabled = true;
|
||||||
|
|
||||||
|
updateViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onHide(AppContext& app) override {
|
||||||
|
service::wifi::getPubsub()->unsubscribe(wifiSubscription);
|
||||||
|
wifiSubscription = nullptr;
|
||||||
|
viewEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onResult(TT_UNUSED AppContext& appContext, TT_UNUSED LaunchId launchId, TT_UNUSED Result result, std::unique_ptr<Bundle> bundle) override {
|
void onResult(TT_UNUSED AppContext& appContext, TT_UNUSED LaunchId launchId, TT_UNUSED Result result, std::unique_ptr<Bundle> bundle) override {
|
||||||
if (result == Result::Ok && bundle != nullptr) {
|
if (result != Result::Ok || bundle == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto index = alertdialog::getResultIndex(*bundle);
|
auto index = alertdialog::getResultIndex(*bundle);
|
||||||
if (index == 0) { // Yes
|
if (index != 0) { // 0 = Yes
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto parameters = appContext.getParameters();
|
auto parameters = appContext.getParameters();
|
||||||
tt_check(parameters != nullptr, "Parameters missing");
|
tt_check(parameters != nullptr, "Parameters missing");
|
||||||
|
|
||||||
std::string ssid = parameters->getString("ssid");
|
std::string ssid = parameters->getString("ssid");
|
||||||
if (service::wifi::settings::remove(ssid.c_str())) {
|
if (!service::wifi::settings::remove(ssid.c_str())) {
|
||||||
TT_LOG_I(TAG, "Removed SSID");
|
TT_LOG_E(TAG, "Failed to remove SSID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TT_LOG_I(TAG, "Removed SSID");
|
||||||
if (
|
if (
|
||||||
service::wifi::getRadioState() == service::wifi::RadioState::ConnectionActive &&
|
service::wifi::getRadioState() == service::wifi::RadioState::ConnectionActive &&
|
||||||
service::wifi::getConnectionTarget() == ssid
|
service::wifi::getConnectionTarget() == ssid
|
||||||
@ -130,13 +235,8 @@ class WifiApSettings : public App {
|
|||||||
service::wifi::disconnect();
|
service::wifi::disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop self
|
// Stop app
|
||||||
app::stop();
|
stop();
|
||||||
} else {
|
|
||||||
TT_LOG_E(TAG, "Failed to remove SSID");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -67,7 +67,7 @@ void WifiConnect::unlock() {
|
|||||||
|
|
||||||
void WifiConnect::requestViewUpdate() {
|
void WifiConnect::requestViewUpdate() {
|
||||||
lock();
|
lock();
|
||||||
if (view_enabled) {
|
if (viewEnabled) {
|
||||||
if (lvgl::lock(1000)) {
|
if (lvgl::lock(1000)) {
|
||||||
view.update();
|
view.update();
|
||||||
lvgl::unlock();
|
lvgl::unlock();
|
||||||
@ -80,7 +80,7 @@ void WifiConnect::requestViewUpdate() {
|
|||||||
|
|
||||||
void WifiConnect::onShow(AppContext& app, lv_obj_t* parent) {
|
void WifiConnect::onShow(AppContext& app, lv_obj_t* parent) {
|
||||||
lock();
|
lock();
|
||||||
view_enabled = true;
|
viewEnabled = true;
|
||||||
view.init(app, parent);
|
view.init(app, parent);
|
||||||
view.update();
|
view.update();
|
||||||
unlock();
|
unlock();
|
||||||
@ -89,7 +89,7 @@ void WifiConnect::onShow(AppContext& app, lv_obj_t* parent) {
|
|||||||
void WifiConnect::onHide(TT_UNUSED AppContext& app) {
|
void WifiConnect::onHide(TT_UNUSED AppContext& app) {
|
||||||
// No need to lock view, as this is called from within Gui's LVGL context
|
// No need to lock view, as this is called from within Gui's LVGL context
|
||||||
lock();
|
lock();
|
||||||
view_enabled = false;
|
viewEnabled = false;
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
#include <Tactility/network/HttpdReq.h>
|
||||||
|
|
||||||
#include <Tactility/app/wifimanage/View.h>
|
#include <Tactility/app/wifimanage/View.h>
|
||||||
|
|
||||||
#include <Tactility/Tactility.h>
|
#include <Tactility/Tactility.h>
|
||||||
@ -5,7 +7,6 @@
|
|||||||
|
|
||||||
#include <Tactility/lvgl/Style.h>
|
#include <Tactility/lvgl/Style.h>
|
||||||
#include <Tactility/lvgl/Toolbar.h>
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
#include <Tactility/lvgl/Spinner.h>
|
|
||||||
|
|
||||||
#include <Tactility/Log.h>
|
#include <Tactility/Log.h>
|
||||||
#include <Tactility/service/wifi/Wifi.h>
|
#include <Tactility/service/wifi/Wifi.h>
|
||||||
@ -21,7 +22,7 @@ constexpr auto* TAG = "WifiManageView";
|
|||||||
|
|
||||||
std::shared_ptr<WifiManage> _Nullable optWifiManage();
|
std::shared_ptr<WifiManage> _Nullable optWifiManage();
|
||||||
|
|
||||||
uint8_t mapRssiToPercentage(int rssi) {
|
static uint8_t mapRssiToPercentage(int rssi) {
|
||||||
auto abs_rssi = std::abs(rssi);
|
auto abs_rssi = std::abs(rssi);
|
||||||
if (abs_rssi < 30U) {
|
if (abs_rssi < 30U) {
|
||||||
abs_rssi = 30U;
|
abs_rssi = 30U;
|
||||||
@ -33,28 +34,31 @@ uint8_t mapRssiToPercentage(int rssi) {
|
|||||||
return (uint8_t)percentage;
|
return (uint8_t)percentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_enable_switch_changed(lv_event_t* event) {
|
static void onEnableSwitchChanged(lv_event_t* event) {
|
||||||
lv_event_code_t code = lv_event_get_code(event);
|
|
||||||
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
||||||
if (code == LV_EVENT_VALUE_CHANGED) {
|
|
||||||
bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED);
|
bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED);
|
||||||
|
|
||||||
auto wifi = std::static_pointer_cast<WifiManage>(getCurrentApp());
|
auto wifi = std::static_pointer_cast<WifiManage>(getCurrentApp());
|
||||||
auto bindings = wifi->getBindings();
|
auto bindings = wifi->getBindings();
|
||||||
|
|
||||||
bindings.onWifiToggled(is_on);
|
bindings.onWifiToggled(is_on);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_enable_on_boot_switch_changed(lv_event_t* event) {
|
static void onEnableOnBootSwitchChanged(lv_event_t* event) {
|
||||||
lv_event_code_t code = lv_event_get_code(event);
|
|
||||||
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
||||||
if (code == LV_EVENT_VALUE_CHANGED) {
|
|
||||||
bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED);
|
bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED);
|
||||||
// Dispatch it, so file IO doesn't block the UI
|
// Dispatch it, so file IO doesn't block the UI
|
||||||
getMainDispatcher().dispatch([is_on] {
|
getMainDispatcher().dispatch([is_on] {
|
||||||
service::wifi::settings::setEnableOnBoot(is_on);
|
service::wifi::settings::setEnableOnBoot(is_on);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onEnableOnBootParentClicked(lv_event_t* event) {
|
||||||
|
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_user_data(event));
|
||||||
|
if (lv_obj_has_state(enable_switch, LV_STATE_CHECKED)) {
|
||||||
|
lv_obj_remove_state(enable_switch, LV_STATE_CHECKED);
|
||||||
|
} else {
|
||||||
|
lv_obj_add_state(enable_switch, LV_STATE_CHECKED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,101 +69,67 @@ static void onConnectToHiddenClicked(lv_event_t* event) {
|
|||||||
|
|
||||||
// region Secondary updates
|
// region Secondary updates
|
||||||
|
|
||||||
static void connect(lv_event_t* event) {
|
void View::connect(lv_event_t* event) {
|
||||||
auto* wrapper = lv_event_get_current_target_obj(event);
|
TT_LOG_D(TAG, "connect()");
|
||||||
// Assumes that the second child of the button is a label ... risky
|
auto* widget = lv_event_get_current_target_obj(event);
|
||||||
auto* label = lv_obj_get_child(wrapper, 0);
|
auto index = reinterpret_cast<size_t>(lv_obj_get_user_data(widget));
|
||||||
// We get the SSID from the button label because it's safer than alloc'ing
|
auto* self = static_cast<View*>(lv_event_get_user_data(event));
|
||||||
// our own and passing it as the event data
|
auto ap_records = self->state->getApRecords();
|
||||||
const char* ssid = lv_label_get_text(label);
|
|
||||||
if (ssid != nullptr) {
|
|
||||||
TT_LOG_I(TAG, "Clicked AP: %s", ssid);
|
|
||||||
auto* bindings = (Bindings*)lv_event_get_user_data(event);
|
|
||||||
|
|
||||||
|
if (index < ap_records.size()) {
|
||||||
|
TT_LOG_I(TAG, "Clicked %d/%d", index, ap_records.size() - 1);
|
||||||
|
auto& ssid = ap_records[index].ssid;
|
||||||
|
TT_LOG_I(TAG, "Clicked AP: %s", ssid.c_str());
|
||||||
std::string connection_target = service::wifi::getConnectionTarget();
|
std::string connection_target = service::wifi::getConnectionTarget();
|
||||||
if (connection_target == ssid) {
|
if (connection_target == ssid) {
|
||||||
bindings->onDisconnect();
|
self->bindings->onDisconnect();
|
||||||
} else {
|
} else {
|
||||||
bindings->onConnectSsid(ssid);
|
self->bindings->onConnectSsid(ssid);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
TT_LOG_W(TAG, "Clicked AP: record %d/%d does not exist", index, ap_records.size() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showDetails(lv_event_t* event) {
|
void View::showDetails(lv_event_t* event) {
|
||||||
auto* wrapper = lv_event_get_current_target_obj(event);
|
TT_LOG_D(TAG, "showDetails()");
|
||||||
// Hack: Get the hidden label with the ssid
|
auto* widget = lv_event_get_current_target_obj(event);
|
||||||
auto* ssid_label = lv_obj_get_child(wrapper, 1);
|
auto index = reinterpret_cast<size_t>(lv_obj_get_user_data(widget));
|
||||||
const char* ssid = lv_label_get_text(ssid_label);
|
auto* self = static_cast<View*>(lv_event_get_user_data(event));
|
||||||
auto* bindings = (Bindings*)lv_event_get_user_data(event);
|
auto ap_records = self->state->getApRecords();
|
||||||
bindings->onShowApSettings(ssid);
|
|
||||||
|
if (index < ap_records.size()) {
|
||||||
|
auto& ssid = ap_records[index].ssid;
|
||||||
|
TT_LOG_I(TAG, "Clicked AP: %s", ssid.c_str());
|
||||||
|
self->bindings->onShowApSettings(ssid);
|
||||||
|
} else {
|
||||||
|
TT_LOG_W(TAG, "Clicked AP: record %d/%d does not exist", index, ap_records.size() - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::createSsidListItem(const service::wifi::ApRecord& record, bool isConnecting) {
|
void View::createSsidListItem(const service::wifi::ApRecord& record, bool isConnecting, size_t index) {
|
||||||
auto ui_scale = hal::getConfiguration()->uiScale;
|
|
||||||
|
|
||||||
auto* wrapper = lv_obj_create(networks_list);
|
|
||||||
lv_obj_add_event_cb(wrapper, &connect, LV_EVENT_SHORT_CLICKED, bindings);
|
|
||||||
lv_obj_set_user_data(wrapper, bindings);
|
|
||||||
lv_obj_set_size(wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_all(wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_pad_gap(wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_margin_all(wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_border_width(wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
|
|
||||||
auto* label = lv_label_create(wrapper);
|
|
||||||
lv_obj_align(label, LV_ALIGN_LEFT_MID, 0, 0);
|
|
||||||
lv_label_set_text(label, record.ssid.c_str());
|
|
||||||
lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
|
||||||
lv_obj_set_width(label, LV_PCT(70));
|
|
||||||
|
|
||||||
auto* info_wrapper = lv_obj_create(wrapper);
|
|
||||||
lv_obj_set_style_margin_all(info_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_align(info_wrapper, LV_ALIGN_RIGHT_MID);
|
|
||||||
|
|
||||||
if (ui_scale == hal::UiScale::Smallest) {
|
|
||||||
lv_obj_set_size(info_wrapper, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_hor(info_wrapper, 4, LV_STATE_DEFAULT);
|
|
||||||
} else {
|
|
||||||
lv_obj_set_size(info_wrapper, 36, 36);
|
|
||||||
lv_obj_set_style_pad_all(info_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_obj_set_style_border_color(info_wrapper, lv_theme_get_color_primary(info_wrapper), 0);
|
|
||||||
lv_obj_add_event_cb(info_wrapper, &showDetails, LV_EVENT_SHORT_CLICKED, bindings);
|
|
||||||
lv_obj_align(info_wrapper, LV_ALIGN_RIGHT_MID, 0, 0);
|
|
||||||
|
|
||||||
auto* info_label = lv_label_create(info_wrapper);
|
|
||||||
lv_label_set_text(info_label, "i");
|
|
||||||
// Hack: Create a hidden label to store data and pass it to the callback
|
|
||||||
auto* ssid_label = lv_label_create(info_wrapper);
|
|
||||||
lv_label_set_text(ssid_label, record.ssid.c_str());
|
|
||||||
lv_obj_add_flag(ssid_label, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
lv_obj_set_style_text_color(info_label, lv_theme_get_color_primary(info_wrapper), LV_STATE_DEFAULT);
|
|
||||||
lv_obj_align(info_label, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
|
|
||||||
if (isConnecting) {
|
if (isConnecting) {
|
||||||
auto* connecting_spinner = lvgl::spinner_create(wrapper);
|
auto* button = lv_list_add_button(networks_list, LV_SYMBOL_WIFI, record.ssid.c_str());
|
||||||
auto spinner_offset_x = (ui_scale == hal::UiScale::Smallest) ? -2 : -8;
|
lv_obj_add_event_cb(button, showDetails, LV_EVENT_SHORT_CLICKED, this);
|
||||||
lv_obj_align_to(connecting_spinner, info_wrapper, LV_ALIGN_OUT_LEFT_MID, spinner_offset_x, 0);
|
|
||||||
} else {
|
} else {
|
||||||
auto percentage = mapRssiToPercentage(record.rssi);
|
const std::string auth_info = (record.auth_mode == WIFI_AUTH_OPEN) ? "(open) " : " ";
|
||||||
|
const auto percentage = mapRssiToPercentage(record.rssi);
|
||||||
std::string auth_info;
|
const auto label = std::format("{} {}{}%", record.ssid, auth_info, percentage);
|
||||||
if (record.auth_mode == WIFI_AUTH_OPEN) {
|
auto* button = lv_list_add_button(networks_list, nullptr, label.c_str());
|
||||||
auth_info = "(open)";
|
lv_obj_set_user_data(button, reinterpret_cast<void*>(index));
|
||||||
|
if (service::wifi::settings::contains(record.ssid)) {
|
||||||
|
lv_obj_add_event_cb(button, showDetails, LV_EVENT_SHORT_CLICKED, this);
|
||||||
} else {
|
} else {
|
||||||
auth_info = "";
|
lv_obj_add_event_cb(button, connect, LV_EVENT_SHORT_CLICKED, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto signal = std::format("{}{}%", auth_info, percentage);
|
|
||||||
auto* signal_label = lv_label_create(wrapper);
|
|
||||||
lv_label_set_text(signal_label, signal.c_str());
|
|
||||||
auto info_label_offset = (ui_scale == hal::UiScale::Smallest) ? -4 : -16;
|
|
||||||
lv_obj_align_to(signal_label, info_wrapper, LV_ALIGN_OUT_LEFT_MID, info_label_offset, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::updateConnectToHidden() {
|
void View::updateConnectToHidden() {
|
||||||
|
if (connect_to_hidden == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
using enum service::wifi::RadioState;
|
using enum service::wifi::RadioState;
|
||||||
switch (state->getRadioState()) {
|
switch (state->getRadioState()) {
|
||||||
case On:
|
case On:
|
||||||
@ -179,6 +149,30 @@ void View::updateConnectToHidden() {
|
|||||||
void View::updateNetworkList() {
|
void View::updateNetworkList() {
|
||||||
lv_obj_clean(networks_list);
|
lv_obj_clean(networks_list);
|
||||||
|
|
||||||
|
// Enable on boot
|
||||||
|
|
||||||
|
auto* enable_on_boot_wrapper = lv_obj_create(networks_list);
|
||||||
|
lv_obj_set_size(enable_on_boot_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
||||||
|
lv_obj_set_style_pad_all(enable_on_boot_wrapper, 0, LV_STATE_DEFAULT);
|
||||||
|
lv_obj_set_style_border_width(enable_on_boot_wrapper, 0, LV_STATE_DEFAULT);
|
||||||
|
|
||||||
|
auto* enable_label = lv_label_create(enable_on_boot_wrapper);
|
||||||
|
lv_label_set_text(enable_label, "Enable on boot");
|
||||||
|
lv_obj_align(enable_label, LV_ALIGN_LEFT_MID, 0, 0);
|
||||||
|
|
||||||
|
enable_on_boot_switch = lv_switch_create(enable_on_boot_wrapper);
|
||||||
|
lv_obj_align(enable_on_boot_switch, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||||
|
lv_obj_add_event_cb(enable_on_boot_switch, onEnableOnBootSwitchChanged, LV_EVENT_VALUE_CHANGED, bindings);
|
||||||
|
lv_obj_add_event_cb(enable_on_boot_wrapper, onEnableOnBootParentClicked, LV_EVENT_SHORT_CLICKED, enable_on_boot_switch);
|
||||||
|
|
||||||
|
if (hal::getConfiguration()->uiScale == hal::UiScale::Smallest) {
|
||||||
|
lv_obj_set_style_pad_ver(enable_on_boot_wrapper, 2, LV_STATE_DEFAULT);
|
||||||
|
} else {
|
||||||
|
lv_obj_set_style_pad_ver(enable_on_boot_wrapper, 8, LV_STATE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateEnableOnBootToggle();
|
||||||
|
|
||||||
switch (state->getRadioState()) {
|
switch (state->getRadioState()) {
|
||||||
using enum service::wifi::RadioState;
|
using enum service::wifi::RadioState;
|
||||||
case OnPending:
|
case OnPending:
|
||||||
@ -188,15 +182,18 @@ void View::updateNetworkList() {
|
|||||||
|
|
||||||
std::string connection_target = service::wifi::getConnectionTarget();
|
std::string connection_target = service::wifi::getConnectionTarget();
|
||||||
|
|
||||||
state->withApRecords([this, &connection_target](const std::vector<service::wifi::ApRecord>& apRecords){
|
// Make safe copy
|
||||||
|
auto ap_records = state->getApRecords();
|
||||||
|
|
||||||
bool is_connected = !connection_target.empty() &&
|
bool is_connected = !connection_target.empty() &&
|
||||||
state->getRadioState() == ConnectionActive;
|
state->getRadioState() == ConnectionActive;
|
||||||
bool added_connected = false;
|
bool added_connected = false;
|
||||||
if (is_connected && !apRecords.empty()) {
|
if (is_connected && !ap_records.empty()) {
|
||||||
for (auto &record : apRecords) {
|
for (int i = 0; i < ap_records.size(); ++i) {
|
||||||
|
auto& record = ap_records[i];
|
||||||
if (record.ssid == connection_target) {
|
if (record.ssid == connection_target) {
|
||||||
lv_list_add_text(networks_list, "Connected");
|
lv_list_add_text(networks_list, "Connected");
|
||||||
createSsidListItem(record, false);
|
createSsidListItem(record, false, i);
|
||||||
added_connected = true;
|
added_connected = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -205,16 +202,17 @@ void View::updateNetworkList() {
|
|||||||
|
|
||||||
lv_list_add_text(networks_list, "Other networks");
|
lv_list_add_text(networks_list, "Other networks");
|
||||||
std::set<std::string> used_ssids;
|
std::set<std::string> used_ssids;
|
||||||
if (!apRecords.empty()) {
|
if (!ap_records.empty()) {
|
||||||
for (auto& record : apRecords) {
|
for (int i = 0; i < ap_records.size(); ++i) {
|
||||||
if (used_ssids.find(record.ssid) == used_ssids.end()) {
|
auto& record = ap_records[i];
|
||||||
|
if (!used_ssids.contains(record.ssid)) {
|
||||||
bool connection_target_match = (record.ssid == connection_target);
|
bool connection_target_match = (record.ssid == connection_target);
|
||||||
bool is_connecting = connection_target_match
|
bool is_connecting = connection_target_match
|
||||||
&& state->getRadioState() == ConnectionPending &&
|
&& state->getRadioState() == ConnectionPending &&
|
||||||
!connection_target.empty();
|
!connection_target.empty();
|
||||||
bool skip = connection_target_match && added_connected;
|
bool skip = connection_target_match && added_connected;
|
||||||
if (!skip) {
|
if (!skip) {
|
||||||
createSsidListItem(record, is_connecting);
|
createSsidListItem(record, is_connecting, i);
|
||||||
}
|
}
|
||||||
used_ssids.insert(record.ssid);
|
used_ssids.insert(record.ssid);
|
||||||
}
|
}
|
||||||
@ -228,21 +226,27 @@ void View::updateNetworkList() {
|
|||||||
lv_obj_t* label = lv_label_create(networks_list);
|
lv_obj_t* label = lv_label_create(networks_list);
|
||||||
lv_label_set_text(label, "No networks found.");
|
lv_label_set_text(label, "No networks found.");
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
|
connect_to_hidden = lv_button_create(networks_list);
|
||||||
|
lv_obj_set_width(connect_to_hidden, LV_PCT(100));
|
||||||
|
lv_obj_set_style_margin_ver(connect_to_hidden, 4, LV_STATE_DEFAULT);
|
||||||
|
auto* connect_to_hidden_label = lv_label_create(connect_to_hidden);
|
||||||
|
lv_label_set_text(connect_to_hidden_label, "Connect to hidden SSID");
|
||||||
|
lv_obj_add_event_cb(connect_to_hidden, onConnectToHiddenClicked, LV_EVENT_SHORT_CLICKED, bindings);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OffPending:
|
|
||||||
case Off: {
|
default:
|
||||||
lv_obj_add_flag(networks_list, LV_OBJ_FLAG_HIDDEN);
|
connect_to_hidden = nullptr;
|
||||||
|
// Nothing to do
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::updateScanning() {
|
void View::updateScanning() {
|
||||||
if (state->getRadioState() == service::wifi::RadioState::On && state->isScanning()) {
|
if (state->getRadioState() == service::wifi::RadioState::On && state->isScanning()) {
|
||||||
lv_obj_clear_flag(scanning_spinner, LV_OBJ_FLAG_HIDDEN);
|
lv_obj_remove_flag(scanning_spinner, LV_OBJ_FLAG_HIDDEN);
|
||||||
} else {
|
} else {
|
||||||
lv_obj_add_flag(scanning_spinner, LV_OBJ_FLAG_HIDDEN);
|
lv_obj_add_flag(scanning_spinner, LV_OBJ_FLAG_HIDDEN);
|
||||||
}
|
}
|
||||||
@ -271,12 +275,14 @@ void View::updateWifiToggle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void View::updateEnableOnBootToggle() {
|
void View::updateEnableOnBootToggle() {
|
||||||
|
if (enable_on_boot_switch != nullptr) {
|
||||||
lv_obj_clear_state(enable_on_boot_switch, LV_STATE_ANY);
|
lv_obj_clear_state(enable_on_boot_switch, LV_STATE_ANY);
|
||||||
if (service::wifi::settings::shouldEnableOnBoot()) {
|
if (service::wifi::settings::shouldEnableOnBoot()) {
|
||||||
lv_obj_add_state(enable_on_boot_switch, LV_STATE_CHECKED);
|
lv_obj_add_state(enable_on_boot_switch, LV_STATE_CHECKED);
|
||||||
} else {
|
} else {
|
||||||
lv_obj_remove_state(enable_on_boot_switch, LV_STATE_CHECKED);
|
lv_obj_remove_state(enable_on_boot_switch, LV_STATE_CHECKED);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion Secondary updates
|
// endregion Secondary updates
|
||||||
@ -284,7 +290,6 @@ void View::updateEnableOnBootToggle() {
|
|||||||
// region Main
|
// region Main
|
||||||
|
|
||||||
void View::init(const AppContext& app, lv_obj_t* parent) {
|
void View::init(const AppContext& app, lv_obj_t* parent) {
|
||||||
auto ui_scale = hal::getConfiguration()->uiScale;
|
|
||||||
|
|
||||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||||
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
|
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
|
||||||
@ -300,64 +305,17 @@ void View::init(const AppContext& app, lv_obj_t* parent) {
|
|||||||
scanning_spinner = lvgl::toolbar_add_spinner_action(toolbar);
|
scanning_spinner = lvgl::toolbar_add_spinner_action(toolbar);
|
||||||
|
|
||||||
enable_switch = lvgl::toolbar_add_switch_action(toolbar);
|
enable_switch = lvgl::toolbar_add_switch_action(toolbar);
|
||||||
lv_obj_add_event_cb(enable_switch, on_enable_switch_changed, LV_EVENT_VALUE_CHANGED, bindings);
|
lv_obj_add_event_cb(enable_switch, onEnableSwitchChanged, LV_EVENT_VALUE_CHANGED, bindings);
|
||||||
|
|
||||||
// Wrappers
|
|
||||||
|
|
||||||
auto* flex_wrapper = lv_obj_create(parent);
|
|
||||||
lv_obj_set_width(flex_wrapper, LV_PCT(100));
|
|
||||||
lv_obj_set_flex_grow(flex_wrapper, 1);
|
|
||||||
lv_obj_set_flex_flow(flex_wrapper, LV_FLEX_FLOW_COLUMN);
|
|
||||||
lv_obj_set_style_border_width(flex_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_pad_all(flex_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_pad_gap(flex_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lvgl::obj_set_style_bg_invisible(flex_wrapper);
|
|
||||||
|
|
||||||
// Fixed size content wrapper: align() methods don't work on flex, so we need this extra wrapper
|
|
||||||
|
|
||||||
auto* content_wrapper = lv_obj_create(flex_wrapper);
|
|
||||||
lv_obj_set_size(content_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lvgl::obj_set_style_bg_invisible(content_wrapper);
|
|
||||||
lv_obj_set_style_border_width(content_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
|
|
||||||
// Enable on boot
|
|
||||||
|
|
||||||
auto* enable_on_boot_wrapper = lv_obj_create(content_wrapper);
|
|
||||||
lv_obj_set_size(enable_on_boot_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_all(enable_on_boot_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_border_width(enable_on_boot_wrapper, 0, LV_STATE_DEFAULT);
|
|
||||||
|
|
||||||
auto* enable_label = lv_label_create(enable_on_boot_wrapper);
|
|
||||||
lv_label_set_text(enable_label, "Enable on boot");
|
|
||||||
lv_obj_align(enable_label, LV_ALIGN_LEFT_MID, 0, 0);
|
|
||||||
|
|
||||||
enable_on_boot_switch = lv_switch_create(enable_on_boot_wrapper);
|
|
||||||
lv_obj_add_event_cb(enable_on_boot_switch, on_enable_on_boot_switch_changed, LV_EVENT_VALUE_CHANGED, bindings);
|
|
||||||
lv_obj_align(enable_on_boot_switch, LV_ALIGN_RIGHT_MID, 0, 0);
|
|
||||||
|
|
||||||
// Networks
|
// Networks
|
||||||
|
|
||||||
networks_list = lv_obj_create(content_wrapper);
|
networks_list = lv_list_create(parent);
|
||||||
lv_obj_set_flex_flow(networks_list, LV_FLEX_FLOW_COLUMN);
|
lv_obj_set_flex_grow(networks_list, 1);
|
||||||
lv_obj_set_width(networks_list, LV_PCT(100));
|
lv_obj_set_width(networks_list, LV_PCT(100));
|
||||||
lv_obj_set_height(networks_list, LV_SIZE_CONTENT);
|
|
||||||
lv_obj_set_style_pad_top(networks_list, 0, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_pad_bottom(networks_list, 0, LV_STATE_DEFAULT);
|
|
||||||
const int network_list_y_offset = ui_scale == hal::UiScale::Smallest ? 22 : 44;
|
|
||||||
lv_obj_align(networks_list, LV_ALIGN_TOP_LEFT, 0, network_list_y_offset);
|
|
||||||
|
|
||||||
connect_to_hidden = lv_button_create(flex_wrapper);
|
|
||||||
lv_obj_set_width(connect_to_hidden, LV_PCT(100));
|
|
||||||
lv_obj_set_style_margin_bottom(connect_to_hidden, 8, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_set_style_margin_hor(connect_to_hidden, 12, LV_STATE_DEFAULT);
|
|
||||||
lv_obj_add_event_cb(connect_to_hidden, onConnectToHiddenClicked, LV_EVENT_SHORT_CLICKED, bindings);
|
|
||||||
auto* connect_to_hidden_label = lv_label_create(connect_to_hidden);
|
|
||||||
lv_label_set_text(connect_to_hidden_label, "Connect to hidden SSID");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::update() {
|
void View::update() {
|
||||||
updateWifiToggle();
|
updateWifiToggle();
|
||||||
updateEnableOnBootToggle();
|
|
||||||
updateScanning();
|
updateScanning();
|
||||||
updateNetworkList();
|
updateNetworkList();
|
||||||
updateConnectToHidden();
|
updateConnectToHidden();
|
||||||
|
|||||||
@ -13,7 +13,7 @@ constexpr auto TAG = "WifiManage";
|
|||||||
|
|
||||||
extern const AppManifest manifest;
|
extern const AppManifest manifest;
|
||||||
|
|
||||||
static void onConnect(const char* ssid) {
|
static void onConnect(const std::string& ssid) {
|
||||||
service::wifi::settings::WifiApSettings settings;
|
service::wifi::settings::WifiApSettings settings;
|
||||||
if (service::wifi::settings::load(ssid, settings)) {
|
if (service::wifi::settings::load(ssid, settings)) {
|
||||||
TT_LOG_I(TAG, "Connecting with known credentials");
|
TT_LOG_I(TAG, "Connecting with known credentials");
|
||||||
@ -24,7 +24,7 @@ static void onConnect(const char* ssid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onShowApSettings(const char* ssid) {
|
static void onShowApSettings(const std::string& ssid) {
|
||||||
wifiapsettings::start(ssid);
|
wifiapsettings::start(ssid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ lv_obj_t* __wrap_lv_button_create(lv_obj_t* parent) {
|
|||||||
|
|
||||||
if (tt::hal::getConfiguration()->uiScale == tt::hal::UiScale::Smallest) {
|
if (tt::hal::getConfiguration()->uiScale == tt::hal::UiScale::Smallest) {
|
||||||
lv_obj_set_style_pad_all(button, 2, LV_STATE_DEFAULT);
|
lv_obj_set_style_pad_all(button, 2, LV_STATE_DEFAULT);
|
||||||
lv_obj_set_style_radius(button, 2, LV_STATE_DEFAULT);
|
lv_obj_set_style_radius(button, 3, LV_STATE_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
|
|||||||
@ -13,7 +13,7 @@ void __wrap_lv_obj_set_flex_flow(lv_obj_t* obj, lv_flex_flow_t flow) {
|
|||||||
__real_lv_obj_set_flex_flow(obj, flow);
|
__real_lv_obj_set_flex_flow(obj, flow);
|
||||||
|
|
||||||
if (tt::hal::getConfiguration()->uiScale == tt::hal::UiScale::Smallest) {
|
if (tt::hal::getConfiguration()->uiScale == tt::hal::UiScale::Smallest) {
|
||||||
lv_obj_set_style_pad_gap(obj, 2, LV_STATE_DEFAULT);
|
lv_obj_set_style_pad_gap(obj, 4, LV_STATE_DEFAULT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user