WIP #183 Custom names and icons

This commit is contained in:
Yegor Vialov 2018-11-15 19:08:47 +02:00
parent 37ad5e81cf
commit c5942d22b3
33 changed files with 153 additions and 97 deletions

View File

@ -77,20 +77,15 @@ class Entity {
}
Widget buildDefaultWidget(BuildContext context) {
return EntityModel(
entity: this,
child: DefaultEntityContainer(
return DefaultEntityContainer(
state: _buildStatePart(context)
),
handleTap: true,
);
}
Widget buildGlanceWidget(BuildContext context) {
return EntityModel(
entity: this,
child: GlanceEntityContainer(),
handleTap: true,
Widget buildGlanceWidget(BuildContext context, bool showName, bool showState) {
return GlanceEntityContainer(
showName: showName,
showState: showState,
);
}
@ -111,7 +106,7 @@ class Entity {
Widget buildEntityPageWidget(BuildContext context) {
return EntityModel(
entity: this,
entity: EntityWrapper(entity: this),
child: EntityPageContainer(children: <Widget>[
DefaultEntityContainer(state: _buildStatePartForPage(context)),
LastUpdatedWidget(),
@ -133,7 +128,7 @@ class Entity {
Widget buildBadgeWidget(BuildContext context) {
return EntityModel(
entity: this,
entity: EntityWrapper(entity: this),
child: BadgeWidget(),
handleTap: true,
);

View File

@ -0,0 +1,14 @@
part of '../main.dart';
class EntityWrapper {
String displayName;
String icon;
Entity entity;
EntityWrapper({this.entity, String icon, String displayName}) {
this.icon = icon ?? entity.icon;
this.displayName = displayName ?? entity.displayName;
}
}

View File

@ -7,12 +7,12 @@ class BadgeWidget extends StatelessWidget {
double iconSize = 26.0;
Widget badgeIcon;
String onBadgeTextValue;
Color iconColor = EntityColor.badgeColors[entityModel.entity.domain] ??
Color iconColor = EntityColor.badgeColors[entityModel.entity.entity.domain] ??
EntityColor.badgeColors["default"];
switch (entityModel.entity.domain) {
switch (entityModel.entity.entity.domain) {
case "sun":
{
badgeIcon = entityModel.entity.state == "below_horizon"
badgeIcon = entityModel.entity.entity.state == "below_horizon"
? Icon(
MaterialDesignIcons.createIconDataFromIconCode(0xf0dc),
size: iconSize,
@ -25,10 +25,10 @@ class BadgeWidget extends StatelessWidget {
}
case "sensor":
{
onBadgeTextValue = entityModel.entity.unitOfMeasurement;
onBadgeTextValue = entityModel.entity.entity.unitOfMeasurement;
badgeIcon = Center(
child: Text(
"${entityModel.entity.state}",
"${entityModel.entity.entity.state}",
overflow: TextOverflow.fade,
softWrap: false,
textAlign: TextAlign.center,
@ -41,7 +41,7 @@ class BadgeWidget extends StatelessWidget {
{
badgeIcon = MaterialDesignIcons.createIconWidgetFromEntityData(
entityModel.entity, iconSize, Colors.black);
onBadgeTextValue = entityModel.entity.state;
onBadgeTextValue = entityModel.entity.entity.state;
break;
}
default:
@ -120,6 +120,6 @@ class BadgeWidget extends StatelessWidget {
],
),
onTap: () =>
eventBus.fire(new ShowEntityPageEvent(entityModel.entity)));
eventBus.fire(new ShowEntityPageEvent(entityModel.entity.entity)));
}
}

View File

@ -165,7 +165,7 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final ClimateEntity entity = entityModel.entity;
final ClimateEntity entity = entityModel.entity.entity;
if (_changedHere) {
_showPending = (_tmpTemperature != entity.temperature);
_changedHere = false;

View File

@ -38,7 +38,7 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final CoverEntity entity = entityModel.entity;
final CoverEntity entity = entityModel.entity.entity;
if (_changedHere) {
_changedHere = false;
} else {
@ -152,7 +152,7 @@ class CoverTiltControlsWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final CoverEntity entity = entityModel.entity;
final CoverEntity entity = entityModel.entity.entity;
List<Widget> buttons = [];
if (entity.supportOpenTilt) {
buttons.add(IconButton(

View File

@ -80,7 +80,7 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final LightEntity entity = entityModel.entity;
final LightEntity entity = entityModel.entity.entity;
if (!_changedHere) {
_resetState(entity);
} else {

View File

@ -28,7 +28,7 @@ class MediaPlayerWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final EntityModel entityModel = EntityModel.of(context);
final MediaPlayerEntity entity = entityModel.entity;
final MediaPlayerEntity entity = entityModel.entity.entity;
return Column(
children: <Widget>[
Stack(
@ -229,7 +229,7 @@ class _MediaPlayerProgressWidgetState extends State<MediaPlayerProgressWidget> {
@override
Widget build(BuildContext context) {
final EntityModel entityModel = EntityModel.of(context);
final MediaPlayerEntity entity = entityModel.entity;
final MediaPlayerEntity entity = entityModel.entity.entity;
double progress;
try {
DateTime lastUpdated = DateTime.parse(

View File

@ -25,7 +25,7 @@ class _SliderControlsWidgetState extends State<SliderControlsWidget> {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final SliderEntity entity = entityModel.entity;
final SliderEntity entity = entityModel.entity.entity;
if (entity.valueStep < 1) {
_multiplier = 10;
} else if (entity.valueStep < 0.1) {

View File

@ -7,14 +7,14 @@ class EntityAttributesList extends StatelessWidget {
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
List<Widget> attrs = [];
if ((entityModel.entity.attributesToShow == null) ||
(entityModel.entity.attributesToShow.contains("all"))) {
entityModel.entity.attributes.forEach((name, value) {
if ((entityModel.entity.entity.attributesToShow == null) ||
(entityModel.entity.entity.attributesToShow.contains("all"))) {
entityModel.entity.entity.attributes.forEach((name, value) {
attrs.add(_buildSingleAttribute("$name", "$value"));
});
} else {
entityModel.entity.attributesToShow.forEach((String attr) {
String attrValue = entityModel.entity.getAttribute("$attr");
entityModel.entity.entity.attributesToShow.forEach((String attr) {
String attrValue = entityModel.entity.entity.getAttribute("$attr");
if (attrValue != null) {
attrs.add(
_buildSingleAttribute("$attr", "$attrValue"));

View File

@ -17,11 +17,11 @@ class EntityIcon extends StatelessWidget {
child: MaterialDesignIcons.createIconWidgetFromEntityData(
entityModel.entity,
iconSize,
EntityColor.stateColor(entityModel.entity.state)
EntityColor.stateColor(entityModel.entity.entity.state)
),
),
onTap: () => entityModel.handleTap
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity.entity))
: null,
);
}

View File

@ -26,7 +26,7 @@ class EntityName extends StatelessWidget {
),
onTap: () =>
entityModel.handleTap
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity.entity))
: null,
);
}

View File

@ -1,34 +1,42 @@
part of '../main.dart';
class GlanceEntityContainer extends StatelessWidget {
final bool showName;
final bool showState;
GlanceEntityContainer({
Key key,
Key key, @required this.showName, @required this.showState,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
EntityName(
List<Widget> result = [];
if (showName) {
result.add(EntityName(
padding: EdgeInsets.only(bottom: Sizes.rowPadding),
textOverflow: TextOverflow.ellipsis,
wordsWrap: false,
textAlign: TextAlign.center,
fontSize: Sizes.smallFontSize,
),
EntityIcon(
));
}
result.add(EntityIcon(
padding: EdgeInsets.all(0.0),
iconSize: Sizes.largeIconSize,
),
SimpleEntityState(
));
if (showState) {
result.add(SimpleEntityState(
textAlign: TextAlign.center,
expanded: false,
padding: EdgeInsets.only(top: Sizes.rowPadding),
)
],
));
}
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: result,
);
}
}

View File

@ -65,7 +65,7 @@ class _EntityHistoryWidgetState extends State<EntityHistoryWidget> {
Widget build(BuildContext context) {
final HomeAssistantModel homeAssistantModel = HomeAssistantModel.of(context);
final EntityModel entityModel = EntityModel.of(context);
final Entity entity = entityModel.entity;
final Entity entity = entityModel.entity.entity;
if (!_needToUpdateHistory) {
_needToUpdateHistory = true;
} else {

View File

@ -8,7 +8,7 @@ class LastUpdatedWidget extends StatelessWidget {
padding: EdgeInsets.fromLTRB(
Sizes.leftWidgetPadding, 0.0, 0.0, 0.0),
child: Text(
'${entityModel.entity.lastUpdated}',
'${entityModel.entity.entity.lastUpdated}',
textAlign: TextAlign.left,
style: TextStyle(
fontSize: Sizes.smallFontSize, color: Colors.black26),

View File

@ -8,7 +8,7 @@ class EntityModel extends InheritedWidget {
@required Widget child,
}) : super(key: key, child: child);
final Entity entity;
final EntityWrapper entity;
final bool handleTap;
static EntityModel of(BuildContext context) {

View File

@ -13,7 +13,7 @@ class ButtonStateWidget extends StatelessWidget {
height: 34.0,
child: FlatButton(
onPressed: (() {
_setNewState(entityModel.entity);
_setNewState(entityModel.entity.entity);
}),
child: Text(
"EXECUTE",

View File

@ -4,7 +4,7 @@ class ClimateStateWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final ClimateEntity entity = entityModel.entity;
final ClimateEntity entity = entityModel.entity.entity;
String targetTemp = "-";
if ((entity.supportTargetTemperature) && (entity.temperature != null)) {
targetTemp = "${entity.temperature}";

View File

@ -19,7 +19,7 @@ class CoverStateWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final CoverEntity entity = entityModel.entity;
final CoverEntity entity = entityModel.entity.entity;
List<Widget> buttons = [];
if (entity.supportOpen) {
buttons.add(IconButton(

View File

@ -4,7 +4,7 @@ class DateTimeStateWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final DateTimeEntity entity = entityModel.entity;
final DateTimeEntity entity = entityModel.entity.entity;
return Padding(
padding: EdgeInsets.fromLTRB(0.0, 0.0, Sizes.rightWidgetPadding, 0.0),
child: GestureDetector(

View File

@ -18,7 +18,7 @@ class _SelectStateWidgetState extends State<SelectStateWidget> {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final SelectEntity entity = entityModel.entity;
final SelectEntity entity = entityModel.entity.entity;
Widget ctrl;
if (entity.listOptions.isNotEmpty) {
ctrl = DropdownButton<String>(

View File

@ -15,7 +15,7 @@ class SimpleEntityState extends StatelessWidget {
padding: padding,
child: GestureDetector(
child: Text(
"${entityModel.entity.state}${entityModel.entity.unitOfMeasurement}",
"${entityModel.entity.entity.state}${entityModel.entity.entity.unitOfMeasurement}",
textAlign: textAlign,
maxLines: 4,
overflow: TextOverflow.ellipsis,
@ -24,7 +24,7 @@ class SimpleEntityState extends StatelessWidget {
fontSize: Sizes.stateFontSize,
)),
onTap: () => entityModel.handleTap
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity.entity))
: null,
)
);

View File

@ -34,7 +34,7 @@ class _SwitchStateWidgetState extends State<SwitchStateWidget> {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final entity = entityModel.entity;
final entity = entityModel.entity.entity;
if (!updatedHere) {
newState = entity.state;
} else {

View File

@ -55,7 +55,7 @@ class _TextInputStateWidgetState extends State<TextInputStateWidget> {
@override
Widget build(BuildContext context) {
final entityModel = EntityModel.of(context);
final TextEntity entity = entityModel.entity;
final TextEntity entity = entityModel.entity.entity;
_entityState = entity.state;
_entityDomain = entity.domain;
_entityId = entity.entityId;

View File

@ -413,20 +413,42 @@ class HomeAssistant {
name: rawCard["title"],
type: rawCard['type'],
columnsCount: rawCard['columns'] ?? 4,
showName: rawCard['show_name'] ?? true,
showState: rawCard['show_state'] ?? true,
);
rawCard["entities"]?.forEach((rawEntity) {
if (rawEntity is String) {
if (entities.isExist(rawEntity)) {
card.entities.add(entities.get(rawEntity));
card.entities.add(EntityWrapper(entity: entities.get(rawEntity)));
}
} else {
if (entities.isExist(rawEntity["entity"])) {
card.entities.add(entities.get(rawEntity["entity"]));
card.entities.add(
EntityWrapper(
entity: entities.get(rawEntity["entity"]),
displayName: rawEntity["name"],
icon: rawEntity["icon"]
)
);
}
}
});
if (rawCard["entity"] != null) {
card.linkedEntity = entities.get(rawCard["entity"]);
var en = rawCard["entity"];
if (en is String) {
if (entities.isExist(en)) {
card.linkedEntity = EntityWrapper(entity: entities.get(en));
}
} else {
if (entities.isExist(en["entity"])) {
card.linkedEntity = EntityWrapper(
entity: entities.get(en["entity"]),
icon: en["icon"],
displayName: en["name"]
);
}
}
}
result.add(card);
}

View File

@ -17,6 +17,7 @@ import 'package:charts_flutter/flutter.dart' as charts;
part 'entity_class/const.dart';
part 'entity_class/entity.class.dart';
part 'entity_class/entity_wrapper.class.dart';
part 'entity_class/switch_entity.class.dart';
part 'entity_class/button_entity.class.dart';
part 'entity_class/text_entity.class.dart';
@ -80,7 +81,7 @@ part 'ui_widgets/card_header_widget.dart';
EventBus eventBus = new EventBus();
const String appName = "HA Client";
const appVersion = "0.3.8 internal build 64";
const appVersion = "0.3.8-65";
String homeAssistantWebHost;
@ -480,7 +481,6 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
//expandedHeight: 100.0,
floating: true,
pinned: true,
primary: true,
@ -530,6 +530,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
if (_homeAssistant.ui == null || _homeAssistant.ui.views == null) {
return Scaffold(
key: _scaffoldKey,
primary: true,
drawer: _buildAppDrawer(),
body: _buildScaffoldBody(true)
);

View File

@ -2880,17 +2880,17 @@ class MaterialDesignIcons {
"mdi:blank": 0xf68c
};
static Widget createIconWidgetFromEntityData(Entity data, double size, Color color) {
static Widget createIconWidgetFromEntityData(EntityWrapper data, double size, Color color) {
if (data == null) {
return null;
}
if (data.entityPicture != null) {
if (data.entity.entityPicture != null) {
if (homeAssistantWebHost != null) {
return CircleAvatar(
radius: size/2,
backgroundColor: Colors.white,
backgroundImage: CachedNetworkImageProvider(
"$homeAssistantWebHost${data.entityPicture}",
"$homeAssistantWebHost${data.entity.entityPicture}",
),
);
} else {
@ -2902,8 +2902,8 @@ class MaterialDesignIcons {
if (iconName.length > 0) {
iconCode = getIconCodeByIconName(iconName);
} else {
iconCode = getDefaultIconByEntityId(data.entityId,
data.deviceClass, data.state); //
iconCode = getDefaultIconByEntityId(data.entity.entityId,
data.entity.deviceClass, data.entity.state); //
}
return Icon(
IconData(iconCode, fontFamily: 'Material Design Icons'),

View File

@ -1,11 +1,13 @@
part of '../main.dart';
class HACard {
List<Entity> entities = [];
Entity linkedEntity;
List<EntityWrapper> entities = [];
EntityWrapper linkedEntity;
String name;
String id;
String type;
bool showName;
bool showState;
int columnsCount;
HACard({
@ -13,6 +15,8 @@ class HACard {
this.id,
this.linkedEntity,
this.columnsCount: 4,
this.showName: true,
this.showState: true,
@required this.type
});

View File

@ -28,7 +28,7 @@ class HAView {
HACard card = HACard(
name: e.displayName,
id: e.entityId,
linkedEntity: e,
linkedEntity: EntityWrapper(entity: e),
type: "media-control"
);
cards.add(card);
@ -42,24 +42,24 @@ class HAView {
name: entity.domain,
type: "entities"
);
card.entities.add(entity);
card.entities.add(EntityWrapper(entity: entity));
autoGeneratedCards.add(card);
} else {
autoGeneratedCards.firstWhere((card) => card.id == groupIdToAdd).entities.add(entity);
autoGeneratedCards.firstWhere((card) => card.id == groupIdToAdd).entities.add(EntityWrapper(entity: entity));
}
} else {
HACard card = HACard(
name: entity.displayName,
id: entity.entityId,
linkedEntity: entity,
linkedEntity: EntityWrapper(entity: entity),
type: "entities"
);
card.entities.addAll(entity.childEntities.where((entity) {return entity.domain != "media_player";}));
card.entities.addAll(entity.childEntities.where((entity) {return entity.domain != "media_player";}).map((e) {return EntityWrapper(entity: entity);}));
entity.childEntities.where((entity) {return entity.domain == "media_player";}).forEach((entity){
HACard mediaCard = HACard(
name: entity.displayName,
id: entity.entityId,
linkedEntity: entity,
linkedEntity: EntityWrapper(entity: entity),
type: "media-control"
);
cards.add(mediaCard);

View File

@ -11,7 +11,7 @@ class EntitiesCardWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
if ((card.linkedEntity!= null) && (card.linkedEntity.isHidden)) {
if ((card.linkedEntity!= null) && (card.linkedEntity.entity.isHidden)) {
return Container(width: 0.0, height: 0.0,);
}
List<Widget> body = [];
@ -24,12 +24,16 @@ class EntitiesCardWidget extends StatelessWidget {
List<Widget> _buildCardBody(BuildContext context) {
List<Widget> result = [];
card.entities.forEach((Entity entity) {
if (!entity.isHidden) {
card.entities.forEach((EntityWrapper entity) {
if (!entity.entity.isHidden) {
result.add(
Padding(
padding: EdgeInsets.fromLTRB(0.0, Sizes.rowPadding, 0.0, Sizes.rowPadding),
child: entity.buildDefaultWidget(context),
child: EntityModel(
entity: entity,
handleTap: true,
child: entity.entity.buildDefaultWidget(context)
),
));
}
});

View File

@ -11,7 +11,7 @@ class GlanceCardWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
if ((card.linkedEntity!= null) && (card.linkedEntity.isHidden)) {
if ((card.linkedEntity!= null) && (card.linkedEntity.entity.isHidden)) {
return Container(width: 0.0, height: 0.0,);
}
List<Widget> rows = [];
@ -25,14 +25,18 @@ class GlanceCardWidget extends StatelessWidget {
Widget _buildRows(BuildContext context) {
List<Widget> result = [];
double width = MediaQuery.of(context).size.width - Sizes.leftWidgetPadding - (2*Sizes.rightWidgetPadding);
List<Entity> toShow = card.entities.where((entity) {return !entity.isHidden;}).toList();
List<EntityWrapper> toShow = card.entities.where((entity) {return !entity.entity.isHidden;}).toList();
int columnsCount = toShow.length >= card.columnsCount ? card.columnsCount : toShow.length;
card.entities.forEach((Entity entity) {
if (!entity.isHidden) {
card.entities.forEach((EntityWrapper entity) {
if (!entity.entity.isHidden) {
result.add(
SizedBox(
width: width / columnsCount,
child: entity.buildGlanceWidget(context),
child: EntityModel(
entity: entity,
child: entity.entity.buildGlanceWidget(context, card.showName, card.showState),
handleTap: true
),
)
);
}

View File

@ -11,7 +11,7 @@ class MediaControlCardWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
if ((card.linkedEntity == null) || (card.linkedEntity.isHidden)) {
if ((card.linkedEntity == null) || (card.linkedEntity.entity.isHidden)) {
return Container(width: 0.0, height: 0.0,);
}

View File

@ -11,7 +11,7 @@ class UnsupportedCardWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
if ((card.linkedEntity!= null) && (card.linkedEntity.isHidden)) {
if ((card.linkedEntity!= null) && (card.linkedEntity.entity.isHidden)) {
return Container(width: 0.0, height: 0.0,);
}
List<Widget> body = [];
@ -32,7 +32,11 @@ class UnsupportedCardWidget extends StatelessWidget {
result.addAll(<Widget>[
Padding(
padding: EdgeInsets.fromLTRB(0.0, Sizes.rowPadding, 0.0, Sizes.rowPadding),
child: card.linkedEntity.buildDefaultWidget(context),
child: EntityModel(
entity: card.linkedEntity,
handleTap: true,
child: card.linkedEntity.entity.buildDefaultWidget(context)
),
)
]);
} else {

View File

@ -1,7 +1,7 @@
name: hass_client
description: Home Assistant Android Client
version: 0.3.8+64
version: 0.3.8+65
environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0"