mirror of
https://github.com/flutter/samples.git
synced 2025-11-09 06:18:49 +00:00
Updates travis config to include place_tracker and platform_view_swift (#42)
This commit is contained in:
@@ -11,7 +11,7 @@ addons:
|
||||
git:
|
||||
depth: 3
|
||||
env:
|
||||
- FLUTTER_VERSION=beta
|
||||
- FLUTTER_VERSION=stable
|
||||
- FLUTTER_VERSION=dev
|
||||
matrix:
|
||||
allow_failures:
|
||||
|
||||
@@ -20,9 +20,6 @@ dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
dependency_overrides:
|
||||
analyzer: 0.33.0
|
||||
|
||||
flutter:
|
||||
|
||||
uses-material-design: true
|
||||
|
||||
@@ -4,7 +4,7 @@ class _AppModelScope<T> extends InheritedWidget {
|
||||
const _AppModelScope({
|
||||
Key key,
|
||||
this.appModelState,
|
||||
Widget child
|
||||
Widget child,
|
||||
}) : super(key: key, child: child);
|
||||
|
||||
final _AppModelState<T> appModelState;
|
||||
@@ -30,13 +30,15 @@ class AppModel<T> extends StatefulWidget {
|
||||
|
||||
static T of<T>(BuildContext context) {
|
||||
final Type appModelScopeType = _typeOf<_AppModelScope<T>>();
|
||||
final _AppModelScope<T> scope = context.inheritFromWidgetOfExactType(appModelScopeType);
|
||||
final _AppModelScope<T> scope =
|
||||
context.inheritFromWidgetOfExactType(appModelScopeType);
|
||||
return scope.appModelState.currentState;
|
||||
}
|
||||
|
||||
static void update<T>(BuildContext context, T newState) {
|
||||
final Type appModelScopeType = _typeOf<_AppModelScope<T>>();
|
||||
final _AppModelScope<T> scope = context.inheritFromWidgetOfExactType(appModelScopeType);
|
||||
final _AppModelScope<T> scope =
|
||||
context.inheritFromWidgetOfExactType(appModelScopeType);
|
||||
scope.appModelState.updateState(newState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ class PlaceDetails extends StatefulWidget {
|
||||
}
|
||||
|
||||
class PlaceDetailsState extends State<PlaceDetails> {
|
||||
|
||||
Place _place;
|
||||
GoogleMapController _mapController;
|
||||
|
||||
@@ -326,7 +325,9 @@ class _Reviews extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: StubData.reviewStrings.map((reviewText) => _buildSingleReview(reviewText)).toList(),
|
||||
children: StubData.reviewStrings
|
||||
.map((reviewText) => _buildSingleReview(reviewText))
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -22,7 +22,8 @@ class PlaceListState extends State<PlaceList> {
|
||||
void _onPlaceChanged(Place value) {
|
||||
// Replace the place with the modified version.
|
||||
final List<Place> newPlaces = List.from(AppState.of(context).places);
|
||||
final int index = newPlaces.indexWhere((Place place) => place.id == value.id);
|
||||
final int index =
|
||||
newPlaces.indexWhere((Place place) => place.id == value.id);
|
||||
newPlaces[index] = value;
|
||||
|
||||
AppState.updateWith(context, places: newPlaces);
|
||||
@@ -41,16 +42,18 @@ class PlaceListState extends State<PlaceList> {
|
||||
padding: const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 8.0),
|
||||
controller: _scrollController,
|
||||
shrinkWrap: true,
|
||||
children: AppState.of(context).places
|
||||
.where((Place place) => place.category == AppState.of(context).selectedCategory)
|
||||
children: AppState.of(context)
|
||||
.places
|
||||
.where((Place place) =>
|
||||
place.category == AppState.of(context).selectedCategory)
|
||||
.map((Place place) => _PlaceListTile(
|
||||
place: place,
|
||||
onPlaceChanged: (Place value) => _onPlaceChanged(value),
|
||||
)
|
||||
).toList(),
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
]
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -95,9 +98,12 @@ class _PlaceListTile extends StatelessWidget {
|
||||
),
|
||||
Row(
|
||||
children: List.generate(5, (int index) {
|
||||
return Icon(Icons.star,
|
||||
return Icon(
|
||||
Icons.star,
|
||||
size: 28.0,
|
||||
color: place.starRating > index ? Colors.amber : Colors.grey[400],
|
||||
color: place.starRating > index
|
||||
? Colors.amber
|
||||
: Colors.grey[400],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
@@ -140,11 +146,13 @@ class _ListCategoryButtonBar extends StatelessWidget {
|
||||
category: PlaceCategory.favorite,
|
||||
selected: selectedCategory == PlaceCategory.favorite,
|
||||
onCategoryChanged: onCategoryChanged,
|
||||
),_CategoryButton(
|
||||
),
|
||||
_CategoryButton(
|
||||
category: PlaceCategory.visited,
|
||||
selected: selectedCategory == PlaceCategory.visited,
|
||||
onCategoryChanged: onCategoryChanged,
|
||||
),_CategoryButton(
|
||||
),
|
||||
_CategoryButton(
|
||||
category: PlaceCategory.wantToGo,
|
||||
selected: selectedCategory == PlaceCategory.wantToGo,
|
||||
onCategoryChanged: onCategoryChanged,
|
||||
|
||||
@@ -21,7 +21,6 @@ class PlaceMap extends StatefulWidget {
|
||||
}
|
||||
|
||||
class PlaceMapState extends State<PlaceMap> {
|
||||
|
||||
static BitmapDescriptor _getPlaceMarkerIcon(PlaceCategory category) {
|
||||
switch (category) {
|
||||
case PlaceCategory.favorite:
|
||||
@@ -36,7 +35,8 @@ class PlaceMapState extends State<PlaceMap> {
|
||||
}
|
||||
}
|
||||
|
||||
static List<Place> _getPlacesForCategory(PlaceCategory category, List<Place> places) {
|
||||
static List<Place> _getPlacesForCategory(
|
||||
PlaceCategory category, List<Place> places) {
|
||||
return places.where((Place place) => place.category == category).toList();
|
||||
}
|
||||
|
||||
@@ -61,7 +61,8 @@ class PlaceMapState extends State<PlaceMap> {
|
||||
}
|
||||
|
||||
Future<Map<Marker, Place>> _markPlaces() async {
|
||||
await Future.wait(AppState.of(context).places.map((Place place) => _markPlace(place)));
|
||||
await Future.wait(
|
||||
AppState.of(context).places.map((Place place) => _markPlace(place)));
|
||||
return _markedPlaces;
|
||||
}
|
||||
|
||||
@@ -101,7 +102,8 @@ class PlaceMapState extends State<PlaceMap> {
|
||||
void _onPlaceChanged(Place value) {
|
||||
// Replace the place with the modified version.
|
||||
final List<Place> newPlaces = List.from(AppState.of(context).places);
|
||||
final int index = newPlaces.indexWhere((Place place) => place.id == value.id);
|
||||
final int index =
|
||||
newPlaces.indexWhere((Place place) => place.id == value.id);
|
||||
newPlaces[index] = value;
|
||||
|
||||
_updateExistingPlaceMarker(place: value);
|
||||
@@ -117,10 +119,9 @@ class PlaceMapState extends State<PlaceMap> {
|
||||
AppState.updateWith(context, places: newPlaces);
|
||||
}
|
||||
|
||||
void _updateExistingPlaceMarker({@required Place place}) async {
|
||||
Marker marker =
|
||||
_markedPlaces.keys.singleWhere(
|
||||
(Marker value) => _markedPlaces[value].id == place.id);
|
||||
Future<void> _updateExistingPlaceMarker({@required Place place}) async {
|
||||
Marker marker = _markedPlaces.keys
|
||||
.singleWhere((Marker value) => _markedPlaces[value].id == place.id);
|
||||
|
||||
// Set marker visibility to false to ensure the info window is hidden. Once
|
||||
// the plugin fully supports the Google Maps API, use hideInfoWindow()
|
||||
@@ -136,9 +137,7 @@ class PlaceMapState extends State<PlaceMap> {
|
||||
MarkerOptions(
|
||||
infoWindowText: InfoWindowText(
|
||||
place.name,
|
||||
place.starRating != 0
|
||||
? '${place.starRating} Star Rating'
|
||||
: null,
|
||||
place.starRating != 0 ? '${place.starRating} Star Rating' : null,
|
||||
),
|
||||
visible: true,
|
||||
),
|
||||
@@ -152,16 +151,20 @@ class PlaceMapState extends State<PlaceMap> {
|
||||
_showPlacesForSelectedCategory(category);
|
||||
}
|
||||
|
||||
void _showPlacesForSelectedCategory(PlaceCategory category) async {
|
||||
await _markedPlaces.forEach((Marker marker, Place place) {
|
||||
mapController.updateMarker(
|
||||
Future<void> _showPlacesForSelectedCategory(PlaceCategory category) async {
|
||||
await Future.wait(
|
||||
_markedPlaces.keys.map(
|
||||
(Marker marker) => mapController.updateMarker(
|
||||
marker,
|
||||
MarkerOptions(
|
||||
visible: place.category == category,
|
||||
visible: _markedPlaces[marker].category == category,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
_zoomToFitPlaces(_getPlacesForCategory(category, _markedPlaces.values.toList()));
|
||||
|
||||
_zoomToFitPlaces(
|
||||
_getPlacesForCategory(category, _markedPlaces.values.toList()));
|
||||
}
|
||||
|
||||
void _zoomToFitPlaces(List<Place> places) {
|
||||
@@ -229,10 +232,8 @@ class PlaceMapState extends State<PlaceMap> {
|
||||
Scaffold.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
duration: Duration(seconds: 3),
|
||||
content: const Text(
|
||||
'New place added.',
|
||||
style: const TextStyle(fontSize: 16.0)
|
||||
),
|
||||
content: const Text('New place added.',
|
||||
style: const TextStyle(fontSize: 16.0)),
|
||||
action: SnackBarAction(
|
||||
label: 'Edit',
|
||||
onPressed: () async {
|
||||
@@ -272,36 +273,38 @@ class PlaceMapState extends State<PlaceMap> {
|
||||
}
|
||||
|
||||
void _onToggleMapTypePressed() {
|
||||
final MapType nextType =
|
||||
MapType.values[(mapController.options.mapType.index + 1) % MapType.values.length];
|
||||
final MapType nextType = MapType.values[
|
||||
(mapController.options.mapType.index + 1) % MapType.values.length];
|
||||
|
||||
mapController.updateMapOptions(
|
||||
GoogleMapOptions(mapType: nextType),
|
||||
);
|
||||
}
|
||||
|
||||
void _maybeUpdateMapConfiguration() async {
|
||||
Future<void> _maybeUpdateMapConfiguration() async {
|
||||
_configuration ??= MapConfiguration.of(AppState.of(context));
|
||||
final MapConfiguration newConfiguration = MapConfiguration.of(AppState.of(context));
|
||||
final MapConfiguration newConfiguration =
|
||||
MapConfiguration.of(AppState.of(context));
|
||||
|
||||
// Since we manually update [_configuration] when place or selectedCategory
|
||||
// changes come from the [place_map], we should only enter this if statement
|
||||
// when returning to the [place_map] after changes have been made from
|
||||
// [place_list].
|
||||
if (_configuration != newConfiguration && mapController != null) {
|
||||
if (_configuration.places == newConfiguration.places
|
||||
&& _configuration.selectedCategory != newConfiguration.selectedCategory) {
|
||||
if (_configuration.places == newConfiguration.places &&
|
||||
_configuration.selectedCategory !=
|
||||
newConfiguration.selectedCategory) {
|
||||
// If the configuration change is only a category change, just update
|
||||
// the marker visibilities.
|
||||
_showPlacesForSelectedCategory(newConfiguration.selectedCategory);
|
||||
} else {
|
||||
// At this point, we know the places have been updated from the list view.
|
||||
// We need to reconfigure the map to respect the updates.
|
||||
await newConfiguration.places.forEach((Place value) {
|
||||
if (!_configuration.places.contains(value)) {
|
||||
_updateExistingPlaceMarker(place: value);
|
||||
}
|
||||
});
|
||||
// At this point, we know the places have been updated from the list
|
||||
// view. We need to reconfigure the map to respect the updates.
|
||||
await Future.wait(
|
||||
newConfiguration.places
|
||||
.where((Place p) => !_configuration.places.contains(p))
|
||||
.map((Place value) => _updateExistingPlaceMarker(place: value)),
|
||||
);
|
||||
_zoomToFitPlaces(
|
||||
_getPlacesForCategory(
|
||||
newConfiguration.selectedCategory,
|
||||
@@ -524,15 +527,22 @@ class MapConfiguration {
|
||||
final List<Place> places;
|
||||
final PlaceCategory selectedCategory;
|
||||
|
||||
@override
|
||||
int get hashCode => places.hashCode ^ selectedCategory.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other))
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
if (other.runtimeType != runtimeType)
|
||||
}
|
||||
|
||||
if (other.runtimeType != runtimeType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final MapConfiguration otherConfiguration = other;
|
||||
return otherConfiguration.places == places
|
||||
&& otherConfiguration.selectedCategory == selectedCategory;
|
||||
return otherConfiguration.places == places &&
|
||||
otherConfiguration.selectedCategory == selectedCategory;
|
||||
}
|
||||
|
||||
static MapConfiguration of(AppState appState) {
|
||||
|
||||
@@ -60,12 +60,13 @@ class _PlaceTrackerHomePage extends StatelessWidget {
|
||||
AppState.of(context).viewType == PlaceTrackerViewType.map
|
||||
? Icons.list
|
||||
: Icons.map,
|
||||
size: 32.0
|
||||
size: 32.0,
|
||||
),
|
||||
onPressed: () {
|
||||
AppState.updateWith(
|
||||
context,
|
||||
viewType: AppState.of(context).viewType == PlaceTrackerViewType.map
|
||||
viewType:
|
||||
AppState.of(context).viewType == PlaceTrackerViewType.map
|
||||
? PlaceTrackerViewType.list
|
||||
: PlaceTrackerViewType.map,
|
||||
);
|
||||
@@ -75,7 +76,8 @@ class _PlaceTrackerHomePage extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
body: IndexedStack(
|
||||
index: AppState.of(context).viewType == PlaceTrackerViewType.map ? 0 : 1,
|
||||
index:
|
||||
AppState.of(context).viewType == PlaceTrackerViewType.map ? 0 : 1,
|
||||
children: <Widget>[
|
||||
PlaceMap(center: const LatLng(45.521563, -122.677433)),
|
||||
PlaceList(),
|
||||
@@ -116,29 +118,29 @@ class AppState {
|
||||
}
|
||||
|
||||
static void updateWith(
|
||||
BuildContext context,
|
||||
{List<Place> places,
|
||||
BuildContext context, {
|
||||
List<Place> places,
|
||||
PlaceCategory selectedCategory,
|
||||
PlaceTrackerViewType viewType,
|
||||
}) {
|
||||
update(
|
||||
context,
|
||||
AppState.of(context).copyWith(
|
||||
places: places, selectedCategory: selectedCategory, viewType: viewType,
|
||||
places: places,
|
||||
selectedCategory: selectedCategory,
|
||||
viewType: viewType,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other))
|
||||
return true;
|
||||
if (other.runtimeType != runtimeType)
|
||||
return false;
|
||||
if (identical(this, other)) return true;
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
final AppState otherAppState = other;
|
||||
return otherAppState.places == places
|
||||
&& otherAppState.selectedCategory == selectedCategory
|
||||
&& otherAppState.viewType == viewType;
|
||||
return otherAppState.places == places &&
|
||||
otherAppState.selectedCategory == selectedCategory &&
|
||||
otherAppState.viewType == viewType;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -17,7 +17,8 @@ class StubData {
|
||||
id: '2',
|
||||
latLng: LatLng(45.516887, -122.675417),
|
||||
name: 'Luc Lac Vietnamese Kitchen',
|
||||
description: 'Popular counter-serve offering pho, banh mi & other Vietnamese favorites in a stylish setting.',
|
||||
description:
|
||||
'Popular counter-serve offering pho, banh mi & other Vietnamese favorites in a stylish setting.',
|
||||
category: PlaceCategory.favorite,
|
||||
starRating: 5,
|
||||
),
|
||||
@@ -133,7 +134,8 @@ class StubData {
|
||||
id: '15',
|
||||
latLng: LatLng(45.485612, -122.784733),
|
||||
name: 'Uwajimaya Beaverton',
|
||||
description: 'Huge Asian grocery outpost stocking meats, produce & prepared foods plus gifts & home goods.',
|
||||
description:
|
||||
'Huge Asian grocery outpost stocking meats, produce & prepared foods plus gifts & home goods.',
|
||||
category: PlaceCategory.wantToGo,
|
||||
starRating: 5,
|
||||
),
|
||||
|
||||
11
place_tracker/test/widget_test.dart
Normal file
11
place_tracker/test/widget_test.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
// This is a basic Flutter widget test.
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter
|
||||
// provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to
|
||||
// find child widgets in the widget tree, read text, and verify that the values of widget properties
|
||||
// are correct.
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('This test always passes', (WidgetTester tester) async {});
|
||||
}
|
||||
@@ -4,8 +4,11 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
flutter:
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
assets:
|
||||
- assets/flutter-mark-square-64.png
|
||||
|
||||
11
platform_view_swift/test/widgets_test.dart
Normal file
11
platform_view_swift/test/widgets_test.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
// This is a basic Flutter widget test.
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter
|
||||
// provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to
|
||||
// find child widgets in the widget tree, read text, and verify that the values of widget properties
|
||||
// are correct.
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('This test always passes', (WidgetTester tester) async {});
|
||||
}
|
||||
@@ -4,6 +4,8 @@ declare -a PROJECT_NAMES=(
|
||||
"jsonexample" \
|
||||
"shrine" \
|
||||
"veggieseasons" \
|
||||
"place_tracker" \
|
||||
"platform_view_swift" \
|
||||
)
|
||||
|
||||
for PROJECT_NAME in "${PROJECT_NAMES[@]}"
|
||||
|
||||
Reference in New Issue
Block a user