Add status icons widget
This commit is contained in:
parent
77d3239866
commit
edba1d9ccf
|
@ -406,6 +406,7 @@ list(APPEND SOURCE_FILES
|
|||
displayapp/Colors.cpp
|
||||
displayapp/widgets/Counter.cpp
|
||||
displayapp/widgets/PageIndicator.cpp
|
||||
displayapp/widgets/StatusIcons.cpp
|
||||
|
||||
## Settings
|
||||
displayapp/screens/settings/QuickSettings.cpp
|
||||
|
@ -611,6 +612,7 @@ set(INCLUDE_FILES
|
|||
displayapp/Colors.h
|
||||
displayapp/widgets/Counter.h
|
||||
displayapp/widgets/PageIndicator.h
|
||||
displayapp/widgets/StatusIcons.h
|
||||
drivers/St7789.h
|
||||
drivers/SpiNorFlash.h
|
||||
drivers/SpiMaster.h
|
||||
|
|
|
@ -311,7 +311,8 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
|
|||
|
||||
switch (app) {
|
||||
case Apps::Launcher:
|
||||
currentScreen = std::make_unique<Screens::ApplicationList>(this, settingsController, batteryController, dateTimeController);
|
||||
currentScreen =
|
||||
std::make_unique<Screens::ApplicationList>(this, settingsController, batteryController, bleController, dateTimeController);
|
||||
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::SwipeDown);
|
||||
break;
|
||||
case Apps::None:
|
||||
|
@ -377,7 +378,8 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
|
|||
dateTimeController,
|
||||
brightnessController,
|
||||
motorController,
|
||||
settingsController);
|
||||
settingsController,
|
||||
bleController);
|
||||
ReturnApp(Apps::Clock, FullRefreshDirections::LeftAnim, TouchEvents::SwipeLeft);
|
||||
break;
|
||||
case Apps::Settings:
|
||||
|
|
|
@ -21,10 +21,12 @@ auto ApplicationList::CreateScreenList() const {
|
|||
ApplicationList::ApplicationList(Pinetime::Applications::DisplayApp* app,
|
||||
Pinetime::Controllers::Settings& settingsController,
|
||||
Pinetime::Controllers::Battery& batteryController,
|
||||
Pinetime::Controllers::Ble& bleController,
|
||||
Controllers::DateTime& dateTimeController)
|
||||
: Screen(app),
|
||||
settingsController {settingsController},
|
||||
batteryController {batteryController},
|
||||
bleController {bleController},
|
||||
dateTimeController {dateTimeController},
|
||||
screens {app, settingsController.GetAppMenu(), CreateScreenList(), Screens::ScreenListModes::UpDown} {
|
||||
}
|
||||
|
@ -43,5 +45,12 @@ std::unique_ptr<Screen> ApplicationList::CreateScreen(unsigned int screenNum) co
|
|||
apps[i] = applications[screenNum * appsPerScreen + i];
|
||||
}
|
||||
|
||||
return std::make_unique<Screens::Tile>(screenNum, nScreens, app, settingsController, batteryController, dateTimeController, apps);
|
||||
return std::make_unique<Screens::Tile>(screenNum,
|
||||
nScreens,
|
||||
app,
|
||||
settingsController,
|
||||
batteryController,
|
||||
bleController,
|
||||
dateTimeController,
|
||||
apps);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace Pinetime {
|
|||
explicit ApplicationList(DisplayApp* app,
|
||||
Pinetime::Controllers::Settings& settingsController,
|
||||
Pinetime::Controllers::Battery& batteryController,
|
||||
Pinetime::Controllers::Ble& bleController,
|
||||
Controllers::DateTime& dateTimeController);
|
||||
~ApplicationList() override;
|
||||
bool OnTouchEvent(TouchEvents event) override;
|
||||
|
@ -29,6 +30,7 @@ namespace Pinetime {
|
|||
|
||||
Controllers::Settings& settingsController;
|
||||
Pinetime::Controllers::Battery& batteryController;
|
||||
Pinetime::Controllers::Ble& bleController;
|
||||
Controllers::DateTime& dateTimeController;
|
||||
|
||||
static constexpr int appsPerScreen = 6;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "displayapp/screens/Tile.h"
|
||||
#include "displayapp/DisplayApp.h"
|
||||
#include "displayapp/screens/BatteryIcon.h"
|
||||
#include "components/ble/BleController.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
|
@ -26,22 +27,26 @@ Tile::Tile(uint8_t screenID,
|
|||
uint8_t numScreens,
|
||||
DisplayApp* app,
|
||||
Controllers::Settings& settingsController,
|
||||
Pinetime::Controllers::Battery& batteryController,
|
||||
Controllers::Battery& batteryController,
|
||||
Controllers::Ble& bleController,
|
||||
Controllers::DateTime& dateTimeController,
|
||||
std::array<Applications, 6>& applications)
|
||||
: Screen(app), batteryController {batteryController}, dateTimeController {dateTimeController}, pageIndicator(screenID, numScreens) {
|
||||
: Screen(app),
|
||||
dateTimeController {dateTimeController},
|
||||
pageIndicator(screenID, numScreens),
|
||||
statusIcons(batteryController, bleController) {
|
||||
|
||||
settingsController.SetAppMenu(screenID);
|
||||
|
||||
statusIcons.Create();
|
||||
lv_obj_align(statusIcons.GetObject(), lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -8, 0);
|
||||
statusIcons.Align();
|
||||
|
||||
// Time
|
||||
label_time = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER);
|
||||
lv_obj_align(label_time, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
|
||||
|
||||
// Battery
|
||||
batteryIcon.Create(lv_scr_act());
|
||||
lv_obj_align(batteryIcon.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, -8, 0);
|
||||
|
||||
pageIndicator.Create();
|
||||
|
||||
uint8_t btIndex = 0;
|
||||
|
@ -93,7 +98,7 @@ Tile::~Tile() {
|
|||
|
||||
void Tile::UpdateScreen() {
|
||||
lv_label_set_text(label_time, dateTimeController.FormattedTime().c_str());
|
||||
batteryIcon.SetBatteryPercentage(batteryController.PercentRemaining());
|
||||
statusIcons.Update();
|
||||
}
|
||||
|
||||
void Tile::OnValueChangedEvent(lv_obj_t* obj, uint32_t buttonId) {
|
||||
|
|
|
@ -7,10 +7,9 @@
|
|||
#include "displayapp/Apps.h"
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "components/settings/Settings.h"
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "components/battery/BatteryController.h"
|
||||
#include "displayapp/screens/BatteryIcon.h"
|
||||
#include "displayapp/widgets/PageIndicator.h"
|
||||
#include "displayapp/widgets/StatusIcons.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
|
@ -26,7 +25,8 @@ namespace Pinetime {
|
|||
uint8_t numScreens,
|
||||
DisplayApp* app,
|
||||
Controllers::Settings& settingsController,
|
||||
Pinetime::Controllers::Battery& batteryController,
|
||||
Controllers::Battery& batteryController,
|
||||
Controllers::Ble& bleController,
|
||||
Controllers::DateTime& dateTimeController,
|
||||
std::array<Applications, 6>& applications);
|
||||
|
||||
|
@ -36,7 +36,6 @@ namespace Pinetime {
|
|||
void OnValueChangedEvent(lv_obj_t* obj, uint32_t buttonId);
|
||||
|
||||
private:
|
||||
Pinetime::Controllers::Battery& batteryController;
|
||||
Controllers::DateTime& dateTimeController;
|
||||
|
||||
lv_task_t* taskUpdate;
|
||||
|
@ -45,8 +44,7 @@ namespace Pinetime {
|
|||
lv_obj_t* btnm1;
|
||||
|
||||
Widgets::PageIndicator pageIndicator;
|
||||
|
||||
BatteryIcon batteryIcon;
|
||||
Widgets::StatusIcons statusIcons;
|
||||
|
||||
const char* btnmMap[8];
|
||||
Pinetime::Applications::Apps apps[6];
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
#include <date/date.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <cstdio>
|
||||
#include "displayapp/screens/BatteryIcon.h"
|
||||
#include "displayapp/screens/BleIcon.h"
|
||||
#include "displayapp/screens/NotificationIcon.h"
|
||||
#include "displayapp/screens/Symbols.h"
|
||||
#include "components/battery/BatteryController.h"
|
||||
|
@ -13,6 +11,7 @@
|
|||
#include "components/heartrate/HeartRateController.h"
|
||||
#include "components/motion/MotionController.h"
|
||||
#include "components/settings/Settings.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
|
||||
|
@ -26,25 +25,13 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
|
|||
: Screen(app),
|
||||
currentDateTime {{}},
|
||||
dateTimeController {dateTimeController},
|
||||
batteryController {batteryController},
|
||||
bleController {bleController},
|
||||
notificatioManager {notificatioManager},
|
||||
settingsController {settingsController},
|
||||
heartRateController {heartRateController},
|
||||
motionController {motionController} {
|
||||
motionController {motionController},
|
||||
statusIcons(batteryController, bleController) {
|
||||
|
||||
batteryIcon.Create(lv_scr_act());
|
||||
lv_obj_align(batteryIcon.GetObject(), lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0);
|
||||
|
||||
batteryPlug = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(batteryPlug, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFF0000));
|
||||
lv_label_set_text_static(batteryPlug, Symbols::plug);
|
||||
lv_obj_align(batteryPlug, batteryIcon.GetObject(), LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
|
||||
bleIcon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0082FC));
|
||||
lv_label_set_text_static(bleIcon, Symbols::bluetooth);
|
||||
lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
statusIcons.Create();
|
||||
|
||||
notificationIcon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00));
|
||||
|
@ -94,24 +81,7 @@ WatchFaceDigital::~WatchFaceDigital() {
|
|||
}
|
||||
|
||||
void WatchFaceDigital::Refresh() {
|
||||
powerPresent = batteryController.IsPowerPresent();
|
||||
if (powerPresent.IsUpdated()) {
|
||||
lv_label_set_text_static(batteryPlug, BatteryIcon::GetPlugIcon(powerPresent.Get()));
|
||||
}
|
||||
|
||||
batteryPercentRemaining = batteryController.PercentRemaining();
|
||||
if (batteryPercentRemaining.IsUpdated()) {
|
||||
auto batteryPercent = batteryPercentRemaining.Get();
|
||||
batteryIcon.SetBatteryPercentage(batteryPercent);
|
||||
}
|
||||
|
||||
bleState = bleController.IsConnected();
|
||||
bleRadioEnabled = bleController.IsRadioEnabled();
|
||||
if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) {
|
||||
lv_label_set_text_static(bleIcon, BleIcon::GetIcon(bleState.Get()));
|
||||
}
|
||||
lv_obj_realign(batteryPlug);
|
||||
lv_obj_realign(bleIcon);
|
||||
statusIcons.Update();
|
||||
|
||||
notificationState = notificatioManager.AreNewNotificationsAvailable();
|
||||
if (notificationState.IsUpdated()) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <displayapp/screens/BatteryIcon.h>
|
||||
#include <lvgl/src/lv_core/lv_obj.h>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
|
@ -8,6 +7,7 @@
|
|||
#include "displayapp/screens/Screen.h"
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "components/ble/BleController.h"
|
||||
#include "displayapp/widgets/StatusIcons.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
|
@ -59,25 +59,20 @@ namespace Pinetime {
|
|||
lv_obj_t* label_time;
|
||||
lv_obj_t* label_time_ampm;
|
||||
lv_obj_t* label_date;
|
||||
lv_obj_t* bleIcon;
|
||||
lv_obj_t* batteryPlug;
|
||||
lv_obj_t* heartbeatIcon;
|
||||
lv_obj_t* heartbeatValue;
|
||||
lv_obj_t* stepIcon;
|
||||
lv_obj_t* stepValue;
|
||||
lv_obj_t* notificationIcon;
|
||||
|
||||
BatteryIcon batteryIcon;
|
||||
|
||||
Controllers::DateTime& dateTimeController;
|
||||
Controllers::Battery& batteryController;
|
||||
Controllers::Ble& bleController;
|
||||
Controllers::NotificationManager& notificatioManager;
|
||||
Controllers::Settings& settingsController;
|
||||
Controllers::HeartRateController& heartRateController;
|
||||
Controllers::MotionController& motionController;
|
||||
|
||||
lv_task_t* taskRefresh;
|
||||
Widgets::StatusIcons statusIcons;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "displayapp/DisplayApp.h"
|
||||
#include "displayapp/screens/Symbols.h"
|
||||
#include "displayapp/screens/BatteryIcon.h"
|
||||
#include <components/ble/BleController.h>
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
|
@ -22,13 +23,16 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
|
|||
Controllers::DateTime& dateTimeController,
|
||||
Controllers::BrightnessController& brightness,
|
||||
Controllers::MotorController& motorController,
|
||||
Pinetime::Controllers::Settings& settingsController)
|
||||
Pinetime::Controllers::Settings& settingsController,
|
||||
Controllers::Ble& bleController)
|
||||
: Screen(app),
|
||||
batteryController {batteryController},
|
||||
dateTimeController {dateTimeController},
|
||||
brightness {brightness},
|
||||
motorController {motorController},
|
||||
settingsController {settingsController} {
|
||||
settingsController {settingsController},
|
||||
statusIcons(batteryController, bleController) {
|
||||
|
||||
statusIcons.Create();
|
||||
|
||||
// This is the distance (padding) between all objects on this screen.
|
||||
static constexpr uint8_t innerDistance = 10;
|
||||
|
@ -38,9 +42,6 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
|
|||
lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER);
|
||||
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 0);
|
||||
|
||||
batteryIcon.Create(lv_scr_act());
|
||||
lv_obj_align(batteryIcon.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
|
||||
|
||||
static constexpr uint8_t barHeight = 20 + innerDistance;
|
||||
static constexpr uint8_t buttonHeight = (LV_VER_RES_MAX - barHeight - innerDistance) / 2;
|
||||
static constexpr uint8_t buttonWidth = (LV_HOR_RES_MAX - innerDistance) / 2; // wide buttons
|
||||
|
@ -117,7 +118,7 @@ QuickSettings::~QuickSettings() {
|
|||
|
||||
void QuickSettings::UpdateScreen() {
|
||||
lv_label_set_text(label_time, dateTimeController.FormattedTime().c_str());
|
||||
batteryIcon.SetBatteryPercentage(batteryController.PercentRemaining());
|
||||
statusIcons.Update();
|
||||
}
|
||||
|
||||
void QuickSettings::OnButtonEvent(lv_obj_t* object, lv_event_t event) {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "components/motor/MotorController.h"
|
||||
#include "components/settings/Settings.h"
|
||||
#include "components/battery/BatteryController.h"
|
||||
#include <displayapp/screens/BatteryIcon.h>
|
||||
#include "displayapp/widgets/StatusIcons.h"
|
||||
|
||||
namespace Pinetime {
|
||||
|
||||
|
@ -22,7 +22,8 @@ namespace Pinetime {
|
|||
Controllers::DateTime& dateTimeController,
|
||||
Controllers::BrightnessController& brightness,
|
||||
Controllers::MotorController& motorController,
|
||||
Pinetime::Controllers::Settings& settingsController);
|
||||
Pinetime::Controllers::Settings& settingsController,
|
||||
Controllers::Ble& bleController);
|
||||
|
||||
~QuickSettings() override;
|
||||
|
||||
|
@ -31,7 +32,6 @@ namespace Pinetime {
|
|||
void UpdateScreen();
|
||||
|
||||
private:
|
||||
Pinetime::Controllers::Battery& batteryController;
|
||||
Controllers::DateTime& dateTimeController;
|
||||
Controllers::BrightnessController& brightness;
|
||||
Controllers::MotorController& motorController;
|
||||
|
@ -40,6 +40,11 @@ namespace Pinetime {
|
|||
lv_task_t* taskUpdate;
|
||||
lv_obj_t* label_time;
|
||||
|
||||
DirtyValue<uint8_t> batteryPercentRemaining {};
|
||||
DirtyValue<bool> powerPresent {};
|
||||
DirtyValue<bool> bleState {};
|
||||
DirtyValue<bool> bleRadioEnabled {};
|
||||
|
||||
lv_style_t btn_style;
|
||||
|
||||
lv_obj_t* btn1;
|
||||
|
@ -49,7 +54,7 @@ namespace Pinetime {
|
|||
lv_obj_t* btn3_lvl;
|
||||
lv_obj_t* btn4;
|
||||
|
||||
BatteryIcon batteryIcon;
|
||||
Widgets::StatusIcons statusIcons;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
55
src/displayapp/widgets/StatusIcons.cpp
Normal file
55
src/displayapp/widgets/StatusIcons.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include "displayapp/widgets/StatusIcons.h"
|
||||
#include "displayapp/screens/Symbols.h"
|
||||
|
||||
using namespace Pinetime::Applications::Widgets;
|
||||
|
||||
StatusIcons::StatusIcons(Controllers::Battery& batteryController, Controllers::Ble& bleController)
|
||||
: batteryController {batteryController}, bleController {bleController} {
|
||||
}
|
||||
|
||||
void StatusIcons::Align() {
|
||||
lv_obj_t* lastIcon = batteryIcon.GetObject();
|
||||
|
||||
for (auto& icon : icons) {
|
||||
if (!lv_obj_get_hidden(icon)) {
|
||||
lv_obj_align(icon, lastIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
lastIcon = icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StatusIcons::Create() {
|
||||
batteryIcon.Create(lv_scr_act());
|
||||
lv_obj_align(batteryIcon.GetObject(), lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0);
|
||||
|
||||
icons[Icons::BatteryPlug] = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(icons[Icons::BatteryPlug], LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFF0000));
|
||||
lv_label_set_text_static(icons[Icons::BatteryPlug], Screens::Symbols::plug);
|
||||
|
||||
icons[Icons::BleIcon] = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(icons[Icons::BleIcon], LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0082FC));
|
||||
lv_label_set_text_static(icons[Icons::BleIcon], Screens::Symbols::bluetooth);
|
||||
|
||||
Align();
|
||||
}
|
||||
|
||||
void StatusIcons::Update() {
|
||||
powerPresent = batteryController.IsPowerPresent();
|
||||
if (powerPresent.IsUpdated()) {
|
||||
lv_obj_set_hidden(icons[Icons::BatteryPlug], !powerPresent.Get());
|
||||
}
|
||||
|
||||
batteryPercentRemaining = batteryController.PercentRemaining();
|
||||
if (batteryPercentRemaining.IsUpdated()) {
|
||||
auto batteryPercent = batteryPercentRemaining.Get();
|
||||
batteryIcon.SetBatteryPercentage(batteryPercent);
|
||||
}
|
||||
|
||||
bleState = bleController.IsConnected();
|
||||
bleRadioEnabled = bleController.IsRadioEnabled();
|
||||
if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) {
|
||||
lv_obj_set_hidden(icons[Icons::BleIcon], !bleState.Get());
|
||||
}
|
||||
|
||||
Align();
|
||||
}
|
38
src/displayapp/widgets/StatusIcons.h
Normal file
38
src/displayapp/widgets/StatusIcons.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include "displayapp/screens/Screen.h"
|
||||
#include "components/battery/BatteryController.h"
|
||||
#include "components/ble/BleController.h"
|
||||
#include "displayapp/screens/BatteryIcon.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Widgets {
|
||||
class StatusIcons {
|
||||
public:
|
||||
StatusIcons(Controllers::Battery& batteryController, Controllers::Ble& bleController);
|
||||
void Align();
|
||||
void Create();
|
||||
lv_obj_t* GetObject() {
|
||||
return batteryIcon.GetObject();
|
||||
}
|
||||
void Update();
|
||||
|
||||
private:
|
||||
Screens::BatteryIcon batteryIcon;
|
||||
Pinetime::Controllers::Battery& batteryController;
|
||||
Controllers::Ble& bleController;
|
||||
|
||||
Screens::DirtyValue<uint8_t> batteryPercentRemaining {};
|
||||
Screens::DirtyValue<bool> powerPresent {};
|
||||
Screens::DirtyValue<bool> bleState {};
|
||||
Screens::DirtyValue<bool> bleRadioEnabled {};
|
||||
|
||||
enum Icons { BatteryPlug, BleIcon };
|
||||
lv_obj_t* icons[2];
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue