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,18 +10,44 @@ 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) {
return ConstrainedBox(
constraints: BoxConstraints.tightFor(height: 112),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
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, alignment: WrapAlignment.center,
spacing: 10.0, spacing: 10.0,
runSpacing: 1.0, runSpacing: 5,
children: entitiesToShow.map((entity) => children: entitiesToShow.map((entity) =>
EntityModel( EntityModel(
entityWrapper: entity, entityWrapper: entity,
child: BadgeWidget(), child: BadgeWidget(),
handleTap: true, handleTap: true,
)).toList(), )).toList(),
)
); );
} }
}
return Container(height: 0.0, width: 0.0,); return Container(height: 0.0, width: 0.0,);
} }

View File

@ -57,6 +57,7 @@ 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(
constraints: BoxConstraints(maxWidth: 50),
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: Theme.of(context).textTheme.overline.copyWith( style: Theme.of(context).textTheme.overline.copyWith(
@ -64,17 +65,23 @@ class BadgeWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
softWrap: false, softWrap: false,
overflow: TextOverflow.fade), overflow: TextOverflow.ellipsis
),
decoration: new BoxDecoration( decoration: new BoxDecoration(
color: iconColor, color: iconColor,
borderRadius: BorderRadius.circular(9.0), borderRadius: BorderRadius.circular(9.0),
)); )
);
} }
return GestureDetector( return GestureDetector(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Stack(
overflow: Overflow.visible,
alignment: Alignment.center,
children: <Widget>[ children: <Widget>[
Container( Container(
//margin: EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
width: 45, width: 45,
height: 45, height: 45,
decoration: new BoxDecoration( decoration: new BoxDecoration(
@ -82,47 +89,41 @@ class BadgeWidget extends StatelessWidget {
shape: BoxShape.circle, shape: BoxShape.circle,
color: Theme.of(context).cardColor, color: Theme.of(context).cardColor,
// The border you want // The border you want
border: new Border.all( border: Border.all(
width: 2.0, width: 2.0,
color: iconColor, color: iconColor,
), ),
), ),
child: Stack( ),
overflow: Overflow.visible, SizedBox(
children: <Widget>[ width: 38,
Positioned( height: 26,
width: 45,
height: 45,
top: 0.0,
left: 0.0,
child: FittedBox( child: FittedBox(
fit: BoxFit.contain, fit: BoxFit.contain,
alignment: Alignment.center, alignment: Alignment.center,
child: badgeIcon, child: badgeIcon,
), )
), ),
Positioned( Positioned(
bottom: -9.0, bottom: -6,
left: -10.0, child: onBadgeText
right: -10.0,
child: Center(
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: