shortcut to search page
This commit is contained in:
parent
9da57961fc
commit
af9edebf86
12 changed files with 389 additions and 68 deletions
|
@ -87,21 +87,21 @@ public class MainActivity extends FlutterActivity {
|
|||
private void setupShortcuts() {
|
||||
ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
|
||||
|
||||
Intent searchIntent = new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class);
|
||||
searchIntent.putExtra("page", "search");
|
||||
// do not use 'route' as extra key, as the Flutter framework acts on it
|
||||
|
||||
ShortcutInfo search = new ShortcutInfo.Builder(this, "search")
|
||||
.setShortLabel(getString(R.string.search_shortcut_short_label))
|
||||
.setIcon(Icon.createWithResource(this, R.drawable.ic_outline_search))
|
||||
.setIntent(searchIntent)
|
||||
.setIntent(new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class)
|
||||
.putExtra("page", "/search"))
|
||||
.build();
|
||||
|
||||
Intent videosIntent = new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class);
|
||||
videosIntent.putExtra("page", "collection");
|
||||
videosIntent.putExtra("filters", new String[]{"anyVideo"});
|
||||
ShortcutInfo videos = new ShortcutInfo.Builder(this, "videos")
|
||||
.setShortLabel(getString(R.string.videos_shortcut_short_label))
|
||||
.setIcon(Icon.createWithResource(this, R.drawable.ic_outline_movie))
|
||||
.setIntent(videosIntent)
|
||||
.setIntent(new Intent(Intent.ACTION_MAIN, null, this, MainActivity.class)
|
||||
.putExtra("page", "/collection")
|
||||
.putExtra("filters", new String[]{"anyVideo"}))
|
||||
.build();
|
||||
shortcutManager.setDynamicShortcuts(Arrays.asList(videos, search));
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:aves/widgets/collection/collection_page.dart';
|
||||
import 'package:aves/widgets/filter_grids/albums_page.dart';
|
||||
|
||||
enum HomePageSetting { collection, albums, search }
|
||||
enum HomePageSetting { collection, albums }
|
||||
|
||||
extension ExtraHomePageSetting on HomePageSetting {
|
||||
String get name {
|
||||
|
@ -10,8 +10,6 @@ extension ExtraHomePageSetting on HomePageSetting {
|
|||
return 'Collection';
|
||||
case HomePageSetting.albums:
|
||||
return 'Albums';
|
||||
case HomePageSetting.search:
|
||||
return 'Search';
|
||||
default:
|
||||
return toString();
|
||||
}
|
||||
|
|
|
@ -295,7 +295,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
collection.clearSelection();
|
||||
break;
|
||||
case CollectionAction.stats:
|
||||
unawaited(_goToStats());
|
||||
_goToStats();
|
||||
break;
|
||||
case CollectionAction.group:
|
||||
final value = await showDialog<EntryGroupFactor>(
|
||||
|
@ -338,14 +338,18 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
}
|
||||
|
||||
void _goToSearch() {
|
||||
showSearch(
|
||||
context: context,
|
||||
delegate: ImageSearchDelegate(collection.source, collection.addFilter),
|
||||
);
|
||||
Navigator.push(
|
||||
context,
|
||||
SearchPageRoute(
|
||||
delegate: ImageSearchDelegate(
|
||||
source: collection.source,
|
||||
parentCollection: collection,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Future<void> _goToStats() {
|
||||
return Navigator.push(
|
||||
void _goToStats() {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
settings: RouteSettings(name: StatsPage.routeName),
|
||||
|
|
|
@ -6,40 +6,46 @@ import 'package:aves/model/filters/mime.dart';
|
|||
import 'package:aves/model/filters/query.dart';
|
||||
import 'package:aves/model/filters/tag.dart';
|
||||
import 'package:aves/model/mime_types.dart';
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/model/source/album.dart';
|
||||
import 'package:aves/model/source/collection_lens.dart';
|
||||
import 'package:aves/model/source/collection_source.dart';
|
||||
import 'package:aves/model/source/location.dart';
|
||||
import 'package:aves/model/source/tag.dart';
|
||||
import 'package:aves/widgets/collection/collection_page.dart';
|
||||
import 'package:aves/widgets/collection/search/expandable_filter_row.dart';
|
||||
import 'package:aves/widgets/collection/search_page.dart';
|
||||
import 'package:aves/widgets/common/aves_filter_chip.dart';
|
||||
import 'package:aves/widgets/common/icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class ImageSearchDelegate extends SearchDelegate<CollectionFilter> {
|
||||
class ImageSearchDelegate {
|
||||
final CollectionSource source;
|
||||
final ValueNotifier<String> expandedSectionNotifier = ValueNotifier(null);
|
||||
final FilterCallback onSelection;
|
||||
final CollectionLens parentCollection;
|
||||
|
||||
ImageSearchDelegate(this.source, this.onSelection);
|
||||
ImageSearchDelegate({@required this.source, this.parentCollection});
|
||||
|
||||
@override
|
||||
ThemeData appBarTheme(BuildContext context) {
|
||||
return Theme.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildLeading(BuildContext context) {
|
||||
return IconButton(
|
||||
icon: AnimatedIcon(
|
||||
icon: AnimatedIcons.menu_arrow,
|
||||
progress: transitionAnimation,
|
||||
),
|
||||
onPressed: () => _select(context, null),
|
||||
tooltip: 'Back',
|
||||
);
|
||||
return Navigator.canPop(context)
|
||||
? IconButton(
|
||||
icon: AnimatedIcon(
|
||||
icon: AnimatedIcons.menu_arrow,
|
||||
progress: transitionAnimation,
|
||||
),
|
||||
onPressed: () => _goBack(context),
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
)
|
||||
: CloseButton(
|
||||
onPressed: SystemNavigator.pop,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Widget> buildActions(BuildContext context) {
|
||||
return [
|
||||
if (query.isNotEmpty)
|
||||
|
@ -54,7 +60,6 @@ class ImageSearchDelegate extends SearchDelegate<CollectionFilter> {
|
|||
];
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildSuggestions(BuildContext context) {
|
||||
final upQuery = query.trim().toUpperCase();
|
||||
bool containQuery(String s) => s.toUpperCase().contains(upQuery);
|
||||
|
@ -137,7 +142,6 @@ class ImageSearchDelegate extends SearchDelegate<CollectionFilter> {
|
|||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildResults(BuildContext context) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// `buildResults` is called in the build phase,
|
||||
|
@ -154,14 +158,160 @@ class ImageSearchDelegate extends SearchDelegate<CollectionFilter> {
|
|||
}
|
||||
|
||||
void _select(BuildContext context, CollectionFilter filter) {
|
||||
if (parentCollection != null) {
|
||||
_applyToParentCollectionPage(context, filter);
|
||||
} else {
|
||||
_goToCollectionPage(context, filter);
|
||||
}
|
||||
}
|
||||
|
||||
void _applyToParentCollectionPage(BuildContext context, CollectionFilter filter) {
|
||||
if (filter != null) {
|
||||
onSelection(filter);
|
||||
parentCollection.addFilter(filter);
|
||||
}
|
||||
// we post closing the search page after applying the filter selection
|
||||
// so that hero animation target is ready in the `FilterBar`,
|
||||
// even when the target is a child of an `AnimatedList`
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
close(context, null);
|
||||
_goBack(context);
|
||||
});
|
||||
}
|
||||
|
||||
void _goBack(BuildContext context) {
|
||||
_clean();
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
void _goToCollectionPage(BuildContext context, CollectionFilter filter) {
|
||||
_clean();
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
settings: RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(CollectionLens(
|
||||
source: source,
|
||||
filters: [filter],
|
||||
groupFactor: settings.collectionGroupFactor,
|
||||
sortFactor: settings.collectionSortFactor,
|
||||
)),
|
||||
),
|
||||
settings.navRemoveRoutePredicate(CollectionPage.routeName),
|
||||
);
|
||||
}
|
||||
|
||||
void _clean() {
|
||||
currentBody = null;
|
||||
focusNode?.unfocus();
|
||||
}
|
||||
|
||||
// adapted from `SearchDelegate`
|
||||
|
||||
void showResults(BuildContext context) {
|
||||
focusNode?.unfocus();
|
||||
currentBody = SearchBody.results;
|
||||
}
|
||||
|
||||
void showSuggestions(BuildContext context) {
|
||||
assert(focusNode != null, '_focusNode must be set by route before showSuggestions is called.');
|
||||
focusNode.requestFocus();
|
||||
currentBody = SearchBody.suggestions;
|
||||
}
|
||||
|
||||
Animation<double> get transitionAnimation => proxyAnimation;
|
||||
|
||||
FocusNode focusNode;
|
||||
|
||||
final TextEditingController queryTextController = TextEditingController();
|
||||
|
||||
final ProxyAnimation proxyAnimation = ProxyAnimation(kAlwaysDismissedAnimation);
|
||||
|
||||
String get query => queryTextController.text;
|
||||
|
||||
set query(String value) {
|
||||
assert(query != null);
|
||||
queryTextController.text = value;
|
||||
}
|
||||
|
||||
final ValueNotifier<SearchBody> currentBodyNotifier = ValueNotifier<SearchBody>(null);
|
||||
|
||||
SearchBody get currentBody => currentBodyNotifier.value;
|
||||
|
||||
set currentBody(SearchBody value) {
|
||||
currentBodyNotifier.value = value;
|
||||
}
|
||||
|
||||
SearchPageRoute route;
|
||||
}
|
||||
|
||||
// adapted from `SearchDelegate`
|
||||
enum SearchBody { suggestions, results }
|
||||
|
||||
// adapted from `SearchDelegate`
|
||||
class SearchPageRoute<T> extends PageRoute<T> {
|
||||
SearchPageRoute({
|
||||
@required this.delegate,
|
||||
}) : assert(delegate != null),
|
||||
super(settings: RouteSettings(name: SearchPage.routeName)) {
|
||||
assert(
|
||||
delegate.route == null,
|
||||
'The ${delegate.runtimeType} instance is currently used by another active '
|
||||
'search. Please close that search by calling close() on the SearchDelegate '
|
||||
'before openening another search with the same delegate instance.',
|
||||
);
|
||||
delegate.route = this;
|
||||
}
|
||||
|
||||
final ImageSearchDelegate delegate;
|
||||
|
||||
@override
|
||||
Color get barrierColor => null;
|
||||
|
||||
@override
|
||||
String get barrierLabel => null;
|
||||
|
||||
@override
|
||||
Duration get transitionDuration => const Duration(milliseconds: 300);
|
||||
|
||||
@override
|
||||
bool get maintainState => false;
|
||||
|
||||
@override
|
||||
Widget buildTransitions(
|
||||
BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
Widget child,
|
||||
) {
|
||||
return FadeTransition(
|
||||
opacity: animation,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Animation<double> createAnimation() {
|
||||
final animation = super.createAnimation();
|
||||
delegate.proxyAnimation.parent = animation;
|
||||
return animation;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildPage(
|
||||
BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
) {
|
||||
return SearchPage(
|
||||
delegate: delegate,
|
||||
animation: animation,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void didComplete(T result) {
|
||||
super.didComplete(result);
|
||||
assert(delegate.route == this);
|
||||
delegate.route = null;
|
||||
delegate.currentBody = null;
|
||||
}
|
||||
}
|
||||
|
|
127
lib/widgets/collection/search_page.dart
Normal file
127
lib/widgets/collection/search_page.dart
Normal file
|
@ -0,0 +1,127 @@
|
|||
import 'package:aves/widgets/collection/search/search_delegate.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SearchPage extends StatefulWidget {
|
||||
static const routeName = '/search';
|
||||
|
||||
final ImageSearchDelegate delegate;
|
||||
final Animation<double> animation;
|
||||
|
||||
const SearchPage({
|
||||
this.delegate,
|
||||
this.animation,
|
||||
});
|
||||
|
||||
@override
|
||||
_SearchPageState createState() => _SearchPageState();
|
||||
}
|
||||
|
||||
class _SearchPageState extends State<SearchPage> {
|
||||
FocusNode focusNode = FocusNode();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.delegate.queryTextController.addListener(_onQueryChanged);
|
||||
widget.animation.addStatusListener(_onAnimationStatusChanged);
|
||||
widget.delegate.currentBodyNotifier.addListener(_onSearchBodyChanged);
|
||||
focusNode.addListener(_onFocusChanged);
|
||||
widget.delegate.focusNode = focusNode;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
widget.delegate.queryTextController.removeListener(_onQueryChanged);
|
||||
widget.animation.removeStatusListener(_onAnimationStatusChanged);
|
||||
widget.delegate.currentBodyNotifier.removeListener(_onSearchBodyChanged);
|
||||
widget.delegate.focusNode = null;
|
||||
focusNode.dispose();
|
||||
}
|
||||
|
||||
void _onAnimationStatusChanged(AnimationStatus status) {
|
||||
if (status != AnimationStatus.completed) {
|
||||
return;
|
||||
}
|
||||
widget.animation.removeStatusListener(_onAnimationStatusChanged);
|
||||
focusNode.requestFocus();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(SearchPage oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.delegate != oldWidget.delegate) {
|
||||
oldWidget.delegate.queryTextController.removeListener(_onQueryChanged);
|
||||
widget.delegate.queryTextController.addListener(_onQueryChanged);
|
||||
oldWidget.delegate.currentBodyNotifier.removeListener(_onSearchBodyChanged);
|
||||
widget.delegate.currentBodyNotifier.addListener(_onSearchBodyChanged);
|
||||
oldWidget.delegate.focusNode = null;
|
||||
widget.delegate.focusNode = focusNode;
|
||||
}
|
||||
}
|
||||
|
||||
void _onFocusChanged() {
|
||||
if (focusNode.hasFocus && widget.delegate.currentBody != SearchBody.suggestions) {
|
||||
widget.delegate.showSuggestions(context);
|
||||
}
|
||||
}
|
||||
|
||||
void _onQueryChanged() {
|
||||
setState(() {
|
||||
// rebuild ourselves because query changed.
|
||||
});
|
||||
}
|
||||
|
||||
void _onSearchBodyChanged() {
|
||||
setState(() {
|
||||
// rebuild ourselves because search body changed.
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = widget.delegate.appBarTheme(context);
|
||||
Widget body;
|
||||
switch (widget.delegate.currentBody) {
|
||||
case SearchBody.suggestions:
|
||||
body = KeyedSubtree(
|
||||
key: ValueKey<SearchBody>(SearchBody.suggestions),
|
||||
child: widget.delegate.buildSuggestions(context),
|
||||
);
|
||||
break;
|
||||
case SearchBody.results:
|
||||
body = KeyedSubtree(
|
||||
key: ValueKey<SearchBody>(SearchBody.results),
|
||||
child: widget.delegate.buildResults(context),
|
||||
);
|
||||
break;
|
||||
}
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: theme.primaryColor,
|
||||
iconTheme: theme.primaryIconTheme,
|
||||
textTheme: theme.primaryTextTheme,
|
||||
brightness: theme.primaryColorBrightness,
|
||||
leading: widget.delegate.buildLeading(context),
|
||||
title: TextField(
|
||||
controller: widget.delegate.queryTextController,
|
||||
focusNode: focusNode,
|
||||
style: theme.textTheme.headline6,
|
||||
textInputAction: TextInputAction.search,
|
||||
onSubmitted: (_) => widget.delegate.showResults(context),
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText: MaterialLocalizations.of(context).searchFieldLabel,
|
||||
hintStyle: theme.inputDecorationTheme.hintStyle,
|
||||
),
|
||||
),
|
||||
actions: widget.delegate.buildActions(context),
|
||||
),
|
||||
body: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: body,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/model/source/collection_lens.dart';
|
||||
import 'package:aves/services/android_app_service.dart';
|
||||
|
@ -12,6 +10,7 @@ import 'package:aves/widgets/common/entry_actions.dart';
|
|||
import 'package:aves/widgets/common/image_providers/uri_image_provider.dart';
|
||||
import 'package:aves/widgets/fullscreen/debug.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:pdf/pdf.dart';
|
||||
import 'package:pdf/widgets.dart' as pdf;
|
||||
|
@ -154,7 +153,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin {
|
|||
}
|
||||
} else {
|
||||
// leave viewer
|
||||
exit(0);
|
||||
unawaited(SystemNavigator.pop());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'package:aves/widgets/common/aves_selection_dialog.dart';
|
|||
import 'package:aves/widgets/common/icons.dart';
|
||||
import 'package:aves/widgets/common/menu_row.dart';
|
||||
import 'package:aves/widgets/filter_grids/filter_grid_page.dart';
|
||||
import 'package:aves/widgets/filter_grids/search_button.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
@ -36,7 +37,7 @@ class AlbumListPage extends StatelessWidget {
|
|||
return FilterNavigationPage(
|
||||
source: source,
|
||||
title: 'Albums',
|
||||
actions: _buildActions(),
|
||||
actions: _buildActions(context),
|
||||
filterEntries: getAlbumEntries(source),
|
||||
filterBuilder: (s) => AlbumFilter(s, source.getUniqueAlbumName(s)),
|
||||
emptyBuilder: () => EmptyContent(
|
||||
|
@ -51,22 +52,21 @@ class AlbumListPage extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
List<Widget> _buildActions() {
|
||||
List<Widget> _buildActions(BuildContext context) {
|
||||
return [
|
||||
Builder(
|
||||
builder: (context) => PopupMenuButton<ChipAction>(
|
||||
key: Key('appbar-menu-button'),
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
PopupMenuItem(
|
||||
key: Key('menu-sort'),
|
||||
value: ChipAction.sort,
|
||||
child: MenuRow(text: 'Sort...', icon: AIcons.sort),
|
||||
),
|
||||
];
|
||||
},
|
||||
onSelected: (action) => _onChipActionSelected(context, action),
|
||||
),
|
||||
SearchButton(source),
|
||||
PopupMenuButton<ChipAction>(
|
||||
key: Key('appbar-menu-button'),
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
PopupMenuItem(
|
||||
key: Key('menu-sort'),
|
||||
value: ChipAction.sort,
|
||||
child: MenuRow(text: 'Sort...', icon: AIcons.sort),
|
||||
),
|
||||
];
|
||||
},
|
||||
onSelected: (action) => _onChipActionSelected(context, action),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -19,11 +19,12 @@ class DecoratedFilterChip extends StatelessWidget {
|
|||
final FilterCallback onPressed;
|
||||
|
||||
const DecoratedFilterChip({
|
||||
Key key,
|
||||
@required this.source,
|
||||
@required this.filter,
|
||||
@required this.entry,
|
||||
@required this.onPressed,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -119,6 +119,7 @@ class FilterGridPage extends StatelessWidget {
|
|||
(context, i) {
|
||||
final key = filterKeys[i];
|
||||
final child = DecoratedFilterChip(
|
||||
key: Key(key),
|
||||
source: source,
|
||||
filter: filterBuilder(key),
|
||||
entry: filterEntries[key],
|
||||
|
|
29
lib/widgets/filter_grids/search_button.dart
Normal file
29
lib/widgets/filter_grids/search_button.dart
Normal file
|
@ -0,0 +1,29 @@
|
|||
import 'package:aves/model/source/collection_source.dart';
|
||||
import 'package:aves/widgets/collection/search/search_delegate.dart';
|
||||
import 'package:aves/widgets/common/icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SearchButton extends StatelessWidget {
|
||||
final CollectionSource source;
|
||||
|
||||
const SearchButton(this.source);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IconButton(
|
||||
key: Key('search-button'),
|
||||
icon: Icon(AIcons.search),
|
||||
onPressed: () => _goToSearch(context),
|
||||
);
|
||||
}
|
||||
|
||||
void _goToSearch(BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
SearchPageRoute(
|
||||
delegate: ImageSearchDelegate(
|
||||
source: source,
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
|
@ -325,11 +325,12 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
|||
}
|
||||
|
||||
void _onLeave() {
|
||||
if (!Navigator.canPop(context)) {
|
||||
if (Navigator.canPop(context)) {
|
||||
_showSystemUI();
|
||||
} else {
|
||||
// exit app when trying to pop a fullscreen page that is a viewer for a single entry
|
||||
exit(0);
|
||||
SystemNavigator.pop();
|
||||
}
|
||||
_showSystemUI();
|
||||
}
|
||||
|
||||
// system UI
|
||||
|
|
|
@ -10,6 +10,8 @@ import 'package:aves/services/image_file_service.dart';
|
|||
import 'package:aves/services/viewer_service.dart';
|
||||
import 'package:aves/utils/android_file_utils.dart';
|
||||
import 'package:aves/widgets/collection/collection_page.dart';
|
||||
import 'package:aves/widgets/collection/search/search_delegate.dart';
|
||||
import 'package:aves/widgets/collection/search_page.dart';
|
||||
import 'package:aves/widgets/common/data_providers/media_store_collection_provider.dart';
|
||||
import 'package:aves/widgets/common/routes.dart';
|
||||
import 'package:aves/widgets/filter_grids/albums_page.dart';
|
||||
|
@ -32,7 +34,7 @@ class HomePage extends StatefulWidget {
|
|||
class _HomePageState extends State<HomePage> {
|
||||
MediaStoreSource _mediaStore;
|
||||
ImageEntry _viewerEntry;
|
||||
HomePageSetting _shortcutPage;
|
||||
String _shortcutRouteName;
|
||||
List<String> _shortcutFilters;
|
||||
|
||||
@override
|
||||
|
@ -83,8 +85,14 @@ class _HomePageState extends State<HomePage> {
|
|||
debugPrint('pick mimeType=$pickMimeTypes');
|
||||
break;
|
||||
default:
|
||||
final extraPage = intentData['page'];
|
||||
_shortcutPage = HomePageSetting.values.firstWhere((v) => v.toString().split('.')[1] == extraPage, orElse: () => null);
|
||||
// do not use 'route' as extra key, as the Flutter framework acts on it
|
||||
final extraRoute = intentData['page'];
|
||||
switch (extraRoute) {
|
||||
case CollectionPage.routeName:
|
||||
case AlbumListPage.routeName:
|
||||
case SearchPage.routeName:
|
||||
_shortcutRouteName = extraRoute;
|
||||
}
|
||||
final extraFilters = intentData['filters'];
|
||||
_shortcutFilters = extraFilters != null ? (extraFilters as List).cast<String>() : null;
|
||||
}
|
||||
|
@ -117,12 +125,12 @@ class _HomePageState extends State<HomePage> {
|
|||
);
|
||||
}
|
||||
|
||||
HomePageSetting startPage;
|
||||
String routeName;
|
||||
Iterable<CollectionFilter> filters;
|
||||
if (AvesApp.mode == AppMode.pick) {
|
||||
startPage = HomePageSetting.collection;
|
||||
routeName = CollectionPage.routeName;
|
||||
} else {
|
||||
startPage = _shortcutPage ?? settings.homePage;
|
||||
routeName = _shortcutRouteName ?? settings.homePage.routeName;
|
||||
filters = (_shortcutFilters ?? []).map((filterString) {
|
||||
switch (filterString) {
|
||||
case 'anyVideo':
|
||||
|
@ -132,14 +140,17 @@ class _HomePageState extends State<HomePage> {
|
|||
return null;
|
||||
});
|
||||
}
|
||||
switch (startPage) {
|
||||
case HomePageSetting.albums:
|
||||
switch (routeName) {
|
||||
case AlbumListPage.routeName:
|
||||
return DirectMaterialPageRoute(
|
||||
settings: RouteSettings(name: AlbumListPage.routeName),
|
||||
builder: (_) => AlbumListPage(source: _mediaStore),
|
||||
);
|
||||
case HomePageSetting.search:
|
||||
case HomePageSetting.collection:
|
||||
case SearchPage.routeName:
|
||||
return SearchPageRoute(
|
||||
delegate: ImageSearchDelegate(source: _mediaStore),
|
||||
);
|
||||
case CollectionPage.routeName:
|
||||
default:
|
||||
return DirectMaterialPageRoute(
|
||||
settings: RouteSettings(name: CollectionPage.routeName),
|
||||
|
|
Loading…
Reference in a new issue