From ea28a63d9a88fa66c981ce07958320fafc5caad1 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Tue, 21 Jul 2015 17:11:39 -0700 Subject: [PATCH 1/2] First pass at adding meal tracking to fitness app --- .../fitness/lib/{home.dart => feed.dart} | 207 ++++++++---------- sky/sdk/example/fitness/lib/fitness_item.dart | 46 ++++ .../example/fitness/lib/fitness_types.dart | 2 +- sky/sdk/example/fitness/lib/main.dart | 36 +-- sky/sdk/example/fitness/lib/meal.dart | 121 ++++++++++ sky/sdk/example/fitness/lib/measurement.dart | 45 +++- sky/sdk/example/fitness/lib/settings.dart | 2 - 7 files changed, 320 insertions(+), 139 deletions(-) rename sky/sdk/example/fitness/lib/{home.dart => feed.dart} (51%) create mode 100644 sky/sdk/example/fitness/lib/fitness_item.dart create mode 100644 sky/sdk/example/fitness/lib/meal.dart diff --git a/sky/sdk/example/fitness/lib/home.dart b/sky/sdk/example/fitness/lib/feed.dart similarity index 51% rename from sky/sdk/example/fitness/lib/home.dart rename to sky/sdk/example/fitness/lib/feed.dart index 515c4135058c4..094d73eee1e58 100644 --- a/sky/sdk/example/fitness/lib/home.dart +++ b/sky/sdk/example/fitness/lib/feed.dart @@ -4,13 +4,12 @@ import 'package:sky/painting/text_style.dart'; import 'package:sky/widgets/basic.dart'; -import 'package:sky/widgets/card.dart'; -import 'package:sky/widgets/default_text_style.dart'; -import 'package:sky/widgets/dismissable.dart'; +import 'package:sky/widgets/dialog.dart'; import 'package:sky/widgets/drawer.dart'; import 'package:sky/widgets/drawer_divider.dart'; import 'package:sky/widgets/drawer_header.dart'; import 'package:sky/widgets/drawer_item.dart'; +import 'package:sky/widgets/flat_button.dart'; import 'package:sky/widgets/floating_action_button.dart'; import 'package:sky/widgets/icon_button.dart'; import 'package:sky/widgets/icon.dart'; @@ -24,22 +23,24 @@ import 'package:sky/widgets/tool_bar.dart'; import 'package:sky/widgets/widget.dart'; import 'fitness_types.dart'; +import 'fitness_item.dart'; import 'measurement.dart'; +import 'meal.dart'; -class MeasurementList extends Component { - MeasurementList({ String key, this.measurements, this.onDismissed }) : super(key: key); +class FitnessItemList extends Component { + FitnessItemList({ String key, this.items, this.onDismissed }) : super(key: key); - final List measurements; - final MeasurementHandler onDismissed; + final List items; + final FitnessItemHandler onDismissed; Widget build() { return new Material( type: MaterialType.canvas, - child: new ScrollableList( - items: measurements, - itemHeight: MeasurementRow.kHeight, - itemBuilder: (measurement) => new MeasurementRow( - measurement: measurement, + child: new ScrollableList( + items: items, + itemHeight: kFitnessItemHeight, + itemBuilder: (item) => new MeasurementRow( + measurement: item as Measurement, onDismissed: onDismissed ) ) @@ -47,60 +48,16 @@ class MeasurementList extends Component { } } -class MeasurementRow extends Component { +class FeedFragment extends StatefulComponent { - MeasurementRow({ Measurement measurement, this.onDismissed }) : this.measurement = measurement, super(key: measurement.when.toString()); - - final Measurement measurement; - final MeasurementHandler onDismissed; - - static const double kHeight = 79.0; - - Widget build() { - - List children = [ - new Flexible( - child: new Text( - measurement.displayWeight, - style: const TextStyle(textAlign: TextAlign.right) - ) - ), - new Flexible( - child: new Text( - measurement.displayDate, - style: Theme.of(this).text.caption.copyWith(textAlign: TextAlign.right) - ) - ) - ]; - - return new Dismissable( - key: measurement.when.toString(), - onDismissed: () => onDismissed(measurement), - child: new Card( - child: new Container( - height: kHeight, - padding: const EdgeDims.all(8.0), - child: new Flex( - children, - alignItems: FlexAlignItems.baseline, - textBaseline: DefaultTextStyle.of(this).textBaseline - ) - ) - ) - ); - } -} - -class HomeFragment extends StatefulComponent { - - HomeFragment({ this.navigator, this.userData, this.onMeasurementCreated, this.onMeasurementDeleted }); + FeedFragment({ this.navigator, this.userData, this.onItemCreated, this.onItemDeleted }); Navigator navigator; - List userData; - MeasurementHandler onMeasurementCreated; - MeasurementHandler onMeasurementDeleted; + List userData; + FitnessItemHandler onItemCreated; + FitnessItemHandler onItemDeleted; - FitnessMode _fitnessMode = FitnessMode.measure; + FitnessMode _fitnessMode = FitnessMode.feed; void initState() { // if (debug) @@ -108,19 +65,19 @@ class HomeFragment extends StatefulComponent { super.initState(); } - void syncFields(HomeFragment source) { + void syncFields(FeedFragment source) { navigator = source.navigator; userData = source.userData; - onMeasurementCreated = source.onMeasurementCreated; - onMeasurementDeleted = source.onMeasurementDeleted; + onItemCreated = source.onItemCreated; + onItemDeleted = source.onItemDeleted; } bool _isShowingSnackBar = false; - bool _isRunning = false; void _handleFitnessModeChange(FitnessMode value) { setState(() { _fitnessMode = value; + _drawerShowing = false; }); } @@ -135,15 +92,15 @@ class HomeFragment extends StatefulComponent { children: [ new DrawerHeader(children: [new Text('Fitness')]), new DrawerItem( - icon: 'action/assessment', - onPressed: () => _handleFitnessModeChange(FitnessMode.measure), - selected: _fitnessMode == FitnessMode.measure, - children: [new Text('Measure')]), + icon: 'action/list', + onPressed: () => _handleFitnessModeChange(FitnessMode.feed), + selected: _fitnessMode == FitnessMode.feed, + children: [new Text('Feed')]), new DrawerItem( - icon: 'maps/directions_run', - onPressed: () => _handleFitnessModeChange(FitnessMode.run), - selected: _fitnessMode == FitnessMode.run, - children: [new Text('Run')]), + icon: 'action/assessment', + onPressed: () => _handleFitnessModeChange(FitnessMode.chart), + selected: _fitnessMode == FitnessMode.chart, + children: [new Text('Chart')]), new DrawerDivider(), new DrawerItem( icon: 'action/settings', @@ -180,8 +137,8 @@ class HomeFragment extends StatefulComponent { // TODO(jackson): We should be localizing String get fitnessModeTitle { switch(_fitnessMode) { - case FitnessMode.measure: return "Measure"; - case FitnessMode.run: return "Run"; + case FitnessMode.feed: return "Feed"; + case FitnessMode.chart: return "Chart"; } } @@ -194,13 +151,12 @@ class HomeFragment extends StatefulComponent { ); } - // TODO(jackson): Pull from file - Measurement _undoMeasurement; + FitnessItem _undoItem; - void _handleMeasurementDismissed(Measurement measurement) { - onMeasurementDeleted(measurement); + void _handleItemDismissed(FitnessItem item) { + onItemDeleted(item); setState(() { - _undoMeasurement = measurement; + _undoItem = item; _isShowingSnackBar = true; }); } @@ -208,33 +164,33 @@ class HomeFragment extends StatefulComponent { Widget buildBody() { TextStyle style = Theme.of(this).text.title; switch (_fitnessMode) { - case FitnessMode.measure: + case FitnessMode.feed: if (userData.length > 0) - return new MeasurementList( - measurements: userData, - onDismissed: _handleMeasurementDismissed + return new FitnessItemList( + items: userData, + onDismissed: _handleItemDismissed ); return new Material( type: MaterialType.canvas, child: new Flex( - [new Text("No measurements yet.\nAdd a new one!", style: style)], + [new Text("No data yet.\nAdd some!", style: style)], justifyContent: FlexJustifyContent.center ) ); - case FitnessMode.run: + case FitnessMode.chart: return new Material( type: MaterialType.canvas, child: new Flex([ - new Text(_isRunning ? "Go go go!" : "Start a new run!", style: style) + new Text("Charts are coming soon!", style: style) ], justifyContent: FlexJustifyContent.center) ); } } void _handleUndo() { - onMeasurementCreated(_undoMeasurement); + onItemCreated(_undoItem); setState(() { - _undoMeasurement = null; + _undoItem = null; _isShowingSnackBar = false; }); } @@ -243,48 +199,71 @@ class HomeFragment extends StatefulComponent { if (!_isShowingSnackBar) return null; return new SnackBar( - content: new Text("Measurement deleted."), + content: new Text("Item deleted."), actions: [new SnackBarAction(label: "UNDO", onPressed: _handleUndo)] ); } - void _handleRunStarted() { - setState(() { - _isRunning = true; - }); + bool _isShowingDialog = false; + + Widget buildDialog() { + return new Dialog( + title: new Text("New item"), + content: new Text("What are you trying to do?"), + onDismiss: navigator.pop, + actions: [ + new FlatButton( + child: new Text('CANCEL'), + onPressed: navigator.pop + ), + new FlatButton( + child: new Text('EAT'), + onPressed: () { + navigator.pop(); + navigator.pushNamed("/meals/new"); + } + ), + new FlatButton( + child: new Text('MEASURE'), + onPressed: () { + navigator.pop(); + navigator.pushNamed("/measurements/new"); + } + ), + ] + ); } - void _handleRunStopped() { + void _handleActionButtonPressed() { setState(() { - _isRunning = false; + _isShowingDialog = true; }); } Widget buildFloatingActionButton() { switch (_fitnessMode) { - case FitnessMode.measure: + case FitnessMode.feed: return new FloatingActionButton( child: new Icon(type: 'content/add', size: 24), - onPressed: () => navigator.pushNamed("/measurements/new") - ); - case FitnessMode.run: - return new FloatingActionButton( - child: new Icon( - type: _isRunning ? 'av/stop' : 'maps/directions_run', - size: 24 - ), - onPressed: _isRunning ? _handleRunStopped : _handleRunStarted + onPressed: _handleActionButtonPressed ); + case FitnessMode.chart: + return null; } } Widget build() { - return new Scaffold( - toolbar: buildToolBar(), - body: buildBody(), - snackBar: buildSnackBar(), - floatingActionButton: buildFloatingActionButton(), - drawer: buildDrawer() - ); + List layers = [ + new Scaffold( + toolbar: buildToolBar(), + body: buildBody(), + snackBar: buildSnackBar(), + floatingActionButton: buildFloatingActionButton(), + drawer: buildDrawer() + ) + ]; + if (_isShowingDialog) + layers.add(buildDialog()); + return new Stack(layers); } } diff --git a/sky/sdk/example/fitness/lib/fitness_item.dart b/sky/sdk/example/fitness/lib/fitness_item.dart new file mode 100644 index 0000000000000..e80224403187c --- /dev/null +++ b/sky/sdk/example/fitness/lib/fitness_item.dart @@ -0,0 +1,46 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:sky/widgets/basic.dart'; +import 'package:sky/widgets/card.dart'; +import 'package:sky/widgets/dismissable.dart'; + +typedef void FitnessItemHandler(FitnessItem item); + +const double kFitnessItemHeight = 79.0; + +class FitnessItem { + FitnessItem({ this.when }) { + assert(when != null); + } + final DateTime when; + + // TODO(jackson): Internationalize + String get displayDate => "${when.year.toString()}-${when.month.toString().padLeft(2,'0')}-${when.day.toString().padLeft(2,'0')}"; +} + +abstract class FitnessItemRow extends Component { + + FitnessItemRow({ FitnessItem item, this.onDismissed }) + : this.item = item, + super(key: item.when.toString()); + + final FitnessItem item; + final FitnessItemHandler onDismissed; + + Widget buildContent(); + + Widget build() { + return new Dismissable( + onDismissed: () => onDismissed(item), + child: new Card( + child: new Container( + height: kFitnessItemHeight, + padding: const EdgeDims.all(8.0), + child: buildContent() + ) + ) + ); + } +} diff --git a/sky/sdk/example/fitness/lib/fitness_types.dart b/sky/sdk/example/fitness/lib/fitness_types.dart index 0bd3377854a02..f7a11199896b8 100644 --- a/sky/sdk/example/fitness/lib/fitness_types.dart +++ b/sky/sdk/example/fitness/lib/fitness_types.dart @@ -2,5 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -enum FitnessMode { measure, run } +enum FitnessMode { feed, chart } enum BackupMode { enabled, disabled } diff --git a/sky/sdk/example/fitness/lib/main.dart b/sky/sdk/example/fitness/lib/main.dart index c24705ed49174..a9c1579754b82 100644 --- a/sky/sdk/example/fitness/lib/main.dart +++ b/sky/sdk/example/fitness/lib/main.dart @@ -9,31 +9,44 @@ import 'package:sky/widgets/theme.dart'; import 'package:sky/widgets/widget.dart'; import 'package:sky/widgets/task_description.dart'; +import 'meal.dart'; import 'measurement.dart'; -import 'home.dart'; +import 'feed.dart'; import 'settings.dart'; +import 'fitness_item.dart'; import 'fitness_types.dart'; class FitnessApp extends App { NavigationState _navigationState; + final List _userData = [ + new Measurement(weight: 180.0, when: new DateTime.now().add(const Duration(days: -1))), + new Measurement(weight: 160.0, when: new DateTime.now()), + ]; void initState() { _navigationState = new NavigationState([ new Route( name: '/', - builder: (navigator, route) => new HomeFragment( + builder: (navigator, route) => new FeedFragment( navigator: navigator, userData: _userData, - onMeasurementCreated: _handleMeasurementCreated, - onMeasurementDeleted: _handleMeasurementDeleted + onItemCreated: _handleItemCreated, + onItemDeleted: _handleItemDeleted + ) + ), + new Route( + name: '/meals/new', + builder: (navigator, route) => new MealFragment( + navigator: navigator, + onCreated: _handleItemCreated ) ), new Route( name: '/measurements/new', builder: (navigator, route) => new MeasurementFragment( navigator: navigator, - onCreated: _handleMeasurementCreated + onCreated: _handleItemCreated ) ), new Route( @@ -54,16 +67,16 @@ class FitnessApp extends App { } } - void _handleMeasurementCreated(Measurement measurement) { + void _handleItemCreated(FitnessItem item) { setState(() { - _userData.add(measurement); + _userData.add(item); _userData.sort((a, b) => a.when.compareTo(b.when)); }); } - void _handleMeasurementDeleted(Measurement measurement) { + void _handleItemDeleted(FitnessItem item) { setState(() { - _userData.remove(measurement); + _userData.remove(item); }); } @@ -76,11 +89,6 @@ class FitnessApp extends App { }); } - final List _userData = [ - new Measurement(weight: 180.0, when: new DateTime.now().add(const Duration(days: -1))), - new Measurement(weight: 160.0, when: new DateTime.now()), - ]; - Widget build() { return new Theme( data: new ThemeData( diff --git a/sky/sdk/example/fitness/lib/meal.dart b/sky/sdk/example/fitness/lib/meal.dart new file mode 100644 index 0000000000000..a9c77d86bfe23 --- /dev/null +++ b/sky/sdk/example/fitness/lib/meal.dart @@ -0,0 +1,121 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:sky/painting/text_style.dart'; +import 'package:sky/editing/input.dart'; +import 'package:sky/widgets/basic.dart'; +import 'package:sky/widgets/default_text_style.dart'; +import 'package:sky/widgets/icon_button.dart'; +import 'package:sky/widgets/ink_well.dart'; +import 'package:sky/widgets/material.dart'; +import 'package:sky/widgets/navigator.dart'; +import 'package:sky/widgets/scaffold.dart'; +import 'package:sky/widgets/scrollable_viewport.dart'; +import 'package:sky/widgets/snack_bar.dart'; +import 'package:sky/widgets/theme.dart'; +import 'package:sky/widgets/tool_bar.dart'; + +import 'fitness_item.dart'; + +class Meal extends FitnessItem { + Meal({ DateTime when, this.description }) : super(when: when); + + final String description; +} + +class MealRow extends FitnessItemRow { + MealRow({ Meal meal, FitnessItemHandler onDismissed }) + : super(item: meal, onDismissed: onDismissed); + + Widget buildContent() { + Meal meal = item; + List children = [ + new Flexible( + child: new Text( + meal.description, + style: const TextStyle(textAlign: TextAlign.right) + ) + ), + new Flexible( + child: new Text( + meal.displayDate, + style: Theme.of(this).text.caption.copyWith(textAlign: TextAlign.right) + ) + ) + ]; + return new Flex( + children, + alignItems: FlexAlignItems.baseline, + textBaseline: DefaultTextStyle.of(this).textBaseline + ); + } +} + +class MealFragment extends StatefulComponent { + + MealFragment({ this.navigator, this.onCreated }); + + Navigator navigator; + FitnessItemHandler onCreated; + + void syncFields(MealFragment source) { + navigator = source.navigator; + onCreated = source.onCreated; + } + + String _description = ""; + + void _handleSave() { + onCreated(new Meal(when: new DateTime.now(), description: _description)); + navigator.pop(); + } + + Widget buildToolBar() { + return new ToolBar( + left: new IconButton( + icon: "navigation/close", + onPressed: navigator.pop), + center: new Text('New Meal'), + right: [new InkWell( + child: new Listener( + onGestureTap: (_) => _handleSave(), + child: new Text('SAVE') + ) + )] + ); + } + + void _handleDescriptionChanged(String description) { + setState(() { + _description = description; + }); + } + + Widget buildBody() { + Meal meal = new Meal(when: new DateTime.now()); + return new Material( + type: MaterialType.canvas, + child: new ScrollableViewport( + child: new Container( + padding: const EdgeDims.all(20.0), + child: new Block([ + new Text(meal.displayDate), + new Input( + focused: false, + placeholder: 'Describe meal', + onChanged: _handleDescriptionChanged + ), + ]) + ) + ) + ); + } + + Widget build() { + return new Scaffold( + toolbar: buildToolBar(), + body: buildBody() + ); + } +} diff --git a/sky/sdk/example/fitness/lib/measurement.dart b/sky/sdk/example/fitness/lib/measurement.dart index c7913388d4c37..6ce36fb5bde55 100644 --- a/sky/sdk/example/fitness/lib/measurement.dart +++ b/sky/sdk/example/fitness/lib/measurement.dart @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:sky/painting/text_style.dart'; import 'package:sky/editing/input.dart'; import 'package:sky/widgets/basic.dart'; +import 'package:sky/widgets/default_text_style.dart'; import 'package:sky/widgets/icon_button.dart'; import 'package:sky/widgets/ink_well.dart'; import 'package:sky/widgets/material.dart'; @@ -11,19 +13,46 @@ import 'package:sky/widgets/navigator.dart'; import 'package:sky/widgets/scaffold.dart'; import 'package:sky/widgets/scrollable_viewport.dart'; import 'package:sky/widgets/snack_bar.dart'; +import 'package:sky/widgets/theme.dart'; import 'package:sky/widgets/tool_bar.dart'; -typedef void MeasurementHandler(Measurement measurement); +import 'fitness_item.dart'; -class Measurement { - Measurement({ this.when, this.weight }); +class Measurement extends FitnessItem { + Measurement({ DateTime when, this.weight }) : super(when: when); - final DateTime when; final double weight; // TODO(jackson): Internationalize String get displayWeight => "${weight.toStringAsFixed(2)} lbs"; - String get displayDate => "${when.year.toString()}-${when.month.toString().padLeft(2,'0')}-${when.day.toString().padLeft(2,'0')}"; +} + +class MeasurementRow extends FitnessItemRow { + MeasurementRow({ Measurement measurement, FitnessItemHandler onDismissed }) + : super(item: measurement, onDismissed: onDismissed); + + Widget buildContent() { + Measurement measurement = item; + List children = [ + new Flexible( + child: new Text( + measurement.displayWeight, + style: const TextStyle(textAlign: TextAlign.right) + ) + ), + new Flexible( + child: new Text( + measurement.displayDate, + style: Theme.of(this).text.caption.copyWith(textAlign: TextAlign.right) + ) + ) + ]; + return new Flex( + children, + alignItems: FlexAlignItems.baseline, + textBaseline: DefaultTextStyle.of(this).textBaseline + ); + } } class MeasurementFragment extends StatefulComponent { @@ -31,7 +60,7 @@ class MeasurementFragment extends StatefulComponent { MeasurementFragment({ this.navigator, this.onCreated }); Navigator navigator; - MeasurementHandler onCreated; + FitnessItemHandler onCreated; void syncFields(MeasurementFragment source) { navigator = source.navigator; @@ -76,7 +105,7 @@ class MeasurementFragment extends StatefulComponent { }); } - Widget buildMeasurementPane() { + Widget buildBody() { Measurement measurement = new Measurement(when: new DateTime.now()); return new Material( type: MaterialType.canvas, @@ -105,7 +134,7 @@ class MeasurementFragment extends StatefulComponent { Widget build() { return new Scaffold( toolbar: buildToolBar(), - body: buildMeasurementPane(), + body: buildBody(), snackBar: buildSnackBar() ); } diff --git a/sky/sdk/example/fitness/lib/settings.dart b/sky/sdk/example/fitness/lib/settings.dart index 51ac6f7532d3a..53bb12d60a1b5 100644 --- a/sky/sdk/example/fitness/lib/settings.dart +++ b/sky/sdk/example/fitness/lib/settings.dart @@ -27,8 +27,6 @@ class SettingsFragment extends Component { final BackupMode backup; final SettingsUpdater updater; - bool showModeDialog = false; - void _handleBackupChanged(bool value) { if (updater != null) updater(backup: value ? BackupMode.enabled : BackupMode.disabled); From 4a4e303ad9d44069898ecd24ce057d3311576656 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Wed, 22 Jul 2015 10:28:43 -0700 Subject: [PATCH 2/2] Fix build --- sky/sdk/example/fitness/lib/feed.dart | 50 +------------------ sky/sdk/example/fitness/lib/fitness_item.dart | 2 +- 2 files changed, 2 insertions(+), 50 deletions(-) diff --git a/sky/sdk/example/fitness/lib/feed.dart b/sky/sdk/example/fitness/lib/feed.dart index 835955216ecc7..bf94dd361965f 100644 --- a/sky/sdk/example/fitness/lib/feed.dart +++ b/sky/sdk/example/fitness/lib/feed.dart @@ -49,56 +49,7 @@ class FitnessItemList extends Component { } class FeedFragment extends StatefulComponent { - -<<<<<<< HEAD:sky/sdk/example/fitness/lib/feed.dart FeedFragment({ this.navigator, this.userData, this.onItemCreated, this.onItemDeleted }); -======= - MeasurementRow({ Measurement measurement, this.onDismissed }) : this.measurement = measurement, super(key: new Key.stringify(measurement.when)); - - final Measurement measurement; - final MeasurementHandler onDismissed; - - static const double kHeight = 79.0; - - Widget build() { - - List children = [ - new Flexible( - child: new Text( - measurement.displayWeight, - style: const TextStyle(textAlign: TextAlign.right) - ) - ), - new Flexible( - child: new Text( - measurement.displayDate, - style: Theme.of(this).text.caption.copyWith(textAlign: TextAlign.right) - ) - ) - ]; - - return new Dismissable( - key: new Key.stringify(measurement.when), - onDismissed: () => onDismissed(measurement), - child: new Card( - child: new Container( - height: kHeight, - padding: const EdgeDims.all(8.0), - child: new Flex( - children, - alignItems: FlexAlignItems.baseline, - textBaseline: DefaultTextStyle.of(this).textBaseline - ) - ) - ) - ); - } -} - -class HomeFragment extends StatefulComponent { - - HomeFragment({ this.navigator, this.userData, this.onMeasurementCreated, this.onMeasurementDeleted }); ->>>>>>> dk/master:sky/sdk/example/fitness/lib/home.dart Navigator navigator; List userData; @@ -247,6 +198,7 @@ class HomeFragment extends StatefulComponent { if (!_isShowingSnackBar) return null; return new SnackBar( + showing: _isShowingSnackBar, content: new Text("Item deleted."), actions: [new SnackBarAction(label: "UNDO", onPressed: _handleUndo)] ); diff --git a/sky/sdk/example/fitness/lib/fitness_item.dart b/sky/sdk/example/fitness/lib/fitness_item.dart index e80224403187c..d46bbb01df4c2 100644 --- a/sky/sdk/example/fitness/lib/fitness_item.dart +++ b/sky/sdk/example/fitness/lib/fitness_item.dart @@ -24,7 +24,7 @@ abstract class FitnessItemRow extends Component { FitnessItemRow({ FitnessItem item, this.onDismissed }) : this.item = item, - super(key: item.when.toString()); + super(key: new Key(item.when.toString())); final FitnessItem item; final FitnessItemHandler onDismissed;