mirror of
https://github.com/esphome/esphome.git
synced 2025-10-30 06:33:51 +00:00
Cleanup dashboard JS (#491)
* Cleanup dashboard JS * Add vscode * Save start_mark/end_mark * Updates * Updates * Remove need for cv.nameable It's a bit hacky but removes so much bloat from integrations * Add enum helper * Document APIs, and Improvements * Fixes * Fixes * Update PULL_REQUEST_TEMPLATE.md * Updates * Updates * Updates
This commit is contained in:
@@ -1,21 +1,21 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.automation import ACTION_REGISTRY
|
||||
from esphome import automation
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_STATE
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE
|
||||
from .. import template_ns
|
||||
|
||||
TemplateBinarySensor = template_ns.class_('TemplateBinarySensor', binary_sensor.BinarySensor,
|
||||
cg.Component)
|
||||
|
||||
CONFIG_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(TemplateBinarySensor),
|
||||
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(TemplateBinarySensor),
|
||||
cv.Optional(CONF_LAMBDA): cv.lambda_,
|
||||
}).extend(cv.COMPONENT_SCHEMA))
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME])
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield binary_sensor.register_binary_sensor(var, config)
|
||||
|
||||
@@ -25,15 +25,15 @@ def to_code(config):
|
||||
cg.add(var.set_template(template_))
|
||||
|
||||
|
||||
@ACTION_REGISTRY.register('binary_sensor.template.publish', cv.Schema({
|
||||
cv.Required(CONF_ID): cv.use_variable_id(binary_sensor.BinarySensor),
|
||||
cv.Required(CONF_STATE): cv.templatable(cv.boolean),
|
||||
}))
|
||||
@automation.register_action('binary_sensor.template.publish',
|
||||
binary_sensor.BinarySensorPublishAction,
|
||||
cv.Schema({
|
||||
cv.Required(CONF_ID): cv.use_id(binary_sensor.BinarySensor),
|
||||
cv.Required(CONF_STATE): cv.templatable(cv.boolean),
|
||||
}))
|
||||
def binary_sensor_template_publish_to_code(config, action_id, template_arg, args):
|
||||
var = yield cg.get_variable(config[CONF_ID])
|
||||
type = binary_sensor.BinarySensorPublishAction.template(template_arg)
|
||||
rhs = type.new(var)
|
||||
action = cg.Pvariable(action_id, rhs, type=type)
|
||||
paren = yield cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = yield cg.templatable(config[CONF_STATE], args, bool)
|
||||
cg.add(action.set_state(template_))
|
||||
yield action
|
||||
cg.add(var.set_state(template_))
|
||||
yield var
|
||||
|
||||
@@ -8,8 +8,6 @@ namespace template_ {
|
||||
|
||||
class TemplateBinarySensor : public Component, public binary_sensor::BinarySensor {
|
||||
public:
|
||||
explicit TemplateBinarySensor(const std::string &name) : BinarySensor(name) {}
|
||||
|
||||
void set_template(std::function<optional<bool>()> &&f) { this->f_ = f; }
|
||||
|
||||
void loop() override;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
from esphome import automation
|
||||
from esphome.automation import ACTION_REGISTRY
|
||||
from esphome.components import cover
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.components import cover
|
||||
from esphome.const import CONF_ASSUMED_STATE, CONF_CLOSE_ACTION, CONF_CURRENT_OPERATION, CONF_ID, \
|
||||
CONF_LAMBDA, CONF_NAME, CONF_OPEN_ACTION, CONF_OPTIMISTIC, CONF_POSITION, CONF_RESTORE_MODE, \
|
||||
CONF_LAMBDA, CONF_OPEN_ACTION, CONF_OPTIMISTIC, CONF_POSITION, CONF_RESTORE_MODE, \
|
||||
CONF_STATE, CONF_STOP_ACTION
|
||||
from .. import template_ns
|
||||
|
||||
|
||||
TemplateCover = template_ns.class_('TemplateCover', cover.Cover)
|
||||
|
||||
TemplateCoverRestoreMode = template_ns.enum('TemplateCoverRestoreMode')
|
||||
@@ -18,20 +16,20 @@ RESTORE_MODES = {
|
||||
'RESTORE_AND_CALL': TemplateCoverRestoreMode.COVER_RESTORE_AND_CALL,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = cv.nameable(cover.COVER_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(TemplateCover),
|
||||
CONFIG_SCHEMA = cover.COVER_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(TemplateCover),
|
||||
cv.Optional(CONF_LAMBDA): cv.lambda_,
|
||||
cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
|
||||
cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean,
|
||||
cv.Optional(CONF_OPEN_ACTION): automation.validate_automation(single=True),
|
||||
cv.Optional(CONF_CLOSE_ACTION): automation.validate_automation(single=True),
|
||||
cv.Optional(CONF_STOP_ACTION): automation.validate_automation(single=True),
|
||||
cv.Optional(CONF_RESTORE_MODE, default='RESTORE'): cv.one_of(*RESTORE_MODES, upper=True),
|
||||
}).extend(cv.COMPONENT_SCHEMA))
|
||||
cv.Optional(CONF_RESTORE_MODE, default='RESTORE'): cv.enum(RESTORE_MODES, upper=True),
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME])
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield cover.register_cover(var, config)
|
||||
if CONF_LAMBDA in config:
|
||||
@@ -47,29 +45,25 @@ def to_code(config):
|
||||
|
||||
cg.add(var.set_optimistic(config[CONF_OPTIMISTIC]))
|
||||
cg.add(var.set_assumed_state(config[CONF_ASSUMED_STATE]))
|
||||
cg.add(var.set_restore_mode(RESTORE_MODES[config[CONF_RESTORE_MODE]]))
|
||||
cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE]))
|
||||
|
||||
|
||||
@ACTION_REGISTRY.register('cover.template.publish', cv.Schema({
|
||||
cv.Required(CONF_ID): cv.use_variable_id(cover.Cover),
|
||||
@automation.register_action('cover.template.publish', cover.CoverPublishAction, cv.Schema({
|
||||
cv.Required(CONF_ID): cv.use_id(cover.Cover),
|
||||
cv.Exclusive(CONF_STATE, 'pos'): cv.templatable(cover.validate_cover_state),
|
||||
cv.Exclusive(CONF_POSITION, 'pos'): cv.templatable(cv.zero_to_one_float),
|
||||
cv.Optional(CONF_CURRENT_OPERATION): cv.templatable(cover.validate_cover_operation),
|
||||
}))
|
||||
def cover_template_publish_to_code(config, action_id, template_arg, args):
|
||||
var = yield cg.get_variable(config[CONF_ID])
|
||||
type = cover.CoverPublishAction.template(template_arg)
|
||||
rhs = type.new(var)
|
||||
action = cg.Pvariable(action_id, rhs, type=type)
|
||||
paren = yield cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
if CONF_STATE in config:
|
||||
template_ = yield cg.templatable(config[CONF_STATE], args, float, to_exp=cover.COVER_STATES)
|
||||
cg.add(action.set_position(template_))
|
||||
template_ = yield cg.templatable(config[CONF_STATE], args, float)
|
||||
cg.add(var.set_position(template_))
|
||||
if CONF_POSITION in config:
|
||||
template_ = yield cg.templatable(config[CONF_POSITION], args, float,
|
||||
to_exp=cover.COVER_STATES)
|
||||
cg.add(action.set_position(template_))
|
||||
template_ = yield cg.templatable(config[CONF_POSITION], args, float)
|
||||
cg.add(var.set_position(template_))
|
||||
if CONF_CURRENT_OPERATION in config:
|
||||
template_ = yield cg.templatable(config[CONF_CURRENT_OPERATION], args,
|
||||
cover.CoverOperation, to_exp=cover.COVER_OPERATIONS)
|
||||
cg.add(action.set_current_operation(template_))
|
||||
yield action
|
||||
template_ = yield cg.templatable(config[CONF_CURRENT_OPERATION], args, cover.CoverOperation)
|
||||
cg.add(var.set_current_operation(template_))
|
||||
yield var
|
||||
|
||||
@@ -8,9 +8,8 @@ using namespace esphome::cover;
|
||||
|
||||
static const char *TAG = "template.cover";
|
||||
|
||||
TemplateCover::TemplateCover(const std::string &name)
|
||||
: Cover(name),
|
||||
open_trigger_(new Trigger<>()),
|
||||
TemplateCover::TemplateCover()
|
||||
: open_trigger_(new Trigger<>()),
|
||||
close_trigger_(new Trigger<>),
|
||||
stop_trigger_(new Trigger<>()),
|
||||
position_trigger_(new Trigger<float>()),
|
||||
|
||||
@@ -15,7 +15,7 @@ enum TemplateCoverRestoreMode {
|
||||
|
||||
class TemplateCover : public cover::Cover, public Component {
|
||||
public:
|
||||
explicit TemplateCover(const std::string &name);
|
||||
TemplateCover();
|
||||
|
||||
void set_state_lambda(std::function<optional<float>()> &&f);
|
||||
Trigger<> *get_open_trigger() const;
|
||||
|
||||
@@ -1,45 +1,37 @@
|
||||
|
||||
from esphome.automation import ACTION_REGISTRY
|
||||
from esphome.components import sensor
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_STATE, CONF_UPDATE_INTERVAL
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.components import sensor
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE, UNIT_EMPTY, ICON_EMPTY
|
||||
from .. import template_ns
|
||||
|
||||
TemplateSensor = template_ns.class_('TemplateSensor', sensor.PollingSensorComponent)
|
||||
|
||||
CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(TemplateSensor),
|
||||
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1).extend({
|
||||
cv.GenerateID(): cv.declare_id(TemplateSensor),
|
||||
cv.Optional(CONF_LAMBDA): cv.lambda_,
|
||||
cv.Optional(CONF_UPDATE_INTERVAL, default="60s"): cv.update_interval,
|
||||
}).extend(cv.COMPONENT_SCHEMA))
|
||||
}).extend(cv.polling_component_schema('60s'))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
rhs = TemplateSensor.new(config[CONF_NAME], config[CONF_UPDATE_INTERVAL])
|
||||
template = cg.Pvariable(config[CONF_ID], rhs)
|
||||
yield cg.register_component(template, config)
|
||||
yield sensor.register_sensor(template, config)
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield sensor.register_sensor(var, config)
|
||||
|
||||
if CONF_LAMBDA in config:
|
||||
template_ = yield cg.process_lambda(config[CONF_LAMBDA], [],
|
||||
return_type=cg.optional.template(float))
|
||||
cg.add(template.set_template(template_))
|
||||
cg.add(var.set_template(template_))
|
||||
|
||||
|
||||
CONF_SENSOR_TEMPLATE_PUBLISH = 'sensor.template.publish'
|
||||
SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA = cv.Schema({
|
||||
cv.Required(CONF_ID): cv.use_variable_id(sensor.Sensor),
|
||||
cv.Required(CONF_STATE): cv.templatable(cv.float_),
|
||||
})
|
||||
|
||||
|
||||
@ACTION_REGISTRY.register(CONF_SENSOR_TEMPLATE_PUBLISH, SENSOR_TEMPLATE_PUBLISH_ACTION_SCHEMA)
|
||||
@automation.register_action('sensor.template.publish', sensor.SensorPublishAction,
|
||||
cv.Schema({
|
||||
cv.Required(CONF_ID): cv.use_id(sensor.Sensor),
|
||||
cv.Required(CONF_STATE): cv.templatable(cv.float_),
|
||||
}))
|
||||
def sensor_template_publish_to_code(config, action_id, template_arg, args):
|
||||
var = yield cg.get_variable(config[CONF_ID])
|
||||
type = sensor.SensorPublishAction.template(template_arg)
|
||||
rhs = type.new(var)
|
||||
action = cg.Pvariable(action_id, rhs, type=type)
|
||||
paren = yield cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = yield cg.templatable(config[CONF_STATE], args, float)
|
||||
cg.add(action.set_state(template_))
|
||||
yield action
|
||||
cg.add(var.set_state(template_))
|
||||
yield var
|
||||
|
||||
@@ -6,8 +6,6 @@ namespace template_ {
|
||||
|
||||
static const char *TAG = "template.sensor";
|
||||
|
||||
TemplateSensor::TemplateSensor(const std::string &name, uint32_t update_interval)
|
||||
: PollingSensorComponent(name, update_interval) {}
|
||||
void TemplateSensor::update() {
|
||||
if (!this->f_.has_value())
|
||||
return;
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
namespace esphome {
|
||||
namespace template_ {
|
||||
|
||||
class TemplateSensor : public sensor::PollingSensorComponent {
|
||||
class TemplateSensor : public sensor::Sensor, public PollingComponent {
|
||||
public:
|
||||
TemplateSensor(const std::string &name, uint32_t update_interval);
|
||||
|
||||
void set_template(std::function<optional<float>()> &&f);
|
||||
|
||||
void update() override;
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.automation import ACTION_REGISTRY
|
||||
from esphome.components import switch
|
||||
from esphome.const import CONF_ASSUMED_STATE, CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_OPTIMISTIC, \
|
||||
from esphome.const import CONF_ASSUMED_STATE, CONF_ID, CONF_LAMBDA, CONF_OPTIMISTIC, \
|
||||
CONF_RESTORE_STATE, CONF_STATE, CONF_TURN_OFF_ACTION, CONF_TURN_ON_ACTION
|
||||
from .. import template_ns
|
||||
|
||||
TemplateSwitch = template_ns.class_('TemplateSwitch', switch.Switch, cg.Component)
|
||||
|
||||
CONFIG_SCHEMA = cv.nameable(switch.SWITCH_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(TemplateSwitch),
|
||||
CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(TemplateSwitch),
|
||||
cv.Optional(CONF_LAMBDA): cv.lambda_,
|
||||
cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
|
||||
cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean,
|
||||
cv.Optional(CONF_TURN_OFF_ACTION): automation.validate_automation(single=True),
|
||||
cv.Optional(CONF_TURN_ON_ACTION): automation.validate_automation(single=True),
|
||||
cv.Optional(CONF_RESTORE_STATE, default=False): cv.boolean,
|
||||
}).extend(cv.COMPONENT_SCHEMA))
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME])
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield switch.register_switch(var, config)
|
||||
|
||||
@@ -40,15 +39,13 @@ def to_code(config):
|
||||
cg.add(var.set_restore_state(config[CONF_RESTORE_STATE]))
|
||||
|
||||
|
||||
@ACTION_REGISTRY.register('switch.template.publish', cv.Schema({
|
||||
cv.Required(CONF_ID): cv.use_variable_id(switch.Switch),
|
||||
@automation.register_action('switch.template.publish', switch.SwitchPublishAction, cv.Schema({
|
||||
cv.Required(CONF_ID): cv.use_id(switch.Switch),
|
||||
cv.Required(CONF_STATE): cv.templatable(cv.boolean),
|
||||
}))
|
||||
def switch_template_publish_to_code(config, action_id, template_arg, args):
|
||||
var = yield cg.get_variable(config[CONF_ID])
|
||||
type = switch.SwitchPublishAction.template(template_arg)
|
||||
rhs = type.new(var)
|
||||
action = cg.Pvariable(action_id, rhs, type=type)
|
||||
paren = yield cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = yield cg.templatable(config[CONF_STATE], args, bool)
|
||||
cg.add(action.set_state(template_))
|
||||
yield action
|
||||
cg.add(var.set_state(template_))
|
||||
yield var
|
||||
|
||||
@@ -6,8 +6,8 @@ namespace template_ {
|
||||
|
||||
static const char *TAG = "template.switch";
|
||||
|
||||
TemplateSwitch::TemplateSwitch(const std::string &name)
|
||||
: switch_::Switch(name), Component(), turn_on_trigger_(new Trigger<>()), turn_off_trigger_(new Trigger<>()) {}
|
||||
TemplateSwitch::TemplateSwitch() : turn_on_trigger_(new Trigger<>()), turn_off_trigger_(new Trigger<>()) {}
|
||||
|
||||
void TemplateSwitch::loop() {
|
||||
if (!this->f_.has_value())
|
||||
return;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace template_ {
|
||||
|
||||
class TemplateSwitch : public switch_::Switch, public Component {
|
||||
public:
|
||||
explicit TemplateSwitch(const std::string &name);
|
||||
TemplateSwitch();
|
||||
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
from esphome.automation import ACTION_REGISTRY
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.components import text_sensor
|
||||
from esphome.components.text_sensor import TextSensorPublishAction
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_STATE, CONF_UPDATE_INTERVAL
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE
|
||||
from .. import template_ns
|
||||
|
||||
|
||||
TemplateTextSensor = template_ns.class_('TemplateTextSensor', text_sensor.TextSensor,
|
||||
cg.PollingComponent)
|
||||
|
||||
CONFIG_SCHEMA = cv.nameable(text_sensor.TEXT_SENSOR_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_variable_id(TemplateTextSensor),
|
||||
CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(TemplateTextSensor),
|
||||
cv.Optional(CONF_LAMBDA): cv.lambda_,
|
||||
cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval,
|
||||
}).extend(cv.COMPONENT_SCHEMA))
|
||||
}).extend(cv.polling_component_schema('60s'))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], config[CONF_UPDATE_INTERVAL])
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield text_sensor.register_text_sensor(var, config)
|
||||
|
||||
@@ -28,15 +26,13 @@ def to_code(config):
|
||||
cg.add(var.set_template(template_))
|
||||
|
||||
|
||||
@ACTION_REGISTRY.register('text_sensor.template.publish', cv.Schema({
|
||||
cv.Required(CONF_ID): cv.use_variable_id(text_sensor.TextSensor),
|
||||
@automation.register_action('text_sensor.template.publish', TextSensorPublishAction, cv.Schema({
|
||||
cv.Required(CONF_ID): cv.use_id(text_sensor.TextSensor),
|
||||
cv.Required(CONF_STATE): cv.templatable(cv.string_strict),
|
||||
}))
|
||||
def text_sensor_template_publish_to_code(config, action_id, template_arg, args):
|
||||
var = yield cg.get_variable(config[CONF_ID])
|
||||
type = TextSensorPublishAction.template(template_arg)
|
||||
rhs = type.new(var)
|
||||
action = cg.Pvariable(action_id, rhs, type=type)
|
||||
paren = yield cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = yield cg.templatable(config[CONF_STATE], args, cg.std_string)
|
||||
cg.add(action.set_state(template_))
|
||||
yield action
|
||||
cg.add(var.set_state(template_))
|
||||
yield var
|
||||
|
||||
@@ -6,8 +6,6 @@ namespace template_ {
|
||||
|
||||
static const char *TAG = "template.text_sensor";
|
||||
|
||||
TemplateTextSensor::TemplateTextSensor(const std::string &name, uint32_t update_interval)
|
||||
: TextSensor(name), PollingComponent(update_interval) {}
|
||||
void TemplateTextSensor::update() {
|
||||
if (!this->f_.has_value())
|
||||
return;
|
||||
|
||||
@@ -9,8 +9,6 @@ namespace template_ {
|
||||
|
||||
class TemplateTextSensor : public text_sensor::TextSensor, public PollingComponent {
|
||||
public:
|
||||
TemplateTextSensor(const std::string &name, uint32_t update_interval);
|
||||
|
||||
void set_template(std::function<optional<std::string>()> &&f);
|
||||
|
||||
void update() override;
|
||||
|
||||
Reference in New Issue
Block a user