Some improvements
This commit is contained in:
parent
0a7bbb5a38
commit
01090dc3b1
@ -16,17 +16,6 @@ class Entity {
|
||||
"sensor"
|
||||
];
|
||||
|
||||
static const rightWidgetPadding = 14.0;
|
||||
static const leftWidgetPadding = 8.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;
|
||||
|
||||
Map attributes;
|
||||
String domain;
|
||||
String entityId;
|
||||
|
@ -174,7 +174,7 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
||||
_resetVars(entity);
|
||||
}
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(Entity.leftWidgetPadding, Entity.rowPadding, Entity.rightWidgetPadding, 0.0),
|
||||
padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, 0.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
@ -273,7 +273,7 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text("Target temperature", style: TextStyle(
|
||||
fontSize: Entity.stateFontSize
|
||||
fontSize: Sizes.stateFontSize
|
||||
)),
|
||||
TemperatureControlWidget(
|
||||
value: _tmpTemperature,
|
||||
@ -324,7 +324,7 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text("Target temperature range", style: TextStyle(
|
||||
fontSize: Entity.stateFontSize
|
||||
fontSize: Sizes.stateFontSize
|
||||
)),
|
||||
Row(
|
||||
children: controls,
|
||||
@ -342,7 +342,7 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
||||
result.addAll(<Widget>[
|
||||
Text(
|
||||
"$_tmpTargetHumidity%",
|
||||
style: TextStyle(fontSize: Entity.largeFontSize),
|
||||
style: TextStyle(fontSize: Sizes.largeFontSize),
|
||||
),
|
||||
Expanded(
|
||||
child: Slider(
|
||||
@ -366,9 +366,9 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
0.0, Entity.rowPadding, 0.0, Entity.rowPadding),
|
||||
0.0, Sizes.rowPadding, 0.0, Sizes.rowPadding),
|
||||
child: Text("Target humidity", style: TextStyle(
|
||||
fontSize: Entity.stateFontSize
|
||||
fontSize: Sizes.stateFontSize
|
||||
)),
|
||||
),
|
||||
Row(
|
||||
@ -376,7 +376,7 @@ class _ClimateControlWidgetState extends State<ClimateControlWidget> {
|
||||
children: result,
|
||||
),
|
||||
Container(
|
||||
height: Entity.rowPadding,
|
||||
height: Sizes.rowPadding,
|
||||
)
|
||||
],
|
||||
);
|
||||
|
@ -45,7 +45,7 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
|
||||
_resetVars(entity);
|
||||
}
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(Entity.leftWidgetPadding, Entity.rowPadding, Entity.rightWidgetPadding, 0.0),
|
||||
padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, 0.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
@ -63,9 +63,9 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
0.0, Entity.rowPadding, 0.0, Entity.rowPadding),
|
||||
0.0, Sizes.rowPadding, 0.0, Sizes.rowPadding),
|
||||
child: Text("Position", style: TextStyle(
|
||||
fontSize: Entity.stateFontSize
|
||||
fontSize: Sizes.stateFontSize
|
||||
)),
|
||||
),
|
||||
Slider(
|
||||
@ -81,7 +81,7 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
|
||||
},
|
||||
onChangeEnd: (double value) => _setNewPosition(entity, value),
|
||||
),
|
||||
Container(height: Entity.rowPadding,)
|
||||
Container(height: Sizes.rowPadding,)
|
||||
],
|
||||
);
|
||||
} else {
|
||||
@ -111,15 +111,15 @@ class _CoverControlWidgetState extends State<CoverControlWidget> {
|
||||
},
|
||||
onChangeEnd: (double value) => _setNewTiltPosition(entity, value),
|
||||
),
|
||||
Container(height: Entity.rowPadding,)
|
||||
Container(height: Sizes.rowPadding,)
|
||||
]);
|
||||
}
|
||||
if (controls.isNotEmpty) {
|
||||
controls.insert(0, Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
0.0, Entity.rowPadding, 0.0, Entity.rowPadding),
|
||||
0.0, Sizes.rowPadding, 0.0, Sizes.rowPadding),
|
||||
child: Text("Tilt position", style: TextStyle(
|
||||
fontSize: Entity.stateFontSize
|
||||
fontSize: Sizes.stateFontSize
|
||||
)),
|
||||
));
|
||||
return Column(
|
||||
@ -159,24 +159,24 @@ class CoverTiltControlsWidget extends StatelessWidget {
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName(
|
||||
"mdi:arrow-top-right"),
|
||||
size: Entity.iconSize,
|
||||
size: Sizes.iconSize,
|
||||
),
|
||||
onPressed: entity.canTiltBeOpened ? () => _open(entity) : null));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
width: Sizes.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
if (entity.supportStopTilt) {
|
||||
buttons.add(IconButton(
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName("mdi:stop"),
|
||||
size: Entity.iconSize,
|
||||
size: Sizes.iconSize,
|
||||
),
|
||||
onPressed: () => _stop(entity)));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
width: Sizes.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
if (entity.supportCloseTilt) {
|
||||
@ -184,12 +184,12 @@ class CoverTiltControlsWidget extends StatelessWidget {
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName(
|
||||
"mdi:arrow-bottom-left"),
|
||||
size: Entity.iconSize,
|
||||
size: Sizes.iconSize,
|
||||
),
|
||||
onPressed: entity.canTiltBeClosed ? () => _close(entity) : null));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
width: Sizes.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -102,12 +102,12 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Container(height: Entity.rowPadding,),
|
||||
Container(height: Sizes.rowPadding,),
|
||||
Text(
|
||||
"Brightness",
|
||||
style: TextStyle(fontSize: Entity.stateFontSize),
|
||||
style: TextStyle(fontSize: Sizes.stateFontSize),
|
||||
),
|
||||
Container(height: Entity.rowPadding,),
|
||||
Container(height: Sizes.rowPadding,),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Icon(Icons.brightness_5),
|
||||
@ -127,7 +127,7 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
|
||||
)
|
||||
],
|
||||
),
|
||||
Container(height: Entity.rowPadding,)
|
||||
Container(height: Sizes.rowPadding,)
|
||||
],
|
||||
);
|
||||
} else {
|
||||
@ -140,12 +140,12 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Container(height: Entity.rowPadding,),
|
||||
Container(height: Sizes.rowPadding,),
|
||||
Text(
|
||||
"Color temperature",
|
||||
style: TextStyle(fontSize: Entity.stateFontSize),
|
||||
style: TextStyle(fontSize: Sizes.stateFontSize),
|
||||
),
|
||||
Container(height: Entity.rowPadding,),
|
||||
Container(height: Sizes.rowPadding,),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Text("Cold", style: TextStyle(color: Colors.lightBlue),),
|
||||
@ -166,7 +166,7 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
|
||||
Text("Warm", style: TextStyle(color: Colors.amberAccent),),
|
||||
],
|
||||
),
|
||||
Container(height: Entity.rowPadding,)
|
||||
Container(height: Sizes.rowPadding,)
|
||||
],
|
||||
);
|
||||
} else {
|
||||
@ -179,7 +179,7 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Container(height: Entity.rowPadding,),
|
||||
Container(height: Sizes.rowPadding,),
|
||||
RaisedButton(
|
||||
onPressed: () => _showColorPicker(entity),
|
||||
color: _tmpColor ?? Colors.black45,
|
||||
@ -193,7 +193,7 @@ class _LightControlsWidgetState extends State<LightControlsWidget> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(height: 2*Entity.rowPadding,),
|
||||
Container(height: 2*Sizes.rowPadding,),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
|
155
lib/entity_widgets/controls/media_player_widget.dart
Normal file
155
lib/entity_widgets/controls/media_player_widget.dart
Normal file
@ -0,0 +1,155 @@
|
||||
part of '../../main.dart';
|
||||
|
||||
class MediaPlayerWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final EntityModel entityModel = EntityModel.of(context);
|
||||
final MediaPlayerEntity entity = entityModel.entity;
|
||||
List<Widget> body = [];
|
||||
body.add(Stack(
|
||||
alignment: AlignmentDirectional.topEnd,
|
||||
children: <Widget>[
|
||||
_buildImage(entity),
|
||||
Positioned(
|
||||
bottom: 0.0,
|
||||
left: 0.0,
|
||||
right: 0.0,
|
||||
child: Container(
|
||||
color: Colors.black45,
|
||||
child: _buildState(entity),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0.0,
|
||||
left: 0.0,
|
||||
right: 0.0,
|
||||
child: MediaPlayerProgressWidget()
|
||||
)
|
||||
],
|
||||
));
|
||||
return Column(
|
||||
children: body
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildState(MediaPlayerEntity entity) {
|
||||
TextStyle style = TextStyle(
|
||||
fontSize: 14.0,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.normal,
|
||||
height: 1.2
|
||||
);
|
||||
List<Widget> states = [];
|
||||
states.add(Text("${entity.displayName}", style: style));
|
||||
String state = entity.state;
|
||||
if (state == null || state == "off" || state == "unavailable" || state == "idle") {
|
||||
states.add(Text("${entity.state}", style: style.apply(fontSizeDelta: 4.0),));
|
||||
}
|
||||
if (entity.attributes['media_title'] != null) {
|
||||
states.add(Text("${entity.attributes['media_title']}", style: style.apply(fontSizeDelta: 6.0, fontWeightDelta: 50),));
|
||||
}
|
||||
if (entity.attributes['media_content_type'] == "music") {
|
||||
states.add(Text("${entity.attributes['media_artist'] ?? entity.attributes['app_name']}", style: style.apply(fontSizeDelta: 4.0),));
|
||||
} else if (entity.attributes['app_name'] != null) {
|
||||
states.add(Text("${entity.attributes['app_name']}", style: style.apply(fontSizeDelta: 4.0),));
|
||||
}
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, Sizes.rowPadding),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: states,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildImage(MediaPlayerEntity entity) {
|
||||
String state = entity.state;
|
||||
if (homeAssistantWebHost != null && entity.entityPicture != null && state != "off" && state != "unavailable" && state != "idle") {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Image(
|
||||
image: CachedNetworkImageProvider("$homeAssistantWebHost${entity.entityPicture}"),
|
||||
height: 240.0,
|
||||
width: 320.0,
|
||||
fit: BoxFit.fitHeight,
|
||||
)
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName("mdi:movie"),
|
||||
size: 150.0,
|
||||
color: EntityColors.stateColor("$state"),
|
||||
)
|
||||
],
|
||||
);
|
||||
/*return Container(
|
||||
color: Colors.blue,
|
||||
height: 80.0,
|
||||
);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MediaPlayerProgressWidget extends StatefulWidget {
|
||||
@override
|
||||
_MediaPlayerProgressWidgetState createState() => _MediaPlayerProgressWidgetState();
|
||||
}
|
||||
|
||||
class _MediaPlayerProgressWidgetState extends State<MediaPlayerProgressWidget> {
|
||||
|
||||
Timer _timer;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final EntityModel entityModel = EntityModel.of(context);
|
||||
final MediaPlayerEntity entity = entityModel.entity;
|
||||
double progress;
|
||||
try {
|
||||
DateTime lastUpdated = DateTime.parse(
|
||||
entity.attributes["media_position_updated_at"]).toLocal();
|
||||
Duration duration = Duration(seconds: entity._getIntAttributeValue("media_duration") ?? 1);
|
||||
Duration position = Duration(seconds: entity._getIntAttributeValue("media_position") ?? 0);
|
||||
int currentPosition = position.inSeconds;
|
||||
if (entity.state == "playing") {
|
||||
_timer?.cancel();
|
||||
_timer = Timer(Duration(seconds: 1), () {
|
||||
setState(() {
|
||||
});
|
||||
});
|
||||
int differenceInSeconds = DateTime
|
||||
.now()
|
||||
.difference(lastUpdated)
|
||||
.inSeconds;
|
||||
currentPosition = currentPosition + differenceInSeconds;
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
}
|
||||
progress = currentPosition / duration.inSeconds;
|
||||
return LinearProgressIndicator(
|
||||
value: progress,
|
||||
backgroundColor: Colors.black45,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(EntityColors.stateColor("on")),
|
||||
);
|
||||
} catch (e) {
|
||||
_timer?.cancel();
|
||||
progress = 0.0;
|
||||
}
|
||||
return LinearProgressIndicator(
|
||||
value: progress,
|
||||
backgroundColor: Colors.black45,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
}
|
@ -34,7 +34,7 @@ class EntityAttributesList extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
Entity.leftWidgetPadding, Entity.rowPadding, 0.0, 0.0),
|
||||
Sizes.leftWidgetPadding, Sizes.rowPadding, 0.0, 0.0),
|
||||
child: Text(
|
||||
"$name",
|
||||
textAlign: TextAlign.left,
|
||||
@ -44,7 +44,7 @@ class EntityAttributesList extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
0.0, Entity.rowPadding, Entity.rightWidgetPadding, 0.0),
|
||||
0.0, Sizes.rowPadding, Sizes.rightWidgetPadding, 0.0),
|
||||
child: Text(
|
||||
"$value",
|
||||
textAlign: TextAlign.right,
|
||||
|
@ -7,10 +7,10 @@ class EntityIcon extends StatelessWidget {
|
||||
return GestureDetector(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
Entity.leftWidgetPadding, 0.0, 12.0, 0.0),
|
||||
Sizes.leftWidgetPadding, 0.0, 12.0, 0.0),
|
||||
child: MaterialDesignIcons.createIconWidgetFromEntityData(
|
||||
entityModel.entity,
|
||||
Entity.iconSize,
|
||||
Sizes.iconSize,
|
||||
EntityColors.stateColor(entityModel.entity.state)
|
||||
),
|
||||
),
|
||||
|
@ -11,7 +11,7 @@ class EntityName extends StatelessWidget {
|
||||
"${entityModel.entity.displayName}",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
style: TextStyle(fontSize: Entity.nameFontSize),
|
||||
style: TextStyle(fontSize: Sizes.nameFontSize),
|
||||
),
|
||||
),
|
||||
onTap: () =>
|
||||
|
@ -69,7 +69,7 @@ class _CombinedHistoryChartWidgetState extends State<CombinedHistoryChartWidget>
|
||||
selectionModels: [
|
||||
new charts.SelectionModelConfig(
|
||||
type: charts.SelectionModelType.info,
|
||||
listener: (model) => _onSelectionChanged(model),
|
||||
changedListener: (model) => _onSelectionChanged(model),
|
||||
)
|
||||
],
|
||||
customSeriesRenderers: [
|
||||
|
@ -83,7 +83,7 @@ class _EntityHistoryWidgetState extends State<EntityHistoryWidget> {
|
||||
}
|
||||
children.add(Divider());
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, Entity.rowPadding),
|
||||
padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, Sizes.rowPadding),
|
||||
child: Column(
|
||||
children: children,
|
||||
),
|
||||
|
@ -57,7 +57,7 @@ class _NumericStateHistoryChartWidgetState extends State<NumericStateHistoryChar
|
||||
selectionModels: [
|
||||
new charts.SelectionModelConfig(
|
||||
type: charts.SelectionModelType.info,
|
||||
listener: (model) => _onSelectionChanged(model),
|
||||
changedListener: (model) => _onSelectionChanged(model),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@ -53,7 +53,7 @@ class _SimpleStateHistoryChartWidgetState extends State<SimpleStateHistoryChartW
|
||||
selectionModels: [
|
||||
new charts.SelectionModelConfig(
|
||||
type: charts.SelectionModelType.info,
|
||||
listener: (model) => _onSelectionChanged(model),
|
||||
changedListener: (model) => _onSelectionChanged(model),
|
||||
)
|
||||
],
|
||||
customSeriesRenderers: [
|
||||
|
@ -6,12 +6,12 @@ class LastUpdatedWidget extends StatelessWidget {
|
||||
final entityModel = EntityModel.of(context);
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
Entity.leftWidgetPadding, 0.0, 0.0, 0.0),
|
||||
Sizes.leftWidgetPadding, 0.0, 0.0, 0.0),
|
||||
child: Text(
|
||||
'${entityModel.entity.lastUpdated}',
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontSize: Entity.smallFontSize, color: Colors.black26),
|
||||
fontSize: Sizes.smallFontSize, color: Colors.black26),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class ModeSelectorWidget extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text("$caption", style: TextStyle(
|
||||
fontSize: captionFontSize ?? Entity.stateFontSize
|
||||
fontSize: captionFontSize ?? Sizes.stateFontSize
|
||||
)),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
@ -39,7 +39,7 @@ class ModeSelectorWidget extends StatelessWidget {
|
||||
iconSize: 30.0,
|
||||
isExpanded: true,
|
||||
style: TextStyle(
|
||||
fontSize: valueFontSize ?? Entity.largeFontSize,
|
||||
fontSize: valueFontSize ?? Sizes.largeFontSize,
|
||||
color: Colors.black,
|
||||
),
|
||||
hint: Text("Select ${caption.toLowerCase()}"),
|
||||
@ -55,7 +55,7 @@ class ModeSelectorWidget extends StatelessWidget {
|
||||
)
|
||||
],
|
||||
),
|
||||
Container(height: bottomPadding ?? Entity.rowPadding,)
|
||||
Container(height: bottomPadding ?? Sizes.rowPadding,)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ class ModeSwitchWidget extends StatelessWidget {
|
||||
child: Text(
|
||||
"$caption",
|
||||
style: TextStyle(
|
||||
fontSize: captionFontSize ?? Entity.stateFontSize
|
||||
fontSize: captionFontSize ?? Sizes.stateFontSize
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -19,7 +19,7 @@ class ButtonStateWidget extends StatelessWidget {
|
||||
"EXECUTE",
|
||||
textAlign: TextAlign.right,
|
||||
style:
|
||||
new TextStyle(fontSize: Entity.stateFontSize, color: Colors.blue),
|
||||
new TextStyle(fontSize: Sizes.stateFontSize, color: Colors.blue),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
@ -18,7 +18,7 @@ class ClimateStateWidget extends StatelessWidget {
|
||||
}
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
0.0, 0.0, Entity.rightWidgetPadding, 0.0),
|
||||
0.0, 0.0, Sizes.rightWidgetPadding, 0.0),
|
||||
child: GestureDetector(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
@ -30,12 +30,12 @@ class ClimateStateWidget extends StatelessWidget {
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: Entity.stateFontSize,
|
||||
fontSize: Sizes.stateFontSize,
|
||||
)),
|
||||
Text(" $targetTemp",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: Entity.stateFontSize,
|
||||
fontSize: Sizes.stateFontSize,
|
||||
))
|
||||
],
|
||||
),
|
||||
@ -43,7 +43,7 @@ class ClimateStateWidget extends StatelessWidget {
|
||||
Text("Currently: ${entity.attributes["current_temperature"]}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: Entity.stateFontSize,
|
||||
fontSize: Sizes.stateFontSize,
|
||||
color: Colors.black45)
|
||||
) :
|
||||
Container(height: 0.0,)
|
||||
|
@ -25,36 +25,36 @@ class CoverStateWidget extends StatelessWidget {
|
||||
buttons.add(IconButton(
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName("mdi:arrow-up"),
|
||||
size: Entity.iconSize,
|
||||
size: Sizes.iconSize,
|
||||
),
|
||||
onPressed: entity.canBeOpened ? () => _open(entity) : null));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
width: Sizes.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
if (entity.supportStop) {
|
||||
buttons.add(IconButton(
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName("mdi:stop"),
|
||||
size: Entity.iconSize,
|
||||
size: Sizes.iconSize,
|
||||
),
|
||||
onPressed: () => _stop(entity)));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
width: Sizes.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
if (entity.supportClose) {
|
||||
buttons.add(IconButton(
|
||||
icon: Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName("mdi:arrow-down"),
|
||||
size: Entity.iconSize,
|
||||
size: Sizes.iconSize,
|
||||
),
|
||||
onPressed: entity.canBeClosed ? () => _close(entity) : null));
|
||||
} else {
|
||||
buttons.add(Container(
|
||||
width: Entity.iconSize + 20.0,
|
||||
width: Sizes.iconSize + 20.0,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -6,12 +6,12 @@ class DateTimeStateWidget extends StatelessWidget {
|
||||
final entityModel = EntityModel.of(context);
|
||||
final DateTimeEntity entity = entityModel.entity;
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 0.0, Entity.rightWidgetPadding, 0.0),
|
||||
padding: EdgeInsets.fromLTRB(0.0, 0.0, Sizes.rightWidgetPadding, 0.0),
|
||||
child: GestureDetector(
|
||||
child: Text("${entity.formattedState}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: Entity.stateFontSize,
|
||||
fontSize: Sizes.stateFontSize,
|
||||
)),
|
||||
onTap: () => _handleStateTap(context, entity),
|
||||
));
|
||||
|
@ -10,13 +10,13 @@ class SimpleEntityState extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final entityModel = EntityModel.of(context);
|
||||
Widget result = Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, 0.0, Entity.rightWidgetPadding, 0.0),
|
||||
padding: EdgeInsets.fromLTRB(0.0, 0.0, Sizes.rightWidgetPadding, 0.0),
|
||||
child: GestureDetector(
|
||||
child: Text(
|
||||
"${entityModel.entity.state}${entityModel.entity.unitOfMeasurement}",
|
||||
textAlign: TextAlign.right,
|
||||
style: new TextStyle(
|
||||
fontSize: Entity.stateFontSize,
|
||||
fontSize: Sizes.stateFontSize,
|
||||
)),
|
||||
onTap: () => entityModel.handleTap
|
||||
? eventBus.fire(new ShowEntityPageEvent(entityModel.entity))
|
||||
|
@ -52,13 +52,13 @@ class _SwitchStateWidgetState extends State<SwitchStateWidget> {
|
||||
onPressed: () => _setNewState(false, entity),
|
||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName("mdi:flash-off")),
|
||||
color: entity.assumedState == 'on' ? Colors.black : Colors.blue,
|
||||
iconSize: Entity.iconSize,
|
||||
iconSize: Sizes.iconSize,
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => _setNewState(true, entity),
|
||||
icon: Icon(MaterialDesignIcons.createIconDataFromIconName("mdi:flash")),
|
||||
color: entity.assumedState == 'on' ? Colors.blue : Colors.black,
|
||||
iconSize: Entity.iconSize
|
||||
iconSize: Sizes.iconSize
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@ -56,6 +56,7 @@ part 'entity_widgets/state/button_state.dart';
|
||||
part 'entity_widgets/controls/climate_controls.dart';
|
||||
part 'entity_widgets/controls/cover_controls.dart';
|
||||
part 'entity_widgets/controls/light_controls.dart';
|
||||
part 'entity_widgets/controls/media_player_widget.dart';
|
||||
part 'settings.page.dart';
|
||||
part 'home_assistant.class.dart';
|
||||
part 'log.page.dart';
|
||||
@ -66,6 +67,7 @@ part 'entity_collection.class.dart';
|
||||
part 'ui_class/ui.dart';
|
||||
part 'ui_class/view.class.dart';
|
||||
part 'ui_class/card.class.dart';
|
||||
part 'ui_class/sizes_class.dart';
|
||||
part 'ui_widgets/view.dart';
|
||||
part 'ui_widgets/entities_card.dart';
|
||||
part 'ui_widgets/unsupported_card.dart';
|
||||
|
14
lib/ui_class/sizes_class.dart
Normal file
14
lib/ui_class/sizes_class.dart
Normal file
@ -0,0 +1,14 @@
|
||||
part of '../main.dart';
|
||||
|
||||
class Sizes {
|
||||
static const rightWidgetPadding = 14.0;
|
||||
static const leftWidgetPadding = 8.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;
|
||||
}
|
@ -14,126 +14,16 @@ class MediaControlCardWidget extends StatelessWidget {
|
||||
if ((card.linkedEntity == null) || (card.linkedEntity.isHidden)) {
|
||||
return Container(width: 0.0, height: 0.0,);
|
||||
}
|
||||
List<Widget> body = [];
|
||||
body.add(Stack(
|
||||
alignment: AlignmentDirectional.topEnd,
|
||||
children: <Widget>[
|
||||
_buildImage(),
|
||||
Positioned(
|
||||
bottom: 0.0,
|
||||
left: 0.0,
|
||||
right: 0.0,
|
||||
child: Container(
|
||||
color: Colors.black45,
|
||||
child: _buildState(),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0.0,
|
||||
left: 0.0,
|
||||
right: 0.0,
|
||||
child: _buildProgress(),
|
||||
)
|
||||
],
|
||||
));
|
||||
|
||||
return Card(
|
||||
child: Column(
|
||||
//crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: body
|
||||
child: EntityModel(
|
||||
entity: card.linkedEntity,
|
||||
handleTap: null,
|
||||
child: MediaPlayerWidget()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildProgress() {
|
||||
double progress;
|
||||
try {
|
||||
DateTime lastUpdated = DateTime.parse(
|
||||
card.linkedEntity.attributes["media_position_updated_at"]).toLocal();
|
||||
Duration duration = Duration(seconds: card.linkedEntity._getIntAttributeValue("media_duration") ?? 1);
|
||||
Duration position = Duration(seconds: card.linkedEntity._getIntAttributeValue("media_position") ?? 0);
|
||||
int currentPosition = position.inSeconds;
|
||||
if (card.linkedEntity.state == "playing") {
|
||||
int differenceInSeconds = DateTime
|
||||
.now()
|
||||
.difference(lastUpdated)
|
||||
.inSeconds;
|
||||
currentPosition = currentPosition + differenceInSeconds;
|
||||
}
|
||||
progress = currentPosition / duration.inSeconds;
|
||||
return LinearProgressIndicator(
|
||||
value: progress,
|
||||
backgroundColor: Colors.black45,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(EntityColors.stateColor("on")),
|
||||
);
|
||||
} catch (e) {
|
||||
progress = 0.0;
|
||||
}
|
||||
return LinearProgressIndicator(
|
||||
value: progress,
|
||||
backgroundColor: Colors.black45,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildState() {
|
||||
TextStyle style = TextStyle(
|
||||
fontSize: 14.0,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.normal,
|
||||
height: 1.2
|
||||
);
|
||||
List<Widget> states = [];
|
||||
states.add(Text("${card.linkedEntity.displayName}", style: style));
|
||||
String state = card.linkedEntity.state;
|
||||
if (state == null || state == "off" || state == "unavailable" || state == "idle") {
|
||||
states.add(Text("${card.linkedEntity.state}", style: style.apply(fontSizeDelta: 4.0),));
|
||||
}
|
||||
if (card.linkedEntity.attributes['media_title'] != null) {
|
||||
states.add(Text("${card.linkedEntity.attributes['media_title']}", style: style.apply(fontSizeDelta: 6.0, fontWeightDelta: 50),));
|
||||
}
|
||||
if (card.linkedEntity.attributes['media_content_type'] == "music") {
|
||||
states.add(Text("${card.linkedEntity.attributes['media_artist'] ?? card.linkedEntity.attributes['app_name']}", style: style.apply(fontSizeDelta: 4.0),));
|
||||
} else if (card.linkedEntity.attributes['app_name'] != null) {
|
||||
states.add(Text("${card.linkedEntity.attributes['app_name']}", style: style.apply(fontSizeDelta: 4.0),));
|
||||
}
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(Entity.leftWidgetPadding, Entity.rowPadding, Entity.rightWidgetPadding, Entity.rowPadding),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: states,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildImage() {
|
||||
String state = card.linkedEntity.state;
|
||||
if (homeAssistantWebHost != null && card.linkedEntity.entityPicture != null && state != "off" && state != "unavailable" && state != "idle") {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Image(
|
||||
image: CachedNetworkImageProvider("$homeAssistantWebHost${card.linkedEntity.entityPicture}"),
|
||||
height: 240.0,
|
||||
width: 320.0,
|
||||
fit: BoxFit.fitHeight,
|
||||
)
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
MaterialDesignIcons.createIconDataFromIconName("mdi:movie"),
|
||||
size: 150.0,
|
||||
color: EntityColors.stateColor("$state"),
|
||||
)
|
||||
],
|
||||
);
|
||||
/*return Container(
|
||||
color: Colors.blue,
|
||||
height: 80.0,
|
||||
);*/
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -31,14 +31,14 @@ class UnsupportedCardWidget extends StatelessWidget {
|
||||
if (card.linkedEntity != null) {
|
||||
result.addAll(<Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(0.0, Entity.rowPadding, 0.0, Entity.rowPadding),
|
||||
padding: EdgeInsets.fromLTRB(0.0, Sizes.rowPadding, 0.0, Sizes.rowPadding),
|
||||
child: card.linkedEntity.buildDefaultWidget(context),
|
||||
)
|
||||
]);
|
||||
} else {
|
||||
result.addAll(<Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(Entity.leftWidgetPadding, Entity.rowPadding, Entity.rightWidgetPadding, Entity.rowPadding),
|
||||
padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, Sizes.rowPadding),
|
||||
child: Text("'${card.type}' card is not supported yet"),
|
||||
),
|
||||
]);
|
||||
|
30
pubspec.lock
30
pubspec.lock
@ -7,7 +7,7 @@ packages:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.32.4"
|
||||
version: "0.33.0"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -42,7 +42,7 @@ packages:
|
||||
name: cached_network_image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.2"
|
||||
version: "0.5.0+1"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -56,14 +56,14 @@ packages:
|
||||
name: charts_common
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.0"
|
||||
version: "0.5.0"
|
||||
charts_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: charts_flutter
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.0"
|
||||
version: "0.5.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -91,7 +91,7 @@ packages:
|
||||
name: csslib
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.14.5"
|
||||
version: "0.14.6"
|
||||
dart_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -126,7 +126,7 @@ packages:
|
||||
name: flutter_cache_manager
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2"
|
||||
version: "0.2.0+1"
|
||||
flutter_colorpicker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -152,7 +152,7 @@ packages:
|
||||
name: front_end
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.4"
|
||||
version: "0.1.6"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -173,7 +173,7 @@ packages:
|
||||
name: http
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.11.3+17"
|
||||
version: "0.12.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -229,7 +229,7 @@ packages:
|
||||
name: kernel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.4"
|
||||
version: "0.3.6"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -285,7 +285,7 @@ packages:
|
||||
name: package_resolver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
version: "1.0.6"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -395,7 +395,7 @@ packages:
|
||||
name: source_maps
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.10.7"
|
||||
version: "0.10.8"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -444,7 +444,7 @@ packages:
|
||||
name: test
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.3.4"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -458,7 +458,7 @@ packages:
|
||||
name: url_launcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
version: "4.0.1"
|
||||
utf:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -516,5 +516,5 @@ packages:
|
||||
source: hosted
|
||||
version: "2.1.15"
|
||||
sdks:
|
||||
dart: ">=2.0.0 <=2.1.0-dev.5.0.flutter-a2eb050044"
|
||||
flutter: ">=0.1.4 <2.0.0"
|
||||
dart: ">=2.0.0 <=2.1.0-dev.8.0.flutter-bf26f760b1"
|
||||
flutter: ">=0.5.6 <2.0.0"
|
||||
|
16
pubspec.yaml
16
pubspec.yaml
@ -10,13 +10,13 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
shared_preferences: any
|
||||
progress_indicators: ^0.1.2
|
||||
event_bus: ^1.0.1
|
||||
cached_network_image: ^0.4.1
|
||||
url_launcher: ^3.0.3
|
||||
date_format: ^1.0.5
|
||||
flutter_colorpicker: ^0.1.0
|
||||
charts_flutter: ^0.4.0
|
||||
progress_indicators: any
|
||||
event_bus: any
|
||||
cached_network_image: any
|
||||
url_launcher: any
|
||||
date_format: any
|
||||
flutter_colorpicker: any
|
||||
charts_flutter: any
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
@ -25,7 +25,7 @@ dependencies:
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_launcher_icons: ^0.6.1
|
||||
flutter_launcher_icons: any
|
||||
|
||||
flutter_icons:
|
||||
android: true
|
||||
|
Reference in New Issue
Block a user