Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
988cd4a72f | |||
d1ea916781 | |||
ce9f25b86c | |||
f29762c931 | |||
30e4496ef1 | |||
7f9dc5dd3a | |||
0f6babc243 | |||
6a43e04b31 | |||
36fa5a50c4 | |||
9ad6d92ccd | |||
fafa8f43f4 | |||
9b490d33d5 | |||
33f9a1075e | |||
b83006e2c3 | |||
ba09c36bd2 | |||
c71ee568b0 | |||
75041f5c23 | |||
14da471774 | |||
369b44f1c8 | |||
8284bb6e76 | |||
9b3b4dfbbc | |||
5ca4424933 | |||
a308aa29a4 | |||
9e80b0eaaf | |||
85379cf491 |
@ -1,11 +1,11 @@
|
|||||||
part of 'main.dart';
|
part of 'main.dart';
|
||||||
|
|
||||||
class HACard extends StatelessWidget {
|
class CardWidget extends StatelessWidget {
|
||||||
|
|
||||||
final List<Entity> entities;
|
final List<Entity> entities;
|
||||||
final String friendlyName;
|
final String friendlyName;
|
||||||
|
|
||||||
const HACard({
|
const CardWidget({
|
||||||
Key key,
|
Key key,
|
||||||
this.entities,
|
this.entities,
|
||||||
this.friendlyName
|
this.friendlyName
|
||||||
@ -13,6 +13,13 @@ class HACard extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final entityModel = EntityModel.of(context);
|
||||||
|
if (entityModel != null) {
|
||||||
|
final groupEntity = entityModel.entity;
|
||||||
|
if ((groupEntity!= null) && (groupEntity.isHidden)) {
|
||||||
|
return Container(width: 0.0, height: 0.0,);
|
||||||
|
}
|
||||||
|
}
|
||||||
List<Widget> body = [];
|
List<Widget> body = [];
|
||||||
body.add(_buildCardHeader());
|
body.add(_buildCardHeader());
|
||||||
body.addAll(_buildCardBody(context));
|
body.addAll(_buildCardBody(context));
|
||||||
|
@ -17,7 +17,6 @@ class _EntityViewPageState extends State<EntityViewPage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
if (_stateSubscription != null) _stateSubscription.cancel();
|
|
||||||
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
|
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
|
||||||
if (event.entityId == widget.entity.entityId) {
|
if (event.entityId == widget.entity.entityId) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
|
@ -23,17 +23,18 @@ class Entity {
|
|||||||
"sensor"
|
"sensor"
|
||||||
];
|
];
|
||||||
|
|
||||||
double rightWidgetPadding = 14.0;
|
static const rightWidgetPadding = 14.0;
|
||||||
double leftWidgetPadding = 8.0;
|
static const leftWidgetPadding = 8.0;
|
||||||
double extendedWidgetHeight = 50.0;
|
static const extendedWidgetHeight = 50.0;
|
||||||
|
static const iconSize = 28.0;
|
||||||
|
static const stateFontSize = 16.0;
|
||||||
|
static const nameFontSize = 16.0;
|
||||||
|
static const smallFontSize = 14.0;
|
||||||
|
static const largeFontSize = 24.0;
|
||||||
|
static const inputWidth = 160.0;
|
||||||
|
static const rowPadding = 10.0;
|
||||||
|
|
||||||
double widgetHeight = 34.0;
|
double widgetHeight = 34.0;
|
||||||
double iconSize = 28.0;
|
|
||||||
double stateFontSize = 16.0;
|
|
||||||
double nameFontSize = 16.0;
|
|
||||||
double smallFontSize = 14.0;
|
|
||||||
double largeFontSize = 24.0;
|
|
||||||
double inputWidth = 160.0;
|
|
||||||
double rowPadding = 10.0;
|
|
||||||
|
|
||||||
Map attributes;
|
Map attributes;
|
||||||
String domain;
|
String domain;
|
||||||
@ -61,6 +62,7 @@ class Entity {
|
|||||||
String get unitOfMeasurement => attributes["unit_of_measurement"] ?? "";
|
String get unitOfMeasurement => attributes["unit_of_measurement"] ?? "";
|
||||||
List get childEntityIds => attributes["entity_id"] ?? [];
|
List get childEntityIds => attributes["entity_id"] ?? [];
|
||||||
String get lastUpdated => _getLastUpdatedFormatted();
|
String get lastUpdated => _getLastUpdatedFormatted();
|
||||||
|
bool get isHidden => attributes["hidden"] ?? false;
|
||||||
|
|
||||||
Entity(Map rawData) {
|
Entity(Map rawData) {
|
||||||
update(rawData);
|
update(rawData);
|
||||||
@ -82,14 +84,28 @@ class Entity {
|
|||||||
} else if (temp1 is double) {
|
} else if (temp1 is double) {
|
||||||
return temp1;
|
return temp1;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return double.tryParse("$temp1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getIntAttributeValue(String attributeName) {
|
||||||
|
var temp1 = attributes["$attributeName"];
|
||||||
|
if (temp1 is int) {
|
||||||
|
return temp1;
|
||||||
|
} else if (temp1 is double) {
|
||||||
|
return temp1.round();
|
||||||
|
} else {
|
||||||
|
return int.tryParse("$temp1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildDefaultWidget(BuildContext context) {
|
Widget buildDefaultWidget(BuildContext context) {
|
||||||
return EntityModel(
|
return EntityModel(
|
||||||
entity: this,
|
entity: this,
|
||||||
child: DefaultEntityContainer(state: _buildStatePart(context)),
|
child: DefaultEntityContainer(
|
||||||
|
state: _buildStatePart(context),
|
||||||
|
height: widgetHeight,
|
||||||
|
),
|
||||||
handleTap: true,
|
handleTap: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -113,7 +129,7 @@ class Entity {
|
|||||||
return EntityModel(
|
return EntityModel(
|
||||||
entity: this,
|
entity: this,
|
||||||
child: EntityPageContainer(children: <Widget>[
|
child: EntityPageContainer(children: <Widget>[
|
||||||
DefaultEntityContainer(state: _buildStatePartForPage(context)),
|
DefaultEntityContainer(state: _buildStatePartForPage(context), height: widgetHeight),
|
||||||
LastUpdatedWidget(),
|
LastUpdatedWidget(),
|
||||||
Divider(),
|
Divider(),
|
||||||
_buildAdditionalControlsForPage(context),
|
_buildAdditionalControlsForPage(context),
|
||||||
@ -174,7 +190,7 @@ class SwitchEntity extends Entity {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget _buildStatePart(BuildContext context) {
|
Widget _buildStatePart(BuildContext context) {
|
||||||
return SwitchControlWidget();
|
return SwitchStateWidget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +199,7 @@ class ButtonEntity extends Entity {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget _buildStatePart(BuildContext context) {
|
Widget _buildStatePart(BuildContext context) {
|
||||||
return ButtonControlWidget();
|
return ButtonStateWidget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +214,7 @@ class TextEntity extends Entity {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget _buildStatePart(BuildContext context) {
|
Widget _buildStatePart(BuildContext context) {
|
||||||
return TextControlWidget();
|
return TextInputStateWidget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +236,7 @@ class SliderEntity extends Entity {
|
|||||||
//width: 200.0,
|
//width: 200.0,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
SliderControlWidget(
|
SliderStateWidget(
|
||||||
expanded: true,
|
expanded: true,
|
||||||
),
|
),
|
||||||
SimpleEntityState(),
|
SimpleEntityState(),
|
||||||
@ -236,7 +252,7 @@ class SliderEntity extends Entity {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget _buildAdditionalControlsForPage(BuildContext context) {
|
Widget _buildAdditionalControlsForPage(BuildContext context) {
|
||||||
return SliderControlWidget(
|
return SliderStateWidget(
|
||||||
expanded: false,
|
expanded: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -446,8 +462,8 @@ class CoverEntity extends Entity {
|
|||||||
|
|
||||||
double get currentPosition => _getDoubleAttributeValue('current_position');
|
double get currentPosition => _getDoubleAttributeValue('current_position');
|
||||||
double get currentTiltPosition => _getDoubleAttributeValue('current_tilt_position');
|
double get currentTiltPosition => _getDoubleAttributeValue('current_tilt_position');
|
||||||
bool get canBeOpened => ((state == "closed") || (state == "closing") || (state == "opening"));
|
bool get canBeOpened => ((state != "opening") && (state != "open"));
|
||||||
bool get canBeClosed => ((state == "open") || (state == "opening")|| (state == "closing"));
|
bool get canBeClosed => ((state != "closing") && (state != "closed"));
|
||||||
bool get canTiltBeOpened => currentPosition < 100;
|
bool get canTiltBeOpened => currentPosition < 100;
|
||||||
bool get canTiltBeClosed => currentPosition > 0;
|
bool get canTiltBeClosed => currentPosition > 0;
|
||||||
|
|
||||||
@ -464,3 +480,83 @@ class CoverEntity extends Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LightEntity extends Entity {
|
||||||
|
|
||||||
|
static const SUPPORT_BRIGHTNESS = 1;
|
||||||
|
static const SUPPORT_COLOR_TEMP = 2;
|
||||||
|
static const SUPPORT_EFFECT = 4;
|
||||||
|
static const SUPPORT_FLASH = 8;
|
||||||
|
static const SUPPORT_COLOR = 16;
|
||||||
|
static const SUPPORT_TRANSITION = 32;
|
||||||
|
static const SUPPORT_WHITE_VALUE = 128;
|
||||||
|
|
||||||
|
bool get supportBrightness => ((attributes["supported_features"] &
|
||||||
|
LightEntity.SUPPORT_BRIGHTNESS) ==
|
||||||
|
LightEntity.SUPPORT_BRIGHTNESS);
|
||||||
|
bool get supportColorTemp => ((attributes["supported_features"] &
|
||||||
|
LightEntity.SUPPORT_COLOR_TEMP) ==
|
||||||
|
LightEntity.SUPPORT_COLOR_TEMP);
|
||||||
|
bool get supportEffect => ((attributes["supported_features"] &
|
||||||
|
LightEntity.SUPPORT_EFFECT) ==
|
||||||
|
LightEntity.SUPPORT_EFFECT);
|
||||||
|
bool get supportFlash => ((attributes["supported_features"] &
|
||||||
|
LightEntity.SUPPORT_FLASH) ==
|
||||||
|
LightEntity.SUPPORT_FLASH);
|
||||||
|
bool get supportColor => ((attributes["supported_features"] &
|
||||||
|
LightEntity.SUPPORT_COLOR) ==
|
||||||
|
LightEntity.SUPPORT_COLOR);
|
||||||
|
bool get supportTransition => ((attributes["supported_features"] &
|
||||||
|
LightEntity.SUPPORT_TRANSITION) ==
|
||||||
|
LightEntity.SUPPORT_TRANSITION);
|
||||||
|
bool get supportWhiteValue => ((attributes["supported_features"] &
|
||||||
|
LightEntity.SUPPORT_WHITE_VALUE) ==
|
||||||
|
LightEntity.SUPPORT_WHITE_VALUE);
|
||||||
|
|
||||||
|
int get brightness => _getIntAttributeValue("brightness");
|
||||||
|
int get colorTemp => _getIntAttributeValue("color_temp");
|
||||||
|
double get maxMireds => _getDoubleAttributeValue("max_mireds");
|
||||||
|
double get minMireds => _getDoubleAttributeValue("min_mireds");
|
||||||
|
Color get color => _getColor();
|
||||||
|
bool get isAdditionalControls => ((attributes["supported_features"] != null) && (attributes["supported_features"] != 0));
|
||||||
|
List<String> get effectList => _getEffectList();
|
||||||
|
|
||||||
|
LightEntity(Map rawData) : super(rawData);
|
||||||
|
|
||||||
|
Color _getColor() {
|
||||||
|
List rgb = attributes["rgb_color"];
|
||||||
|
try {
|
||||||
|
if ((rgb != null) && (rgb.length > 0)) {
|
||||||
|
return Color.fromARGB(255, rgb[0], rgb[1], rgb[2]);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> _getEffectList() {
|
||||||
|
if (attributes["effect_list"] != null) {
|
||||||
|
List<String> result = (attributes["effect_list"] as List).cast<String>();
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget _buildStatePart(BuildContext context) {
|
||||||
|
return SwitchStateWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget _buildAdditionalControlsForPage(BuildContext context) {
|
||||||
|
if (!isAdditionalControls) {
|
||||||
|
return Container(height: 0.0, width: 0.0);
|
||||||
|
} else {
|
||||||
|
return LightControlsWidget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
part of '../main.dart';
|
part of '../main.dart';
|
||||||
|
|
||||||
class SwitchControlWidget extends StatefulWidget {
|
class SwitchStateWidget extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_SwitchControlWidgetState createState() => _SwitchControlWidgetState();
|
_SwitchStateWidgetState createState() => _SwitchStateWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SwitchControlWidgetState extends State<SwitchControlWidget> {
|
class _SwitchStateWidgetState extends State<SwitchStateWidget> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -28,57 +28,46 @@ class _SwitchControlWidgetState extends State<SwitchControlWidget> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
final entityModel = EntityModel.of(context);
|
||||||
return Switch(
|
final entity = entityModel.entity;
|
||||||
value: entityModel.entity.assumedState == 'on',
|
if ((entity.attributes["assumed_state"] == null) || (entity.attributes["assumed_state"] == false)) {
|
||||||
onChanged: ((switchState) {
|
return Switch(
|
||||||
_setNewState(switchState, entityModel.entity);
|
value: entity.assumedState == 'on',
|
||||||
}),
|
onChanged: ((switchState) {
|
||||||
);
|
_setNewState(switchState, entity);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => _setNewState(false, entity),
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName("mdi:flash-off")),
|
||||||
|
color: entity.assumedState == 'on' ? Colors.black : Colors.blue,
|
||||||
|
iconSize: Entity.iconSize,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => _setNewState(true, entity),
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName("mdi:flash")),
|
||||||
|
color: entity.assumedState == 'on' ? Colors.blue : Colors.black,
|
||||||
|
iconSize: Entity.iconSize
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ButtonControlWidget extends StatefulWidget {
|
class TextInputStateWidget extends StatefulWidget {
|
||||||
|
|
||||||
|
TextInputStateWidget({Key key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ButtonControlWidgetState createState() => _ButtonControlWidgetState();
|
_TextInputStateWidgetState createState() => _TextInputStateWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ButtonControlWidgetState extends State<ButtonControlWidget> {
|
class _TextInputStateWidgetState extends State<TextInputStateWidget> {
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _setNewState(Entity entity) {
|
|
||||||
eventBus.fire(new ServiceCallEvent(entity.domain, "turn_on", entity.entityId, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final entityModel = EntityModel.of(context);
|
|
||||||
return FlatButton(
|
|
||||||
onPressed: (() {
|
|
||||||
_setNewState(entityModel.entity);
|
|
||||||
}),
|
|
||||||
child: Text(
|
|
||||||
"EXECUTE",
|
|
||||||
textAlign: TextAlign.right,
|
|
||||||
style:
|
|
||||||
new TextStyle(fontSize: entityModel.entity.stateFontSize, color: Colors.blue),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TextControlWidget extends StatefulWidget {
|
|
||||||
|
|
||||||
TextControlWidget({Key key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_TextControlWidgetState createState() => _TextControlWidgetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _TextControlWidgetState extends State<TextControlWidget> {
|
|
||||||
String _tmpValue;
|
String _tmpValue;
|
||||||
String _entityState;
|
String _entityState;
|
||||||
String _entityDomain;
|
String _entityDomain;
|
||||||
@ -167,17 +156,17 @@ class _TextControlWidgetState extends State<TextControlWidget> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SliderControlWidget extends StatefulWidget {
|
class SliderStateWidget extends StatefulWidget {
|
||||||
|
|
||||||
final bool expanded;
|
final bool expanded;
|
||||||
|
|
||||||
SliderControlWidget({Key key, @required this.expanded}) : super(key: key);
|
SliderStateWidget({Key key, @required this.expanded}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_SliderControlWidgetState createState() => _SliderControlWidgetState();
|
_SliderStateWidgetState createState() => _SliderStateWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SliderControlWidgetState extends State<SliderControlWidget> {
|
class _SliderStateWidgetState extends State<SliderStateWidget> {
|
||||||
int _multiplier = 1;
|
int _multiplier = 1;
|
||||||
|
|
||||||
void setNewState(newValue, domain, entityId) {
|
void setNewState(newValue, domain, entityId) {
|
||||||
@ -398,12 +387,13 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
_resetVars(entity);
|
_resetVars(entity);
|
||||||
}
|
}
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.fromLTRB(entity.leftWidgetPadding, entity.rowPadding, entity.rightWidgetPadding, 0.0),
|
padding: EdgeInsets.fromLTRB(Entity.leftWidgetPadding, Entity.rowPadding, Entity.rightWidgetPadding, 0.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
_buildOnOffControl(entity),
|
_buildOnOffControl(entity),
|
||||||
_buildTemperatureControls(entity),
|
_buildTemperatureControls(entity),
|
||||||
|
_buildTargetTemperatureControls(entity),
|
||||||
_buildHumidityControls(entity),
|
_buildHumidityControls(entity),
|
||||||
_buildOperationControl(entity),
|
_buildOperationControl(entity),
|
||||||
_buildFanControl(entity),
|
_buildFanControl(entity),
|
||||||
@ -417,21 +407,10 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
|
|
||||||
Widget _buildAwayModeControl(ClimateEntity entity) {
|
Widget _buildAwayModeControl(ClimateEntity entity) {
|
||||||
if (entity.supportAwayMode) {
|
if (entity.supportAwayMode) {
|
||||||
return Row(
|
return ModeSwitchWidget(
|
||||||
children: <Widget>[
|
caption: "Away mode",
|
||||||
Expanded(
|
onChange: (value) => _setAwayMode(entity, value),
|
||||||
child: Text(
|
value: _tmpAwayMode,
|
||||||
"Away mode",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: entity.stateFontSize
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Switch(
|
|
||||||
onChanged: (value) => _setAwayMode(entity, value),
|
|
||||||
value: _tmpAwayMode,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Container(height: 0.0, width: 0.0,);
|
return Container(height: 0.0, width: 0.0,);
|
||||||
@ -440,21 +419,10 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
|
|
||||||
Widget _buildOnOffControl(ClimateEntity entity) {
|
Widget _buildOnOffControl(ClimateEntity entity) {
|
||||||
if (entity.supportOnOff) {
|
if (entity.supportOnOff) {
|
||||||
return Row(
|
return ModeSwitchWidget(
|
||||||
children: <Widget>[
|
onChange: (value) => _setOnOf(entity, value),
|
||||||
Expanded(
|
caption: "On / Off",
|
||||||
child: Text(
|
value: !_tmpIsOff
|
||||||
"On / Off",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: entity.stateFontSize
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Switch(
|
|
||||||
onChanged: (value) => _setOnOf(entity, value),
|
|
||||||
value: !_tmpIsOff,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Container(height: 0.0, width: 0.0,);
|
return Container(height: 0.0, width: 0.0,);
|
||||||
@ -463,21 +431,10 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
|
|
||||||
Widget _buildAuxHeatControl(ClimateEntity entity) {
|
Widget _buildAuxHeatControl(ClimateEntity entity) {
|
||||||
if (entity.supportAuxHeat ) {
|
if (entity.supportAuxHeat ) {
|
||||||
return Row(
|
return ModeSwitchWidget(
|
||||||
children: <Widget>[
|
caption: "Aux heat",
|
||||||
Expanded(
|
onChange: (value) => _setAuxHeat(entity, value),
|
||||||
child: Text(
|
value: _tmpAuxHeat
|
||||||
"Aux heat",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: entity.stateFontSize
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Switch(
|
|
||||||
onChanged: (value) => _setAuxHeat(entity, value),
|
|
||||||
value: _tmpAuxHeat,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Container(height: 0.0, width: 0.0,);
|
return Container(height: 0.0, width: 0.0,);
|
||||||
@ -486,29 +443,11 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
|
|
||||||
Widget _buildOperationControl(ClimateEntity entity) {
|
Widget _buildOperationControl(ClimateEntity entity) {
|
||||||
if (entity.supportOperationMode) {
|
if (entity.supportOperationMode) {
|
||||||
return Column(
|
return ModeSelectorWidget(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
onChange: (mode) => _setOperationMode(entity, mode),
|
||||||
children: <Widget>[
|
options: entity.operationList,
|
||||||
Text("Operation", style: TextStyle(
|
caption: "Operation",
|
||||||
fontSize: entity.stateFontSize
|
value: _tmpOperationMode,
|
||||||
)),
|
|
||||||
DropdownButton<String>(
|
|
||||||
value: "$_tmpOperationMode",
|
|
||||||
iconSize: 30.0,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: entity.largeFontSize,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
items: entity.operationList.map((String value) {
|
|
||||||
return new DropdownMenuItem<String>(
|
|
||||||
value: value,
|
|
||||||
child: new Text(value),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
onChanged: (mode) => _setOperationMode(entity, mode),
|
|
||||||
),
|
|
||||||
Container(height: entity.rowPadding,)
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Container(height: 0.0, width: 0.0);
|
return Container(height: 0.0, width: 0.0);
|
||||||
@ -517,29 +456,11 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
|
|
||||||
Widget _buildFanControl(ClimateEntity entity) {
|
Widget _buildFanControl(ClimateEntity entity) {
|
||||||
if (entity.supportFanMode) {
|
if (entity.supportFanMode) {
|
||||||
return Column(
|
return ModeSelectorWidget(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
options: entity.fanList,
|
||||||
children: <Widget>[
|
onChange: (mode) => _setFanMode(entity, mode),
|
||||||
Text("Fan mode", style: TextStyle(
|
caption: "Fan mode",
|
||||||
fontSize: entity.stateFontSize
|
value: _tmpFanMode,
|
||||||
)),
|
|
||||||
DropdownButton<String>(
|
|
||||||
value: "$_tmpFanMode",
|
|
||||||
iconSize: 30.0,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: entity.largeFontSize,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
items: entity.fanList.map((String value) {
|
|
||||||
return new DropdownMenuItem<String>(
|
|
||||||
value: value,
|
|
||||||
child: new Text(value),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
onChanged: (mode) => _setFanMode(entity, mode),
|
|
||||||
),
|
|
||||||
Container(height: entity.rowPadding,)
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Container(height: 0.0, width: 0.0);
|
return Container(height: 0.0, width: 0.0);
|
||||||
@ -548,29 +469,11 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
|
|
||||||
Widget _buildSwingControl(ClimateEntity entity) {
|
Widget _buildSwingControl(ClimateEntity entity) {
|
||||||
if (entity.supportSwingMode) {
|
if (entity.supportSwingMode) {
|
||||||
return Column(
|
return ModeSelectorWidget(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
onChange: (mode) => _setSwingMode(entity, mode),
|
||||||
children: <Widget>[
|
options: entity.swingList,
|
||||||
Text("Swing mode", style: TextStyle(
|
value: _tmpSwingMode,
|
||||||
fontSize: entity.stateFontSize
|
caption: "Swing mode"
|
||||||
)),
|
|
||||||
DropdownButton<String>(
|
|
||||||
value: "$_tmpSwingMode",
|
|
||||||
iconSize: 30.0,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: entity.largeFontSize,
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
items: entity.swingList.map((String value) {
|
|
||||||
return new DropdownMenuItem<String>(
|
|
||||||
value: value,
|
|
||||||
child: new Text(value),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
onChanged: (mode) => _setSwingMode(entity, mode),
|
|
||||||
),
|
|
||||||
Container(height: entity.rowPadding,)
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Container(height: 0.0, width: 0.0);
|
return Container(height: 0.0, width: 0.0);
|
||||||
@ -578,139 +481,71 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTemperatureControls(ClimateEntity entity) {
|
Widget _buildTemperatureControls(ClimateEntity entity) {
|
||||||
List<Widget> result = [];
|
if ((entity.supportTargetTemperature) && (entity.temperature != null)) {
|
||||||
if (entity.supportTargetTemperature) {
|
|
||||||
result.addAll(<Widget>[
|
|
||||||
Text(
|
|
||||||
"$_tmpTemperature",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: entity.largeFontSize,
|
|
||||||
color: _showPending ? Colors.red : Colors.black
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: <Widget>[
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-up')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _temperatureUp(entity, 0.1),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-down')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _temperatureDown(entity, 0.1),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: <Widget>[
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-up')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _temperatureUp(entity, 0.5),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-down')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _temperatureDown(entity, 0.5),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
} else if (entity.supportTargetTemperatureHigh && entity.supportTargetTemperatureLow) {
|
|
||||||
result.addAll(<Widget>[
|
|
||||||
Text(
|
|
||||||
"$_tmpTargetLow",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: entity.largeFontSize,
|
|
||||||
color: _showPending ? Colors.red : Colors.black
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: <Widget>[
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-up')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _targetLowUp(entity, 0.1),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-down')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _targetLowDown(entity, 0.1),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: <Widget>[
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-up')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _targetLowUp(entity, 0.5),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-down')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _targetLowDown(entity, 0.5),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Container(height: 10.0),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"$_tmpTargetHigh",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: entity.largeFontSize,
|
|
||||||
color: _showPending ? Colors.red : Colors.black
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: <Widget>[
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-up')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _targetHighUp(entity, 0.1),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-down')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _targetHighDown(entity, 0.1),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: <Widget>[
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-up')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _targetHighUp(entity, 0.5),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName('mdi:chevron-double-down')),
|
|
||||||
iconSize: 30.0,
|
|
||||||
onPressed: () => _targetHighDown(entity, 0.5),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
} else if (entity.supportTargetTemperatureHigh || entity.supportTargetTemperatureLow) {
|
|
||||||
result.add(Text("Unsupported temperature control. Please, report an issue."));
|
|
||||||
}
|
|
||||||
if (result.isNotEmpty) {
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text("Target temperature", style: TextStyle(
|
Text("Target temperature", style: TextStyle(
|
||||||
fontSize: entity.stateFontSize
|
fontSize: Entity.stateFontSize
|
||||||
)),
|
)),
|
||||||
Row(
|
TemperatureControlWidget(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
value: _tmpTemperature,
|
||||||
children: result,
|
fontColor: _showPending ? Colors.red : Colors.black,
|
||||||
|
onLargeDec: () => _temperatureDown(entity, 0.5),
|
||||||
|
onLargeInc: () => _temperatureUp(entity, 0.5),
|
||||||
|
onSmallDec: () => _temperatureDown(entity, 0.1),
|
||||||
|
onSmallInc: () => _temperatureUp(entity, 0.1),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Container(height: 0.0, width: 0.0,);
|
return Container(width: 0.0, height: 0.0,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTargetTemperatureControls(ClimateEntity entity) {
|
||||||
|
List<Widget> controls = [];
|
||||||
|
if ((entity.supportTargetTemperatureLow) && (entity.targetLow != null)) {
|
||||||
|
controls.addAll(<Widget>[
|
||||||
|
TemperatureControlWidget(
|
||||||
|
value: _tmpTargetLow,
|
||||||
|
fontColor: _showPending ? Colors.red : Colors.black,
|
||||||
|
onLargeDec: () => _targetLowDown(entity, 0.5),
|
||||||
|
onLargeInc: () => _targetLowUp(entity, 0.5),
|
||||||
|
onSmallDec: () => _targetLowDown(entity, 0.1),
|
||||||
|
onSmallInc: () => _targetLowUp(entity, 0.1),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(height: 10.0),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if ((entity.supportTargetTemperatureHigh) && (entity.targetHigh != null)) {
|
||||||
|
controls.add(
|
||||||
|
TemperatureControlWidget(
|
||||||
|
value: _tmpTargetHigh,
|
||||||
|
fontColor: _showPending ? Colors.red : Colors.black,
|
||||||
|
onLargeDec: () => _targetHighDown(entity, 0.5),
|
||||||
|
onLargeInc: () => _targetHighUp(entity, 0.5),
|
||||||
|
onSmallDec: () => _targetHighDown(entity, 0.1),
|
||||||
|
onSmallInc: () => _targetHighUp(entity, 0.1),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (controls.isNotEmpty) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Text("Target temperature range", style: TextStyle(
|
||||||
|
fontSize: Entity.stateFontSize
|
||||||
|
)),
|
||||||
|
Row(
|
||||||
|
children: controls,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container(width: 0.0, height: 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,7 +555,7 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
result.addAll(<Widget>[
|
result.addAll(<Widget>[
|
||||||
Text(
|
Text(
|
||||||
"$_tmpTargetHumidity%",
|
"$_tmpTargetHumidity%",
|
||||||
style: TextStyle(fontSize: entity.largeFontSize),
|
style: TextStyle(fontSize: Entity.largeFontSize),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Slider(
|
child: Slider(
|
||||||
@ -744,9 +579,9 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(
|
padding: EdgeInsets.fromLTRB(
|
||||||
0.0, entity.rowPadding, 0.0, entity.rowPadding),
|
0.0, Entity.rowPadding, 0.0, Entity.rowPadding),
|
||||||
child: Text("Target humidity", style: TextStyle(
|
child: Text("Target humidity", style: TextStyle(
|
||||||
fontSize: entity.stateFontSize
|
fontSize: Entity.stateFontSize
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
@ -754,7 +589,7 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
|||||||
children: result,
|
children: result,
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
height: entity.rowPadding,
|
height: Entity.rowPadding,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -859,13 +694,14 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
final entityModel = EntityModel.of(context);
|
||||||
final CoverEntity entity = entityModel.entity;
|
final CoverEntity entity = entityModel.entity;
|
||||||
|
TheLogger.log("debug", "${entity.state}");
|
||||||
if (_changedHere) {
|
if (_changedHere) {
|
||||||
_changedHere = false;
|
_changedHere = false;
|
||||||
} else {
|
} else {
|
||||||
_resetVars(entity);
|
_resetVars(entity);
|
||||||
}
|
}
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.fromLTRB(entity.leftWidgetPadding, entity.rowPadding, entity.rightWidgetPadding, 0.0),
|
padding: EdgeInsets.fromLTRB(Entity.leftWidgetPadding, Entity.rowPadding, Entity.rightWidgetPadding, 0.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
@ -883,9 +719,9 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.fromLTRB(
|
padding: EdgeInsets.fromLTRB(
|
||||||
0.0, entity.rowPadding, 0.0, entity.rowPadding),
|
0.0, Entity.rowPadding, 0.0, Entity.rowPadding),
|
||||||
child: Text("Position", style: TextStyle(
|
child: Text("Position", style: TextStyle(
|
||||||
fontSize: entity.stateFontSize
|
fontSize: Entity.stateFontSize
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
Slider(
|
Slider(
|
||||||
@ -901,7 +737,7 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
|
|||||||
},
|
},
|
||||||
onChangeEnd: (double value) => _setNewPosition(entity, value),
|
onChangeEnd: (double value) => _setNewPosition(entity, value),
|
||||||
),
|
),
|
||||||
Container(height: entity.rowPadding,)
|
Container(height: Entity.rowPadding,)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -913,7 +749,7 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
|
|||||||
List<Widget> controls = [];
|
List<Widget> controls = [];
|
||||||
if (entity.supportCloseTilt || entity.supportOpenTilt || entity.supportStopTilt) {
|
if (entity.supportCloseTilt || entity.supportOpenTilt || entity.supportStopTilt) {
|
||||||
controls.add(
|
controls.add(
|
||||||
CoverEntityTiltControlState()
|
CoverEntityTiltControlButtons()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (entity.supportSetTiltPosition) {
|
if (entity.supportSetTiltPosition) {
|
||||||
@ -931,15 +767,15 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
|
|||||||
},
|
},
|
||||||
onChangeEnd: (double value) => _setNewTiltPosition(entity, value),
|
onChangeEnd: (double value) => _setNewTiltPosition(entity, value),
|
||||||
),
|
),
|
||||||
Container(height: entity.rowPadding,)
|
Container(height: Entity.rowPadding,)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if (controls.isNotEmpty) {
|
if (controls.isNotEmpty) {
|
||||||
controls.insert(0, Padding(
|
controls.insert(0, Padding(
|
||||||
padding: EdgeInsets.fromLTRB(
|
padding: EdgeInsets.fromLTRB(
|
||||||
0.0, entity.rowPadding, 0.0, entity.rowPadding),
|
0.0, Entity.rowPadding, 0.0, Entity.rowPadding),
|
||||||
child: Text("Tilt position", style: TextStyle(
|
child: Text("Tilt position", style: TextStyle(
|
||||||
fontSize: entity.stateFontSize
|
fontSize: Entity.stateFontSize
|
||||||
)),
|
)),
|
||||||
));
|
));
|
||||||
return Column(
|
return Column(
|
||||||
@ -951,4 +787,243 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class LightControlsWidget extends StatefulWidget {
|
||||||
|
|
||||||
|
@override
|
||||||
|
_LightControlsWidgetState createState() => _LightControlsWidgetState();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LightControlsWidgetState extends State<LightControlsWidget> {
|
||||||
|
|
||||||
|
int _tmpBrightness;
|
||||||
|
int _tmpColorTemp;
|
||||||
|
Color _tmpColor;
|
||||||
|
bool _changedHere = false;
|
||||||
|
String _tmpEffect;
|
||||||
|
|
||||||
|
void _resetState(LightEntity entity) {
|
||||||
|
_tmpBrightness = entity.brightness ?? 0;
|
||||||
|
_tmpColorTemp = entity.colorTemp;
|
||||||
|
_tmpColor = entity.color;
|
||||||
|
_tmpEffect = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setBrightness(LightEntity entity, double value) {
|
||||||
|
setState(() {
|
||||||
|
_tmpBrightness = value.round();
|
||||||
|
_changedHere = true;
|
||||||
|
if (_tmpBrightness > 0) {
|
||||||
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "turn_on", entity.entityId,
|
||||||
|
{"brightness": _tmpBrightness}));
|
||||||
|
} else {
|
||||||
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "turn_off", entity.entityId,
|
||||||
|
null));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setColorTemp(LightEntity entity, double value) {
|
||||||
|
setState(() {
|
||||||
|
_tmpColorTemp = value.round();
|
||||||
|
_changedHere = true;
|
||||||
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "turn_on", entity.entityId,
|
||||||
|
{"color_temp": _tmpColorTemp}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setColor(LightEntity entity, Color color) {
|
||||||
|
setState(() {
|
||||||
|
_tmpColor = color;
|
||||||
|
_changedHere = true;
|
||||||
|
TheLogger.log("Debug", "Color: [${color.red}, ${color.green}, ${color.blue}]");
|
||||||
|
if ((color == Colors.black) || ((color.red == color.green) && (color.green == color.blue))) {
|
||||||
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "turn_off", entity.entityId,
|
||||||
|
null));
|
||||||
|
} else {
|
||||||
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "turn_on", entity.entityId,
|
||||||
|
{"rgb_color": [color.red, color.green, color.blue]}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setEffect(LightEntity entity, String value) {
|
||||||
|
setState(() {
|
||||||
|
_tmpEffect = value;
|
||||||
|
_changedHere = true;
|
||||||
|
if (_tmpEffect != null) {
|
||||||
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "turn_on", entity.entityId,
|
||||||
|
{"effect": "$value"}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final entityModel = EntityModel.of(context);
|
||||||
|
final LightEntity entity = entityModel.entity;
|
||||||
|
if (!_changedHere) {
|
||||||
|
_resetState(entity);
|
||||||
|
} else {
|
||||||
|
_changedHere = false;
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
_buildBrightnessControl(entity),
|
||||||
|
_buildColorTempControl(entity),
|
||||||
|
_buildColorControl(entity),
|
||||||
|
_buildEffectControl(entity)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildBrightnessControl(LightEntity entity) {
|
||||||
|
if ((entity.supportBrightness) && (_tmpBrightness != null)) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Container(height: Entity.rowPadding,),
|
||||||
|
Text(
|
||||||
|
"Brightness",
|
||||||
|
style: TextStyle(fontSize: Entity.stateFontSize),
|
||||||
|
),
|
||||||
|
Container(height: Entity.rowPadding,),
|
||||||
|
Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Icon(Icons.brightness_5),
|
||||||
|
Expanded(
|
||||||
|
child: Slider(
|
||||||
|
value: _tmpBrightness.toDouble(),
|
||||||
|
min: 0.0,
|
||||||
|
max: 255.0,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_changedHere = true;
|
||||||
|
_tmpBrightness = value.round();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onChangeEnd: (value) => _setBrightness(entity, value),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Container(height: Entity.rowPadding,)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container(width: 0.0, height: 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildColorTempControl(LightEntity entity) {
|
||||||
|
if ((entity.supportColorTemp) && (_tmpColorTemp != null)) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Container(height: Entity.rowPadding,),
|
||||||
|
Text(
|
||||||
|
"Color temperature",
|
||||||
|
style: TextStyle(fontSize: Entity.stateFontSize),
|
||||||
|
),
|
||||||
|
Container(height: Entity.rowPadding,),
|
||||||
|
Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Text("Cold", style: TextStyle(color: Colors.lightBlue),),
|
||||||
|
Expanded(
|
||||||
|
child: Slider(
|
||||||
|
value: _tmpColorTemp.toDouble(),
|
||||||
|
min: entity.minMireds,
|
||||||
|
max: entity.maxMireds,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_changedHere = true;
|
||||||
|
_tmpColorTemp = value.round();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onChangeEnd: (value) => _setColorTemp(entity, value),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text("Warm", style: TextStyle(color: Colors.amberAccent),),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Container(height: Entity.rowPadding,)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container(width: 0.0, height: 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildColorControl(LightEntity entity) {
|
||||||
|
if ((entity.supportColor) && (entity.color != null)) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Container(height: Entity.rowPadding,),
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _showColorPicker(entity),
|
||||||
|
color: _tmpColor ?? Colors.black45,
|
||||||
|
child: Text(
|
||||||
|
"COLOR",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 50.0,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.black12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(height: 2*Entity.rowPadding,),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container(width: 0.0, height: 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showColorPicker(LightEntity entity) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
titlePadding: EdgeInsets.all(0.0),
|
||||||
|
contentPadding: EdgeInsets.all(0.0),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: MaterialPicker(
|
||||||
|
pickerColor: _tmpColor,
|
||||||
|
onColorChanged: (color) {
|
||||||
|
_setColor(entity, color);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
enableLabel: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildEffectControl(LightEntity entity) {
|
||||||
|
if ((entity.supportEffect) && (entity.effectList != null)) {
|
||||||
|
return ModeSelectorWidget(
|
||||||
|
onChange: (effect) => _setEffect(entity, effect),
|
||||||
|
caption: "Effect",
|
||||||
|
options: entity.effectList,
|
||||||
|
value: _tmpEffect
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container(width: 0.0, height: 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,11 +1,8 @@
|
|||||||
part of '../main.dart';
|
part of '../main.dart';
|
||||||
|
|
||||||
class EntityWidgetsSizes {
|
class EntityWidgetsSizes {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class EntityModel extends InheritedWidget {
|
class EntityModel extends InheritedWidget {
|
||||||
|
|
||||||
const EntityModel({
|
const EntityModel({
|
||||||
Key key,
|
Key key,
|
||||||
@required this.entity,
|
@required this.entity,
|
||||||
@ -24,23 +21,22 @@ class EntityModel extends InheritedWidget {
|
|||||||
bool updateShouldNotify(InheritedWidget oldWidget) {
|
bool updateShouldNotify(InheritedWidget oldWidget) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DefaultEntityContainer extends StatelessWidget {
|
class DefaultEntityContainer extends StatelessWidget {
|
||||||
|
|
||||||
DefaultEntityContainer({
|
DefaultEntityContainer({
|
||||||
Key key,
|
Key key,
|
||||||
@required this.state,
|
@required this.state,
|
||||||
|
@required this.height
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
final Widget state;
|
final Widget state;
|
||||||
|
final double height;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: entityModel.entity.widgetHeight,
|
height: height,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
EntityIcon(),
|
EntityIcon(),
|
||||||
@ -52,11 +48,9 @@ class DefaultEntityContainer extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class EntityPageContainer extends StatelessWidget {
|
class EntityPageContainer extends StatelessWidget {
|
||||||
|
|
||||||
EntityPageContainer({Key key, @required this.children}) : super(key: key);
|
EntityPageContainer({Key key, @required this.children}) : super(key: key);
|
||||||
|
|
||||||
final List<Widget> children;
|
final List<Widget> children;
|
||||||
@ -67,33 +61,30 @@ class EntityPageContainer extends StatelessWidget {
|
|||||||
children: children,
|
children: children,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SimpleEntityState extends StatelessWidget {
|
class SimpleEntityState extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
final entityModel = EntityModel.of(context);
|
||||||
return Padding(
|
return Padding(
|
||||||
padding:
|
padding: EdgeInsets.fromLTRB(
|
||||||
EdgeInsets.fromLTRB(0.0, 0.0, entityModel.entity.rightWidgetPadding, 0.0),
|
0.0, 0.0, Entity.rightWidgetPadding, 0.0),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
child: Text(
|
child: Text(
|
||||||
"${entityModel.entity.state}${entityModel.entity.unitOfMeasurement}",
|
"${entityModel.entity.state}${entityModel.entity.unitOfMeasurement}",
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
style: new TextStyle(
|
style: new TextStyle(
|
||||||
fontSize: entityModel.entity.stateFontSize,
|
fontSize: Entity.stateFontSize,
|
||||||
)),
|
)),
|
||||||
onTap: () => entityModel.handleTap ? eventBus.fire(new ShowEntityPageEvent(entityModel.entity)) : null,
|
onTap: () => entityModel.handleTap
|
||||||
)
|
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
|
||||||
);
|
: null,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class EntityName extends StatelessWidget {
|
class EntityName extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
final entityModel = EntityModel.of(context);
|
||||||
@ -104,75 +95,73 @@ class EntityName extends StatelessWidget {
|
|||||||
"${entityModel.entity.displayName}",
|
"${entityModel.entity.displayName}",
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
softWrap: false,
|
softWrap: false,
|
||||||
style: TextStyle(fontSize: entityModel.entity.nameFontSize),
|
style: TextStyle(fontSize: Entity.nameFontSize),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () => entityModel.handleTap ? eventBus.fire(new ShowEntityPageEvent(entityModel.entity)) : null,
|
onTap: () => entityModel.handleTap
|
||||||
|
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class EntityIcon extends StatelessWidget {
|
class EntityIcon extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
final entityModel = EntityModel.of(context);
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.fromLTRB(entityModel.entity.leftWidgetPadding, 0.0, 12.0, 0.0),
|
padding: EdgeInsets.fromLTRB(
|
||||||
|
Entity.leftWidgetPadding, 0.0, 12.0, 0.0),
|
||||||
//TODO: move createIconWidgetFromEntityData into this widget
|
//TODO: move createIconWidgetFromEntityData into this widget
|
||||||
child: MaterialDesignIcons.createIconWidgetFromEntityData(
|
child: MaterialDesignIcons.createIconWidgetFromEntityData(
|
||||||
entityModel.entity,
|
entityModel.entity,
|
||||||
entityModel.entity.iconSize,
|
Entity.iconSize,
|
||||||
Entity.STATE_ICONS_COLORS[entityModel.entity.state] ?? Entity.STATE_ICONS_COLORS["default"]),
|
Entity.STATE_ICONS_COLORS[entityModel.entity.state] ??
|
||||||
|
Entity.STATE_ICONS_COLORS["default"]),
|
||||||
),
|
),
|
||||||
onTap: () => entityModel.handleTap ? eventBus.fire(new ShowEntityPageEvent(entityModel.entity)) : null,
|
onTap: () => entityModel.handleTap
|
||||||
|
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LastUpdatedWidget extends StatelessWidget {
|
class LastUpdatedWidget extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
final entityModel = EntityModel.of(context);
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.fromLTRB(
|
padding: EdgeInsets.fromLTRB(
|
||||||
entityModel.entity.leftWidgetPadding, 0.0, 0.0, 0.0),
|
Entity.leftWidgetPadding, 0.0, 0.0, 0.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
'${entityModel.entity.lastUpdated}',
|
'${entityModel.entity.lastUpdated}',
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
style:
|
style: TextStyle(
|
||||||
TextStyle(fontSize: entityModel.entity.smallFontSize, color: Colors.black26),
|
fontSize: Entity.smallFontSize, color: Colors.black26),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class EntityAttributesList extends StatelessWidget {
|
class EntityAttributesList extends StatelessWidget {
|
||||||
|
|
||||||
EntityAttributesList({Key key}) : super(key: key);
|
EntityAttributesList({Key key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
final entityModel = EntityModel.of(context);
|
||||||
List<Widget> attrs = [];
|
List<Widget> attrs = [];
|
||||||
if ((entityModel.entity.attributesToShow == null) || (entityModel.entity.attributesToShow.contains("all"))) {
|
if ((entityModel.entity.attributesToShow == null) ||
|
||||||
entityModel.entity.attributes.forEach((name, value){
|
(entityModel.entity.attributesToShow.contains("all"))) {
|
||||||
attrs.add(
|
entityModel.entity.attributes.forEach((name, value) {
|
||||||
_buildSingleAttribute(entityModel.entity, "$name", "$value")
|
attrs.add(_buildSingleAttribute("$name", "$value"));
|
||||||
);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
entityModel.entity.attributesToShow.forEach((String attr) {
|
entityModel.entity.attributesToShow.forEach((String attr) {
|
||||||
String attrValue = entityModel.entity.getAttribute("$attr");
|
String attrValue = entityModel.entity.getAttribute("$attr");
|
||||||
if (attrValue != null) {
|
if (attrValue != null) {
|
||||||
attrs.add(
|
attrs.add(
|
||||||
_buildSingleAttribute(entityModel.entity, "$attr", "$attrValue")
|
_buildSingleAttribute("$attr", "$attrValue"));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -183,12 +172,13 @@ class EntityAttributesList extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSingleAttribute(Entity entity, String name, String value) {
|
Widget _buildSingleAttribute(String name, String value) {
|
||||||
return Row(
|
return Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.fromLTRB(entity.leftWidgetPadding, entity.rowPadding, 0.0, 0.0),
|
padding: EdgeInsets.fromLTRB(
|
||||||
|
Entity.leftWidgetPadding, Entity.rowPadding, 0.0, 0.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
"$name",
|
"$name",
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
@ -197,7 +187,8 @@ class EntityAttributesList extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.fromLTRB(0.0, entity.rowPadding, entity.rightWidgetPadding, 0.0),
|
padding: EdgeInsets.fromLTRB(
|
||||||
|
0.0, Entity.rowPadding, Entity.rightWidgetPadding, 0.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
"$value",
|
"$value",
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
@ -210,48 +201,54 @@ class EntityAttributesList extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Badge extends StatelessWidget {
|
class Badge extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
final entityModel = EntityModel.of(context);
|
||||||
double iconSize = 26.0;
|
double iconSize = 26.0;
|
||||||
Widget badgeIcon;
|
Widget badgeIcon;
|
||||||
String onBadgeTextValue;
|
String onBadgeTextValue;
|
||||||
Color iconColor = Entity.badgeColors[entityModel.entity.domain] ?? Entity.badgeColors["default"];
|
Color iconColor = Entity.badgeColors[entityModel.entity.domain] ??
|
||||||
|
Entity.badgeColors["default"];
|
||||||
switch (entityModel.entity.domain) {
|
switch (entityModel.entity.domain) {
|
||||||
case "sun": {
|
case "sun":
|
||||||
badgeIcon = entityModel.entity.state == "below_horizon" ?
|
{
|
||||||
Icon(
|
badgeIcon = entityModel.entity.state == "below_horizon"
|
||||||
MaterialDesignIcons.createIconDataFromIconCode(0xf0dc),
|
? Icon(
|
||||||
size: iconSize,
|
MaterialDesignIcons.createIconDataFromIconCode(0xf0dc),
|
||||||
) :
|
size: iconSize,
|
||||||
Icon(
|
)
|
||||||
MaterialDesignIcons.createIconDataFromIconCode(0xf5a8),
|
: Icon(
|
||||||
size: iconSize,
|
MaterialDesignIcons.createIconDataFromIconCode(0xf5a8),
|
||||||
);
|
size: iconSize,
|
||||||
break;
|
);
|
||||||
}
|
break;
|
||||||
case "sensor": {
|
}
|
||||||
onBadgeTextValue = entityModel.entity.unitOfMeasurement;
|
case "sensor":
|
||||||
badgeIcon = Center(
|
{
|
||||||
child: Text(
|
onBadgeTextValue = entityModel.entity.unitOfMeasurement;
|
||||||
"${entityModel.entity.state}",
|
badgeIcon = Center(
|
||||||
overflow: TextOverflow.fade,
|
child: Text(
|
||||||
softWrap: false,
|
"${entityModel.entity.state}",
|
||||||
textAlign: TextAlign.center,
|
overflow: TextOverflow.fade,
|
||||||
style: TextStyle(fontSize: 17.0),
|
softWrap: false,
|
||||||
),
|
textAlign: TextAlign.center,
|
||||||
);
|
style: TextStyle(fontSize: 17.0),
|
||||||
break;
|
),
|
||||||
}
|
);
|
||||||
case "device_tracker": {
|
break;
|
||||||
badgeIcon = MaterialDesignIcons.createIconWidgetFromEntityData(entityModel.entity, iconSize,Colors.black);
|
}
|
||||||
onBadgeTextValue = entityModel.entity.state;
|
case "device_tracker":
|
||||||
break;
|
{
|
||||||
}
|
badgeIcon = MaterialDesignIcons.createIconWidgetFromEntityData(
|
||||||
default: {
|
entityModel.entity, iconSize, Colors.black);
|
||||||
badgeIcon = MaterialDesignIcons.createIconWidgetFromEntityData(entityModel.entity, iconSize,Colors.black);
|
onBadgeTextValue = entityModel.entity.state;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
badgeIcon = MaterialDesignIcons.createIconWidgetFromEntityData(
|
||||||
|
entityModel.entity, iconSize, Colors.black);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Widget onBadgeText;
|
Widget onBadgeText;
|
||||||
if (onBadgeTextValue == null || onBadgeTextValue.length == 0) {
|
if (onBadgeTextValue == null || onBadgeTextValue.length == 0) {
|
||||||
@ -261,71 +258,70 @@ class Badge extends StatelessWidget {
|
|||||||
padding: EdgeInsets.fromLTRB(6.0, 2.0, 6.0, 2.0),
|
padding: EdgeInsets.fromLTRB(6.0, 2.0, 6.0, 2.0),
|
||||||
child: Text("$onBadgeTextValue",
|
child: Text("$onBadgeTextValue",
|
||||||
style: TextStyle(fontSize: 12.0, color: Colors.white),
|
style: TextStyle(fontSize: 12.0, color: Colors.white),
|
||||||
textAlign: TextAlign.center, softWrap: false, overflow: TextOverflow.fade),
|
textAlign: TextAlign.center,
|
||||||
|
softWrap: false,
|
||||||
|
overflow: TextOverflow.fade),
|
||||||
decoration: new BoxDecoration(
|
decoration: new BoxDecoration(
|
||||||
// Circle shape
|
// Circle shape
|
||||||
//shape: BoxShape.circle,
|
//shape: BoxShape.circle,
|
||||||
color: iconColor,
|
color: iconColor,
|
||||||
borderRadius: BorderRadius.circular(9.0),
|
borderRadius: BorderRadius.circular(9.0),
|
||||||
)
|
));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(
|
Container(
|
||||||
margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
|
margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
|
||||||
width: 50.0,
|
width: 50.0,
|
||||||
height: 50.0,
|
height: 50.0,
|
||||||
decoration: new BoxDecoration(
|
decoration: new BoxDecoration(
|
||||||
// Circle shape
|
// Circle shape
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
// The border you want
|
// The border you want
|
||||||
border: new Border.all(
|
border: new Border.all(
|
||||||
width: 2.0,
|
width: 2.0,
|
||||||
color: iconColor,
|
color: iconColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
|
overflow: Overflow.visible,
|
||||||
|
children: <Widget>[
|
||||||
|
Positioned(
|
||||||
|
width: 46.0,
|
||||||
|
height: 46.0,
|
||||||
|
top: 0.0,
|
||||||
|
left: 0.0,
|
||||||
|
child: badgeIcon,
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
//width: 50.0,
|
||||||
|
bottom: -9.0,
|
||||||
|
left: -10.0,
|
||||||
|
right: -10.0,
|
||||||
|
child: Center(
|
||||||
|
child: onBadgeText,
|
||||||
|
))
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Stack(
|
Container(
|
||||||
overflow: Overflow.visible,
|
width: 60.0,
|
||||||
children: <Widget>[
|
child: Text(
|
||||||
Positioned(
|
"${entityModel.entity.displayName}",
|
||||||
width: 46.0,
|
textAlign: TextAlign.center,
|
||||||
height: 46.0,
|
style: TextStyle(fontSize: 12.0),
|
||||||
top: 0.0,
|
softWrap: true,
|
||||||
left: 0.0,
|
maxLines: 3,
|
||||||
child: badgeIcon,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
Positioned(
|
|
||||||
//width: 50.0,
|
|
||||||
bottom: -9.0,
|
|
||||||
left: -10.0,
|
|
||||||
right: -10.0,
|
|
||||||
child: Center(
|
|
||||||
child: onBadgeText,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
Container(
|
),
|
||||||
width: 60.0,
|
onTap: () =>
|
||||||
child: Text(
|
eventBus.fire(new ShowEntityPageEvent(entityModel.entity)));
|
||||||
"${entityModel.entity.displayName}",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(fontSize: 12.0),
|
|
||||||
softWrap: true,
|
|
||||||
maxLines: 3,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onTap: () => eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClimateStateWidget extends StatelessWidget {
|
class ClimateStateWidget extends StatelessWidget {
|
||||||
@ -333,65 +329,141 @@ class ClimateStateWidget extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
final entityModel = EntityModel.of(context);
|
||||||
final ClimateEntity entity = entityModel.entity;
|
final ClimateEntity entity = entityModel.entity;
|
||||||
|
String targetTemp = "-";
|
||||||
|
if ((entity.supportTargetTemperature) && (entity.temperature != null)) {
|
||||||
|
targetTemp = "${entity.temperature}";
|
||||||
|
} else if ((entity.supportTargetTemperatureLow) &&
|
||||||
|
(entity.targetLow != null)) {
|
||||||
|
targetTemp = "${entity.targetLow}";
|
||||||
|
if ((entity.supportTargetTemperatureHigh) &&
|
||||||
|
(entity.targetHigh != null)) {
|
||||||
|
targetTemp += " - ${entity.targetHigh}";
|
||||||
|
}
|
||||||
|
}
|
||||||
return Padding(
|
return Padding(
|
||||||
padding:
|
padding: EdgeInsets.fromLTRB(
|
||||||
EdgeInsets.fromLTRB(0.0, 0.0, entityModel.entity.rightWidgetPadding, 0.0),
|
0.0, 0.0, Entity.rightWidgetPadding, 0.0),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text("${entity.state}",
|
||||||
"${entity.state}",
|
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
style: new TextStyle(
|
style: new TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: entityModel.entity.stateFontSize,
|
fontSize: Entity.stateFontSize,
|
||||||
)),
|
)),
|
||||||
Text(
|
Text(" $targetTemp",
|
||||||
entity.supportTargetTemperature ? " ${entity.temperature}" : " ${entity.targetLow} - ${entity.targetHigh}",
|
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
style: new TextStyle(
|
style: new TextStyle(
|
||||||
fontSize: entityModel.entity.stateFontSize,
|
fontSize: Entity.stateFontSize,
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Text(
|
entity.attributes["current_temperature"] != null ?
|
||||||
"Currently: ${entity.attributes["current_temperature"]}",
|
Text("Currently: ${entity.attributes["current_temperature"]}",
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
style: new TextStyle(
|
style: new TextStyle(
|
||||||
fontSize: entityModel.entity.stateFontSize,
|
fontSize: Entity.stateFontSize,
|
||||||
color: Colors.black45
|
color: Colors.black45)
|
||||||
))
|
) :
|
||||||
|
Container(height: 0.0,)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () => entityModel.handleTap ? eventBus.fire(new ShowEntityPageEvent(entity)) : null,
|
onTap: () => entityModel.handleTap
|
||||||
|
? eventBus.fire(new ShowEntityPageEvent(entity))
|
||||||
|
: null,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemperatureControlWidget extends StatelessWidget {
|
||||||
|
final double value;
|
||||||
|
final double fontSize;
|
||||||
|
final Color fontColor;
|
||||||
|
final onSmallInc;
|
||||||
|
final onLargeInc;
|
||||||
|
final onSmallDec;
|
||||||
|
final onLargeDec;
|
||||||
|
|
||||||
|
TemperatureControlWidget(
|
||||||
|
{Key key,
|
||||||
|
@required this.value,
|
||||||
|
@required this.onSmallInc,
|
||||||
|
@required this.onSmallDec,
|
||||||
|
@required this.onLargeInc,
|
||||||
|
@required this.onLargeDec,
|
||||||
|
this.fontSize,
|
||||||
|
this.fontColor})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
"$value",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: fontSize ?? 24.0,
|
||||||
|
color: fontColor ?? Colors.black
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName(
|
||||||
|
'mdi:chevron-up')),
|
||||||
|
iconSize: 30.0,
|
||||||
|
onPressed: () => onSmallInc(),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName(
|
||||||
|
'mdi:chevron-down')),
|
||||||
|
iconSize: 30.0,
|
||||||
|
onPressed: () => onSmallDec(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: <Widget>[
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName(
|
||||||
|
'mdi:chevron-double-up')),
|
||||||
|
iconSize: 30.0,
|
||||||
|
onPressed: () => onLargeInc(),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(MaterialDesignIcons.createIconDataFromIconName(
|
||||||
|
'mdi:chevron-double-down')),
|
||||||
|
iconSize: 30.0,
|
||||||
|
onPressed: () => onLargeDec(),
|
||||||
|
)
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DateTimeStateWidget extends StatelessWidget {
|
class DateTimeStateWidget extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entityModel = EntityModel.of(context);
|
final entityModel = EntityModel.of(context);
|
||||||
final DateTimeEntity entity = entityModel.entity;
|
final DateTimeEntity entity = entityModel.entity;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding:
|
padding: EdgeInsets.fromLTRB(0.0, 0.0, Entity.rightWidgetPadding, 0.0),
|
||||||
EdgeInsets.fromLTRB(0.0, 0.0, entity.rightWidgetPadding, 0.0),
|
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
child: Text(
|
child: Text("${entity.formattedState}",
|
||||||
"${entity.formattedState}",
|
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
style: new TextStyle(
|
style: new TextStyle(
|
||||||
fontSize: entity.stateFontSize,
|
fontSize: Entity.stateFontSize,
|
||||||
)),
|
)),
|
||||||
onTap: () => _handleStateTap(context, entity),
|
onTap: () => _handleStateTap(context, entity),
|
||||||
)
|
));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleStateTap(BuildContext context, DateTimeEntity entity) {
|
void _handleStateTap(BuildContext context, DateTimeEntity entity) {
|
||||||
@ -399,18 +471,35 @@ class DateTimeStateWidget extends StatelessWidget {
|
|||||||
_showDatePicker(context, entity).then((date) {
|
_showDatePicker(context, entity).then((date) {
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
if (entity.hasTime) {
|
if (entity.hasTime) {
|
||||||
_showTimePicker(context, entity).then((time){
|
_showTimePicker(context, entity).then((time) {
|
||||||
entity.setNewState({"date": "${formatDate(date, [yyyy, '-', mm, '-', dd])}", "time": "${formatDate(DateTime(1970, 1, 1, time.hour, time.minute), [HH, ':', nn])}"});
|
entity.setNewState({
|
||||||
|
"date": "${formatDate(date, [yyyy, '-', mm, '-', dd])}",
|
||||||
|
"time":
|
||||||
|
"${formatDate(DateTime(1970, 1, 1, time.hour, time.minute), [
|
||||||
|
HH,
|
||||||
|
':',
|
||||||
|
nn
|
||||||
|
])}"
|
||||||
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
entity.setNewState({"date": "${formatDate(date, [yyyy, '-', mm, '-', dd])}"});
|
entity.setNewState({
|
||||||
|
"date": "${formatDate(date, [yyyy, '-', mm, '-', dd])}"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (entity.hasTime) {
|
} else if (entity.hasTime) {
|
||||||
_showTimePicker(context, entity).then((time){
|
_showTimePicker(context, entity).then((time) {
|
||||||
if (time != null) {
|
if (time != null) {
|
||||||
entity.setNewState({"time": "${formatDate(DateTime(1970, 1, 1, time.hour, time.minute), [HH, ':', nn])}"});
|
entity.setNewState({
|
||||||
|
"time":
|
||||||
|
"${formatDate(DateTime(1970, 1, 1, time.hour, time.minute), [
|
||||||
|
HH,
|
||||||
|
':',
|
||||||
|
nn
|
||||||
|
])}"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -424,30 +513,30 @@ class DateTimeStateWidget extends StatelessWidget {
|
|||||||
initialDate: entity.dateTimeState,
|
initialDate: entity.dateTimeState,
|
||||||
firstDate: DateTime(1970),
|
firstDate: DateTime(1970),
|
||||||
lastDate: DateTime(2037) //Unix timestamp will finish at Jan 19, 2038
|
lastDate: DateTime(2037) //Unix timestamp will finish at Jan 19, 2038
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _showTimePicker(BuildContext context, DateTimeEntity entity) {
|
Future _showTimePicker(BuildContext context, DateTimeEntity entity) {
|
||||||
return showTimePicker(
|
return showTimePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialTime: TimeOfDay.fromDateTime(entity.dateTimeState)
|
initialTime: TimeOfDay.fromDateTime(entity.dateTimeState));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CoverEntityControlState extends StatelessWidget {
|
class CoverEntityControlState extends StatelessWidget {
|
||||||
|
|
||||||
void _open(CoverEntity entity) {
|
void _open(CoverEntity entity) {
|
||||||
eventBus.fire(new ServiceCallEvent(entity.domain, "open_cover", entity.entityId, null));
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "open_cover", entity.entityId, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _close(CoverEntity entity) {
|
void _close(CoverEntity entity) {
|
||||||
eventBus.fire(new ServiceCallEvent(entity.domain, "close_cover", entity.entityId, null));
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "close_cover", entity.entityId, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _stop(CoverEntity entity) {
|
void _stop(CoverEntity entity) {
|
||||||
eventBus.fire(new ServiceCallEvent(entity.domain, "stop_cover", entity.entityId, null));
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "stop_cover", entity.entityId, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -456,64 +545,62 @@ class CoverEntityControlState extends StatelessWidget {
|
|||||||
final CoverEntity entity = entityModel.entity;
|
final CoverEntity entity = entityModel.entity;
|
||||||
List<Widget> buttons = [];
|
List<Widget> buttons = [];
|
||||||
if (entity.supportOpen) {
|
if (entity.supportOpen) {
|
||||||
buttons.add(
|
buttons.add(IconButton(
|
||||||
IconButton(
|
icon: Icon(
|
||||||
icon: Icon(
|
MaterialDesignIcons.createIconDataFromIconName("mdi:arrow-up"),
|
||||||
MaterialDesignIcons.createIconDataFromIconName("mdi:arrow-up"),
|
size: Entity.iconSize,
|
||||||
size: entity.iconSize,
|
),
|
||||||
),
|
onPressed: entity.canBeOpened ? () => _open(entity) : null));
|
||||||
onPressed: entity.canBeOpened ? () =>_open(entity) : null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
buttons.add(Container(width: entity.iconSize+20.0,));
|
buttons.add(Container(
|
||||||
|
width: Entity.iconSize + 20.0,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (entity.supportStop) {
|
if (entity.supportStop) {
|
||||||
buttons.add(
|
buttons.add(IconButton(
|
||||||
IconButton(
|
icon: Icon(
|
||||||
icon: Icon(
|
MaterialDesignIcons.createIconDataFromIconName("mdi:stop"),
|
||||||
MaterialDesignIcons.createIconDataFromIconName("mdi:stop"),
|
size: Entity.iconSize,
|
||||||
size: entity.iconSize,
|
),
|
||||||
),
|
onPressed: () => _stop(entity)));
|
||||||
onPressed: () => _stop(entity)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
buttons.add(Container(width: entity.iconSize+20.0,));
|
buttons.add(Container(
|
||||||
|
width: Entity.iconSize + 20.0,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (entity.supportClose) {
|
if (entity.supportClose) {
|
||||||
buttons.add(
|
buttons.add(IconButton(
|
||||||
IconButton(
|
icon: Icon(
|
||||||
icon: Icon(
|
MaterialDesignIcons.createIconDataFromIconName("mdi:arrow-down"),
|
||||||
MaterialDesignIcons.createIconDataFromIconName("mdi:arrow-down"),
|
size: Entity.iconSize,
|
||||||
size: entity.iconSize,
|
),
|
||||||
),
|
onPressed: entity.canBeClosed ? () => _close(entity) : null));
|
||||||
onPressed: entity.canBeClosed ? () => _close(entity) : null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
buttons.add(Container(width: entity.iconSize+20.0,));
|
buttons.add(Container(
|
||||||
|
width: Entity.iconSize + 20.0,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
children: buttons,
|
children: buttons,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CoverEntityTiltControlState extends StatelessWidget {
|
class CoverEntityTiltControlButtons extends StatelessWidget {
|
||||||
|
|
||||||
void _open(CoverEntity entity) {
|
void _open(CoverEntity entity) {
|
||||||
eventBus.fire(new ServiceCallEvent(entity.domain, "open_cover_tilt", entity.entityId, null));
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "open_cover_tilt", entity.entityId, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _close(CoverEntity entity) {
|
void _close(CoverEntity entity) {
|
||||||
eventBus.fire(new ServiceCallEvent(entity.domain, "close_cover_tilt", entity.entityId, null));
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "close_cover_tilt", entity.entityId, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _stop(CoverEntity entity) {
|
void _stop(CoverEntity entity) {
|
||||||
eventBus.fire(new ServiceCallEvent(entity.domain, "stop_cover_tilt", entity.entityId, null));
|
eventBus.fire(new ServiceCallEvent(
|
||||||
|
entity.domain, "stop_cover_tilt", entity.entityId, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -522,48 +609,167 @@ class CoverEntityTiltControlState extends StatelessWidget {
|
|||||||
final CoverEntity entity = entityModel.entity;
|
final CoverEntity entity = entityModel.entity;
|
||||||
List<Widget> buttons = [];
|
List<Widget> buttons = [];
|
||||||
if (entity.supportOpenTilt) {
|
if (entity.supportOpenTilt) {
|
||||||
buttons.add(
|
buttons.add(IconButton(
|
||||||
IconButton(
|
icon: Icon(
|
||||||
icon: Icon(
|
MaterialDesignIcons.createIconDataFromIconName(
|
||||||
MaterialDesignIcons.createIconDataFromIconName("mdi:arrow-top-right"),
|
"mdi:arrow-top-right"),
|
||||||
size: entity.iconSize,
|
size: Entity.iconSize,
|
||||||
),
|
),
|
||||||
onPressed: entity.canTiltBeOpened ? () =>_open(entity) : null
|
onPressed: entity.canTiltBeOpened ? () => _open(entity) : null));
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
buttons.add(Container(width: entity.iconSize+20.0,));
|
buttons.add(Container(
|
||||||
|
width: Entity.iconSize + 20.0,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (entity.supportStopTilt) {
|
if (entity.supportStopTilt) {
|
||||||
buttons.add(
|
buttons.add(IconButton(
|
||||||
IconButton(
|
icon: Icon(
|
||||||
icon: Icon(
|
MaterialDesignIcons.createIconDataFromIconName("mdi:stop"),
|
||||||
MaterialDesignIcons.createIconDataFromIconName("mdi:stop"),
|
size: Entity.iconSize,
|
||||||
size: entity.iconSize,
|
),
|
||||||
),
|
onPressed: () => _stop(entity)));
|
||||||
onPressed: () => _stop(entity)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
buttons.add(Container(width: entity.iconSize+20.0,));
|
buttons.add(Container(
|
||||||
|
width: Entity.iconSize + 20.0,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (entity.supportCloseTilt) {
|
if (entity.supportCloseTilt) {
|
||||||
buttons.add(
|
buttons.add(IconButton(
|
||||||
IconButton(
|
icon: Icon(
|
||||||
icon: Icon(
|
MaterialDesignIcons.createIconDataFromIconName(
|
||||||
MaterialDesignIcons.createIconDataFromIconName("mdi:arrow-bottom-left"),
|
"mdi:arrow-bottom-left"),
|
||||||
size: entity.iconSize,
|
size: Entity.iconSize,
|
||||||
),
|
),
|
||||||
onPressed: entity.canTiltBeClosed ? () => _close(entity) : null
|
onPressed: entity.canTiltBeClosed ? () => _close(entity) : null));
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
buttons.add(Container(width: entity.iconSize+20.0,));
|
buttons.add(Container(
|
||||||
|
width: Entity.iconSize + 20.0,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
children: buttons,
|
children: buttons,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ButtonStateWidget extends StatelessWidget {
|
||||||
|
|
||||||
|
void _setNewState(Entity entity) {
|
||||||
|
eventBus.fire(new ServiceCallEvent(entity.domain, "turn_on", entity.entityId, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final entityModel = EntityModel.of(context);
|
||||||
|
return FlatButton(
|
||||||
|
onPressed: (() {
|
||||||
|
_setNewState(entityModel.entity);
|
||||||
|
}),
|
||||||
|
child: Text(
|
||||||
|
"EXECUTE",
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
style:
|
||||||
|
new TextStyle(fontSize: Entity.stateFontSize, color: Colors.blue),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ModeSelectorWidget extends StatelessWidget {
|
||||||
|
|
||||||
|
final String caption;
|
||||||
|
final List<String> options;
|
||||||
|
final String value;
|
||||||
|
final double captionFontSize;
|
||||||
|
final double valueFontSize;
|
||||||
|
final double bottomPadding;
|
||||||
|
final onChange;
|
||||||
|
|
||||||
|
ModeSelectorWidget({
|
||||||
|
Key key,
|
||||||
|
this.caption,
|
||||||
|
@required this.options,
|
||||||
|
this.value,
|
||||||
|
@required this.onChange,
|
||||||
|
this.captionFontSize,
|
||||||
|
this.valueFontSize,
|
||||||
|
this.bottomPadding
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Text("$caption", style: TextStyle(
|
||||||
|
fontSize: captionFontSize ?? Entity.stateFontSize
|
||||||
|
)),
|
||||||
|
Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: ButtonTheme(
|
||||||
|
alignedDropdown: true,
|
||||||
|
child: DropdownButton<String>(
|
||||||
|
value: value,
|
||||||
|
iconSize: 30.0,
|
||||||
|
isExpanded: true,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: valueFontSize ?? Entity.largeFontSize,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
hint: Text("Select ${caption.toLowerCase()}"),
|
||||||
|
items: options.map((String value) {
|
||||||
|
return new DropdownMenuItem<String>(
|
||||||
|
value: value,
|
||||||
|
child: Text(value),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
onChanged: (mode) => onChange(mode),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Container(height: bottomPadding ?? Entity.rowPadding,)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ModeSwitchWidget extends StatelessWidget {
|
||||||
|
|
||||||
|
final String caption;
|
||||||
|
final onChange;
|
||||||
|
final double captionFontSize;
|
||||||
|
final bool value;
|
||||||
|
|
||||||
|
ModeSwitchWidget({
|
||||||
|
Key key,
|
||||||
|
@required this.caption,
|
||||||
|
@required this.onChange,
|
||||||
|
this.captionFontSize,
|
||||||
|
this.value
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"$caption",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: captionFontSize ?? Entity.stateFontSize
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Switch(
|
||||||
|
onChanged: (value) => onChange(value),
|
||||||
|
value: value ?? false,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,28 +2,32 @@ part of 'main.dart';
|
|||||||
|
|
||||||
class EntityCollection {
|
class EntityCollection {
|
||||||
|
|
||||||
Map<String, Entity> _entities;
|
Map<String, Entity> _allEntities;
|
||||||
List<String> viewList;
|
Map<String, Entity> views;
|
||||||
|
|
||||||
bool get isEmpty => _entities.isEmpty;
|
bool get isEmpty => _allEntities.isEmpty;
|
||||||
|
|
||||||
EntityCollection() {
|
EntityCollection() {
|
||||||
_entities = {};
|
_allEntities = {};
|
||||||
viewList = [];
|
views = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get hasDefaultView => _entities["group.default_view"] != null;
|
bool get hasDefaultView => _allEntities["group.default_view"] != null;
|
||||||
|
|
||||||
void parse(List rawData) {
|
void parse(List rawData) {
|
||||||
_entities.clear();
|
_allEntities.clear();
|
||||||
viewList.clear();
|
views.clear();
|
||||||
|
|
||||||
TheLogger.log("Debug","Parsing ${rawData.length} Home Assistant entities");
|
TheLogger.log("Debug","Parsing ${rawData.length} Home Assistant entities");
|
||||||
rawData.forEach((rawEntityData) {
|
rawData.forEach((rawEntityData) {
|
||||||
Entity newEntity = addFromRaw(rawEntityData);
|
addFromRaw(rawEntityData);
|
||||||
|
});
|
||||||
if (newEntity.isView) {
|
_allEntities.forEach((entityId, entity){
|
||||||
viewList.add(newEntity.entityId);
|
if ((entity.isGroup) && (entity.childEntityIds != null)) {
|
||||||
|
entity.childEntities = getAll(entity.childEntityIds);
|
||||||
|
}
|
||||||
|
if (entity.isView) {
|
||||||
|
views[entityId] = entity;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -35,13 +39,15 @@ class EntityCollection {
|
|||||||
}
|
}
|
||||||
case "automation":
|
case "automation":
|
||||||
case "input_boolean":
|
case "input_boolean":
|
||||||
case "switch":
|
case "switch": {
|
||||||
|
return SwitchEntity(rawEntityData);
|
||||||
|
}
|
||||||
case "light": {
|
case "light": {
|
||||||
return SwitchEntity(rawEntityData);
|
return LightEntity(rawEntityData);
|
||||||
}
|
}
|
||||||
case "script":
|
case "script":
|
||||||
case "scene": {
|
case "scene": {
|
||||||
return ButtonEntity(rawEntityData);
|
return ButtonEntity(rawEntityData);
|
||||||
}
|
}
|
||||||
case "input_datetime": {
|
case "input_datetime": {
|
||||||
return DateTimeEntity(rawEntityData);
|
return DateTimeEntity(rawEntityData);
|
||||||
@ -76,12 +82,12 @@ class EntityCollection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add(Entity entity) {
|
void add(Entity entity) {
|
||||||
_entities[entity.entityId] = entity;
|
_allEntities[entity.entityId] = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity addFromRaw(Map rawEntityData) {
|
Entity addFromRaw(Map rawEntityData) {
|
||||||
Entity entity = _createEntityInstance(rawEntityData);
|
Entity entity = _createEntityInstance(rawEntityData);
|
||||||
_entities[entity.entityId] = entity;
|
_allEntities[entity.entityId] = entity;
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +96,7 @@ class EntityCollection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity get(String entityId) {
|
Entity get(String entityId) {
|
||||||
return _entities[entityId];
|
return _allEntities[entityId];
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Entity> getAll(List ids) {
|
List<Entity> getAll(List ids) {
|
||||||
@ -105,13 +111,13 @@ class EntityCollection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isExist(String entityId) {
|
bool isExist(String entityId) {
|
||||||
return _entities[entityId] != null;
|
return _allEntities[entityId] != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String,List<String>> getDefaultViewTopLevelEntities() {
|
Map<String,List<String>> getDefaultViewTopLevelEntities() {
|
||||||
Map<String,List<String>> result = {"userGroups": [], "notGroupedEntities": []};
|
Map<String,List<String>> result = {"userGroups": [], "notGroupedEntities": []};
|
||||||
List<String> entities = [];
|
List<String> entities = [];
|
||||||
_entities.forEach((id, entity){
|
_allEntities.forEach((id, entity){
|
||||||
if ((id.indexOf("group.") == 0) && (id.indexOf(".all_") == -1) && (!entity.isView)) {
|
if ((id.indexOf("group.") == 0) && (id.indexOf(".all_") == -1) && (!entity.isView)) {
|
||||||
result["userGroups"].add(id);
|
result["userGroups"].add(id);
|
||||||
}
|
}
|
||||||
@ -123,7 +129,7 @@ class EntityCollection {
|
|||||||
entities.forEach((entiyId) {
|
entities.forEach((entiyId) {
|
||||||
bool foundInGroup = false;
|
bool foundInGroup = false;
|
||||||
result["userGroups"].forEach((userGroupId) {
|
result["userGroups"].forEach((userGroupId) {
|
||||||
if (_entities[userGroupId].childEntityIds.contains(entiyId)) {
|
if (_allEntities[userGroupId].childEntityIds.contains(entiyId)) {
|
||||||
foundInGroup = true;
|
foundInGroup = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -38,7 +38,7 @@ class HomeAssistant {
|
|||||||
String get locationName => _instanceConfig["location_name"] ?? "";
|
String get locationName => _instanceConfig["location_name"] ?? "";
|
||||||
String get userName => _userName ?? locationName;
|
String get userName => _userName ?? locationName;
|
||||||
String get userAvatarText => userName.length > 0 ? userName[0] : "";
|
String get userAvatarText => userName.length > 0 ? userName[0] : "";
|
||||||
int get viewsCount => _entities.viewList.length ?? 0;
|
int get viewsCount => _entities.views.length ?? 0;
|
||||||
|
|
||||||
EntityCollection get entities => _entities;
|
EntityCollection get entities => _entities;
|
||||||
|
|
||||||
@ -192,7 +192,6 @@ class HomeAssistant {
|
|||||||
|
|
||||||
_handleMessage(String message) {
|
_handleMessage(String message) {
|
||||||
var data = json.decode(message);
|
var data = json.decode(message);
|
||||||
TheLogger.log("Debug","[Received] => ${data['type']}");
|
|
||||||
if (data["type"] == "auth_required") {
|
if (data["type"] == "auth_required") {
|
||||||
_sendAuthMessageRaw('{"type": "auth","$_authType": "$_password"}');
|
_sendAuthMessageRaw('{"type": "auth","$_authType": "$_password"}');
|
||||||
} else if (data["type"] == "auth_ok") {
|
} else if (data["type"] == "auth_ok") {
|
||||||
@ -210,10 +209,11 @@ class HomeAssistant {
|
|||||||
} else if (data["id"] == _userInfoMessageId) {
|
} else if (data["id"] == _userInfoMessageId) {
|
||||||
_parseUserInfo(data);
|
_parseUserInfo(data);
|
||||||
} else if (data["id"] == _currentMessageId) {
|
} else if (data["id"] == _currentMessageId) {
|
||||||
TheLogger.log("Debug","Request id:$_currentMessageId was successful");
|
TheLogger.log("Debug","[Received] => Request id:$_currentMessageId was successful");
|
||||||
}
|
}
|
||||||
} else if (data["type"] == "event") {
|
} else if (data["type"] == "event") {
|
||||||
if ((data["event"] != null) && (data["event"]["event_type"] == "state_changed")) {
|
if ((data["event"] != null) && (data["event"]["event_type"] == "state_changed")) {
|
||||||
|
TheLogger.log("Debug","[Received] => ${data['type']}.${data["event"]["event_type"]}: ${data["event"]["data"]["entity_id"]}");
|
||||||
_handleEntityStateChange(data["event"]["data"]);
|
_handleEntityStateChange(data["event"]["data"]);
|
||||||
} else if (data["event"] != null) {
|
} else if (data["event"] != null) {
|
||||||
TheLogger.log("Warning","Unhandled event type: ${data["event"]["event_type"]}");
|
TheLogger.log("Warning","Unhandled event type: ${data["event"]["event_type"]}");
|
||||||
@ -300,7 +300,7 @@ class HomeAssistant {
|
|||||||
String message = '{"id": $_currentMessageId, "type": "call_service", "domain": "$domain", "service": "$service", "service_data": {"entity_id": "$entityId"';
|
String message = '{"id": $_currentMessageId, "type": "call_service", "domain": "$domain", "service": "$service", "service_data": {"entity_id": "$entityId"';
|
||||||
if (additionalParams != null) {
|
if (additionalParams != null) {
|
||||||
additionalParams.forEach((name, value){
|
additionalParams.forEach((name, value){
|
||||||
if ((value is double) || (value is int)) {
|
if ((value is double) || (value is int) || (value is List)) {
|
||||||
message += ', "$name" : $value';
|
message += ', "$name" : $value';
|
||||||
} else {
|
} else {
|
||||||
message += ', "$name" : "$value"';
|
message += ', "$name" : "$value"';
|
||||||
|
@ -12,6 +12,7 @@ import 'package:url_launcher/url_launcher.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:date_format/date_format.dart';
|
import 'package:date_format/date_format.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:flutter_colorpicker/material_picker.dart';
|
||||||
|
|
||||||
part 'entity_class/entity.class.dart';
|
part 'entity_class/entity.class.dart';
|
||||||
part 'entity_class/stateless_widgets.dart';
|
part 'entity_class/stateless_widgets.dart';
|
||||||
@ -30,7 +31,7 @@ part 'card_class.dart';
|
|||||||
|
|
||||||
EventBus eventBus = new EventBus();
|
EventBus eventBus = new EventBus();
|
||||||
const String appName = "HA Client";
|
const String appName = "HA Client";
|
||||||
const appVersion = "0.3.0.38";
|
const appVersion = "0.3.3";
|
||||||
|
|
||||||
String homeAssistantWebHost;
|
String homeAssistantWebHost;
|
||||||
|
|
||||||
@ -206,6 +207,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
|||||||
//_instanceConfig = _homeAssistant.instanceConfig;
|
//_instanceConfig = _homeAssistant.instanceConfig;
|
||||||
_entities = _homeAssistant.entities;
|
_entities = _homeAssistant.entities;
|
||||||
_uiViewsCount = _homeAssistant.viewsCount;
|
_uiViewsCount = _homeAssistant.viewsCount;
|
||||||
|
TheLogger.log("Debug","_uiViewsCount=$_uiViewsCount");
|
||||||
_isLoading = 0;
|
_isLoading = 0;
|
||||||
});
|
});
|
||||||
}).catchError((e) {
|
}).catchError((e) {
|
||||||
@ -238,7 +240,6 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Tab> buildUIViewTabs() {
|
List<Tab> buildUIViewTabs() {
|
||||||
//TODO move somewhere to ViewBuilder
|
|
||||||
List<Tab> result = [];
|
List<Tab> result = [];
|
||||||
if (!_entities.isEmpty) {
|
if (!_entities.isEmpty) {
|
||||||
if (!_entities.hasDefaultView) {
|
if (!_entities.hasDefaultView) {
|
||||||
@ -252,10 +253,10 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_entities.viewList.forEach((viewId) {
|
_entities.views.forEach((viewId, groupEntity) {
|
||||||
result.add(
|
result.add(
|
||||||
Tab(
|
Tab(
|
||||||
icon: MaterialDesignIcons.createIconWidgetFromEntityData(_entities.get(viewId), 24.0, null) ??
|
icon: MaterialDesignIcons.createIconWidgetFromEntityData(groupEntity, 24.0, null) ??
|
||||||
Icon(
|
Icon(
|
||||||
MaterialDesignIcons.createIconDataFromIconName("mdi:home-assistant"),
|
MaterialDesignIcons.createIconDataFromIconName("mdi:home-assistant"),
|
||||||
size: 24.0,
|
size: 24.0,
|
||||||
|
@ -31,7 +31,8 @@ class ViewBuilder{
|
|||||||
Map<String, List<String>> userGroupsList = entityCollection.getDefaultViewTopLevelEntities();
|
Map<String, List<String>> userGroupsList = entityCollection.getDefaultViewTopLevelEntities();
|
||||||
List<Entity> entitiesForView = [];
|
List<Entity> entitiesForView = [];
|
||||||
userGroupsList["userGroups"].forEach((groupId){
|
userGroupsList["userGroups"].forEach((groupId){
|
||||||
entitiesForView.add(entityCollection.get(groupId));
|
Entity en = entityCollection.get(groupId);
|
||||||
|
entitiesForView.add(en);
|
||||||
});
|
});
|
||||||
userGroupsList["notGroupedEntities"].forEach((entityId){
|
userGroupsList["notGroupedEntities"].forEach((entityId){
|
||||||
entitiesForView.add(entityCollection.get(entityId));
|
entitiesForView.add(entityCollection.get(entityId));
|
||||||
@ -45,26 +46,12 @@ class ViewBuilder{
|
|||||||
List<View> _composeViews() {
|
List<View> _composeViews() {
|
||||||
List<View> result = [];
|
List<View> result = [];
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
entityCollection.viewList.forEach((viewId) {
|
entityCollection.views.forEach((viewId, viewGroupEntity) {
|
||||||
counter += 1;
|
counter += 1;
|
||||||
//try {
|
//try {
|
||||||
Entity viewGroupEntity = entityCollection.get(viewId);
|
|
||||||
List<Entity> entitiesForView = [];
|
|
||||||
viewGroupEntity.childEntityIds.forEach((
|
|
||||||
entityId) { //Each entity or group in view
|
|
||||||
if (entityCollection.isExist(entityId)) {
|
|
||||||
Entity en = entityCollection.get(entityId);
|
|
||||||
if (en.isGroup) {
|
|
||||||
en.childEntities = entityCollection.getAll(en.childEntityIds);
|
|
||||||
}
|
|
||||||
entitiesForView.add(en);
|
|
||||||
} else {
|
|
||||||
TheLogger.log("Warning", "Unknown entity inside view: $entityId");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
result.add(View(
|
result.add(View(
|
||||||
count: counter,
|
count: counter,
|
||||||
entities: entitiesForView
|
entities: viewGroupEntity.childEntities
|
||||||
));
|
));
|
||||||
/*} catch (error) {
|
/*} catch (error) {
|
||||||
TheLogger.log("Error","Error parsing view: $viewId");
|
TheLogger.log("Error","Error parsing view: $viewId");
|
||||||
|
@ -14,7 +14,7 @@ class View {
|
|||||||
}) {
|
}) {
|
||||||
childEntitiesAsBadges = [];
|
childEntitiesAsBadges = [];
|
||||||
childEntitiesAsCards = {};
|
childEntitiesAsCards = {};
|
||||||
_composeEntities();
|
_filterEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildWidget(BuildContext context) {
|
Widget buildWidget(BuildContext context) {
|
||||||
@ -24,7 +24,7 @@ class View {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _composeEntities() {
|
void _filterEntities() {
|
||||||
entities.forEach((Entity entity){
|
entities.forEach((Entity entity){
|
||||||
if (!entity.isGroup) {
|
if (!entity.isGroup) {
|
||||||
if (entity.isBadge) {
|
if (entity.isBadge) {
|
||||||
@ -41,6 +41,7 @@ class View {
|
|||||||
} else {
|
} else {
|
||||||
childEntitiesAsCards[entity.entityId] = CardSkeleton(
|
childEntitiesAsCards[entity.entityId] = CardSkeleton(
|
||||||
displayName: entity.displayName,
|
displayName: entity.displayName,
|
||||||
|
groupEntity: entity
|
||||||
);
|
);
|
||||||
childEntitiesAsCards[entity.entityId].childEntities = entity.childEntities;
|
childEntitiesAsCards[entity.entityId].childEntities = entity.childEntities;
|
||||||
}
|
}
|
||||||
@ -111,10 +112,14 @@ class ViewWidgetState extends State<ViewWidget> {
|
|||||||
|
|
||||||
widget.cards.forEach((String id, CardSkeleton skeleton){
|
widget.cards.forEach((String id, CardSkeleton skeleton){
|
||||||
result.add(
|
result.add(
|
||||||
HACard(
|
EntityModel(
|
||||||
entities: skeleton.childEntities,
|
entity: skeleton.groupEntity,
|
||||||
friendlyName: skeleton.displayName,
|
handleTap: false,
|
||||||
)
|
child: CardWidget(
|
||||||
|
entities: skeleton.childEntities,
|
||||||
|
friendlyName: skeleton.displayName,
|
||||||
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -151,8 +156,13 @@ class ViewWidgetState extends State<ViewWidget> {
|
|||||||
class CardSkeleton {
|
class CardSkeleton {
|
||||||
String displayName;
|
String displayName;
|
||||||
List<Entity> childEntities;
|
List<Entity> childEntities;
|
||||||
|
Entity groupEntity;
|
||||||
|
|
||||||
CardSkeleton({Key key, this.displayName, this.childEntities}) {
|
CardSkeleton({
|
||||||
|
Key key,
|
||||||
|
this.displayName,
|
||||||
|
this.childEntities,
|
||||||
|
this.groupEntity}) {
|
||||||
childEntities = [];
|
childEntities = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -113,6 +113,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.2"
|
version: "0.1.2"
|
||||||
|
flutter_colorpicker:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_colorpicker
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.0"
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
name: hass_client
|
name: hass_client
|
||||||
description: Home Assistant Android Client
|
description: Home Assistant Android Client
|
||||||
|
|
||||||
version: 0.3.0+38
|
version: 0.3.3+43
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||||
@ -15,6 +15,7 @@ dependencies:
|
|||||||
cached_network_image: ^0.4.1
|
cached_network_image: ^0.4.1
|
||||||
url_launcher: ^3.0.3
|
url_launcher: ^3.0.3
|
||||||
date_format: ^1.0.5
|
date_format: ^1.0.5
|
||||||
|
flutter_colorpicker: ^0.1.0
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
|
Reference in New Issue
Block a user