ente/lib/ui/search_page.dart

170 lines
5.3 KiB
Dart
Raw Normal View History

2020-06-03 13:18:55 +00:00
import 'package:dio/dio.dart';
2020-04-05 08:31:01 +00:00
import 'package:flutter/material.dart';
2020-06-03 13:18:55 +00:00
import 'package:flutter_typeahead/flutter_typeahead.dart';
2020-05-01 18:20:12 +00:00
import 'package:photos/core/configuration.dart';
import 'package:photos/face_search_manager.dart';
import 'package:photos/models/face.dart';
2020-06-03 16:06:49 +00:00
import 'package:photos/models/location.dart';
2020-05-01 18:20:12 +00:00
import 'package:photos/ui/circular_network_image_widget.dart';
import 'package:photos/ui/face_search_results_page.dart';
2020-06-02 11:32:35 +00:00
import 'package:photos/ui/loading_widget.dart';
2020-06-03 14:11:34 +00:00
import 'package:photos/ui/location_search_results_page.dart';
2020-04-05 08:31:01 +00:00
2020-06-03 13:18:55 +00:00
class SearchPage extends StatefulWidget {
@override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
2020-04-05 14:00:44 +00:00
final FaceSearchManager _faceSearchManager = FaceSearchManager.instance;
2020-06-03 13:18:55 +00:00
String _searchString = "";
2020-04-05 08:31:01 +00:00
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
2020-06-03 13:18:55 +00:00
title: TypeAheadField(
textFieldConfiguration: TextFieldConfiguration(
autofocus: true,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Search your photos',
contentPadding: const EdgeInsets.all(0.0),
),
2020-04-05 08:31:01 +00:00
),
2020-06-03 13:18:55 +00:00
hideOnEmpty: true,
hideOnLoading: true,
loadingBuilder: (context) {
return loadWidget;
},
2020-06-03 16:06:49 +00:00
debounceDuration: Duration(milliseconds: 300),
2020-06-03 13:18:55 +00:00
suggestionsCallback: (pattern) async {
if (pattern.isEmpty) {
return null;
}
return (await Dio().get(
"https://maps.googleapis.com/maps/api/place/textsearch/json",
queryParameters: {
"query": pattern,
"key": "AIzaSyC9lAYIERrNFsCkdLxX6DmZfPhybTKod8U",
}))
.data["results"];
},
itemBuilder: (context, suggestion) {
return LocationSearchResultWidget(suggestion['name']);
},
onSuggestionSelected: (suggestion) {
2020-06-03 14:11:34 +00:00
Navigator.pop(context);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => LocationSearchResultsPage(
2020-06-03 16:06:49 +00:00
ViewPort(
Location(
suggestion['geometry']['viewport']['northeast']
['lat'],
suggestion['geometry']['viewport']['northeast']
['lng']),
Location(
suggestion['geometry']['viewport']['southwest']
['lat'],
suggestion['geometry']['viewport']['southwest']
['lng'])),
2020-06-03 14:11:34 +00:00
suggestion['name'],
)));
2020-06-03 13:18:55 +00:00
},
2020-04-05 08:31:01 +00:00
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () {},
)
],
),
2020-04-05 12:22:38 +00:00
body: Container(
2020-06-03 13:18:55 +00:00
child: _searchString.isEmpty ? _getSearchSuggestions() : Container(),
2020-04-05 12:22:38 +00:00
),
);
}
Widget _getSearchSuggestions() {
return FutureBuilder<List<Face>>(
future: _faceSearchManager.getFaces(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Container(
height: 60,
margin: EdgeInsets.only(top: 4, left: 4),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return _buildItem(context, snapshot.data[index]);
}),
);
2020-06-02 11:32:35 +00:00
} else if (snapshot.hasError) {
return Center(child: Text("Error: " + snapshot.error.toString()));
2020-04-05 12:22:38 +00:00
} else {
2020-06-02 11:32:35 +00:00
return Center(child: loadWidget);
2020-04-05 12:22:38 +00:00
}
},
2020-04-05 08:31:01 +00:00
);
}
2020-04-05 12:22:38 +00:00
Widget _buildItem(BuildContext context, Face face) {
2020-04-05 14:00:44 +00:00
return GestureDetector(
onTap: () {
_routeToSearchResults(face, context);
},
2020-06-02 14:24:37 +00:00
child: CircularNetworkImageWidget(
Configuration.instance.getHttpEndpoint() + "/" + face.thumbnailPath,
60),
2020-04-05 14:00:44 +00:00
);
}
void _routeToSearchResults(Face face, BuildContext context) {
2020-06-03 14:11:34 +00:00
final page = FaceSearchResultsPage(face);
Navigator.pop(context);
2020-04-05 14:00:44 +00:00
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return page;
},
),
);
2020-04-05 12:22:38 +00:00
}
2020-04-05 08:31:01 +00:00
}
2020-06-03 13:18:55 +00:00
class LocationSearchResultWidget extends StatelessWidget {
final String name;
const LocationSearchResultWidget(
this.name, {
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: new EdgeInsets.symmetric(vertical: 6.0, horizontal: 6.0),
margin: EdgeInsets.symmetric(vertical: 6.0),
child: Column(children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(
Icons.location_on,
),
Padding(padding: EdgeInsets.only(left: 20.0)),
Flexible(
child: Container(
child: Text(
name,
overflow: TextOverflow.clip,
),
),
),
],
),
]),
);
}
}