From 9c28b0085bfb77356804fd975dfbb469649eaa05 Mon Sep 17 00:00:00 2001 From: estevez-dev Date: Tue, 10 Sep 2019 15:40:49 +0300 Subject: [PATCH 1/8] Tablet UI in progress --- lib/const.dart | 1 + lib/view.dart | 96 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/lib/const.dart b/lib/const.dart index 6e7c99e..9da7af2 100644 --- a/lib/const.dart +++ b/lib/const.dart @@ -113,4 +113,5 @@ class Sizes { static const inputWidth = 160.0; static const rowPadding = 10.0; static const doubleRowPadding = rowPadding*2; + static const minViewColumnWidth = 350; } \ No newline at end of file diff --git a/lib/view.dart b/lib/view.dart index e6e2d06..7a3ee9a 100644 --- a/lib/view.dart +++ b/lib/view.dart @@ -32,9 +32,19 @@ class ViewWidgetState extends State { ); } else { return ListView( - padding: EdgeInsets.all(0.0), - //physics: const AlwaysScrollableScrollPhysics(), - children: _buildChildren(context), + shrinkWrap: true, + padding: EdgeInsets.all(0), + children: [ + ConstrainedBox( + constraints: BoxConstraints(maxHeight: 3000), + child: CustomMultiChildLayout( + delegate: ViewLayoutBuilder( + cardsCount: widget.view.cards.length + ), + children: _buildChildren(context), + ), + ) + ], ); } } @@ -49,34 +59,31 @@ class ViewWidgetState extends State { List _buildChildren(BuildContext context) { List result = []; + int layoutChildId = 0; if (widget.view.badges.isNotEmpty) { - result.insert(0, - Wrap( - alignment: WrapAlignment.center, - spacing: 10.0, - runSpacing: 1.0, - children: _buildBadges(context), + result.add( + LayoutId( + id: "badges", + child: Wrap( + alignment: WrapAlignment.center, + spacing: 10.0, + runSpacing: 1.0, + children: _buildBadges(context), + ), ) ); } - - List cards = []; widget.view.cards.forEach((HACard card){ - cards.add( - ConstrainedBox( - constraints: BoxConstraints(maxWidth: 500), + result.add( + LayoutId( + id: 'card_$layoutChildId', child: card.build(context), ) ); + layoutChildId += 1; }); - result.add( - Column ( - children: cards, - ) - ); - return result; } @@ -84,7 +91,9 @@ class ViewWidgetState extends State { List result = []; widget.view.badges.forEach((Entity entity) { if (!entity.isHidden) { - result.add(entity.buildBadgeWidget(context)); + result.add( + entity.buildBadgeWidget(context) + ); } }); return result; @@ -95,5 +104,50 @@ class ViewWidgetState extends State { super.dispose(); } +} +class ViewLayoutBuilder extends MultiChildLayoutDelegate { + final int cardsCount; + + ViewLayoutBuilder({@required this.cardsCount}); + + @override + void performLayout(Size size) { + int columnsCount = (size.width ~/ Sizes.minViewColumnWidth); + double columnWidth = size.width / columnsCount; + List columnXPositions = []; + List columnYPositions = []; + double startY = 0; + if (hasChild("badges")) { + Size badgesSizes = layoutChild( + 'badges', BoxConstraints.tightFor(width: size.width)); + startY += badgesSizes.height; + positionChild('badges', Offset(0, 0)); + } + for (int i =0; i < columnsCount; i++) { + columnXPositions.add(i*columnWidth); + columnYPositions.add(startY); + } + for (int i = 0; i < cardsCount; i++) { + final String cardId = 'card_$i'; + + if (hasChild(cardId)) { + int columnToAdd = 0; + double minYPosition = columnYPositions[0]; + for (int i=1; i false; } \ No newline at end of file From ecf0a696f79812fbccfcbf189ad7f0579369b95c Mon Sep 17 00:00:00 2001 From: Yegor Vialov Date: Thu, 12 Sep 2019 13:36:37 +0300 Subject: [PATCH 2/8] Create no-response.yml --- .github/no-response.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/no-response.yml diff --git a/.github/no-response.yml b/.github/no-response.yml new file mode 100644 index 0000000..e0e8617 --- /dev/null +++ b/.github/no-response.yml @@ -0,0 +1,11 @@ +# Configuration for probot-no-response - https://github.com/probot/no-response + +# Number of days of inactivity before an Issue is closed for lack of response +daysUntilClose: 14 +# Label requiring a response +responseRequiredLabel: more info needed +# Comment to post when closing an Issue for lack of response. Set to `false` to disable +closeComment: > + This issue has been automatically closed because there has been no response + to our request for more information from the original author. If the issue still relevant + feel free to reopen this issue and add more information, or report a new one. From 7ecfc8a9ffb9fe4605fd2f936309f98baca7c5e8 Mon Sep 17 00:00:00 2001 From: Yegor Vialov Date: Thu, 12 Sep 2019 14:00:16 +0300 Subject: [PATCH 3/8] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..b814fc4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,41 @@ +--- +name: Bug report +about: Create a report to help improve HA Client +title: '' +labels: '' +assignees: '' + +--- + + +**HA Client version:** + +**Home Assistant version:** + +**Device name:** + +**Android version:** + +**Connection type:** + +**Login type:** + +**Description** + + +**Screenshots** + + +**Logs** + +``` +[Replace this text with your logs] +``` From bcf3dab0e2f1ce49f7ca312d7dcdd87689248eca Mon Sep 17 00:00:00 2001 From: Yegor Vialov Date: Thu, 12 Sep 2019 14:05:45 +0300 Subject: [PATCH 4/8] Update issue templates --- .../ISSUE_TEMPLATE/entity-support-request.md | 12 ++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 17 +++++++++++++++++ .../lovelace-card-implementation-request.md | 12 ++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/entity-support-request.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/lovelace-card-implementation-request.md diff --git a/.github/ISSUE_TEMPLATE/entity-support-request.md b/.github/ISSUE_TEMPLATE/entity-support-request.md new file mode 100644 index 0000000..6534418 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/entity-support-request.md @@ -0,0 +1,12 @@ +--- +name: Entity support request +about: Suggest to add support of any entity type +title: '' +labels: feature/improvement, ENTITY +assignees: '' + +--- + +**Entity type:** + +**Link to documentation:** diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..29b288f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for HA Client if it is not a card or entity support +title: '' +labels: feature/improvement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/lovelace-card-implementation-request.md b/.github/ISSUE_TEMPLATE/lovelace-card-implementation-request.md new file mode 100644 index 0000000..859313d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/lovelace-card-implementation-request.md @@ -0,0 +1,12 @@ +--- +name: Lovelace card implementation request +about: Suggest to add any Lovelace card support +title: '' +labels: feature/improvement, CARD +assignees: '' + +--- + +**Card name:** + +**Link to card repository or web page:** From 092469d668ed3e95b3aa845d5469fc7604e5561c Mon Sep 17 00:00:00 2001 From: Yegor Vialov Date: Thu, 12 Sep 2019 14:06:44 +0300 Subject: [PATCH 5/8] Update issue templates --- .github/ISSUE_TEMPLATE/entity-support-request.md | 2 +- .../ISSUE_TEMPLATE/lovelace-card-support-request.md | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/lovelace-card-support-request.md diff --git a/.github/ISSUE_TEMPLATE/entity-support-request.md b/.github/ISSUE_TEMPLATE/entity-support-request.md index 6534418..c529d38 100644 --- a/.github/ISSUE_TEMPLATE/entity-support-request.md +++ b/.github/ISSUE_TEMPLATE/entity-support-request.md @@ -2,7 +2,7 @@ name: Entity support request about: Suggest to add support of any entity type title: '' -labels: feature/improvement, ENTITY +labels: ENTITY, feature/improvement assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/lovelace-card-support-request.md b/.github/ISSUE_TEMPLATE/lovelace-card-support-request.md new file mode 100644 index 0000000..998fabf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/lovelace-card-support-request.md @@ -0,0 +1,12 @@ +--- +name: Lovelace Card support request +about: Suggest to add any Lovelace card support +title: '' +labels: CARD, feature/improvement +assignees: '' + +--- + +**Card name:** + +**Link to card repository or web page:** From 9e2c67396680bf2c47fb47c38da5a5cffe2ba7e7 Mon Sep 17 00:00:00 2001 From: Yegor Vialov Date: Thu, 12 Sep 2019 14:07:24 +0300 Subject: [PATCH 6/8] Delete lovelace-card-implementation-request.md --- .../lovelace-card-implementation-request.md | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/lovelace-card-implementation-request.md diff --git a/.github/ISSUE_TEMPLATE/lovelace-card-implementation-request.md b/.github/ISSUE_TEMPLATE/lovelace-card-implementation-request.md deleted file mode 100644 index 859313d..0000000 --- a/.github/ISSUE_TEMPLATE/lovelace-card-implementation-request.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Lovelace card implementation request -about: Suggest to add any Lovelace card support -title: '' -labels: feature/improvement, CARD -assignees: '' - ---- - -**Card name:** - -**Link to card repository or web page:** From 298a64b7ae0c5be50690052597d2a7e14c296bc0 Mon Sep 17 00:00:00 2001 From: estevez-dev Date: Thu, 12 Sep 2019 17:08:40 +0300 Subject: [PATCH 7/8] Packages update --- ios/Flutter/flutter_export_environment.sh | 10 ++++++++++ pubspec.lock | 20 ++++++++++---------- pubspec.yaml | 6 +++--- 3 files changed, 23 insertions(+), 13 deletions(-) create mode 100755 ios/Flutter/flutter_export_environment.sh diff --git a/ios/Flutter/flutter_export_environment.sh b/ios/Flutter/flutter_export_environment.sh new file mode 100755 index 0000000..b7ea8ef --- /dev/null +++ b/ios/Flutter/flutter_export_environment.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=/home/estevez/sdk/flutter" +export "FLUTTER_APPLICATION_PATH=/home/estevez/src/ha_client" +export "FLUTTER_TARGET=lib/main.dart" +export "FLUTTER_BUILD_DIR=build" +export "SYMROOT=${SOURCE_ROOT}/../build/ios" +export "FLUTTER_FRAMEWORK_DIR=/home/estevez/sdk/flutter/bin/cache/artifacts/engine/ios" +export "FLUTTER_BUILD_NAME=0.6.6" +export "FLUTTER_BUILD_NUMBER=660" diff --git a/pubspec.lock b/pubspec.lock index a90ac41..ce6d395 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,14 +21,14 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.3.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.5" cached_network_image: dependency: "direct main" description: @@ -77,7 +77,7 @@ packages: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.3" date_format: dependency: "direct main" description: @@ -138,7 +138,7 @@ packages: name: flutter_local_notifications url: "https://pub.dartlang.org" source: hosted - version: "0.8.2" + version: "0.8.2+1" flutter_markdown: dependency: "direct main" description: @@ -152,7 +152,7 @@ packages: name: flutter_secure_storage url: "https://pub.dartlang.org" source: hosted - version: "3.2.1+1" + version: "3.3.1" flutter_test: dependency: "direct dev" description: flutter @@ -234,14 +234,14 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.1.7" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.2" + version: "1.6.4" path_provider: dependency: transitive description: @@ -255,7 +255,7 @@ packages: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0+1" petitparser: dependency: transitive description: @@ -283,7 +283,7 @@ packages: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.5" share: dependency: "direct main" description: @@ -339,7 +339,7 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.5" synchronized: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 88209fa..1fa6816 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,11 +21,11 @@ dependencies: in_app_purchase: ^0.2.1+3 # flutter_svg: ^0.10.3 flutter_custom_tabs: ^0.6.0 - firebase_messaging: ^5.1.4 + firebase_messaging: ^5.1.5 flutter_webview_plugin: ^0.3.7 - flutter_secure_storage: ^3.2.1+1 + flutter_secure_storage: ^3.3.1 device_info: ^0.4.0+2 - flutter_local_notifications: ^0.8.2 + flutter_local_notifications: ^0.8.2+1 share: git: url: https://github.com/d-silveira/flutter-share.git From d61103ac4270c97fef51881a3d428e4c3c4f3911 Mon Sep 17 00:00:00 2001 From: estevez-dev Date: Sat, 14 Sep 2019 12:14:54 +0300 Subject: [PATCH 8/8] WIP #224 Dynamic multi column view --- lib/main.dart | 1 + lib/plugins/DynamicMultiColumnLayout.dart | 146 ++++++++++++++++++++++ lib/view.dart | 20 +-- pubspec.lock | 4 +- 4 files changed, 162 insertions(+), 9 deletions(-) create mode 100644 lib/plugins/DynamicMultiColumnLayout.dart diff --git a/lib/main.dart b/lib/main.dart index 03c4af3..f062ef6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -25,6 +25,7 @@ import 'package:in_app_purchase/in_app_purchase.dart'; import 'plugins/circular_slider/single_circular_slider.dart'; import 'package:share/receive_share_state.dart'; import 'package:share/share.dart'; +import 'plugins/DynamicMultiColumnLayout.dart'; import 'utils/logger.dart'; diff --git a/lib/plugins/DynamicMultiColumnLayout.dart b/lib/plugins/DynamicMultiColumnLayout.dart new file mode 100644 index 0000000..116462f --- /dev/null +++ b/lib/plugins/DynamicMultiColumnLayout.dart @@ -0,0 +1,146 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'dart:math' as math; + +class DynamicMultiColumnLayout extends MultiChildRenderObjectWidget { + + final int minColumnWidth; + + DynamicMultiColumnLayout({ + Key key, + this.minColumnWidth: 350, + List children = const [], + }) : super(key: key, children: children); + + @override + RenderCustomLayoutBox createRenderObject(BuildContext context) { + return RenderCustomLayoutBox(minColumnWidth: this.minColumnWidth); + } + +} + +class RenderCustomLayoutBox extends RenderBox + with ContainerRenderObjectMixin, + RenderBoxContainerDefaultsMixin { + + final int minColumnWidth; + + RenderCustomLayoutBox({ + this.minColumnWidth, + List children, + }) { + addAll(children); + } + + @override + void setupParentData(RenderBox child) { + if (child.parentData is! CustomLayoutParentData) { + child.parentData = CustomLayoutParentData(); + } + } + + double _getIntrinsicHeight(double childSize(RenderBox child)) { + double inflexibleSpace = 0.0; + RenderBox child = firstChild; + while (child != null) { + inflexibleSpace += childSize(child); + final FlexParentData childParentData = child.parentData; + child = childParentData.nextSibling; + } + return inflexibleSpace; + } + + double _getIntrinsicWidth(double childSize(RenderBox child)) { + double maxSpace = 0.0; + RenderBox child = firstChild; + while (child != null) { + maxSpace = math.max(maxSpace, childSize(child)); + final FlexParentData childParentData = child.parentData; + child = childParentData.nextSibling; + } + return maxSpace; + } + + @override + double computeMinIntrinsicWidth(double height) { + return _getIntrinsicWidth((RenderBox child) => child.getMinIntrinsicWidth(height)); + } + + @override + double computeMaxIntrinsicWidth(double height) { + return _getIntrinsicWidth((RenderBox child) => child.getMaxIntrinsicWidth(height)); + } + + @override + double computeMinIntrinsicHeight(double width) { + return _getIntrinsicHeight((RenderBox child) => child.getMinIntrinsicHeight(width)); + } + + @override + double computeMaxIntrinsicHeight(double width) { + return _getIntrinsicHeight((RenderBox child) => child.getMaxIntrinsicHeight(width)); + } + + @override + void performLayout() { + int columnsCount; + List columnXPositions = []; + List columnYPositions = []; + if (childCount == 0) { + size = constraints.biggest; + assert(size.isFinite); + return; + } + + columnsCount = (constraints.maxWidth ~/ this.minColumnWidth); + double columnWidth = constraints.maxWidth / columnsCount; + double startY = 0; + for (int i =0; i < columnsCount; i++) { + columnXPositions.add(i*columnWidth); + columnYPositions.add(startY); + } + RenderBox child = firstChild; + while (child != null) { + final CustomLayoutParentData childParentData = child.parentData; + + int columnToAdd = 0; + double minYPosition = columnYPositions[0]; + for (int i=0; i height) { + height = columnYPositions[i]; + } + } + + size = Size(width, height); + } + + @override + void paint(PaintingContext context, Offset offset) { + defaultPaint(context, offset); + } + + @override + bool hitTestChildren(HitTestResult result, { Offset position }) { + return defaultHitTestChildren(result, position: position); + } +} + +class CustomLayoutParentData extends ContainerBoxParentData { + +} \ No newline at end of file diff --git a/lib/view.dart b/lib/view.dart index 7a3ee9a..b3eef0b 100644 --- a/lib/view.dart +++ b/lib/view.dart @@ -31,6 +31,16 @@ class ViewWidgetState extends State { child: _buildPanelChild(context), ); } else { + return ListView( + shrinkWrap: true, + padding: EdgeInsets.all(0), + children: [ + DynamicMultiColumnLayout( + minColumnWidth: Sizes.minViewColumnWidth, + children: _buildChildren(context), + ) + ] + ); return ListView( shrinkWrap: true, padding: EdgeInsets.all(0), @@ -61,7 +71,7 @@ class ViewWidgetState extends State { List result = []; int layoutChildId = 0; - if (widget.view.badges.isNotEmpty) { + /*if (widget.view.badges.isNotEmpty) { result.add( LayoutId( id: "badges", @@ -73,15 +83,11 @@ class ViewWidgetState extends State { ), ) ); - } + }*/ widget.view.cards.forEach((HACard card){ result.add( - LayoutId( - id: 'card_$layoutChildId', - child: card.build(context), - ) + card.build(context) ); - layoutChildId += 1; }); return result; diff --git a/pubspec.lock b/pubspec.lock index ce6d395..9d96ec2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -164,7 +164,7 @@ packages: name: flutter_webview_plugin url: "https://pub.dartlang.org" source: hosted - version: "0.3.7" + version: "0.3.8" http: dependency: transitive description: @@ -374,7 +374,7 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "5.1.2" + version: "5.1.3" uuid: dependency: transitive description: