| // Copyright 2016 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| import 'dart:async'; |
| import 'dart:convert'; |
| |
| import 'package:flutter/material.dart'; |
| import 'package:flutter/services.dart'; |
| import 'package:flutter/widgets.dart'; |
| |
| class BakuDistro extends StatefulWidget { |
| @override |
| _BakuDistroState createState() => new _BakuDistroState(); |
| } |
| |
| class _Device { |
| String name, description; |
| |
| _Device(this.name, this.description); |
| } |
| |
| class _BakuDistroState extends State<BakuDistro> { |
| _BakuDistroState() { |
| HostMessages.addMessageHandler('deviceOnline', _onDeviceOnline); |
| HostMessages.addMessageHandler('deviceOffline', _onDeviceOffline); |
| HostMessages.addMessageHandler('castTerminated', _onCastTerminated); |
| } |
| |
| final Map<String, String> devices = {}; |
| final Set<String> castTargets = new Set(); |
| |
| Future<String> _onDeviceOnline(final String json) async { |
| final Map<String, dynamic> message = JSON.decode(json); |
| setState(() => devices[message['name']] = message['description']); |
| return null; |
| } |
| |
| Future<String> _onDeviceOffline(final String name) async { |
| setState(() { |
| devices.remove(name); |
| castTargets.remove(name); |
| }devices.remove(name)); |
| if (castTargetName == name) { |
| terminateCast(); |
| } |
| return null; |
| } |
| |
| InputValue _data = InputValue.empty; |
| |
| InputValue get data => _data; |
| |
| void set data(final InputValue value) { |
| if (_data != value) { |
| final InputValue oldData = _data; |
| setState(() => _data = value); |
| |
| if (castTargetName != null && oldData.text != value.text ) { |
| HostMessages.sendToHost('updateCast', getCastData()) |
| .catchError(_handleCastError); |
| } |
| } |
| } |
| |
| String getCastData() { |
| return JSON.encode({ |
| 'name': castTargetName, |
| 'data': data.text |
| }); |
| } |
| |
| String _castTargetName; |
| |
| String get castTargetName => _castTargetName; |
| |
| void set castTargetName(final String value) { |
| if (_castTargetName != value) { |
| initiateCast(value); |
| } |
| } |
| |
| void initiateCast(final String target) { |
| terminateCast(); |
| if (target != null) { |
| setState(() => _castTargetName = target); |
| HostMessages.sendToHost('initiateCast', getCastData()) |
| .catchError(_handleCastError); |
| } |
| } |
| |
| void terminateCast() { |
| if (_castTargetName != null) { |
| HostMessages.sendToHost('terminateCast', _castTargetName); |
| setState(() => _castTargetName = null); |
| } |
| } |
| |
| Future<String> _onCastTerminated(final String name) async { |
| if (castTargetName == name) { |
| terminateCast(); |
| } |
| return null; |
| } |
| |
| void _handleCastError(final Object e) { |
| terminateCast(); |
| Scaffold.of(context).showSnackBar( |
| new SnackBar(content: new Text(e.toString()))); |
| } |
| |
| @override |
| Widget build(final BuildContext context) { |
| final List<_Device> sortedDevices = devices.keys.map((name) => |
| new _Device(name, devices[name])).toList(growable: false); |
| sortedDevices.sort((a, b) => a.description.compareTo(b.description)); |
| |
| final List<Widget> layout = []; |
| |
| if (castTargetName == null) { |
| final TextStyle style = Theme.of(context).textTheme.display1; |
| |
| layout.add(new Padding( |
| padding: new EdgeInsets.all(8.0), |
| child: data.text.isEmpty? |
| new Text('No content', style: |
| style.copyWith(color: Theme.of(context).disabledColor)) : |
| new Text(data.text, style: style) |
| )); |
| } |
| |
| layout.add(new Input( |
| value: data, |
| labelText: 'Text content', |
| onChanged: (value) => data = value |
| )); |
| |
| if (castTargetName == null) { |
| layout.add(new MaterialList( |
| type: MaterialListType.oneLine, |
| children: sortedDevices.map((d) => new ListItem( |
| title: new Text(d.description), |
| onTap: () => castTargetName = d.name |
| )) |
| )); |
| } else { |
| layout.add(new RaisedButton( |
| child: new Text('Recall'), |
| onPressed: terminateCast |
| )); |
| } |
| |
| return new Scaffold( |
| appBar: new AppBar( |
| title: new Text('Baku Distro Example') |
| ), |
| body: new Column(children: layout) |
| ); |
| } |
| } |