removed noisy const
This commit is contained in:
parent
c7670b9ccf
commit
d715d628be
51 changed files with 282 additions and 282 deletions
|
@ -45,10 +45,10 @@ class _AvesAppState extends State<AvesApp> {
|
||||||
scaffoldBackgroundColor: Colors.grey[900],
|
scaffoldBackgroundColor: Colors.grey[900],
|
||||||
buttonColor: accentColor,
|
buttonColor: accentColor,
|
||||||
toggleableActiveColor: accentColor,
|
toggleableActiveColor: accentColor,
|
||||||
tooltipTheme: const TooltipThemeData(
|
tooltipTheme: TooltipThemeData(
|
||||||
verticalOffset: 32,
|
verticalOffset: 32,
|
||||||
),
|
),
|
||||||
appBarTheme: const AppBarTheme(
|
appBarTheme: AppBarTheme(
|
||||||
textTheme: TextTheme(
|
textTheme: TextTheme(
|
||||||
headline6: TextStyle(
|
headline6: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
|
@ -61,9 +61,9 @@ class _AvesAppState extends State<AvesApp> {
|
||||||
home: FutureBuilder<void>(
|
home: FutureBuilder<void>(
|
||||||
future: _appSetup,
|
future: _appSetup,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return const Icon(AIcons.error);
|
if (snapshot.hasError) return Icon(AIcons.error);
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const Scaffold();
|
if (snapshot.connectionState != ConnectionState.done) return Scaffold();
|
||||||
return settings.hasAcceptedTerms ? const HomePage() : const WelcomePage();
|
return settings.hasAcceptedTerms ? HomePage() : WelcomePage();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -177,7 +177,7 @@ class CollectionLens with ChangeNotifier, CollectionActivityMixin, CollectionSel
|
||||||
final va = androidFileUtils.getStorageVolume(a)?.path ?? '';
|
final va = androidFileUtils.getStorageVolume(a)?.path ?? '';
|
||||||
final vb = androidFileUtils.getStorageVolume(b)?.path ?? '';
|
final vb = androidFileUtils.getStorageVolume(b)?.path ?? '';
|
||||||
return compareAsciiUpperCase(va, vb);
|
return compareAsciiUpperCase(va, vb);
|
||||||
};
|
}
|
||||||
sections = SplayTreeMap.of(byAlbum, compare);
|
sections = SplayTreeMap.of(byAlbum, compare);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ class CollectionSource with SourceBase, AlbumMixin, LocationMixin, TagMixin {
|
||||||
_rawEntries.addAll(entries);
|
_rawEntries.addAll(entries);
|
||||||
addFolderPath(_rawEntries.map((entry) => entry.directory));
|
addFolderPath(_rawEntries.map((entry) => entry.directory));
|
||||||
invalidateFilterEntryCounts();
|
invalidateFilterEntryCounts();
|
||||||
eventBus.fire(const EntryAddedEvent());
|
eventBus.fire(EntryAddedEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeEntries(Iterable<ImageEntry> entries) {
|
void removeEntries(Iterable<ImageEntry> entries) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ class MetadataService {
|
||||||
debugPrint('getCatalogMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}');
|
debugPrint('getCatalogMetadata failed with code=${e.code}, exception=${e.message}, details=${e.details}');
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
return background
|
return background
|
||||||
? servicePolicy.call(
|
? servicePolicy.call(
|
||||||
call,
|
call,
|
||||||
|
|
|
@ -20,7 +20,7 @@ extension ExtraDateTime on DateTime {
|
||||||
|
|
||||||
bool get isToday => isAtSameDayAs(DateTime.now());
|
bool get isToday => isAtSameDayAs(DateTime.now());
|
||||||
|
|
||||||
bool get isYesterday => isAtSameDayAs(DateTime.now().subtract(const Duration(days: 1)));
|
bool get isYesterday => isAtSameDayAs(DateTime.now().subtract(Duration(days: 1)));
|
||||||
|
|
||||||
bool get isThisMonth => isAtSameMonthAs(DateTime.now());
|
bool get isThisMonth => isAtSameMonthAs(DateTime.now());
|
||||||
|
|
||||||
|
|
|
@ -11,20 +11,20 @@ class AboutPage extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('About'),
|
title: Text('About'),
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: AnimationLimiter(
|
child: AnimationLimiter(
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
padding: const EdgeInsets.only(top: 16),
|
padding: EdgeInsets.only(top: 16),
|
||||||
sliver: SliverList(
|
sliver: SliverList(
|
||||||
delegate: SliverChildListDelegate(
|
delegate: SliverChildListDelegate(
|
||||||
[
|
[
|
||||||
AppReference(),
|
AppReference(),
|
||||||
const SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
const Divider(),
|
Divider(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -92,7 +92,7 @@ class _AppReferenceState extends State<AppReference> {
|
||||||
children: [
|
children: [
|
||||||
WidgetSpan(
|
WidgetSpan(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsetsDirectional.only(end: 4),
|
padding: EdgeInsetsDirectional.only(end: 4),
|
||||||
child: FlutterLogo(
|
child: FlutterLogo(
|
||||||
size: style.fontSize * 1.25,
|
size: style.fontSize * 1.25,
|
||||||
),
|
),
|
||||||
|
|
|
@ -39,7 +39,7 @@ class _LicensesState extends State<Licenses> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SliverPadding(
|
return SliverPadding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
sliver: SliverList(
|
sliver: SliverList(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, index) {
|
(context, index) {
|
||||||
|
@ -69,7 +69,7 @@ class _LicensesState extends State<Licenses> {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsetsDirectional.only(start: 8),
|
padding: EdgeInsetsDirectional.only(start: 8),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -95,13 +95,13 @@ class _LicensesState extends State<Licenses> {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
tooltip: 'Sort',
|
tooltip: 'Sort',
|
||||||
icon: const Icon(AIcons.sort),
|
icon: Icon(AIcons.sort),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
const Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
child: Text('The following sets forth attribution notices for third party software that may be contained in this application.'),
|
child: Text('The following sets forth attribution notices for third party software that may be contained in this application.'),
|
||||||
),
|
),
|
||||||
|
@ -122,17 +122,17 @@ class LicenseRow extends StatelessWidget {
|
||||||
final subColor = bodyTextStyle.color.withOpacity(.6);
|
final subColor = bodyTextStyle.color.withOpacity(.6);
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(top: 16),
|
padding: EdgeInsets.only(top: 16),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
LinkChip(
|
LinkChip(
|
||||||
text: package.name,
|
text: package.name,
|
||||||
url: package.sourceUrl,
|
url: package.sourceUrl,
|
||||||
textStyle: const TextStyle(fontWeight: FontWeight.bold),
|
textStyle: TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsetsDirectional.only(start: 16),
|
padding: EdgeInsetsDirectional.only(start: 16),
|
||||||
child: LinkChip(
|
child: LinkChip(
|
||||||
text: package.license,
|
text: package.license,
|
||||||
url: package.licenseUrl,
|
url: package.licenseUrl,
|
||||||
|
|
|
@ -144,7 +144,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
// so that we can also detect taps around the title `Text`
|
// so that we can also detect taps around the title `Text`
|
||||||
child: Container(
|
child: Container(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: NavigationToolbar.kMiddleSpacing),
|
padding: EdgeInsets.symmetric(horizontal: NavigationToolbar.kMiddleSpacing),
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
height: kToolbarHeight,
|
height: kToolbarHeight,
|
||||||
child: title,
|
child: title,
|
||||||
|
@ -166,7 +166,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
return [
|
return [
|
||||||
if (collection.isBrowsing)
|
if (collection.isBrowsing)
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(AIcons.search),
|
icon: Icon(AIcons.search),
|
||||||
onPressed: _goToSearch,
|
onPressed: _goToSearch,
|
||||||
),
|
),
|
||||||
if (collection.isSelecting)
|
if (collection.isSelecting)
|
||||||
|
@ -190,15 +190,15 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
if (collection.isBrowsing) ...[
|
if (collection.isBrowsing) ...[
|
||||||
if (AvesApp.mode == AppMode.main)
|
if (AvesApp.mode == AppMode.main)
|
||||||
if (kDebugMode)
|
if (kDebugMode)
|
||||||
const PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: CollectionAction.refresh,
|
value: CollectionAction.refresh,
|
||||||
child: MenuRow(text: 'Refresh', icon: AIcons.refresh),
|
child: MenuRow(text: 'Refresh', icon: AIcons.refresh),
|
||||||
),
|
),
|
||||||
const PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: CollectionAction.select,
|
value: CollectionAction.select,
|
||||||
child: MenuRow(text: 'Select', icon: AIcons.select),
|
child: MenuRow(text: 'Select', icon: AIcons.select),
|
||||||
),
|
),
|
||||||
const PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: CollectionAction.stats,
|
value: CollectionAction.stats,
|
||||||
child: MenuRow(text: 'Stats', icon: AIcons.stats),
|
child: MenuRow(text: 'Stats', icon: AIcons.stats),
|
||||||
),
|
),
|
||||||
|
@ -207,27 +207,27 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: CollectionAction.copy,
|
value: CollectionAction.copy,
|
||||||
enabled: hasSelection,
|
enabled: hasSelection,
|
||||||
child: const MenuRow(text: 'Copy to album'),
|
child: MenuRow(text: 'Copy to album'),
|
||||||
),
|
),
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: CollectionAction.move,
|
value: CollectionAction.move,
|
||||||
enabled: hasSelection,
|
enabled: hasSelection,
|
||||||
child: const MenuRow(text: 'Move to album'),
|
child: MenuRow(text: 'Move to album'),
|
||||||
),
|
),
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: CollectionAction.refreshMetadata,
|
value: CollectionAction.refreshMetadata,
|
||||||
enabled: hasSelection,
|
enabled: hasSelection,
|
||||||
child: const MenuRow(text: 'Refresh metadata'),
|
child: MenuRow(text: 'Refresh metadata'),
|
||||||
),
|
),
|
||||||
const PopupMenuDivider(),
|
PopupMenuDivider(),
|
||||||
const PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: CollectionAction.selectAll,
|
value: CollectionAction.selectAll,
|
||||||
child: MenuRow(text: 'Select all'),
|
child: MenuRow(text: 'Select all'),
|
||||||
),
|
),
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: CollectionAction.selectNone,
|
value: CollectionAction.selectNone,
|
||||||
enabled: hasSelection,
|
enabled: hasSelection,
|
||||||
child: const MenuRow(text: 'Select none'),
|
child: MenuRow(text: 'Select none'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
@ -252,7 +252,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
value: CollectionAction.sortByName,
|
value: CollectionAction.sortByName,
|
||||||
child: MenuRow(text: 'Sort by name', checked: collection.sortFactor == SortFactor.name),
|
child: MenuRow(text: 'Sort by name', checked: collection.sortFactor == SortFactor.name),
|
||||||
),
|
),
|
||||||
const PopupMenuDivider(),
|
PopupMenuDivider(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,7 +271,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
value: CollectionAction.groupByDay,
|
value: CollectionAction.groupByDay,
|
||||||
child: MenuRow(text: 'Group by day', checked: collection.groupFactor == GroupFactor.day),
|
child: MenuRow(text: 'Group by day', checked: collection.groupFactor == GroupFactor.day),
|
||||||
),
|
),
|
||||||
const PopupMenuDivider(),
|
PopupMenuDivider(),
|
||||||
]
|
]
|
||||||
: [];
|
: [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,10 @@ class EmptyContent extends StatelessWidget {
|
||||||
size: 64,
|
size: 64,
|
||||||
color: color,
|
color: color,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
text,
|
text,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
color: color,
|
color: color,
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
fontFamily: 'Concourse',
|
fontFamily: 'Concourse',
|
||||||
|
|
|
@ -18,7 +18,7 @@ class FilterBar extends StatefulWidget implements PreferredSizeWidget {
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final Size preferredSize = const Size.fromHeight(preferredHeight);
|
final Size preferredSize = Size.fromHeight(preferredHeight);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_FilterBarState createState() => _FilterBarState();
|
_FilterBarState createState() => _FilterBarState();
|
||||||
|
@ -85,8 +85,8 @@ class _FilterBarState extends State<FilterBar> {
|
||||||
key: _animatedListKey,
|
key: _animatedListKey,
|
||||||
initialItemCount: widget.filters.length,
|
initialItemCount: widget.filters.length,
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
physics: const BouncingScrollPhysics(),
|
physics: BouncingScrollPhysics(),
|
||||||
padding: const EdgeInsets.only(left: 8),
|
padding: EdgeInsets.only(left: 8),
|
||||||
itemBuilder: (context, index, animation) {
|
itemBuilder: (context, index, animation) {
|
||||||
if (index >= widget.filters.length) return null;
|
if (index >= widget.filters.length) return null;
|
||||||
return _buildChip(widget.filters.toList()[index]);
|
return _buildChip(widget.filters.toList()[index]);
|
||||||
|
@ -98,7 +98,7 @@ class _FilterBarState extends State<FilterBar> {
|
||||||
|
|
||||||
Padding _buildChip(CollectionFilter filter) {
|
Padding _buildChip(CollectionFilter filter) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(right: 8),
|
padding: EdgeInsets.only(right: 8),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: AvesFilterChip(
|
child: AvesFilterChip(
|
||||||
key: ValueKey(filter),
|
key: ValueKey(filter),
|
||||||
|
|
|
@ -29,7 +29,7 @@ class AlbumSectionHeader extends StatelessWidget {
|
||||||
leading: albumIcon,
|
leading: albumIcon,
|
||||||
title: albumName,
|
title: albumName,
|
||||||
trailing: androidFileUtils.isOnRemovableStorage(folderPath)
|
trailing: androidFileUtils.isOnRemovableStorage(folderPath)
|
||||||
? const Icon(
|
? Icon(
|
||||||
AIcons.removableStorage,
|
AIcons.removableStorage,
|
||||||
size: 16,
|
size: 16,
|
||||||
color: Color(0xFF757575),
|
color: Color(0xFF757575),
|
||||||
|
|
|
@ -54,7 +54,7 @@ class SectionHeader extends StatelessWidget {
|
||||||
height: height,
|
height: height,
|
||||||
child: header,
|
child: header,
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink();
|
: SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAlbumSectionHeader() {
|
Widget _buildAlbumSectionHeader() {
|
||||||
|
@ -128,7 +128,7 @@ class TitleSectionHeader extends StatelessWidget {
|
||||||
return Container(
|
return Container(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
padding: padding,
|
padding: padding,
|
||||||
constraints: const BoxConstraints(minHeight: leadingDimension),
|
constraints: BoxConstraints(minHeight: leadingDimension),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => _toggleSectionSelection(context),
|
onTap: () => _toggleSectionSelection(context),
|
||||||
child: Text.rich(
|
child: Text.rich(
|
||||||
|
@ -213,12 +213,12 @@ class SectionSelectableLeading extends StatelessWidget {
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
iconSize: 26,
|
iconSize: 26,
|
||||||
padding: const EdgeInsets.only(top: 1),
|
padding: EdgeInsets.only(top: 1),
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
icon: Icon(selected ? AIcons.selected : AIcons.unselected),
|
icon: Icon(selected ? AIcons.selected : AIcons.unselected),
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
tooltip: selected ? 'Deselect section' : 'Select section',
|
tooltip: selected ? 'Deselect section' : 'Select section',
|
||||||
constraints: const BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
minHeight: leadingDimension,
|
minHeight: leadingDimension,
|
||||||
minWidth: leadingDimension,
|
minWidth: leadingDimension,
|
||||||
),
|
),
|
||||||
|
@ -236,7 +236,7 @@ class SectionSelectableLeading extends StatelessWidget {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: browsingBuilder?.call(context) ?? const SizedBox(height: leadingDimension);
|
: browsingBuilder?.call(context) ?? SizedBox(height: leadingDimension);
|
||||||
return AnimatedSwitcher(
|
return AnimatedSwitcher(
|
||||||
duration: Durations.sectionHeaderAnimation,
|
duration: Durations.sectionHeaderAnimation,
|
||||||
switchInCurve: Curves.easeInOut,
|
switchInCurve: Curves.easeInOut,
|
||||||
|
|
|
@ -109,7 +109,7 @@ class SectionedListLayoutProvider extends StatelessWidget {
|
||||||
sectionKey: sectionKey,
|
sectionKey: sectionKey,
|
||||||
height: headerExtent,
|
height: headerExtent,
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink();
|
: SizedBox.shrink();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ class CollectionListSliver extends StatelessWidget {
|
||||||
(context, index) {
|
(context, index) {
|
||||||
if (index >= childCount) return null;
|
if (index >= childCount) return null;
|
||||||
final sectionLayout = sectionLayouts.firstWhere((section) => section.hasChild(index), orElse: () => null);
|
final sectionLayout = sectionLayouts.firstWhere((section) => section.hasChild(index), orElse: () => null);
|
||||||
return sectionLayout?.builder(context, index) ?? const SizedBox.shrink();
|
return sectionLayout?.builder(context, index) ?? SizedBox.shrink();
|
||||||
},
|
},
|
||||||
childCount: childCount,
|
childCount: childCount,
|
||||||
addAutomaticKeepAlives: false,
|
addAutomaticKeepAlives: false,
|
||||||
|
|
|
@ -192,7 +192,7 @@ class _ScaleOverlayState extends State<ScaleOverlay> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: const BoxDecoration(
|
: BoxDecoration(
|
||||||
// provide dummy gradient to lerp to the other one during animation
|
// provide dummy gradient to lerp to the other one during animation
|
||||||
gradient: RadialGradient(
|
gradient: RadialGradient(
|
||||||
colors: [
|
colors: [
|
||||||
|
|
|
@ -23,7 +23,7 @@ class ExpandableFilterRow extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (filters.isEmpty) return const SizedBox.shrink();
|
if (filters.isEmpty) return SizedBox.shrink();
|
||||||
|
|
||||||
final hasTitle = title != null && title.isNotEmpty;
|
final hasTitle = title != null && title.isNotEmpty;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class ExpandableFilterRow extends StatelessWidget {
|
||||||
Widget titleRow;
|
Widget titleRow;
|
||||||
if (hasTitle) {
|
if (hasTitle) {
|
||||||
titleRow = Padding(
|
titleRow = Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
|
@ -52,7 +52,7 @@ class ExpandableFilterRow extends StatelessWidget {
|
||||||
final filtersList = filters.toList();
|
final filtersList = filters.toList();
|
||||||
final wrap = Container(
|
final wrap = Container(
|
||||||
key: ValueKey('wrap$title'),
|
key: ValueKey('wrap$title'),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: horizontalPadding),
|
padding: EdgeInsets.symmetric(horizontal: horizontalPadding),
|
||||||
// specify transparent as a workaround to prevent
|
// specify transparent as a workaround to prevent
|
||||||
// chip border clipping when the floating app bar is fading
|
// chip border clipping when the floating app bar is fading
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
|
@ -75,8 +75,8 @@ class ExpandableFilterRow extends StatelessWidget {
|
||||||
height: AvesFilterChip.minChipHeight,
|
height: AvesFilterChip.minChipHeight,
|
||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
physics: const BouncingScrollPhysics(),
|
physics: BouncingScrollPhysics(),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: horizontalPadding),
|
padding: EdgeInsets.symmetric(horizontal: horizontalPadding),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (index >= filtersList.length) return null;
|
if (index >= filtersList.length) return null;
|
||||||
final filter = filtersList[index];
|
final filter = filtersList[index];
|
||||||
|
@ -85,7 +85,7 @@ class ExpandableFilterRow extends StatelessWidget {
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (context, index) => const SizedBox(width: 8),
|
separatorBuilder: (context, index) => SizedBox(width: 8),
|
||||||
itemCount: filtersList.length,
|
itemCount: filtersList.length,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -44,7 +44,7 @@ class ImageSearchDelegate extends SearchDelegate<CollectionFilter> {
|
||||||
return [
|
return [
|
||||||
if (query.isNotEmpty)
|
if (query.isNotEmpty)
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(AIcons.clear),
|
icon: Icon(AIcons.clear),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
query = '';
|
query = '';
|
||||||
showSuggestions(context);
|
showSuggestions(context);
|
||||||
|
@ -63,7 +63,7 @@ class ImageSearchDelegate extends SearchDelegate<CollectionFilter> {
|
||||||
valueListenable: expandedSectionNotifier,
|
valueListenable: expandedSectionNotifier,
|
||||||
builder: (context, expandedSection, child) {
|
builder: (context, expandedSection, child) {
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.only(top: 8),
|
padding: EdgeInsets.only(top: 8),
|
||||||
children: [
|
children: [
|
||||||
_buildFilterRow(
|
_buildFilterRow(
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -135,7 +135,7 @@ class ImageSearchDelegate extends SearchDelegate<CollectionFilter> {
|
||||||
// and possibly trigger a rebuild here
|
// and possibly trigger a rebuild here
|
||||||
_select(context, _buildQueryFilter(true));
|
_select(context, _buildQueryFilter(true));
|
||||||
});
|
});
|
||||||
return const SizedBox.shrink();
|
return SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryFilter _buildQueryFilter(bool colorful) {
|
QueryFilter _buildQueryFilter(bool colorful) {
|
||||||
|
|
|
@ -75,7 +75,7 @@ class ThumbnailSelectionOverlay extends StatelessWidget {
|
||||||
icon: selected ? AIcons.selected : AIcons.unselected,
|
icon: selected ? AIcons.selected : AIcons.unselected,
|
||||||
size: iconSize,
|
size: iconSize,
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink();
|
: SizedBox.shrink();
|
||||||
child = AnimatedSwitcher(
|
child = AnimatedSwitcher(
|
||||||
duration: duration,
|
duration: duration,
|
||||||
switchInCurve: Curves.easeOutBack,
|
switchInCurve: Curves.easeOutBack,
|
||||||
|
@ -95,7 +95,7 @@ class ThumbnailSelectionOverlay extends StatelessWidget {
|
||||||
return child;
|
return child;
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink();
|
: SizedBox.shrink();
|
||||||
return AnimatedSwitcher(
|
return AnimatedSwitcher(
|
||||||
duration: duration,
|
duration: duration,
|
||||||
child: child,
|
child: child,
|
||||||
|
|
|
@ -81,7 +81,7 @@ class _ThumbnailRasterImageState extends State<ThumbnailRasterImage> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final fastImage = Image(
|
final fastImage = Image(
|
||||||
key: const ValueKey('LQ'),
|
key: ValueKey('LQ'),
|
||||||
image: _fastThumbnailProvider,
|
image: _fastThumbnailProvider,
|
||||||
width: extent,
|
width: extent,
|
||||||
height: extent,
|
height: extent,
|
||||||
|
@ -90,7 +90,7 @@ class _ThumbnailRasterImageState extends State<ThumbnailRasterImage> {
|
||||||
final image = _sizedThumbnailProvider == null
|
final image = _sizedThumbnailProvider == null
|
||||||
? fastImage
|
? fastImage
|
||||||
: Image(
|
: Image(
|
||||||
key: const ValueKey('HQ'),
|
key: ValueKey('HQ'),
|
||||||
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
|
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
|
||||||
if (wasSynchronouslyLoaded) return child;
|
if (wasSynchronouslyLoaded) return child;
|
||||||
return AnimatedSwitcher(
|
return AnimatedSwitcher(
|
||||||
|
|
|
@ -36,7 +36,7 @@ class ThumbnailCollection extends StatelessWidget {
|
||||||
final mqSize = mq.item1;
|
final mqSize = mq.item1;
|
||||||
final mqHorizontalPadding = mq.item2;
|
final mqHorizontalPadding = mq.item2;
|
||||||
|
|
||||||
if (mqSize.isEmpty) return const SizedBox.shrink();
|
if (mqSize.isEmpty) return SizedBox.shrink();
|
||||||
|
|
||||||
TileExtentManager.applyTileExtent(mqSize, mqHorizontalPadding, _tileExtentNotifier);
|
TileExtentManager.applyTileExtent(mqSize, mqHorizontalPadding, _tileExtentNotifier);
|
||||||
final cacheExtent = TileExtentManager.extentMaxForSize(mqSize) * 2;
|
final cacheExtent = TileExtentManager.extentMaxForSize(mqSize) * 2;
|
||||||
|
@ -159,7 +159,7 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
|
||||||
primary: true,
|
primary: true,
|
||||||
// workaround to prevent scrolling the app bar away
|
// workaround to prevent scrolling the app bar away
|
||||||
// when there is no content and we use `SliverFillRemaining`
|
// when there is no content and we use `SliverFillRemaining`
|
||||||
physics: collection.isEmpty ? const NeverScrollableScrollPhysics() : const SloppyScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
|
physics: collection.isEmpty ? NeverScrollableScrollPhysics() : SloppyScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
|
||||||
cacheExtent: widget.cacheExtent,
|
cacheExtent: widget.cacheExtent,
|
||||||
slivers: [
|
slivers: [
|
||||||
appBar,
|
appBar,
|
||||||
|
@ -168,7 +168,7 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
|
||||||
child: _buildEmptyCollectionPlaceholder(collection),
|
child: _buildEmptyCollectionPlaceholder(collection),
|
||||||
hasScrollBody: false,
|
hasScrollBody: false,
|
||||||
)
|
)
|
||||||
: const CollectionListSliver(),
|
: CollectionListSliver(),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Selector<MediaQueryData, double>(
|
child: Selector<MediaQueryData, double>(
|
||||||
selector: (context, mq) => mq.viewInsets.bottom,
|
selector: (context, mq) => mq.viewInsets.bottom,
|
||||||
|
@ -211,22 +211,22 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
|
||||||
valueListenable: collection.source.stateNotifier,
|
valueListenable: collection.source.stateNotifier,
|
||||||
builder: (context, sourceState, child) {
|
builder: (context, sourceState, child) {
|
||||||
if (sourceState == SourceState.loading) {
|
if (sourceState == SourceState.loading) {
|
||||||
return const SizedBox.shrink();
|
return SizedBox.shrink();
|
||||||
}
|
}
|
||||||
if (collection.filters.any((filter) => filter is FavouriteFilter)) {
|
if (collection.filters.any((filter) => filter is FavouriteFilter)) {
|
||||||
return const EmptyContent(
|
return EmptyContent(
|
||||||
icon: AIcons.favourite,
|
icon: AIcons.favourite,
|
||||||
text: 'No favourites',
|
text: 'No favourites',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
debugPrint('collection.filters=${collection.filters}');
|
debugPrint('collection.filters=${collection.filters}');
|
||||||
if (collection.filters.any((filter) => filter is MimeFilter && filter.mime == MimeTypes.anyVideo)) {
|
if (collection.filters.any((filter) => filter is MimeFilter && filter.mime == MimeTypes.anyVideo)) {
|
||||||
return const EmptyContent(
|
return EmptyContent(
|
||||||
icon: AIcons.video,
|
icon: AIcons.video,
|
||||||
text: 'No videos',
|
text: 'No videos',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return const EmptyContent(
|
return EmptyContent(
|
||||||
icon: AIcons.image,
|
icon: AIcons.image,
|
||||||
text: 'No images',
|
text: 'No images',
|
||||||
);
|
);
|
||||||
|
|
|
@ -46,7 +46,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
color: Theme.of(context).accentColor,
|
color: Theme.of(context).accentColor,
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -58,8 +58,8 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
spacing: 16,
|
spacing: 16,
|
||||||
crossAxisAlignment: WrapCrossAlignment.center,
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const AvesLogo(size: 64),
|
AvesLogo(size: 64),
|
||||||
const Text(
|
Text(
|
||||||
'Aves',
|
'Aves',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 44,
|
fontSize: 44,
|
||||||
|
@ -77,19 +77,19 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
|
|
||||||
final allMediaEntry = _FilteredCollectionNavTile(
|
final allMediaEntry = _FilteredCollectionNavTile(
|
||||||
source: source,
|
source: source,
|
||||||
leading: const Icon(AIcons.allMedia),
|
leading: Icon(AIcons.allMedia),
|
||||||
title: 'All media',
|
title: 'All media',
|
||||||
filter: null,
|
filter: null,
|
||||||
);
|
);
|
||||||
final videoEntry = _FilteredCollectionNavTile(
|
final videoEntry = _FilteredCollectionNavTile(
|
||||||
source: source,
|
source: source,
|
||||||
leading: const Icon(AIcons.video),
|
leading: Icon(AIcons.video),
|
||||||
title: 'Videos',
|
title: 'Videos',
|
||||||
filter: MimeFilter(MimeTypes.anyVideo),
|
filter: MimeFilter(MimeTypes.anyVideo),
|
||||||
);
|
);
|
||||||
final favouriteEntry = _FilteredCollectionNavTile(
|
final favouriteEntry = _FilteredCollectionNavTile(
|
||||||
source: source,
|
source: source,
|
||||||
leading: const Icon(AIcons.favourite),
|
leading: Icon(AIcons.favourite),
|
||||||
title: 'Favourites',
|
title: 'Favourites',
|
||||||
filter: FavouriteFilter(),
|
filter: FavouriteFilter(),
|
||||||
);
|
);
|
||||||
|
@ -97,8 +97,8 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
top: false,
|
top: false,
|
||||||
bottom: false,
|
bottom: false,
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: const Icon(AIcons.info),
|
leading: Icon(AIcons.info),
|
||||||
title: const Text('About'),
|
title: Text('About'),
|
||||||
onTap: () => _goToAbout(context),
|
onTap: () => _goToAbout(context),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -109,20 +109,20 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
videoEntry,
|
videoEntry,
|
||||||
favouriteEntry,
|
favouriteEntry,
|
||||||
_buildSpecialAlbumSection(),
|
_buildSpecialAlbumSection(),
|
||||||
const Divider(),
|
Divider(),
|
||||||
_buildRegularAlbumSection(),
|
_buildRegularAlbumSection(),
|
||||||
_buildCountrySection(),
|
_buildCountrySection(),
|
||||||
_buildTagSection(),
|
_buildTagSection(),
|
||||||
const Divider(),
|
Divider(),
|
||||||
aboutEntry,
|
aboutEntry,
|
||||||
if (kDebugMode) ...[
|
if (kDebugMode) ...[
|
||||||
const Divider(),
|
Divider(),
|
||||||
SafeArea(
|
SafeArea(
|
||||||
top: false,
|
top: false,
|
||||||
bottom: false,
|
bottom: false,
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: const Icon(AIcons.debug),
|
leading: Icon(AIcons.debug),
|
||||||
title: const Text('Debug'),
|
title: Text('Debug'),
|
||||||
onTap: () => _goToDebug(context),
|
onTap: () => _goToDebug(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -157,7 +157,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
leading: IconUtils.getAlbumIcon(context: context, album: album),
|
leading: IconUtils.getAlbumIcon(context: context, album: album),
|
||||||
title: uniqueName,
|
title: uniqueName,
|
||||||
trailing: androidFileUtils.isOnRemovableStorage(album)
|
trailing: androidFileUtils.isOnRemovableStorage(album)
|
||||||
? const Icon(
|
? Icon(
|
||||||
AIcons.removableStorage,
|
AIcons.removableStorage,
|
||||||
size: 16,
|
size: 16,
|
||||||
color: Colors.grey,
|
color: Colors.grey,
|
||||||
|
@ -177,10 +177,10 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
return type != AlbumType.regular && type != AlbumType.app;
|
return type != AlbumType.regular && type != AlbumType.app;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (specialAlbums.isEmpty) return const SizedBox.shrink();
|
if (specialAlbums.isEmpty) return SizedBox.shrink();
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
const Divider(),
|
Divider(),
|
||||||
...specialAlbums.map((album) => _buildAlbumEntry(album, dense: false)),
|
...specialAlbums.map((album) => _buildAlbumEntry(album, dense: false)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -192,8 +192,8 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
top: false,
|
top: false,
|
||||||
bottom: false,
|
bottom: false,
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: const Icon(AIcons.album),
|
leading: Icon(AIcons.album),
|
||||||
title: const Text('Albums'),
|
title: Text('Albums'),
|
||||||
trailing: StreamBuilder(
|
trailing: StreamBuilder(
|
||||||
stream: source.eventBus.on<AlbumsChangedEvent>(),
|
stream: source.eventBus.on<AlbumsChangedEvent>(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
@ -214,8 +214,8 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
top: false,
|
top: false,
|
||||||
bottom: false,
|
bottom: false,
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: const Icon(AIcons.location),
|
leading: Icon(AIcons.location),
|
||||||
title: const Text('Countries'),
|
title: Text('Countries'),
|
||||||
trailing: StreamBuilder(
|
trailing: StreamBuilder(
|
||||||
stream: source.eventBus.on<LocationsChangedEvent>(),
|
stream: source.eventBus.on<LocationsChangedEvent>(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
@ -236,8 +236,8 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
top: false,
|
top: false,
|
||||||
bottom: false,
|
bottom: false,
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: const Icon(AIcons.tag),
|
leading: Icon(AIcons.tag),
|
||||||
title: const Text('Tags'),
|
title: Text('Tags'),
|
||||||
trailing: StreamBuilder(
|
trailing: StreamBuilder(
|
||||||
stream: source.eventBus.on<TagsChangedEvent>(),
|
stream: source.eventBus.on<TagsChangedEvent>(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
@ -263,7 +263,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
title: 'Albums',
|
title: 'Albums',
|
||||||
filterEntries: source.getAlbumEntries(),
|
filterEntries: source.getAlbumEntries(),
|
||||||
filterBuilder: (s) => AlbumFilter(s, source.getUniqueAlbumName(s)),
|
filterBuilder: (s) => AlbumFilter(s, source.getUniqueAlbumName(s)),
|
||||||
emptyBuilder: () => const EmptyContent(
|
emptyBuilder: () => EmptyContent(
|
||||||
icon: AIcons.album,
|
icon: AIcons.album,
|
||||||
text: 'No albums',
|
text: 'No albums',
|
||||||
),
|
),
|
||||||
|
@ -282,7 +282,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
title: 'Countries',
|
title: 'Countries',
|
||||||
filterEntries: source.getCountryEntries(),
|
filterEntries: source.getCountryEntries(),
|
||||||
filterBuilder: (s) => LocationFilter(LocationLevel.country, s),
|
filterBuilder: (s) => LocationFilter(LocationLevel.country, s),
|
||||||
emptyBuilder: () => const EmptyContent(
|
emptyBuilder: () => EmptyContent(
|
||||||
icon: AIcons.location,
|
icon: AIcons.location,
|
||||||
text: 'No countries',
|
text: 'No countries',
|
||||||
),
|
),
|
||||||
|
@ -301,7 +301,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||||
title: 'Tags',
|
title: 'Tags',
|
||||||
filterEntries: source.getTagEntries(),
|
filterEntries: source.getTagEntries(),
|
||||||
filterBuilder: (s) => TagFilter(s),
|
filterBuilder: (s) => TagFilter(s),
|
||||||
emptyBuilder: () => const EmptyContent(
|
emptyBuilder: () => EmptyContent(
|
||||||
icon: AIcons.tag,
|
icon: AIcons.tag,
|
||||||
text: 'No tags',
|
text: 'No tags',
|
||||||
),
|
),
|
||||||
|
|
|
@ -34,7 +34,7 @@ class _CreateAlbumDialogState extends State<CreateAlbumDialog> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text('New Album'),
|
title: Text('New Album'),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
@ -42,8 +42,8 @@ class _CreateAlbumDialogState extends State<CreateAlbumDialog> {
|
||||||
Row(
|
Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Text('Storage:'),
|
Text('Storage:'),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: DropdownButton<StorageVolume>(
|
child: DropdownButton<StorageVolume>(
|
||||||
isExpanded: true,
|
isExpanded: true,
|
||||||
|
@ -68,7 +68,7 @@ class _CreateAlbumDialogState extends State<CreateAlbumDialog> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
ValueListenableBuilder<bool>(
|
ValueListenableBuilder<bool>(
|
||||||
valueListenable: _existsNotifier,
|
valueListenable: _existsNotifier,
|
||||||
|
@ -84,7 +84,7 @@ class _CreateAlbumDialogState extends State<CreateAlbumDialog> {
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 0),
|
contentPadding: EdgeInsets.fromLTRB(24, 20, 24, 0),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
FlatButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
|
|
|
@ -120,7 +120,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin {
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
content: const Text('Are you sure?'),
|
content: Text('Are you sure?'),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
FlatButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
|
|
|
@ -11,7 +11,7 @@ mixin FeedbackMixin {
|
||||||
void showFeedback(BuildContext context, String message) {
|
void showFeedback(BuildContext context, String message) {
|
||||||
_flushbar = Flushbar(
|
_flushbar = Flushbar(
|
||||||
message: message,
|
message: message,
|
||||||
margin: const EdgeInsets.all(8),
|
margin: EdgeInsets.all(8),
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
borderColor: Colors.white30,
|
borderColor: Colors.white30,
|
||||||
borderWidth: 0.5,
|
borderWidth: 0.5,
|
||||||
|
|
|
@ -23,7 +23,7 @@ mixin PermissionAwareMixin {
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text('Storage Volume Access'),
|
title: Text('Storage Volume Access'),
|
||||||
content: Text('Please select the $dirDisplayName directory of “$volumeDescription” in the next screen, so that this app can access it and complete your request.'),
|
content: Text('Please select the $dirDisplayName directory of “$volumeDescription” in the next screen, so that this app can access it and complete your request.'),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
FlatButton(
|
||||||
|
|
|
@ -69,7 +69,7 @@ class SelectionActionDelegate with FeedbackMixin, PermissionAwareMixin {
|
||||||
return FilterGridPage(
|
return FilterGridPage(
|
||||||
source: source,
|
source: source,
|
||||||
appBar: SliverAppBar(
|
appBar: SliverAppBar(
|
||||||
leading: const BackButton(),
|
leading: BackButton(),
|
||||||
title: Text(copy ? 'Copy to Album' : 'Move to Album'),
|
title: Text(copy ? 'Copy to Album' : 'Move to Album'),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
|
@ -90,7 +90,7 @@ class SelectionActionDelegate with FeedbackMixin, PermissionAwareMixin {
|
||||||
),
|
),
|
||||||
filterEntries: source.getAlbumEntries(),
|
filterEntries: source.getAlbumEntries(),
|
||||||
filterBuilder: (s) => AlbumFilter(s, source.getUniqueAlbumName(s)),
|
filterBuilder: (s) => AlbumFilter(s, source.getUniqueAlbumName(s)),
|
||||||
emptyBuilder: () => const EmptyContent(
|
emptyBuilder: () => EmptyContent(
|
||||||
icon: AIcons.album,
|
icon: AIcons.album,
|
||||||
text: 'No albums',
|
text: 'No albums',
|
||||||
),
|
),
|
||||||
|
@ -258,7 +258,7 @@ class SelectionActionDelegate with FeedbackMixin, PermissionAwareMixin {
|
||||||
child: StreamBuilder<T>(
|
child: StreamBuilder<T>(
|
||||||
stream: opStream,
|
stream: opStream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
Widget child = const SizedBox.shrink();
|
Widget child = SizedBox.shrink();
|
||||||
if (!snapshot.hasError && snapshot.connectionState == ConnectionState.active) {
|
if (!snapshot.hasError && snapshot.connectionState == ConnectionState.active) {
|
||||||
final percent = processed.length.toDouble() / selection.length;
|
final percent = processed.length.toDouble() / selection.length;
|
||||||
child = CircularPercentIndicator(
|
child = CircularPercentIndicator(
|
||||||
|
|
|
@ -32,7 +32,7 @@ class SourceStateAwareAppBarTitle extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: sourceState == SourceState.ready
|
child: sourceState == SourceState.ready
|
||||||
? const SizedBox.shrink()
|
? SizedBox.shrink()
|
||||||
: SourceStateSubtitle(
|
: SourceStateSubtitle(
|
||||||
source: source,
|
source: source,
|
||||||
),
|
),
|
||||||
|
@ -68,7 +68,7 @@ class SourceStateSubtitle extends StatelessWidget {
|
||||||
}
|
}
|
||||||
final subtitleStyle = Theme.of(context).textTheme.caption;
|
final subtitleStyle = Theme.of(context).textTheme.caption;
|
||||||
return subtitle == null
|
return subtitle == null
|
||||||
? const SizedBox.shrink()
|
? SizedBox.shrink()
|
||||||
: Row(
|
: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
@ -76,10 +76,10 @@ class SourceStateSubtitle extends StatelessWidget {
|
||||||
StreamBuilder<ProgressEvent>(
|
StreamBuilder<ProgressEvent>(
|
||||||
stream: source.progressStream,
|
stream: source.progressStream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError || !snapshot.hasData) return const SizedBox.shrink();
|
if (snapshot.hasError || !snapshot.hasData) return SizedBox.shrink();
|
||||||
final progress = snapshot.data;
|
final progress = snapshot.data;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsetsDirectional.only(start: 8),
|
padding: EdgeInsetsDirectional.only(start: 8),
|
||||||
child: Text(
|
child: Text(
|
||||||
'${progress.done}/${progress.total}',
|
'${progress.done}/${progress.total}',
|
||||||
style: subtitleStyle.copyWith(color: Colors.white30),
|
style: subtitleStyle.copyWith(color: Colors.white30),
|
||||||
|
|
|
@ -66,7 +66,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final hasBackground = widget.background != null;
|
final hasBackground = widget.background != null;
|
||||||
final leading = filter.iconBuilder(context, AvesFilterChip.iconSize, showGenericIcon: widget.showGenericIcon);
|
final leading = filter.iconBuilder(context, AvesFilterChip.iconSize, showGenericIcon: widget.showGenericIcon);
|
||||||
final trailing = widget.removable ? const Icon(AIcons.clear, size: AvesFilterChip.iconSize) : null;
|
final trailing = widget.removable ? Icon(AIcons.clear, size: AvesFilterChip.iconSize) : null;
|
||||||
|
|
||||||
Widget content = Row(
|
Widget content = Row(
|
||||||
mainAxisSize: hasBackground ? MainAxisSize.max : MainAxisSize.min,
|
mainAxisSize: hasBackground ? MainAxisSize.max : MainAxisSize.min,
|
||||||
|
@ -74,7 +74,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
|
||||||
children: [
|
children: [
|
||||||
if (leading != null) ...[
|
if (leading != null) ...[
|
||||||
leading,
|
leading,
|
||||||
const SizedBox(width: AvesFilterChip.padding),
|
SizedBox(width: AvesFilterChip.padding),
|
||||||
],
|
],
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
|
@ -85,7 +85,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (trailing != null) ...[
|
if (trailing != null) ...[
|
||||||
const SizedBox(width: AvesFilterChip.padding),
|
SizedBox(width: AvesFilterChip.padding),
|
||||||
trailing,
|
trailing,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
@ -102,7 +102,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
|
||||||
}
|
}
|
||||||
|
|
||||||
content = Padding(
|
content = Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.padding * 2, vertical: 2),
|
padding: EdgeInsets.symmetric(horizontal: AvesFilterChip.padding * 2, vertical: 2),
|
||||||
child: content,
|
child: content,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
|
||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
child: DefaultTextStyle(
|
child: DefaultTextStyle(
|
||||||
style: Theme.of(context).textTheme.bodyText2.copyWith(
|
style: Theme.of(context).textTheme.bodyText2.copyWith(
|
||||||
shadows: const [
|
shadows: [
|
||||||
Shadow(
|
Shadow(
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
offset: Offset(0.5, 1.0),
|
offset: Offset(0.5, 1.0),
|
||||||
|
@ -128,7 +128,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
|
||||||
final borderRadius = AvesFilterChip.borderRadius;
|
final borderRadius = AvesFilterChip.borderRadius;
|
||||||
|
|
||||||
Widget chip = Container(
|
Widget chip = Container(
|
||||||
constraints: const BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
minWidth: AvesFilterChip.minChipWidth,
|
minWidth: AvesFilterChip.minChipWidth,
|
||||||
maxWidth: AvesFilterChip.maxChipWidth,
|
maxWidth: AvesFilterChip.maxChipWidth,
|
||||||
minHeight: AvesFilterChip.minChipHeight,
|
minHeight: AvesFilterChip.minChipHeight,
|
||||||
|
@ -171,7 +171,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
|
||||||
),
|
),
|
||||||
position: DecorationPosition.foreground,
|
position: DecorationPosition.foreground,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
child: content,
|
child: content,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -55,7 +55,7 @@ class MediaStoreSource extends CollectionSource {
|
||||||
allNewEntries.addAll(pendingNewEntries);
|
allNewEntries.addAll(pendingNewEntries);
|
||||||
addAll(pendingNewEntries);
|
addAll(pendingNewEntries);
|
||||||
pendingNewEntries.clear();
|
pendingNewEntries.clear();
|
||||||
};
|
}
|
||||||
ImageFileService.getImageEntries(knownEntryMap).listen(
|
ImageFileService.getImageEntries(knownEntryMap).listen(
|
||||||
(entry) {
|
(entry) {
|
||||||
pendingNewEntries.add(entry);
|
pendingNewEntries.add(entry);
|
||||||
|
|
|
@ -131,10 +131,10 @@ class OverlayIcon extends StatelessWidget {
|
||||||
);
|
);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.all(1),
|
margin: EdgeInsets.all(1),
|
||||||
padding: text != null ? EdgeInsets.only(right: size / 4) : null,
|
padding: text != null ? EdgeInsets.only(right: size / 4) : null,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xBB000000),
|
color: Color(0xBB000000),
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
Radius.circular(size),
|
Radius.circular(size),
|
||||||
),
|
),
|
||||||
|
@ -146,7 +146,7 @@ class OverlayIcon extends StatelessWidget {
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
iconChild,
|
iconChild,
|
||||||
const SizedBox(width: 2),
|
SizedBox(width: 2),
|
||||||
Text(text),
|
Text(text),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,7 +23,7 @@ class LinkChip extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DefaultTextStyle.merge(
|
return DefaultTextStyle.merge(
|
||||||
style: (textStyle ?? const TextStyle()).copyWith(color: color),
|
style: (textStyle ?? TextStyle()).copyWith(color: color),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
@ -32,16 +32,16 @@ class LinkChip extends StatelessWidget {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(8.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
if (leading != null) ...[
|
if (leading != null) ...[
|
||||||
leading,
|
leading,
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
],
|
],
|
||||||
Text(text),
|
Text(text),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Builder(
|
Builder(
|
||||||
builder: (context) => Icon(
|
builder: (context) => Icon(
|
||||||
AIcons.openInNew,
|
AIcons.openInNew,
|
||||||
|
|
|
@ -20,13 +20,13 @@ class MenuRow extends StatelessWidget {
|
||||||
if (checked != null) ...[
|
if (checked != null) ...[
|
||||||
Opacity(
|
Opacity(
|
||||||
opacity: checked ? 1 : 0,
|
opacity: checked ? 1 : 0,
|
||||||
child: const Icon(AIcons.checked),
|
child: Icon(AIcons.checked),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
],
|
],
|
||||||
if (icon != null) ...[
|
if (icon != null) ...[
|
||||||
Icon(icon),
|
Icon(icon),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
],
|
],
|
||||||
Expanded(child: Text(text)),
|
Expanded(child: Text(text)),
|
||||||
],
|
],
|
||||||
|
|
|
@ -10,21 +10,21 @@ ScrollThumbBuilder avesScrollThumbBuilder({
|
||||||
@required Color backgroundColor,
|
@required Color backgroundColor,
|
||||||
}) {
|
}) {
|
||||||
final scrollThumb = Container(
|
final scrollThumb = Container(
|
||||||
decoration: const BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.black26,
|
color: Colors.black26,
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
Radius.circular(12.0),
|
Radius.circular(12.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
height: height,
|
height: height,
|
||||||
margin: const EdgeInsets.only(right: .5),
|
margin: EdgeInsets.only(right: .5),
|
||||||
padding: const EdgeInsets.all(2),
|
padding: EdgeInsets.all(2),
|
||||||
child: ClipPath(
|
child: ClipPath(
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 20.0,
|
width: 20.0,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: backgroundColor,
|
color: backgroundColor,
|
||||||
borderRadius: const BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
Radius.circular(12.0),
|
Radius.circular(12.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -51,8 +51,8 @@ class DebugPageState extends State<DebugPage> {
|
||||||
length: 4,
|
length: 4,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Debug'),
|
title: Text('Debug'),
|
||||||
bottom: const TabBar(
|
bottom: TabBar(
|
||||||
tabs: [
|
tabs: [
|
||||||
Tab(icon: Icon(OMIcons.whatshot)),
|
Tab(icon: Icon(OMIcons.whatshot)),
|
||||||
Tab(icon: Icon(OMIcons.settings)),
|
Tab(icon: Icon(OMIcons.settings)),
|
||||||
|
@ -81,9 +81,9 @@ class DebugPageState extends State<DebugPage> {
|
||||||
final withGps = catalogued.where((entry) => entry.hasGps);
|
final withGps = catalogued.where((entry) => entry.hasGps);
|
||||||
final located = withGps.where((entry) => entry.isLocated);
|
final located = withGps.where((entry) => entry.isLocated);
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
const Text('Time dilation'),
|
Text('Time dilation'),
|
||||||
Slider(
|
Slider(
|
||||||
value: timeDilation,
|
value: timeDilation,
|
||||||
onChanged: (v) => setState(() => timeDilation = v),
|
onChanged: (v) => setState(() => timeDilation = v),
|
||||||
|
@ -92,24 +92,24 @@ class DebugPageState extends State<DebugPage> {
|
||||||
divisions: 9,
|
divisions: 9,
|
||||||
label: '$timeDilation',
|
label: '$timeDilation',
|
||||||
),
|
),
|
||||||
const Divider(),
|
Divider(),
|
||||||
Text('Entries: ${entries.length}'),
|
Text('Entries: ${entries.length}'),
|
||||||
Text('Catalogued: ${catalogued.length}'),
|
Text('Catalogued: ${catalogued.length}'),
|
||||||
Text('With GPS: ${withGps.length}'),
|
Text('With GPS: ${withGps.length}'),
|
||||||
Text('With address: ${located.length}'),
|
Text('With address: ${located.length}'),
|
||||||
const Divider(),
|
Divider(),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text('Image cache:\n\t${imageCache.currentSize}/${imageCache.maximumSize} items\n\t${formatFilesize(imageCache.currentSizeBytes)}/${formatFilesize(imageCache.maximumSizeBytes)}'),
|
child: Text('Image cache:\n\t${imageCache.currentSize}/${imageCache.maximumSize} items\n\t${formatFilesize(imageCache.currentSizeBytes)}/${formatFilesize(imageCache.maximumSizeBytes)}'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
imageCache.clear();
|
imageCache.clear();
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
child: const Text('Clear'),
|
child: Text('Clear'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -118,43 +118,43 @@ class DebugPageState extends State<DebugPage> {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text('SVG cache: ${PictureProvider.cacheCount} items'),
|
child: Text('SVG cache: ${PictureProvider.cacheCount} items'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
PictureProvider.clearCache();
|
PictureProvider.clearCache();
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
child: const Text('Clear'),
|
child: Text('Clear'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Expanded(
|
Expanded(
|
||||||
child: Text('Glide disk cache: ?'),
|
child: Text('Glide disk cache: ?'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
const RaisedButton(
|
RaisedButton(
|
||||||
onPressed: ImageFileService.clearSizedThumbnailDiskCache,
|
onPressed: ImageFileService.clearSizedThumbnailDiskCache,
|
||||||
child: Text('Clear'),
|
child: Text('Clear'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const Divider(),
|
Divider(),
|
||||||
FutureBuilder<int>(
|
FutureBuilder<int>(
|
||||||
future: _dbFileSizeLoader,
|
future: _dbFileSizeLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text('DB file size: ${formatFilesize(snapshot.data)}'),
|
child: Text('DB file size: ${formatFilesize(snapshot.data)}'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
onPressed: () => metadataDb.reset().then((_) => _startDbReport()),
|
onPressed: () => metadataDb.reset().then((_) => _startDbReport()),
|
||||||
child: const Text('Reset'),
|
child: Text('Reset'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -164,16 +164,16 @@ class DebugPageState extends State<DebugPage> {
|
||||||
future: _dbEntryLoader,
|
future: _dbEntryLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text('DB entry rows: ${snapshot.data.length}'),
|
child: Text('DB entry rows: ${snapshot.data.length}'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
onPressed: () => metadataDb.clearEntries().then((_) => _startDbReport()),
|
onPressed: () => metadataDb.clearEntries().then((_) => _startDbReport()),
|
||||||
child: const Text('Clear'),
|
child: Text('Clear'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -183,16 +183,16 @@ class DebugPageState extends State<DebugPage> {
|
||||||
future: _dbDateLoader,
|
future: _dbDateLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text('DB date rows: ${snapshot.data.length}'),
|
child: Text('DB date rows: ${snapshot.data.length}'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
onPressed: () => metadataDb.clearDates().then((_) => _startDbReport()),
|
onPressed: () => metadataDb.clearDates().then((_) => _startDbReport()),
|
||||||
child: const Text('Clear'),
|
child: Text('Clear'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -202,16 +202,16 @@ class DebugPageState extends State<DebugPage> {
|
||||||
future: _dbMetadataLoader,
|
future: _dbMetadataLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text('DB metadata rows: ${snapshot.data.length}'),
|
child: Text('DB metadata rows: ${snapshot.data.length}'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
onPressed: () => metadataDb.clearMetadataEntries().then((_) => _startDbReport()),
|
onPressed: () => metadataDb.clearMetadataEntries().then((_) => _startDbReport()),
|
||||||
child: const Text('Clear'),
|
child: Text('Clear'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -221,16 +221,16 @@ class DebugPageState extends State<DebugPage> {
|
||||||
future: _dbAddressLoader,
|
future: _dbAddressLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text('DB address rows: ${snapshot.data.length}'),
|
child: Text('DB address rows: ${snapshot.data.length}'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
onPressed: () => metadataDb.clearAddresses().then((_) => _startDbReport()),
|
onPressed: () => metadataDb.clearAddresses().then((_) => _startDbReport()),
|
||||||
child: const Text('Clear'),
|
child: Text('Clear'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -240,16 +240,16 @@ class DebugPageState extends State<DebugPage> {
|
||||||
future: _dbFavouritesLoader,
|
future: _dbFavouritesLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text('DB favourite rows: ${snapshot.data.length} (${favourites.count} in memory)'),
|
child: Text('DB favourite rows: ${snapshot.data.length} (${favourites.count} in memory)'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
onPressed: () => favourites.clear().then((_) => _startDbReport()),
|
onPressed: () => favourites.clear().then((_) => _startDbReport()),
|
||||||
child: const Text('Clear'),
|
child: Text('Clear'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -261,17 +261,17 @@ class DebugPageState extends State<DebugPage> {
|
||||||
|
|
||||||
Widget _buildSettingsTabView() {
|
Widget _buildSettingsTabView() {
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Expanded(
|
Expanded(
|
||||||
child: Text('Settings'),
|
child: Text('Settings'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
onPressed: () => settings.reset().then((_) => setState(() {})),
|
onPressed: () => settings.reset().then((_) => setState(() {})),
|
||||||
child: const Text('Reset'),
|
child: Text('Reset'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -287,7 +287,7 @@ class DebugPageState extends State<DebugPage> {
|
||||||
|
|
||||||
Widget _buildStorageTabView() {
|
Widget _buildStorageTabView() {
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
...androidFileUtils.storageVolumes.expand((v) => [
|
...androidFileUtils.storageVolumes.expand((v) => [
|
||||||
Text(v.path),
|
Text(v.path),
|
||||||
|
@ -298,7 +298,7 @@ class DebugPageState extends State<DebugPage> {
|
||||||
'isRemovable': '${v.isRemovable}',
|
'isRemovable': '${v.isRemovable}',
|
||||||
'state': '${v.state}',
|
'state': '${v.state}',
|
||||||
}),
|
}),
|
||||||
const Divider(),
|
Divider(),
|
||||||
])
|
])
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -306,13 +306,13 @@ class DebugPageState extends State<DebugPage> {
|
||||||
|
|
||||||
Widget _buildEnvTabView() {
|
Widget _buildEnvTabView() {
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
FutureBuilder<Map>(
|
FutureBuilder<Map>(
|
||||||
future: _envLoader,
|
future: _envLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
final data = SplayTreeMap.of(snapshot.data.map((k, v) => MapEntry(k.toString(), v?.toString() ?? 'null')));
|
final data = SplayTreeMap.of(snapshot.data.map((k, v) => MapEntry(k.toString(), v?.toString() ?? 'null')));
|
||||||
return InfoRowGroup(data);
|
return InfoRowGroup(data);
|
||||||
},
|
},
|
||||||
|
|
|
@ -106,7 +106,7 @@ class FilterGridPage extends StatelessWidget {
|
||||||
hasScrollBody: false,
|
hasScrollBody: false,
|
||||||
)
|
)
|
||||||
: SliverPadding(
|
: SliverPadding(
|
||||||
padding: const EdgeInsets.all(AvesFilterChip.outlineWidth),
|
padding: EdgeInsets.all(AvesFilterChip.outlineWidth),
|
||||||
sliver: SliverGrid(
|
sliver: SliverGrid(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, i) {
|
(context, i) {
|
||||||
|
@ -132,7 +132,7 @@ class FilterGridPage extends StatelessWidget {
|
||||||
},
|
},
|
||||||
childCount: filterKeys.length,
|
childCount: filterKeys.length,
|
||||||
),
|
),
|
||||||
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
maxCrossAxisExtent: maxCrossAxisExtent,
|
maxCrossAxisExtent: maxCrossAxisExtent,
|
||||||
mainAxisSpacing: 8,
|
mainAxisSpacing: 8,
|
||||||
crossAxisSpacing: 8,
|
crossAxisSpacing: 8,
|
||||||
|
@ -201,18 +201,18 @@ class DecoratedFilterChip extends StatelessWidget {
|
||||||
Widget _buildDetails(CollectionFilter filter) {
|
Widget _buildDetails(CollectionFilter filter) {
|
||||||
final count = Text(
|
final count = Text(
|
||||||
'${source.count(filter)}',
|
'${source.count(filter)}',
|
||||||
style: const TextStyle(color: FilterGridPage.detailColor),
|
style: TextStyle(color: FilterGridPage.detailColor),
|
||||||
);
|
);
|
||||||
return filter is AlbumFilter && androidFileUtils.isOnRemovableStorage(filter.album)
|
return filter is AlbumFilter && androidFileUtils.isOnRemovableStorage(filter.album)
|
||||||
? Row(
|
? Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Icon(
|
Icon(
|
||||||
AIcons.removableStorage,
|
AIcons.removableStorage,
|
||||||
size: 16,
|
size: 16,
|
||||||
color: FilterGridPage.detailColor,
|
color: FilterGridPage.detailColor,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
count,
|
count,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -37,8 +37,8 @@ class _FullscreenDebugPageState extends State<FullscreenDebugPage> {
|
||||||
length: 2,
|
length: 2,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Debug'),
|
title: Text('Debug'),
|
||||||
bottom: const TabBar(
|
bottom: TabBar(
|
||||||
tabs: [
|
tabs: [
|
||||||
Tab(text: 'DB'),
|
Tab(text: 'DB'),
|
||||||
Tab(text: 'Content Resolver'),
|
Tab(text: 'Content Resolver'),
|
||||||
|
@ -60,13 +60,13 @@ class _FullscreenDebugPageState extends State<FullscreenDebugPage> {
|
||||||
Widget _buildDbTabView() {
|
Widget _buildDbTabView() {
|
||||||
final catalog = widget.entry.catalogMetadata;
|
final catalog = widget.entry.catalogMetadata;
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
FutureBuilder<DateMetadata>(
|
FutureBuilder<DateMetadata>(
|
||||||
future: _dbDateLoader,
|
future: _dbDateLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
final data = snapshot.data;
|
final data = snapshot.data;
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -80,12 +80,12 @@ class _FullscreenDebugPageState extends State<FullscreenDebugPage> {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
FutureBuilder<CatalogMetadata>(
|
FutureBuilder<CatalogMetadata>(
|
||||||
future: _dbMetadataLoader,
|
future: _dbMetadataLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
final data = snapshot.data;
|
final data = snapshot.data;
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -106,12 +106,12 @@ class _FullscreenDebugPageState extends State<FullscreenDebugPage> {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
FutureBuilder<AddressDetails>(
|
FutureBuilder<AddressDetails>(
|
||||||
future: _dbAddressLoader,
|
future: _dbAddressLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
final data = snapshot.data;
|
final data = snapshot.data;
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -129,7 +129,7 @@ class _FullscreenDebugPageState extends State<FullscreenDebugPage> {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Divider(),
|
Divider(),
|
||||||
Text('Catalog metadata:${catalog == null ? ' no data' : ''}'),
|
Text('Catalog metadata:${catalog == null ? ' no data' : ''}'),
|
||||||
if (catalog != null)
|
if (catalog != null)
|
||||||
InfoRowGroup({
|
InfoRowGroup({
|
||||||
|
@ -153,13 +153,13 @@ class _FullscreenDebugPageState extends State<FullscreenDebugPage> {
|
||||||
|
|
||||||
Widget _buildContentResolverTabView() {
|
Widget _buildContentResolverTabView() {
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
FutureBuilder<Map>(
|
FutureBuilder<Map>(
|
||||||
future: _contentResolverMetadataLoader,
|
future: _contentResolverMetadataLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
final data = SplayTreeMap.of(snapshot.data.map((k, v) {
|
final data = SplayTreeMap.of(snapshot.data.map((k, v) {
|
||||||
final key = k.toString();
|
final key = k.toString();
|
||||||
var value = v?.toString() ?? 'null';
|
var value = v?.toString() ?? 'null';
|
||||||
|
|
|
@ -87,7 +87,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
// no bounce at the bottom, to avoid video controller displacement
|
// no bounce at the bottom, to avoid video controller displacement
|
||||||
curve: Curves.easeOutQuad,
|
curve: Curves.easeOutQuad,
|
||||||
);
|
);
|
||||||
_bottomOverlayOffset = Tween(begin: const Offset(0, 1), end: const Offset(0, 0)).animate(CurvedAnimation(
|
_bottomOverlayOffset = Tween(begin: Offset(0, 1), end: Offset(0, 0)).animate(CurvedAnimation(
|
||||||
parent: _overlayAnimationController,
|
parent: _overlayAnimationController,
|
||||||
curve: Curves.easeOutQuad,
|
curve: Curves.easeOutQuad,
|
||||||
));
|
));
|
||||||
|
@ -178,7 +178,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
final child = ValueListenableBuilder<ImageEntry>(
|
final child = ValueListenableBuilder<ImageEntry>(
|
||||||
valueListenable: _entryNotifier,
|
valueListenable: _entryNotifier,
|
||||||
builder: (context, entry, child) {
|
builder: (context, entry, child) {
|
||||||
if (entry == null) return const SizedBox.shrink();
|
if (entry == null) return SizedBox.shrink();
|
||||||
return FullscreenTopOverlay(
|
return FullscreenTopOverlay(
|
||||||
entry: entry,
|
entry: entry,
|
||||||
scale: _topOverlayScale,
|
scale: _topOverlayScale,
|
||||||
|
@ -459,7 +459,7 @@ class _FullscreenVerticalPageViewState extends State<FullscreenVerticalPageView>
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final pages = [
|
final pages = [
|
||||||
// fake page for opacity transition between collection and fullscreen views
|
// fake page for opacity transition between collection and fullscreen views
|
||||||
const SizedBox(),
|
SizedBox(),
|
||||||
hasCollection
|
hasCollection
|
||||||
? MultiImagePage(
|
? MultiImagePage(
|
||||||
collection: collection,
|
collection: collection,
|
||||||
|
@ -494,7 +494,7 @@ class _FullscreenVerticalPageViewState extends State<FullscreenVerticalPageView>
|
||||||
child: PageView(
|
child: PageView(
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
controller: widget.verticalPager,
|
controller: widget.verticalPager,
|
||||||
physics: const PhotoViewPageViewScrollPhysics(parent: PageScrollPhysics()),
|
physics: PhotoViewPageViewScrollPhysics(parent: PageScrollPhysics()),
|
||||||
onPageChanged: (page) {
|
onPageChanged: (page) {
|
||||||
widget.onVerticalPageChanged(page);
|
widget.onVerticalPageChanged(page);
|
||||||
_infoPageVisibleNotifier.value = page == pages.length - 1;
|
_infoPageVisibleNotifier.value = page == pages.length - 1;
|
||||||
|
|
|
@ -39,7 +39,7 @@ class MultiImagePageState extends State<MultiImagePage> with AutomaticKeepAliveC
|
||||||
child: PageView.builder(
|
child: PageView.builder(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
controller: widget.pageController,
|
controller: widget.pageController,
|
||||||
physics: const PhotoViewPageViewScrollPhysics(parent: BouncingScrollPhysics()),
|
physics: PhotoViewPageViewScrollPhysics(parent: BouncingScrollPhysics()),
|
||||||
onPageChanged: widget.onPageChanged,
|
onPageChanged: widget.onPageChanged,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final entry = entries[index];
|
final entry = entries[index];
|
||||||
|
|
|
@ -41,7 +41,7 @@ class ImageView extends StatelessWidget {
|
||||||
entry: entry,
|
entry: entry,
|
||||||
controller: videoController,
|
controller: videoController,
|
||||||
)
|
)
|
||||||
: const SizedBox(),
|
: SizedBox(),
|
||||||
backgroundDecoration: backgroundDecoration,
|
backgroundDecoration: backgroundDecoration,
|
||||||
scaleStateChangedCallback: onScaleChanged,
|
scaleStateChangedCallback: onScaleChanged,
|
||||||
minScale: PhotoViewComputedScale.contained,
|
minScale: PhotoViewComputedScale.contained,
|
||||||
|
@ -72,7 +72,7 @@ class ImageView extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
Widget child;
|
Widget child;
|
||||||
if (entry.isSvg) {
|
if (entry.isSvg) {
|
||||||
|
@ -107,7 +107,7 @@ class ImageView extends StatelessWidget {
|
||||||
context,
|
context,
|
||||||
imageCache.statusForKey(uriImage).keepAlive ? uriImage : fastThumbnailProvider,
|
imageCache.statusForKey(uriImage).keepAlive ? uriImage : fastThumbnailProvider,
|
||||||
),
|
),
|
||||||
loadFailedChild: const EmptyContent(
|
loadFailedChild: EmptyContent(
|
||||||
icon: AIcons.error,
|
icon: AIcons.error,
|
||||||
text: 'Oops!',
|
text: 'Oops!',
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
|
|
|
@ -65,9 +65,9 @@ class BasicSection extends StatelessWidget {
|
||||||
...filters,
|
...filters,
|
||||||
if (entry.isFavourite) FavouriteFilter(),
|
if (entry.isFavourite) FavouriteFilter(),
|
||||||
]..sort();
|
]..sort();
|
||||||
if (effectiveFilters.isEmpty) return const SizedBox.shrink();
|
if (effectiveFilters.isEmpty) return SizedBox.shrink();
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.outlineWidth / 2) + const EdgeInsets.only(top: 8),
|
padding: EdgeInsets.symmetric(horizontal: AvesFilterChip.outlineWidth / 2) + EdgeInsets.only(top: 8),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
|
|
|
@ -40,11 +40,11 @@ class InfoPageState extends State<InfoPage> {
|
||||||
|
|
||||||
final appBar = SliverAppBar(
|
final appBar = SliverAppBar(
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: const Icon(AIcons.goUp),
|
icon: Icon(AIcons.goUp),
|
||||||
onPressed: _goToImage,
|
onPressed: _goToImage,
|
||||||
tooltip: 'Back to image',
|
tooltip: 'Back to image',
|
||||||
),
|
),
|
||||||
title: const Text('Info'),
|
title: Text('Info'),
|
||||||
floating: true,
|
floating: true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class InfoPageState extends State<InfoPage> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: BasicSection(entry: entry, collection: collection, onFilter: _goToCollection)),
|
Expanded(child: BasicSection(entry: entry, collection: collection, onFilter: _goToCollection)),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Expanded(child: locationSection),
|
Expanded(child: locationSection),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -100,7 +100,7 @@ class InfoPageState extends State<InfoPage> {
|
||||||
slivers: [
|
slivers: [
|
||||||
appBar,
|
appBar,
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
padding: horizontalPadding + const EdgeInsets.only(top: 8),
|
padding: horizontalPadding + EdgeInsets.only(top: 8),
|
||||||
sliver: basicAndLocationSliver,
|
sliver: basicAndLocationSliver,
|
||||||
),
|
),
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
|
@ -165,7 +165,7 @@ class SectionRow extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
const dim = 32.0;
|
const dim = 32.0;
|
||||||
Widget buildDivider() => const SizedBox(
|
Widget buildDivider() => SizedBox(
|
||||||
width: dim,
|
width: dim,
|
||||||
child: Divider(
|
child: Divider(
|
||||||
thickness: AvesFilterChip.outlineWidth,
|
thickness: AvesFilterChip.outlineWidth,
|
||||||
|
@ -177,7 +177,7 @@ class SectionRow extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
buildDivider(),
|
buildDivider(),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: EdgeInsets.all(16.0),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
icon,
|
icon,
|
||||||
size: dim,
|
size: dim,
|
||||||
|
@ -196,7 +196,7 @@ class InfoRowGroup extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (keyValues.isEmpty) return const SizedBox.shrink();
|
if (keyValues.isEmpty) return SizedBox.shrink();
|
||||||
final lastKey = keyValues.keys.last;
|
final lastKey = keyValues.keys.last;
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -206,13 +206,13 @@ class InfoRowGroup extends StatelessWidget {
|
||||||
children: keyValues.entries
|
children: keyValues.entries
|
||||||
.expand(
|
.expand(
|
||||||
(kv) => [
|
(kv) => [
|
||||||
TextSpan(text: '${kv.key} ', style: const TextStyle(color: Colors.white70, height: 1.7)),
|
TextSpan(text: '${kv.key} ', style: TextStyle(color: Colors.white70, height: 1.7)),
|
||||||
TextSpan(text: '${kv.value}${kv.key == lastKey ? '' : '\n'}'),
|
TextSpan(text: '${kv.value}${kv.key == lastKey ? '' : '\n'}'),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
),
|
),
|
||||||
style: const TextStyle(fontFamily: 'Concourse'),
|
style: TextStyle(fontFamily: 'Concourse'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
@ -90,7 +90,7 @@ class _LocationSectionState extends State<LocationSection> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (widget.showTitle)
|
if (widget.showTitle)
|
||||||
const Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(bottom: 8),
|
padding: EdgeInsets.only(bottom: 8),
|
||||||
child: SectionRow(AIcons.location),
|
child: SectionRow(AIcons.location),
|
||||||
),
|
),
|
||||||
|
@ -105,12 +105,12 @@ class _LocationSectionState extends State<LocationSection> {
|
||||||
),
|
),
|
||||||
if (location.isNotEmpty)
|
if (location.isNotEmpty)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 8),
|
padding: EdgeInsets.only(top: 8),
|
||||||
child: InfoRowGroup({'Address': location}),
|
child: InfoRowGroup({'Address': location}),
|
||||||
),
|
),
|
||||||
if (filters.isNotEmpty)
|
if (filters.isNotEmpty)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.outlineWidth / 2) + const EdgeInsets.only(top: 8),
|
padding: EdgeInsets.symmetric(horizontal: AvesFilterChip.outlineWidth / 2) + EdgeInsets.only(top: 8),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
|
@ -126,7 +126,7 @@ class _LocationSectionState extends State<LocationSection> {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
_loadedUri = null;
|
_loadedUri = null;
|
||||||
return const SizedBox.shrink();
|
return SizedBox.shrink();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ class ImageMapState extends State<ImageMap> with AutomaticKeepAliveClientMixin {
|
||||||
// and triggering by mistake a move to the image page above
|
// and triggering by mistake a move to the image page above
|
||||||
},
|
},
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: const BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
Radius.circular(16),
|
Radius.circular(16),
|
||||||
),
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
|
@ -208,24 +208,24 @@ class ImageMapState extends State<ImageMap> with AutomaticKeepAliveClientMixin {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
TooltipTheme(
|
TooltipTheme(
|
||||||
data: TooltipTheme.of(context).copyWith(
|
data: TooltipTheme.of(context).copyWith(
|
||||||
preferBelow: false,
|
preferBelow: false,
|
||||||
),
|
),
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(AIcons.zoomIn),
|
icon: Icon(AIcons.zoomIn),
|
||||||
onPressed: _controller == null ? null : () => _zoomBy(1),
|
onPressed: _controller == null ? null : () => _zoomBy(1),
|
||||||
tooltip: 'Zoom in',
|
tooltip: 'Zoom in',
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(AIcons.zoomOut),
|
icon: Icon(AIcons.zoomOut),
|
||||||
onPressed: _controller == null ? null : () => _zoomBy(-1),
|
onPressed: _controller == null ? null : () => _zoomBy(-1),
|
||||||
tooltip: 'Zoom out',
|
tooltip: 'Zoom out',
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(AIcons.openInNew),
|
icon: Icon(AIcons.openInNew),
|
||||||
onPressed: () => AndroidAppService.openMap(widget.geoUri),
|
onPressed: () => AndroidAppService.openMap(widget.geoUri),
|
||||||
tooltip: 'Show on map...',
|
tooltip: 'Show on map...',
|
||||||
),
|
),
|
||||||
|
|
|
@ -65,7 +65,7 @@ class _MetadataSectionSliverState extends State<MetadataSectionSliver> with Auto
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
|
|
||||||
if (_metadata.isEmpty) return const SliverToBoxAdapter(child: SizedBox.shrink());
|
if (_metadata.isEmpty) return SliverToBoxAdapter(child: SizedBox.shrink());
|
||||||
|
|
||||||
final directoriesWithoutTitle = _metadata.where((dir) => dir.name.isEmpty).toList();
|
final directoriesWithoutTitle = _metadata.where((dir) => dir.name.isEmpty).toList();
|
||||||
final directoriesWithTitle = _metadata.where((dir) => dir.name.isNotEmpty).toList();
|
final directoriesWithTitle = _metadata.where((dir) => dir.name.isNotEmpty).toList();
|
||||||
|
@ -74,7 +74,7 @@ class _MetadataSectionSliverState extends State<MetadataSectionSliver> with Auto
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, index) {
|
(context, index) {
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
return const SectionRow(AIcons.info);
|
return SectionRow(AIcons.info);
|
||||||
}
|
}
|
||||||
if (index < untitledDirectoryCount + 1) {
|
if (index < untitledDirectoryCount + 1) {
|
||||||
final dir = directoriesWithoutTitle[index - 1];
|
final dir = directoriesWithoutTitle[index - 1];
|
||||||
|
@ -91,10 +91,10 @@ class _MetadataSectionSliverState extends State<MetadataSectionSliver> with Auto
|
||||||
expandedNotifier: _expandedDirectoryNotifier,
|
expandedNotifier: _expandedDirectoryNotifier,
|
||||||
title: _DirectoryTitle(dir.name),
|
title: _DirectoryTitle(dir.name),
|
||||||
children: [
|
children: [
|
||||||
const Divider(thickness: 1.0, height: 1.0),
|
Divider(thickness: 1.0, height: 1.0),
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
padding: const EdgeInsets.all(8),
|
padding: EdgeInsets.all(8),
|
||||||
child: InfoRowGroup(dir.tags),
|
child: InfoRowGroup(dir.tags),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -150,10 +150,10 @@ class _DirectoryTitle extends StatelessWidget {
|
||||||
decoration: HighlightDecoration(
|
decoration: HighlightDecoration(
|
||||||
color: stringToColor(name),
|
color: stringToColor(name),
|
||||||
),
|
),
|
||||||
margin: const EdgeInsets.symmetric(vertical: 4.0),
|
margin: EdgeInsets.symmetric(vertical: 4.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
name,
|
name,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
shadows: [
|
shadows: [
|
||||||
Shadow(
|
Shadow(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
|
|
|
@ -90,7 +90,7 @@ class _FullscreenBottomOverlayState extends State<FullscreenBottomOverlay> {
|
||||||
_lastEntry = entry;
|
_lastEntry = entry;
|
||||||
}
|
}
|
||||||
return _lastEntry == null
|
return _lastEntry == null
|
||||||
? const SizedBox.shrink()
|
? SizedBox.shrink()
|
||||||
: Padding(
|
: Padding(
|
||||||
// keep padding inside `FutureBuilder` so that overlay takes no space until data is ready
|
// keep padding inside `FutureBuilder` so that overlay takes no space until data is ready
|
||||||
padding: innerPadding,
|
padding: innerPadding,
|
||||||
|
@ -134,7 +134,7 @@ class _FullscreenBottomOverlayContent extends AnimatedWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DefaultTextStyle(
|
return DefaultTextStyle(
|
||||||
style: Theme.of(context).textTheme.bodyText2.copyWith(
|
style: Theme.of(context).textTheme.bodyText2.copyWith(
|
||||||
shadows: const [
|
shadows: [
|
||||||
Shadow(
|
Shadow(
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
offset: Offset(0.5, 1.0),
|
offset: Offset(0.5, 1.0),
|
||||||
|
@ -163,12 +163,12 @@ class _FullscreenBottomOverlayContent extends AnimatedWidget {
|
||||||
if (positionTitle.isNotEmpty) Text(positionTitle, strutStyle: Constants.overflowStrutStyle),
|
if (positionTitle.isNotEmpty) Text(positionTitle, strutStyle: Constants.overflowStrutStyle),
|
||||||
if (entry.hasGps)
|
if (entry.hasGps)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.only(top: _interRowPadding),
|
padding: EdgeInsets.only(top: _interRowPadding),
|
||||||
child: _LocationRow(entry: entry),
|
child: _LocationRow(entry: entry),
|
||||||
),
|
),
|
||||||
if (twoColumns)
|
if (twoColumns)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: _interRowPadding),
|
padding: EdgeInsets.only(top: _interRowPadding),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Container(width: subRowWidth, child: _DateRow(entry)),
|
Container(width: subRowWidth, child: _DateRow(entry)),
|
||||||
|
@ -178,13 +178,13 @@ class _FullscreenBottomOverlayContent extends AnimatedWidget {
|
||||||
)
|
)
|
||||||
else ...[
|
else ...[
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.only(top: _interRowPadding),
|
padding: EdgeInsets.only(top: _interRowPadding),
|
||||||
width: subRowWidth,
|
width: subRowWidth,
|
||||||
child: _DateRow(entry),
|
child: _DateRow(entry),
|
||||||
),
|
),
|
||||||
if (hasShootingDetails)
|
if (hasShootingDetails)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.only(top: _interRowPadding),
|
padding: EdgeInsets.only(top: _interRowPadding),
|
||||||
width: subRowWidth,
|
width: subRowWidth,
|
||||||
child: _ShootingRow(details),
|
child: _ShootingRow(details),
|
||||||
),
|
),
|
||||||
|
@ -216,8 +216,8 @@ class _LocationRow extends AnimatedWidget {
|
||||||
}
|
}
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(AIcons.location, size: _iconSize),
|
Icon(AIcons.location, size: _iconSize),
|
||||||
const SizedBox(width: _iconPadding),
|
SizedBox(width: _iconPadding),
|
||||||
Expanded(child: Text(location, strutStyle: Constants.overflowStrutStyle)),
|
Expanded(child: Text(location, strutStyle: Constants.overflowStrutStyle)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -236,8 +236,8 @@ class _DateRow extends StatelessWidget {
|
||||||
final resolution = '${entry.width ?? '?'} × ${entry.height ?? '?'}';
|
final resolution = '${entry.width ?? '?'} × ${entry.height ?? '?'}';
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(AIcons.date, size: _iconSize),
|
Icon(AIcons.date, size: _iconSize),
|
||||||
const SizedBox(width: _iconPadding),
|
SizedBox(width: _iconPadding),
|
||||||
Expanded(flex: 3, child: Text(dateText, strutStyle: Constants.overflowStrutStyle)),
|
Expanded(flex: 3, child: Text(dateText, strutStyle: Constants.overflowStrutStyle)),
|
||||||
if (!entry.isSvg) Expanded(flex: 2, child: Text(resolution, strutStyle: Constants.overflowStrutStyle)),
|
if (!entry.isSvg) Expanded(flex: 2, child: Text(resolution, strutStyle: Constants.overflowStrutStyle)),
|
||||||
],
|
],
|
||||||
|
@ -254,8 +254,8 @@ class _ShootingRow extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(AIcons.shooting, size: _iconSize),
|
Icon(AIcons.shooting, size: _iconSize),
|
||||||
const SizedBox(width: _iconPadding),
|
SizedBox(width: _iconPadding),
|
||||||
Expanded(child: Text(details.aperture, strutStyle: Constants.overflowStrutStyle)),
|
Expanded(child: Text(details.aperture, strutStyle: Constants.overflowStrutStyle)),
|
||||||
Expanded(child: Text(details.exposureTime, strutStyle: Constants.overflowStrutStyle)),
|
Expanded(child: Text(details.exposureTime, strutStyle: Constants.overflowStrutStyle)),
|
||||||
Expanded(child: Text(details.focalLength, strutStyle: Constants.overflowStrutStyle)),
|
Expanded(child: Text(details.focalLength, strutStyle: Constants.overflowStrutStyle)),
|
||||||
|
|
|
@ -40,7 +40,7 @@ class FullscreenTopOverlay extends StatelessWidget {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
minimum: (viewInsets ?? EdgeInsets.zero) + (viewPadding ?? EdgeInsets.zero),
|
minimum: (viewInsets ?? EdgeInsets.zero) + (viewPadding ?? EdgeInsets.zero),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(padding),
|
padding: EdgeInsets.all(padding),
|
||||||
child: Selector<MediaQueryData, Tuple2<double, Orientation>>(
|
child: Selector<MediaQueryData, Tuple2<double, Orientation>>(
|
||||||
selector: (c, mq) => Tuple2(mq.size.width, mq.orientation),
|
selector: (c, mq) => Tuple2(mq.size.width, mq.orientation),
|
||||||
builder: (c, mq, child) {
|
builder: (c, mq, child) {
|
||||||
|
@ -126,19 +126,19 @@ class _TopOverlayRow extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
OverlayButton(
|
OverlayButton(
|
||||||
scale: scale,
|
scale: scale,
|
||||||
child: ModalRoute.of(context)?.canPop ?? true ? const BackButton() : const CloseButton(),
|
child: ModalRoute.of(context)?.canPop ?? true ? BackButton() : CloseButton(),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
Spacer(),
|
||||||
...quickActions.map(_buildOverlayButton),
|
...quickActions.map(_buildOverlayButton),
|
||||||
OverlayButton(
|
OverlayButton(
|
||||||
scale: scale,
|
scale: scale,
|
||||||
child: PopupMenuButton<EntryAction>(
|
child: PopupMenuButton<EntryAction>(
|
||||||
itemBuilder: (context) => [
|
itemBuilder: (context) => [
|
||||||
...inAppActions.map(_buildPopupMenuItem),
|
...inAppActions.map(_buildPopupMenuItem),
|
||||||
const PopupMenuDivider(),
|
PopupMenuDivider(),
|
||||||
...externalAppActions.map(_buildPopupMenuItem),
|
...externalAppActions.map(_buildPopupMenuItem),
|
||||||
if (kDebugMode) ...[
|
if (kDebugMode) ...[
|
||||||
const PopupMenuDivider(),
|
PopupMenuDivider(),
|
||||||
_buildPopupMenuItem(EntryAction.debug),
|
_buildPopupMenuItem(EntryAction.debug),
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
@ -181,13 +181,13 @@ class _TopOverlayRow extends StatelessWidget {
|
||||||
}
|
}
|
||||||
return child != null
|
return child != null
|
||||||
? Padding(
|
? Padding(
|
||||||
padding: const EdgeInsetsDirectional.only(end: padding),
|
padding: EdgeInsetsDirectional.only(end: padding),
|
||||||
child: OverlayButton(
|
child: OverlayButton(
|
||||||
scale: scale,
|
scale: scale,
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink();
|
: SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupMenuEntry<EntryAction> _buildPopupMenuItem(EntryAction action) {
|
PopupMenuEntry<EntryAction> _buildPopupMenuItem(EntryAction action) {
|
||||||
|
@ -269,11 +269,11 @@ class _FavouriteTogglerState extends State<_FavouriteToggler> {
|
||||||
builder: (context, isFavourite, child) {
|
builder: (context, isFavourite, child) {
|
||||||
if (widget.isMenuItem) {
|
if (widget.isMenuItem) {
|
||||||
return isFavourite
|
return isFavourite
|
||||||
? const MenuRow(
|
? MenuRow(
|
||||||
text: 'Remove from favourites',
|
text: 'Remove from favourites',
|
||||||
icon: AIcons.favouriteActive,
|
icon: AIcons.favouriteActive,
|
||||||
)
|
)
|
||||||
: const MenuRow(
|
: MenuRow(
|
||||||
text: 'Add to favourites',
|
text: 'Add to favourites',
|
||||||
icon: AIcons.favourite,
|
icon: AIcons.favourite,
|
||||||
);
|
);
|
||||||
|
@ -288,7 +288,7 @@ class _FavouriteTogglerState extends State<_FavouriteToggler> {
|
||||||
),
|
),
|
||||||
Sweeper(
|
Sweeper(
|
||||||
key: ValueKey(widget.entry),
|
key: ValueKey(widget.entry),
|
||||||
builder: (context) => const Icon(AIcons.favourite, color: Colors.redAccent),
|
builder: (context) => Icon(AIcons.favourite, color: Colors.redAccent),
|
||||||
toggledNotifier: isFavouriteNotifier,
|
toggledNotifier: isFavouriteNotifier,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -105,7 +105,7 @@ class VideoControlOverlayState extends State<VideoControlOverlay> with SingleTic
|
||||||
|
|
||||||
final viewInsets = widget.viewInsets ?? mqViewInsets;
|
final viewInsets = widget.viewInsets ?? mqViewInsets;
|
||||||
final viewPadding = widget.viewPadding ?? mqViewPadding;
|
final viewPadding = widget.viewPadding ?? mqViewPadding;
|
||||||
final safePadding = (viewInsets + viewPadding).copyWith(bottom: 8) + const EdgeInsets.symmetric(horizontal: 8.0);
|
final safePadding = (viewInsets + viewPadding).copyWith(bottom: 8) + EdgeInsets.symmetric(horizontal: 8.0);
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: safePadding,
|
padding: safePadding,
|
||||||
|
@ -127,7 +127,7 @@ class VideoControlOverlayState extends State<VideoControlOverlay> with SingleTic
|
||||||
OverlayButton(
|
OverlayButton(
|
||||||
scale: scale,
|
scale: scale,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: const Icon(AIcons.openInNew),
|
icon: Icon(AIcons.openInNew),
|
||||||
onPressed: () => AndroidAppService.open(entry.uri, entry.mimeTypeAnySubtype),
|
onPressed: () => AndroidAppService.open(entry.uri, entry.mimeTypeAnySubtype),
|
||||||
tooltip: 'Open',
|
tooltip: 'Open',
|
||||||
),
|
),
|
||||||
|
@ -137,7 +137,7 @@ class VideoControlOverlayState extends State<VideoControlOverlay> with SingleTic
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _buildProgressBar(),
|
child: _buildProgressBar(),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
OverlayButton(
|
OverlayButton(
|
||||||
scale: scale,
|
scale: scale,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
|
@ -178,11 +178,11 @@ class VideoControlOverlayState extends State<VideoControlOverlay> with SingleTic
|
||||||
if (_playingOnDragStart) controller.play();
|
if (_playingOnDragStart) controller.play();
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16) + const EdgeInsets.only(bottom: 16),
|
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 16) + EdgeInsets.only(bottom: 16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: FullscreenOverlay.backgroundColor,
|
color: FullscreenOverlay.backgroundColor,
|
||||||
border: FullscreenOverlay.buildBorder(context),
|
border: FullscreenOverlay.buildBorder(context),
|
||||||
borderRadius: const BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
Radius.circular(progressBarBorderRadius),
|
Radius.circular(progressBarBorderRadius),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -198,7 +198,7 @@ class VideoControlOverlayState extends State<VideoControlOverlay> with SingleTic
|
||||||
final position = videoInfo.currentPosition?.floor() ?? 0;
|
final position = videoInfo.currentPosition?.floor() ?? 0;
|
||||||
return Text(formatDuration(Duration(seconds: position)));
|
return Text(formatDuration(Duration(seconds: position)));
|
||||||
}),
|
}),
|
||||||
const Spacer(),
|
Spacer(),
|
||||||
Text(entry.durationText),
|
Text(entry.durationText),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -60,7 +60,7 @@ class AvesVideoState extends State<AvesVideo> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (controller == null) return const SizedBox();
|
if (controller == null) return SizedBox();
|
||||||
return StreamBuilder<IjkStatus>(
|
return StreamBuilder<IjkStatus>(
|
||||||
stream: widget.controller.ijkStatusStream,
|
stream: widget.controller.ijkStatusStream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
@ -68,8 +68,8 @@ class AvesVideoState extends State<AvesVideo> {
|
||||||
return isPlayable(status)
|
return isPlayable(status)
|
||||||
? IjkPlayer(
|
? IjkPlayer(
|
||||||
mediaController: controller,
|
mediaController: controller,
|
||||||
controllerWidgetBuilder: (controller) => const SizedBox.shrink(),
|
controllerWidgetBuilder: (controller) => SizedBox.shrink(),
|
||||||
statusWidgetBuilder: (context, controller, status) => const SizedBox.shrink(),
|
statusWidgetBuilder: (context, controller, status) => SizedBox.shrink(),
|
||||||
textureBuilder: (context, controller, info) {
|
textureBuilder: (context, controller, info) {
|
||||||
var id = controller.textureId;
|
var id = controller.textureId;
|
||||||
var child = id != null
|
var child = id != null
|
||||||
|
|
|
@ -95,8 +95,8 @@ class _HomePageState extends State<HomePage> {
|
||||||
return FutureBuilder<void>(
|
return FutureBuilder<void>(
|
||||||
future: _appSetup,
|
future: _appSetup,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) return const Icon(AIcons.error);
|
if (snapshot.hasError) return Icon(AIcons.error);
|
||||||
if (snapshot.connectionState != ConnectionState.done) return const Scaffold();
|
if (snapshot.connectionState != ConnectionState.done) return Scaffold();
|
||||||
if (AvesApp.mode == AppMode.view) {
|
if (AvesApp.mode == AppMode.view) {
|
||||||
return SingleFullscreenPage(entry: _viewerEntry);
|
return SingleFullscreenPage(entry: _viewerEntry);
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ class _HomePageState extends State<HomePage> {
|
||||||
sortFactor: settings.collectionSortFactor,
|
sortFactor: settings.collectionSortFactor,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return const SizedBox.shrink();
|
return SizedBox.shrink();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ class FilterTable extends StatelessWidget {
|
||||||
final lineHeight = 16 * textScaleFactor;
|
final lineHeight = 16 * textScaleFactor;
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsetsDirectional.only(start: AvesFilterChip.outlineWidth / 2 + 6, end: 8),
|
padding: EdgeInsetsDirectional.only(start: AvesFilterChip.outlineWidth / 2 + 6, end: 8),
|
||||||
child: LayoutBuilder(
|
child: LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
final showPercentIndicator = constraints.maxWidth - (chipWidth + countWidth) > percentIndicatorMinWidth;
|
final showPercentIndicator = constraints.maxWidth - (chipWidth + countWidth) > percentIndicatorMinWidth;
|
||||||
|
@ -49,7 +49,7 @@ class FilterTable extends StatelessWidget {
|
||||||
return TableRow(
|
return TableRow(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.only(bottom: 8),
|
padding: EdgeInsets.only(bottom: 8),
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
child: AvesFilterChip(
|
child: AvesFilterChip(
|
||||||
filter: filter,
|
filter: filter,
|
||||||
|
@ -68,13 +68,13 @@ class FilterTable extends StatelessWidget {
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'$count',
|
'$count',
|
||||||
style: const TextStyle(color: Colors.white70),
|
style: TextStyle(color: Colors.white70),
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
columnWidths: const {
|
columnWidths: {
|
||||||
0: MaxColumnWidth(IntrinsicColumnWidth(), FixedColumnWidth(chipWidth)),
|
0: MaxColumnWidth(IntrinsicColumnWidth(), FixedColumnWidth(chipWidth)),
|
||||||
2: MaxColumnWidth(IntrinsicColumnWidth(), FixedColumnWidth(countWidth)),
|
2: MaxColumnWidth(IntrinsicColumnWidth(), FixedColumnWidth(countWidth)),
|
||||||
},
|
},
|
||||||
|
|
|
@ -49,7 +49,7 @@ class StatsPage extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Widget child;
|
Widget child;
|
||||||
if (collection.isEmpty) {
|
if (collection.isEmpty) {
|
||||||
child = const EmptyContent(
|
child = EmptyContent(
|
||||||
icon: AIcons.image,
|
icon: AIcons.image,
|
||||||
text: 'No images',
|
text: 'No images',
|
||||||
);
|
);
|
||||||
|
@ -71,7 +71,7 @@ class StatsPage extends StatelessWidget {
|
||||||
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
||||||
final lineHeight = 16 * textScaleFactor;
|
final lineHeight = 16 * textScaleFactor;
|
||||||
final locationIndicator = Padding(
|
final locationIndicator = Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
LinearPercentIndicator(
|
LinearPercentIndicator(
|
||||||
|
@ -80,12 +80,12 @@ class StatsPage extends StatelessWidget {
|
||||||
backgroundColor: Colors.white24,
|
backgroundColor: Colors.white24,
|
||||||
progressColor: Theme.of(context).accentColor,
|
progressColor: Theme.of(context).accentColor,
|
||||||
animation: true,
|
animation: true,
|
||||||
leading: const Icon(AIcons.location),
|
leading: Icon(AIcons.location),
|
||||||
// right padding to match leading, so that inside label is aligned with outside label below
|
// right padding to match leading, so that inside label is aligned with outside label below
|
||||||
padding: EdgeInsets.symmetric(horizontal: lineHeight) + const EdgeInsets.only(right: 24),
|
padding: EdgeInsets.symmetric(horizontal: lineHeight) + EdgeInsets.only(right: 24),
|
||||||
center: Text(NumberFormat.percentPattern().format(withGpsPercent)),
|
center: Text(NumberFormat.percentPattern().format(withGpsPercent)),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
Text('${withGps.length} ${Intl.plural(withGps.length, one: 'item', other: 'items')} with location'),
|
Text('${withGps.length} ${Intl.plural(withGps.length, one: 'item', other: 'items')} with location'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -103,7 +103,7 @@ class StatsPage extends StatelessWidget {
|
||||||
return MediaQueryDataProvider(
|
return MediaQueryDataProvider(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Stats'),
|
title: Text('Stats'),
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: child,
|
child: child,
|
||||||
|
@ -118,7 +118,7 @@ class StatsPage extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMimeDonut(BuildContext context, String Function(num) label, Map<String, num> byMimeTypes) {
|
Widget _buildMimeDonut(BuildContext context, String Function(num) label, Map<String, num> byMimeTypes) {
|
||||||
if (byMimeTypes.isEmpty) return const SizedBox.shrink();
|
if (byMimeTypes.isEmpty) return SizedBox.shrink();
|
||||||
|
|
||||||
final sum = byMimeTypes.values.fold<int>(0, (prev, v) => prev + v);
|
final sum = byMimeTypes.values.fold<int>(0, (prev, v) => prev + v);
|
||||||
|
|
||||||
|
@ -177,12 +177,12 @@ class StatsPage extends StatelessWidget {
|
||||||
WidgetSpan(
|
WidgetSpan(
|
||||||
alignment: PlaceholderAlignment.middle,
|
alignment: PlaceholderAlignment.middle,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsetsDirectional.only(end: 8),
|
padding: EdgeInsetsDirectional.only(end: 8),
|
||||||
child: Icon(AIcons.disc, color: stringToColor(kv.key)),
|
child: Icon(AIcons.disc, color: stringToColor(kv.key)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(text: '${kv.key} '),
|
TextSpan(text: '${kv.key} '),
|
||||||
TextSpan(text: '${kv.value}', style: const TextStyle(color: Colors.white70)),
|
TextSpan(text: '${kv.value}', style: TextStyle(color: Colors.white70)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
overflow: TextOverflow.fade,
|
overflow: TextOverflow.fade,
|
||||||
|
@ -217,7 +217,7 @@ class StatsPage extends StatelessWidget {
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
child: Text(
|
child: Text(
|
||||||
title,
|
title,
|
||||||
style: Constants.titleTextStyle,
|
style: Constants.titleTextStyle,
|
||||||
|
|
|
@ -32,11 +32,11 @@ class _WelcomePageState extends State<WelcomePage> {
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Container(
|
child: Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: EdgeInsets.all(16.0),
|
||||||
child: FutureBuilder<String>(
|
child: FutureBuilder<String>(
|
||||||
future: _termsLoader,
|
future: _termsLoader,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError || snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
if (snapshot.hasError || snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
||||||
final terms = snapshot.data;
|
final terms = snapshot.data;
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
@ -73,21 +73,21 @@ class _WelcomePageState extends State<WelcomePage> {
|
||||||
return [
|
return [
|
||||||
...(MediaQuery.of(context).orientation == Orientation.portrait
|
...(MediaQuery.of(context).orientation == Orientation.portrait
|
||||||
? [
|
? [
|
||||||
const AvesLogo(size: 64),
|
AvesLogo(size: 64),
|
||||||
const SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
message,
|
message,
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const AvesLogo(size: 48),
|
AvesLogo(size: 48),
|
||||||
const SizedBox(width: 16),
|
SizedBox(width: 16),
|
||||||
message,
|
message,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
const SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,14 +98,14 @@ class _WelcomePageState extends State<WelcomePage> {
|
||||||
text: 'I agree to the terms and conditions',
|
text: 'I agree to the terms and conditions',
|
||||||
);
|
);
|
||||||
final button = RaisedButton(
|
final button = RaisedButton(
|
||||||
child: const Text('Continue'),
|
child: Text('Continue'),
|
||||||
onPressed: _hasAcceptedTerms
|
onPressed: _hasAcceptedTerms
|
||||||
? () {
|
? () {
|
||||||
settings.hasAcceptedTerms = true;
|
settings.hasAcceptedTerms = true;
|
||||||
Navigator.pushAndRemoveUntil(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => const HomePage(),
|
builder: (context) => HomePage(),
|
||||||
),
|
),
|
||||||
(route) => false,
|
(route) => false,
|
||||||
);
|
);
|
||||||
|
@ -118,11 +118,11 @@ class _WelcomePageState extends State<WelcomePage> {
|
||||||
button,
|
button,
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
const SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
checkbox,
|
checkbox,
|
||||||
const Spacer(),
|
Spacer(),
|
||||||
button,
|
button,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -135,7 +135,7 @@ class _WelcomePageState extends State<WelcomePage> {
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
color: Colors.white10,
|
color: Colors.white10,
|
||||||
),
|
),
|
||||||
constraints: const BoxConstraints(maxWidth: 460),
|
constraints: BoxConstraints(maxWidth: 460),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
child: Markdown(
|
child: Markdown(
|
||||||
|
|
Loading…
Reference in a new issue