syncslides: Updating to the latest versions of Flutter,
Mojo and v23Discovery and fixing breaking changes.
-Adding some logging.
-Using asset bundl so images load when phone is
not connected Fixes: https://github.com/vanadium/syncslides/issues/1
Please note that Flutter no longer publishes on Pub and
therefore we all need to have a clone of Flutter at a
specific place (until we add a Flutter profile)
I have added two files that specify the commit # for
flutter and mojo that I have tested the app in. This is
temporary and will go away when we have Mojo and Flutter
profiles.
Change-Id: If658a9cebb3fb649686dcfb5b88dfc164b74c6c9
diff --git a/dart/FLUTTER_VERSION b/dart/FLUTTER_VERSION
new file mode 100644
index 0000000..fb36760
--- /dev/null
+++ b/dart/FLUTTER_VERSION
@@ -0,0 +1 @@
+a35b214d891efaeddfb4b4270ebe222dfab16a8a
diff --git a/dart/MOJO_VERSION b/dart/MOJO_VERSION
new file mode 100644
index 0000000..df87133
--- /dev/null
+++ b/dart/MOJO_VERSION
@@ -0,0 +1 @@
+7a690c5c0344946ed74402d61d473502bc03ad77
diff --git a/dart/Makefile b/dart/Makefile
index 922d478..be5398d 100644
--- a/dart/Makefile
+++ b/dart/Makefile
@@ -37,8 +37,8 @@
# DEVICE_NUM=1 make run
# DEVICE_NUM=2 make run
run: packages
- pub run sky_tools build && pub run sky_tools run_mojo \
- --mojo-path $(MOJO_DIR)/src/mojo/devtools/common/mojo_run \
+ pub run flutter_tools build && pub run flutter_tools run_mojo \
+ --mojo-path $(MOJO_DIR)/src \
--android --mojo-debug -- --enable-multiprocess \
--map-origin="https://syncslides.mojo.v.io/=$(PWD)" \
--map-origin="https://discovery.mojo.v.io/=$(JIRI_ROOT)/release/mojo/discovery/gen/mojo/android" \
diff --git a/dart/README.md b/dart/README.md
index ced3a3b..fc704b7 100644
--- a/dart/README.md
+++ b/dart/README.md
@@ -4,10 +4,17 @@
# Prerequisites
-##Mojo
+## Mojo
Currently, development is heavily tied to an existing installation of [Mojo](https://github.com/domokit/mojo). Please ensure that your Mojo checkout is located at `$MOJO_DIR` and has been build for Android. Instructions are available [here](https://github.com/domokit/mojo#mojo).
+We only guarantee compatibility with the version of Mojo as specified in MOJO_VERSION.
+
+## Flutter
+
+A clone of https://github.com/flutter/flutter/ at the commit # specified in FLUTTER_VERSION file must be available in a directory
+called `flutter` at the same level as $V23_ROOT directory.
+
## Dart
Flutter depends on a relatively new version of the Dart SDK. Therefore, please ensure that you have installed the following version or greater:
diff --git a/dart/flutter.yaml b/dart/flutter.yaml
index 2da469b..00911c6 100644
--- a/dart/flutter.yaml
+++ b/dart/flutter.yaml
@@ -3,3 +3,14 @@
- name: navigation/arrow_back
- name: navigation/arrow_forward
- name: content/add
+assets:
+ - assets/images/defaults/thumbnail.png
+ - assets/images/sample_decks/vanadium/1.jpg
+ - assets/images/sample_decks/vanadium/2.jpg
+ - assets/images/sample_decks/vanadium/3.jpg
+ - assets/images/sample_decks/vanadium/4.jpg
+ - assets/images/sample_decks/vanadium/5.jpg
+ - assets/images/sample_decks/vanadium/6.jpg
+ - assets/images/sample_decks/baku/thumb.png
+ - assets/images/sample_decks/vanadium/thumb.png
+ - assets/images/sample_decks/pitch/thumb.png
diff --git a/dart/lib/components/deckgrid.dart b/dart/lib/components/deckgrid.dart
index 479e995..f092be9 100644
--- a/dart/lib/components/deckgrid.dart
+++ b/dart/lib/components/deckgrid.dart
@@ -86,7 +86,7 @@
subtitleWidget = _stopWrapping(subtitleWidget);
var footer = _buildBoxFooter(deckData.name, subtitleWidget);
var box = _buildCard(deckData.key, [thumbnail, footer], () {
- Navigator.of(context).push(new PageRoute(
+ Navigator.of(context).push(new MaterialPageRoute(
builder: (context) => new SlideListPage(deckData.key, deckData.name)));
});
diff --git a/dart/lib/components/slidelist.dart b/dart/lib/components/slidelist.dart
index cbbb17f..e27dbc7 100644
--- a/dart/lib/components/slidelist.dart
+++ b/dart/lib/components/slidelist.dart
@@ -9,8 +9,6 @@
import '../stores/store.dart';
import '../styles/common.dart' as style;
-import '../utils/keyvalue.dart';
-
import 'slideshow.dart';
// SlideListPage is the full page view of the list of slides for a deck.
@@ -36,9 +34,8 @@
child: new Icon(icon: 'navigation/arrow_forward'), onPressed: () async {
model.PresentationAdvertisement presentation =
await _store.startPresentation(deckId);
- Navigator
- .of(context)
- .push(new PageRoute(builder: (context) => new SlideshowPage(deckId)));
+ Navigator.of(context).push(new MaterialPageRoute(
+ builder: (context) => new SlideshowPage(deckId)));
});
}
}
@@ -69,18 +66,13 @@
}
Widget build(BuildContext context) {
- // Create a list of <SlideNumber, Slide> pairs.
- List<KeyValue<int, model.Slide>> slidesWithPosition = [];
- for (var i = 0; i < _slides.length; i++) {
- slidesWithPosition.add(new KeyValue(i, _slides[i]));
- }
return new ScrollableList(
itemExtent: style.Size.listHeight,
- items: slidesWithPosition,
- itemBuilder: (context, kv) =>
- _buildSlide(context, kv.key.toString(), kv.value, onTap: () {
- _store.setCurrSlideNum(config.deckId, kv.key);
- Navigator.of(context).push(new PageRoute(
+ items: _slides,
+ itemBuilder: (context, value, index) =>
+ _buildSlide(context, index.toString(), value, onTap: () {
+ _store.setCurrSlideNum(config.deckId, index);
+ Navigator.of(context).push(new MaterialPageRoute(
builder: (context) => new SlideshowPage(config.deckId)));
}));
}
diff --git a/dart/lib/discovery/client.dart b/dart/lib/discovery/client.dart
index e2a766f..d120433 100644
--- a/dart/lib/discovery/client.dart
+++ b/dart/lib/discovery/client.dart
@@ -6,11 +6,14 @@
import 'dart:convert';
import 'package:flutter/services.dart' show shell;
+import 'package:logging/logging.dart';
import 'package:v23discovery/discovery.dart' as v23discovery;
import '../models/all.dart' as model;
import '../utils/asset.dart' as assetutil;
+final Logger log = new Logger('discovery/client');
+
const String v23DiscoveryMojoUrl =
'https://syncslides.mojo.v.io/packages/v23discovery/mojo_services/android/discovery.mojo';
@@ -38,6 +41,7 @@
new Map();
Future advertise(model.PresentationAdvertisement presentation) async {
+ log.info('Started advertising ${presentation.deck.name}.');
if (_advertiseCalls.containsKey(presentation.key)) {
// We are already advertising for this presentation.
return _advertiseCalls[presentation.key].responseFuture;
@@ -49,7 +53,7 @@
v23discovery.Service serviceInfo = new v23discovery.Service()
..instanceUuid = UTF8.encode(presentation.key)
..interfaceName = presentationInterfaceName
- ..instanceName = ''
+ ..instanceName = presentation.key
..attrs = serviceAttrs
..addrs = [presentation.syncgroupName];
@@ -62,6 +66,7 @@
new ProxyResponseFuturePair(advertiser, advertiseResponseFuture);
await advertiseResponseFuture;
+ log.info('Advertised ${presentation.deck.name} under ${presentation.key}.');
}
// Tracks advertisements that are in the middle of being stopped.
@@ -93,7 +98,7 @@
stoppingCall.then((_) {
_advertiseCalls.remove(presentationId);
- _stoppingAdvertisingCalls.remove(presentationId);
+ log.info('Stopped advertising ${presentationId}.');
}).catchError((e) {
_stoppingAdvertisingCalls.remove(presentationId);
throw e;
@@ -117,6 +122,7 @@
_scanCall = new ProxyResponseFuturePair(scanner, scannerResponseFuture);
await scannerResponseFuture;
+ log.info('Scan started.');
}
// Tracks whether we are already in the middle of stopping scan.
@@ -144,7 +150,7 @@
_stoppingScanCall.then((_) {
_scanCall = null;
- _stoppingScanCall = null;
+ log.info('Scan stopped.');
}).catchError((e) {
_stoppingScanCall = null;
throw e;
@@ -154,14 +160,18 @@
class ScanHandler extends v23discovery.ScanHandler {
found(v23discovery.Service s) async {
String key = UTF8.decode(s.instanceUuid);
+ log.info('Found presentation ${s.attrs['name']} under $key.');
// Ignore our own advertised services.
if (_advertiseCalls.containsKey(key)) {
+ log.info(
+ 'Presentation ${s.attrs['name']} was advertised by this device itself, ignoring it.');
return;
}
// TODO(aghassemi): For now we use the default thumbnail. We need to find a way
// to fetch the actual thumbnail from the other side.
- var thumbnail = await assetutil.getRawBytes(assetutil.defaultThumbnailUrl);
+ var thumbnail =
+ await assetutil.getRawBytes(assetutil.defaultThumbnailAssetKey);
model.Deck deck =
new model.Deck(s.attrs['deckid'], s.attrs['name'], thumbnail.toList());
var syncgroupName = s.addrs[0];
@@ -174,6 +184,7 @@
lost(List<int> instanceId) {
String presentationId = UTF8.decode(instanceId);
// Ignore our own advertised services.
+ log.info('Lost presentation $presentationId.');
_onLostEmitter.add(presentationId);
}
}
diff --git a/dart/lib/main.dart b/dart/lib/main.dart
index 0503e05..85e2522 100644
--- a/dart/lib/main.dart
+++ b/dart/lib/main.dart
@@ -3,13 +3,23 @@
// license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
+import 'package:logging/logging.dart';
import 'styles/common.dart' as style;
import 'components/deckgrid.dart';
void main() {
+ _initLogging();
+
runApp(new MaterialApp(
theme: style.theme,
title: 'SyncSlides',
routes: {'/': (RouteArguments args) => new DeckGridPage()}));
}
+
+void _initLogging() {
+ Logger.root.level = Level.ALL;
+ Logger.root.onRecord.listen((LogRecord rec) {
+ print('\nSyncSlides: ${rec.time}: ${rec.message}');
+ });
+}
diff --git a/dart/lib/stores/syncbase_store.dart b/dart/lib/stores/syncbase_store.dart
index 2a98a33..e6d6ddf 100644
--- a/dart/lib/stores/syncbase_store.dart
+++ b/dart/lib/stores/syncbase_store.dart
@@ -165,10 +165,12 @@
Future<int> getCurrSlideNum(String deckId) async {
sb.SyncbaseTable tb = await _getDecksTable();
- var v = await tb.get(keyutil.getCurrSlideNumKey(deckId));
- if (v == null || v.isEmpty) {
+ String key = keyutil.getCurrSlideNumKey(deckId);
+ // TODO(aghassemi): Run exist and get in a batch.
+ if (await tb.row(key).exists()) {
return 0;
}
+ var v = await tb.get(key);
return v[0];
}
diff --git a/dart/lib/utils/asset.dart b/dart/lib/utils/asset.dart
index bb001a3..fbeaa73 100644
--- a/dart/lib/utils/asset.dart
+++ b/dart/lib/utils/asset.dart
@@ -5,17 +5,15 @@
import 'dart:async';
import 'dart:typed_data';
+import 'package:mojo/core.dart';
+
import 'package:flutter/services.dart' as services;
-Map<String, Uint8List> _assetCache = new Map<String, Uint8List>();
-Future<Uint8List> getRawBytes(String url) async {
- if (_assetCache.containsKey(url)) {
- return _assetCache[url];
- }
- services.Response response = await services.fetchBody(url);
- var bytes = new Uint8List.fromList(response.body.buffer.asUint8List());
- _assetCache[url] = bytes;
+Future<Uint8List> getRawBytes(String assetKey) async {
+ MojoDataPipeConsumer pipe = await services.rootBundle.load(assetKey);
+ ByteData data = await DataPipeDrainer.drainHandle(pipe);
+ Uint8List bytes = new Uint8List.fromList(data.buffer.asUint8List());
return bytes;
}
-String defaultThumbnailUrl = 'assets/images/defaults/thumbnail.png';
+String defaultThumbnailAssetKey = 'assets/images/defaults/thumbnail.png';
diff --git a/dart/lib/utils/keyvalue.dart b/dart/lib/utils/keyvalue.dart
deleted file mode 100644
index 8fa83d7..0000000
--- a/dart/lib/utils/keyvalue.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2015 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.
-
-// KeyValue presents a generic pair of key and value objects.
-class KeyValue<T1, T2> {
- T1 key;
- T2 value;
-
- KeyValue(this.key, this.value);
-}
diff --git a/dart/pubspec.lock b/dart/pubspec.lock
index a8af949..bf3850a 100644
--- a/dart/pubspec.lock
+++ b/dart/pubspec.lock
@@ -30,8 +30,10 @@
source: hosted
version: "0.0.7"
cassowary:
- description: cassowary
- source: hosted
+ description:
+ path: "../../../../../flutter/packages/cassowary"
+ relative: true
+ source: path
version: "0.1.7"
charcode:
description: charcode
@@ -45,10 +47,6 @@
description: collection
source: hosted
version: "1.1.3"
- concepts:
- description: concepts
- source: hosted
- version: "0.2.0"
convert:
description: convert
source: hosted
@@ -61,21 +59,27 @@
description: csslib
source: hosted
version: "0.12.2"
- either:
- description: either
- source: hosted
- version: "0.1.8"
fixnum:
description: fixnum
source: hosted
version: "0.9.1+2"
flutter:
- description: flutter
- source: hosted
- version: "0.0.18"
+ description:
+ path: "../../../../../flutter/packages/flutter"
+ relative: true
+ source: path
+ version: "0.0.20"
+ flutter_tools:
+ description:
+ path: "../../../../../flutter/packages/flutter_tools"
+ relative: true
+ source: path
+ version: "0.0.38"
flx:
- description: flx
- source: hosted
+ description:
+ path: "../../../../../flutter/packages/flx"
+ relative: true
+ source: path
version: "0.0.10"
glob:
description: glob
@@ -116,35 +120,33 @@
mojo:
description: mojo
source: hosted
- version: "0.4.2"
+ version: "0.4.3"
mojo_apptest:
description: mojo_apptest
source: hosted
- version: "0.2.7"
+ version: "0.2.8"
mojo_sdk:
description: mojo_sdk
source: hosted
- version: "0.2.1"
+ version: "0.2.2"
mojo_services:
description: mojo_services
source: hosted
- version: "0.4.4"
+ version: "0.4.5"
mojom:
description: mojom
source: hosted
- version: "0.2.7"
+ version: "0.2.8"
mustache4dart:
description: mustache4dart
source: hosted
version: "1.0.10"
newton:
- description: newton
- source: hosted
+ description:
+ path: "../../../../../flutter/packages/newton"
+ relative: true
+ source: path
version: "0.1.5"
- option:
- description: option
- source: hosted
- version: "1.1.0"
package_config:
description: package_config
source: hosted
@@ -169,22 +171,10 @@
description: pub_semver
source: hosted
version: "1.2.3"
- quiver:
- description: quiver
- source: hosted
- version: "0.21.4"
shelf:
description: shelf
source: hosted
version: "0.6.4+1"
- shelf_path:
- description: shelf_path
- source: hosted
- version: "0.1.7"
- shelf_route:
- description: shelf_route
- source: hosted
- version: "0.13.5"
shelf_static:
description: shelf_static
source: hosted
@@ -196,15 +186,11 @@
sky_engine:
description: sky_engine
source: hosted
- version: "0.0.49"
+ version: "0.0.56"
sky_services:
description: sky_services
source: hosted
- version: "0.0.50"
- sky_tools:
- description: sky_tools
- source: hosted
- version: "0.0.37"
+ version: "0.0.56"
source_map_stack_trace:
description: source_map_stack_trace
source: hosted
@@ -237,10 +223,6 @@
description: typed_data
source: hosted
version: "1.1.1"
- uri:
- description: uri
- source: hosted
- version: "0.11.0"
utf:
description: utf
source: hosted
@@ -252,7 +234,7 @@
v23discovery:
description: v23discovery
source: hosted
- version: "0.0.2"
+ version: "0.0.4"
vector_math:
description: vector_math
source: hosted
diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml
index b44d99c..45a372b 100644
--- a/dart/pubspec.yaml
+++ b/dart/pubspec.yaml
@@ -1,9 +1,12 @@
name: syncslides
description: A simple multi-device presentation system built on Flutter and Syncbase.
dependencies:
- flutter: ">=0.0.16 <0.1.0"
+ flutter:
+ path: "../../../../../flutter/packages/flutter"
+ logging: ">=0.11.2 <0.12.0"
syncbase: ">=0.0.9 <0.1.0"
- v23discovery: ">=0.0.1 < 0.1.0"
+ v23discovery: ">=0.0.4 < 0.1.0"
uuid: ">=0.5.0 <0.6.0"
dev_dependencies:
- sky_tools: ">=0.0.27 <0.1.0"
+ flutter_tools:
+ path: "../../../../../flutter/packages/flutter_tools"