insets fixes
This commit is contained in:
parent
a37c10a969
commit
fd8191639b
21 changed files with 135 additions and 97 deletions
34
lib/model/settings/map_style.dart
Normal file
34
lib/model/settings/map_style.dart
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// browse providers at https://leaflet-extras.github.io/leaflet-providers/preview/
|
||||||
|
enum EntryMapStyle { googleNormal, googleHybrid, googleTerrain, osmHot, stamenToner, stamenWatercolor }
|
||||||
|
|
||||||
|
extension ExtraEntryMapStyle on EntryMapStyle {
|
||||||
|
String get name {
|
||||||
|
switch (this) {
|
||||||
|
case EntryMapStyle.googleNormal:
|
||||||
|
return 'Google Maps';
|
||||||
|
case EntryMapStyle.googleHybrid:
|
||||||
|
return 'Google Maps (Hybrid)';
|
||||||
|
case EntryMapStyle.googleTerrain:
|
||||||
|
return 'Google Maps (Terrain)';
|
||||||
|
case EntryMapStyle.osmHot:
|
||||||
|
return 'Humanitarian OSM';
|
||||||
|
case EntryMapStyle.stamenToner:
|
||||||
|
return 'Stamen Toner';
|
||||||
|
case EntryMapStyle.stamenWatercolor:
|
||||||
|
return 'Stamen Watercolor';
|
||||||
|
default:
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get isGoogleMaps {
|
||||||
|
switch (this) {
|
||||||
|
case EntryMapStyle.googleNormal:
|
||||||
|
case EntryMapStyle.googleHybrid:
|
||||||
|
case EntryMapStyle.googleTerrain:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,8 @@ import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/model/settings/coordinate_format.dart';
|
import 'package:aves/model/settings/coordinate_format.dart';
|
||||||
import 'package:aves/model/settings/entry_background.dart';
|
import 'package:aves/model/settings/entry_background.dart';
|
||||||
import 'package:aves/model/settings/home_page.dart';
|
import 'package:aves/model/settings/home_page.dart';
|
||||||
|
import 'package:aves/model/settings/map_style.dart';
|
||||||
import 'package:aves/model/settings/screen_on.dart';
|
import 'package:aves/model/settings/screen_on.dart';
|
||||||
import 'package:aves/widgets/viewer/info/location_section.dart';
|
|
||||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/widgets/collection/thumbnail_collection.dart';
|
import 'package:aves/widgets/collection/thumbnail_collection.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/insets.dart';
|
||||||
import 'package:aves/widgets/common/behaviour/double_back_pop.dart';
|
import 'package:aves/widgets/common/behaviour/double_back_pop.dart';
|
||||||
import 'package:aves/widgets/common/gesture_area_protector.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/drawer/app_drawer.dart';
|
import 'package:aves/widgets/drawer/app_drawer.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'dart:math';
|
||||||
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/utils/math_utils.dart';
|
import 'package:aves/utils/math_utils.dart';
|
||||||
|
import 'package:aves/widgets/common/extensions/media_query.dart';
|
||||||
import 'package:aves/widgets/common/grid/section_layout.dart';
|
import 'package:aves/widgets/common/grid/section_layout.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
|
@ -62,7 +63,7 @@ class _GridSelectionGestureDetectorState extends State<GridSelectionGestureDetec
|
||||||
_lastToIndex = _fromIndex;
|
_lastToIndex = _fromIndex;
|
||||||
_scrollableInsets = EdgeInsets.only(
|
_scrollableInsets = EdgeInsets.only(
|
||||||
top: appBarHeight,
|
top: appBarHeight,
|
||||||
bottom: context.read<MediaQueryData>().viewInsets.bottom,
|
bottom: context.read<MediaQueryData>().effectiveBottomPadding,
|
||||||
);
|
);
|
||||||
_scrollSpeedFactor = 0;
|
_scrollSpeedFactor = 0;
|
||||||
_pressing = true;
|
_pressing = true;
|
||||||
|
|
|
@ -16,8 +16,10 @@ import 'package:aves/widgets/collection/grid/section_layout.dart';
|
||||||
import 'package:aves/widgets/collection/grid/selector.dart';
|
import 'package:aves/widgets/collection/grid/selector.dart';
|
||||||
import 'package:aves/widgets/collection/grid/thumbnail.dart';
|
import 'package:aves/widgets/collection/grid/thumbnail.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/basic/insets.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/extensions/build_context.dart';
|
||||||
|
import 'package:aves/widgets/common/extensions/media_query.dart';
|
||||||
import 'package:aves/widgets/common/grid/section_layout.dart';
|
import 'package:aves/widgets/common/grid/section_layout.dart';
|
||||||
import 'package:aves/widgets/common/grid/sliver.dart';
|
import 'package:aves/widgets/common/grid/sliver.dart';
|
||||||
import 'package:aves/widgets/common/identity/scroll_thumb.dart';
|
import 'package:aves/widgets/common/identity/scroll_thumb.dart';
|
||||||
|
@ -222,14 +224,7 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
|
||||||
hasScrollBody: false,
|
hasScrollBody: false,
|
||||||
)
|
)
|
||||||
: SectionedListSliver<ImageEntry>(),
|
: SectionedListSliver<ImageEntry>(),
|
||||||
SliverToBoxAdapter(
|
BottomPaddingSliver(),
|
||||||
child: Selector<MediaQueryData, double>(
|
|
||||||
selector: (context, mq) => mq.viewInsets.bottom,
|
|
||||||
builder: (context, mqViewInsetsBottom, child) {
|
|
||||||
return SizedBox(height: mqViewInsetsBottom);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -238,8 +233,8 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
|
||||||
return ValueListenableBuilder<double>(
|
return ValueListenableBuilder<double>(
|
||||||
valueListenable: widget.appBarHeightNotifier,
|
valueListenable: widget.appBarHeightNotifier,
|
||||||
builder: (context, appBarHeight, child) => Selector<MediaQueryData, double>(
|
builder: (context, appBarHeight, child) => Selector<MediaQueryData, double>(
|
||||||
selector: (context, mq) => mq.viewInsets.bottom,
|
selector: (context, mq) => mq.effectiveBottomPadding,
|
||||||
builder: (context, mqViewInsetsBottom, child) => DraggableScrollbar(
|
builder: (context, mqPaddingBottom, child) => DraggableScrollbar(
|
||||||
heightScrollThumb: avesScrollThumbHeight,
|
heightScrollThumb: avesScrollThumbHeight,
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
scrollThumbBuilder: avesScrollThumbBuilder(
|
scrollThumbBuilder: avesScrollThumbBuilder(
|
||||||
|
@ -250,7 +245,7 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
// padding to keep scroll thumb between app bar above and nav bar below
|
// padding to keep scroll thumb between app bar above and nav bar below
|
||||||
top: appBarHeight,
|
top: appBarHeight,
|
||||||
bottom: mqViewInsetsBottom,
|
bottom: mqPaddingBottom,
|
||||||
),
|
),
|
||||||
child: scrollView,
|
child: scrollView,
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:math';
|
import 'package:aves/widgets/common/extensions/media_query.dart';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
@ -15,7 +14,7 @@ class BottomGestureAreaProtector extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Selector<MediaQueryData, double>(
|
return Selector<MediaQueryData, double>(
|
||||||
selector: (c, mq) => max(mq.viewPadding.bottom, mq.viewInsets.bottom),
|
selector: (c, mq) => mq.effectiveBottomPadding,
|
||||||
builder: (c, mqPaddingBottom, child) {
|
builder: (c, mqPaddingBottom, child) {
|
||||||
// devices with physical navigation buttons have no bottom insets
|
// devices with physical navigation buttons have no bottom insets
|
||||||
// we assume these devices do not use gesture navigation
|
// we assume these devices do not use gesture navigation
|
||||||
|
@ -47,3 +46,17 @@ class GestureAreaProtectorStack extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BottomPaddingSliver extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SliverToBoxAdapter(
|
||||||
|
child: Selector<MediaQueryData, double>(
|
||||||
|
selector: (context, mq) => mq.effectiveBottomPadding,
|
||||||
|
builder: (context, mqPaddingBottom, child) {
|
||||||
|
return SizedBox(height: mqPaddingBottom);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
extension ExtraContext on BuildContext {
|
|
||||||
String get currentRouteName => ModalRoute.of(this)?.settings?.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DirectMaterialPageRoute<T> extends PageRouteBuilder<T> {
|
class DirectMaterialPageRoute<T> extends PageRouteBuilder<T> {
|
||||||
DirectMaterialPageRoute({
|
DirectMaterialPageRoute({
|
||||||
RouteSettings settings,
|
RouteSettings settings,
|
||||||
|
|
5
lib/widgets/common/extensions/build_context.dart
Normal file
5
lib/widgets/common/extensions/build_context.dart
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
extension ExtraContext on BuildContext {
|
||||||
|
String get currentRouteName => ModalRoute.of(this)?.settings?.name;
|
||||||
|
}
|
41
lib/widgets/common/extensions/media_query.dart
Normal file
41
lib/widgets/common/extensions/media_query.dart
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
extension ExtraMediaQueryData on MediaQueryData {
|
||||||
|
/*
|
||||||
|
examples of MediaQuery props in practice, as of Flutter v1.22.5
|
||||||
|
|
||||||
|
S20, Android 11, portrait, notch top, button nav bar bottom
|
||||||
|
padding EdgeInsets(0.0, 26.0, 0.0, 48.0)
|
||||||
|
viewPadding EdgeInsets(0.0, 26.0, 0.0, 48.0)
|
||||||
|
viewInsets EdgeInsets.zero
|
||||||
|
|
||||||
|
S20, Android 11, landscape, notch left, button nav bar right
|
||||||
|
padding EdgeInsets(26.0, 24.0, 0.0, 0.0)
|
||||||
|
viewPadding EdgeInsets(26.0, 24.0, 0.0, 0.0)
|
||||||
|
viewInsets EdgeInsets.zero
|
||||||
|
|
||||||
|
S10e, Android 10, portrait, notch top, button nav bar bottom
|
||||||
|
padding EdgeInsets(0.0, 39.0, 0.0, 0.0)
|
||||||
|
viewPadding EdgeInsets(0.0, 39.0, 0.0, 0.0)
|
||||||
|
viewInsets EdgeInsets(0.0, 0.0, 0.0, 48.0)
|
||||||
|
|
||||||
|
S10e, Android 10, portrait, notch top, gesture nav bar bottom
|
||||||
|
padding EdgeInsets(0.0, 39.0, 0.0, 0.0)
|
||||||
|
viewPadding EdgeInsets(0.0, 39.0, 0.0, 0.0)
|
||||||
|
viewInsets EdgeInsets(0.0, 0.0, 0.0, 15.0)
|
||||||
|
|
||||||
|
S10e, Android 10, landscape, notch left, button nav bar right
|
||||||
|
padding EdgeInsets(38.7, 24.0, 0.0, 0.0)
|
||||||
|
viewPadding EdgeInsets(38.7, 24.0, 0.0, 0.0)
|
||||||
|
viewInsets EdgeInsets.zero
|
||||||
|
|
||||||
|
S7, portrait/landscape, no notch, no nav bar
|
||||||
|
padding EdgeInsets(0.0, 24.0, 0.0, 0.0)
|
||||||
|
viewPadding EdgeInsets(0.0, 24.0, 0.0, 0.0)
|
||||||
|
viewInsets EdgeInsets.zero
|
||||||
|
*/
|
||||||
|
|
||||||
|
double get effectiveBottomPadding => max(viewPadding.bottom, viewInsets.bottom);
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:aves/services/service_policy.dart';
|
import 'package:aves/services/service_policy.dart';
|
||||||
|
import 'package:aves/widgets/common/extensions/media_query.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DebugTaskQueueOverlay extends StatelessWidget {
|
class DebugTaskQueueOverlay extends StatelessWidget {
|
||||||
|
@ -13,7 +14,7 @@ class DebugTaskQueueOverlay extends StatelessWidget {
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Colors.indigo[900].withAlpha(0xCC),
|
color: Colors.indigo[900].withAlpha(0xCC),
|
||||||
margin: EdgeInsets.only(
|
margin: EdgeInsets.only(
|
||||||
bottom: MediaQuery.of(context).viewInsets.bottom,
|
bottom: MediaQuery.of(context).effectiveBottomPadding,
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.all(8),
|
padding: EdgeInsets.all(8),
|
||||||
child: StreamBuilder<QueueState>(
|
child: StreamBuilder<QueueState>(
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'dart:math';
|
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:aves/model/filters/album.dart';
|
import 'package:aves/model/filters/album.dart';
|
||||||
|
@ -12,6 +11,7 @@ import 'package:aves/ref/mime_types.dart';
|
||||||
import 'package:aves/theme/icons.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/about/about_page.dart';
|
import 'package:aves/widgets/about/about_page.dart';
|
||||||
|
import 'package:aves/widgets/common/extensions/media_query.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_icons.dart';
|
import 'package:aves/widgets/common/identity/aves_icons.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_logo.dart';
|
import 'package:aves/widgets/common/identity/aves_logo.dart';
|
||||||
import 'package:aves/widgets/debug/app_debug_page.dart';
|
import 'package:aves/widgets/debug/app_debug_page.dart';
|
||||||
|
@ -60,7 +60,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
|
|
||||||
return Drawer(
|
return Drawer(
|
||||||
child: Selector<MediaQueryData, double>(
|
child: Selector<MediaQueryData, double>(
|
||||||
selector: (c, mq) => max(mq.viewPadding.bottom, mq.viewInsets.bottom),
|
selector: (c, mq) => mq.effectiveBottomPadding,
|
||||||
builder: (c, mqPaddingBottom, child) {
|
builder: (c, mqPaddingBottom, child) {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
padding: EdgeInsets.only(bottom: mqPaddingBottom),
|
padding: EdgeInsets.only(bottom: mqPaddingBottom),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:aves/widgets/common/behaviour/routes.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,10 @@ import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/model/highlight.dart';
|
import 'package:aves/model/highlight.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';
|
||||||
|
import 'package:aves/widgets/common/basic/insets.dart';
|
||||||
import 'package:aves/widgets/common/behaviour/double_back_pop.dart';
|
import 'package:aves/widgets/common/behaviour/double_back_pop.dart';
|
||||||
import 'package:aves/widgets/common/behaviour/routes.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/gesture_area_protector.dart';
|
import 'package:aves/widgets/common/extensions/media_query.dart';
|
||||||
import 'package:aves/widgets/common/grid/section_layout.dart';
|
import 'package:aves/widgets/common/grid/section_layout.dart';
|
||||||
import 'package:aves/widgets/common/grid/sliver.dart';
|
import 'package:aves/widgets/common/grid/sliver.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
|
@ -189,8 +190,8 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
||||||
|
|
||||||
Widget _buildDraggableScrollView(ScrollView scrollView) {
|
Widget _buildDraggableScrollView(ScrollView scrollView) {
|
||||||
return Selector<MediaQueryData, double>(
|
return Selector<MediaQueryData, double>(
|
||||||
selector: (context, mq) => mq.viewInsets.bottom,
|
selector: (context, mq) => mq.effectiveBottomPadding,
|
||||||
builder: (context, mqViewInsetsBottom, child) => DraggableScrollbar(
|
builder: (context, mqPaddingBottom, child) => DraggableScrollbar(
|
||||||
heightScrollThumb: avesScrollThumbHeight,
|
heightScrollThumb: avesScrollThumbHeight,
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
scrollThumbBuilder: avesScrollThumbBuilder(
|
scrollThumbBuilder: avesScrollThumbBuilder(
|
||||||
|
@ -201,7 +202,7 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
// padding to keep scroll thumb between app bar above and nav bar below
|
// padding to keep scroll thumb between app bar above and nav bar below
|
||||||
top: _appBarHeightNotifier.value,
|
top: _appBarHeightNotifier.value,
|
||||||
bottom: mqViewInsetsBottom,
|
bottom: mqPaddingBottom,
|
||||||
),
|
),
|
||||||
child: scrollView,
|
child: scrollView,
|
||||||
),
|
),
|
||||||
|
@ -213,10 +214,10 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
||||||
if (empty) {
|
if (empty) {
|
||||||
content = SliverFillRemaining(
|
content = SliverFillRemaining(
|
||||||
child: Selector<MediaQueryData, double>(
|
child: Selector<MediaQueryData, double>(
|
||||||
selector: (context, mq) => mq.viewInsets.bottom,
|
selector: (context, mq) => mq.effectiveBottomPadding,
|
||||||
builder: (context, mqViewInsetsBottom, child) {
|
builder: (context, mqPaddingBottom, child) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(bottom: mqViewInsetsBottom),
|
padding: EdgeInsets.only(bottom: mqPaddingBottom),
|
||||||
child: emptyBuilder(),
|
child: emptyBuilder(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -227,22 +228,13 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
||||||
content = SectionedListSliver<FilterGridItem<T>>();
|
content = SectionedListSliver<FilterGridItem<T>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
final padding = SliverToBoxAdapter(
|
|
||||||
child: Selector<MediaQueryData, double>(
|
|
||||||
selector: (context, mq) => mq.viewInsets.bottom,
|
|
||||||
builder: (context, mqViewInsetsBottom, child) {
|
|
||||||
return SizedBox(height: mqViewInsetsBottom);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
key: _scrollableKey,
|
key: _scrollableKey,
|
||||||
controller: PrimaryScrollController.of(context),
|
controller: PrimaryScrollController.of(context),
|
||||||
slivers: [
|
slivers: [
|
||||||
appBar,
|
appBar,
|
||||||
content,
|
content,
|
||||||
padding,
|
BottomPaddingSliver(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@ import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/widgets/collection/collection_page.dart';
|
import 'package:aves/widgets/collection/collection_page.dart';
|
||||||
import 'package:aves/widgets/common/behaviour/routes.dart';
|
import 'package:aves/widgets/common/behaviour/routes.dart';
|
||||||
import 'package:aves/widgets/filter_grids/albums_page.dart';
|
import 'package:aves/widgets/filter_grids/albums_page.dart';
|
||||||
import 'package:aves/widgets/viewer/entry_viewer_page.dart';
|
|
||||||
import 'package:aves/widgets/search/search_delegate.dart';
|
import 'package:aves/widgets/search/search_delegate.dart';
|
||||||
import 'package:aves/widgets/search/search_page.dart';
|
import 'package:aves/widgets/search/search_page.dart';
|
||||||
|
import 'package:aves/widgets/viewer/entry_viewer_page.dart';
|
||||||
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
|
@ -8,7 +8,7 @@ import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/utils/change_notifier.dart';
|
import 'package:aves/utils/change_notifier.dart';
|
||||||
import 'package:aves/widgets/collection/collection_page.dart';
|
import 'package:aves/widgets/collection/collection_page.dart';
|
||||||
import 'package:aves/widgets/common/gesture_area_protector.dart';
|
import 'package:aves/widgets/common/basic/insets.dart';
|
||||||
import 'package:aves/widgets/common/magnifier/pan/scroll_physics.dart';
|
import 'package:aves/widgets/common/magnifier/pan/scroll_physics.dart';
|
||||||
import 'package:aves/widgets/viewer/entry_action_delegate.dart';
|
import 'package:aves/widgets/viewer/entry_action_delegate.dart';
|
||||||
import 'package:aves/widgets/viewer/entry_scroller.dart';
|
import 'package:aves/widgets/viewer/entry_scroller.dart';
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'package:aves/model/filters/filters.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/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/widgets/common/gesture_area_protector.dart';
|
import 'package:aves/widgets/common/basic/insets.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/viewer/info/basic_section.dart';
|
import 'package:aves/widgets/viewer/info/basic_section.dart';
|
||||||
import 'package:aves/widgets/viewer/info/info_app_bar.dart';
|
import 'package:aves/widgets/viewer/info/info_app_bar.dart';
|
||||||
|
@ -11,7 +11,6 @@ import 'package:aves/widgets/viewer/info/metadata/metadata_section.dart';
|
||||||
import 'package:aves/widgets/viewer/info/notifications.dart';
|
import 'package:aves/widgets/viewer/info/notifications.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
|
||||||
|
|
||||||
class InfoPage extends StatefulWidget {
|
class InfoPage extends StatefulWidget {
|
||||||
final CollectionLens collection;
|
final CollectionLens collection;
|
||||||
|
@ -46,11 +45,9 @@ class _InfoPageState extends State<InfoPage> {
|
||||||
bottom: false,
|
bottom: false,
|
||||||
child: NotificationListener(
|
child: NotificationListener(
|
||||||
onNotification: _handleTopScroll,
|
onNotification: _handleTopScroll,
|
||||||
child: Selector<MediaQueryData, Tuple2<double, double>>(
|
child: Selector<MediaQueryData, double>(
|
||||||
selector: (c, mq) => Tuple2(mq.size.width, mq.viewInsets.bottom),
|
selector: (c, mq) => mq.size.width,
|
||||||
builder: (c, mq, child) {
|
builder: (c, mqWidth, child) {
|
||||||
final mqWidth = mq.item1;
|
|
||||||
final mqViewInsetsBottom = mq.item2;
|
|
||||||
return ValueListenableBuilder<ImageEntry>(
|
return ValueListenableBuilder<ImageEntry>(
|
||||||
valueListenable: widget.entryNotifier,
|
valueListenable: widget.entryNotifier,
|
||||||
builder: (context, entry, child) {
|
builder: (context, entry, child) {
|
||||||
|
@ -61,7 +58,6 @@ class _InfoPageState extends State<InfoPage> {
|
||||||
visibleNotifier: widget.visibleNotifier,
|
visibleNotifier: widget.visibleNotifier,
|
||||||
scrollController: _scrollController,
|
scrollController: _scrollController,
|
||||||
split: mqWidth > 400,
|
split: mqWidth > 400,
|
||||||
mqViewInsetsBottom: mqViewInsetsBottom,
|
|
||||||
goToViewer: _goToViewer,
|
goToViewer: _goToViewer,
|
||||||
)
|
)
|
||||||
: SizedBox.shrink();
|
: SizedBox.shrink();
|
||||||
|
@ -115,7 +111,6 @@ class _InfoPageContent extends StatefulWidget {
|
||||||
final ValueNotifier<bool> visibleNotifier;
|
final ValueNotifier<bool> visibleNotifier;
|
||||||
final ScrollController scrollController;
|
final ScrollController scrollController;
|
||||||
final bool split;
|
final bool split;
|
||||||
final double mqViewInsetsBottom;
|
|
||||||
final VoidCallback goToViewer;
|
final VoidCallback goToViewer;
|
||||||
|
|
||||||
const _InfoPageContent({
|
const _InfoPageContent({
|
||||||
|
@ -125,7 +120,6 @@ class _InfoPageContent extends StatefulWidget {
|
||||||
@required this.visibleNotifier,
|
@required this.visibleNotifier,
|
||||||
@required this.scrollController,
|
@required this.scrollController,
|
||||||
@required this.split,
|
@required this.split,
|
||||||
@required this.mqViewInsetsBottom,
|
|
||||||
@required this.goToViewer,
|
@required this.goToViewer,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@ -190,9 +184,10 @@ class _InfoPageContentState extends State<_InfoPageContent> {
|
||||||
sliver: basicAndLocationSliver,
|
sliver: basicAndLocationSliver,
|
||||||
),
|
),
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
padding: horizontalPadding + EdgeInsets.only(bottom: 8 + widget.mqViewInsetsBottom),
|
padding: horizontalPadding + EdgeInsets.only(bottom: 8),
|
||||||
sliver: metadataSliver,
|
sliver: metadataSliver,
|
||||||
),
|
),
|
||||||
|
BottomPaddingSliver(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:aves/model/filters/location.dart';
|
import 'package:aves/model/filters/location.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/settings/coordinate_format.dart';
|
import 'package:aves/model/settings/coordinate_format.dart';
|
||||||
|
import 'package:aves/model/settings/map_style.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/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
|
@ -190,38 +191,3 @@ class _AddressInfoGroupState extends State<_AddressInfoGroup> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// browse providers at https://leaflet-extras.github.io/leaflet-providers/preview/
|
|
||||||
enum EntryMapStyle { googleNormal, googleHybrid, googleTerrain, osmHot, stamenToner, stamenWatercolor }
|
|
||||||
|
|
||||||
extension ExtraEntryMapStyle on EntryMapStyle {
|
|
||||||
String get name {
|
|
||||||
switch (this) {
|
|
||||||
case EntryMapStyle.googleNormal:
|
|
||||||
return 'Google Maps';
|
|
||||||
case EntryMapStyle.googleHybrid:
|
|
||||||
return 'Google Maps (Hybrid)';
|
|
||||||
case EntryMapStyle.googleTerrain:
|
|
||||||
return 'Google Maps (Terrain)';
|
|
||||||
case EntryMapStyle.osmHot:
|
|
||||||
return 'Humanitarian OSM';
|
|
||||||
case EntryMapStyle.stamenToner:
|
|
||||||
return 'Stamen Toner';
|
|
||||||
case EntryMapStyle.stamenWatercolor:
|
|
||||||
return 'Stamen Watercolor';
|
|
||||||
default:
|
|
||||||
return toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get isGoogleMaps {
|
|
||||||
switch (this) {
|
|
||||||
case EntryMapStyle.googleNormal:
|
|
||||||
case EntryMapStyle.googleHybrid:
|
|
||||||
case EntryMapStyle.googleTerrain:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:aves/model/settings/map_style.dart';
|
||||||
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';
|
||||||
|
@ -6,7 +7,6 @@ import 'package:aves/widgets/common/fx/blurred.dart';
|
||||||
import 'package:aves/widgets/common/fx/borders.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/viewer/info/location_section.dart';
|
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
import 'package:aves/widgets/viewer/overlay/common.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:aves/model/settings/map_style.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/widgets/viewer/info/location_section.dart';
|
|
||||||
import 'package:aves/widgets/viewer/info/maps/common.dart';
|
import 'package:aves/widgets/viewer/info/maps/common.dart';
|
||||||
import 'package:aves/widgets/viewer/info/maps/marker.dart';
|
import 'package:aves/widgets/viewer/info/maps/marker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:aves/model/settings/map_style.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/widgets/viewer/info/maps/common.dart';
|
import 'package:aves/widgets/viewer/info/maps/common.dart';
|
||||||
import 'package:aves/widgets/viewer/info/maps/scale_layer.dart';
|
import 'package:aves/widgets/viewer/info/maps/scale_layer.dart';
|
||||||
|
@ -7,8 +8,6 @@ import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
import 'package:latlong/latlong.dart';
|
import 'package:latlong/latlong.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import '../location_section.dart';
|
|
||||||
|
|
||||||
class EntryLeafletMap extends StatefulWidget {
|
class EntryLeafletMap extends StatefulWidget {
|
||||||
final LatLng latLng;
|
final LatLng latLng;
|
||||||
final String geoUri;
|
final String geoUri;
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'package:aves/image_providers/uri_image_provider.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/panorama.dart';
|
import 'package:aves/model/panorama.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/gesture_area_protector.dart';
|
import 'package:aves/widgets/common/basic/insets.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/viewer/overlay/common.dart';
|
import 'package:aves/widgets/viewer/overlay/common.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
Loading…
Reference in a new issue