aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Murray <scott.murray@konsulko.com>2022-11-21 02:30:35 -0500
committerScott Murray <scott.murray@konsulko.com>2022-11-21 02:44:25 -0500
commite21709c9601209e26d09dea0a45e37f0636bb605 (patch)
tree6f7e9d1bda9126cc0dfe6ba401b40739715867e2
parent1f5b482843291c17e3cbb265f59101f8d1874182 (diff)
Rework for use in Flutter demo platform image
Changes: - Converted to portrait orientation. - Application enumeration and launching+activation enabled via use of applaunchd gRPC API and agl-shell protocol platform channel plugin in the embedder. - Previous dashboard, hvac, media, etc. pages disabled. Some of the code has been kept for potential reuse. - Clock widget tweaked to fit in portrait mode navigation bar, and take text color argument. - Bluetooth, wifi, and phone signal icons mocked up in navigation bar. Known issues: - The bottom panel area is static at present, support for popping up a volume control slider like the Qt demo is planned as an addition. - The path to implementing connection and signal strength indications is currently a bit hazy, it is possible that flutter-dbus might be the simplest stopgap. - State management has been kept basic, as there are a couple of places where using provider or riverpod seems like perhaps an overcomplication. This will be reviewed when KUKSA.val support is integrated for the volume slider. - Some of the layout sizing is a bit ad hoc, and it is not clear if the previous layout helper class is actually worth keeping or not. This should be reviewed when time permits. Bug-AGL: SPEC-4611 Signed-off-by: Scott Murray <scott.murray@konsulko.com> Change-Id: Ib486b1fd92047f6c1ff1cd9569f49e3ccaf3269d
-rw-r--r--images/Utility_Logo_Grey-01.svg84
-rw-r--r--lib/demo_3d.dart20
-rw-r--r--lib/generated/applauncher.pb.dart463
-rw-r--r--lib/generated/applauncher.pbenum.dart7
-rw-r--r--lib/generated/applauncher.pbgrpc.dart106
-rw-r--r--lib/generated/applauncher.pbjson.dart99
-rw-r--r--lib/homescreen.dart311
-rw-r--r--lib/layout_size_helper.dart3
-rw-r--r--lib/main.dart20
-rw-r--r--lib/page_apps.dart159
-rw-r--r--lib/page_home.dart108
-rw-r--r--lib/page_media.dart78
-rw-r--r--lib/widget_clock.dart23
-rw-r--r--protos/applauncher.proto50
-rw-r--r--pubspec.lock177
-rw-r--r--pubspec.yaml33
16 files changed, 1382 insertions, 359 deletions
diff --git a/images/Utility_Logo_Grey-01.svg b/images/Utility_Logo_Grey-01.svg
new file mode 100644
index 0000000..16ac88c
--- /dev/null
+++ b/images/Utility_Logo_Grey-01.svg
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+ <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+ <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+ <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
+ <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
+ <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
+ <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
+ <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
+]>
+<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 215 215"
+ style="enable-background:new 0 0 215 215;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#525252;}
+</style>
+<switch>
+ <g i:extraneous="self">
+ <g>
+ <path class="st0" d="M113.8,150.3h4.2v15.3h9.5v3.8h-13.7V150.3z"/>
+ <path class="st0" d="M130.9,150.3h4.2v19.1h-4.2V150.3z"/>
+ <path class="st0" d="M139.9,150.3h3.9l9,11.8v-11.8h4.2v19.1h-3.6l-9.3-12.2v12.2h-4.2V150.3z"/>
+ <path class="st0" d="M169.4,169.7c-2.6,0-4.6-0.7-6.1-2.1c-1.5-1.4-2.2-3.5-2.2-6.4v-10.9h4.2v10.8c0,1.6,0.4,2.7,1.1,3.5
+ c0.7,0.8,1.7,1.2,3,1.2c1.3,0,2.3-0.4,3-1.1c0.7-0.8,1.1-1.9,1.1-3.4v-11h4.2v10.8c0,1.5-0.2,2.7-0.6,3.8c-0.4,1.1-1,2-1.7,2.7
+ c-0.7,0.7-1.6,1.3-2.7,1.6C171.9,169.5,170.7,169.7,169.4,169.7z"/>
+ <path class="st0" d="M187.3,159.7l-6.4-9.4h4.9l4,6.2l4-6.2h4.8l-6.4,9.3l6.7,9.8H194l-4.3-6.6l-4.3,6.6h-4.8L187.3,159.7z"/>
+ <path class="st0" d="M24.6,126.9h2l8.4,18.6h-2.2l-2.2-4.9H20.5l-2.2,4.9h-2.1L24.6,126.9z M29.7,138.7l-4.2-9.4l-4.2,9.4H29.7z"
+ />
+ <path class="st0" d="M37.7,137.7V127h2.1v10.6c0,4,2.1,6.2,5.6,6.2c3.4,0,5.6-2.1,5.6-6.1V127H53v10.6c0,5.4-3.1,8.2-7.7,8.2
+ C40.8,145.7,37.7,142.9,37.7,137.7z"/>
+ <path class="st0" d="M62.9,128.9h-6.2V127h14.5v1.9H65v16.5h-2.1V128.9z"/>
+ <path class="st0" d="M73,136.3L73,136.3c0-5.1,3.8-9.6,9.4-9.6c5.6,0,9.4,4.4,9.4,9.5c0,0,0,0,0,0.1c0,5.1-3.8,9.5-9.4,9.5
+ C76.8,145.8,73,141.4,73,136.3z M89.7,136.3L89.7,136.3c0-4.2-3.1-7.7-7.3-7.7c-4.2,0-7.2,3.4-7.2,7.6v0.1c0,4.2,3.1,7.6,7.3,7.6
+ C86.6,143.8,89.7,140.5,89.7,136.3z"/>
+ <path class="st0" d="M96.2,127h2.1l6.7,10.1l6.7-10.1h2.1v18.5h-2.1v-15l-6.7,9.9H105l-6.7-9.9v14.9h-2V127z"/>
+ <path class="st0" d="M145.2,128.9H139V127h14.5v1.9h-6.2v16.5h-2.1V128.9z"/>
+ <path class="st0" d="M157.6,127h2.1v18.5h-2.1V127z"/>
+ <path class="st0" d="M163.5,127h2.3l6.6,15.9L179,127h2.2l-7.9,18.6h-1.8L163.5,127z"/>
+ <path class="st0" d="M184.8,127h13.3v1.9h-11.3v6.3H197v1.9h-10.1v6.5h11.4v1.9h-13.5V127z"/>
+ <rect x="105.6" y="55.1" class="st0" width="3.8" height="16.8"/>
+
+ <rect x="69.3" y="69.6" transform="matrix(0.707 -0.7072 0.7072 0.707 -34.2747 73.1702)" class="st0" width="3.8" height="16.8"/>
+ <rect x="155.1" y="104.5" class="st0" width="16.8" height="3.8"/>
+ <rect x="47.4" y="104.5" class="st0" width="16.8" height="3.8"/>
+ <path class="st0" d="M43.7,113.9c2.1-34.7,31-62.4,66.2-62.4c35.2,0,64.2,27.6,66.2,62.4h6.4c-2.1-38.3-33.8-68.8-72.6-68.8
+ s-70.5,30.5-72.6,68.8H43.7z"/>
+ <circle class="st0" cx="107.5" cy="114.9" r="6.7"/>
+
+ <rect x="107.1" y="88.5" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -24.9453 120.6025)" class="st0" width="52" height="3.8"/>
+ <rect x="86.9" y="78" class="st0" width="9.2" height="9.2"/>
+ <rect x="97.6" y="78" class="st0" width="9.2" height="9.2"/>
+ <rect x="108.3" y="78" class="st0" width="9.2" height="9.2"/>
+ <rect x="118.9" y="78" class="st0" width="9.2" height="9.2"/>
+ <g>
+ <g>
+ <path class="st0" d="M35.1,153.7l-1.5,1.4c-1.1-1-2.2-1.8-3.5-2.4c-1.3-0.5-2.5-0.8-3.7-0.8c-1.5,0-2.9,0.4-4.2,1.1
+ c-1.3,0.7-2.4,1.7-3.1,3c-0.7,1.2-1.1,2.6-1.1,4c0,1.4,0.4,2.8,1.1,4.1c0.8,1.3,1.8,2.3,3.2,3c1.3,0.7,2.8,1.1,4.4,1.1
+ c1.9,0,3.6-0.5,4.9-1.6c1.3-1.1,2.1-2.5,2.4-4.3h-6v-1.8h8.2c0,2.9-0.9,5.2-2.6,7c-1.7,1.7-4,2.6-6.9,2.6
+ c-3.5,0-6.3-1.2-8.3-3.6c-1.6-1.8-2.4-4-2.4-6.4c0-1.8,0.5-3.5,1.4-5c0.9-1.5,2.1-2.8,3.7-3.6c1.6-0.9,3.3-1.3,5.3-1.3
+ c1.6,0,3.1,0.3,4.5,0.9C32.4,151.5,33.8,152.4,35.1,153.7z"/>
+ <path class="st0" d="M39.9,150.5h3.8c2.1,0,3.5,0.1,4.3,0.3c1.1,0.3,2,0.8,2.7,1.7c0.7,0.8,1.1,1.9,1.1,3.1
+ c0,1-0.2,1.9-0.7,2.7c-0.5,0.8-1.2,1.4-2.1,1.8c-0.9,0.4-2.1,0.6-3.7,0.6l6.8,8.8h-2.3l-6.8-8.8h-1.1v8.8h-1.9V150.5z
+ M41.8,152.3v6.4l3.3,0c1.3,0,2.2-0.1,2.8-0.4c0.6-0.2,1.1-0.6,1.4-1.2c0.3-0.5,0.5-1.1,0.5-1.8c0-0.6-0.2-1.2-0.5-1.7
+ s-0.8-0.9-1.4-1.1c-0.6-0.2-1.5-0.3-2.8-0.3H41.8z"/>
+ <path class="st0" d="M63.6,150.5l8.8,18.9h-2l-3-6.2h-8.2l-2.9,6.2h-2.1l8.9-18.9H63.6z M63.3,154.5l-3.2,6.9h6.5L63.3,154.5z"
+ />
+ <path class="st0" d="M75.3,169.4v-18.9h3.9c2.8,0,4.9,0.2,6.2,0.7c1.8,0.6,3.3,1.8,4.3,3.3c1,1.6,1.6,3.5,1.6,5.7
+ c0,1.9-0.4,3.6-1.2,5c-0.8,1.4-1.9,2.5-3.2,3.2c-1.3,0.7-3.1,1-5.5,1H75.3z M77.1,167.6h2.2c2.6,0,4.4-0.2,5.4-0.5
+ c1.4-0.5,2.5-1.3,3.4-2.5c0.8-1.2,1.2-2.7,1.2-4.4c0-1.8-0.4-3.4-1.3-4.7c-0.9-1.3-2.1-2.2-3.7-2.7c-1.2-0.4-3.1-0.5-5.9-0.5
+ h-1.3V167.6z"/>
+ <path class="st0" d="M95,150.5h10.9v1.9h-9v5.9h8.9v1.9h-8.9v7.4h8.9v1.9H95V150.5z"/>
+ </g>
+ </g>
+ <g>
+ <polygon class="st0" points="121.4,141.8 121.4,134.4 117.7,134.4 117.7,145.4 128.7,145.4 128.7,141.8 "/>
+ <polygon class="st0" points="136.1,127 117.7,127 117.7,132.6 121.4,132.6 121.4,130.7 132.4,130.7 132.4,141.8 130.6,141.8
+ 130.6,145.4 136.1,145.4 "/>
+ </g>
+ </g>
+ </g>
+</switch>
+</svg>
diff --git a/lib/demo_3d.dart b/lib/demo_3d.dart
deleted file mode 100644
index 9aeda40..0000000
--- a/lib/demo_3d.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-import 'package:flutter/material.dart';
-
-// A 3D demo.
-class Demo3dPage extends StatelessWidget {
- Demo3dPage({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Container(
- decoration: BoxDecoration(
- gradient: LinearGradient(
- begin: Alignment.topRight,
- end: Alignment.bottomLeft,
- colors: [Colors.grey.shade800, Colors.grey.shade900])),
- child: Texture(
- textureId: 1,
- ),
- );
- }
-}
diff --git a/lib/generated/applauncher.pb.dart b/lib/generated/applauncher.pb.dart
new file mode 100644
index 0000000..34b1533
--- /dev/null
+++ b/lib/generated/applauncher.pb.dart
@@ -0,0 +1,463 @@
+///
+// Generated code. Do not modify.
+// source: applauncher.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
+
+import 'dart:core' as $core;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class StartRequest extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'StartRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'automotivegradelinux'), createEmptyInstance: create)
+ ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
+ ..hasRequiredFields = false
+ ;
+
+ StartRequest._() : super();
+ factory StartRequest({
+ $core.String? id,
+ }) {
+ final _result = create();
+ if (id != null) {
+ _result.id = id;
+ }
+ return _result;
+ }
+ factory StartRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory StartRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ StartRequest clone() => StartRequest()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ StartRequest copyWith(void Function(StartRequest) updates) => super.copyWith((message) => updates(message as StartRequest)) as StartRequest; // ignore: deprecated_member_use
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static StartRequest create() => StartRequest._();
+ StartRequest createEmptyInstance() => create();
+ static $pb.PbList<StartRequest> createRepeated() => $pb.PbList<StartRequest>();
+ @$core.pragma('dart2js:noInline')
+ static StartRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<StartRequest>(create);
+ static StartRequest? _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.String get id => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set id($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasId() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearId() => clearField(1);
+}
+
+class StartResponse extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'StartResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'automotivegradelinux'), createEmptyInstance: create)
+ ..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'status')
+ ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'message')
+ ..hasRequiredFields = false
+ ;
+
+ StartResponse._() : super();
+ factory StartResponse({
+ $core.bool? status,
+ $core.String? message,
+ }) {
+ final _result = create();
+ if (status != null) {
+ _result.status = status;
+ }
+ if (message != null) {
+ _result.message = message;
+ }
+ return _result;
+ }
+ factory StartResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory StartResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ StartResponse clone() => StartResponse()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ StartResponse copyWith(void Function(StartResponse) updates) => super.copyWith((message) => updates(message as StartResponse)) as StartResponse; // ignore: deprecated_member_use
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static StartResponse create() => StartResponse._();
+ StartResponse createEmptyInstance() => create();
+ static $pb.PbList<StartResponse> createRepeated() => $pb.PbList<StartResponse>();
+ @$core.pragma('dart2js:noInline')
+ static StartResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<StartResponse>(create);
+ static StartResponse? _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.bool get status => $_getBF(0);
+ @$pb.TagNumber(1)
+ set status($core.bool v) { $_setBool(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasStatus() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearStatus() => clearField(1);
+
+ @$pb.TagNumber(2)
+ $core.String get message => $_getSZ(1);
+ @$pb.TagNumber(2)
+ set message($core.String v) { $_setString(1, v); }
+ @$pb.TagNumber(2)
+ $core.bool hasMessage() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearMessage() => clearField(2);
+}
+
+class ListRequest extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ListRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'automotivegradelinux'), createEmptyInstance: create)
+ ..hasRequiredFields = false
+ ;
+
+ ListRequest._() : super();
+ factory ListRequest() => create();
+ factory ListRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory ListRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ ListRequest clone() => ListRequest()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ ListRequest copyWith(void Function(ListRequest) updates) => super.copyWith((message) => updates(message as ListRequest)) as ListRequest; // ignore: deprecated_member_use
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static ListRequest create() => ListRequest._();
+ ListRequest createEmptyInstance() => create();
+ static $pb.PbList<ListRequest> createRepeated() => $pb.PbList<ListRequest>();
+ @$core.pragma('dart2js:noInline')
+ static ListRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ListRequest>(create);
+ static ListRequest? _defaultInstance;
+}
+
+class ListResponse extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'ListResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'automotivegradelinux'), createEmptyInstance: create)
+ ..pc<AppInfo>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'apps', $pb.PbFieldType.PM, subBuilder: AppInfo.create)
+ ..hasRequiredFields = false
+ ;
+
+ ListResponse._() : super();
+ factory ListResponse({
+ $core.Iterable<AppInfo>? apps,
+ }) {
+ final _result = create();
+ if (apps != null) {
+ _result.apps.addAll(apps);
+ }
+ return _result;
+ }
+ factory ListResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory ListResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ ListResponse clone() => ListResponse()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ ListResponse copyWith(void Function(ListResponse) updates) => super.copyWith((message) => updates(message as ListResponse)) as ListResponse; // ignore: deprecated_member_use
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static ListResponse create() => ListResponse._();
+ ListResponse createEmptyInstance() => create();
+ static $pb.PbList<ListResponse> createRepeated() => $pb.PbList<ListResponse>();
+ @$core.pragma('dart2js:noInline')
+ static ListResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ListResponse>(create);
+ static ListResponse? _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.List<AppInfo> get apps => $_getList(0);
+}
+
+class AppInfo extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'AppInfo', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'automotivegradelinux'), createEmptyInstance: create)
+ ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
+ ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
+ ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'iconPath')
+ ..hasRequiredFields = false
+ ;
+
+ AppInfo._() : super();
+ factory AppInfo({
+ $core.String? id,
+ $core.String? name,
+ $core.String? iconPath,
+ }) {
+ final _result = create();
+ if (id != null) {
+ _result.id = id;
+ }
+ if (name != null) {
+ _result.name = name;
+ }
+ if (iconPath != null) {
+ _result.iconPath = iconPath;
+ }
+ return _result;
+ }
+ factory AppInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory AppInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ AppInfo clone() => AppInfo()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ AppInfo copyWith(void Function(AppInfo) updates) => super.copyWith((message) => updates(message as AppInfo)) as AppInfo; // ignore: deprecated_member_use
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static AppInfo create() => AppInfo._();
+ AppInfo createEmptyInstance() => create();
+ static $pb.PbList<AppInfo> createRepeated() => $pb.PbList<AppInfo>();
+ @$core.pragma('dart2js:noInline')
+ static AppInfo getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AppInfo>(create);
+ static AppInfo? _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.String get id => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set id($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasId() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearId() => clearField(1);
+
+ @$pb.TagNumber(2)
+ $core.String get name => $_getSZ(1);
+ @$pb.TagNumber(2)
+ set name($core.String v) { $_setString(1, v); }
+ @$pb.TagNumber(2)
+ $core.bool hasName() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearName() => clearField(2);
+
+ @$pb.TagNumber(3)
+ $core.String get iconPath => $_getSZ(2);
+ @$pb.TagNumber(3)
+ set iconPath($core.String v) { $_setString(2, v); }
+ @$pb.TagNumber(3)
+ $core.bool hasIconPath() => $_has(2);
+ @$pb.TagNumber(3)
+ void clearIconPath() => clearField(3);
+}
+
+class StatusRequest extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'StatusRequest', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'automotivegradelinux'), createEmptyInstance: create)
+ ..hasRequiredFields = false
+ ;
+
+ StatusRequest._() : super();
+ factory StatusRequest() => create();
+ factory StatusRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory StatusRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ StatusRequest clone() => StatusRequest()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ StatusRequest copyWith(void Function(StatusRequest) updates) => super.copyWith((message) => updates(message as StatusRequest)) as StatusRequest; // ignore: deprecated_member_use
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static StatusRequest create() => StatusRequest._();
+ StatusRequest createEmptyInstance() => create();
+ static $pb.PbList<StatusRequest> createRepeated() => $pb.PbList<StatusRequest>();
+ @$core.pragma('dart2js:noInline')
+ static StatusRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<StatusRequest>(create);
+ static StatusRequest? _defaultInstance;
+}
+
+class AppStatus extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'AppStatus', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'automotivegradelinux'), createEmptyInstance: create)
+ ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
+ ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'status')
+ ..hasRequiredFields = false
+ ;
+
+ AppStatus._() : super();
+ factory AppStatus({
+ $core.String? id,
+ $core.String? status,
+ }) {
+ final _result = create();
+ if (id != null) {
+ _result.id = id;
+ }
+ if (status != null) {
+ _result.status = status;
+ }
+ return _result;
+ }
+ factory AppStatus.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory AppStatus.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ AppStatus clone() => AppStatus()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ AppStatus copyWith(void Function(AppStatus) updates) => super.copyWith((message) => updates(message as AppStatus)) as AppStatus; // ignore: deprecated_member_use
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static AppStatus create() => AppStatus._();
+ AppStatus createEmptyInstance() => create();
+ static $pb.PbList<AppStatus> createRepeated() => $pb.PbList<AppStatus>();
+ @$core.pragma('dart2js:noInline')
+ static AppStatus getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AppStatus>(create);
+ static AppStatus? _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.String get id => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set id($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasId() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearId() => clearField(1);
+
+ @$pb.TagNumber(2)
+ $core.String get status => $_getSZ(1);
+ @$pb.TagNumber(2)
+ set status($core.String v) { $_setString(1, v); }
+ @$pb.TagNumber(2)
+ $core.bool hasStatus() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearStatus() => clearField(2);
+}
+
+class LauncherStatus extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'LauncherStatus', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'automotivegradelinux'), createEmptyInstance: create)
+ ..hasRequiredFields = false
+ ;
+
+ LauncherStatus._() : super();
+ factory LauncherStatus() => create();
+ factory LauncherStatus.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory LauncherStatus.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ LauncherStatus clone() => LauncherStatus()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ LauncherStatus copyWith(void Function(LauncherStatus) updates) => super.copyWith((message) => updates(message as LauncherStatus)) as LauncherStatus; // ignore: deprecated_member_use
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static LauncherStatus create() => LauncherStatus._();
+ LauncherStatus createEmptyInstance() => create();
+ static $pb.PbList<LauncherStatus> createRepeated() => $pb.PbList<LauncherStatus>();
+ @$core.pragma('dart2js:noInline')
+ static LauncherStatus getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<LauncherStatus>(create);
+ static LauncherStatus? _defaultInstance;
+}
+
+enum StatusResponse_Status {
+ app,
+ launcher,
+ notSet
+}
+
+class StatusResponse extends $pb.GeneratedMessage {
+ static const $core.Map<$core.int, StatusResponse_Status> _StatusResponse_StatusByTag = {
+ 1 : StatusResponse_Status.app,
+ 2 : StatusResponse_Status.launcher,
+ 0 : StatusResponse_Status.notSet
+ };
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'StatusResponse', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'automotivegradelinux'), createEmptyInstance: create)
+ ..oo(0, [1, 2])
+ ..aOM<AppStatus>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'app', subBuilder: AppStatus.create)
+ ..aOM<LauncherStatus>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'launcher', subBuilder: LauncherStatus.create)
+ ..hasRequiredFields = false
+ ;
+
+ StatusResponse._() : super();
+ factory StatusResponse({
+ AppStatus? app,
+ LauncherStatus? launcher,
+ }) {
+ final _result = create();
+ if (app != null) {
+ _result.app = app;
+ }
+ if (launcher != null) {
+ _result.launcher = launcher;
+ }
+ return _result;
+ }
+ factory StatusResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory StatusResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ StatusResponse clone() => StatusResponse()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ StatusResponse copyWith(void Function(StatusResponse) updates) => super.copyWith((message) => updates(message as StatusResponse)) as StatusResponse; // ignore: deprecated_member_use
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static StatusResponse create() => StatusResponse._();
+ StatusResponse createEmptyInstance() => create();
+ static $pb.PbList<StatusResponse> createRepeated() => $pb.PbList<StatusResponse>();
+ @$core.pragma('dart2js:noInline')
+ static StatusResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<StatusResponse>(create);
+ static StatusResponse? _defaultInstance;
+
+ StatusResponse_Status whichStatus() => _StatusResponse_StatusByTag[$_whichOneof(0)]!;
+ void clearStatus() => clearField($_whichOneof(0));
+
+ @$pb.TagNumber(1)
+ AppStatus get app => $_getN(0);
+ @$pb.TagNumber(1)
+ set app(AppStatus v) { setField(1, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasApp() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearApp() => clearField(1);
+ @$pb.TagNumber(1)
+ AppStatus ensureApp() => $_ensure(0);
+
+ @$pb.TagNumber(2)
+ LauncherStatus get launcher => $_getN(1);
+ @$pb.TagNumber(2)
+ set launcher(LauncherStatus v) { setField(2, v); }
+ @$pb.TagNumber(2)
+ $core.bool hasLauncher() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearLauncher() => clearField(2);
+ @$pb.TagNumber(2)
+ LauncherStatus ensureLauncher() => $_ensure(1);
+}
+
diff --git a/lib/generated/applauncher.pbenum.dart b/lib/generated/applauncher.pbenum.dart
new file mode 100644
index 0000000..255c0ab
--- /dev/null
+++ b/lib/generated/applauncher.pbenum.dart
@@ -0,0 +1,7 @@
+///
+// Generated code. Do not modify.
+// source: applauncher.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
+
diff --git a/lib/generated/applauncher.pbgrpc.dart b/lib/generated/applauncher.pbgrpc.dart
new file mode 100644
index 0000000..d054e8f
--- /dev/null
+++ b/lib/generated/applauncher.pbgrpc.dart
@@ -0,0 +1,106 @@
+///
+// Generated code. Do not modify.
+// source: applauncher.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
+
+import 'dart:async' as $async;
+
+import 'dart:core' as $core;
+
+import 'package:grpc/service_api.dart' as $grpc;
+import 'applauncher.pb.dart' as $0;
+export 'applauncher.pb.dart';
+
+class AppLauncherClient extends $grpc.Client {
+ static final _$startApplication =
+ $grpc.ClientMethod<$0.StartRequest, $0.StartResponse>(
+ '/automotivegradelinux.AppLauncher/StartApplication',
+ ($0.StartRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.StartResponse.fromBuffer(value));
+ static final _$listApplications =
+ $grpc.ClientMethod<$0.ListRequest, $0.ListResponse>(
+ '/automotivegradelinux.AppLauncher/ListApplications',
+ ($0.ListRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.ListResponse.fromBuffer(value));
+ static final _$getStatusEvents =
+ $grpc.ClientMethod<$0.StatusRequest, $0.StatusResponse>(
+ '/automotivegradelinux.AppLauncher/GetStatusEvents',
+ ($0.StatusRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.StatusResponse.fromBuffer(value));
+
+ AppLauncherClient($grpc.ClientChannel channel,
+ {$grpc.CallOptions? options,
+ $core.Iterable<$grpc.ClientInterceptor>? interceptors})
+ : super(channel, options: options, interceptors: interceptors);
+
+ $grpc.ResponseFuture<$0.StartResponse> startApplication(
+ $0.StartRequest request,
+ {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$startApplication, request, options: options);
+ }
+
+ $grpc.ResponseFuture<$0.ListResponse> listApplications($0.ListRequest request,
+ {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$listApplications, request, options: options);
+ }
+
+ $grpc.ResponseStream<$0.StatusResponse> getStatusEvents(
+ $0.StatusRequest request,
+ {$grpc.CallOptions? options}) {
+ return $createStreamingCall(
+ _$getStatusEvents, $async.Stream.fromIterable([request]),
+ options: options);
+ }
+}
+
+abstract class AppLauncherServiceBase extends $grpc.Service {
+ $core.String get $name => 'automotivegradelinux.AppLauncher';
+
+ AppLauncherServiceBase() {
+ $addMethod($grpc.ServiceMethod<$0.StartRequest, $0.StartResponse>(
+ 'StartApplication',
+ startApplication_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.StartRequest.fromBuffer(value),
+ ($0.StartResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.ListRequest, $0.ListResponse>(
+ 'ListApplications',
+ listApplications_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.ListRequest.fromBuffer(value),
+ ($0.ListResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.StatusRequest, $0.StatusResponse>(
+ 'GetStatusEvents',
+ getStatusEvents_Pre,
+ false,
+ true,
+ ($core.List<$core.int> value) => $0.StatusRequest.fromBuffer(value),
+ ($0.StatusResponse value) => value.writeToBuffer()));
+ }
+
+ $async.Future<$0.StartResponse> startApplication_Pre(
+ $grpc.ServiceCall call, $async.Future<$0.StartRequest> request) async {
+ return startApplication(call, await request);
+ }
+
+ $async.Future<$0.ListResponse> listApplications_Pre(
+ $grpc.ServiceCall call, $async.Future<$0.ListRequest> request) async {
+ return listApplications(call, await request);
+ }
+
+ $async.Stream<$0.StatusResponse> getStatusEvents_Pre(
+ $grpc.ServiceCall call, $async.Future<$0.StatusRequest> request) async* {
+ yield* getStatusEvents(call, await request);
+ }
+
+ $async.Future<$0.StartResponse> startApplication(
+ $grpc.ServiceCall call, $0.StartRequest request);
+ $async.Future<$0.ListResponse> listApplications(
+ $grpc.ServiceCall call, $0.ListRequest request);
+ $async.Stream<$0.StatusResponse> getStatusEvents(
+ $grpc.ServiceCall call, $0.StatusRequest request);
+}
diff --git a/lib/generated/applauncher.pbjson.dart b/lib/generated/applauncher.pbjson.dart
new file mode 100644
index 0000000..4d89f09
--- /dev/null
+++ b/lib/generated/applauncher.pbjson.dart
@@ -0,0 +1,99 @@
+///
+// Generated code. Do not modify.
+// source: applauncher.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
+
+import 'dart:core' as $core;
+import 'dart:convert' as $convert;
+import 'dart:typed_data' as $typed_data;
+@$core.Deprecated('Use startRequestDescriptor instead')
+const StartRequest$json = const {
+ '1': 'StartRequest',
+ '2': const [
+ const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
+ ],
+};
+
+/// Descriptor for `StartRequest`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List startRequestDescriptor = $convert.base64Decode('CgxTdGFydFJlcXVlc3QSDgoCaWQYASABKAlSAmlk');
+@$core.Deprecated('Use startResponseDescriptor instead')
+const StartResponse$json = const {
+ '1': 'StartResponse',
+ '2': const [
+ const {'1': 'status', '3': 1, '4': 1, '5': 8, '10': 'status'},
+ const {'1': 'message', '3': 2, '4': 1, '5': 9, '10': 'message'},
+ ],
+};
+
+/// Descriptor for `StartResponse`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List startResponseDescriptor = $convert.base64Decode('Cg1TdGFydFJlc3BvbnNlEhYKBnN0YXR1cxgBIAEoCFIGc3RhdHVzEhgKB21lc3NhZ2UYAiABKAlSB21lc3NhZ2U=');
+@$core.Deprecated('Use listRequestDescriptor instead')
+const ListRequest$json = const {
+ '1': 'ListRequest',
+};
+
+/// Descriptor for `ListRequest`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List listRequestDescriptor = $convert.base64Decode('CgtMaXN0UmVxdWVzdA==');
+@$core.Deprecated('Use listResponseDescriptor instead')
+const ListResponse$json = const {
+ '1': 'ListResponse',
+ '2': const [
+ const {'1': 'apps', '3': 1, '4': 3, '5': 11, '6': '.automotivegradelinux.AppInfo', '10': 'apps'},
+ ],
+};
+
+/// Descriptor for `ListResponse`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List listResponseDescriptor = $convert.base64Decode('CgxMaXN0UmVzcG9uc2USMQoEYXBwcxgBIAMoCzIdLmF1dG9tb3RpdmVncmFkZWxpbnV4LkFwcEluZm9SBGFwcHM=');
+@$core.Deprecated('Use appInfoDescriptor instead')
+const AppInfo$json = const {
+ '1': 'AppInfo',
+ '2': const [
+ const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
+ const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'},
+ const {'1': 'icon_path', '3': 3, '4': 1, '5': 9, '10': 'iconPath'},
+ ],
+};
+
+/// Descriptor for `AppInfo`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List appInfoDescriptor = $convert.base64Decode('CgdBcHBJbmZvEg4KAmlkGAEgASgJUgJpZBISCgRuYW1lGAIgASgJUgRuYW1lEhsKCWljb25fcGF0aBgDIAEoCVIIaWNvblBhdGg=');
+@$core.Deprecated('Use statusRequestDescriptor instead')
+const StatusRequest$json = const {
+ '1': 'StatusRequest',
+};
+
+/// Descriptor for `StatusRequest`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List statusRequestDescriptor = $convert.base64Decode('Cg1TdGF0dXNSZXF1ZXN0');
+@$core.Deprecated('Use appStatusDescriptor instead')
+const AppStatus$json = const {
+ '1': 'AppStatus',
+ '2': const [
+ const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
+ const {'1': 'status', '3': 2, '4': 1, '5': 9, '10': 'status'},
+ ],
+};
+
+/// Descriptor for `AppStatus`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List appStatusDescriptor = $convert.base64Decode('CglBcHBTdGF0dXMSDgoCaWQYASABKAlSAmlkEhYKBnN0YXR1cxgCIAEoCVIGc3RhdHVz');
+@$core.Deprecated('Use launcherStatusDescriptor instead')
+const LauncherStatus$json = const {
+ '1': 'LauncherStatus',
+};
+
+/// Descriptor for `LauncherStatus`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List launcherStatusDescriptor = $convert.base64Decode('Cg5MYXVuY2hlclN0YXR1cw==');
+@$core.Deprecated('Use statusResponseDescriptor instead')
+const StatusResponse$json = const {
+ '1': 'StatusResponse',
+ '2': const [
+ const {'1': 'app', '3': 1, '4': 1, '5': 11, '6': '.automotivegradelinux.AppStatus', '9': 0, '10': 'app'},
+ const {'1': 'launcher', '3': 2, '4': 1, '5': 11, '6': '.automotivegradelinux.LauncherStatus', '9': 0, '10': 'launcher'},
+ ],
+ '8': const [
+ const {'1': 'status'},
+ ],
+};
+
+/// Descriptor for `StatusResponse`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List statusResponseDescriptor = $convert.base64Decode('Cg5TdGF0dXNSZXNwb25zZRIzCgNhcHAYASABKAsyHy5hdXRvbW90aXZlZ3JhZGVsaW51eC5BcHBTdGF0dXNIAFIDYXBwEkIKCGxhdW5jaGVyGAIgASgLMiQuYXV0b21vdGl2ZWdyYWRlbGludXguTGF1bmNoZXJTdGF0dXNIAFIIbGF1bmNoZXJCCAoGc3RhdHVz');
diff --git a/lib/homescreen.dart b/lib/homescreen.dart
index 944355c..d666bd3 100644
--- a/lib/homescreen.dart
+++ b/lib/homescreen.dart
@@ -1,14 +1,14 @@
import 'package:flutter/material.dart';
-import 'package:flutter_homescreen/demo_3d.dart';
+import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
+import 'package:grpc/grpc.dart';
+import 'package:jovial_svg/jovial_svg.dart';
+import 'package:flutter_homescreen/generated/applauncher.pbgrpc.dart';
import 'package:flutter_homescreen/homescreen_model.dart';
-import 'package:flutter_homescreen/page_dashboard.dart';
-import 'package:flutter_homescreen/page_home.dart';
-import 'package:flutter_homescreen/page_hvac.dart';
-import 'package:flutter_homescreen/page_media.dart';
+import 'package:flutter_homescreen/page_apps.dart';
import 'package:flutter_homescreen/widget_clock.dart';
-enum PageIndex { home, dashboard, hvac, media, demo3d }
+enum PageIndex { home, dashboard, hvac, media }
class Homescreen extends StatefulWidget {
Homescreen({Key? key}) : super(key: key);
@@ -21,27 +21,116 @@ class _HomescreenState extends State<Homescreen> with TickerProviderStateMixin {
int _selectedIndex = 0;
int _previousIndex = 0;
+ late ClientChannel channel;
+ late AppLauncherClient stub;
+ List<String> apps_stack = [];
+ static const agl_shell_channel = MethodChannel('flutter/agl_shell');
+
+ Future<List<AppInfo>> getAppList() async {
+ var response = await stub.listApplications(ListRequest());
+ for (AppInfo info in response.apps) {
+ debugPrint("Got app:");
+ debugPrint("$info");
+ }
+ return response.apps;
+ }
+
+ addAppToStack(String id) {
+ if (!apps_stack.contains(id)) {
+ apps_stack.add(id);
+ } else {
+ int current_pos = apps_stack.indexOf(id);
+ if (current_pos != (apps_stack.length - 1)) {
+ apps_stack.removeAt(current_pos);
+ apps_stack.add(id);
+ }
+ }
+ }
+
+ activateApp(String id) async {
+ try {
+ agl_shell_channel.invokeMethod('activate_app', { 'app_id': id, 'index': 0 });
+ } catch (e) {
+ print('Could not invoke flutter/agl_shell/activate_app: $e');
+ }
+ addAppToStack(id);
+ }
+
+ deactivateApp(String id) async {
+ if (apps_stack.contains(id)) {
+ apps_stack.remove(id);
+ if (apps_stack.isNotEmpty) {
+ activateApp(apps_stack.last);
+ }
+ }
+ }
+
+ handleAppStatusEvents() async {
+ try {
+ var response = stub.getStatusEvents(StatusRequest());
+ await for (var event in response) {
+ if (event.hasApp()) {
+ AppStatus app_status = event.app;
+ debugPrint("Got app status:");
+ debugPrint("$app_status");
+ if (app_status.hasId() && app_status.hasStatus()) {
+ if (app_status.status == "started") {
+ activateApp(app_status.id);
+ } else if (app_status.status == "terminated") {
+ deactivateApp(app_status.id);
+ }
+ }
+ }
+ }
+ } catch(e) {
+ print(e);
+ }
+ }
+
+ initState() {
+ debugPrint("_HomescreenState.initState!");
+ channel = ClientChannel('localhost',
+ port: 50052,
+ options: ChannelOptions(credentials: ChannelCredentials.insecure()));
+
+ stub = AppLauncherClient(channel);
+
+ handleAppStatusEvents();
+
+ super.initState();
+ }
+
+ void startApp(String id) async {
+ await stub.startApplication(StartRequest(id: id));
+ }
+
setNavigationIndex(int index) {
- setState(() {
- _previousIndex = _selectedIndex;
- _selectedIndex = index;
- });
+ switch (PageIndex.values[index]) {
+ case PageIndex.dashboard:
+ startApp("dashboard_app");
+ return;
+ case PageIndex.hvac:
+ startApp("flutter_hvac");
+ return;
+ case PageIndex.media:
+ startApp("mediaplayer");
+ return;
+ default:
+ setState(() {
+ _previousIndex = _selectedIndex;
+ _selectedIndex = index;
+ });
+ activateApp("homescreen");
+ }
}
Widget _childForIndex(int selectedIndex) {
switch (PageIndex.values[selectedIndex]) {
case PageIndex.home:
- return HomePage(
+ return AppsPage(
key: ValueKey(selectedIndex),
- onSetNavigationIndex: setNavigationIndex);
- case PageIndex.dashboard:
- return DashboardPage(key: ValueKey(selectedIndex));
- case PageIndex.hvac:
- return HVACPage(key: ValueKey(selectedIndex));
- case PageIndex.media:
- return MediaPage(key: ValueKey(selectedIndex));
- case PageIndex.demo3d:
- return Demo3dPage(key: ValueKey(selectedIndex));
+ getApps: getAppList,
+ startApp: startApp);
default:
return Text('Undefined');
}
@@ -50,97 +139,105 @@ class _HomescreenState extends State<Homescreen> with TickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return Container(
- color: Colors.deepPurple.shade50,
child: Center(
child: LayoutBuilder(
- builder: _buildLayout,
- )));
+ builder: _buildLayout,
+ )));
}
Widget _buildLayout(BuildContext context, BoxConstraints constraints) {
- // size the icons so they cover the left edge of the screen
- var iconSize = constraints.maxHeight / (PageIndex.values.length + 2);
- var railSize = constraints.maxHeight / (PageIndex.values.length + 1);
+ var railSize = 160.0;
+ var iconSize = railSize / 2;
+ var foregroundColor = Theme.of(context)
+ .navigationBarTheme
+ .iconTheme!
+ .resolve({MaterialState.pressed})!.color!;
return Scaffold(
- body: Row(
+ body: Column(
children: <Widget>[
- Container(
- decoration: BoxDecoration(
- gradient: LinearGradient(
- begin: Alignment.centerLeft,
- end: Alignment.centerRight,
- colors: [
- Colors.blueGrey.shade800,
- Colors.blueGrey.shade900
- ])),
- child: Stack(
- children: [
- NavigationRail(
- backgroundColor: Colors.transparent,
- selectedIndex: _selectedIndex,
- groupAlignment: -1.0,
- minWidth: railSize,
- // leading widget?
- // leading: Icon(Icons.house_outlined, size: iconSize),
- // trailing widget does not expand to bottom
- onDestinationSelected: (int index) {
- setNavigationIndex(index);
- },
- selectedIconTheme: IconTheme.of(context).copyWith(
- size: iconSize,
- color: Colors.orangeAccent.shade100,
- ),
- unselectedIconTheme: IconTheme.of(context).copyWith(
- size: iconSize,
- color: Colors.blueGrey.shade400,
- ),
- labelType: NavigationRailLabelType.none,
- destinations: <NavigationRailDestination>[
- NavigationRailDestination(
- icon: Icon(Icons.house),
- selectedIcon: Icon(Icons.house),
- label: Text('Home'),
- ),
- NavigationRailDestination(
- icon: Icon(Icons.drive_eta),
- selectedIcon: Icon(Icons.drive_eta),
- label: Text('Dashboard'),
- ),
- NavigationRailDestination(
- icon: Icon(Icons.thermostat),
- selectedIcon: Icon(Icons.thermostat),
- label: Text('HVAC'),
- ),
- NavigationRailDestination(
- icon: Icon(Icons.music_note),
- selectedIcon: Icon(Icons.music_note),
- label: Text('Media'),
- ),
- NavigationRailDestination(
- icon: Icon(Icons.view_in_ar),
- selectedIcon: Icon(Icons.view_in_ar),
- label: Text('3D example'),
- ),
- ],
+ IntrinsicHeight(
+ child: Row(children: <Widget>[
+ Theme(
+ data: Theme.of(context).copyWith(
+ // Disable indicator (for now?)
+ navigationBarTheme: NavigationBarTheme.of(context)
+ .copyWith(indicatorColor: Colors.transparent),
+ // Disable splash animations
+ splashFactory: NoSplash.splashFactory,
+ hoverColor: Colors.transparent,
),
- Positioned(
- bottom: 0,
- left: 0,
- right: 0,
- // This is the info widget with time, date, etc.
- child: ClockWiddget(
- size: railSize,
- textColor: Colors.blueGrey.shade100,
- ),
- )
- ],
- ),
- ),
- VerticalDivider(
- thickness: 1,
- width: 1,
- color: Colors.grey.shade900,
+ child: Expanded(
+ child: NavigationBar(
+ onDestinationSelected: (int index) {
+ setState(() {
+ setNavigationIndex(index);
+ });
+ },
+ selectedIndex: _selectedIndex,
+ height: railSize,
+ animationDuration: Duration(seconds: 0),
+ destinations: <Widget>[
+ NavigationDestination(
+ icon: Icon(Icons.home, size: iconSize),
+ label: 'Home',
+ ),
+ NavigationDestination(
+ icon: Icon(Icons.drive_eta, size: iconSize),
+ label: 'Dashboard',
+ ),
+ NavigationDestination(
+ icon: Icon(Icons.thermostat, size: iconSize),
+ label: 'HVAC',
+ ),
+ NavigationDestination(
+ icon: Icon(Icons.music_note, size: iconSize),
+ label: 'Media',
+ ),
+ ]),
+ ),
+ ),
+ SizedBox(
+ width: 128,
+ child: Container(
+ color: NavigationBarTheme.of(context).backgroundColor)),
+ Container(
+ color: NavigationBarTheme.of(context).backgroundColor,
+ child: VerticalDivider(
+ width: 32,
+ thickness: 1,
+ color: foregroundColor,
+ indent: railSize / 16,
+ endIndent: railSize / 16)),
+ Container(
+ color: NavigationBarTheme.of(context).backgroundColor,
+ child: ClockWidget(
+ textColor: foregroundColor,
+ size: railSize)),
+ Container(
+ color: NavigationBarTheme.of(context).backgroundColor,
+ child: VerticalDivider(
+ width: 32,
+ thickness: 1,
+ color: foregroundColor,
+ indent: railSize / 16,
+ endIndent: railSize / 16)),
+ Container(
+ color: NavigationBarTheme.of(context).backgroundColor,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ children: <Widget>[
+ Icon(Icons.bluetooth, color: foregroundColor, size: 32),
+ Icon(Icons.wifi, color: foregroundColor, size: 32),
+ Icon(Icons.signal_cellular_4_bar, color: foregroundColor, size: 32),
+ ])),
+ SizedBox(
+ width: 16,
+ child: Container(
+ color:
+ Theme.of(context).navigationBarTheme.backgroundColor)),
+ ]),
),
// This is the main content.
Expanded(
@@ -182,6 +279,16 @@ class _HomescreenState extends State<Homescreen> with TickerProviderStateMixin {
),
),
),
+ SizedBox(
+ height: railSize,
+ child: Container(
+ color: NavigationBarTheme.of(context).backgroundColor,
+ child: Align(
+ alignment: Alignment.center,
+ child: ScalableImageWidget.fromSISource(
+ si: ScalableImageSource.fromSvg(rootBundle,
+ 'images/Utility_Logo_Grey-01.svg'))))
+ )
],
),
);
diff --git a/lib/layout_size_helper.dart b/lib/layout_size_helper.dart
index 9cbb0d7..d952d79 100644
--- a/lib/layout_size_helper.dart
+++ b/lib/layout_size_helper.dart
@@ -6,7 +6,8 @@ class LayoutSizeHelper {
LayoutSizeHelper(context)
: _size = MediaQuery.of(context).size,
- _ratio = MediaQuery.of(context).devicePixelRatio;
+ //_ratio = MediaQuery.of(context).devicePixelRatio;
+ _ratio = 9 / 16;
update(context) {
_size = MediaQuery.of(context).size;
diff --git a/lib/main.dart b/lib/main.dart
index e85c7f6..c09f328 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -9,17 +9,21 @@ class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
+ const navBarColor = const Color(0xff181818);
+ const navBarIconColor = Colors.white;
+
return MaterialApp(
- title: 'Flutter Homescreen',
+ title: 'Homescreen',
theme: ThemeData(
- primarySwatch: Colors.blue,
- brightness: Brightness.light,
- ),
- darkTheme: ThemeData(
- brightness: Brightness.dark,
- /* dark theme settings */
+ navigationBarTheme: NavigationBarThemeData(
+ backgroundColor: navBarColor,
+ labelTextStyle: MaterialStateProperty.all(const TextStyle(
+ color: navBarIconColor,
+ )),
+ iconTheme: MaterialStateProperty.all(const IconThemeData(
+ color: navBarIconColor,
+ ))),
),
- themeMode: ThemeMode.dark,
home: Homescreen(),
);
}
diff --git a/lib/page_apps.dart b/lib/page_apps.dart
new file mode 100644
index 0000000..39fb754
--- /dev/null
+++ b/lib/page_apps.dart
@@ -0,0 +1,159 @@
+import 'dart:io';
+import 'dart:convert';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:jovial_svg/jovial_svg.dart';
+import 'package:flutter_homescreen/homescreen.dart';
+import 'package:flutter_homescreen/layout_size_helper.dart';
+import 'package:flutter_homescreen/generated/applauncher.pb.dart';
+
+// The Applications page.
+class AppsPage extends StatefulWidget {
+ final Future<List<AppInfo>> Function() getApps;
+ final Function(String id) startApp;
+
+ const AppsPage({Key? key, required this.getApps, required this.startApp})
+ : super(key: key);
+
+ @override
+ _AppsPageState createState() => _AppsPageState();
+}
+
+class _AppsPageState extends State<AppsPage> {
+ List<AppInfo> apps = [];
+
+ @override
+ initState() {
+ widget.getApps().then((val) => setState(() {
+ apps = val;
+ }));
+
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ var sizeHelper = LayoutSizeHelper(context);
+ return Container(
+ decoration: BoxDecoration(
+ gradient: LinearGradient(
+ begin: Alignment.topRight,
+ end: Alignment.bottomLeft,
+ colors: [Colors.blueGrey.shade800, Colors.grey.shade900])),
+ constraints: BoxConstraints.expand(),
+ alignment: Alignment.center,
+ child: Column(children: [
+ SizedBox(height: 160.0),
+ GridView.builder(
+ scrollDirection: Axis.vertical,
+ shrinkWrap: true,
+ itemCount: apps.length,
+ gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
+ crossAxisCount: 3),
+ itemBuilder: (context, index) {
+ return GridTile(
+ child: Container(
+ alignment: Alignment.center,
+ child: _AppsPageEntry(
+ id: apps[index].id,
+ label: apps[index].name,
+ iconPath: apps[index].iconPath,
+ appSelected: widget.startApp,
+ )));
+ })
+ ]),
+ );
+ }
+}
+
+// Each one of the items on the Home page.
+class _AppsPageEntry extends StatefulWidget {
+ final String id;
+ final String label;
+ final String iconPath;
+ final void Function(String id) appSelected;
+
+ const _AppsPageEntry(
+ {Key? key,
+ required this.id,
+ required this.label,
+ required this.iconPath,
+ required this.appSelected})
+ : super(key: key);
+
+ @override
+ _AppsPageEntryState createState() => _AppsPageEntryState();
+}
+
+class _AppsPageEntryState extends State<_AppsPageEntry> {
+ late ScalableImage svgIcon;
+ bool svgIconLoaded = false;
+ final iconColor = const Color(0xff4ee6f5);
+
+ @override
+ void initState() {
+ if (widget.iconPath.endsWith(".svg")) {
+ readSvgIcon().then((val) => setState(() {
+ svgIconLoaded = val;
+ }));
+ }
+ super.initState();
+ }
+
+ Future<bool> readSvgIcon() async {
+ if (widget.iconPath.endsWith(".svg")) {
+ var iconFile = File(widget.iconPath);
+ if (await iconFile.exists()) {
+ svgIcon = await ScalableImage.fromSvgStream(iconFile.openRead().transform(utf8.decoder));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Widget buildIcon() {
+ if (svgIconLoaded) {
+ return GestureDetector(
+ onTap: () {
+ widget.appSelected(widget.id);
+ },
+ child: SizedBox.expand(
+ child: ScalableImageWidget(si: svgIcon))
+ );
+ } else {
+ return OutlinedButton(
+ style: ElevatedButton.styleFrom(
+ shape: CircleBorder(),
+ padding: EdgeInsets.all(8),
+ side: BorderSide(width: 4, color: iconColor),
+ ),
+ onPressed: () {
+ widget.appSelected(widget.id);
+ },
+ child: Icon(Icons.question_mark,
+ color: iconColor,
+ size: 160.0));
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.symmetric(vertical: 32.0),
+ child: Column(
+ children: [
+ Expanded(child: buildIcon()),
+ Padding(
+ padding: EdgeInsets.all(4),
+ child: Text(
+ widget.label,
+ style: DefaultTextStyle.of(context).style.copyWith(
+ fontSize: 28,
+ color: iconColor,
+ ),
+ ),
+ ),
+ ],
+ ));
+ }
+}
diff --git a/lib/page_home.dart b/lib/page_home.dart
deleted file mode 100644
index 0c93c4e..0000000
--- a/lib/page_home.dart
+++ /dev/null
@@ -1,108 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_homescreen/homescreen.dart';
-import 'package:flutter_homescreen/layout_size_helper.dart';
-
-// The Home page.
-class HomePage extends StatelessWidget {
- final Function(int index) onSetNavigationIndex;
-
- const HomePage({Key? key, required this.onSetNavigationIndex})
- : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- var sizeHelper = LayoutSizeHelper(context);
- return Container(
- decoration: BoxDecoration(
- gradient: LinearGradient(
- begin: Alignment.topRight,
- end: Alignment.bottomLeft,
- colors: [Colors.blueGrey.shade800, Colors.grey.shade900])),
- constraints: BoxConstraints.expand(),
- alignment: Alignment.center,
- child: Wrap(
- spacing: sizeHelper.largePadding,
- runSpacing: sizeHelper.largePadding,
- children: <Widget>[
- _HomePageEntry(
- label: "DASHBOARD",
- icon: Icons.drive_eta,
- onPressed: () {
- onSetNavigationIndex(PageIndex.dashboard.index);
- },
- ),
- _HomePageEntry(
- label: "HVAC",
- icon: Icons.thermostat,
- onPressed: () {
- onSetNavigationIndex(PageIndex.hvac.index);
- },
- ),
- _HomePageEntry(
- label: "MEDIA",
- icon: Icons.music_note,
- onPressed: () {
- onSetNavigationIndex(PageIndex.media.index);
- },
- ),
- _HomePageEntry(
- label: "DEMO 3D",
- icon: Icons.view_in_ar,
- onPressed: () {
- onSetNavigationIndex(PageIndex.demo3d.index);
- },
- ),
- ],
- ));
- }
-}
-
-// Each one of the items on the Home page.
-class _HomePageEntry extends StatelessWidget {
- final String label;
- final IconData icon;
- final Null Function() onPressed;
-
- const _HomePageEntry(
- {Key? key,
- required this.label,
- required this.icon,
- required this.onPressed})
- : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- var sizeHelper = LayoutSizeHelper(context);
- return Padding(
- padding: const EdgeInsets.symmetric(vertical: 8.0),
- child: Column(
- children: [
- OutlinedButton(
- style: ElevatedButton.styleFrom(
- shape: CircleBorder(),
- padding: EdgeInsets.all(sizeHelper.largePadding),
- side: BorderSide(
- width: sizeHelper.defaultBorder,
- color: Colors.lightBlue.shade100),
- ),
- onPressed: onPressed,
- child: Icon(
- icon,
- color: Colors.lightBlue.shade50,
- size: sizeHelper.largeIconSize,
- ),
- ),
- Padding(
- padding: EdgeInsets.all(sizeHelper.defaultPadding),
- child: Text(
- label,
- style: DefaultTextStyle.of(context).style.copyWith(
- fontSize: sizeHelper.baseFontSize,
- color: Colors.lightBlue.shade100,
- ),
- ),
- ),
- ],
- ));
- }
-}
diff --git a/lib/page_media.dart b/lib/page_media.dart
deleted file mode 100644
index 618feb3..0000000
--- a/lib/page_media.dart
+++ /dev/null
@@ -1,78 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_homescreen/layout_size_helper.dart';
-
-class MediaPage extends StatelessWidget {
- const MediaPage({Key? key}) : super(key: key);
-
- Widget _createMediaButton(
- IconData icon, double iconSize, Null Function() onPressed) {
- return Padding(
- padding: EdgeInsets.all(iconSize / 8),
- child: ElevatedButton(
- onPressed: onPressed,
- child: Icon(
- icon,
- color: Colors.blueGrey.shade700,
- size: iconSize,
- ),
- style: ElevatedButton.styleFrom(
- shape: CircleBorder(),
- padding: EdgeInsets.all(iconSize / 8),
- primary: Colors.blueGrey.shade100,
- onPrimary: Colors.white,
- ),
- ),
- );
- }
-
- @override
- Widget build(BuildContext context) {
- var sizeHelper = LayoutSizeHelper(context);
- return Container(
- color: Colors.deepPurple.shade50,
- child: Center(
- child: Container(
- color: Colors.blueGrey.shade900,
- constraints: BoxConstraints.expand(),
- alignment: Alignment.center,
- child: Stack(
- alignment: Alignment.center,
- children: [
- AspectRatio(
- aspectRatio: 16 / 9,
- child: Container(
- decoration: BoxDecoration(
- gradient: LinearGradient(
- begin: Alignment.bottomLeft,
- end: Alignment.topRight,
- colors: [
- Colors.blueGrey.shade700,
- Colors.blueGrey.shade400
- ])),
- ),
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- _createMediaButton(
- Icons.skip_previous,
- sizeHelper.defaultIconSize,
- () {},
- ),
- _createMediaButton(
- Icons.play_arrow,
- sizeHelper.defaultIconSize,
- () {},
- ),
- _createMediaButton(
- Icons.skip_next,
- sizeHelper.defaultIconSize,
- () {},
- ),
- ],
- )
- ],
- ),
- )));
- }
-}
diff --git a/lib/widget_clock.dart b/lib/widget_clock.dart
index ae9fb26..c7b53ec 100644
--- a/lib/widget_clock.dart
+++ b/lib/widget_clock.dart
@@ -3,18 +3,18 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
-class ClockWiddget extends StatefulWidget {
+class ClockWidget extends StatefulWidget {
final double size;
final Color textColor;
- const ClockWiddget({Key? key, required this.size, required this.textColor})
+ const ClockWidget({Key? key, required this.size, required this.textColor})
: super(key: key);
@override
- _ClockWiddgetState createState() => _ClockWiddgetState();
+ _ClockWidgetState createState() => _ClockWidgetState();
}
-class _ClockWiddgetState extends State<ClockWiddget> {
+class _ClockWidgetState extends State<ClockWidget> {
late Timer _timer;
DateTime _now = DateTime.now();
@@ -42,20 +42,14 @@ class _ClockWiddgetState extends State<ClockWiddget> {
Widget build(BuildContext context) {
TextStyle? textStyle = Theme.of(context)
.textTheme
- .headline2
+ .labelLarge
?.copyWith(color: widget.textColor);
return Container(
height: widget.size,
- padding: EdgeInsets.all(16.0),
- decoration: BoxDecoration(
- border: Border(
- top: BorderSide(
- width: 1.0,
- ),
- ),
- ),
+ //padding: EdgeInsets.all(16.0),
child: Column(
children: [
+ SizedBox(height: 16),
FittedBox(
fit: BoxFit.contain,
child: Text(
@@ -63,7 +57,7 @@ class _ClockWiddgetState extends State<ClockWiddget> {
style: textStyle,
),
),
- const Divider(thickness: 1),
+ //const Divider(thickness: 1),
FittedBox(
fit: BoxFit.contain,
child: Text(
@@ -71,6 +65,7 @@ class _ClockWiddgetState extends State<ClockWiddget> {
style: textStyle,
),
),
+ SizedBox(height: 16),
],
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
),
diff --git a/protos/applauncher.proto b/protos/applauncher.proto
new file mode 100644
index 0000000..0b8e0fc
--- /dev/null
+++ b/protos/applauncher.proto
@@ -0,0 +1,50 @@
+syntax = "proto3";
+
+package automotivegradelinux;
+
+service AppLauncher {
+ rpc StartApplication(StartRequest) returns (StartResponse) {}
+ rpc ListApplications(ListRequest) returns (ListResponse) {}
+ rpc GetStatusEvents(StatusRequest) returns (stream StatusResponse) {}
+}
+
+message StartRequest {
+ string id = 1;
+}
+
+message StartResponse {
+ bool status = 1;
+ string message = 2;
+}
+
+message ListRequest {
+}
+
+message ListResponse {
+ repeated AppInfo apps = 1;
+}
+
+message AppInfo {
+ string id = 1;
+ string name = 2;
+ string icon_path = 3;
+}
+
+message StatusRequest {
+}
+
+message AppStatus {
+ string id = 1;
+ string status = 2;
+}
+
+// Future-proofing for e.g. potentially signaling a list refresh
+message LauncherStatus {
+}
+
+message StatusResponse {
+ oneof status {
+ AppStatus app = 1;
+ LauncherStatus launcher = 2;
+ }
+}
diff --git a/pubspec.lock b/pubspec.lock
index a5a78f1..21e1809 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,13 +1,27 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
+ archive:
+ dependency: transitive
+ description:
+ name: archive
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.3.4"
+ args:
+ dependency: transitive
+ description:
+ name: args
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.3.1"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.8.1"
+ version: "2.9.0"
boolean_selector:
dependency: transitive
description:
@@ -21,28 +35,35 @@ packages:
name: characters
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
- charcode:
- dependency: transitive
- description:
- name: charcode
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.3.1"
+ version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
- version: "1.15.0"
+ version: "1.16.0"
+ convert:
+ dependency: transitive
+ description:
+ name: convert
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.1.1"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.2"
cupertino_icons:
dependency: "direct main"
description:
@@ -56,17 +77,66 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0"
+ version: "1.3.1"
+ fixnum:
+ dependency: transitive
+ description:
+ name: fixnum
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
+ flutter_lints:
+ dependency: "direct dev"
+ description:
+ name: flutter_lints
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.1"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
+ googleapis_auth:
+ dependency: transitive
+ description:
+ name: googleapis_auth
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.3.1"
+ grpc:
+ dependency: "direct main"
+ description:
+ name: grpc
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.1.0"
+ http:
+ dependency: transitive
+ description:
+ name: http
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.13.5"
+ http2:
+ dependency: transitive
+ description:
+ name: http2
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.1"
+ http_parser:
+ dependency: transitive
+ description:
+ name: http_parser
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "4.0.2"
infinite_listview:
dependency: transitive
description:
@@ -81,20 +151,55 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.17.0"
+ jovial_misc:
+ dependency: transitive
+ description:
+ name: jovial_misc
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.8.4"
+ jovial_svg:
+ dependency: "direct main"
+ description:
+ name: jovial_svg
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.6"
+ js:
+ dependency: transitive
+ description:
+ name: js
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.6.5"
+ lints:
+ dependency: transitive
+ description:
+ name: lints
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.1"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.10"
+ version: "0.12.12"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.7.0"
+ version: "1.8.0"
nested:
dependency: transitive
description:
@@ -115,7 +220,28 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.0"
+ version: "1.8.2"
+ petitparser:
+ dependency: transitive
+ description:
+ name: petitparser
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "5.1.0"
+ pointycastle:
+ dependency: transitive
+ description:
+ name: pointycastle
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.6.2"
+ protobuf:
+ dependency: "direct main"
+ description:
+ name: protobuf
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.1.0"
provider:
dependency: "direct main"
description:
@@ -134,7 +260,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.1"
+ version: "1.9.0"
stack_trace:
dependency: transitive
description:
@@ -155,21 +281,21 @@ packages:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0"
+ version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0"
+ version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.4.2"
+ version: "0.4.12"
typed_data:
dependency: transitive
description:
@@ -183,7 +309,14 @@ packages:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0"
+ version: "2.1.2"
+ xml:
+ dependency: transitive
+ description:
+ name: xml
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "6.1.0"
sdks:
- dart: ">=2.12.0 <3.0.0"
- flutter: ">=1.16.0"
+ dart: ">=2.18.0 <3.0.0"
+ flutter: ">=3.0.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index fdadb5d..dfc2877 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -2,7 +2,7 @@ name: flutter_homescreen
description: A new Flutter project.
# The following line prevents the package from being accidentally published to
-# pub.dev using `pub publish`. This is preferred for private packages.
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
@@ -12,34 +12,54 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
-# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+# In Windows, build-name is used as the major, minor, and patch parts
+# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1
environment:
- sdk: ">=2.12.0 <3.0.0"
+ sdk: '>=2.18.0 <3.0.0'
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
-
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
+
intl: ^0.17.0
numberpicker: ^2.1.1
provider: ^6.0.1
+ jovial_svg: ^1.1.6
+
+ grpc: ^3.0.0
+ protobuf: ^2.1.0
+
dev_dependencies:
flutter_test:
sdk: flutter
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^2.0.0
+
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
-# The following section is specific to Flutter.
+# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
@@ -49,6 +69,7 @@ flutter:
# To add assets to your application, add an assets section, like this:
assets:
+ - images/Utility_Logo_Grey-01.svg
- images/HMI_HVAC_Fan_Icon.png
- images/HMI_HVAC_Left_Chair_ON.png
- images/HMI_HVAC_Right_Chair_ON.png
@@ -60,7 +81,7 @@ flutter:
- images/HMI_Dashboard_Car_720.png
# An image asset can refer to one or more resolution-specific "variants", see
- # https://flutter.dev/assets-and-images/#resolution-aware.
+ # https://flutter.dev/assets-and-images/#resolution-aware
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages