info: added album filter chip
This commit is contained in:
parent
246e697d9d
commit
0199f9bd22
11 changed files with 166 additions and 159 deletions
|
@ -107,9 +107,7 @@ class _HomePageState extends State<HomePage> {
|
||||||
)
|
)
|
||||||
: MediaStoreCollectionProvider(
|
: MediaStoreCollectionProvider(
|
||||||
child: Consumer<CollectionLens>(
|
child: Consumer<CollectionLens>(
|
||||||
builder: (context, collection, child) => CollectionPage(
|
builder: (context, collection, child) => CollectionPage(collection),
|
||||||
collection: collection,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -32,25 +32,6 @@ class CollectionLens with ChangeNotifier {
|
||||||
onEntryAdded();
|
onEntryAdded();
|
||||||
}
|
}
|
||||||
|
|
||||||
factory CollectionLens.empty() {
|
|
||||||
return CollectionLens(
|
|
||||||
source: CollectionSource(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
factory CollectionLens.from(CollectionLens lens, CollectionFilter filter) {
|
|
||||||
if (lens == null) return null;
|
|
||||||
return CollectionLens(
|
|
||||||
source: lens.source,
|
|
||||||
filters: [
|
|
||||||
...lens.filters,
|
|
||||||
if (filter != null) filter,
|
|
||||||
],
|
|
||||||
groupFactor: lens.groupFactor,
|
|
||||||
sortFactor: lens.sortFactor,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_subscriptions
|
_subscriptions
|
||||||
|
@ -60,8 +41,28 @@ class CollectionLens with ChangeNotifier {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
factory CollectionLens.empty() {
|
||||||
|
return CollectionLens(
|
||||||
|
source: CollectionSource(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectionLens derive(CollectionFilter filter) {
|
||||||
|
return CollectionLens(
|
||||||
|
source: source,
|
||||||
|
filters: [
|
||||||
|
...filters,
|
||||||
|
if (filter != null) filter,
|
||||||
|
],
|
||||||
|
groupFactor: groupFactor,
|
||||||
|
sortFactor: sortFactor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
bool get isEmpty => _filteredEntries.isEmpty;
|
bool get isEmpty => _filteredEntries.isEmpty;
|
||||||
|
|
||||||
|
int get entryCount => _filteredEntries.length;
|
||||||
|
|
||||||
int get imageCount => _filteredEntries.where((entry) => !entry.isVideo).length;
|
int get imageCount => _filteredEntries.where((entry) => !entry.isVideo).length;
|
||||||
|
|
||||||
int get videoCount => _filteredEntries.where((entry) => entry.isVideo).length;
|
int get videoCount => _filteredEntries.where((entry) => entry.isVideo).length;
|
||||||
|
|
|
@ -278,13 +278,10 @@ class _FilteredCollectionNavTile extends StatelessWidget {
|
||||||
Navigator.pushAndRemoveUntil(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => CollectionPage(
|
builder: (context) => CollectionPage(CollectionLens(
|
||||||
collection: CollectionLens(
|
|
||||||
source: source,
|
source: source,
|
||||||
filters: [filter],
|
filters: [filter],
|
||||||
),
|
)),
|
||||||
title: title,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(route) => false,
|
(route) => false,
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,13 +12,8 @@ import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class CollectionPage extends StatelessWidget {
|
class CollectionPage extends StatelessWidget {
|
||||||
final CollectionLens collection;
|
final CollectionLens collection;
|
||||||
final String title;
|
|
||||||
|
|
||||||
const CollectionPage({
|
const CollectionPage(this.collection);
|
||||||
Key key,
|
|
||||||
@required this.collection,
|
|
||||||
this.title,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -30,7 +25,7 @@ class CollectionPage extends StatelessWidget {
|
||||||
appBar: collection.filters.isEmpty
|
appBar: collection.filters.isEmpty
|
||||||
? AllCollectionAppBar()
|
? AllCollectionAppBar()
|
||||||
: SliverAppBar(
|
: SliverAppBar(
|
||||||
title: Text(title),
|
title: const Text('Aves'),
|
||||||
actions: _buildActions(),
|
actions: _buildActions(),
|
||||||
bottom: FilterBar(collection.filters),
|
bottom: FilterBar(collection.filters),
|
||||||
floating: true,
|
floating: true,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:aves/model/collection_filters.dart';
|
import 'package:aves/model/collection_filters.dart';
|
||||||
import 'package:aves/utils/color_utils.dart';
|
import 'package:aves/widgets/common/aves_filter_chip.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/navigation_button.dart';
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -9,7 +8,6 @@ class FilterBar extends StatelessWidget implements PreferredSizeWidget {
|
||||||
|
|
||||||
final ScrollController _scrollController = ScrollController();
|
final ScrollController _scrollController = ScrollController();
|
||||||
|
|
||||||
static const double maxChipWidth = 160;
|
|
||||||
static const EdgeInsets padding = EdgeInsets.only(left: 8, right: 8, bottom: 8);
|
static const EdgeInsets padding = EdgeInsets.only(left: 8, right: 8, bottom: 8);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -38,44 +36,13 @@ class FilterBar extends StatelessWidget implements PreferredSizeWidget {
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
primary: false,
|
primary: false,
|
||||||
physics: const BouncingScrollPhysics(),
|
physics: const BouncingScrollPhysics(),
|
||||||
padding: EdgeInsets.all(NavigationButton.buttonBorderWidth / 2),
|
padding: const EdgeInsets.all(AvesFilterChip.buttonBorderWidth / 2),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (index >= filters.length) return null;
|
if (index >= filters.length) return null;
|
||||||
final filter = filters[index];
|
final filter = filters[index];
|
||||||
final icon = filter.icon;
|
return AvesFilterChip.fromFilter(
|
||||||
final label = filter.label;
|
filter,
|
||||||
return ConstrainedBox(
|
onPressed: (filter) {},
|
||||||
constraints: const BoxConstraints(maxWidth: maxChipWidth),
|
|
||||||
child: Tooltip(
|
|
||||||
message: label,
|
|
||||||
child: OutlineButton(
|
|
||||||
onPressed: () {},
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: stringToColor(label),
|
|
||||||
width: NavigationButton.buttonBorderWidth,
|
|
||||||
),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(42),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
if (icon != null) ...[
|
|
||||||
Icon(icon),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
],
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
label,
|
|
||||||
softWrap: false,
|
|
||||||
overflow: TextOverflow.fade,
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (context, index) => const SizedBox(width: 8),
|
separatorBuilder: (context, index) => const SizedBox(width: 8),
|
||||||
|
|
67
lib/widgets/common/aves_filter_chip.dart
Normal file
67
lib/widgets/common/aves_filter_chip.dart
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import 'package:aves/model/collection_filters.dart';
|
||||||
|
import 'package:aves/utils/color_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
typedef FilterCallback = void Function(CollectionFilter filter);
|
||||||
|
|
||||||
|
class AvesFilterChip extends StatelessWidget {
|
||||||
|
final String label;
|
||||||
|
final IconData icon;
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
|
||||||
|
const AvesFilterChip({
|
||||||
|
this.icon,
|
||||||
|
@required this.label,
|
||||||
|
@required this.onPressed,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory AvesFilterChip.fromFilter(
|
||||||
|
CollectionFilter filter, {
|
||||||
|
@required FilterCallback onPressed,
|
||||||
|
}) =>
|
||||||
|
AvesFilterChip(
|
||||||
|
icon: filter.icon,
|
||||||
|
label: filter.label,
|
||||||
|
onPressed: onPressed != null ? () => onPressed(filter) : null,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const double buttonBorderWidth = 2;
|
||||||
|
static const double maxChipWidth = 160;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: maxChipWidth),
|
||||||
|
child: Tooltip(
|
||||||
|
message: label,
|
||||||
|
child: OutlineButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: stringToColor(label),
|
||||||
|
width: buttonBorderWidth,
|
||||||
|
),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(42),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
if (icon != null) ...[
|
||||||
|
Icon(icon),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
],
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
softWrap: false,
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,19 @@
|
||||||
|
import 'package:aves/model/collection_filters.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/utils/file_utils.dart';
|
import 'package:aves/utils/file_utils.dart';
|
||||||
|
import 'package:aves/widgets/common/aves_filter_chip.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class BasicSection extends StatelessWidget {
|
class BasicSection extends StatelessWidget {
|
||||||
final ImageEntry entry;
|
final ImageEntry entry;
|
||||||
|
final FilterCallback onFilter;
|
||||||
|
|
||||||
const BasicSection({
|
const BasicSection({
|
||||||
Key key,
|
Key key,
|
||||||
@required this.entry,
|
@required this.entry,
|
||||||
|
@required this.onFilter,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -19,7 +23,11 @@ class BasicSection extends StatelessWidget {
|
||||||
final showMegaPixels = !entry.isVideo && !entry.isGif && entry.megaPixels != null && entry.megaPixels > 0;
|
final showMegaPixels = !entry.isVideo && !entry.isGif && entry.megaPixels != null && entry.megaPixels > 0;
|
||||||
final resolutionText = '${entry.width ?? '?'} × ${entry.height ?? '?'}${showMegaPixels ? ' (${entry.megaPixels} MP)' : ''}';
|
final resolutionText = '${entry.width ?? '?'} × ${entry.height ?? '?'}${showMegaPixels ? ' (${entry.megaPixels} MP)' : ''}';
|
||||||
|
|
||||||
return InfoRowGroup({
|
final filter = entry.directory != null ? AlbumFilter(entry.directory) : null;
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
InfoRowGroup({
|
||||||
'Title': entry.title ?? '?',
|
'Title': entry.title ?? '?',
|
||||||
'Date': dateText,
|
'Date': dateText,
|
||||||
if (entry.isVideo) ..._buildVideoRows(),
|
if (entry.isVideo) ..._buildVideoRows(),
|
||||||
|
@ -27,7 +35,16 @@ class BasicSection extends StatelessWidget {
|
||||||
'Size': entry.sizeBytes != null ? formatFilesize(entry.sizeBytes) : '?',
|
'Size': entry.sizeBytes != null ? formatFilesize(entry.sizeBytes) : '?',
|
||||||
'URI': entry.uri ?? '?',
|
'URI': entry.uri ?? '?',
|
||||||
if (entry.path != null) 'Path': entry.path,
|
if (entry.path != null) 'Path': entry.path,
|
||||||
});
|
}),
|
||||||
|
if (filter != null) ...[
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
AvesFilterChip.fromFilter(
|
||||||
|
filter,
|
||||||
|
onPressed: onFilter,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> _buildVideoRows() {
|
Map<String, String> _buildVideoRows() {
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
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/widgets/album/collection_page.dart';
|
||||||
|
import 'package:aves/widgets/common/aves_filter_chip.dart';
|
||||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/basic_section.dart';
|
import 'package:aves/widgets/fullscreen/info/basic_section.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/location_section.dart';
|
import 'package:aves/widgets/fullscreen/info/location_section.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/metadata_section.dart';
|
import 'package:aves/widgets/fullscreen/info/metadata_section.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/navigation_button.dart';
|
|
||||||
import 'package:aves/widgets/fullscreen/info/xmp_section.dart';
|
import 'package:aves/widgets/fullscreen/info/xmp_section.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
@ -74,13 +76,14 @@ class InfoPageState extends State<InfoPage> {
|
||||||
entry: entry,
|
entry: entry,
|
||||||
showTitle: !locationAtTop,
|
showTitle: !locationAtTop,
|
||||||
visibleNotifier: widget.visibleNotifier,
|
visibleNotifier: widget.visibleNotifier,
|
||||||
|
onFilter: _goToFilteredCollection,
|
||||||
);
|
);
|
||||||
final basicAndLocationSliver = locationAtTop
|
final basicAndLocationSliver = locationAtTop
|
||||||
? SliverToBoxAdapter(
|
? SliverToBoxAdapter(
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: BasicSection(entry: entry)),
|
Expanded(child: BasicSection(entry: entry, onFilter: _goToFilteredCollection)),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(child: locationSection),
|
Expanded(child: locationSection),
|
||||||
],
|
],
|
||||||
|
@ -89,7 +92,7 @@ class InfoPageState extends State<InfoPage> {
|
||||||
: SliverList(
|
: SliverList(
|
||||||
delegate: SliverChildListDelegate.fixed(
|
delegate: SliverChildListDelegate.fixed(
|
||||||
[
|
[
|
||||||
BasicSection(entry: entry),
|
BasicSection(entry: entry, onFilter: _goToFilteredCollection),
|
||||||
locationSection,
|
locationSection,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -97,6 +100,7 @@ class InfoPageState extends State<InfoPage> {
|
||||||
final tagSliver = XmpTagSectionSliver(
|
final tagSliver = XmpTagSectionSliver(
|
||||||
collection: collection,
|
collection: collection,
|
||||||
entry: entry,
|
entry: entry,
|
||||||
|
onFilter: _goToFilteredCollection,
|
||||||
);
|
);
|
||||||
final metadataSliver = MetadataSectionSliver(
|
final metadataSliver = MetadataSectionSliver(
|
||||||
entry: entry,
|
entry: entry,
|
||||||
|
@ -158,6 +162,16 @@ class InfoPageState extends State<InfoPage> {
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _goToFilteredCollection(CollectionFilter filter) {
|
||||||
|
if (collection == null) return;
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => CollectionPage(collection.derive(filter)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SectionRow extends StatelessWidget {
|
class SectionRow extends StatelessWidget {
|
||||||
|
@ -171,7 +185,7 @@ class SectionRow extends StatelessWidget {
|
||||||
final buildDivider = () => const SizedBox(
|
final buildDivider = () => const SizedBox(
|
||||||
width: dim,
|
width: dim,
|
||||||
child: Divider(
|
child: Divider(
|
||||||
thickness: NavigationButton.buttonBorderWidth,
|
thickness: AvesFilterChip.buttonBorderWidth,
|
||||||
color: Colors.white70,
|
color: Colors.white70,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,9 +4,8 @@ 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/collection_page.dart';
|
import 'package:aves/widgets/common/aves_filter_chip.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';
|
||||||
|
@ -16,6 +15,7 @@ class LocationSection extends StatefulWidget {
|
||||||
final ImageEntry entry;
|
final ImageEntry entry;
|
||||||
final bool showTitle;
|
final bool showTitle;
|
||||||
final ValueNotifier<bool> visibleNotifier;
|
final ValueNotifier<bool> visibleNotifier;
|
||||||
|
final FilterCallback onFilter;
|
||||||
|
|
||||||
const LocationSection({
|
const LocationSection({
|
||||||
Key key,
|
Key key,
|
||||||
|
@ -23,6 +23,7 @@ class LocationSection extends StatefulWidget {
|
||||||
@required this.entry,
|
@required this.entry,
|
||||||
@required this.showTitle,
|
@required this.showTitle,
|
||||||
@required this.visibleNotifier,
|
@required this.visibleNotifier,
|
||||||
|
@required this.onFilter,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -78,7 +79,10 @@ class _LocationSectionState extends State<LocationSection> {
|
||||||
} else if (entry.hasGps) {
|
} else if (entry.hasGps) {
|
||||||
location = toDMS(entry.latLng).join(', ');
|
location = toDMS(entry.latLng).join(', ');
|
||||||
}
|
}
|
||||||
final country = entry.addressDetails?.countryName ?? '';
|
final country = entry.addressDetails?.countryName;
|
||||||
|
final filters = [
|
||||||
|
if (country != null) CountryFilter(country),
|
||||||
|
];
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -102,17 +106,17 @@ 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)
|
if (filters.isNotEmpty)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: NavigationButton.buttonBorderWidth / 2) + const EdgeInsets.only(top: 8),
|
padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.buttonBorderWidth / 2) + const EdgeInsets.only(top: 8),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: filters
|
||||||
NavigationButton(
|
.map((filter) => AvesFilterChip.fromFilter(
|
||||||
label: country,
|
filter,
|
||||||
onPressed: () => _goToCountry(context, country),
|
onPressed: widget.onFilter,
|
||||||
),
|
))
|
||||||
],
|
.toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -124,19 +128,6 @@ 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) => CollectionPage(
|
|
||||||
collection: CollectionLens.from(collection, CountryFilter(country)),
|
|
||||||
title: country,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImageMap extends StatefulWidget {
|
class ImageMap extends StatefulWidget {
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
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,8 @@
|
||||||
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/widgets/album/collection_page.dart';
|
import 'package:aves/widgets/common/aves_filter_chip.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:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:outline_material_icons/outline_material_icons.dart';
|
import 'package:outline_material_icons/outline_material_icons.dart';
|
||||||
|
@ -11,11 +10,13 @@ import 'package:outline_material_icons/outline_material_icons.dart';
|
||||||
class XmpTagSectionSliver extends AnimatedWidget {
|
class XmpTagSectionSliver extends AnimatedWidget {
|
||||||
final CollectionLens collection;
|
final CollectionLens collection;
|
||||||
final ImageEntry entry;
|
final ImageEntry entry;
|
||||||
|
final FilterCallback onFilter;
|
||||||
|
|
||||||
XmpTagSectionSliver({
|
XmpTagSectionSliver({
|
||||||
Key key,
|
Key key,
|
||||||
@required this.collection,
|
@required this.collection,
|
||||||
@required this.entry,
|
@required this.entry,
|
||||||
|
@required this.onFilter,
|
||||||
}) : super(key: key, listenable: entry.metadataChangeNotifier);
|
}) : super(key: key, listenable: entry.metadataChangeNotifier);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -28,13 +29,14 @@ class XmpTagSectionSliver extends AnimatedWidget {
|
||||||
: [
|
: [
|
||||||
const SectionRow(OMIcons.localOffer),
|
const SectionRow(OMIcons.localOffer),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: NavigationButton.buttonBorderWidth / 2),
|
padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.buttonBorderWidth / 2),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: tags
|
children: tags
|
||||||
.map((tag) => NavigationButton(
|
.map((tag) => TagFilter(tag))
|
||||||
label: tag,
|
.map((filter) => AvesFilterChip.fromFilter(
|
||||||
onPressed: () => _goToTag(context, tag),
|
filter,
|
||||||
|
onPressed: onFilter,
|
||||||
))
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
),
|
),
|
||||||
|
@ -43,17 +45,4 @@ class XmpTagSectionSliver extends AnimatedWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _goToTag(BuildContext context, String tag) {
|
|
||||||
if (collection == null) return;
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => CollectionPage(
|
|
||||||
collection: CollectionLens.from(collection, TagFilter(tag)),
|
|
||||||
title: tag,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue