diff --git a/lib/model/filters/location.dart b/lib/model/filters/location.dart index a4ab64d42..abc444dad 100644 --- a/lib/model/filters/location.dart +++ b/lib/model/filters/location.dart @@ -55,7 +55,7 @@ class LocationFilter extends CollectionFilter { final flag = countryCodeToFlag(_countryCode); // 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: [])); + if (flag != null) return Text(flag, style: TextStyle(fontSize: size, shadows: []), textScaleFactor: 1.0,); return Icon(_location.isEmpty ? AIcons.locationOff : AIcons.location, size: size); } diff --git a/lib/widgets/about/app_ref.dart b/lib/widgets/about/app_ref.dart index 6e0057358..4a7f4b91c 100644 --- a/lib/widgets/about/app_ref.dart +++ b/lib/widgets/about/app_ref.dart @@ -46,7 +46,7 @@ class _AppReferenceState extends State { builder: (context, snapshot) { return LinkChip( leading: AvesLogo( - size: style.fontSize * 1.25, + size: style.fontSize * MediaQuery.textScaleFactorOf(context) * 1.25, ), text: 'Aves ${snapshot.data?.version}', url: 'https://github.com/deckerst/aves', diff --git a/lib/widgets/about/credits.dart b/lib/widgets/about/credits.dart index 913e0f1d4..55f2a5406 100644 --- a/lib/widgets/about/credits.dart +++ b/lib/widgets/about/credits.dart @@ -31,7 +31,7 @@ class AboutCredits extends StatelessWidget { ), alignment: PlaceholderAlignment.middle, ), - TextSpan(text: ', under ISC License.'), + TextSpan(text: 'under ISC License.'), ], ), ), diff --git a/lib/widgets/collection/collection_page.dart b/lib/widgets/collection/collection_page.dart index 99a6547bf..710b62848 100644 --- a/lib/widgets/collection/collection_page.dart +++ b/lib/widgets/collection/collection_page.dart @@ -48,9 +48,7 @@ class _CollectionPageState extends State { ), ), ), - drawer: AppDrawer( - source: collection.source, - ), + drawer: AppDrawer(), resizeToAvoidBottomInset: false, ), ), diff --git a/lib/widgets/common/basic/link_chip.dart b/lib/widgets/common/basic/link_chip.dart index b04c0b2ae..4842b8ce3 100644 --- a/lib/widgets/common/basic/link_chip.dart +++ b/lib/widgets/common/basic/link_chip.dart @@ -40,7 +40,14 @@ class LinkChip extends StatelessWidget { leading, SizedBox(width: 8), ], - Text(text), + Flexible( + child: Text( + text, + softWrap: false, + overflow: TextOverflow.fade, + maxLines: 1, + ), + ), SizedBox(width: 8), Builder( builder: (context) => Icon( diff --git a/lib/widgets/common/basic/menu_row.dart b/lib/widgets/common/basic/menu_row.dart index c14161c84..bcc3acf06 100644 --- a/lib/widgets/common/basic/menu_row.dart +++ b/lib/widgets/common/basic/menu_row.dart @@ -15,17 +15,19 @@ class MenuRow extends StatelessWidget { @override Widget build(BuildContext context) { + final textScaleFactor = MediaQuery.textScaleFactorOf(context); + final iconSize = IconTheme.of(context).size * textScaleFactor; return Row( children: [ if (checked != null) ...[ Opacity( opacity: checked ? 1 : 0, - child: Icon(AIcons.checked), + child: Icon(AIcons.checked, size: iconSize), ), SizedBox(width: 8), ], if (icon != null) ...[ - Icon(icon), + Icon(icon, size: iconSize), SizedBox(width: 8), ], Expanded(child: Text(text)), diff --git a/lib/widgets/common/identity/aves_filter_chip.dart b/lib/widgets/common/identity/aves_filter_chip.dart index db71d1320..ebf8a03a8 100644 --- a/lib/widgets/common/identity/aves_filter_chip.dart +++ b/lib/widgets/common/identity/aves_filter_chip.dart @@ -26,7 +26,6 @@ class AvesFilterChip extends StatefulWidget { static const double minChipHeight = kMinInteractiveDimension; static const double minChipWidth = 80; static const double maxChipWidth = 160; - static const double iconSize = 20; const AvesFilterChip({ Key key, @@ -88,7 +87,8 @@ class _AvesFilterChipState extends State { @override Widget build(BuildContext context) { - const iconSize = AvesFilterChip.iconSize; + final textScaleFactor = MediaQuery.textScaleFactorOf(context); + final iconSize = 20 * textScaleFactor; final hasBackground = widget.background != null; final leading = filter.iconBuilder(context, iconSize, showGenericIcon: widget.showGenericIcon, embossed: hasBackground); diff --git a/lib/widgets/common/identity/aves_icons.dart b/lib/widgets/common/identity/aves_icons.dart index 4fd080246..953c9ed0c 100644 --- a/lib/widgets/common/identity/aves_icons.dart +++ b/lib/widgets/common/identity/aves_icons.dart @@ -7,6 +7,7 @@ import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/utils/constants.dart'; import 'package:decorated_icon/decorated_icon.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class VideoIcon extends StatelessWidget { final AvesEntry entry; @@ -172,10 +173,26 @@ class IconUtils { static Widget getAlbumIcon({ @required BuildContext context, @required String album, - double size = 24, + double size, bool embossed = false, }) { - Widget buildIcon(IconData icon) => embossed ? DecoratedIcon(icon, shadows: [Constants.embossShadow], size: size) : Icon(icon, size: size); + size ??= IconTheme.of(context).size; + Widget buildIcon(IconData icon) => embossed + ? MediaQuery( + // `DecoratedIcon` internally uses `Text`, + // which size depends on the ambient `textScaleFactor` + // but we already accommodate for it upstream + data: context.read().copyWith(textScaleFactor: 1.0), + child: DecoratedIcon( + icon, + shadows: [Constants.embossShadow], + size: size, + ), + ) + : Icon( + icon, + size: size, + ); switch (androidFileUtils.getAlbumType(album)) { case AlbumType.camera: return buildIcon(AIcons.cameraAlbum); diff --git a/lib/widgets/debug/app_debug_page.dart b/lib/widgets/debug/app_debug_page.dart index 57d1caa86..d4698e79e 100644 --- a/lib/widgets/debug/app_debug_page.dart +++ b/lib/widgets/debug/app_debug_page.dart @@ -14,20 +14,17 @@ import 'package:aves/widgets/debug/storage.dart'; import 'package:aves/widgets/viewer/info/common.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; +import 'package:provider/provider.dart'; class AppDebugPage extends StatefulWidget { static const routeName = '/debug'; - final CollectionSource source; - - const AppDebugPage({this.source}); - @override State createState() => _AppDebugPageState(); } class _AppDebugPageState extends State { - CollectionSource get source => widget.source; + CollectionSource get source => context.read(); Set get visibleEntries => source.visibleEntries; diff --git a/lib/widgets/drawer/album_tile.dart b/lib/widgets/drawer/album_tile.dart new file mode 100644 index 000000000..ca8b17fd5 --- /dev/null +++ b/lib/widgets/drawer/album_tile.dart @@ -0,0 +1,35 @@ +import 'package:aves/model/filters/album.dart'; +import 'package:aves/model/source/collection_source.dart'; +import 'package:aves/theme/icons.dart'; +import 'package:aves/utils/android_file_utils.dart'; +import 'package:aves/widgets/common/identity/aves_icons.dart'; +import 'package:aves/widgets/drawer/collection_tile.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class AlbumTile extends StatelessWidget { + final String album; + + const AlbumTile(this.album); + + @override + Widget build(BuildContext context) { + final source = context.read(); + final uniqueName = source.getUniqueAlbumName(album); + return CollectionNavTile( + leading: IconUtils.getAlbumIcon( + context: context, + album: album, + ), + title: uniqueName, + trailing: androidFileUtils.isOnRemovableStorage(album) + ? Icon( + AIcons.removableStorage, + size: 16, + color: Colors.grey, + ) + : null, + filter: AlbumFilter(album, uniqueName), + ); + } +} diff --git a/lib/widgets/drawer/app_drawer.dart b/lib/widgets/drawer/app_drawer.dart index 0830f9331..fb942856a 100644 --- a/lib/widgets/drawer/app_drawer.dart +++ b/lib/widgets/drawer/app_drawer.dart @@ -1,7 +1,6 @@ import 'dart:ui'; import 'package:aves/model/availability.dart'; -import 'package:aves/model/filters/album.dart'; import 'package:aves/model/filters/favourite.dart'; import 'package:aves/model/filters/mime.dart'; import 'package:aves/model/source/album.dart'; @@ -14,9 +13,9 @@ import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/widgets/about/about_page.dart'; import 'package:aves/widgets/about/news_badge.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'; +import 'package:aves/widgets/drawer/album_tile.dart'; import 'package:aves/widgets/drawer/collection_tile.dart'; import 'package:aves/widgets/drawer/tile.dart'; import 'package:aves/widgets/filter_grids/albums_page.dart'; @@ -28,10 +27,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class AppDrawer extends StatefulWidget { - final CollectionSource source; - - const AppDrawer({@required this.source}); - @override _AppDrawerState createState() => _AppDrawerState(); } @@ -39,7 +34,7 @@ class AppDrawer extends StatefulWidget { class _AppDrawerState extends State { Future _newVersionLoader; - CollectionSource get source => widget.source; + CollectionSource get source => context.read(); @override void initState() { @@ -72,6 +67,7 @@ class _AppDrawerState extends State { child: Selector( selector: (c, mq) => mq.effectiveBottomPadding, builder: (c, mqPaddingBottom, child) { + final iconTheme = IconTheme.of(context); return SingleChildScrollView( padding: EdgeInsets.only(bottom: mqPaddingBottom), child: Theme( @@ -79,8 +75,11 @@ class _AppDrawerState extends State { // color used by `ExpansionTile` for leading icon unselectedWidgetColor: Colors.white, ), - child: Column( - children: drawerItems, + child: IconTheme( + data: iconTheme.copyWith(size: iconTheme.size * MediaQuery.textScaleFactorOf(context)), + child: Column( + children: drawerItems, + ), ), ), ); @@ -123,23 +122,6 @@ class _AppDrawerState extends State { ); } - Widget _buildAlbumTile(String album) { - final uniqueName = source.getUniqueAlbumName(album); - return CollectionNavTile( - source: source, - leading: IconUtils.getAlbumIcon(context: context, album: album), - title: uniqueName, - trailing: androidFileUtils.isOnRemovableStorage(album) - ? Icon( - AIcons.removableStorage, - size: 16, - color: Colors.grey, - ) - : null, - filter: AlbumFilter(album, uniqueName), - ); - } - Widget _buildSpecialAlbumSection() { return StreamBuilder( stream: source.eventBus.on(), @@ -154,7 +136,7 @@ class _AppDrawerState extends State { return Column( children: [ Divider(), - ...specialAlbums.map(_buildAlbumTile), + ...specialAlbums.map((album) => AlbumTile(album)), ], ); }); @@ -163,21 +145,18 @@ class _AppDrawerState extends State { // tiles Widget get allCollectionTile => CollectionNavTile( - source: source, leading: Icon(AIcons.allCollection), title: 'All collection', filter: null, ); Widget get videoTile => CollectionNavTile( - source: source, leading: Icon(AIcons.video), title: 'Videos', filter: MimeFilter(MimeTypes.anyVideo), ); Widget get favouriteTile => CollectionNavTile( - source: source, leading: Icon(AIcons.favourite), title: 'Favourites', filter: FavouriteFilter(), @@ -191,7 +170,7 @@ class _AppDrawerState extends State { builder: (context, _) => Text('${source.rawAlbums.length}'), ), routeName: AlbumListPage.routeName, - pageBuilder: (_) => AlbumListPage(source: source), + pageBuilder: (_) => AlbumListPage(), ); Widget get countryListTile => NavTile( @@ -202,7 +181,7 @@ class _AppDrawerState extends State { builder: (context, _) => Text('${source.sortedCountries.length}'), ), routeName: CountryListPage.routeName, - pageBuilder: (_) => CountryListPage(source: source), + pageBuilder: (_) => CountryListPage(), ); Widget get tagListTile => NavTile( @@ -213,7 +192,7 @@ class _AppDrawerState extends State { builder: (context, _) => Text('${source.sortedTags.length}'), ), routeName: TagListPage.routeName, - pageBuilder: (_) => TagListPage(source: source), + pageBuilder: (_) => TagListPage(), ); Widget get settingsTile => NavTile( @@ -244,6 +223,6 @@ class _AppDrawerState extends State { title: 'Debug', topLevel: false, routeName: AppDebugPage.routeName, - pageBuilder: (_) => AppDebugPage(source: source), + pageBuilder: (_) => AppDebugPage(), ); } diff --git a/lib/widgets/drawer/collection_tile.dart b/lib/widgets/drawer/collection_tile.dart index 61c2ad3bd..5001baa48 100644 --- a/lib/widgets/drawer/collection_tile.dart +++ b/lib/widgets/drawer/collection_tile.dart @@ -4,9 +4,9 @@ import 'package:aves/model/source/collection_source.dart'; import 'package:aves/widgets/collection/collection_page.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class CollectionNavTile extends StatelessWidget { - final CollectionSource source; final Widget leading; final String title; final Widget trailing; @@ -14,7 +14,6 @@ class CollectionNavTile extends StatelessWidget { final CollectionFilter filter; const CollectionNavTile({ - @required this.source, @required this.leading, @required this.title, this.trailing, @@ -44,7 +43,7 @@ class CollectionNavTile extends StatelessWidget { MaterialPageRoute( settings: RouteSettings(name: CollectionPage.routeName), builder: (context) => CollectionPage(CollectionLens( - source: source, + source: context.read(), filters: [filter], )), ), diff --git a/lib/widgets/filter_grids/albums_page.dart b/lib/widgets/filter_grids/albums_page.dart index a484a158e..c481b94e6 100644 --- a/lib/widgets/filter_grids/albums_page.dart +++ b/lib/widgets/filter_grids/albums_page.dart @@ -20,12 +20,9 @@ import 'package:tuple/tuple.dart'; class AlbumListPage extends StatelessWidget { static const routeName = '/albums'; - final CollectionSource source; - - const AlbumListPage({@required this.source}); - @override Widget build(BuildContext context) { + final source = context.read(); return Selector>>( selector: (context, s) => Tuple3(s.albumGroupFactor, s.albumSortFactor, s.pinnedFilters), builder: (context, s, child) { diff --git a/lib/widgets/filter_grids/common/filter_grid_page.dart b/lib/widgets/filter_grids/common/filter_grid_page.dart index 20b9c29b9..aacfb7445 100644 --- a/lib/widgets/filter_grids/common/filter_grid_page.dart +++ b/lib/widgets/filter_grids/common/filter_grid_page.dart @@ -180,9 +180,7 @@ class FilterGridPage extends StatelessWidget { ), ), ), - drawer: AppDrawer( - source: source, - ), + drawer: AppDrawer(), resizeToAvoidBottomInset: false, ), ); diff --git a/lib/widgets/filter_grids/countries_page.dart b/lib/widgets/filter_grids/countries_page.dart index eceecf5c8..37250584d 100644 --- a/lib/widgets/filter_grids/countries_page.dart +++ b/lib/widgets/filter_grids/countries_page.dart @@ -19,12 +19,9 @@ import 'package:tuple/tuple.dart'; class CountryListPage extends StatelessWidget { static const routeName = '/countries'; - final CollectionSource source; - - const CountryListPage({@required this.source}); - @override Widget build(BuildContext context) { + final source = context.read(); return Selector>>( selector: (context, s) => Tuple2(s.countrySortFactor, s.pinnedFilters), builder: (context, s, child) { @@ -39,7 +36,7 @@ class CountryListPage extends StatelessWidget { settings.pinnedFilters.contains(filter) ? ChipAction.unpin : ChipAction.pin, ChipAction.hide, ], - filterSections: _getCountryEntries(), + filterSections: _getCountryEntries(source), emptyBuilder: () => EmptyContent( icon: AIcons.location, text: 'No countries', @@ -50,7 +47,7 @@ class CountryListPage extends StatelessWidget { ); } - Map>> _getCountryEntries() { + Map>> _getCountryEntries(CollectionSource source) { final filters = source.sortedCountries.map((location) => LocationFilter(LocationLevel.country, location)).toSet(); final sorted = FilterNavigationPage.sort(settings.countrySortFactor, source, filters); diff --git a/lib/widgets/filter_grids/tags_page.dart b/lib/widgets/filter_grids/tags_page.dart index c31525c3e..4c60cc0fe 100644 --- a/lib/widgets/filter_grids/tags_page.dart +++ b/lib/widgets/filter_grids/tags_page.dart @@ -19,12 +19,9 @@ import 'package:tuple/tuple.dart'; class TagListPage extends StatelessWidget { static const routeName = '/tags'; - final CollectionSource source; - - const TagListPage({@required this.source}); - @override Widget build(BuildContext context) { + final source = context.read(); return Selector>>( selector: (context, s) => Tuple2(s.tagSortFactor, s.pinnedFilters), builder: (context, s, child) { @@ -39,7 +36,7 @@ class TagListPage extends StatelessWidget { settings.pinnedFilters.contains(filter) ? ChipAction.unpin : ChipAction.pin, ChipAction.hide, ], - filterSections: _getTagEntries(), + filterSections: _getTagEntries(source), emptyBuilder: () => EmptyContent( icon: AIcons.tag, text: 'No tags', @@ -50,7 +47,7 @@ class TagListPage extends StatelessWidget { ); } - Map>> _getTagEntries() { + Map>> _getTagEntries(CollectionSource source) { final filters = source.sortedTags.map((tag) => TagFilter(tag)).toSet(); final sorted = FilterNavigationPage.sort(settings.tagSortFactor, source, filters); diff --git a/lib/widgets/home_page.dart b/lib/widgets/home_page.dart index d11a993b2..76da78c66 100644 --- a/lib/widgets/home_page.dart +++ b/lib/widgets/home_page.dart @@ -140,7 +140,7 @@ class _HomePageState extends State { case AlbumListPage.routeName: return DirectMaterialPageRoute( settings: RouteSettings(name: AlbumListPage.routeName), - builder: (_) => AlbumListPage(source: source), + builder: (_) => AlbumListPage(), ); case SearchPage.routeName: return SearchPageRoute(