Resolves #530 Badges refactoring

This commit is contained in:
Yegor Vialov
2020-05-09 18:08:42 +00:00
parent e258b3bc2c
commit 1d1d132b33
7 changed files with 141 additions and 72 deletions

View File

@ -10,17 +10,43 @@ class Badges extends StatelessWidget {
List<EntityWrapper> entitiesToShow = badges.getEntitiesToShow(); List<EntityWrapper> entitiesToShow = badges.getEntitiesToShow();
if (entitiesToShow.isNotEmpty) { if (entitiesToShow.isNotEmpty) {
return Wrap( if (ConnectionManager().scrollBadges) {
alignment: WrapAlignment.center, return ConstrainedBox(
spacing: 10.0, constraints: BoxConstraints.tightFor(height: 112),
runSpacing: 1.0, child: SingleChildScrollView(
children: entitiesToShow.map((entity) => scrollDirection: Axis.horizontal,
EntityModel( child: Row(
entityWrapper: entity, mainAxisSize: MainAxisSize.min,
child: BadgeWidget(), mainAxisAlignment: MainAxisAlignment.center,
handleTap: true, crossAxisAlignment: CrossAxisAlignment.start,
)).toList(), children: entitiesToShow.map((entity) =>
); EntityModel(
entityWrapper: entity,
child: Padding(
padding: EdgeInsets.fromLTRB(5, 10, 5, 10),
child: BadgeWidget(),
),
handleTap: true,
)).toList()
),
)
);
} else {
return Padding(
padding: EdgeInsets.fromLTRB(5, 10, 5, 10),
child: Wrap(
alignment: WrapAlignment.center,
spacing: 10.0,
runSpacing: 5,
children: entitiesToShow.map((entity) =>
EntityModel(
entityWrapper: entity,
child: BadgeWidget(),
handleTap: true,
)).toList(),
)
);
}
} }
return Container(height: 0.0, width: 0.0,); return Container(height: 0.0, width: 0.0,);
} }

View File

@ -57,72 +57,73 @@ class BadgeWidget extends StatelessWidget {
onBadgeText = Container(width: 0.0, height: 0.0); onBadgeText = Container(width: 0.0, height: 0.0);
} else { } else {
onBadgeText = Container( onBadgeText = Container(
padding: EdgeInsets.fromLTRB(6.0, 2.0, 6.0, 2.0), constraints: BoxConstraints(maxWidth: 50),
child: Text("$onBadgeTextValue", padding: EdgeInsets.fromLTRB(6.0, 2.0, 6.0, 2.0),
style: Theme.of(context).textTheme.overline.copyWith( child: Text("$onBadgeTextValue",
color: HAClientTheme().getOnBadgeTextColor() style: Theme.of(context).textTheme.overline.copyWith(
), color: HAClientTheme().getOnBadgeTextColor()
textAlign: TextAlign.center, ),
softWrap: false, textAlign: TextAlign.center,
overflow: TextOverflow.fade), softWrap: false,
decoration: new BoxDecoration( overflow: TextOverflow.ellipsis
color: iconColor, ),
borderRadius: BorderRadius.circular(9.0), decoration: new BoxDecoration(
)); color: iconColor,
borderRadius: BorderRadius.circular(9.0),
)
);
} }
return GestureDetector( return GestureDetector(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
Container( Stack(
//margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0), overflow: Overflow.visible,
width: 45, alignment: Alignment.center,
height: 45, children: <Widget>[
decoration: new BoxDecoration( Container(
// Circle shape width: 45,
shape: BoxShape.circle, height: 45,
color: Theme.of(context).cardColor, decoration: new BoxDecoration(
// The border you want // Circle shape
border: new Border.all( shape: BoxShape.circle,
width: 2.0, color: Theme.of(context).cardColor,
color: iconColor, // The border you want
), border: Border.all(
), width: 2.0,
child: Stack( color: iconColor,
overflow: Overflow.visible,
children: <Widget>[
Positioned(
width: 45,
height: 45,
top: 0.0,
left: 0.0,
child: FittedBox(
fit: BoxFit.contain,
alignment: Alignment.center,
child: badgeIcon,
), ),
), ),
Positioned( ),
bottom: -9.0, SizedBox(
left: -10.0, width: 38,
right: -10.0, height: 26,
child: Center( child: FittedBox(
child: onBadgeText, fit: BoxFit.contain,
) alignment: Alignment.center,
child: badgeIcon,
) )
], ),
), Positioned(
bottom: -6,
child: onBadgeText
)
],
), ),
Container( Container(
width: 60.0, constraints: BoxConstraints(maxWidth: 45),
padding: EdgeInsets.only(top: 10),
child: Text( child: Text(
"${entityModel.entityWrapper.displayName}", "${entityModel.entityWrapper.displayName}",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.caption, style: Theme.of(context).textTheme.caption.copyWith(
fontSize: 10
),
softWrap: true, softWrap: true,
maxLines: 3, maxLines: 3,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
), )
], ],
), ),
onTap: () => entityModel.entityWrapper.handleTap(), onTap: () => entityModel.entityWrapper.handleTap(),

View File

@ -20,6 +20,7 @@ class ConnectionManager {
String oauthUrl; String oauthUrl;
String webhookId; String webhookId;
double haVersion; double haVersion;
bool scrollBadges;
String mobileAppDeviceName; String mobileAppDeviceName;
bool settingsLoaded = false; bool settingsLoaded = false;
int appIntegrationVersion; int appIntegrationVersion;
@ -48,6 +49,7 @@ class ConnectionManager {
webhookId = prefs.getString('app-webhook-id'); webhookId = prefs.getString('app-webhook-id');
appIntegrationVersion = prefs.getInt('app-integration-version') ?? 0; appIntegrationVersion = prefs.getInt('app-integration-version') ?? 0;
mobileAppDeviceName = prefs.getString('app-integration-device-name'); mobileAppDeviceName = prefs.getString('app-integration-device-name');
scrollBadges = prefs.getBool('scroll-badges') ?? true;
displayHostname = "$_domain:$_port"; displayHostname = "$_domain:$_port";
_webSocketAPIEndpoint = _webSocketAPIEndpoint =
"${prefs.getString('hassio-protocol')}://$_domain:$_port/api/websocket"; "${prefs.getString('hassio-protocol')}://$_domain:$_port/api/websocket";

View File

@ -12,7 +12,7 @@ class LookAndFeelSettingsPage extends StatefulWidget {
class _LookAndFeelSettingsPageState extends State<LookAndFeelSettingsPage> { class _LookAndFeelSettingsPageState extends State<LookAndFeelSettingsPage> {
AppTheme _currentTheme; AppTheme _currentTheme;
bool _changed = false; bool _scrollBadges = false;
@override @override
void initState() { void initState() {
@ -26,13 +26,15 @@ class _LookAndFeelSettingsPageState extends State<LookAndFeelSettingsPage> {
SharedPreferences.getInstance().then((prefs) { SharedPreferences.getInstance().then((prefs) {
setState(() { setState(() {
_currentTheme = AppTheme.values[prefs.getInt("app-theme") ?? AppTheme.defaultTheme.index]; _currentTheme = AppTheme.values[prefs.getInt("app-theme") ?? AppTheme.defaultTheme.index];
_scrollBadges = prefs.getBool('scroll-badges') ?? true;
}); });
}); });
} }
_saveSettings(AppTheme theme) { _saveTheme(AppTheme theme) {
SharedPreferences.getInstance().then((prefs) { SharedPreferences.getInstance().then((prefs) {
prefs.setInt('app-theme', theme.index); prefs.setInt('app-theme', theme.index);
prefs.setBool('scroll-badges', _scrollBadges);
setState(() { setState(() {
_currentTheme = theme; _currentTheme = theme;
eventBus.fire(ChangeThemeEvent(_currentTheme)); eventBus.fire(ChangeThemeEvent(_currentTheme));
@ -40,6 +42,12 @@ class _LookAndFeelSettingsPageState extends State<LookAndFeelSettingsPage> {
}); });
} }
Future _saveOther() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
ConnectionManager().scrollBadges = _scrollBadges;
await prefs.setBool('scroll-badges', _scrollBadges);
}
Map appThemeName = { Map appThemeName = {
AppTheme.defaultTheme: 'Default', AppTheme.defaultTheme: 'Default',
AppTheme.haTheme: 'Home Assistant theme', AppTheme.haTheme: 'Home Assistant theme',
@ -59,15 +67,35 @@ class _LookAndFeelSettingsPageState extends State<LookAndFeelSettingsPage> {
iconSize: 30.0, iconSize: 30.0,
isExpanded: true, isExpanded: true,
style: Theme.of(context).textTheme.title, style: Theme.of(context).textTheme.title,
//hint: Text("Select ${caption.toLowerCase()}"),
items: AppTheme.values.map((value) { items: AppTheme.values.map((value) {
return new DropdownMenuItem<AppTheme>( return new DropdownMenuItem<AppTheme>(
value: value, value: value,
child: Text('${appThemeName[value]}'), child: Text('${appThemeName[value]}'),
); );
}).toList(), }).toList(),
onChanged: (theme) => _saveSettings(theme), onChanged: (theme) => _saveTheme(theme),
) ),
Container(height: Sizes.doubleRowPadding),
Text("Badges display:", style: Theme.of(context).textTheme.body2),
Container(height: Sizes.rowPadding),
DropdownButton<bool>(
value: _scrollBadges,
iconSize: 30.0,
isExpanded: true,
style: Theme.of(context).textTheme.title,
items: [true, false].map((value) {
return new DropdownMenuItem<bool>(
value: value,
child: Text('${value ? 'Horizontal scroll' : 'In rows'}'),
);
}).toList(),
onChanged: (val) {
setState(() {
_scrollBadges = val;
});
_saveOther();
},
),
] ]
); );
} }

View File

@ -2,6 +2,7 @@ part of 'main.dart';
class HAView { class HAView {
List<CardData> cards = []; List<CardData> cards = [];
CardData badges;
Entity linkedEntity; Entity linkedEntity;
String name; String name;
String id; String id;
@ -16,10 +17,10 @@ class HAView {
isPanel = rawData['panel'] ?? false; isPanel = rawData['panel'] ?? false;
if (rawData['badges'] != null && !isPanel) { if (rawData['badges'] != null && !isPanel) {
cards.add(CardData.parse({ badges = CardData.parse({
'type': CardType.BADGES, 'type': CardType.BADGES,
'badges': rawData['badges'] 'badges': rawData['badges']
})); });
} }
(rawData['cards'] ?? []).forEach((rawCardData) { (rawData['cards'] ?? []).forEach((rawCardData) {

View File

@ -18,6 +18,12 @@ class ViewWidget extends StatelessWidget {
); );
} else { } else {
Widget cardsContainer; Widget cardsContainer;
Widget badgesContainer;
if (this.view.badges != null && this.view.badges is BadgesData) {
badgesContainer = this.view.badges.buildCardWidget();
} else {
badgesContainer = Container(width: 0, height: 0);
}
if (this.view.cards.isNotEmpty) { if (this.view.cards.isNotEmpty) {
cardsContainer = DynamicMultiColumnLayout( cardsContainer = DynamicMultiColumnLayout(
minColumnWidth: Sizes.minViewColumnWidth, minColumnWidth: Sizes.minViewColumnWidth,
@ -45,9 +51,14 @@ class ViewWidget extends StatelessWidget {
cardsContainer = Container(); cardsContainer = Container();
} }
return SingleChildScrollView( return SingleChildScrollView(
scrollDirection: Axis.vertical,
padding: EdgeInsets.all(0), padding: EdgeInsets.all(0),
child: cardsContainer child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
badgesContainer,
cardsContainer
],
),
); );
} }
} }

View File

@ -31,8 +31,8 @@ dependencies:
workmanager: ^0.2.2 workmanager: ^0.2.2
battery: ^1.0.0 battery: ^1.0.0
firebase_crashlytics: ^0.1.3+3 firebase_crashlytics: ^0.1.3+3
syncfusion_flutter_core: ^18.1.43 syncfusion_flutter_core: ^18.1.48
syncfusion_flutter_gauges: ^18.1.43 syncfusion_flutter_gauges: ^18.1.48
dev_dependencies: dev_dependencies: