SD card storage indicator in drawer and section headers
This commit is contained in:
parent
23eac7c3c7
commit
53dfe85e07
6 changed files with 69 additions and 18 deletions
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
),
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
|
|
|
@ -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),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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: [
|
||||
|
|
Loading…
Reference in a new issue