diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/demo_3d.dart | 20 | ||||
-rw-r--r-- | lib/generated/applauncher.pb.dart | 463 | ||||
-rw-r--r-- | lib/generated/applauncher.pbenum.dart | 7 | ||||
-rw-r--r-- | lib/generated/applauncher.pbgrpc.dart | 106 | ||||
-rw-r--r-- | lib/generated/applauncher.pbjson.dart | 99 | ||||
-rw-r--r-- | lib/homescreen.dart | 311 | ||||
-rw-r--r-- | lib/layout_size_helper.dart | 3 | ||||
-rw-r--r-- | lib/main.dart | 20 | ||||
-rw-r--r-- | lib/page_apps.dart | 159 | ||||
-rw-r--r-- | lib/page_home.dart | 108 | ||||
-rw-r--r-- | lib/page_media.dart | 78 | ||||
-rw-r--r-- | lib/widget_clock.dart | 23 |
12 files changed, 1066 insertions, 331 deletions
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, ), |