syncslides: Upgrading to latest flutter/syncbase/discovery and
fixing plenty of breaking changes.

Change-Id: I2104a17774327298d4d14b73747c40a2869a9c89
diff --git a/.gitignore b/.gitignore
index 0ef0e2d..10f38dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
 /dart/packages
 /dart/.packages
 /dart/.pub
+/dart/*.log
 /dart/shortcut_commands
 /dart/snapshot_blob.bin
-/.jiri
\ No newline at end of file
+/.jiri
diff --git a/dart/FLUTTER_VERSION b/dart/FLUTTER_VERSION
index b01d319..cd75950 100644
--- a/dart/FLUTTER_VERSION
+++ b/dart/FLUTTER_VERSION
@@ -1 +1 @@
-b70a53807aca5c74c48298f68fcb6f041fedbe9a
+4df24abb336ff5120eba3617d82b0022bbb77b0f
diff --git a/dart/Makefile b/dart/Makefile
index 85074d9..0b8308a 100644
--- a/dart/Makefile
+++ b/dart/Makefile
@@ -67,7 +67,7 @@
 
 .PHONY: build
 build: packages
-	pub run flutter_tools build
+	pub run flutter_tools build flx
 
 .PHONY: create-shortcut
 create-shortcut: clear-shortcut build install-shell
diff --git a/dart/flutter.yaml b/dart/flutter.yaml
index ac78010..ac9fb10 100644
--- a/dart/flutter.yaml
+++ b/dart/flutter.yaml
@@ -1,19 +1,5 @@
 name: syncslides
-material-design-icons:
-  - name: action/account_circle
-  - name: action/delete
-  - name: action/perm_device_information
-  - name: av/loop
-  - name: av/stop
-  - name: av/play_arrow
-  - name: communication/live_help
-  - name: content/add
-  - name: maps/layers
-  - name: navigation/arrow_back
-  - name: navigation/arrow_forward
-  - name: navigation/menu
-  - name: notification/sync
-  - name: maps/layers
+uses-material-design: true
 assets:
   - assets/images/defaults/thumbnail.png
   - assets/images/splash/background.png
diff --git a/dart/lib/components/askquestion.dart b/dart/lib/components/askquestion.dart
index 3762a43..7ffba1a 100644
--- a/dart/lib/components/askquestion.dart
+++ b/dart/lib/components/askquestion.dart
@@ -13,6 +13,7 @@
 
   AskQuestionPage(this._deckId, this._currSlideNum);
 
+  @override
   Widget build(BuildContext context, AppState appState, AppActions appActions) {
     if (!appState.decks.containsKey(_deckId)) {
       // TODO(aghassemi): Proper error page with navigation back to main view.
@@ -27,24 +28,27 @@
 
     // TODO(aghassemi): Switch to multi-line input when support is added.
     // https://github.com/flutter/flutter/issues/627
-    var input = new Input(labelText: 'Your question', autofocus: true,
-        onSubmitted: (String questionText) async {
-      await appActions.askQuestion(
-          deckState.deck.key, _currSlideNum, questionText);
+    var input = new Input(
+        labelText: 'Your question',
+        autofocus: true,
+        onSubmitted: (InputValue questionText) async {
+          await appActions.askQuestion(
+              deckState.deck.key, _currSlideNum, questionText.text);
 
-      // TODO(aghassemi): Add a 'Question submitted.' toast on the parent page.
-      // Blocked on https://github.com/flutter/flutter/issues/608
-      Navigator.pop(context);
-    });
+          // TODO(aghassemi): Add a 'Question submitted.' toast on the parent page.
+          // Blocked on https://github.com/flutter/flutter/issues/608
+          Navigator.pop(context);
+        });
 
-    var view = new Row(children: [input], alignItems: FlexAlignItems.stretch);
+    var view = new Row(
+        children: [input], crossAxisAlignment: CrossAxisAlignment.stretch);
 
     return new Scaffold(
-        toolBar: new ToolBar(
-            left: new IconButton(
-                icon: 'navigation/arrow_back',
+        appBar: new AppBar(
+            leading: new IconButton(
+                icon: Icons.arrow_back,
                 onPressed: () => Navigator.pop(context)),
-            center: new Text('Ask a question')),
+            title: new Text('Ask a question')),
         body: new Material(child: view));
   }
 }
diff --git a/dart/lib/components/deckgrid.dart b/dart/lib/components/deckgrid.dart
index 1131d3f..f920ba8 100644
--- a/dart/lib/components/deckgrid.dart
+++ b/dart/lib/components/deckgrid.dart
@@ -7,7 +7,7 @@
 import '../models/all.dart' as model;
 import '../stores/store.dart';
 import '../styles/common.dart' as style;
-import '../utils/image_provider.dart' as imageProvider;
+import '../utils/image_provider.dart' as image_provider;
 import 'slidelist.dart';
 import 'slideshow.dart';
 import 'syncslides_page.dart';
@@ -18,6 +18,7 @@
 
 // DeckGridPage is the full page view of the list of decks.
 class DeckGridPage extends SyncSlidesPage {
+  @override
   Widget build(BuildContext context, AppState appState, AppActions appActions) {
     // Advertised decks.
     List<model.PresentationAdvertisement> presentations =
@@ -25,32 +26,33 @@
 
     // Local decks that are not advertised.
     List<model.Deck> decks = appState.decks.values
-        .where((DeckState d) => d.deck != null &&
+        .where((DeckState d) =>
+            d.deck != null &&
             !presentations.any((model.PresentationAdvertisement p) =>
                 p.deck.key == d.deck.key))
         .map((DeckState d) => d.deck);
 
     return new Scaffold(
         key: _scaffoldKey,
-        toolBar: new ToolBar(center: new Text('SyncSlides')),
+        appBar: new AppBar(title: new Text('SyncSlides')),
         floatingActionButton: new FloatingActionButton(
-            child: new Icon(icon: 'content/add'), onPressed: () {
-          appActions.loadDeckFromSdCard();
-        }),
+            child: new Icon(icon: Icons.add),
+            onPressed: () {
+              appActions.loadDeckFromSdCard();
+            }),
         drawer: _buildDrawer(context, appState),
         body: new Material(
             child: new DeckGrid(decks, presentations, appState, appActions)));
   }
 
   Widget _buildDrawer(BuildContext context, AppState appState) {
-    return new Drawer(
-        child: new Block(children: [
+    return new Drawer(child: new Block(children: [
       new DrawerItem(
-          icon: 'action/account_circle',
+          icon: Icons.account_circle,
           child: stopWrapping(
               new Text(appState.user.name, style: style.Text.titleStyle))),
       new DrawerItem(
-          icon: 'action/perm_device_information',
+          icon: Icons.devices,
           child: stopWrapping(new Text(appState.settings.deviceId,
               style: style.Text.titleStyle)))
     ]));
@@ -58,7 +60,7 @@
 }
 
 // DeckGrid is scrollable grid view of decks.
-class DeckGrid extends StatelessComponent {
+class DeckGrid extends StatelessWidget {
   AppActions _appActions;
   AppState _appState;
   List<model.Deck> _decks;
@@ -66,6 +68,7 @@
 
   DeckGrid(this._decks, this._presentations, this._appState, this._appActions);
 
+  @override
   Widget build(BuildContext context) {
     List<Widget> deckBoxes = _decks.map((deck) => _buildDeckBox(context, deck));
     List<Widget> presentationBoxes = _presentations
@@ -80,7 +83,7 @@
 
   Widget _buildDeckBox(BuildContext context, model.Deck deckData) {
     var thumbnail = new AsyncImage(
-        provider: imageProvider.getDeckThumbnailImage(deckData),
+        provider: image_provider.getDeckThumbnailImage(deckData),
         fit: ImageFit.scaleDown);
 
     var resumeLiveBox;
@@ -108,7 +111,7 @@
   Widget _buildPresentationBox(
       BuildContext context, model.PresentationAdvertisement presentationData) {
     var thumbnail = new AsyncImage(
-        provider: imageProvider.getDeckThumbnailImage(presentationData.deck),
+        provider: image_provider.getDeckThumbnailImage(presentationData.deck),
         fit: ImageFit.scaleDown);
     var liveBox = new Row(children: [
       new Container(
@@ -130,12 +133,10 @@
 
         Navigator.openTransaction(context, (NavigatorTransaction transaction) {
           // Push slides list page first before navigating to the slideshow.
-          transaction.push(new MaterialPageRoute(
-              builder: (context) =>
-                  new SlideListPage(presentationData.deck.key)));
-          transaction.push(new MaterialPageRoute(
-              builder: (context) =>
-                  new SlideshowPage(presentationData.deck.key)));
+          transaction.push(new MaterialPageRoute(builder: (context) =>
+              new SlideListPage(presentationData.deck.key)));
+          transaction.push(new MaterialPageRoute(builder: (context) =>
+              new SlideshowPage(presentationData.deck.key)));
         });
       } catch (e) {
         toast.error(_scaffoldKey,
@@ -168,9 +169,9 @@
             new Size.fromHeight(style.Size.boxFooterHeight)));
     footer = new Flexible(child: footer, flex: 0);
     var content = new Container(
-        child: new Card(
-            child: new Column(
-                children: [image, footer], alignItems: FlexAlignItems.stretch)),
+        child: new Card(child: new Column(
+            children: [image, footer],
+            crossAxisAlignment: CrossAxisAlignment.stretch)),
         margin: style.Spacing.normalMargin);
 
     return new InkWell(key: new Key(key), child: content, onTap: onTap);
diff --git a/dart/lib/components/questionlist.dart b/dart/lib/components/questionlist.dart
index 8182ffb..1159de6 100644
--- a/dart/lib/components/questionlist.dart
+++ b/dart/lib/components/questionlist.dart
@@ -8,7 +8,7 @@
 import '../models/all.dart' as model;
 import '../stores/store.dart';
 import '../styles/common.dart' as style;
-import '../utils/image_provider.dart' as imageProvider;
+import '../utils/image_provider.dart' as image_provider;
 import 'syncslides_page.dart';
 import 'toast.dart' as toast;
 
@@ -19,6 +19,7 @@
 
   QuestionListPage(this._deckId);
 
+  @override
   Widget build(BuildContext context, AppState appState, AppActions appActions) {
     if (!appState.decks.containsKey(_deckId)) {
       // TODO(aghassemi): Proper error page with navigation back to main view.
@@ -37,18 +38,17 @@
 
     return new Scaffold(
         key: _scaffoldKey,
-        toolBar: new ToolBar(
-            left: new IconButton(
-                icon: 'navigation/arrow_back',
+        appBar: new AppBar(
+            leading: new IconButton(
+                icon: Icons.arrow_back,
                 onPressed: () => Navigator.pop(context)),
-            center: new Text('Answer questions')),
-        body: new Material(
-            child: new QuestionList(_deckId, presentationState,
-                deckState.slides, appActions, appState)));
+            title: new Text('Answer questions')),
+        body: new Material(child: new QuestionList(_deckId, presentationState,
+            deckState.slides, appActions, appState)));
   }
 }
 
-class QuestionList extends StatelessComponent {
+class QuestionList extends StatelessWidget {
   String _deckId;
   PresentationState _presentationState;
   List<model.Slide> _slides;
@@ -57,6 +57,7 @@
   QuestionList(this._deckId, this._presentationState, this._slides,
       this._appActions, this._appState);
 
+  @override
   Widget build(BuildContext context) {
     List<Widget> questionCards = _presentationState.questions
         .map((model.Question q) => _buildQuestionCard(context, q))
@@ -71,10 +72,12 @@
 
     Widget jumpToSlide;
     if (_presentationState.isDriving(_appState.user)) {
-      jumpToSlide = new IconButton(icon: 'av/loop', onPressed: () async {
-        await _appActions.setCurrSlideNum(_deckId, q.slideNum);
-        toast.info(_scaffoldKey, 'Jumped to slide ${q.slideNum + 1}');
-      });
+      jumpToSlide = new IconButton(
+          icon: Icons.loop,
+          onPressed: () async {
+            await _appActions.setCurrSlideNum(_deckId, q.slideNum);
+            toast.info(_scaffoldKey, 'Jumped to slide ${q.slideNum + 1}');
+          });
       titleChildren.add(jumpToSlide);
     }
 
@@ -82,41 +85,40 @@
       new Text('${q.questioner.name} asked about',
           style: style.Text.subtitleStyle),
       new Row(children: titleChildren)
-    ], alignItems: FlexAlignItems.start);
+    ], crossAxisAlignment: CrossAxisAlignment.start);
 
-    Widget thumbnail = new Container(
-        child: new AsyncImage(
-            width: style.Size.questionListThumbnailWidth,
-            provider:
-                imageProvider.getSlideImage(_deckId, _slides[q.slideNum])));
+    Widget thumbnail = new Container(child: new AsyncImage(
+        width: style.Size.questionListThumbnailWidth,
+        provider: image_provider.getSlideImage(_deckId, _slides[q.slideNum])));
 
     Widget titleAndThumbnail = new Row(children: [
       new Flexible(child: title, flex: 2),
       new Flexible(child: thumbnail, flex: 1)
-    ], alignItems: FlexAlignItems.start);
+    ], crossAxisAlignment: CrossAxisAlignment.start);
 
     Widget question = new Container(
         child: new BlockBody(children: [titleAndThumbnail, new Text(q.text)]),
         padding: style.Spacing.normalPadding);
 
-    Widget handoff = new GestureDetector(onTap: () async {
-      await _appActions.setDriver(_deckId, q.questioner);
-      Navigator.pop(context);
-    }, child: new Container(child: new Text('HAND OFF')));
+    Widget handoff = new GestureDetector(
+        onTap: () async {
+          await _appActions.setDriver(_deckId, q.questioner);
+          Navigator.pop(context);
+        },
+        child: new Container(child: new Text('HAND OFF')));
 
     Widget actions = new Container(
         padding: style.Spacing.normalPadding,
-        decoration: new BoxDecoration(
-            border: new Border(
-                top: new BorderSide(color: style.theme.dividerColor))),
+        decoration: new BoxDecoration(border: new Border(
+            top: new BorderSide(color: style.theme.dividerColor))),
         child: new DefaultTextStyle(
             style: new TextStyle(color: style.theme.accentColor),
             child: new Row(
-                children: [handoff], justifyContent: FlexJustifyContent.end)));
+                children: [handoff],
+                mainAxisAlignment: MainAxisAlignment.end)));
 
-    return new Card(
-        child: new Container(
-            child: new BlockBody(children: [question, actions]),
-            margin: style.Spacing.listItemMargin));
+    return new Card(child: new Container(
+        child: new BlockBody(children: [question, actions]),
+        margin: style.Spacing.listItemMargin));
   }
 }
diff --git a/dart/lib/components/slidelist.dart b/dart/lib/components/slidelist.dart
index ac09153..514a5a1 100644
--- a/dart/lib/components/slidelist.dart
+++ b/dart/lib/components/slidelist.dart
@@ -7,7 +7,7 @@
 import '../models/all.dart' as model;
 import '../stores/store.dart';
 import '../styles/common.dart' as style;
-import '../utils/image_provider.dart' as imageProvider;
+import '../utils/image_provider.dart' as image_provider;
 import 'slideshow.dart';
 import 'syncslides_page.dart';
 import 'toast.dart' as toast;
@@ -19,6 +19,7 @@
 
   SlideListPage(this._deckId);
 
+  @override
   Widget build(BuildContext context, AppState appState, AppActions appActions) {
     if (!appState.decks.containsKey(_deckId)) {
       // TODO(aghassemi): Proper error page with navigation back to main view.
@@ -33,79 +34,86 @@
     }
     return new Scaffold(
         key: _scaffoldKey,
-        toolBar: new ToolBar(
-            left: new IconButton(
-                icon: 'navigation/arrow_back',
+        appBar: new AppBar(
+            leading: new IconButton(
+                icon: Icons.arrow_back,
                 onPressed: () => Navigator.pop(context)),
-            center: new Text(deckState.deck.name),
-            right: toolbarActions),
+            title: new Text(deckState.deck.name),
+            actions: toolbarActions),
         floatingActionButton: _buildFab(context, appState, appActions),
         body: new Material(child: new SlideList(_deckId, slides, appActions)));
   }
 
-  _buildDelete(BuildContext context, AppState appState, AppActions appActions) {
+  IconButton _buildDelete(
+      BuildContext context, AppState appState, AppActions appActions) {
     var deckState = appState.decks[_deckId];
     if (deckState.presentation != null) {
       // Can't delete while in a presentation.
       return null;
     }
 
-    return new IconButton(icon: 'action/delete', onPressed: () async {
-      await appActions.removeDeck(deckState.deck.key);
-      Navigator.pop(context);
-    });
+    return new IconButton(
+        icon: Icons.delete,
+        onPressed: () async {
+          await appActions.removeDeck(deckState.deck.key);
+          Navigator.pop(context);
+        });
   }
 
-  _buildFab(BuildContext context, AppState appState, AppActions appActions) {
+  FloatingActionButton _buildFab(
+      BuildContext context, AppState appState, AppActions appActions) {
     var deckState = appState.decks[_deckId];
 
     if (deckState.presentation == null) {
-      return new FloatingActionButton(child: new Icon(icon: 'av/play_arrow'),
+      return new FloatingActionButton(
+          child: new Icon(icon: Icons.play_arrow),
           onPressed: () async {
-        toast.info(_scaffoldKey, 'Starting presentation...',
-            duration: toast.Durations.permanent);
+            toast.info(_scaffoldKey, 'Starting presentation...',
+                duration: toast.Durations.permanent);
 
-        try {
-          await appActions.startPresentation(_deckId);
-          toast.info(_scaffoldKey, 'Presentation started.');
+            try {
+              await appActions.startPresentation(_deckId);
+              toast.info(_scaffoldKey, 'Presentation started.');
 
-          Navigator.push(
-              context,
-              new MaterialPageRoute(
-                  builder: (context) => new SlideshowPage(_deckId)));
-        } catch (e) {
-          toast.error(_scaffoldKey, 'Failed to start presentation.', e);
-        }
-      });
+              Navigator.push(
+                  context,
+                  new MaterialPageRoute(
+                      builder: (context) => new SlideshowPage(_deckId)));
+            } catch (e) {
+              toast.error(_scaffoldKey, 'Failed to start presentation.', e);
+            }
+          });
     }
 
     // Already presenting own deck, allow for stopping it.
     if (deckState.presentation != null && deckState.presentation.isOwner) {
       var key = deckState.presentation.key;
-      return new FloatingActionButton(child: new Icon(icon: 'av/stop'),
+      return new FloatingActionButton(
+          child: new Icon(icon: Icons.stop),
           onPressed: () async {
-        toast.info(_scaffoldKey, 'Stopping presentation...',
-            duration: toast.Durations.permanent);
+            toast.info(_scaffoldKey, 'Stopping presentation...',
+                duration: toast.Durations.permanent);
 
-        try {
-          await appActions.stopPresentation(key);
-          toast.info(_scaffoldKey, 'Presentation stopped.');
-        } catch (e) {
-          toast.error(_scaffoldKey, 'Failed to stop presentation.', e);
-        }
-      });
+            try {
+              await appActions.stopPresentation(key);
+              toast.info(_scaffoldKey, 'Presentation stopped.');
+            } catch (e) {
+              toast.error(_scaffoldKey, 'Failed to stop presentation.', e);
+            }
+          });
     }
 
     return null;
   }
 }
 
-class SlideList extends StatelessComponent {
+class SlideList extends StatelessWidget {
   String _deckId;
   List<model.Slide> _slides = new List<model.Slide>();
   AppActions _appActions;
   SlideList(this._deckId, this._slides, this._appActions);
 
+  @override
   Widget build(BuildContext context) {
     Iterable<Widget> items = _slides.map(
         (slide) => _buildSlide(context, _deckId, slide.num, slide, onTap: () {
@@ -126,7 +134,7 @@
     BuildContext context, String deckId, int slideIndex, model.Slide slideData,
     {Function onTap}) {
   var thumbnail = new AsyncImage(
-      provider: imageProvider.getSlideImage(deckId, slideData),
+      provider: image_provider.getSlideImage(deckId, slideData),
       fit: ImageFit.cover,
       width: style.Size.slideListThumbnailWidth);
 
@@ -136,11 +144,11 @@
       new Text('Slide ${slideIndex + 1}', style: style.Text.subtitleStyle);
   var notes = new Text(
       'This is the teaser slide. It should be memorable and descriptive.');
-  var titleAndNotes = new Flexible(
-      child: new Container(
-          child: new Column(
-              children: [title, notes], alignItems: FlexAlignItems.start),
-          padding: style.Spacing.normalPadding));
+  var titleAndNotes = new Flexible(child: new Container(
+      child: new Column(
+          children: [title, notes],
+          crossAxisAlignment: CrossAxisAlignment.start),
+      padding: style.Spacing.normalPadding));
 
   var card = new Container(
       child: new Container(
diff --git a/dart/lib/components/slideshow.dart b/dart/lib/components/slideshow.dart
index 76dc606..fb3cb64 100644
--- a/dart/lib/components/slideshow.dart
+++ b/dart/lib/components/slideshow.dart
@@ -7,7 +7,7 @@
 
 import '../stores/store.dart';
 import '../styles/common.dart' as style;
-import '../utils/image_provider.dart' as imageProvider;
+import '../utils/image_provider.dart' as image_provider;
 import 'askquestion.dart';
 import 'questionlist.dart';
 import 'slideshow_fullscreen.dart';
@@ -22,6 +22,7 @@
 
   SlideshowPage(this._deckId);
 
+  @override
   Widget build(BuildContext context, AppState appState, AppActions appActions) {
     if (!appState.decks.containsKey(_deckId)) {
       // TODO(aghassemi): Proper error page with navigation back to main view.
@@ -36,7 +37,7 @@
   }
 }
 
-class SlideShow extends StatelessComponent {
+class SlideShow extends StatelessWidget {
   AppActions _appActions;
   AppState _appState;
   DeckState _deckState;
@@ -44,6 +45,7 @@
 
   SlideShow(this._appActions, this._appState, this._deckState);
 
+  @override
   Widget build(BuildContext context) {
     if (_deckState.slides.length == 0) {
       // TODO(aghassemi): Proper error page with navigation back to main view.
@@ -92,8 +94,8 @@
       items.add(footer);
     }
 
-    var layout =
-        new Column(children: items, alignItems: FlexAlignItems.stretch);
+    var layout = new Column(
+        children: items, crossAxisAlignment: CrossAxisAlignment.stretch);
 
     return layout;
   }
@@ -108,22 +110,24 @@
 
     var notesAndNavColumn = new Flexible(
         child: new Column(
-            children: [notes, nav], alignItems: FlexAlignItems.stretch),
+            children: [notes, nav],
+            crossAxisAlignment: CrossAxisAlignment.stretch),
         flex: 4);
     var imageAndActionsColumn = new Flexible(
         child: new Column(
-            children: [image, actions], alignItems: FlexAlignItems.stretch),
+            children: [image, actions],
+            crossAxisAlignment: CrossAxisAlignment.stretch),
         flex: 16);
 
     var layout = new Row(
         children: [notesAndNavColumn, imageAndActionsColumn],
-        alignItems: FlexAlignItems.stretch);
+        crossAxisAlignment: CrossAxisAlignment.stretch);
 
     var footer = _buildFooter();
     if (footer != null) {
       layout = new Column(
           children: [new Flexible(child: layout, flex: 8), footer],
-          alignItems: FlexAlignItems.stretch);
+          crossAxisAlignment: CrossAxisAlignment.stretch);
     }
 
     return layout;
@@ -137,7 +141,7 @@
   }
 
   Widget _buildImage(BuildContext context) {
-    var provider = imageProvider.getSlideImage(
+    var provider = image_provider.getSlideImage(
         _deckState.deck.key, _deckState.slides[_currSlideNum]);
 
     var image = new AsyncImage(provider: provider, fit: ImageFit.scaleDown);
@@ -145,13 +149,14 @@
     // If not driving the presentation, tapping the image navigates to fullscreen mode.
     if (_deckState.presentation == null ||
         !_deckState.presentation.isDriving(_appState.user)) {
-      image = new InkWell(child: image, onTap: () {
-        Navigator.push(
-            context,
-            new MaterialPageRoute(
-                builder: (context) =>
+      image = new InkWell(
+          child: image,
+          onTap: () {
+            Navigator.push(
+                context,
+                new MaterialPageRoute(builder: (context) =>
                     new SlideshowFullscreenPage(_deckState.deck.key)));
-      });
+          });
     }
 
     var counter = _buildBubbleOverlay(
@@ -167,9 +172,8 @@
     var container = new Container(
         child: notes,
         padding: style.Spacing.normalPadding,
-        decoration: new BoxDecoration(
-            border: new Border(
-                bottom: new BorderSide(color: style.theme.dividerColor))));
+        decoration: new BoxDecoration(border: new Border(
+            bottom: new BorderSide(color: style.theme.dividerColor))));
     return container;
   }
 
@@ -178,19 +182,20 @@
 
     if (slideNum >= 0 && slideNum < _deckState.slides.length) {
       var thumbnail = new AsyncImage(
-          provider: imageProvider.getSlideImage(
+          provider: image_provider.getSlideImage(
               _deckState.deck.key, _deckState.slides[slideNum]),
           height: style.Size.thumbnailNavHeight,
           fit: ImageFit.scaleDown);
 
-      container = new InkWell(child: thumbnail, onTap: () {
-        _appActions.setCurrSlideNum(_deckState.deck.key, slideNum);
-      });
+      container = new InkWell(
+          child: thumbnail,
+          onTap: () {
+            _appActions.setCurrSlideNum(_deckState.deck.key, slideNum);
+          });
     } else {
       // Empty grey placeholder.
       container = new Container(
-          decoration: new BoxDecoration(
-              backgroundColor: style.theme.primarySwatch[100]));
+          decoration: new BoxDecoration(backgroundColor: Colors.grey[100]));
     }
 
     var nextPreviousBubble = _buildBubbleOverlay(label, 0.5, 0.05);
@@ -207,37 +212,40 @@
     List<Widget> left = [];
     List<Widget> right = [];
 
-    _buildActions_prev(left, right);
-    _buildActions_slidelist(left, right, context);
-    _buildActions_question(left, right, context);
-    _buildActions_next(left, right);
-    _buildActions_followPresentation(left, right);
+    _buildActionsPrev(left, right);
+    _buildActionsSlidelist(left, right, context);
+    _buildActionsQuestion(left, right, context);
+    _buildActionsNext(left, right);
+    _buildActionsFollowPresentation(left, right);
 
-    return new ToolBar(
-        left: new Row(children: _buildActions_addMargin(left)), right: right);
+    return new AppBar(
+        leading: new Row(children: _buildActionsAddMargin(left)),
+        actions: right);
   }
 
-  void _buildActions_prev(List<Widget> left, List<Widget> right) {
+  void _buildActionsPrev(List<Widget> left, List<Widget> right) {
     if (_currSlideNum == 0) {
       return;
     }
-    var prev =
-        new InkWell(child: new Icon(icon: 'navigation/arrow_back'), onTap: () {
-      _appActions.setCurrSlideNum(_deckState.deck.key, _currSlideNum - 1);
-    });
+    var prev = new InkWell(
+        child: new Icon(icon: Icons.arrow_back),
+        onTap: () {
+          _appActions.setCurrSlideNum(_deckState.deck.key, _currSlideNum - 1);
+        });
     left.add(prev);
   }
 
-  void _buildActions_slidelist(
+  void _buildActionsSlidelist(
       List<Widget> left, List<Widget> right, BuildContext context) {
-    var slideList =
-        new InkWell(child: new Icon(icon: 'maps/layers'), onTap: () {
-      Navigator.pop(context);
-    });
+    var slideList = new InkWell(
+        child: new Icon(icon: Icons.layers),
+        onTap: () {
+          Navigator.pop(context);
+        });
     left.add(slideList);
   }
 
-  void _buildActions_question(
+  void _buildActionsQuestion(
       List<Widget> left, List<Widget> right, BuildContext context) {
     if (_deckState.presentation == null) {
       return;
@@ -245,9 +253,9 @@
 
     // Presentation over is taken to a list of questions view.
     if (_deckState.presentation.isOwner) {
-      var numQuestions = new FloatingActionButton(
-          child: new Text(_deckState.presentation.questions.length.toString(),
-              style: style.theme.primaryTextTheme.title));
+      var numQuestions = new FloatingActionButton(child: new Text(
+          _deckState.presentation.questions.length.toString(),
+          style: style.theme.primaryTextTheme.title));
       // TODO(aghassemi): Find a better way. Scaling down a FAB and
       // using transform to position it does not seem to be the best approach.
       final Matrix4 moveUp = new Matrix4.identity().translate(-95.0, 25.0);
@@ -256,26 +264,26 @@
       numQuestions = new Transform(child: numQuestions, transform: scaleDown);
 
       var questions = new InkWell(
-          child: new Icon(icon: 'communication/live_help'), onTap: () {
-        Navigator.push(
-            context,
-            new MaterialPageRoute(
-                builder: (context) =>
+          child: new Icon(icon: Icons.help),
+          onTap: () {
+            Navigator.push(
+                context,
+                new MaterialPageRoute(builder: (context) =>
                     new QuestionListPage(_deckState.deck.key)));
-      });
+          });
 
       left.add(questions);
       left.add(numQuestions);
     } else {
       // Audience is taken to ask a question view.
-      var route = new MaterialPageRoute(
-          builder: (context) =>
-              new AskQuestionPage(_deckState.deck.key, _currSlideNum));
+      var route = new MaterialPageRoute(builder: (context) =>
+          new AskQuestionPage(_deckState.deck.key, _currSlideNum));
 
       var askQuestion = new InkWell(
-          child: new Icon(icon: 'communication/live_help'), onTap: () {
-        Navigator.push(context, route);
-      });
+          child: new Icon(icon: Icons.help),
+          onTap: () {
+            Navigator.push(context, route);
+          });
       left.add(askQuestion);
     }
   }
@@ -283,7 +291,7 @@
   final Matrix4 moveUpFabTransform =
       new Matrix4.identity().translate(0.0, -27.5);
 
-  void _buildActions_next(List<Widget> left, List<Widget> right) {
+  void _buildActionsNext(List<Widget> left, List<Widget> right) {
     if (_currSlideNum >= (_deckState.slides.length - 1)) {
       return;
     }
@@ -297,8 +305,7 @@
     if (_deckState.presentation != null &&
         _deckState.presentation.isDriving(_appState.user)) {
       var next = new FloatingActionButton(
-          child: new Icon(icon: 'navigation/arrow_forward'),
-          onPressed: nextOnTap);
+          child: new Icon(icon: Icons.arrow_forward), onPressed: nextOnTap);
 
       var container =
           new Container(child: next, margin: style.Spacing.fabMargin);
@@ -307,21 +314,22 @@
       right.add(next);
     } else {
       var next = new InkWell(
-          child: new Icon(icon: 'navigation/arrow_forward'), onTap: nextOnTap);
+          child: new Icon(icon: Icons.arrow_forward), onTap: nextOnTap);
       left.add(next);
     }
   }
 
-  void _buildActions_followPresentation(List<Widget> left, List<Widget> right) {
+  void _buildActionsFollowPresentation(List<Widget> left, List<Widget> right) {
     if (_deckState.presentation == null ||
         _deckState.presentation.isFollowingPresentation) {
       return;
     }
 
     var syncNav = new FloatingActionButton(
-        child: new Icon(icon: 'notification/sync'), onPressed: () async {
-      _appActions.followPresentation(_deckState.deck.key);
-    });
+        child: new Icon(icon: Icons.sync),
+        onPressed: () async {
+          _appActions.followPresentation(_deckState.deck.key);
+        });
 
     syncNav =
         new Container(child: syncNav, margin: style.Spacing.actionsMargin);
@@ -338,10 +346,11 @@
     // Owner and not driving?
     if (_deckState.presentation.isOwner &&
         !_deckState.presentation.isDriving(_appState.user)) {
-      SnackBarAction resume =
-          new SnackBarAction(label: 'RESUME', onPressed: () {
-        _appActions.setDriver(_deckState.deck.key, _appState.user);
-      });
+      SnackBarAction resume = new SnackBarAction(
+          label: 'RESUME',
+          onPressed: () {
+            _appActions.setDriver(_deckState.deck.key, _appState.user);
+          });
 
       return _buildSnackbarFooter('You have handed off control.',
           action: resume);
@@ -356,7 +365,7 @@
     return null;
   }
 
-  _buildActions_addMargin(List<Widget> actions) {
+  List<Widget> _buildActionsAddMargin(List<Widget> actions) {
     return actions
         .map(
             (w) => new Container(child: w, margin: style.Spacing.actionsMargin))
@@ -372,34 +381,32 @@
                 borderRadius: 50.0, // Make the bubble round.
                 backgroundColor:
                     style.Box.bubbleOverlayBackground), // Transparent gray.
-            padding: new EdgeDims.symmetric(horizontal: 5.0, vertical: 2.0)),
+            padding: new EdgeInsets.symmetric(horizontal: 5.0, vertical: 2.0)),
         alignment: new FractionalOffset(xOffset, yOffset));
   }
 
-  _buildSnackbarFooter(String lable, {SnackBarAction action}) {
+  Widget _buildSnackbarFooter(String lable, {SnackBarAction action}) {
     var text = new Text(lable);
     text = new DefaultTextStyle(style: Typography.white.subhead, child: text);
     List<Widget> children = <Widget>[
-      new Flexible(
-          child: new Container(
-              margin: style.Spacing.footerVerticalMargin,
-              child: new DefaultTextStyle(
-                  style: Typography.white.subhead, child: text)))
+      new Flexible(child: new Container(
+          margin: style.Spacing.footerVerticalMargin,
+          child: new DefaultTextStyle(
+              style: Typography.white.subhead, child: text)))
     ];
 
     if (action != null) {
       children.add(action);
     }
 
-    var clipper = new ClipRect(
-        child: new Material(
-            elevation: 6,
-            color: style.Box.footerBackground,
-            child: new Container(
-                margin: style.Spacing.footerHorizontalMargin,
-                child: new DefaultTextStyle(
-                    style: new TextStyle(color: style.theme.accentColor),
-                    child: new Row(children: children)))));
+    var clipper = new ClipRect(child: new Material(
+        elevation: 6,
+        color: style.Box.footerBackground,
+        child: new Container(
+            margin: style.Spacing.footerHorizontalMargin,
+            child: new DefaultTextStyle(
+                style: new TextStyle(color: style.theme.accentColor),
+                child: new Row(children: children)))));
 
     return new Flexible(child: clipper, flex: 1);
   }
diff --git a/dart/lib/components/slideshow_fullscreen.dart b/dart/lib/components/slideshow_fullscreen.dart
index 009592c..c48ee2c 100644
--- a/dart/lib/components/slideshow_fullscreen.dart
+++ b/dart/lib/components/slideshow_fullscreen.dart
@@ -6,7 +6,7 @@
 import 'package:flutter/widgets.dart';
 
 import '../stores/store.dart';
-import '../utils/image_provider.dart' as imageProvider;
+import '../utils/image_provider.dart' as image_provider;
 import 'slideshow.dart';
 
 class SlideshowFullscreenPage extends SlideshowPage {
@@ -28,7 +28,7 @@
     } else {
       currSlideNum = deckState.currSlideNum;
     }
-    var provider = imageProvider.getSlideImage(
+    var provider = image_provider.getSlideImage(
         deckState.deck.key, deckState.slides[currSlideNum]);
     return new GestureDetector(
         child: new AsyncImage(provider: provider, fit: ImageFit.contain),
diff --git a/dart/lib/components/syncslides_page.dart b/dart/lib/components/syncslides_page.dart
index c6c3a25..a9d6c0b 100644
--- a/dart/lib/components/syncslides_page.dart
+++ b/dart/lib/components/syncslides_page.dart
@@ -14,10 +14,12 @@
 // The base class for every page.
 // Responsible for watching state changes from the store and passing
 // the state and actions to the build function of descendant components.
-abstract class SyncSlidesPage extends StatefulComponent {
-  build(BuildContext context, AppState appState, AppActions appActions);
-  initState(AppState appState, AppActions appActions) {}
+abstract class SyncSlidesPage extends StatefulWidget {
+  Widget build(BuildContext context, AppState appState, AppActions appActions);
 
+  void initState(AppState appState, AppActions appActions) {}
+
+  @override
   _SyncSlidesPage createState() => new _SyncSlidesPage();
 }
 
@@ -44,6 +46,7 @@
     super.dispose();
   }
 
+  @override
   Widget build(BuildContext context) {
     return config.build(context, _state, _store.actions);
   }
diff --git a/dart/lib/components/utils/stop_wrapping.dart b/dart/lib/components/utils/stop_wrapping.dart
index 68d0e4b..bbe8e86 100644
--- a/dart/lib/components/utils/stop_wrapping.dart
+++ b/dart/lib/components/utils/stop_wrapping.dart
@@ -9,5 +9,5 @@
   // overflow: hidden or text-overflow: ellipsis in Flutter yet.
   // This workaround simulates white-space: nowrap and overflow: hidden.
   // See https://github.com/flutter/flutter/issues/417
-  return new Viewport(child: child, scrollDirection: Axis.horizontal);
+  return new Viewport(child: child, mainAxis: Axis.horizontal);
 }
diff --git a/dart/lib/discovery/client.dart b/dart/lib/discovery/client.dart
index cf3d7dc..0f84a39 100644
--- a/dart/lib/discovery/client.dart
+++ b/dart/lib/discovery/client.dart
@@ -4,11 +4,11 @@
 
 import 'dart:async';
 
-import 'package:flutter/services.dart' show shell;
+import 'package:flutter/shell.dart' show shell;
 import 'package:logging/logging.dart';
 import 'package:v23discovery/discovery.dart' as discovery;
 
-export 'package:v23discovery/discovery.dart' show UpdateType;
+export 'package:v23discovery/discovery.dart' show UpdateTypes;
 
 import '../models/all.dart' as model;
 
@@ -26,7 +26,7 @@
     new discovery.Client(shell.connectToService, _discoveryMojoUrl);
 
 final Map<String, discovery.Advertiser> _advertisers = new Map();
-discovery.Scanner _scanner = null;
+discovery.Scanner _scanner;
 
 Future advertise(model.PresentationAdvertisement presentation) async {
   if (_advertisers.containsKey(presentation.key)) {
@@ -40,11 +40,8 @@
   serviceAttrs['name'] = presentation.deck.name;
   serviceAttrs['thumbnailkey'] = presentation.deck.thumbnail.key;
   serviceAttrs['presentationid'] = presentation.key;
-  discovery.Service service = new discovery.Service()
-    ..interfaceName = _presentationInterfaceName
-    ..instanceName = presentation.key
-    ..attrs = serviceAttrs
-    ..addrs = [presentation.syncgroupName, presentation.thumbnailSyncgroupName];
+  discovery.Advertisement service = new discovery.Advertisement('s/v', []);
+  ..attributes = serviceAttrs;
 
   _advertisers[presentation.key] = await _discoveryClient.advertise(service);
 
@@ -63,20 +60,19 @@
 // Transforms a stream of discovery services to PresentationAdvertisement model objects.
 StreamTransformer toPresentationUpdate = new StreamTransformer.fromHandlers(
     handleData: (discovery.Update u, EventSink<PresentationUpdate> sink) {
-  discovery.Service s = u.service;
-
-  String key = s.attrs['presentationid'];
-  log.info('Found presentation ${s.attrs['name']} under $key.');
+  String key = u.attributes['presentationid'];
+  log.info('Found presentation ${u.attributes['name']} under $key.');
   // Ignore our own advertised services.
   if (_advertisers.containsKey(key)) {
-    log.info('Presentation ${s.attrs['name']} was advertised by us; ignoring.');
+    log.info(
+        'Presentation ${u.attributes['name']} was advertised by us; ignoring.');
     return;
   }
 
-  model.Deck deck = new model.Deck(s.attrs['deckid'], s.attrs['name'],
-      new model.BlobRef(s.attrs['thumbnailkey']));
-  var syncgroupName = s.addrs[0];
-  var thumbnailSyncgroupName = s.addrs[1];
+  model.Deck deck = new model.Deck(u.attributes['deckid'], u.attributes['name'],
+      new model.BlobRef(u.attributes['thumbnailkey']));
+  var syncgroupName = u.addresses[0];
+  var thumbnailSyncgroupName = u.addresses[1];
   model.PresentationAdvertisement presentation =
       new model.PresentationAdvertisement(
           key, deck, syncgroupName, thumbnailSyncgroupName);
@@ -105,7 +101,7 @@
 
 class PresentationUpdate {
   model.PresentationAdvertisement presentation;
-  discovery.UpdateType updateType;
+  discovery.UpdateTypes updateType;
   PresentationUpdate._internal(this.presentation, this.updateType);
 }
 
diff --git a/dart/lib/identity/client.dart b/dart/lib/identity/client.dart
index 91de45b..5146b36 100644
--- a/dart/lib/identity/client.dart
+++ b/dart/lib/identity/client.dart
@@ -4,7 +4,7 @@
 
 import 'dart:async';
 
-import 'package:flutter/services.dart' show shell;
+import 'package:flutter/shell.dart' show shell;
 import 'package:logging/logging.dart';
 import 'package:mojo_services/authentication/authentication.mojom.dart' as auth;
 
diff --git a/dart/lib/loaders/loader.dart b/dart/lib/loaders/loader.dart
index 4d6a58e..ef584a6 100644
--- a/dart/lib/loaders/loader.dart
+++ b/dart/lib/loaders/loader.dart
@@ -27,7 +27,7 @@
     return _singletonLoader;
   }
 
-  Loader._internal() {}
+  Loader._internal();
 
   // Loads all the decks in /sdcard/syncslides/decks
   // Name of each deck is the name of its directory.
diff --git a/dart/lib/main.dart b/dart/lib/main.dart
index dc642a7..ac0f96e 100644
--- a/dart/lib/main.dart
+++ b/dart/lib/main.dart
@@ -9,8 +9,8 @@
 import 'components/deckgrid.dart';
 import 'stores/store.dart';
 import 'styles/common.dart' as style;
-import 'utils/back_button.dart' as backButtonUtil;
-import 'utils/image_provider.dart' as imageProvider;
+import 'utils/back_button.dart' as back_button_util;
+import 'utils/image_provider.dart' as image_provider;
 
 NavigatorState _navigator;
 final Completer storeStatus = new Completer();
@@ -21,15 +21,18 @@
     storeStatus.complete();
   });
   _initLogging();
-  _initBackButtonHandler();
+  // TODO(aghassemi): Fix back button integration. It has been broken throwing
+  // "Only one back button handler can exist per app"
+  //_initBackButtonHandler();
 
   runApp(new MaterialApp(
       theme: style.theme,
       title: 'SyncSlides',
-      routes: {'/': (RouteArguments args) => new LandingPage()}));
+      routes: {'/': (BuildContext context) => new LandingPage()}));
 }
 
-class LandingPage extends StatefulComponent {
+class LandingPage extends StatefulWidget {
+  @override
   _LandingPage createState() => new _LandingPage();
 }
 
@@ -49,6 +52,7 @@
     }
   }
 
+  @override
   Widget build(BuildContext context) {
     if (!_initialized) {
       return _buildSplashScreen();
@@ -61,22 +65,23 @@
   Widget _buildSplashScreen() {
     var stack = new Stack(children: [
       new AsyncImage(
-          provider: imageProvider.splashBackgroundImageProvider,
+          provider: image_provider.splashBackgroundImageProvider,
           fit: ImageFit.cover),
       new Row(children: [
         new AsyncImage(
-            provider: imageProvider.splashFlutterImageProvider,
+            provider: image_provider.splashFlutterImageProvider,
             width: style.Size.splashLogo),
         new AsyncImage(
-            provider: imageProvider.splashVanadiumImageProvider,
+            provider: image_provider.splashVanadiumImageProvider,
             width: style.Size.splashLogo)
-      ], justifyContent: FlexJustifyContent.center),
+      ], mainAxisAlignment: MainAxisAlignment.center),
       new Container(
           child: new Row(
-              children:
-                  [new Text('Loading SyncSlides...', style: style.Text.splash)],
-              alignItems: FlexAlignItems.end,
-              justifyContent: FlexJustifyContent.center),
+              children: [
+                new Text('Loading SyncSlides...', style: style.Text.splash)
+              ],
+              crossAxisAlignment: CrossAxisAlignment.end,
+              mainAxisAlignment: MainAxisAlignment.center),
           padding: style.Spacing.normalPadding)
     ]);
     return stack;
@@ -91,7 +96,7 @@
 }
 
 void _initBackButtonHandler() {
-  backButtonUtil.onBackButton(() {
+  back_button_util.onBackButton(() {
     if (_navigator != null && _navigator.canPop()) {
       bool returnValue;
       _navigator.openTransaction((NavigatorTransaction transaction) {
diff --git a/dart/lib/models/blobref.dart b/dart/lib/models/blobref.dart
index bf89028..46855b3 100644
--- a/dart/lib/models/blobref.dart
+++ b/dart/lib/models/blobref.dart
@@ -11,20 +11,19 @@
 const Duration interval = const Duration(milliseconds: 100);
 
 class BlobRef {
+  BlobRef(this._key);
   String _key;
   String get key => _key;
 
-  BlobRef(this._key);
-
   Future<List<int>> getData() {
     var store = new Store.singleton();
     int numTries = 0;
 
-    getBlobFromStore() async {
+    Future<List<int>> getBlobFromStore() async {
       return store.actions.getBlob(key);
     }
 
-    getBlobWithRetries() async {
+    Future<List<int>> getBlobWithRetries() async {
       // Don't fail immediately if blob is not found in store, it might be still syncing.
       try {
         numTries++;
diff --git a/dart/lib/models/deck.dart b/dart/lib/models/deck.dart
index 861d186..56ed325 100644
--- a/dart/lib/models/deck.dart
+++ b/dart/lib/models/deck.dart
@@ -8,6 +8,15 @@
 
 // Deck represents a deck of slides.
 class Deck {
+  Deck(this._key, this._name, this._thumbnail);
+
+  Deck.fromJson(String key, String json) {
+    Map map = JSON.decode(json);
+    _key = key;
+    _name = map['name'];
+    _thumbnail = new BlobRef(map['thumbnailkey']);
+  }
+
   String _key;
   String get key => _key;
 
@@ -17,15 +26,6 @@
   BlobRef _thumbnail;
   BlobRef get thumbnail => _thumbnail;
 
-  Deck(this._key, this._name, this._thumbnail) {}
-
-  Deck.fromJson(String key, String json) {
-    Map map = JSON.decode(json);
-    _key = key;
-    _name = map['name'];
-    _thumbnail = new BlobRef(map['thumbnailkey']);
-  }
-
   String toJson() {
     // NOTE(aghassemi): We never serialize the key with the object.
     Map map = new Map();
diff --git a/dart/lib/models/presentation_advertisement.dart b/dart/lib/models/presentation_advertisement.dart
index 925fc8a..ece1ae8 100644
--- a/dart/lib/models/presentation_advertisement.dart
+++ b/dart/lib/models/presentation_advertisement.dart
@@ -6,6 +6,9 @@
 
 // Represents an advertised presentation of a deck.
 class PresentationAdvertisement {
+  PresentationAdvertisement(
+      this._key, this._deck, this._syncgroupName, this._thumbnailSyncgroupName);
+
   // TODO(aghassemi): Fix inconsistencies between key and id everywhere.
   String _key;
   String get key => _key;
@@ -18,7 +21,4 @@
 
   String _thumbnailSyncgroupName;
   String get thumbnailSyncgroupName => _thumbnailSyncgroupName;
-
-  PresentationAdvertisement(
-      this._key, this._deck, this._syncgroupName, this._thumbnailSyncgroupName);
 }
diff --git a/dart/lib/models/question.dart b/dart/lib/models/question.dart
index cc7fd73..57c031f 100644
--- a/dart/lib/models/question.dart
+++ b/dart/lib/models/question.dart
@@ -7,6 +7,18 @@
 import 'user.dart';
 
 class Question {
+  Question(
+      this._id, this._text, this._slideNum, this._questioner, this._timestamp);
+
+  Question.fromJson(String id, String json) {
+    Map map = JSON.decode(json);
+    _id = id;
+    _text = map['text'];
+    _slideNum = map['slidenum'];
+    _questioner = new User.fromJson(map['questioner']);
+    _timestamp = new DateTime.fromMillisecondsSinceEpoch(map['timestamp']);
+  }
+
   // TODO(aghassemi): Fix inconsistencies between key and id everywhere.
   String _id;
   String get id => _id;
@@ -23,18 +35,6 @@
   DateTime _timestamp;
   DateTime get timestamp => _timestamp;
 
-  Question(
-      this._id, this._text, this._slideNum, this._questioner, this._timestamp);
-
-  Question.fromJson(String id, String json) {
-    Map map = JSON.decode(json);
-    _id = id;
-    _text = map['text'];
-    _slideNum = map['slidenum'];
-    _questioner = new User.fromJson(map['questioner']);
-    _timestamp = new DateTime.fromMillisecondsSinceEpoch(map['timestamp']);
-  }
-
   String toJson() {
     Map map = new Map();
     map['text'] = text;
diff --git a/dart/lib/models/settings.dart b/dart/lib/models/settings.dart
index cfb1638..09537ba 100644
--- a/dart/lib/models/settings.dart
+++ b/dart/lib/models/settings.dart
@@ -5,12 +5,6 @@
 import 'dart:convert';
 
 class Settings {
-  String _deviceId;
-  String get deviceId => _deviceId;
-
-  String _mounttable;
-  String get mounttable => _mounttable;
-
   Settings(this._deviceId, this._mounttable);
 
   Settings.fromJson(String json) {
@@ -18,6 +12,11 @@
     _deviceId = map['deviceid'];
     _mounttable = map['mounttable'];
   }
+  String _deviceId;
+  String get deviceId => _deviceId;
+
+  String _mounttable;
+  String get mounttable => _mounttable;
 
   String toJson() {
     Map map = new Map();
diff --git a/dart/lib/models/slide.dart b/dart/lib/models/slide.dart
index 7694ddd..72abb17 100644
--- a/dart/lib/models/slide.dart
+++ b/dart/lib/models/slide.dart
@@ -8,13 +8,7 @@
 
 // Slide represents a slide within a deck.
 class Slide {
-  int _num;
-  int get num => _num;
-
-  BlobRef _image;
-  BlobRef get image => _image;
-
-  Slide(this._num, this._image) {}
+  Slide(this._num, this._image);
 
   Slide.fromJson(String json) {
     Map map = JSON.decode(json);
@@ -22,6 +16,12 @@
     _image = new BlobRef(map['imagekey']);
   }
 
+  int _num;
+  int get num => _num;
+
+  BlobRef _image;
+  BlobRef get image => _image;
+
   String toJson() {
     Map map = new Map();
     map['num'] = _num;
diff --git a/dart/lib/models/user.dart b/dart/lib/models/user.dart
index 15e9607..c153da1 100644
--- a/dart/lib/models/user.dart
+++ b/dart/lib/models/user.dart
@@ -5,15 +5,6 @@
 import 'dart:convert';
 
 class User {
-  String _name;
-  String get name => _name;
-
-  String _blessing;
-  String get blessing => _blessing;
-
-  String _deviceId;
-  String get deviceId => _deviceId;
-
   User(this._name, this._blessing, this._deviceId);
 
   User.fromJson(String json) {
@@ -23,6 +14,15 @@
     _deviceId = map['deviceid'];
   }
 
+  String _name;
+  String get name => _name;
+
+  String _blessing;
+  String get blessing => _blessing;
+
+  String _deviceId;
+  String get deviceId => _deviceId;
+
   String toJson() {
     Map map = new Map();
     map['name'] = name;
diff --git a/dart/lib/stores/syncbase/actions.dart b/dart/lib/stores/syncbase/actions.dart
index a266586..b56531a 100644
--- a/dart/lib/stores/syncbase/actions.dart
+++ b/dart/lib/stores/syncbase/actions.dart
@@ -12,6 +12,7 @@
   //////////////////////////////////////
   // Decks
 
+  @override
   Future addDeck(model.Deck deck) async {
     log.info("Adding deck ${deck.name}...");
     sb.SyncbaseTable tb = _getDecksTable();
@@ -19,11 +20,13 @@
     log.info("Deck ${deck.name} added.");
   }
 
+  @override
   Future removeDeck(String deckKey) async {
     sb.SyncbaseTable tb = _getDecksTable();
     tb.deleteRange(new sb.RowRange.prefix(deckKey));
   }
 
+  @override
   Future setSlides(String deckKey, List<model.Slide> slides) async {
     sb.SyncbaseTable tb = _getDecksTable();
 
@@ -34,6 +37,7 @@
     });
   }
 
+  @override
   Future setCurrSlideNum(String deckId, int slideNum) async {
     var deckState = _state._getOrCreateDeckState(deckId);
     if (slideNum < 0 || slideNum >= deckState.slides.length) {
@@ -64,6 +68,7 @@
     _emitChange();
   }
 
+  @override
   Future loadDeckFromSdCard() {
     return new Loader.singleton().loadDeck();
   }
@@ -71,6 +76,7 @@
   //////////////////////////////////////
   // Presentation
 
+  @override
   Future<model.PresentationAdvertisement> startPresentation(
       String deckId) async {
     if (!_state._decks.containsKey(deckId)) {
@@ -116,7 +122,7 @@
         deckState._getOrCreatePresentationState(presentation.key);
     presentationstate._isOwner = true;
 
-    setDefaultsAndJoin() async {
+    Future setDefaultsAndJoin() async {
       // Set the current slide number to 0.
       sb.SyncbaseTable tb = _getPresentationsTable();
       await tb.put(
@@ -141,6 +147,7 @@
     return presentation;
   }
 
+  @override
   Future joinPresentation(model.PresentationAdvertisement presentation) async {
     String deckId = presentation.deck.key;
 
@@ -151,7 +158,7 @@
     deckState._isPresenting = true;
 
     // Wait until at least the current slide number, driver and the slide for current slide number is synced.
-    join() async {
+    Future join() async {
       bool isMyOwnPresentation =
           _state._advertisedPresentation?.key == presentation.key;
       if (!isMyOwnPresentation) {
@@ -185,6 +192,7 @@
     log.info('Joined presentation ${presentation.key}');
   }
 
+  @override
   Future stopPresentation(String presentationId) async {
     await discovery.stopAdvertising(presentationId);
     _state._advertisedPresentation = null;
@@ -198,6 +206,7 @@
     log.info('Presentation $presentationId stopped');
   }
 
+  @override
   Future followPresentation(String deckId) async {
     var deckState = _state._getOrCreateDeckState(deckId);
 
@@ -211,6 +220,7 @@
     deckState.presentation._isFollowingPresentation = true;
   }
 
+  @override
   Future askQuestion(String deckId, int slideNum, String questionText) async {
     var deckState = _state._getOrCreateDeckState(deckId);
 
@@ -231,6 +241,7 @@
     await tb.put(key, UTF8.encode(question.toJson()));
   }
 
+  @override
   Future setDriver(String deckId, model.User driver) async {
     var deckState = _state._getOrCreateDeckState(deckId);
 
@@ -244,11 +255,13 @@
   //////////////////////////////////////
   // Blobs
 
+  @override
   Future putBlob(String key, List<int> bytes) async {
     sb.SyncbaseTable tb = _getBlobsTable();
     await tb.put(key, bytes);
   }
 
+  @override
   Future<List<int>> getBlob(String key) async {
     sb.SyncbaseTable tb = _getBlobsTable();
     return tb.get(key);
diff --git a/dart/lib/stores/syncbase/state.dart b/dart/lib/stores/syncbase/state.dart
index b943899..78c4abf 100644
--- a/dart/lib/stores/syncbase/state.dart
+++ b/dart/lib/stores/syncbase/state.dart
@@ -5,14 +5,6 @@
 part of syncbase_store;
 
 class _AppState extends AppState {
-  model.User get user => _user;
-  model.Settings get settings => _settings;
-  UnmodifiableMapView<String, DeckState> decks;
-  model.PresentationAdvertisement get advertisedPresentation =>
-      _advertisedPresentation;
-  UnmodifiableMapView<String,
-      model.PresentationAdvertisement> presentationAdvertisements;
-
   _AppState() {
     _user = null;
     _settings = null;
@@ -21,6 +13,22 @@
         new UnmodifiableMapView(_presentationsAdvertisements);
   }
 
+  @override
+  model.User get user => _user;
+  @override
+  model.Settings get settings => _settings;
+
+  @override
+  UnmodifiableMapView<String, DeckState> decks;
+
+  @override
+  model.PresentationAdvertisement get advertisedPresentation =>
+      _advertisedPresentation;
+
+  @override
+  UnmodifiableMapView<String, model.PresentationAdvertisement>
+      presentationAdvertisements;
+
   model.User _user;
   model.Settings _settings;
   Map<String, _DeckState> _decks = new Map();
@@ -36,13 +44,20 @@
 }
 
 class _DeckState extends DeckState {
+  _DeckState() {
+    slides = new UnmodifiableListView(_slides);
+  }
+
   model.Deck _deck;
+  @override
   model.Deck get deck => _deck;
 
   List<model.Slide> _slides = new List();
+  @override
   UnmodifiableListView<model.Slide> slides;
 
-  _PresentationState _presentation = null;
+  _PresentationState _presentation;
+  @override
   PresentationState get presentation {
     if (_isPresenting) {
       return _presentation;
@@ -51,14 +66,11 @@
   }
 
   int _currSlideNum = 0;
+  @override
   int get currSlideNum => _currSlideNum;
 
   bool _isPresenting = false;
 
-  _DeckState() {
-    slides = new UnmodifiableListView(_slides);
-  }
-
   _PresentationState _getOrCreatePresentationState(String presentationId) {
     if (_presentation == null || _presentation.key != presentationId) {
       _presentation = new _PresentationState(presentationId);
@@ -68,24 +80,30 @@
 }
 
 class _PresentationState extends PresentationState {
-  final String key;
-
-  int _currSlideNum = 0;
-  int get currSlideNum => _currSlideNum;
-
-  model.User _driver;
-  model.User get driver => _driver;
-
-  bool _isOwner = false;
-  bool get isOwner => _isOwner;
-
-  bool _isFollowingPresentation = true;
-  bool get isFollowingPresentation => _isFollowingPresentation;
-
-  List<model.Question> _questions = new List();
-  UnmodifiableListView<model.Question> questions;
-
   _PresentationState(this.key) {
     questions = new UnmodifiableListView(_questions);
   }
+
+  @override
+  final String key;
+
+  int _currSlideNum = 0;
+  @override
+  int get currSlideNum => _currSlideNum;
+
+  model.User _driver;
+  @override
+  model.User get driver => _driver;
+
+  bool _isOwner = false;
+  @override
+  bool get isOwner => _isOwner;
+
+  bool _isFollowingPresentation = true;
+  @override
+  bool get isFollowingPresentation => _isFollowingPresentation;
+
+  List<model.Question> _questions = new List();
+  @override
+  UnmodifiableListView<model.Question> questions;
 }
diff --git a/dart/lib/stores/syncbase/store.dart b/dart/lib/stores/syncbase/store.dart
index 7825e5b..4f73f3b 100644
--- a/dart/lib/stores/syncbase/store.dart
+++ b/dart/lib/stores/syncbase/store.dart
@@ -27,19 +27,25 @@
 
 // Implementation of Store using Syncbase (http://v.io/syncbase) storage system.
 class SyncbaseStore implements Store {
-  _AppState _state;
-  _AppActions _actions;
-  StreamController _stateChangeEmitter = new StreamController.broadcast();
-
-  AppState get state => _state;
-  Stream get onStateChange => _stateChangeEmitter.stream;
-  AppActions get actions => _actions;
-
   SyncbaseStore() {
     _state = new _AppState();
     _actions = new _AppActions(_state, _triggerStateChange);
   }
 
+  _AppState _state;
+  _AppActions _actions;
+  StreamController _stateChangeEmitter = new StreamController.broadcast();
+
+  @override
+  AppState get state => _state;
+
+  @override
+  Stream get onStateChange => _stateChangeEmitter.stream;
+
+  @override
+  AppActions get actions => _actions;
+
+  @override
   Future init() async {
     // Wait for synchronous initializers.
     await _syncInits();
@@ -79,7 +85,7 @@
     discovery.PresentationScanner scanner = await discovery.scan();
 
     scanner.onUpdate.listen((discovery.PresentationUpdate update) {
-      if (update.updateType == discovery.UpdateType.found) {
+      if (update.updateType == discovery.UpdateTypes.found) {
         _state._presentationsAdvertisements[update.presentation.key] =
             update.presentation;
         _triggerStateChange();
@@ -89,7 +95,7 @@
         // Join the thumbnail syncgroup to get the thumbnail blob.
         String sgName = update.presentation.thumbnailSyncgroupName;
         sb.joinSyncgroup(sgName);
-      } else if (update.updateType == discovery.UpdateType.lost) {
+      } else if (update.updateType == discovery.UpdateTypes.lost) {
         String presentationId = update.presentation.key;
         _state._presentationsAdvertisements.remove(presentationId);
         _state._decks.values.forEach((_DeckState deck) {
@@ -129,7 +135,7 @@
         _onChange(table, change.changeType, change.rowKey, change.valueBytes));
   }
 
-  _onChange(String table, int changeType, String rowKey, List<int> value) {
+  void _onChange(String table, int changeType, String rowKey, List<int> value) {
     log.finest('Change in $table for $rowKey of the type $changeType.');
 
     keyutil.KeyType keyType = keyutil.getKeyType(rowKey);
@@ -155,7 +161,7 @@
     _triggerStateChange();
   }
 
-  _onDeckChange(int changeType, String rowKey, List<int> value) {
+  void _onDeckChange(int changeType, String rowKey, List<int> value) {
     var deckId = rowKey;
     if (changeType == sb.WatchChangeTypes.put) {
       _state._getOrCreateDeckState(deckId)._deck =
@@ -165,7 +171,7 @@
     }
   }
 
-  _onSlideChange(int changeType, String rowKey, List<int> value) {
+  void _onSlideChange(int changeType, String rowKey, List<int> value) {
     var deckId = keyutil.currSlideKeyToDeckId(rowKey);
     var index = keyutil.currSlideKeyToIndex(rowKey);
     var slides = _state._getOrCreateDeckState(deckId)._slides;
@@ -182,7 +188,7 @@
     });
   }
 
-  _onPresentationSlideNumChange(
+  void _onPresentationSlideNumChange(
       int changeType, String rowKey, List<int> value) {
     String deckId = keyutil.presentationCurrSlideNumKeyToDeckId(rowKey);
     String presentationId =
@@ -200,7 +206,8 @@
     }
   }
 
-  _onPresentationDriverChange(int changeType, String rowKey, List<int> value) {
+  void _onPresentationDriverChange(
+      int changeType, String rowKey, List<int> value) {
     String deckId = keyutil.presentationDriverKeyToDeckId(rowKey);
     String presentationId =
         keyutil.presentationDriverKeyToPresentationId(rowKey);
@@ -218,7 +225,7 @@
     }
   }
 
-  _onPresentationQuestionChange(
+  void _onPresentationQuestionChange(
       int changeType, String rowKey, List<int> value) {
     String deckId = keyutil.presentationQuestionKeyToDeckId(rowKey);
 
diff --git a/dart/lib/styles/common.dart b/dart/lib/styles/common.dart
index fbd8017..d11c6a7 100644
--- a/dart/lib/styles/common.dart
+++ b/dart/lib/styles/common.dart
@@ -28,19 +28,20 @@
 }
 
 class Spacing {
-  static final EdgeDims extraSmallPadding = new EdgeDims.all(2.0);
-  static final EdgeDims smallPadding = new EdgeDims.all(5.0);
-  static final EdgeDims normalPadding = new EdgeDims.all(10.0);
-  static final EdgeDims normalMargin = new EdgeDims.all(2.0);
-  static final EdgeDims cardMargin = new EdgeDims.all(4.0);
-  static final EdgeDims listItemMargin = new EdgeDims.TRBL(3.0, 6.0, 0.0, 6.0);
-  static final EdgeDims actionsMargin =
-      new EdgeDims.symmetric(horizontal: 10.0);
-  static final EdgeDims fabMargin = new EdgeDims.only(right: 7.0);
-  static final EdgeDims footerVerticalMargin =
-      const EdgeDims.symmetric(vertical: 14.0);
-  static final EdgeDims footerHorizontalMargin =
-      const EdgeDims.symmetric(horizontal: 24.0);
+  static final EdgeInsets extraSmallPadding = new EdgeInsets.all(2.0);
+  static final EdgeInsets smallPadding = new EdgeInsets.all(5.0);
+  static final EdgeInsets normalPadding = new EdgeInsets.all(10.0);
+  static final EdgeInsets normalMargin = new EdgeInsets.all(2.0);
+  static final EdgeInsets cardMargin = new EdgeInsets.all(4.0);
+  static final EdgeInsets listItemMargin =
+      new EdgeInsets.fromLTRB(6.0, 3.0, 6.0, 0.0);
+  static final EdgeInsets actionsMargin =
+      new EdgeInsets.symmetric(horizontal: 10.0);
+  static final EdgeInsets fabMargin = new EdgeInsets.only(right: 7.0);
+  static final EdgeInsets footerVerticalMargin =
+      const EdgeInsets.symmetric(vertical: 14.0);
+  static final EdgeInsets footerHorizontalMargin =
+      const EdgeInsets.symmetric(horizontal: 24.0);
 }
 
 class Box {
diff --git a/dart/lib/syncbase/client.dart b/dart/lib/syncbase/client.dart
index c4d0c73..238ff48 100644
--- a/dart/lib/syncbase/client.dart
+++ b/dart/lib/syncbase/client.dart
@@ -4,7 +4,7 @@
 
 import 'dart:async';
 
-import 'package:flutter/services.dart' show shell;
+import 'package:flutter/shell.dart' show shell;
 import 'package:logging/logging.dart';
 import 'package:syncbase/syncbase_client.dart';
 
diff --git a/dart/lib/utils/image_provider.dart b/dart/lib/utils/image_provider.dart
index 50777cf..6a26125 100644
--- a/dart/lib/utils/image_provider.dart
+++ b/dart/lib/utils/image_provider.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 import 'dart:typed_data' show Uint8List;
-import 'dart:ui' as ui;
 
 import 'package:flutter/services.dart';
 import 'package:logging/logging.dart';
@@ -56,21 +55,28 @@
 
   _RawImageProvider(this.imageKey, this.blobFetcher);
 
-  Future<ui.Image> loadImage() async {
+  @override
+  Future<ImageInfo> loadImage() async {
     List<int> imageData;
     try {
       imageData = await blobFetcher();
     } catch (e) {
-      log.warning('Blob for ${imageKey} not found.');
+      log.warning('Blob for $imageKey not found.');
       imageData =
           await assetutil.getRawBytes(assetutil.defaultThumbnailAssetKey);
     }
 
-    return await decodeImageFromList(new Uint8List.fromList(imageData));
+    return new ImageInfo(
+        image: await decodeImageFromList(new Uint8List.fromList(imageData)));
   }
 
+  @override
   bool operator ==(other) =>
       other is _RawImageProvider && imageKey == other.imageKey;
+
+  @override
   int get hashCode => imageKey.hashCode;
+
+  @override
   String toString() => imageKey;
 }
diff --git a/dart/pubspec.lock b/dart/pubspec.lock
index 3f442c6..15d2911 100644
--- a/dart/pubspec.lock
+++ b/dart/pubspec.lock
@@ -2,33 +2,53 @@
 # See http://pub.dartlang.org/doc/glossary.html#lockfile
 packages:
   analyzer:
-    description: analyzer
+    description:
+      name: analyzer
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.27.1+2"
+    version: "0.27.2"
   archive:
-    description: archive
+    description:
+      name: archive
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "1.0.20"
   args:
-    description: args
+    description:
+      name: args
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.13.3+1"
+    version: "0.13.4"
   asn1lib:
-    description: asn1lib
+    description:
+      name: asn1lib
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.4.1"
   async:
-    description: async
+    description:
+      name: async
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.8.0"
+    version: "1.9.0"
   barback:
-    description: barback
+    description:
+      name: barback
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.15.2+7"
   bignum:
-    description: bignum
+    description:
+      name: bignum
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.0.7"
+    version: "0.1.0"
+  boolean_selector:
+    description:
+      name: boolean_selector
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.0"
   cassowary:
     description:
       path: "../../../../../flutter/packages/cassowary"
@@ -36,41 +56,77 @@
     source: path
     version: "0.1.7"
   charcode:
-    description: charcode
+    description:
+      name: charcode
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "1.1.0"
-  cipher:
-    description: cipher
+  cli_util:
+    description:
+      name: cli_util
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.7.1"
+    version: "0.0.1+2"
+  code_transformers:
+    description:
+      name: code_transformers
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.4.2+1"
   collection:
-    description: collection
+    description:
+      name: collection
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.4.0"
+    version: "1.5.1"
   contrast:
-    description: contrast
+    description:
+      name: contrast
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.1.1"
   convert:
-    description: convert
+    description:
+      name: convert
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "1.0.1"
   crypto:
-    description: crypto
+    description:
+      name: crypto
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.9.1"
+    version: "0.9.2"
   csslib:
-    description: csslib
+    description:
+      name: csslib
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.12.2"
+  dart_style:
+    description:
+      name: dart_style
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.2.4"
   den_api:
-    description: den_api
+    description:
+      name: den_api
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.1.0"
+  file:
+    description:
+      name: file
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.1.0"
   fixnum:
-    description: fixnum
+    description:
+      name: fixnum
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.9.1+2"
+    version: "0.10.2"
   flutter:
     description:
       path: "../../../../../flutter/packages/flutter"
@@ -90,71 +146,93 @@
     source: path
     version: "0.0.10"
   github:
-    description: github
+    description:
+      name: github
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "2.3.1+1"
   glob:
-    description: glob
+    description:
+      name: glob
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0"
+    version: "1.1.1"
   html:
-    description: html
+    description:
+      name: html
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.12.2+1"
   http:
-    description: http
+    description:
+      name: http
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.11.3+3"
   http_multi_server:
-    description: http_multi_server
+    description:
+      name: http_multi_server
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.2"
+    version: "2.0.0"
   http_parser:
-    description: http_parser
+    description:
+      name: http_parser
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.0"
+    version: "2.2.1"
   intl:
-    description: intl
+    description:
+      name: intl
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.12.6"
+    version: "0.12.7"
+  json_schema:
+    description:
+      name: json_schema
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.3"
   logging:
-    description: logging
+    description:
+      name: logging
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.11.2"
   matcher:
-    description: matcher
+    description:
+      name: matcher
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.12.0+1"
-  material_design_icons:
-    description: material_design_icons
-    source: hosted
-    version: "0.0.3"
+    version: "0.12.0+2"
   mime:
-    description: mime
+    description:
+      name: mime
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.9.3"
   mojo:
-    description: mojo
+    description:
+      name: mojo
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.4.12"
-  mojo_apptest:
-    description: mojo_apptest
-    source: hosted
-    version: "0.2.16"
+    version: "0.4.18"
   mojo_sdk:
-    description: mojo_sdk
+    description:
+      name: mojo_sdk
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.2.11"
+    version: "0.2.22"
   mojo_services:
-    description: mojo_services
+    description:
+      name: mojo_services
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.4.14"
-  mojom:
-    description: mojom
-    source: hosted
-    version: "0.2.16"
+    version: "0.4.25"
   mustache4dart:
-    description: mustache4dart
+    description:
+      name: mustache4dart
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "1.0.10"
   newton:
@@ -164,122 +242,225 @@
     source: path
     version: "0.1.5"
   package_config:
-    description: package_config
+    description:
+      name: package_config
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.1.3"
   path:
-    description: path
+    description:
+      name: path
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "1.3.9"
   petitparser:
-    description: petitparser
+    description:
+      name: petitparser
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "1.5.1"
   plugin:
-    description: plugin
+    description:
+      name: plugin
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.1.0"
+  pointycastle:
+    description:
+      name: pointycastle
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.10.0"
   pool:
-    description: pool
+    description:
+      name: pool
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "1.2.1"
   pub_package_data:
-    description: pub_package_data
+    description:
+      name: pub_package_data
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.0.1"
   pub_semver:
-    description: pub_semver
+    description:
+      name: pub_semver
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "1.2.3"
   quiver:
-    description: quiver
+    description:
+      name: quiver
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.21.4"
+  quiver_collection:
+    description:
+      name: quiver_collection
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.0"
+  quiver_iterables:
+    description:
+      name: quiver_iterables
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.0"
+  quiver_pattern:
+    description:
+      name: quiver_pattern
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.0"
+  reflectable:
+    description:
+      name: reflectable
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.5.3"
   shelf:
-    description: shelf
+    description:
+      name: shelf
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.6.4+3"
+    version: "0.6.5"
   shelf_static:
-    description: shelf_static
+    description:
+      name: shelf_static
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.2.3+2"
+    version: "0.2.3+3"
   shelf_web_socket:
-    description: shelf_web_socket
+    description:
+      name: shelf_web_socket
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.0.1+5"
+    version: "0.2.0"
   sky_engine:
-    description: sky_engine
-    source: hosted
-    version: "0.0.89"
+    description:
+      path: "../../../../../flutter/bin/cache/pkg/sky_engine"
+      relative: true
+    source: path
+    version: "0.0.99"
   sky_services:
-    description: sky_services
-    source: hosted
-    version: "0.0.89"
+    description:
+      path: "../../../../../flutter/bin/cache/pkg/sky_services"
+      relative: true
+    source: path
+    version: "0.0.99"
   source_map_stack_trace:
-    description: source_map_stack_trace
+    description:
+      name: source_map_stack_trace
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "1.0.4"
   source_maps:
-    description: source_maps
+    description:
+      name: source_maps
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.10.1"
+    version: "0.10.1+1"
   source_span:
-    description: source_span
+    description:
+      name: source_span
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.1"
+    version: "1.2.2"
   stack_trace:
-    description: stack_trace
+    description:
+      name: stack_trace
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.6.0"
+    version: "1.6.4"
+  stream_channel:
+    description:
+      name: stream_channel
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.3.1"
   string_scanner:
-    description: string_scanner
+    description:
+      name: string_scanner
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.1.4+1"
   syncbase:
-    description: syncbase
+    description:
+      name: syncbase
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.0.28"
+    version: "0.0.35"
   test:
-    description: test
+    description:
+      name: test
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.12.6+1"
+    version: "0.12.13"
   typed_data:
-    description: typed_data
+    description:
+      name: typed_data
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.1"
+    version: "1.1.2"
   utf:
-    description: utf
+    description:
+      name: utf
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.9.0+2"
+    version: "0.9.0+3"
   uuid:
-    description: uuid
+    description:
+      name: uuid
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.5.0"
+    version: "0.5.1"
   v23discovery:
-    description: v23discovery
-    source: hosted
-    version: "0.0.12"
+    description:
+      path: "../../../mojo/discovery"
+      relative: true
+    source: path
+    version: "0.0.17"
   vector_math:
-    description: vector_math
+    description:
+      name: vector_math
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.4.6"
+    version: "1.4.7"
   watcher:
-    description: watcher
+    description:
+      name: watcher
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.9.7"
+  web_socket_channel:
+    description:
+      name: web_socket_channel
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.2"
   when:
-    description: when
+    description:
+      name: when
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.2.0"
   which:
-    description: which
+    description:
+      name: which
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "0.1.3"
   xml:
-    description: xml
+    description:
+      name: xml
+      url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.4.1"
+    version: "2.4.2"
   yaml:
-    description: yaml
+    description:
+      name: yaml
+      url: "https://pub.dartlang.org"
     source: hosted
     version: "2.1.8"
+sdk: ">=1.14.0 <1.17.0"
diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml
index ca27e2c..93d94a0 100644
--- a/dart/pubspec.yaml
+++ b/dart/pubspec.yaml
@@ -5,8 +5,8 @@
     path: "../../../../../flutter/packages/flutter"
   logging: ">=0.11.2 <0.12.0"
   mojo_services: ">=0.4.5 <0.5.0"
-  syncbase: ">=0.0.28 <0.1.0"
-  v23discovery: ">=0.0.12 < 0.1.0"
+  syncbase: ">=0.0.34 <0.1.0"
+  v23discovery: ">=0.0.17 < 0.1.0"
   uuid: ">=0.5.0 <0.6.0"
 dev_dependencies:
   flutter_tools: