info: navigate by country
This commit is contained in:
parent
2e5a2e7c91
commit
77c9d86ea3
5 changed files with 99 additions and 57 deletions
|
@ -138,9 +138,9 @@ class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final tags = source.sortedTags;
|
|
||||||
final countries = source.sortedCountries;
|
final countries = source.sortedCountries;
|
||||||
|
final tags = source.sortedTags;
|
||||||
|
|
||||||
final drawerItems = [
|
final drawerItems = [
|
||||||
header,
|
header,
|
||||||
gifEntry,
|
gifEntry,
|
||||||
|
@ -175,28 +175,6 @@ class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (tags.isNotEmpty)
|
|
||||||
SafeArea(
|
|
||||||
top: false,
|
|
||||||
bottom: false,
|
|
||||||
child: ExpansionTile(
|
|
||||||
leading: const Icon(OMIcons.label),
|
|
||||||
title: Row(
|
|
||||||
children: [
|
|
||||||
const Text('Tags'),
|
|
||||||
const Spacer(),
|
|
||||||
Text(
|
|
||||||
'${tags.length}',
|
|
||||||
style: TextStyle(
|
|
||||||
color: (_tagsExpanded ? Theme.of(context).accentColor : Colors.white).withOpacity(.6),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onExpansionChanged: (expanded) => setState(() => _tagsExpanded = expanded),
|
|
||||||
children: tags.map(buildTagEntry).toList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (countries.isNotEmpty)
|
if (countries.isNotEmpty)
|
||||||
SafeArea(
|
SafeArea(
|
||||||
top: false,
|
top: false,
|
||||||
|
@ -219,6 +197,28 @@ class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
||||||
children: countries.map(buildCountryEntry).toList(),
|
children: countries.map(buildCountryEntry).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (tags.isNotEmpty)
|
||||||
|
SafeArea(
|
||||||
|
top: false,
|
||||||
|
bottom: false,
|
||||||
|
child: ExpansionTile(
|
||||||
|
leading: const Icon(OMIcons.label),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
const Text('Tags'),
|
||||||
|
const Spacer(),
|
||||||
|
Text(
|
||||||
|
'${tags.length}',
|
||||||
|
style: TextStyle(
|
||||||
|
color: (_tagsExpanded ? Theme.of(context).accentColor : Colors.white).withOpacity(.6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onExpansionChanged: (expanded) => setState(() => _tagsExpanded = expanded),
|
||||||
|
children: tags.map(buildTagEntry).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
return Drawer(
|
return Drawer(
|
||||||
|
|
|
@ -32,6 +32,8 @@ class InfoPageState extends State<InfoPage> {
|
||||||
ScrollController _scrollController = ScrollController();
|
ScrollController _scrollController = ScrollController();
|
||||||
bool _scrollStartFromTop = false;
|
bool _scrollStartFromTop = false;
|
||||||
|
|
||||||
|
CollectionLens get collection => widget.collection;
|
||||||
|
|
||||||
ImageEntry get entry => widget.entry;
|
ImageEntry get entry => widget.entry;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -68,6 +70,7 @@ class InfoPageState extends State<InfoPage> {
|
||||||
final locationAtTop = split && entry.hasGps;
|
final locationAtTop = split && entry.hasGps;
|
||||||
|
|
||||||
final locationSection = LocationSection(
|
final locationSection = LocationSection(
|
||||||
|
collection: collection,
|
||||||
entry: entry,
|
entry: entry,
|
||||||
showTitle: !locationAtTop,
|
showTitle: !locationAtTop,
|
||||||
visibleNotifier: widget.visibleNotifier,
|
visibleNotifier: widget.visibleNotifier,
|
||||||
|
@ -92,7 +95,7 @@ class InfoPageState extends State<InfoPage> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final tagSliver = XmpTagSectionSliver(
|
final tagSliver = XmpTagSectionSliver(
|
||||||
collection: widget.collection,
|
collection: collection,
|
||||||
entry: entry,
|
entry: entry,
|
||||||
);
|
);
|
||||||
final metadataSliver = MetadataSectionSliver(
|
final metadataSliver = MetadataSectionSliver(
|
||||||
|
|
|
@ -1,19 +1,25 @@
|
||||||
|
import 'package:aves/model/collection_filters.dart';
|
||||||
|
import 'package:aves/model/collection_lens.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/settings.dart';
|
import 'package:aves/model/settings.dart';
|
||||||
import 'package:aves/utils/android_app_service.dart';
|
import 'package:aves/utils/android_app_service.dart';
|
||||||
import 'package:aves/utils/geo_utils.dart';
|
import 'package:aves/utils/geo_utils.dart';
|
||||||
|
import 'package:aves/widgets/album/filtered_collection_page.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
||||||
|
import 'package:aves/widgets/fullscreen/info/navigation_button.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
import 'package:outline_material_icons/outline_material_icons.dart';
|
import 'package:outline_material_icons/outline_material_icons.dart';
|
||||||
|
|
||||||
class LocationSection extends StatefulWidget {
|
class LocationSection extends StatefulWidget {
|
||||||
|
final CollectionLens collection;
|
||||||
final ImageEntry entry;
|
final ImageEntry entry;
|
||||||
final bool showTitle;
|
final bool showTitle;
|
||||||
final ValueNotifier<bool> visibleNotifier;
|
final ValueNotifier<bool> visibleNotifier;
|
||||||
|
|
||||||
const LocationSection({
|
const LocationSection({
|
||||||
Key key,
|
Key key,
|
||||||
|
@required this.collection,
|
||||||
@required this.entry,
|
@required this.entry,
|
||||||
@required this.showTitle,
|
@required this.showTitle,
|
||||||
@required this.visibleNotifier,
|
@required this.visibleNotifier,
|
||||||
|
@ -26,6 +32,8 @@ class LocationSection extends StatefulWidget {
|
||||||
class _LocationSectionState extends State<LocationSection> {
|
class _LocationSectionState extends State<LocationSection> {
|
||||||
String _loadedUri;
|
String _loadedUri;
|
||||||
|
|
||||||
|
CollectionLens get collection => widget.collection;
|
||||||
|
|
||||||
ImageEntry get entry => widget.entry;
|
ImageEntry get entry => widget.entry;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -64,12 +72,14 @@ class _LocationSectionState extends State<LocationSection> {
|
||||||
final showMap = (_loadedUri == entry.uri) || (entry.hasGps && widget.visibleNotifier.value);
|
final showMap = (_loadedUri == entry.uri) || (entry.hasGps && widget.visibleNotifier.value);
|
||||||
if (showMap) {
|
if (showMap) {
|
||||||
_loadedUri = entry.uri;
|
_loadedUri = entry.uri;
|
||||||
String location;
|
String location = '';
|
||||||
if (entry.isLocated) {
|
if (entry.isLocated) {
|
||||||
location = entry.addressDetails.addressLine;
|
location = entry.addressDetails.addressLine;
|
||||||
} else if (entry.hasGps) {
|
} else if (entry.hasGps) {
|
||||||
location = toDMS(entry.latLng).join(', ');
|
location = toDMS(entry.latLng).join(', ');
|
||||||
}
|
}
|
||||||
|
final country = entry.addressDetails?.countryName ?? '';
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
@ -92,6 +102,19 @@ class _LocationSectionState extends State<LocationSection> {
|
||||||
padding: const EdgeInsets.only(top: 8),
|
padding: const EdgeInsets.only(top: 8),
|
||||||
child: InfoRowGroup({'Address': location}),
|
child: InfoRowGroup({'Address': location}),
|
||||||
),
|
),
|
||||||
|
if (country.isNotEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: NavigationButton.buttonBorderWidth / 2) + const EdgeInsets.only(top: 8),
|
||||||
|
child: Wrap(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
NavigationButton(
|
||||||
|
label: country,
|
||||||
|
onPressed: () => _goToCountry(context, country),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -101,6 +124,20 @@ class _LocationSectionState extends State<LocationSection> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleChange() => setState(() {});
|
void _handleChange() => setState(() {});
|
||||||
|
|
||||||
|
void _goToCountry(BuildContext context, String country) {
|
||||||
|
if (collection == null) return;
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => FilteredCollectionPage(
|
||||||
|
collection: collection,
|
||||||
|
filter: CountryFilter(country),
|
||||||
|
title: country,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImageMap extends StatefulWidget {
|
class ImageMap extends StatefulWidget {
|
||||||
|
|
29
lib/widgets/fullscreen/info/navigation_button.dart
Normal file
29
lib/widgets/fullscreen/info/navigation_button.dart
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import 'package:aves/utils/color_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class NavigationButton extends StatelessWidget {
|
||||||
|
final String label;
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
|
||||||
|
const NavigationButton({
|
||||||
|
@required this.label,
|
||||||
|
@required this.onPressed,
|
||||||
|
});
|
||||||
|
|
||||||
|
static const double buttonBorderWidth = 2;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return OutlineButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: stringToColor(label),
|
||||||
|
width: buttonBorderWidth,
|
||||||
|
),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(42),
|
||||||
|
),
|
||||||
|
child: Text(label),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
import 'package:aves/model/collection_filters.dart';
|
import 'package:aves/model/collection_filters.dart';
|
||||||
import 'package:aves/model/collection_lens.dart';
|
import 'package:aves/model/collection_lens.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/utils/color_utils.dart';
|
|
||||||
import 'package:aves/widgets/album/filtered_collection_page.dart';
|
import 'package:aves/widgets/album/filtered_collection_page.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
||||||
|
import 'package:aves/widgets/fullscreen/info/navigation_button.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class XmpTagSectionSliver extends AnimatedWidget {
|
class XmpTagSectionSliver extends AnimatedWidget {
|
||||||
|
@ -26,12 +26,12 @@ class XmpTagSectionSliver extends AnimatedWidget {
|
||||||
: [
|
: [
|
||||||
const SectionRow('Tags'),
|
const SectionRow('Tags'),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: TagButton.buttonBorderWidth / 2),
|
padding: const EdgeInsets.symmetric(horizontal: NavigationButton.buttonBorderWidth / 2),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: tags
|
children: tags
|
||||||
.map((tag) => TagButton(
|
.map((tag) => NavigationButton(
|
||||||
tag: tag,
|
label: tag,
|
||||||
onPressed: () => _goToTag(context, tag),
|
onPressed: () => _goToTag(context, tag),
|
||||||
))
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
|
@ -56,30 +56,3 @@ class XmpTagSectionSliver extends AnimatedWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TagButton extends StatelessWidget {
|
|
||||||
final String tag;
|
|
||||||
final VoidCallback onPressed;
|
|
||||||
|
|
||||||
const TagButton({
|
|
||||||
@required this.tag,
|
|
||||||
@required this.onPressed,
|
|
||||||
});
|
|
||||||
|
|
||||||
static const double buttonBorderWidth = 2;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return OutlineButton(
|
|
||||||
onPressed: onPressed,
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: stringToColor(tag),
|
|
||||||
width: buttonBorderWidth,
|
|
||||||
),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(42),
|
|
||||||
),
|
|
||||||
child: Text(tag),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue