mirror of
https://github.com/HASwitchPlate/openHASP.git
synced 2025-07-26 20:56:37 +00:00
Fix zifont
This commit is contained in:
parent
ef57a6ec41
commit
762d5190ac
@ -256,7 +256,7 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in
|
|||||||
* Log settings
|
* Log settings
|
||||||
*===============*/
|
*===============*/
|
||||||
|
|
||||||
#define LV_USE_PERF_MONITOR 0
|
#define LV_USE_PERF_MONITOR 1
|
||||||
|
|
||||||
/*1: Enable the log module*/
|
/*1: Enable the log module*/
|
||||||
#define LV_USE_LOG 1 // set back to 0 before release !!
|
#define LV_USE_LOG 1 // set back to 0 before release !!
|
||||||
@ -400,6 +400,9 @@ typedef void* lv_font_user_data_t;
|
|||||||
#define LV_THEME_DEFAULT_FONT_TITLE LV_FONT_DEFAULT // &lv_font_roboto_28
|
#define LV_THEME_DEFAULT_FONT_TITLE LV_FONT_DEFAULT // &lv_font_roboto_28
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define LV_USE_THEME_EMPTY 1
|
||||||
|
#define LV_USE_THEME_TEMPLATE 1
|
||||||
|
|
||||||
/*=================
|
/*=================
|
||||||
* Text settings
|
* Text settings
|
||||||
*=================*/
|
*=================*/
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
#include "lv_zifont.h"
|
#include "lv_zifont.h"
|
||||||
// #include "../src/hasp_log.h"
|
|
||||||
#include "ArduinoLog.h"
|
#include "ArduinoLog.h"
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
@ -121,28 +120,48 @@ int lv_zifont_font_init(lv_font_t ** font, const char * font_path, uint16_t size
|
|||||||
{
|
{
|
||||||
charInBuffer = 0; // invalidate any previous cache
|
charInBuffer = 0; // invalidate any previous cache
|
||||||
|
|
||||||
if(!*font) *font = (lv_font_t *)lv_mem_alloc(sizeof(lv_font_t));
|
Log.trace("ZI: start");
|
||||||
LV_ASSERT_MEM(*font);
|
|
||||||
|
if(!*font) {
|
||||||
|
*font = (lv_font_t *)lv_mem_alloc(sizeof(lv_font_t));
|
||||||
|
LV_ASSERT_MEM(*font);
|
||||||
|
lv_memset(*font, 0x00, sizeof(lv_font_t)); // lv_mem_alloc might be dirty
|
||||||
|
}
|
||||||
|
Log.trace("ZI: struct ptr OK");
|
||||||
|
|
||||||
lv_font_fmt_zifont_dsc_t * dsc;
|
lv_font_fmt_zifont_dsc_t * dsc;
|
||||||
if(!(*font)->dsc) {
|
if(!(*font)->dsc) {
|
||||||
dsc = (lv_font_fmt_zifont_dsc_t *)lv_mem_alloc(sizeof(lv_font_fmt_zifont_dsc_t));
|
dsc = (lv_font_fmt_zifont_dsc_t *)lv_mem_alloc(sizeof(lv_font_fmt_zifont_dsc_t));
|
||||||
LV_ASSERT_MEM(dsc);
|
LV_ASSERT_MEM(dsc);
|
||||||
|
lv_memset(dsc, 0x00, sizeof(lv_font_fmt_zifont_dsc_t)); // lv_mem_alloc might be dirty
|
||||||
|
Log.trace("ZI: created new font dsc");
|
||||||
} else {
|
} else {
|
||||||
dsc = (lv_font_fmt_zifont_dsc_t *)(*font)->dsc;
|
dsc = (lv_font_fmt_zifont_dsc_t *)(*font)->dsc;
|
||||||
|
Log.trace("ZI: font dsc exists");
|
||||||
}
|
}
|
||||||
if(dsc == NULL) return ZIFONT_ERROR_OUT_OF_MEMORY;
|
LV_ASSERT_MEM(dsc);
|
||||||
|
Log.trace("ZI: struct dsc OK");
|
||||||
|
if(!dsc) return ZIFONT_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
/* Initialize Last Glyph DSC */
|
/* Initialize Last Glyph DSC */
|
||||||
dsc->last_glyph_dsc = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t));
|
dsc->last_glyph_dsc = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t));
|
||||||
|
lv_memset(dsc->last_glyph_dsc, 0x00, sizeof(lv_zifont_char_t)); // lv_mem_alloc might be dirty
|
||||||
|
|
||||||
|
Log.trace("ZI: glyph dsc A");
|
||||||
if(dsc->last_glyph_dsc == NULL) return ZIFONT_ERROR_OUT_OF_MEMORY;
|
if(dsc->last_glyph_dsc == NULL) return ZIFONT_ERROR_OUT_OF_MEMORY;
|
||||||
|
Log.trace("ZI: glyph dsc B");
|
||||||
dsc->last_glyph_dsc->width = 0;
|
dsc->last_glyph_dsc->width = 0;
|
||||||
dsc->last_glyph_id = 0;
|
Log.trace("ZI: glyph dsc C");
|
||||||
|
dsc->last_glyph_id = 0;
|
||||||
|
|
||||||
|
Log.trace("ZI: glyph dsc OK");
|
||||||
|
|
||||||
/* Open the font for reading */
|
/* Open the font for reading */
|
||||||
File file;
|
File file;
|
||||||
if(!openFont(file, font_path)) return ZIFONT_ERROR_OPENING_FILE;
|
if(!openFont(file, font_path)) return ZIFONT_ERROR_OPENING_FILE;
|
||||||
|
|
||||||
|
Log.trace("ZI: font open OK");
|
||||||
|
|
||||||
/* Read file header as dsc */
|
/* Read file header as dsc */
|
||||||
zi_font_header_t header;
|
zi_font_header_t header;
|
||||||
size_t readSize = file.readBytes((char *)&header, sizeof(zi_font_header_t));
|
size_t readSize = file.readBytes((char *)&header, sizeof(zi_font_header_t));
|
||||||
@ -161,6 +180,8 @@ int lv_zifont_font_init(lv_font_t ** font, const char * font_path, uint16_t size
|
|||||||
return ZIFONT_ERROR_UNKNOWN_HEADER;
|
return ZIFONT_ERROR_UNKNOWN_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.trace("ZI: headers OK");
|
||||||
|
|
||||||
dsc->CharHeight = header.CharHeight;
|
dsc->CharHeight = header.CharHeight;
|
||||||
dsc->CharWidth = header.CharWidth;
|
dsc->CharWidth = header.CharWidth;
|
||||||
dsc->Maximumnumchars = header.Maximumnumchars;
|
dsc->Maximumnumchars = header.Maximumnumchars;
|
||||||
@ -169,14 +190,19 @@ int lv_zifont_font_init(lv_font_t ** font, const char * font_path, uint16_t size
|
|||||||
dsc->Startdataaddress = header.Startdataaddress + header.Descriptionlength;
|
dsc->Startdataaddress = header.Startdataaddress + header.Descriptionlength;
|
||||||
dsc->Fontdataadd8byte = header.Fontdataadd8byte;
|
dsc->Fontdataadd8byte = header.Fontdataadd8byte;
|
||||||
|
|
||||||
|
Log.trace("ZI: dsc info OK");
|
||||||
|
|
||||||
if(!dsc->ascii_glyph_dsc) {
|
if(!dsc->ascii_glyph_dsc) {
|
||||||
dsc->ascii_glyph_dsc = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t) * CHAR_CACHE_SIZE);
|
dsc->ascii_glyph_dsc = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t) * CHAR_CACHE_SIZE);
|
||||||
LV_ASSERT_MEM(dsc->ascii_glyph_dsc);
|
LV_ASSERT_MEM(dsc->ascii_glyph_dsc);
|
||||||
|
lv_memset(dsc->ascii_glyph_dsc, 0x00,
|
||||||
|
sizeof(lv_zifont_char_t) * CHAR_CACHE_SIZE); // lv_mem_alloc might be dirty
|
||||||
}
|
}
|
||||||
if(dsc->ascii_glyph_dsc == NULL) {
|
if(dsc->ascii_glyph_dsc == NULL) {
|
||||||
file.close();
|
file.close();
|
||||||
return ZIFONT_ERROR_OUT_OF_MEMORY;
|
return ZIFONT_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
Log.trace("ZI: ascii glyph dsc OK");
|
||||||
|
|
||||||
/* read charmap into cache */
|
/* read charmap into cache */
|
||||||
file.seek(0 * sizeof(zi_font_header_t) + dsc->Startdataaddress, SeekSet);
|
file.seek(0 * sizeof(zi_font_header_t) + dsc->Startdataaddress, SeekSet);
|
||||||
@ -222,10 +248,15 @@ int lv_zifont_font_init(lv_font_t ** font, const char * font_path, uint16_t size
|
|||||||
/* header data struct */ /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */
|
/* header data struct */ /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */
|
||||||
(*font)->subpx = 0;
|
(*font)->subpx = 0;
|
||||||
|
|
||||||
|
Log.trace("ZI: font dsc data OK");
|
||||||
|
|
||||||
if((*font)->user_data != (char *)font_path) {
|
if((*font)->user_data != (char *)font_path) {
|
||||||
if((*font)->user_data) free((*font)->user_data);
|
if((*font)->user_data) free((*font)->user_data);
|
||||||
(*font)->user_data = (char *)font_path;
|
(*font)->user_data = (char *)font_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.trace("ZI: font load OK");
|
||||||
|
|
||||||
return ZIFONT_NO_ERROR;
|
return ZIFONT_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +314,8 @@ const uint8_t * lv_font_get_bitmap_fmt_zifont(const lv_font_t * font, uint32_t u
|
|||||||
} else {
|
} else {
|
||||||
Serial.print("%");
|
Serial.print("%");
|
||||||
/* Read Character Table */
|
/* Read Character Table */
|
||||||
charInfo = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t));
|
charInfo = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t));
|
||||||
|
lv_memset(charInfo, 0x00, sizeof(lv_zifont_char_t)); // lv_mem_alloc might be dirty
|
||||||
uint32_t char_position = glyphID * sizeof(lv_zifont_char_t) + charmap_position;
|
uint32_t char_position = glyphID * sizeof(lv_zifont_char_t) + charmap_position;
|
||||||
file.seek(char_position, SeekSet);
|
file.seek(char_position, SeekSet);
|
||||||
size_t readSize = file.readBytes((char *)charInfo, sizeof(lv_zifont_char_t));
|
size_t readSize = file.readBytes((char *)charInfo, sizeof(lv_zifont_char_t));
|
||||||
|
166
src/hasp.cpp
166
src/hasp.cpp
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#if HASP_USE_SPIFFS
|
#if HASP_USE_SPIFFS
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
//#include "lv_zifont.h"
|
#include "lv_zifont.h"
|
||||||
#include "SPIFFS.h"
|
#include "SPIFFS.h"
|
||||||
#endif
|
#endif
|
||||||
#include "lv_zifont.h"
|
#include "lv_zifont.h"
|
||||||
@ -107,11 +107,11 @@ static const char * btnm_map2[] = {"0", "1", "\n", "2", "3", "\n", "4", "5",
|
|||||||
|
|
||||||
static lv_obj_t * pages[HASP_NUM_PAGES];
|
static lv_obj_t * pages[HASP_NUM_PAGES];
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
#if defined(ARDUINO_ARCH_ESP8266)
|
||||||
// static lv_font_t * haspFonts[4];
|
static lv_font_t * haspFonts[4];
|
||||||
// static lv_style_t labelStyles[4];
|
// static lv_style_t labelStyles[4];
|
||||||
// static lv_style_t rollerStyles[4];
|
// static lv_style_t rollerStyles[4];
|
||||||
#else
|
#else
|
||||||
// static lv_font_t * haspFonts[8];
|
lv_font_t * haspFonts[8];
|
||||||
// static lv_style_t labelStyles[8];
|
// static lv_style_t labelStyles[8];
|
||||||
// static lv_style_t rollerStyles[8];
|
// static lv_style_t rollerStyles[8];
|
||||||
#endif
|
#endif
|
||||||
@ -611,98 +611,78 @@ void haspSetup(JsonObject settings)
|
|||||||
|
|
||||||
lv_zifont_init();
|
lv_zifont_init();
|
||||||
|
|
||||||
/* if(lv_zifont_font_init(&defaultFont, haspZiFontPath, 24) != 0) {
|
if(lv_zifont_font_init(&haspFonts[0], haspZiFontPath, 24) != 0) {
|
||||||
errorPrintln(String(F("HASP: %sFailed to set the custom font to ")) + String(haspZiFontPath));
|
Log.error(F("HASP: Failed to set the custom font to %s"), haspZiFontPath);
|
||||||
defaultFont = LV_FONT_DEFAULT; // Use default font
|
defaultFont = LV_FONT_DEFAULT; // Use default font
|
||||||
}*/
|
} else {
|
||||||
|
defaultFont = haspFonts[0];
|
||||||
|
}
|
||||||
|
|
||||||
lv_theme_t * th = lv_theme_material_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, LV_FONT_DEFAULT,
|
lv_theme_t * th;
|
||||||
LV_FONT_DEFAULT, LV_FONT_DEFAULT, LV_FONT_DEFAULT);
|
switch(haspThemeId) {
|
||||||
|
#if LV_USE_THEME_ALIEN == 1
|
||||||
|
case 1:
|
||||||
|
th = lv_theme_alien_init(haspThemeHue, defaultFont);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if LV_USE_THEME_NIGHT == 1
|
||||||
|
case 2:
|
||||||
|
th = lv_theme_night_init(haspThemeHue, defaultFont); // heavy
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if(LV_USE_THEME_MONO == 1) || (LV_USE_THEME_EMPTY == 1)
|
||||||
|
case 3:
|
||||||
|
th = lv_theme_empty_init(LV_COLOR_PURPLE, LV_COLOR_BLACK, LV_THEME_DEFAULT_FLAGS, defaultFont, defaultFont,
|
||||||
|
defaultFont, defaultFont);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if LV_USE_THEME_MATERIAL == 1
|
||||||
|
case 4:
|
||||||
|
th = lv_theme_material_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, defaultFont,
|
||||||
|
defaultFont, defaultFont, defaultFont);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if LV_USE_THEME_ZEN == 1
|
||||||
|
case 5:
|
||||||
|
th = lv_theme_zen_init(haspThemeHue, defaultFont); // lightweight
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if LV_USE_THEME_NEMO == 1
|
||||||
|
case 6:
|
||||||
|
th = lv_theme_nemo_init(haspThemeHue, defaultFont); // heavy
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if LV_USE_THEME_TEMPL == 1
|
||||||
|
case 7:
|
||||||
|
th = lv_theme_templ_init(haspThemeHue, defaultFont); // lightweight, not for production...
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if(LV_USE_THEME_HASP == 1) || (LV_USE_THEME_TEMPLATE == 1)
|
||||||
|
case 8:
|
||||||
|
th = lv_theme_template_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, defaultFont,
|
||||||
|
defaultFont, defaultFont, defaultFont);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
/* case 0:
|
||||||
|
#if LV_USE_THEME_DEFAULT == 1
|
||||||
|
th = lv_theme_default_init(haspThemeHue, defaultFont);
|
||||||
|
#else
|
||||||
|
th = lv_theme_hasp_init(512, defaultFont);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
th = lv_theme_material_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, defaultFont,
|
||||||
|
defaultFont, defaultFont, defaultFont);
|
||||||
|
Log.error(F("HASP: Unknown theme selected"));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
if(th) {
|
||||||
lv_theme_t * th;
|
Log.verbose(F("HASP: Custom theme loaded"));
|
||||||
switch(haspThemeId) {
|
} else {
|
||||||
#if LV_USE_THEME_ALIEN == 1
|
Log.error(F("HASP: No theme could be loaded"));
|
||||||
case 1:
|
}
|
||||||
th = lv_theme_alien_init(haspThemeHue, defaultFont);
|
// lv_theme_set_current(th);
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if LV_USE_THEME_NIGHT == 1
|
|
||||||
case 2:
|
|
||||||
th = lv_theme_night_init(haspThemeHue, defaultFont); // heavy
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if LV_USE_THEME_MONO == 1
|
|
||||||
case 3:
|
|
||||||
th = lv_theme_mono_init(haspThemeHue, defaultFont); // lightweight
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if LV_USE_THEME_MATERIAL == 1
|
|
||||||
case 4:
|
|
||||||
// th = lv_theme_material_init(haspThemeHue, defaultFont);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if LV_USE_THEME_ZEN == 1
|
|
||||||
case 5:
|
|
||||||
th = lv_theme_zen_init(haspThemeHue, defaultFont); // lightweight
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if LV_USE_THEME_NEMO == 1
|
|
||||||
case 6:
|
|
||||||
th = lv_theme_nemo_init(haspThemeHue, defaultFont); // heavy
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if LV_USE_THEME_TEMPL == 1
|
|
||||||
case 7:
|
|
||||||
th = lv_theme_templ_init(haspThemeHue, defaultFont); // lightweight, not for production...
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if LV_USE_THEME_HASP == 1
|
|
||||||
case 8:
|
|
||||||
th = lv_theme_hasp_init(haspThemeHue, defaultFont);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case 0:
|
|
||||||
#if LV_USE_THEME_DEFAULT == 1
|
|
||||||
th = lv_theme_default_init(haspThemeHue, defaultFont);
|
|
||||||
#else
|
|
||||||
th = lv_theme_hasp_init(512, defaultFont);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
th = lv_theme_hasp_init(512, defaultFont);
|
|
||||||
debugPrintln(F("HASP: Unknown theme selected"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(th) {
|
|
||||||
debugPrintln(F("HASP: Custom theme loaded"));
|
|
||||||
} else {
|
|
||||||
errorPrintln(F("HASP: %sNo theme could be loaded"));
|
|
||||||
}
|
|
||||||
// lv_theme_set_current(th);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(lv_zifont_font_init(&haspFonts[0], "/fonts/HMI FrankRuhlLibre 24.zi", 24) != 0) {
|
|
||||||
errorPrintln(String(F("HASP: %sFailed to set the custom font to 0")));
|
|
||||||
defaultFont = NULL; // Use default font
|
|
||||||
}
|
|
||||||
if(lv_zifont_font_init(&haspFonts[1], "/fonts/HMI FiraSans 24.zi", 24) != 0) {
|
|
||||||
errorPrintln(String(F("HASP: %sFailed to set the custom font to 1")));
|
|
||||||
defaultFont = NULL; // Use default font
|
|
||||||
}
|
|
||||||
if(lv_zifont_font_init(&haspFonts[2], "/fonts/HMI AbrilFatface 24.zi", 24) != 0) {
|
|
||||||
errorPrintln(String(F("HASP: %sFailed to set the custom font to 2")));
|
|
||||||
defaultFont = NULL; // Use default font
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < 3; i++) {
|
|
||||||
//lv_style_copy(&labelStyles[i], &lv_style_pretty_color);
|
|
||||||
labelStyles[i].text.font = haspFonts[i];
|
|
||||||
labelStyles[i].text.color = LV_COLOR_BLUE;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
haspDisconnect();
|
haspDisconnect();
|
||||||
haspLoadPage(haspPagesPath);
|
haspLoadPage(haspPagesPath);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#define LVGL7 1
|
#define LVGL7 1
|
||||||
|
|
||||||
LV_FONT_DECLARE(unscii_8_icon);
|
LV_FONT_DECLARE(unscii_8_icon);
|
||||||
|
extern lv_font_t * haspFonts[8];
|
||||||
|
|
||||||
static inline bool is_true(const char * s)
|
static inline bool is_true(const char * s)
|
||||||
{
|
{
|
||||||
@ -341,6 +342,10 @@ void haspSetLocalStyle(lv_obj_t * obj, const char * attr_p, const char * payload
|
|||||||
} else if(!strcmp_P(attr, PSTR("text_font"))) {
|
} else if(!strcmp_P(attr, PSTR("text_font"))) {
|
||||||
#if ESP32
|
#if ESP32
|
||||||
switch(var) {
|
switch(var) {
|
||||||
|
case 0:
|
||||||
|
lv_obj_set_style_local_text_font(obj, part, state, haspFonts[0]);
|
||||||
|
Log.verbose(F("Changing font to : %s"), (char *)haspFonts[0]->user_data);
|
||||||
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
lv_obj_set_style_local_text_font(obj, part, state, &unscii_8_icon);
|
lv_obj_set_style_local_text_font(obj, part, state, &unscii_8_icon);
|
||||||
break;
|
break;
|
||||||
|
@ -201,5 +201,5 @@ void loop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delay(1);
|
delay(3);
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user