diff --git a/lib/model/filters/location.dart b/lib/model/filters/location.dart index 97160bf31..a8bafbe0e 100644 --- a/lib/model/filters/location.dart +++ b/lib/model/filters/location.dart @@ -43,7 +43,7 @@ class LocationFilter extends CollectionFilter { @override Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true, bool embossed = false}) { final flag = countryCodeToFlag(_countryCode); - // as of Flutter v1.22.0-12.1.pre emoji shadows are rendered as colorful duplicates, + // as of Flutter v1.22.3, emoji shadows are rendered as colorful duplicates, // not filled with the shadow color as expected, so we remove them if (flag != null) return Text(flag, style: TextStyle(fontSize: size, shadows: [])); return Icon(_location.isEmpty ? AIcons.locationOff : AIcons.location, size: size); diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index 81a9b539c..69e9e0c6d 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.dart @@ -3,7 +3,7 @@ import 'package:flutter/painting.dart'; import 'package:tuple/tuple.dart'; class Constants { - // as of Flutter v1.11.0, overflowing `Text` miscalculates height and some text (e.g. 'Å') is clipped + // as of Flutter v1.22.3, overflowing `Text` miscalculates height and some text (e.g. 'Å') is clipped // so we give it a `strutStyle` with a slightly larger height static const overflowStrutStyle = StrutStyle(height: 1.3); diff --git a/lib/widgets/collection/grid/header_generic.dart b/lib/widgets/collection/grid/header_generic.dart index 7c0fda47a..e314fa14c 100644 --- a/lib/widgets/collection/grid/header_generic.dart +++ b/lib/widgets/collection/grid/header_generic.dart @@ -80,7 +80,7 @@ class SectionHeader extends StatelessWidget { final para = RenderParagraph( TextSpan( children: [ - // `RenderParagraph` fails to lay out `WidgetSpan` offscreen as of Flutter v1.17.0 + // as of Flutter v1.22.3, `RenderParagraph` fails to lay out `WidgetSpan` offscreen // so we use a hair space times a magic number to match width TextSpan( text: '\u200A' * (hasLeading ? 23 : 1), diff --git a/lib/widgets/collection/grid/list_sliver.dart b/lib/widgets/collection/grid/list_sliver.dart index 186df604d..3ed09aea1 100644 --- a/lib/widgets/collection/grid/list_sliver.dart +++ b/lib/widgets/collection/grid/list_sliver.dart @@ -10,9 +10,9 @@ import 'package:aves/widgets/fullscreen/fullscreen_page.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -// use a `SliverList` instead of multiple `SliverGrid` because having one `SliverGrid` per section does not scale up -// with the multiple `SliverGrid` solution, thumbnails at the beginning of each sections are built even though they are offscreen -// because of `RenderSliverMultiBoxAdaptor.addInitialChild` called by `RenderSliverGrid.performLayout` (line 547), as of Flutter v1.17.0 +// Use a `SliverList` instead of multiple `SliverGrid` because having one `SliverGrid` per section does not scale up. +// With the multiple `SliverGrid` solution, thumbnails at the beginning of each sections are built even though they are offscreen +// because of `RenderSliverMultiBoxAdaptor.addInitialChild` called by `RenderSliverGrid.performLayout` (line 547), as of Flutter v1.17.0. class CollectionListSliver extends StatelessWidget { const CollectionListSliver(); diff --git a/lib/widgets/settings/settings_page.dart b/lib/widgets/settings/settings_page.dart index b42f35c8a..8a63f6a04 100644 --- a/lib/widgets/settings/settings_page.dart +++ b/lib/widgets/settings/settings_page.dart @@ -3,6 +3,7 @@ import 'package:aves/model/settings/home_page.dart'; import 'package:aves/model/settings/screen_on.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/utils/constants.dart'; +import 'package:aves/utils/durations.dart'; import 'package:aves/widgets/common/aves_expansion_tile.dart'; import 'package:aves/widgets/common/aves_selection_dialog.dart'; import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart'; @@ -10,6 +11,7 @@ import 'package:aves/widgets/common/highlight_title.dart'; import 'package:aves/widgets/settings/access_grants.dart'; import 'package:aves/widgets/settings/svg_background.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:provider/provider.dart'; class SettingsPage extends StatefulWidget { @@ -33,16 +35,28 @@ class _SettingsPageState extends State { ), body: SafeArea( child: Consumer( - builder: (context, settings, child) => ListView( - padding: EdgeInsets.all(8), - children: [ - _buildNavigationSection(context), - _buildDisplaySection(context), - _buildThumbnailsSection(context), - _buildViewerSection(context), - _buildSearchSection(context), - _buildPrivacySection(context), - ], + builder: (context, settings, child) => AnimationLimiter( + child: ListView( + padding: EdgeInsets.all(8), + children: AnimationConfiguration.toStaggeredList( + duration: Durations.staggeredAnimation, + delay: Durations.staggeredAnimationDelay, + childAnimationBuilder: (child) => SlideAnimation( + verticalOffset: 50.0, + child: FadeInAnimation( + child: child, + ), + ), + children: [ + _buildNavigationSection(context), + _buildDisplaySection(context), + _buildThumbnailsSection(context), + _buildViewerSection(context), + _buildSearchSection(context), + _buildPrivacySection(context), + ], + ), + ), ), ), ), diff --git a/lib/widgets/stats/filter_table.dart b/lib/widgets/stats/filter_table.dart index 958f63a62..6c64666d5 100644 --- a/lib/widgets/stats/filter_table.dart +++ b/lib/widgets/stats/filter_table.dart @@ -2,6 +2,7 @@ import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/utils/color_utils.dart'; +import 'package:aves/utils/constants.dart'; import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/common/aves_filter_chip.dart'; import 'package:collection/collection.dart'; @@ -50,7 +51,10 @@ class FilterTable extends StatelessWidget { return TableRow( children: [ Container( - padding: EdgeInsets.only(bottom: 8), + // the `Table` `border` property paints on the cells and does not add margins, + // so we define margins here instead, but they should be symmetric + // to keep all cells vertically aligned on the center/middle + margin: EdgeInsets.symmetric(vertical: 4), alignment: AlignmentDirectional.centerStart, child: AvesFilterChip( filter: filter, @@ -65,7 +69,10 @@ class FilterTable extends StatelessWidget { progressColor: stringToColor(label), animation: true, padding: EdgeInsets.symmetric(horizontal: lineHeight), - center: Text(NumberFormat.percentPattern().format(percent)), + center: Text( + NumberFormat.percentPattern().format(percent), + style: TextStyle(shadows: [Constants.embossShadow]), + ), ), Text( '$count', diff --git a/lib/widgets/stats/stats.dart b/lib/widgets/stats/stats.dart index 4239b5239..28aa0779e 100644 --- a/lib/widgets/stats/stats.dart +++ b/lib/widgets/stats/stats.dart @@ -90,7 +90,10 @@ class StatsPage extends StatelessWidget { leading: Icon(AIcons.location), // right padding to match leading, so that inside label is aligned with outside label below padding: EdgeInsets.symmetric(horizontal: lineHeight) + EdgeInsets.only(right: 24), - center: Text(NumberFormat.percentPattern().format(withGpsPercent)), + center: Text( + NumberFormat.percentPattern().format(withGpsPercent), + style: TextStyle(shadows: [Constants.embossShadow]), + ), ), SizedBox(height: 8), Text('${withGps.length} ${Intl.plural(withGps.length, one: 'item', other: 'items')} with location'), diff --git a/lib/widgets/welcome_page.dart b/lib/widgets/welcome_page.dart index fb254a531..fb8b1f64b 100644 --- a/lib/widgets/welcome_page.dart +++ b/lib/widgets/welcome_page.dart @@ -3,6 +3,7 @@ import 'package:aves/utils/durations.dart'; import 'package:aves/widgets/common/aves_logo.dart'; import 'package:aves/widgets/common/labeled_checkbox.dart'; import 'package:aves/widgets/home_page.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; @@ -24,6 +25,9 @@ class _WelcomePageState extends State { void initState() { super.initState(); _termsLoader = rootBundle.loadString('assets/terms.md'); + if (!kReleaseMode) { + settings.isCrashlyticsEnabled = false; + } } @override @@ -167,9 +171,8 @@ class _WelcomePageState extends State { ); } - // workaround to handle `Flexible` widgets, - // because `AnimationConfiguration.toStaggeredList` does not, - // as of flutter_staggered_animations v0.1.2, + // as of flutter_staggered_animations v0.1.2, `AnimationConfiguration.toStaggeredList` does not handle `Flexible` widgets + // so we use this workaround instead static List _toStaggeredList({ Duration duration, Duration delay,