insets fixes

This commit is contained in:
Thibault Deckers 2021-01-19 18:31:18 +09:00
parent a37c10a969
commit fd8191639b
21 changed files with 135 additions and 97 deletions

View 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;
}
}
}

View file

@ -2,8 +2,8 @@ import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/settings/coordinate_format.dart';
import 'package:aves/model/settings/entry_background.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/widgets/viewer/info/location_section.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';

View file

@ -1,7 +1,7 @@
import 'package:aves/model/source/collection_lens.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/gesture_area_protector.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
import 'package:aves/widgets/drawer/app_drawer.dart';
import 'package:flutter/foundation.dart';

View file

@ -4,6 +4,7 @@ import 'dart:math';
import 'package:aves/model/image_entry.dart';
import 'package:aves/model/source/collection_lens.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:flutter/material.dart';
import 'package:flutter/rendering.dart';
@ -62,7 +63,7 @@ class _GridSelectionGestureDetectorState extends State<GridSelectionGestureDetec
_lastToIndex = _fromIndex;
_scrollableInsets = EdgeInsets.only(
top: appBarHeight,
bottom: context.read<MediaQueryData>().viewInsets.bottom,
bottom: context.read<MediaQueryData>().effectiveBottomPadding,
);
_scrollSpeedFactor = 0;
_pressing = true;

View file

@ -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/thumbnail.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/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/sliver.dart';
import 'package:aves/widgets/common/identity/scroll_thumb.dart';
@ -222,14 +224,7 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
hasScrollBody: false,
)
: SectionedListSliver<ImageEntry>(),
SliverToBoxAdapter(
child: Selector<MediaQueryData, double>(
selector: (context, mq) => mq.viewInsets.bottom,
builder: (context, mqViewInsetsBottom, child) {
return SizedBox(height: mqViewInsetsBottom);
},
),
),
BottomPaddingSliver(),
],
);
}
@ -238,8 +233,8 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
return ValueListenableBuilder<double>(
valueListenable: widget.appBarHeightNotifier,
builder: (context, appBarHeight, child) => Selector<MediaQueryData, double>(
selector: (context, mq) => mq.viewInsets.bottom,
builder: (context, mqViewInsetsBottom, child) => DraggableScrollbar(
selector: (context, mq) => mq.effectiveBottomPadding,
builder: (context, mqPaddingBottom, child) => DraggableScrollbar(
heightScrollThumb: avesScrollThumbHeight,
backgroundColor: Colors.white,
scrollThumbBuilder: avesScrollThumbBuilder(
@ -250,7 +245,7 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
padding: EdgeInsets.only(
// padding to keep scroll thumb between app bar above and nav bar below
top: appBarHeight,
bottom: mqViewInsetsBottom,
bottom: mqPaddingBottom,
),
child: scrollView,
),

View file

@ -1,5 +1,4 @@
import 'dart:math';
import 'package:aves/widgets/common/extensions/media_query.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -15,7 +14,7 @@ class BottomGestureAreaProtector extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Selector<MediaQueryData, double>(
selector: (c, mq) => max(mq.viewPadding.bottom, mq.viewInsets.bottom),
selector: (c, mq) => mq.effectiveBottomPadding,
builder: (c, mqPaddingBottom, child) {
// devices with physical navigation buttons have no bottom insets
// 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);
},
),
);
}
}

View file

@ -1,9 +1,5 @@
import 'package:flutter/material.dart';
extension ExtraContext on BuildContext {
String get currentRouteName => ModalRoute.of(this)?.settings?.name;
}
class DirectMaterialPageRoute<T> extends PageRouteBuilder<T> {
DirectMaterialPageRoute({
RouteSettings settings,

View file

@ -0,0 +1,5 @@
import 'package:flutter/widgets.dart';
extension ExtraContext on BuildContext {
String get currentRouteName => ModalRoute.of(this)?.settings?.name;
}

View 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);
}

View file

@ -1,4 +1,5 @@
import 'package:aves/services/service_policy.dart';
import 'package:aves/widgets/common/extensions/media_query.dart';
import 'package:flutter/material.dart';
class DebugTaskQueueOverlay extends StatelessWidget {
@ -13,7 +14,7 @@ class DebugTaskQueueOverlay extends StatelessWidget {
child: Container(
color: Colors.indigo[900].withAlpha(0xCC),
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
bottom: MediaQuery.of(context).effectiveBottomPadding,
),
padding: EdgeInsets.all(8),
child: StreamBuilder<QueueState>(

View file

@ -1,4 +1,3 @@
import 'dart:math';
import 'dart:ui';
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/utils/android_file_utils.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_logo.dart';
import 'package:aves/widgets/debug/app_debug_page.dart';
@ -60,7 +60,7 @@ class _AppDrawerState extends State<AppDrawer> {
return Drawer(
child: Selector<MediaQueryData, double>(
selector: (c, mq) => max(mq.viewPadding.bottom, mq.viewInsets.bottom),
selector: (c, mq) => mq.effectiveBottomPadding,
builder: (c, mqPaddingBottom, child) {
return SingleChildScrollView(
padding: EdgeInsets.only(bottom: mqPaddingBottom),

View file

@ -1,6 +1,6 @@
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/material.dart';

View file

@ -4,9 +4,10 @@ import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/highlight.dart';
import 'package:aves/model/settings/settings.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/routes.dart';
import 'package:aves/widgets/common/gesture_area_protector.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/sliver.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) {
return Selector<MediaQueryData, double>(
selector: (context, mq) => mq.viewInsets.bottom,
builder: (context, mqViewInsetsBottom, child) => DraggableScrollbar(
selector: (context, mq) => mq.effectiveBottomPadding,
builder: (context, mqPaddingBottom, child) => DraggableScrollbar(
heightScrollThumb: avesScrollThumbHeight,
backgroundColor: Colors.white,
scrollThumbBuilder: avesScrollThumbBuilder(
@ -201,7 +202,7 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
padding: EdgeInsets.only(
// padding to keep scroll thumb between app bar above and nav bar below
top: _appBarHeightNotifier.value,
bottom: mqViewInsetsBottom,
bottom: mqPaddingBottom,
),
child: scrollView,
),
@ -213,10 +214,10 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
if (empty) {
content = SliverFillRemaining(
child: Selector<MediaQueryData, double>(
selector: (context, mq) => mq.viewInsets.bottom,
builder: (context, mqViewInsetsBottom, child) {
selector: (context, mq) => mq.effectiveBottomPadding,
builder: (context, mqPaddingBottom, child) {
return Padding(
padding: EdgeInsets.only(bottom: mqViewInsetsBottom),
padding: EdgeInsets.only(bottom: mqPaddingBottom),
child: emptyBuilder(),
);
},
@ -227,22 +228,13 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
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(
key: _scrollableKey,
controller: PrimaryScrollController.of(context),
slivers: [
appBar,
content,
padding,
BottomPaddingSliver(),
],
);
}

View file

@ -12,9 +12,9 @@ import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/widgets/collection/collection_page.dart';
import 'package:aves/widgets/common/behaviour/routes.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_page.dart';
import 'package:aves/widgets/viewer/entry_viewer_page.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

View file

@ -8,7 +8,7 @@ import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/utils/change_notifier.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/viewer/entry_action_delegate.dart';
import 'package:aves/widgets/viewer/entry_scroller.dart';

View file

@ -2,7 +2,7 @@ import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/image_entry.dart';
import 'package:aves/model/source/collection_lens.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/viewer/info/basic_section.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:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tuple/tuple.dart';
class InfoPage extends StatefulWidget {
final CollectionLens collection;
@ -46,11 +45,9 @@ class _InfoPageState extends State<InfoPage> {
bottom: false,
child: NotificationListener(
onNotification: _handleTopScroll,
child: Selector<MediaQueryData, Tuple2<double, double>>(
selector: (c, mq) => Tuple2(mq.size.width, mq.viewInsets.bottom),
builder: (c, mq, child) {
final mqWidth = mq.item1;
final mqViewInsetsBottom = mq.item2;
child: Selector<MediaQueryData, double>(
selector: (c, mq) => mq.size.width,
builder: (c, mqWidth, child) {
return ValueListenableBuilder<ImageEntry>(
valueListenable: widget.entryNotifier,
builder: (context, entry, child) {
@ -61,7 +58,6 @@ class _InfoPageState extends State<InfoPage> {
visibleNotifier: widget.visibleNotifier,
scrollController: _scrollController,
split: mqWidth > 400,
mqViewInsetsBottom: mqViewInsetsBottom,
goToViewer: _goToViewer,
)
: SizedBox.shrink();
@ -115,7 +111,6 @@ class _InfoPageContent extends StatefulWidget {
final ValueNotifier<bool> visibleNotifier;
final ScrollController scrollController;
final bool split;
final double mqViewInsetsBottom;
final VoidCallback goToViewer;
const _InfoPageContent({
@ -125,7 +120,6 @@ class _InfoPageContent extends StatefulWidget {
@required this.visibleNotifier,
@required this.scrollController,
@required this.split,
@required this.mqViewInsetsBottom,
@required this.goToViewer,
}) : super(key: key);
@ -190,9 +184,10 @@ class _InfoPageContentState extends State<_InfoPageContent> {
sliver: basicAndLocationSliver,
),
SliverPadding(
padding: horizontalPadding + EdgeInsets.only(bottom: 8 + widget.mqViewInsetsBottom),
padding: horizontalPadding + EdgeInsets.only(bottom: 8),
sliver: metadataSliver,
),
BottomPaddingSliver(),
],
);
}

View file

@ -1,6 +1,7 @@
import 'package:aves/model/filters/location.dart';
import 'package:aves/model/image_entry.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/source/collection_lens.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;
}
}
}

View file

@ -1,3 +1,4 @@
import 'package:aves/model/settings/map_style.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/services/android_app_service.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/dialogs/aves_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:flutter/material.dart';
import 'package:flutter/scheduler.dart';

View file

@ -1,8 +1,8 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:aves/model/settings/map_style.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/marker.dart';
import 'package:flutter/material.dart';

View file

@ -1,3 +1,4 @@
import 'package:aves/model/settings/map_style.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/widgets/viewer/info/maps/common.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:url_launcher/url_launcher.dart';
import '../location_section.dart';
class EntryLeafletMap extends StatefulWidget {
final LatLng latLng;
final String geoUri;

View file

@ -2,7 +2,7 @@ import 'package:aves/image_providers/uri_image_provider.dart';
import 'package:aves/model/image_entry.dart';
import 'package:aves/model/panorama.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/viewer/overlay/common.dart';
import 'package:flutter/foundation.dart';