filter grid scaling: highlight
This commit is contained in:
parent
548d723223
commit
d21cd23ac8
19 changed files with 319 additions and 204 deletions
|
@ -1,9 +1,9 @@
|
||||||
|
import 'package:aves/image_providers/app_icon_image_provider.dart';
|
||||||
import 'package:aves/model/filters/filters.dart';
|
import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_icons.dart';
|
import 'package:aves/widgets/common/identity/aves_icons.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
|
||||||
import 'package:aves/image_providers/app_icon_image_provider.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
|
|
24
lib/model/highlight.dart
Normal file
24
lib/model/highlight.dart
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
class HighlightInfo extends ChangeNotifier {
|
||||||
|
final Queue<Object> _items = Queue();
|
||||||
|
|
||||||
|
void add(Object item) {
|
||||||
|
if (_items.contains(item)) return;
|
||||||
|
|
||||||
|
_items.addFirst(item);
|
||||||
|
while (_items.length > 5) {
|
||||||
|
_items.removeLast();
|
||||||
|
}
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(Object item) {
|
||||||
|
_items.removeWhere((element) => element == item);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(Object item) => _items.contains(item);
|
||||||
|
}
|
|
@ -18,7 +18,6 @@ class CollectionLens with ChangeNotifier, CollectionActivityMixin, CollectionSel
|
||||||
EntryGroupFactor groupFactor;
|
EntryGroupFactor groupFactor;
|
||||||
EntrySortFactor sortFactor;
|
EntrySortFactor sortFactor;
|
||||||
final AChangeNotifier filterChangeNotifier = AChangeNotifier();
|
final AChangeNotifier filterChangeNotifier = AChangeNotifier();
|
||||||
final StreamController<ImageEntry> _highlightController = StreamController.broadcast();
|
|
||||||
|
|
||||||
List<ImageEntry> _filteredEntries;
|
List<ImageEntry> _filteredEntries;
|
||||||
List<StreamSubscription> _subscriptions = [];
|
List<StreamSubscription> _subscriptions = [];
|
||||||
|
@ -70,10 +69,6 @@ class CollectionLens with ChangeNotifier, CollectionActivityMixin, CollectionSel
|
||||||
return _sortedEntries;
|
return _sortedEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<ImageEntry> get highlightStream => _highlightController.stream;
|
|
||||||
|
|
||||||
void highlight(ImageEntry entry) => _highlightController.add(entry);
|
|
||||||
|
|
||||||
bool get showHeaders {
|
bool get showHeaders {
|
||||||
if (sortFactor == EntrySortFactor.size) return false;
|
if (sortFactor == EntrySortFactor.size) return false;
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/main.dart';
|
import 'package:aves/main.dart';
|
||||||
|
import 'package:aves/model/actions/collection_actions.dart';
|
||||||
|
import 'package:aves/model/actions/entry_actions.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/model/source/enums.dart';
|
import 'package:aves/model/source/enums.dart';
|
||||||
import 'package:aves/services/app_shortcut_service.dart';
|
import 'package:aves/services/app_shortcut_service.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/model/actions/collection_actions.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/collection/filter_bar.dart';
|
|
||||||
import 'package:aves/widgets/dialogs/add_shortcut_dialog.dart';
|
|
||||||
import 'package:aves/widgets/collection/entry_set_action_delegate.dart';
|
import 'package:aves/widgets/collection/entry_set_action_delegate.dart';
|
||||||
|
import 'package:aves/widgets/collection/filter_bar.dart';
|
||||||
import 'package:aves/widgets/common/app_bar_subtitle.dart';
|
import 'package:aves/widgets/common/app_bar_subtitle.dart';
|
||||||
import 'package:aves/widgets/common/app_bar_title.dart';
|
import 'package:aves/widgets/common/app_bar_title.dart';
|
||||||
import 'package:aves/widgets/dialogs/aves_selection_dialog.dart';
|
|
||||||
import 'package:aves/model/actions/entry_actions.dart';
|
|
||||||
import 'package:aves/theme/icons.dart';
|
|
||||||
import 'package:aves/widgets/common/basic/menu_row.dart';
|
import 'package:aves/widgets/common/basic/menu_row.dart';
|
||||||
|
import 'package:aves/widgets/dialogs/add_shortcut_dialog.dart';
|
||||||
|
import 'package:aves/widgets/dialogs/aves_selection_dialog.dart';
|
||||||
import 'package:aves/widgets/search/search_button.dart';
|
import 'package:aves/widgets/search/search_button.dart';
|
||||||
import 'package:aves/widgets/search/search_delegate.dart';
|
import 'package:aves/widgets/search/search_delegate.dart';
|
||||||
import 'package:aves/widgets/stats/stats.dart';
|
import 'package:aves/widgets/stats/stats.dart';
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:aves/model/actions/collection_actions.dart';
|
||||||
|
import 'package:aves/model/actions/entry_actions.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/services/android_app_service.dart';
|
import 'package:aves/services/android_app_service.dart';
|
||||||
import 'package:aves/services/image_file_service.dart';
|
import 'package:aves/services/image_file_service.dart';
|
||||||
import 'package:aves/model/actions/collection_actions.dart';
|
|
||||||
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
||||||
import 'package:aves/widgets/common/action_mixins/permission_aware.dart';
|
import 'package:aves/widgets/common/action_mixins/permission_aware.dart';
|
||||||
import 'package:aves/widgets/common/action_mixins/size_aware.dart';
|
import 'package:aves/widgets/common/action_mixins/size_aware.dart';
|
||||||
import 'package:aves/widgets/dialogs/aves_dialog.dart';
|
import 'package:aves/widgets/dialogs/aves_dialog.dart';
|
||||||
import 'package:aves/model/actions/entry_actions.dart';
|
|
||||||
import 'package:aves/widgets/filter_grids/album_pick.dart';
|
import 'package:aves/widgets/filter_grids/album_pick.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
|
@ -3,12 +3,12 @@ import 'dart:math';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/model/source/enums.dart';
|
import 'package:aves/model/source/enums.dart';
|
||||||
|
import 'package:aves/theme/durations.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
|
||||||
import 'package:aves/widgets/collection/grid/header_album.dart';
|
import 'package:aves/widgets/collection/grid/header_album.dart';
|
||||||
import 'package:aves/widgets/collection/grid/header_date.dart';
|
import 'package:aves/widgets/collection/grid/header_date.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
|
@ -10,7 +10,7 @@ class DecoratedThumbnail extends StatelessWidget {
|
||||||
final double extent;
|
final double extent;
|
||||||
final CollectionLens collection;
|
final CollectionLens collection;
|
||||||
final ValueNotifier<bool> isScrollingNotifier;
|
final ValueNotifier<bool> isScrollingNotifier;
|
||||||
final bool showOverlay;
|
final bool selectable, highlightable;
|
||||||
final Object heroTag;
|
final Object heroTag;
|
||||||
|
|
||||||
static final Color borderColor = Colors.grey.shade700;
|
static final Color borderColor = Colors.grey.shade700;
|
||||||
|
@ -22,7 +22,8 @@ class DecoratedThumbnail extends StatelessWidget {
|
||||||
@required this.extent,
|
@required this.extent,
|
||||||
this.collection,
|
this.collection,
|
||||||
this.isScrollingNotifier,
|
this.isScrollingNotifier,
|
||||||
this.showOverlay = true,
|
this.selectable = true,
|
||||||
|
this.highlightable = true,
|
||||||
}) : heroTag = collection?.heroTag(entry),
|
}) : heroTag = collection?.heroTag(entry),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
|
@ -40,8 +41,9 @@ class DecoratedThumbnail extends StatelessWidget {
|
||||||
isScrollingNotifier: isScrollingNotifier,
|
isScrollingNotifier: isScrollingNotifier,
|
||||||
heroTag: heroTag,
|
heroTag: heroTag,
|
||||||
);
|
);
|
||||||
if (showOverlay) {
|
|
||||||
child = Stack(
|
child = Stack(
|
||||||
|
fit: StackFit.passthrough,
|
||||||
children: [
|
children: [
|
||||||
child,
|
child,
|
||||||
Positioned(
|
Positioned(
|
||||||
|
@ -52,17 +54,19 @@ class DecoratedThumbnail extends StatelessWidget {
|
||||||
extent: extent,
|
extent: extent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (selectable)
|
||||||
ThumbnailSelectionOverlay(
|
ThumbnailSelectionOverlay(
|
||||||
entry: entry,
|
entry: entry,
|
||||||
extent: extent,
|
extent: extent,
|
||||||
),
|
),
|
||||||
|
if (highlightable)
|
||||||
ThumbnailHighlightOverlay(
|
ThumbnailHighlightOverlay(
|
||||||
highlightedStream: collection.highlightStream.map((highlighted) => highlighted == entry),
|
entry: entry,
|
||||||
extent: extent,
|
extent: extent,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
|
||||||
return Container(
|
return Container(
|
||||||
foregroundDecoration: BoxDecoration(
|
foregroundDecoration: BoxDecoration(
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:aves/model/highlight.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
|
@ -116,13 +117,13 @@ class ThumbnailSelectionOverlay extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ThumbnailHighlightOverlay extends StatefulWidget {
|
class ThumbnailHighlightOverlay extends StatefulWidget {
|
||||||
|
final ImageEntry entry;
|
||||||
final double extent;
|
final double extent;
|
||||||
final Stream<bool> highlightedStream;
|
|
||||||
|
|
||||||
const ThumbnailHighlightOverlay({
|
const ThumbnailHighlightOverlay({
|
||||||
Key key,
|
Key key,
|
||||||
|
@required this.entry,
|
||||||
@required this.extent,
|
@required this.extent,
|
||||||
@required this.highlightedStream,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -132,12 +133,12 @@ class ThumbnailHighlightOverlay extends StatefulWidget {
|
||||||
class _ThumbnailHighlightOverlayState extends State<ThumbnailHighlightOverlay> {
|
class _ThumbnailHighlightOverlayState extends State<ThumbnailHighlightOverlay> {
|
||||||
final ValueNotifier<bool> _highlightedNotifier = ValueNotifier(false);
|
final ValueNotifier<bool> _highlightedNotifier = ValueNotifier(false);
|
||||||
|
|
||||||
|
ImageEntry get entry => widget.entry;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StreamBuilder<bool>(
|
final highlightInfo = context.watch<HighlightInfo>();
|
||||||
stream: widget.highlightedStream,
|
_highlightedNotifier.value = highlightInfo.contains(entry);
|
||||||
builder: (context, snapshot) {
|
|
||||||
_highlightedNotifier.value = snapshot.hasData && snapshot.data;
|
|
||||||
return Sweeper(
|
return Sweeper(
|
||||||
builder: (context) => Container(
|
builder: (context) => Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
@ -150,9 +151,7 @@ class _ThumbnailHighlightOverlayState extends State<ThumbnailHighlightOverlay> {
|
||||||
toggledNotifier: _highlightedNotifier,
|
toggledNotifier: _highlightedNotifier,
|
||||||
startAngle: pi * -3 / 4,
|
startAngle: pi * -3 / 4,
|
||||||
centerSweep: false,
|
centerSweep: false,
|
||||||
onSweepEnd: () => _highlightedNotifier.value = false,
|
onSweepEnd: () => highlightInfo.remove(entry),
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/model/filters/favourite.dart';
|
import 'package:aves/model/filters/favourite.dart';
|
||||||
import 'package:aves/model/filters/mime.dart';
|
import 'package:aves/model/filters/mime.dart';
|
||||||
|
import 'package:aves/model/highlight.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
|
@ -12,12 +13,13 @@ import 'package:aves/widgets/collection/app_bar.dart';
|
||||||
import 'package:aves/widgets/collection/empty.dart';
|
import 'package:aves/widgets/collection/empty.dart';
|
||||||
import 'package:aves/widgets/collection/grid/list_section_layout.dart';
|
import 'package:aves/widgets/collection/grid/list_section_layout.dart';
|
||||||
import 'package:aves/widgets/collection/grid/list_sliver.dart';
|
import 'package:aves/widgets/collection/grid/list_sliver.dart';
|
||||||
import 'package:aves/widgets/common/scaling.dart';
|
|
||||||
import 'package:aves/widgets/common/tile_extent_manager.dart';
|
|
||||||
import 'package:aves/widgets/collection/thumbnail/decorated.dart';
|
import 'package:aves/widgets/collection/thumbnail/decorated.dart';
|
||||||
import 'package:aves/widgets/common/behaviour/routes.dart';
|
import 'package:aves/widgets/common/behaviour/routes.dart';
|
||||||
import 'package:aves/widgets/common/behaviour/sloppy_scroll_physics.dart';
|
import 'package:aves/widgets/common/behaviour/sloppy_scroll_physics.dart';
|
||||||
import 'package:aves/widgets/common/identity/scroll_thumb.dart';
|
import 'package:aves/widgets/common/identity/scroll_thumb.dart';
|
||||||
|
import 'package:aves/widgets/common/providers/highlight_info_provider.dart';
|
||||||
|
import 'package:aves/widgets/common/scaling.dart';
|
||||||
|
import 'package:aves/widgets/common/tile_extent_manager.dart';
|
||||||
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
|
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
|
@ -35,7 +37,8 @@ class ThumbnailCollection extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SafeArea(
|
return HighlightInfoProvider(
|
||||||
|
child: SafeArea(
|
||||||
child: LayoutBuilder(
|
child: LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
final viewportSize = constraints.biggest;
|
final viewportSize = constraints.biggest;
|
||||||
|
@ -78,13 +81,14 @@ class ThumbnailCollection extends StatelessWidget {
|
||||||
scaledBuilder: (entry, extent) => DecoratedThumbnail(
|
scaledBuilder: (entry, extent) => DecoratedThumbnail(
|
||||||
entry: entry,
|
entry: entry,
|
||||||
extent: extent,
|
extent: extent,
|
||||||
showOverlay: false,
|
selectable: false,
|
||||||
|
highlightable: false,
|
||||||
),
|
),
|
||||||
getScaledItemTileRect: (context, entry) {
|
getScaledItemTileRect: (context, entry) {
|
||||||
final sectionedListLayout = Provider.of<SectionedListLayout>(context, listen: false);
|
final sectionedListLayout = Provider.of<SectionedListLayout>(context, listen: false);
|
||||||
return sectionedListLayout.getTileRect(entry) ?? Rect.zero;
|
return sectionedListLayout.getTileRect(entry) ?? Rect.zero;
|
||||||
},
|
},
|
||||||
onScaled: collection.highlight,
|
onScaled: (entry) => Provider.of<HighlightInfo>(context, listen: false).add(entry),
|
||||||
child: scrollView,
|
child: scrollView,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -109,6 +113,7 @@ class ThumbnailCollection extends StatelessWidget {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
lib/widgets/common/providers/highlight_info_provider.dart
Normal file
17
lib/widgets/common/providers/highlight_info_provider.dart
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import 'package:aves/model/highlight.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class HighlightInfoProvider extends StatelessWidget {
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const HighlightInfoProvider({@required this.child});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider<HighlightInfo>(
|
||||||
|
create: (context) => HighlightInfo(),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
|
|
|
@ -13,6 +13,7 @@ import 'package:aves/widgets/collection/thumbnail/raster.dart';
|
||||||
import 'package:aves/widgets/collection/thumbnail/vector.dart';
|
import 'package:aves/widgets/collection/thumbnail/vector.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/filter_grid_page.dart';
|
import 'package:aves/widgets/filter_grids/common/filter_grid_page.dart';
|
||||||
|
import 'package:aves/widgets/filter_grids/common/overlay.dart';
|
||||||
import 'package:decorated_icon/decorated_icon.dart';
|
import 'package:decorated_icon/decorated_icon.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ class DecoratedFilterChip extends StatelessWidget {
|
||||||
final CollectionFilter filter;
|
final CollectionFilter filter;
|
||||||
final ImageEntry entry;
|
final ImageEntry entry;
|
||||||
final double extent;
|
final double extent;
|
||||||
final bool pinned;
|
final bool pinned, highlightable;
|
||||||
final FilterCallback onTap;
|
final FilterCallback onTap;
|
||||||
final OffsetFilterCallback onLongPress;
|
final OffsetFilterCallback onLongPress;
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ class DecoratedFilterChip extends StatelessWidget {
|
||||||
@required this.entry,
|
@required this.entry,
|
||||||
@required this.extent,
|
@required this.extent,
|
||||||
this.pinned = false,
|
this.pinned = false,
|
||||||
|
this.highlightable = true,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.onLongPress,
|
this.onLongPress,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
@ -49,18 +51,34 @@ class DecoratedFilterChip extends StatelessWidget {
|
||||||
entry: entry,
|
entry: entry,
|
||||||
extent: extent,
|
extent: extent,
|
||||||
);
|
);
|
||||||
final borderRadius = min<double>(AvesFilterChip.defaultRadius, extent / 4);
|
final radius = min<double>(AvesFilterChip.defaultRadius, extent / 4);
|
||||||
final titlePadding = min<double>(6.0, extent / 16);
|
final titlePadding = min<double>(6.0, extent / 16);
|
||||||
return AvesFilterChip(
|
final borderRadius = BorderRadius.all(Radius.circular(radius));
|
||||||
|
Widget child = AvesFilterChip(
|
||||||
filter: filter,
|
filter: filter,
|
||||||
showGenericIcon: false,
|
showGenericIcon: false,
|
||||||
background: backgroundImage,
|
background: backgroundImage,
|
||||||
details: _buildDetails(filter),
|
details: _buildDetails(filter),
|
||||||
borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
|
borderRadius: borderRadius,
|
||||||
padding: titlePadding,
|
padding: titlePadding,
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
onLongPress: onLongPress,
|
onLongPress: onLongPress,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
child = Stack(
|
||||||
|
fit: StackFit.passthrough,
|
||||||
|
children: [
|
||||||
|
child,
|
||||||
|
if (highlightable)
|
||||||
|
ChipHighlightOverlay(
|
||||||
|
filter: filter,
|
||||||
|
extent: extent,
|
||||||
|
borderRadius: borderRadius,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDetails(CollectionFilter filter) {
|
Widget _buildDetails(CollectionFilter filter) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:aves/model/filters/filters.dart';
|
import 'package:aves/model/filters/filters.dart';
|
||||||
|
import 'package:aves/model/highlight.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
|
@ -9,6 +10,7 @@ import 'package:aves/widgets/common/behaviour/double_back_pop.dart';
|
||||||
import 'package:aves/widgets/common/behaviour/routes.dart';
|
import 'package:aves/widgets/common/behaviour/routes.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
import 'package:aves/widgets/common/identity/scroll_thumb.dart';
|
import 'package:aves/widgets/common/identity/scroll_thumb.dart';
|
||||||
|
import 'package:aves/widgets/common/providers/highlight_info_provider.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/common/scaling.dart';
|
import 'package:aves/widgets/common/scaling.dart';
|
||||||
import 'package:aves/widgets/common/tile_extent_manager.dart';
|
import 'package:aves/widgets/common/tile_extent_manager.dart';
|
||||||
|
@ -59,6 +61,7 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
||||||
return MediaQueryDataProvider(
|
return MediaQueryDataProvider(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
body: DoubleBackPopScope(
|
body: DoubleBackPopScope(
|
||||||
|
child: HighlightInfoProvider(
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: LayoutBuilder(
|
child: LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
|
@ -107,6 +110,7 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
||||||
entry: item.entry,
|
entry: item.entry,
|
||||||
extent: extent,
|
extent: extent,
|
||||||
pinned: settings.pinnedFilters.contains(filter),
|
pinned: settings.pinnedFilters.contains(filter),
|
||||||
|
highlightable: false,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -118,9 +122,7 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
||||||
final top = tileExtent * row + spacing * (row - 1);
|
final top = tileExtent * row + spacing * (row - 1);
|
||||||
return Rect.fromLTWH(left, top, tileExtent, tileExtent);
|
return Rect.fromLTWH(left, top, tileExtent, tileExtent);
|
||||||
},
|
},
|
||||||
onScaled: (item) {
|
onScaled: (item) => Provider.of<HighlightInfo>(context, listen: false).add(item.filter),
|
||||||
// TODO TLAD highlight scaled item
|
|
||||||
},
|
|
||||||
child: scrollView,
|
child: scrollView,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -131,6 +133,7 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
drawer: AppDrawer(
|
drawer: AppDrawer(
|
||||||
source: source,
|
source: source,
|
||||||
),
|
),
|
||||||
|
|
50
lib/widgets/filter_grids/common/overlay.dart
Normal file
50
lib/widgets/filter_grids/common/overlay.dart
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:aves/model/filters/filters.dart';
|
||||||
|
import 'package:aves/model/highlight.dart';
|
||||||
|
import 'package:aves/widgets/common/fx/sweeper.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ChipHighlightOverlay extends StatefulWidget {
|
||||||
|
final CollectionFilter filter;
|
||||||
|
final double extent;
|
||||||
|
final BorderRadius borderRadius;
|
||||||
|
|
||||||
|
const ChipHighlightOverlay({
|
||||||
|
Key key,
|
||||||
|
@required this.filter,
|
||||||
|
@required this.extent,
|
||||||
|
@required this.borderRadius,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_ChipHighlightOverlayState createState() => _ChipHighlightOverlayState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChipHighlightOverlayState extends State<ChipHighlightOverlay> {
|
||||||
|
final ValueNotifier<bool> _highlightedNotifier = ValueNotifier(false);
|
||||||
|
|
||||||
|
CollectionFilter get filter => widget.filter;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final highlightInfo = context.watch<HighlightInfo>();
|
||||||
|
_highlightedNotifier.value = highlightInfo.contains(filter);
|
||||||
|
return Sweeper(
|
||||||
|
builder: (context) => Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: Theme.of(context).accentColor,
|
||||||
|
width: widget.extent * .1,
|
||||||
|
),
|
||||||
|
borderRadius: widget.borderRadius,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
toggledNotifier: _highlightedNotifier,
|
||||||
|
startAngle: pi * -3 / 4,
|
||||||
|
centerSweep: false,
|
||||||
|
onSweepEnd: () => highlightInfo.remove(filter),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
|
import 'package:aves/image_providers/thumbnail_provider.dart';
|
||||||
|
import 'package:aves/image_providers/uri_picture_provider.dart';
|
||||||
import 'package:aves/main.dart';
|
import 'package:aves/main.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/image_providers/thumbnail_provider.dart';
|
|
||||||
import 'package:aves/image_providers/uri_picture_provider.dart';
|
|
||||||
import 'package:aves/widgets/fullscreen/debug/db.dart';
|
import 'package:aves/widgets/fullscreen/debug/db.dart';
|
||||||
import 'package:aves/widgets/fullscreen/debug/metadata.dart';
|
import 'package:aves/widgets/fullscreen/debug/metadata.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/common.dart';
|
import 'package:aves/widgets/fullscreen/info/common.dart';
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/services/android_app_service.dart';
|
import 'package:aves/services/android_app_service.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/widgets/common/fx/blurred.dart';
|
||||||
|
import 'package:aves/widgets/common/fx/borders.dart';
|
||||||
import 'package:aves/widgets/dialogs/aves_dialog.dart';
|
import 'package:aves/widgets/dialogs/aves_dialog.dart';
|
||||||
import 'package:aves/widgets/dialogs/aves_selection_dialog.dart';
|
import 'package:aves/widgets/dialogs/aves_selection_dialog.dart';
|
||||||
import 'package:aves/widgets/common/fx/borders.dart';
|
|
||||||
import 'package:aves/widgets/common/fx/blurred.dart';
|
|
||||||
import 'package:aves/theme/icons.dart';
|
|
||||||
import 'package:aves/widgets/fullscreen/info/location_section.dart';
|
import 'package:aves/widgets/fullscreen/info/location_section.dart';
|
||||||
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/services/metadata_service.dart';
|
|
||||||
import 'package:aves/ref/brand_colors.dart';
|
import 'package:aves/ref/brand_colors.dart';
|
||||||
|
import 'package:aves/services/metadata_service.dart';
|
||||||
|
import 'package:aves/theme/durations.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/utils/color_utils.dart';
|
import 'package:aves/utils/color_utils.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
|
||||||
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
|
||||||
import 'package:aves/widgets/fullscreen/info/common.dart';
|
import 'package:aves/widgets/fullscreen/info/common.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/metadata/metadata_thumbnail.dart';
|
import 'package:aves/widgets/fullscreen/info/metadata/metadata_thumbnail.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/metadata/xmp_tile.dart';
|
import 'package:aves/widgets/fullscreen/info/metadata/xmp_tile.dart';
|
||||||
|
|
|
@ -5,10 +5,10 @@ import 'package:aves/model/image_metadata.dart';
|
||||||
import 'package:aves/model/settings/coordinate_format.dart';
|
import 'package:aves/model/settings/coordinate_format.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/services/metadata_service.dart';
|
import 'package:aves/services/metadata_service.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/widgets/common/fx/blurred.dart';
|
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/utils/constants.dart';
|
||||||
|
import 'package:aves/widgets/common/fx/blurred.dart';
|
||||||
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
||||||
import 'package:decorated_icon/decorated_icon.dart';
|
import 'package:decorated_icon/decorated_icon.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
|
@ -8,12 +8,12 @@ import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/utils/color_utils.dart';
|
import 'package:aves/utils/color_utils.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/utils/mime_utils.dart';
|
import 'package:aves/utils/mime_utils.dart';
|
||||||
import 'package:aves/widgets/collection/collection_page.dart';
|
import 'package:aves/widgets/collection/collection_page.dart';
|
||||||
import 'package:aves/widgets/collection/empty.dart';
|
import 'package:aves/widgets/collection/empty.dart';
|
||||||
import 'package:aves/theme/icons.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/stats/filter_table.dart';
|
import 'package:aves/widgets/stats/filter_table.dart';
|
||||||
import 'package:charts_flutter/flutter.dart' as charts;
|
import 'package:charts_flutter/flutter.dart' as charts;
|
||||||
|
|
Loading…
Reference in a new issue