mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
First pass at adding meal tracking to fitness app
This commit is contained in:
parent
a43a34e901
commit
ea28a63d9a
@ -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<Measurement> measurements;
|
||||
final MeasurementHandler onDismissed;
|
||||
final List<FitnessItem> items;
|
||||
final FitnessItemHandler onDismissed;
|
||||
|
||||
Widget build() {
|
||||
return new Material(
|
||||
type: MaterialType.canvas,
|
||||
child: new ScrollableList<Measurement>(
|
||||
items: measurements,
|
||||
itemHeight: MeasurementRow.kHeight,
|
||||
itemBuilder: (measurement) => new MeasurementRow(
|
||||
measurement: measurement,
|
||||
child: new ScrollableList<FitnessItem>(
|
||||
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<Widget> 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<Measurement> userData;
|
||||
MeasurementHandler onMeasurementCreated;
|
||||
MeasurementHandler onMeasurementDeleted;
|
||||
List<FitnessItem> 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<Widget> layers = [
|
||||
new Scaffold(
|
||||
toolbar: buildToolBar(),
|
||||
body: buildBody(),
|
||||
snackBar: buildSnackBar(),
|
||||
floatingActionButton: buildFloatingActionButton(),
|
||||
drawer: buildDrawer()
|
||||
)
|
||||
];
|
||||
if (_isShowingDialog)
|
||||
layers.add(buildDialog());
|
||||
return new Stack(layers);
|
||||
}
|
||||
}
|
||||
46
sky/sdk/example/fitness/lib/fitness_item.dart
Normal file
46
sky/sdk/example/fitness/lib/fitness_item.dart
Normal file
@ -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()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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 }
|
||||
|
||||
@ -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<FitnessItem> _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<Measurement> _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(
|
||||
|
||||
121
sky/sdk/example/fitness/lib/meal.dart
Normal file
121
sky/sdk/example/fitness/lib/meal.dart
Normal file
@ -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<Widget> 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()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<Widget> 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()
|
||||
);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user