SD card storage indicator in drawer and section headers

This commit is contained in:
Thibault Deckers 2020-04-13 14:32:18 +09:00
parent 23eac7c3c7
commit 53dfe85e07
6 changed files with 69 additions and 18 deletions

View file

@ -32,6 +32,10 @@ class AndroidFileUtils {
bool isDownloadPath(String path) => path == downloadPath;
StorageVolume getStorageVolume(String path) => storageVolumes.firstWhere((v) => path.startsWith(v.path), orElse: () => null);
bool isOnSD(String path) => getStorageVolume(path).isRemovable;
AlbumType getAlbumType(String albumDirectory) {
if (albumDirectory != null) {
if (androidFileUtils.isCameraPath(albumDirectory)) return AlbumType.Camera;

View file

@ -93,13 +93,23 @@ class _CollectionDrawerState extends State<CollectionDrawer> {
title: 'Favourites',
filter: FavouriteFilter(),
);
final buildAlbumEntry = (String album) => _FilteredCollectionNavTile(
source: source,
leading: IconUtils.getAlbumIcon(context: context, album: album),
title: source.getUniqueAlbumName(album),
dense: true,
filter: AlbumFilter(album, source.getUniqueAlbumName(album)),
);
final buildAlbumEntry = (String album) {
final uniqueName = source.getUniqueAlbumName(album);
return _FilteredCollectionNavTile(
source: source,
leading: IconUtils.getAlbumIcon(context: context, album: album),
title: uniqueName,
trailing: androidFileUtils.isOnSD(album)
? const Icon(
OMIcons.sdStorage,
size: 16,
color: Colors.grey,
)
: null,
dense: true,
filter: AlbumFilter(album, uniqueName),
);
};
final buildTagEntry = (String tag) => _FilteredCollectionNavTile(
source: source,
leading: Icon(
@ -311,6 +321,7 @@ class _FilteredCollectionNavTile extends StatelessWidget {
final CollectionSource source;
final Widget leading;
final String title;
final Widget trailing;
final bool dense;
final CollectionFilter filter;
@ -318,6 +329,7 @@ class _FilteredCollectionNavTile extends StatelessWidget {
@required this.source,
@required this.leading,
@required this.title,
this.trailing,
bool dense,
@required this.filter,
}) : dense = dense ?? false;
@ -330,6 +342,7 @@ class _FilteredCollectionNavTile extends StatelessWidget {
child: ListTile(
leading: leading,
title: Text(title),
trailing: trailing,
dense: dense,
onTap: () => _goToCollection(context),
),

View file

@ -1,6 +1,8 @@
import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/widgets/album/grid/header_generic.dart';
import 'package:aves/widgets/common/icons.dart';
import 'package:flutter/material.dart';
import 'package:outline_material_icons/outline_material_icons.dart';
class AlbumSectionHeader extends StatelessWidget {
final String folderPath, albumName;
@ -26,6 +28,13 @@ class AlbumSectionHeader extends StatelessWidget {
return TitleSectionHeader(
leading: albumIcon,
title: albumName,
trailing: androidFileUtils.isOnSD(folderPath)
? const Icon(
OMIcons.sdStorage,
size: 16,
color: Color(0xFF757575),
)
: null,
);
}
}

View file

@ -70,17 +70,19 @@ class SectionHeader extends StatelessWidget {
var headerExtent = 0.0;
if (sectionKey is String) {
// only compute height for album headers, as they're the only likely ones to split on multiple lines
final hasIcon = androidFileUtils.getAlbumType(sectionKey) != AlbumType.Default;
final hasLeading = androidFileUtils.getAlbumType(sectionKey) != AlbumType.Default;
final hasTrailing = androidFileUtils.isOnSD(sectionKey);
final text = source.getUniqueAlbumName(sectionKey);
final maxWidth = scrollableWidth - TitleSectionHeader.padding.horizontal;
final para = RenderParagraph(
TextSpan(
children: [
if (hasIcon)
if (hasLeading)
// `RenderParagraph` fails to lay out `WidgetSpan` offscreen as of Flutter v1.17.0
// so we use a hair space times a magic number to match leading width
// 23 hair spaces match a width of 40.0
TextSpan(text: '\u200A' * 23),
TextSpan(text: '\u200A' * 23), // 23 hair spaces match a width of 40.0
if (hasTrailing)
TextSpan(text: '\u200A' * 17),
TextSpan(
text: text,
style: Constants.titleTextStyle,
@ -97,13 +99,19 @@ class SectionHeader extends StatelessWidget {
}
class TitleSectionHeader extends StatelessWidget {
final Widget leading;
final Widget leading, trailing;
final String title;
const TitleSectionHeader({Key key, this.leading, this.title}) : super(key: key);
const TitleSectionHeader({
Key key,
this.leading,
this.title,
this.trailing,
}) : super(key: key);
static const leadingDimension = 32.0;
static const leadingPadding = EdgeInsets.only(right: 8, bottom: 4);
static const trailingPadding = EdgeInsets.only(left: 8, bottom: 4);
static const padding = EdgeInsets.all(16);
@override
@ -122,6 +130,12 @@ class TitleSectionHeader extends StatelessWidget {
)
: null,
text: title,
trailingBuilder: trailing != null
? (context, isShadow) => Container(
padding: trailingPadding,
child: isShadow ? null : trailing,
)
: null,
style: Constants.titleTextStyle,
outlineWidth: 2,
),

View file

@ -3,18 +3,19 @@ import 'package:flutter/material.dart';
typedef OutlinedWidgetBuilder = Widget Function(BuildContext context, bool isShadow);
class OutlinedText extends StatelessWidget {
final OutlinedWidgetBuilder leadingBuilder;
final OutlinedWidgetBuilder leadingBuilder, trailingBuilder;
final String text;
final TextStyle style;
final double outlineWidth;
final Color outlineColor;
static const leadingAlignment = PlaceholderAlignment.middle;
static const widgetSpanAlignment = PlaceholderAlignment.middle;
const OutlinedText({
Key key,
this.leadingBuilder,
@required this.text,
this.trailingBuilder,
@required this.style,
double outlineWidth,
Color outlineColor,
@ -31,7 +32,7 @@ class OutlinedText extends StatelessWidget {
children: [
if (leadingBuilder != null)
WidgetSpan(
alignment: leadingAlignment,
alignment: widgetSpanAlignment,
child: leadingBuilder(context, true),
),
TextSpan(
@ -43,6 +44,11 @@ class OutlinedText extends StatelessWidget {
..color = outlineColor,
),
),
if (trailingBuilder != null)
WidgetSpan(
alignment: widgetSpanAlignment,
child: trailingBuilder(context, true),
),
],
),
),
@ -51,13 +57,18 @@ class OutlinedText extends StatelessWidget {
children: [
if (leadingBuilder != null)
WidgetSpan(
alignment: leadingAlignment,
alignment: widgetSpanAlignment,
child: leadingBuilder(context, false),
),
TextSpan(
text: text,
style: style,
),
if (trailingBuilder != null)
WidgetSpan(
alignment: widgetSpanAlignment,
child: trailingBuilder(context, false),
),
],
),
),

View file

@ -50,7 +50,7 @@ class DebugPageState extends State<DebugPage> {
padding: const EdgeInsets.all(8),
children: [
const Text('Storage'),
...AndroidFileUtils.storageVolumes.map((v) => Text('${v.description}: ${v.path} (removable: ${v.isRemovable}))')),
...AndroidFileUtils.storageVolumes.map((v) => Text('${v.description}: ${v.path} (removable: ${v.isRemovable})')),
const Divider(),
Row(
children: [