fix screenshot testing
This commit is contained in:
2
lvgl.h
2
lvgl.h
@@ -82,6 +82,8 @@ extern "C" {
|
|||||||
|
|
||||||
#include "src/lv_api_map.h"
|
#include "src/lv_api_map.h"
|
||||||
|
|
||||||
|
//#define LV_BUILD_TEST 1
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ CSRCS += lv_test_core/lv_test_core.c
|
|||||||
CSRCS += lv_test_core/lv_test_obj.c
|
CSRCS += lv_test_core/lv_test_obj.c
|
||||||
CSRCS += lv_test_core/lv_test_style.c
|
CSRCS += lv_test_core/lv_test_style.c
|
||||||
CSRCS += lv_test_core/lv_test_font_loader.c
|
CSRCS += lv_test_core/lv_test_font_loader.c
|
||||||
|
CSRCS += lv_test_widgets/lv_test_label.c
|
||||||
CSRCS += lv_test_fonts/font_1.c
|
CSRCS += lv_test_fonts/font_1.c
|
||||||
CSRCS += lv_test_fonts/font_2.c
|
CSRCS += lv_test_fonts/font_2.c
|
||||||
CSRCS += lv_test_fonts/font_3.c
|
CSRCS += lv_test_fonts/font_3.c
|
||||||
|
|||||||
@@ -294,8 +294,8 @@ advanced_features = {
|
|||||||
"LV_MEM_CUSTOM":1,
|
"LV_MEM_CUSTOM":1,
|
||||||
"LV_HOR_RES_MAX":800,
|
"LV_HOR_RES_MAX":800,
|
||||||
"LV_VER_RES_MAX":480,
|
"LV_VER_RES_MAX":480,
|
||||||
"LV_COLOR_DEPTH":16,
|
"LV_COLOR_DEPTH":32,
|
||||||
"LV_COLOR_16_SWAP":1,
|
"LV_COLOR_16_SWAP":0,
|
||||||
"LV_COLOR_SCREEN_TRANSP":1,
|
"LV_COLOR_SCREEN_TRANSP":1,
|
||||||
"LV_USE_GROUP":1,
|
"LV_USE_GROUP":1,
|
||||||
"LV_USE_ANIMATION":1,
|
"LV_USE_ANIMATION":1,
|
||||||
@@ -305,9 +305,6 @@ advanced_features = {
|
|||||||
"LV_USE_IMG_TRANSFORM":1,
|
"LV_USE_IMG_TRANSFORM":1,
|
||||||
"LV_USE_API_EXTENSION_V6":1,
|
"LV_USE_API_EXTENSION_V6":1,
|
||||||
"LV_USE_USER_DATA":1,
|
"LV_USE_USER_DATA":1,
|
||||||
"LV_USE_USER_DATA_FREE":1,
|
|
||||||
"LV_USER_DATA_FREE_INCLUDE":"\\\"<stdio.h>\\\"",
|
|
||||||
"LV_USER_DATA_FREE": "\\\"free\\\"",
|
|
||||||
"LV_IMG_CACHE_DEF_SIZE":32,
|
"LV_IMG_CACHE_DEF_SIZE":32,
|
||||||
"LV_USE_LOG":1,
|
"LV_USE_LOG":1,
|
||||||
"LV_USE_THEME_MATERIAL":1,
|
"LV_USE_THEME_MATERIAL":1,
|
||||||
@@ -382,7 +379,8 @@ advanced_features = {
|
|||||||
|
|
||||||
build("Minimal monochrome", minimal_monochrome)
|
build("Minimal monochrome", minimal_monochrome)
|
||||||
build("All objects, minimal features", all_obj_minimal_features)
|
build("All objects, minimal features", all_obj_minimal_features)
|
||||||
build("All objects, all features", all_obj_all_features)
|
build("All objects, all common features", all_obj_all_features)
|
||||||
|
build("All objects, with advanced features", advanced_features)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,8 @@
|
|||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* DEFINES
|
||||||
*********************/
|
*********************/
|
||||||
#define REF_IMGS_PATH "lvgl/tests/lv_test_ref_imgs/"
|
//#define REF_IMGS_PATH "lvgl/tests/lv_test_ref_imgs/"
|
||||||
|
#define REF_IMGS_PATH "lv_test_ref_imgs/"
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
@@ -177,6 +178,16 @@ void lv_test_assert_color_eq(lv_color_t c_ref, lv_color_t c_act, const char * s)
|
|||||||
|
|
||||||
void lv_test_assert_img_eq(const char * fn_ref, const char * s)
|
void lv_test_assert_img_eq(const char * fn_ref, const char * s)
|
||||||
{
|
{
|
||||||
|
#if LV_COLOR_DEPTH != 32
|
||||||
|
lv_test_print(" SKIP: Can't compare '%s' because LV_COLOR_DEPTH != 32", fn_ref);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LV_HOR_RES_MAX != 800 || LV_VER_RES_MAX != 480
|
||||||
|
lv_test_print(" SKIP: Can't compare '%s' because the resolution needs to be 800x480 (LV_HOR_RES_MAX, LV_VER_RES_MAX)", fn_ref);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
char fn_ref_full[512];
|
char fn_ref_full[512];
|
||||||
sprintf(fn_ref_full, "%s%s", REF_IMGS_PATH, fn_ref);
|
sprintf(fn_ref_full, "%s%s", REF_IMGS_PATH, fn_ref);
|
||||||
|
|
||||||
@@ -185,16 +196,23 @@ void lv_test_assert_img_eq(const char * fn_ref, const char * s)
|
|||||||
uint8_t * screen_buf;
|
uint8_t * screen_buf;
|
||||||
|
|
||||||
lv_disp_t * disp = lv_disp_get_default();
|
lv_disp_t * disp = lv_disp_get_default();
|
||||||
|
lv_obj_invalidate(lv_disp_get_scr_act(disp));
|
||||||
lv_refr_now(disp);
|
lv_refr_now(disp);
|
||||||
screen_buf = disp->driver.buffer->buf1;
|
|
||||||
|
extern lv_color_t test_fb[];
|
||||||
|
|
||||||
|
screen_buf = (uint8_t *)test_fb;
|
||||||
|
|
||||||
|
uint8_t * ptr_act = NULL;
|
||||||
|
const png_byte* ptr_ref = NULL;
|
||||||
|
|
||||||
bool err = false;
|
bool err = false;
|
||||||
int x, y, i_buf = 0;
|
int x, y, i_buf = 0;
|
||||||
for (y=0; y<p.height; y++) {
|
for (y=0; y<p.height; y++) {
|
||||||
png_byte* row = p.row_pointers[y];
|
png_byte* row = p.row_pointers[y];
|
||||||
for (x=0; x<p.width; x++) {
|
for (x=0; x<p.width; x++) {
|
||||||
const png_byte* ptr_ref = &(row[x*3]);
|
ptr_ref = &(row[x*3]);
|
||||||
uint8_t * ptr_act = &(screen_buf[i_buf*4]);
|
ptr_act = &(screen_buf[i_buf*4]);
|
||||||
uint8_t tmp = ptr_act[0];
|
uint8_t tmp = ptr_act[0];
|
||||||
ptr_act[0] = ptr_act[2];
|
ptr_act[0] = ptr_act[2];
|
||||||
ptr_act[2] = tmp;
|
ptr_act[2] = tmp;
|
||||||
@@ -211,7 +229,11 @@ void lv_test_assert_img_eq(const char * fn_ref, const char * s)
|
|||||||
png_release(&p);
|
png_release(&p);
|
||||||
|
|
||||||
if(err) {
|
if(err) {
|
||||||
lv_test_error(" FAIL: %s. (Expected: %s)", s, fn_ref);
|
uint32_t ref_px = 0;
|
||||||
|
uint32_t act_px = 0;
|
||||||
|
memcpy(&ref_px, ptr_ref, 3);
|
||||||
|
memcpy(&act_px, ptr_act, 3);
|
||||||
|
lv_test_error(" FAIL: %s. (Expected: %s, diff. at (%d;%d), %08x instead of %08x)", s, fn_ref, x, y, act_px, ref_px);
|
||||||
} else {
|
} else {
|
||||||
lv_test_print(" PASS: %s. (Expected: %s)", s, fn_ref);
|
lv_test_print(" PASS: %s. (Expected: %s)", s, fn_ref);
|
||||||
}
|
}
|
||||||
@@ -334,7 +356,7 @@ static void png_release(png_img_t * p)
|
|||||||
free(p->row_pointers[y]);
|
free(p->row_pointers[y]);
|
||||||
free(p->row_pointers);
|
free(p->row_pointers);
|
||||||
}
|
}
|
||||||
//
|
|
||||||
//static void process_file(png_img_t * p)
|
//static void process_file(png_img_t * p)
|
||||||
//{
|
//{
|
||||||
// if (png_get_color_type(p->png_ptr, p->info_ptr) == PNG_COLOR_TYPE_RGB)
|
// if (png_get_color_type(p->png_ptr, p->info_ptr) == PNG_COLOR_TYPE_RGB)
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
* INCLUDES
|
* INCLUDES
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
#include "../lv_test_assert.h"
|
#include "lvgl/lvgl.h"
|
||||||
#if LV_BUILD_TEST
|
#if LV_BUILD_TEST
|
||||||
#include "../lvgl.h"
|
#include "../lv_test_assert.h"
|
||||||
#include "../src/lv_font/lv_font_fmt_txt.h"
|
#include "lvgl/src/lv_font/lv_font_fmt_txt.h"
|
||||||
#include "../src/lv_font/lv_font.h"
|
#include "lvgl/src/lv_font/lv_font.h"
|
||||||
#include "../src/lv_font/lv_font_loader.h"
|
#include "lvgl/src/lv_font/lv_font_loader.h"
|
||||||
|
|
||||||
#include "lv_test_font_loader.h"
|
#include "lv_test_font_loader.h"
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
* STATIC PROTOTYPES
|
* STATIC PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
#if LV_USE_FILESYSTEM
|
#if LV_USE_FILESYSTEM && LV_FONT_FMT_TXT_LARGE == 0
|
||||||
static int compare_fonts(lv_font_t * f1, lv_font_t * f2);
|
static int compare_fonts(lv_font_t * f1, lv_font_t * f2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ extern lv_font_t font_3;
|
|||||||
|
|
||||||
void lv_test_font_loader(void)
|
void lv_test_font_loader(void)
|
||||||
{
|
{
|
||||||
#if LV_USE_FILESYSTEM
|
#if LV_USE_FILESYSTEM && LV_FONT_FMT_TXT_LARGE == 0
|
||||||
lv_font_t * font_1_bin = lv_font_load("f:font_1.fnt");
|
lv_font_t * font_1_bin = lv_font_load("f:font_1.fnt");
|
||||||
lv_font_t * font_2_bin = lv_font_load("f:font_2.fnt");
|
lv_font_t * font_2_bin = lv_font_load("f:font_2.fnt");
|
||||||
lv_font_t * font_3_bin = lv_font_load("f:font_3.fnt");
|
lv_font_t * font_3_bin = lv_font_load("f:font_3.fnt");
|
||||||
@@ -62,10 +62,12 @@ void lv_test_font_loader(void)
|
|||||||
lv_font_free(font_1_bin);
|
lv_font_free(font_1_bin);
|
||||||
lv_font_free(font_2_bin);
|
lv_font_free(font_2_bin);
|
||||||
lv_font_free(font_3_bin);
|
lv_font_free(font_3_bin);
|
||||||
|
#else
|
||||||
|
lv_test_print("SKIP: font load test because it requires LV_USE_FILESYSTEM 1 and LV_FONT_FMT_TXT_LARGE 0");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LV_USE_FILESYSTEM
|
#if LV_USE_FILESYSTEM && LV_FONT_FMT_TXT_LARGE == 0
|
||||||
static int compare_fonts(lv_font_t * f1, lv_font_t * f2)
|
static int compare_fonts(lv_font_t * f1, lv_font_t * f2)
|
||||||
{
|
{
|
||||||
lv_test_assert_true(f1 != NULL && f2 != NULL, "font not null");
|
lv_test_assert_true(f1 != NULL && f2 != NULL, "font not null");
|
||||||
|
|||||||
@@ -3,12 +3,15 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "lv_test_core/lv_test_core.h"
|
#include "lv_test_core/lv_test_core.h"
|
||||||
|
#include "lv_test_widgets/lv_test_label.h"
|
||||||
|
|
||||||
#if LV_BUILD_TEST
|
#if LV_BUILD_TEST
|
||||||
|
|
||||||
static void hal_init(void);
|
static void hal_init(void);
|
||||||
static void dummy_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
|
static void dummy_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
|
||||||
|
|
||||||
|
lv_color_t test_fb[LV_HOR_RES_MAX * LV_VER_RES_MAX];
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
printf("Call lv_init...\n");
|
printf("Call lv_init...\n");
|
||||||
@@ -17,6 +20,7 @@ int main(void)
|
|||||||
hal_init();
|
hal_init();
|
||||||
|
|
||||||
lv_test_core();
|
lv_test_core();
|
||||||
|
lv_test_label();
|
||||||
|
|
||||||
printf("Exit with success!\n");
|
printf("Exit with success!\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -85,7 +89,7 @@ static void hal_init(void)
|
|||||||
static lv_disp_buf_t disp_buf;
|
static lv_disp_buf_t disp_buf;
|
||||||
lv_color_t * disp_buf1 = (lv_color_t *)malloc(LV_HOR_RES * LV_VER_RES * sizeof(lv_color_t));
|
lv_color_t * disp_buf1 = (lv_color_t *)malloc(LV_HOR_RES * LV_VER_RES * sizeof(lv_color_t));
|
||||||
|
|
||||||
lv_disp_buf_init(&disp_buf, disp_buf1, NULL, LV_HOR_RES* LV_VER_RES);
|
lv_disp_buf_init(&disp_buf, disp_buf1, NULL, LV_HOR_RES * LV_VER_RES);
|
||||||
|
|
||||||
lv_disp_drv_t disp_drv;
|
lv_disp_drv_t disp_drv;
|
||||||
lv_disp_drv_init(&disp_drv);
|
lv_disp_drv_init(&disp_drv);
|
||||||
@@ -109,11 +113,15 @@ static void hal_init(void)
|
|||||||
lv_fs_drv_register(&drv); /*Finally register the drive*/
|
lv_fs_drv_register(&drv); /*Finally register the drive*/
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
static void dummy_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
|
static void dummy_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
|
||||||
{
|
{
|
||||||
LV_UNUSED(area);
|
LV_UNUSED(area);
|
||||||
LV_UNUSED(color_p);
|
LV_UNUSED(color_p);
|
||||||
|
|
||||||
|
memcpy(test_fb, color_p, lv_area_get_size(area) * sizeof(lv_color_t));
|
||||||
|
|
||||||
lv_disp_flush_ready(disp_drv);
|
lv_disp_flush_ready(disp_drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file lv_test_cont.c
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*********************
|
|
||||||
* INCLUDES
|
|
||||||
*********************/
|
|
||||||
#include "../../lvgl.h"
|
|
||||||
#include "../lv_test_assert.h"
|
|
||||||
|
|
||||||
#if LV_BUILD_TEST
|
|
||||||
|
|
||||||
|
|
||||||
/*********************
|
|
||||||
* DEFINES
|
|
||||||
*********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* TYPEDEFS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* STATIC PROTOTYPES
|
|
||||||
**********************/
|
|
||||||
static void create_copy(void);
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* STATIC VARIABLES
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* MACROS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* GLOBAL FUNCTIONS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
void lv_test_cont(void)
|
|
||||||
{
|
|
||||||
lv_test_print("");
|
|
||||||
lv_test_print("===================");
|
|
||||||
lv_test_print("Start lv_cont tests");
|
|
||||||
lv_test_print("===================");
|
|
||||||
|
|
||||||
create_copy();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**********************
|
|
||||||
* STATIC FUNCTIONS
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
static void create_copy(void)
|
|
||||||
{
|
|
||||||
lv_test_print("");
|
|
||||||
lv_test_print("Create and copy a container");
|
|
||||||
lv_test_print("---------------------------");
|
|
||||||
|
|
||||||
lv_test_print("Create a container");
|
|
||||||
lv_test_assert_int_eq(0, lv_obj_count_children(lv_scr_act()), "Screen's children count before creation");
|
|
||||||
|
|
||||||
lv_obj_t * obj = lv_cont_create(lv_scr_act(), NULL);
|
|
||||||
lv_test_assert_int_eq(1, lv_obj_count_children(lv_scr_act()), "Screen's children count after creation");
|
|
||||||
|
|
||||||
lv_test_print("Test the default values");
|
|
||||||
lv_test_assert_int_eq(LV_FIT_NONE, lv_cont_get_fit_left(obj), "Default left fit");
|
|
||||||
lv_test_assert_int_eq(LV_FIT_NONE, lv_cont_get_fit_right(obj), "Default right fit");
|
|
||||||
lv_test_assert_int_eq(LV_FIT_NONE, lv_cont_get_fit_top(obj), "Default top fit");
|
|
||||||
lv_test_assert_int_eq(LV_FIT_NONE, lv_cont_get_fit_bottom(obj), "Default bottom fit");
|
|
||||||
lv_test_assert_int_eq(LV_LAYOUT_OFF, lv_cont_get_layout(obj), "Default layout");
|
|
||||||
|
|
||||||
lv_test_print("Delete the container");
|
|
||||||
lv_obj_del(obj);
|
|
||||||
obj = NULL;
|
|
||||||
lv_test_assert_int_eq(0, lv_obj_count_children(lv_scr_act()), "Screen's children count after delete");
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
BIN
tests/lv_test_ref_imgs/lv_test_img32_label_1.png
Normal file
BIN
tests/lv_test_ref_imgs/lv_test_img32_label_1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.7 KiB |
70
tests/lv_test_widgets/lv_test_label.c
Normal file
70
tests/lv_test_widgets/lv_test_label.c
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* @file lv_test_label.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* INCLUDES
|
||||||
|
*********************/
|
||||||
|
#include "../../lvgl.h"
|
||||||
|
#include "../lv_test_assert.h"
|
||||||
|
#include "lv_test_label.h"
|
||||||
|
|
||||||
|
#if LV_BUILD_TEST
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* DEFINES
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* TYPEDEFS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC PROTOTYPES
|
||||||
|
**********************/
|
||||||
|
static void create_copy(void);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC VARIABLES
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* MACROS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* GLOBAL FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void lv_test_label(void)
|
||||||
|
{
|
||||||
|
lv_test_print("");
|
||||||
|
lv_test_print("===================");
|
||||||
|
lv_test_print("Start lv_label tests");
|
||||||
|
lv_test_print("===================");
|
||||||
|
|
||||||
|
#if LV_USE_LABEL
|
||||||
|
create_copy();
|
||||||
|
#else
|
||||||
|
lv_test_print("Skip label test: LV_USE_LABEL == 0");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* STATIC FUNCTIONS
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
static void create_copy(void)
|
||||||
|
{
|
||||||
|
lv_test_print("");
|
||||||
|
lv_test_print("Create a label");
|
||||||
|
lv_test_print("---------------------------");
|
||||||
|
|
||||||
|
lv_label_create(lv_scr_act(), NULL);
|
||||||
|
#if LV_COLOR_DEPTH == 32
|
||||||
|
lv_test_assert_img_eq("lv_test_img32_label_1.png", "Create a label and leave the default settings");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* @file lv_test_obj.h
|
* @file lv_test_label.h
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LV_TEST_CONT_H
|
#ifndef LV_TEST_LABEL_H
|
||||||
#define LV_TEST_CONT_H
|
#define LV_TEST_LABEL_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -25,7 +25,7 @@ extern "C" {
|
|||||||
/**********************
|
/**********************
|
||||||
* GLOBAL PROTOTYPES
|
* GLOBAL PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
void lv_test_cont(void);
|
void lv_test_label(void);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
Reference in New Issue
Block a user