packages upgrade & fixed pedantic issues
This commit is contained in:
parent
99271e0428
commit
dd2199ef20
25 changed files with 68 additions and 75 deletions
|
@ -40,9 +40,9 @@ class SliverTransitionGridDelegateWithCrossAxisCount extends SliverGridDelegate
|
||||||
}
|
}
|
||||||
|
|
||||||
SliverTransitionGridTileLayoutSettings _buildSettings(SliverConstraints constraints, double crossAxisCount) {
|
SliverTransitionGridTileLayoutSettings _buildSettings(SliverConstraints constraints, double crossAxisCount) {
|
||||||
final double usableCrossAxisExtent = constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1);
|
final usableCrossAxisExtent = constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1);
|
||||||
final double childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount;
|
final childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount;
|
||||||
final double childMainAxisExtent = childCrossAxisExtent / childAspectRatio;
|
final childMainAxisExtent = childCrossAxisExtent / childAspectRatio;
|
||||||
final current = SliverTransitionGridTileLayoutSettings(
|
final current = SliverTransitionGridTileLayoutSettings(
|
||||||
crossAxisCount: crossAxisCount,
|
crossAxisCount: crossAxisCount,
|
||||||
mainAxisStride: childMainAxisExtent + mainAxisSpacing,
|
mainAxisStride: childMainAxisExtent + mainAxisSpacing,
|
||||||
|
@ -129,7 +129,7 @@ class SliverTransitionGridTileLayout extends SliverGridLayout {
|
||||||
int getMaxChildIndexForScrollOffset(double scrollOffset) {
|
int getMaxChildIndexForScrollOffset(double scrollOffset) {
|
||||||
final settings = t == 0 ? current : floor;
|
final settings = t == 0 ? current : floor;
|
||||||
if (settings.mainAxisStride > 0.0) {
|
if (settings.mainAxisStride > 0.0) {
|
||||||
final int mainAxisCount = (scrollOffset / settings.mainAxisStride).ceil();
|
final mainAxisCount = (scrollOffset / settings.mainAxisStride).ceil();
|
||||||
final index = math.max(0, settings.crossAxisCount * mainAxisCount - 1).ceil();
|
final index = math.max(0, settings.crossAxisCount * mainAxisCount - 1).ceil();
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ class SliverTransitionGridTileLayout extends SliverGridLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
double _getCrossAxisOffset(int index, SliverTransitionGridTileLayoutSettings settings) {
|
double _getCrossAxisOffset(int index, SliverTransitionGridTileLayoutSettings settings) {
|
||||||
final double crossAxisStart = (index % settings.crossAxisCount) * settings.crossAxisStride;
|
final crossAxisStart = (index % settings.crossAxisCount) * settings.crossAxisStride;
|
||||||
if (reverseCrossAxis) {
|
if (reverseCrossAxis) {
|
||||||
return settings.crossAxisCount * settings.crossAxisStride - crossAxisStart - settings.childCrossAxisExtent - (settings.crossAxisStride - settings.childCrossAxisExtent);
|
return settings.crossAxisCount * settings.crossAxisStride - crossAxisStart - settings.childCrossAxisExtent - (settings.crossAxisStride - settings.childCrossAxisExtent);
|
||||||
}
|
}
|
||||||
|
@ -168,8 +168,8 @@ class SliverTransitionGridTileLayout extends SliverGridLayout {
|
||||||
return maxScrollOffset;
|
return maxScrollOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int mainAxisCount = ((childCount - 1) ~/ current.crossAxisCount) + 1;
|
final mainAxisCount = ((childCount - 1) ~/ current.crossAxisCount) + 1;
|
||||||
final double mainAxisSpacing = current.mainAxisStride - current.childMainAxisExtent;
|
final mainAxisSpacing = current.mainAxisStride - current.childMainAxisExtent;
|
||||||
final maxScrollOffset = current.mainAxisStride * mainAxisCount - mainAxisSpacing;
|
final maxScrollOffset = current.mainAxisStride * mainAxisCount - mainAxisSpacing;
|
||||||
return maxScrollOffset;
|
return maxScrollOffset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,12 +67,12 @@ class _HomePageState extends State<HomePage> {
|
||||||
debugPrint('$runtimeType _setup');
|
debugPrint('$runtimeType _setup');
|
||||||
|
|
||||||
// TODO reduce permission check time
|
// TODO reduce permission check time
|
||||||
final permissions = await PermissionHandler().requestPermissions([
|
final permissions = await [
|
||||||
PermissionGroup.storage,
|
Permission.storage,
|
||||||
// unredacted EXIF with scoped storage (Android 10+)
|
// unredacted EXIF with scoped storage (Android 10+)
|
||||||
PermissionGroup.accessMediaLocation,
|
Permission.accessMediaLocation,
|
||||||
]); // 350ms
|
].request(); // 350ms
|
||||||
if (permissions[PermissionGroup.storage] != PermissionStatus.granted) {
|
if (permissions[Permission.storage] != PermissionStatus.granted) {
|
||||||
unawaited(SystemNavigator.pop());
|
unawaited(SystemNavigator.pop());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,9 @@ class CollectionLens with ChangeNotifier {
|
||||||
Iterable<CollectionFilter> filters,
|
Iterable<CollectionFilter> filters,
|
||||||
@required GroupFactor groupFactor,
|
@required GroupFactor groupFactor,
|
||||||
@required SortFactor sortFactor,
|
@required SortFactor sortFactor,
|
||||||
}) : this.filters = [if (filters != null) ...filters.where((f) => f != null)].toSet(),
|
}) : filters = {if (filters != null) ...filters.where((f) => f != null)},
|
||||||
this.groupFactor = groupFactor ?? GroupFactor.month,
|
groupFactor = groupFactor ?? GroupFactor.month,
|
||||||
this.sortFactor = sortFactor ?? SortFactor.date {
|
sortFactor = sortFactor ?? SortFactor.date {
|
||||||
_subscriptions.add(source.eventBus.on<EntryAddedEvent>().listen((e) => onEntryAdded()));
|
_subscriptions.add(source.eventBus.on<EntryAddedEvent>().listen((e) => onEntryAdded()));
|
||||||
_subscriptions.add(source.eventBus.on<EntryRemovedEvent>().listen((e) => onEntryRemoved(e.entry)));
|
_subscriptions.add(source.eventBus.on<EntryRemovedEvent>().listen((e) => onEntryRemoved(e.entry)));
|
||||||
_subscriptions.add(source.eventBus.on<CatalogMetadataChangedEvent>().listen((e) => onMetadataChanged()));
|
_subscriptions.add(source.eventBus.on<CatalogMetadataChangedEvent>().listen((e) => onMetadataChanged()));
|
||||||
|
@ -69,9 +69,7 @@ class CollectionLens with ChangeNotifier {
|
||||||
List<ImageEntry> _sortedEntries;
|
List<ImageEntry> _sortedEntries;
|
||||||
|
|
||||||
List<ImageEntry> get sortedEntries {
|
List<ImageEntry> get sortedEntries {
|
||||||
if (_sortedEntries == null) {
|
_sortedEntries ??= List.of(sections.entries.expand((e) => e.value));
|
||||||
_sortedEntries = List.of(sections.entries.expand((e) => e.value));
|
|
||||||
}
|
|
||||||
return _sortedEntries;
|
return _sortedEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ class CollectionSource {
|
||||||
|
|
||||||
void updateLocations() {
|
void updateLocations() {
|
||||||
final locations = _rawEntries.where((entry) => entry.isLocated).map((entry) => entry.addressDetails);
|
final locations = _rawEntries.where((entry) => entry.isLocated).map((entry) => entry.addressDetails);
|
||||||
final lister = (String f(AddressDetails a)) => List<String>.unmodifiable(locations.map(f).where((s) => s != null && s.isNotEmpty).toSet().toList()..sort(compareAsciiUpperCase));
|
final lister = (String Function(AddressDetails a) f) => List<String>.unmodifiable(locations.map(f).where((s) => s != null && s.isNotEmpty).toSet().toList()..sort(compareAsciiUpperCase));
|
||||||
sortedCountries = lister((address) => address.countryName);
|
sortedCountries = lister((address) => address.countryName);
|
||||||
sortedCities = lister((address) => address.city);
|
sortedCities = lister((address) => address.city);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ class CollectionSource {
|
||||||
static String getUniqueAlbumName(String album, Iterable<String> albums) {
|
static String getUniqueAlbumName(String album, Iterable<String> albums) {
|
||||||
final otherAlbums = albums?.where((item) => item != album) ?? [];
|
final otherAlbums = albums?.where((item) => item != album) ?? [];
|
||||||
final parts = album.split(separator);
|
final parts = album.split(separator);
|
||||||
int partCount = 0;
|
var partCount = 0;
|
||||||
String testName;
|
String testName;
|
||||||
do {
|
do {
|
||||||
testName = separator + parts.skip(parts.length - ++partCount).join(separator);
|
testName = separator + parts.skip(parts.length - ++partCount).join(separator);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import 'package:aves/model/metadata_db.dart';
|
||||||
final FavouriteRepo favourites = FavouriteRepo._private();
|
final FavouriteRepo favourites = FavouriteRepo._private();
|
||||||
|
|
||||||
class FavouriteRepo {
|
class FavouriteRepo {
|
||||||
List<FavouriteRow> _rows = List();
|
List<FavouriteRow> _rows = [];
|
||||||
|
|
||||||
FavouriteRepo._private();
|
FavouriteRepo._private();
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import 'package:path/path.dart';
|
||||||
class AlbumFilter extends CollectionFilter {
|
class AlbumFilter extends CollectionFilter {
|
||||||
static const type = 'album';
|
static const type = 'album';
|
||||||
|
|
||||||
static Map<String, Color> _appColors = Map();
|
static final Map<String, Color> _appColors = {};
|
||||||
|
|
||||||
final String album;
|
final String album;
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ class CatalogMetadata {
|
||||||
double longitude,
|
double longitude,
|
||||||
})
|
})
|
||||||
// Geocoder throws an IllegalArgumentException when a coordinate has a funky values like 1.7056881853375E7
|
// Geocoder throws an IllegalArgumentException when a coordinate has a funky values like 1.7056881853375E7
|
||||||
: this.latitude = latitude == null || latitude < -90.0 || latitude > 90.0 ? null : latitude,
|
: latitude = latitude == null || latitude < -90.0 || latitude > 90.0 ? null : latitude,
|
||||||
this.longitude = longitude == null || longitude < -180.0 || longitude > 180.0 ? null : longitude;
|
longitude = longitude == null || longitude < -180.0 || longitude > 180.0 ? null : longitude;
|
||||||
|
|
||||||
factory CatalogMetadata.fromMap(Map map) {
|
factory CatalogMetadata.fromMap(Map map) {
|
||||||
return CatalogMetadata(
|
return CatalogMetadata(
|
||||||
|
@ -53,7 +53,7 @@ class OverlayMetadata {
|
||||||
this.exposureTime,
|
this.exposureTime,
|
||||||
this.focalLength,
|
this.focalLength,
|
||||||
this.iso,
|
this.iso,
|
||||||
}) : this.aperture = aperture.replaceFirst('f', 'ƒ');
|
}) : aperture = aperture.replaceFirst('f', 'ƒ');
|
||||||
|
|
||||||
factory OverlayMetadata.fromMap(Map map) {
|
factory OverlayMetadata.fromMap(Map map) {
|
||||||
return OverlayMetadata(
|
return OverlayMetadata(
|
||||||
|
|
|
@ -35,7 +35,7 @@ class Settings {
|
||||||
void notifyListeners(String key, dynamic oldValue, dynamic newValue) {
|
void notifyListeners(String key, dynamic oldValue, dynamic newValue) {
|
||||||
debugPrint('$runtimeType notifyListeners key=$key, old=$oldValue, new=$newValue');
|
debugPrint('$runtimeType notifyListeners key=$key, old=$oldValue, new=$newValue');
|
||||||
if (_listeners != null) {
|
if (_listeners != null) {
|
||||||
final List<SettingsCallback> localListeners = _listeners.toList();
|
final localListeners = _listeners.toList();
|
||||||
for (final listener in localListeners) {
|
for (final listener in localListeners) {
|
||||||
try {
|
try {
|
||||||
if (_listeners.contains(listener)) {
|
if (_listeners.contains(listener)) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
String formatFilesize(int size, {int round = 2}) {
|
String formatFilesize(int size, {int round = 2}) {
|
||||||
int divider = 1024;
|
var divider = 1024;
|
||||||
|
|
||||||
if (size < divider) return '$size B';
|
if (size < divider) return '$size B';
|
||||||
|
|
||||||
|
|
|
@ -10,24 +10,24 @@ String _decimal2sexagesimal(final double dec) {
|
||||||
List<int> _split(final double value) {
|
List<int> _split(final double value) {
|
||||||
// NumberFormat is necessary to create digit after comma if the value
|
// NumberFormat is necessary to create digit after comma if the value
|
||||||
// has no decimal point (only necessary for browser)
|
// has no decimal point (only necessary for browser)
|
||||||
final List<String> tmp = NumberFormat('0.0#####').format(_round(value, decimals: 10)).split('.');
|
final tmp = NumberFormat('0.0#####').format(_round(value, decimals: 10)).split('.');
|
||||||
return <int>[
|
return <int>[
|
||||||
int.parse(tmp[0]).abs(),
|
int.parse(tmp[0]).abs(),
|
||||||
int.parse(tmp[1]),
|
int.parse(tmp[1]),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<int> parts = _split(dec);
|
final parts = _split(dec);
|
||||||
final int integerPart = parts[0];
|
final integerPart = parts[0];
|
||||||
final int fractionalPart = parts[1];
|
final fractionalPart = parts[1];
|
||||||
|
|
||||||
final int deg = integerPart;
|
final deg = integerPart;
|
||||||
final double min = double.parse('0.$fractionalPart') * 60;
|
final min = double.parse('0.$fractionalPart') * 60;
|
||||||
|
|
||||||
final List<int> minParts = _split(min);
|
final minParts = _split(min);
|
||||||
final int minFractionalPart = minParts[1];
|
final minFractionalPart = minParts[1];
|
||||||
|
|
||||||
final double sec = double.parse('0.$minFractionalPart') * 60;
|
final sec = double.parse('0.$minFractionalPart') * 60;
|
||||||
|
|
||||||
return '$deg° ${min.floor()}′ ${_round(sec, decimals: 2).toStringAsFixed(2)}″';
|
return '$deg° ${min.floor()}′ ${_round(sec, decimals: 2).toStringAsFixed(2)}″';
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,19 @@ String formatDuration(Duration d) {
|
||||||
return '0$n';
|
return '0$n';
|
||||||
}
|
}
|
||||||
|
|
||||||
String twoDigitSeconds = twoDigits(d.inSeconds.remainder(Duration.secondsPerMinute));
|
final twoDigitSeconds = twoDigits(d.inSeconds.remainder(Duration.secondsPerMinute));
|
||||||
if (d.inHours == 0) return '${d.inMinutes}:$twoDigitSeconds';
|
if (d.inHours == 0) return '${d.inMinutes}:$twoDigitSeconds';
|
||||||
|
|
||||||
String twoDigitMinutes = twoDigits(d.inMinutes.remainder(Duration.minutesPerHour));
|
final twoDigitMinutes = twoDigits(d.inMinutes.remainder(Duration.minutesPerHour));
|
||||||
return '${d.inHours}:$twoDigitMinutes:$twoDigitSeconds';
|
return '${d.inHours}:$twoDigitMinutes:$twoDigitSeconds';
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ExtraDateTime on DateTime {
|
extension ExtraDateTime on DateTime {
|
||||||
bool isAtSameYearAs(DateTime other) => this != null && other != null && this.year == other.year;
|
bool isAtSameYearAs(DateTime other) => this != null && other != null && year == other.year;
|
||||||
|
|
||||||
bool isAtSameMonthAs(DateTime other) => isAtSameYearAs(other) && this.month == other.month;
|
bool isAtSameMonthAs(DateTime other) => isAtSameYearAs(other) && month == other.month;
|
||||||
|
|
||||||
bool isAtSameDayAs(DateTime other) => isAtSameMonthAs(other) && this.day == other.day;
|
bool isAtSameDayAs(DateTime other) => isAtSameMonthAs(other) && day == other.day;
|
||||||
|
|
||||||
bool get isToday => isAtSameDayAs(DateTime.now());
|
bool get isToday => isAtSameDayAs(DateTime.now());
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@ import 'dart:ui';
|
||||||
import 'package:aves/model/collection_lens.dart';
|
import 'package:aves/model/collection_lens.dart';
|
||||||
import 'package:aves/model/collection_source.dart';
|
import 'package:aves/model/collection_source.dart';
|
||||||
import 'package:aves/model/filters/album.dart';
|
import 'package:aves/model/filters/album.dart';
|
||||||
import 'package:aves/model/filters/location.dart';
|
|
||||||
import 'package:aves/model/filters/favourite.dart';
|
import 'package:aves/model/filters/favourite.dart';
|
||||||
import 'package:aves/model/filters/filters.dart';
|
import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/model/filters/gif.dart';
|
import 'package:aves/model/filters/gif.dart';
|
||||||
|
import 'package:aves/model/filters/location.dart';
|
||||||
import 'package:aves/model/filters/tag.dart';
|
import 'package:aves/model/filters/tag.dart';
|
||||||
import 'package:aves/model/filters/video.dart';
|
import 'package:aves/model/filters/video.dart';
|
||||||
import 'package:aves/model/settings.dart';
|
import 'package:aves/model/settings.dart';
|
||||||
|
@ -300,7 +300,7 @@ class _FilteredCollectionNavTile extends StatelessWidget {
|
||||||
@required this.title,
|
@required this.title,
|
||||||
bool dense,
|
bool dense,
|
||||||
@required this.filter,
|
@required this.filter,
|
||||||
}) : this.dense = dense ?? false;
|
}) : dense = dense ?? false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
|
@ -233,7 +233,7 @@ class GridPainter extends CustomPainter {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
final topLeft = center.translate(-extent / 2, -extent / 2);
|
final topLeft = center.translate(-extent / 2, -extent / 2);
|
||||||
for (int i = -1; i <= 2; i++) {
|
for (var i = -1; i <= 2; i++) {
|
||||||
canvas.drawLine(Offset(0, topLeft.dy + extent * i), Offset(size.width, topLeft.dy + extent * i), paint);
|
canvas.drawLine(Offset(0, topLeft.dy + extent * i), Offset(size.width, topLeft.dy + extent * i), paint);
|
||||||
canvas.drawLine(Offset(topLeft.dx + extent * i, 0), Offset(topLeft.dx + extent * i, size.height), paint);
|
canvas.drawLine(Offset(topLeft.dx + extent * i, 0), Offset(topLeft.dx + extent * i, size.height), paint);
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ class SectionHeader extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAlbumSectionHeader(BuildContext context) {
|
Widget _buildAlbumSectionHeader(BuildContext context) {
|
||||||
Widget albumIcon = IconUtils.getAlbumIcon(context: context, album: sectionKey as String);
|
var albumIcon = IconUtils.getAlbumIcon(context: context, album: sectionKey as String);
|
||||||
if (albumIcon != null) {
|
if (albumIcon != null) {
|
||||||
albumIcon = Material(
|
albumIcon = Material(
|
||||||
type: MaterialType.circle,
|
type: MaterialType.circle,
|
||||||
|
|
|
@ -10,7 +10,7 @@ class TransparentMaterialPageRoute<T> extends PageRouteBuilder<T> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
|
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
|
||||||
final PageTransitionsTheme theme = Theme.of(context).pageTransitionsTheme;
|
final theme = Theme.of(context).pageTransitionsTheme;
|
||||||
return theme.buildTransitions<T>(this, context, animation, secondaryAnimation, child);
|
return theme.buildTransitions<T>(this, context, animation, secondaryAnimation, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ class _MediaStoreCollectionProviderState extends State<MediaStoreCollectionProvi
|
||||||
settings.catalogTimeZone = currentTimeZone;
|
settings.catalogTimeZone = currentTimeZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
final allEntries = List<ImageEntry>();
|
final allEntries = <ImageEntry>[];
|
||||||
eventChannel.receiveBroadcastStream().cast<Map>().listen(
|
eventChannel.receiveBroadcastStream().cast<Map>().listen(
|
||||||
(entryMap) => allEntries.add(ImageEntry.fromMap(entryMap)),
|
(entryMap) => allEntries.add(ImageEntry.fromMap(entryMap)),
|
||||||
onDone: () async {
|
onDone: () async {
|
||||||
|
|
|
@ -121,11 +121,10 @@ class _SweepClipPath extends CustomClipper<Path> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Path getClip(Size size) {
|
Path getClip(Size size) {
|
||||||
Path path = Path();
|
return Path()
|
||||||
path.moveTo(size.width / 2, size.height / 2);
|
..moveTo(size.width / 2, size.height / 2)
|
||||||
path.addArc(Rect.fromLTWH(0, 0, size.width, size.height), startAngle, sweepAngle);
|
..addArc(Rect.fromLTWH(0, 0, size.width, size.height), startAngle, sweepAngle)
|
||||||
path.lineTo(size.width / 2, size.height / 2);
|
..lineTo(size.width / 2, size.height / 2);
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'dart:typed_data';
|
|
||||||
import 'dart:ui' as ui show Codec;
|
import 'dart:ui' as ui show Codec;
|
||||||
|
|
||||||
import 'package:aves/utils/android_app_service.dart';
|
import 'package:aves/utils/android_app_service.dart';
|
||||||
|
@ -38,7 +37,7 @@ class AppIconImage extends ImageProvider<AppIconImageKey> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ui.Codec> _loadAsync(AppIconImageKey key, DecoderCallback decode) async {
|
Future<ui.Codec> _loadAsync(AppIconImageKey key, DecoderCallback decode) async {
|
||||||
final Uint8List bytes = await AndroidAppService.getAppIcon(key.packageName, key.sizePixels);
|
final bytes = await AndroidAppService.getAppIcon(key.packageName, key.sizePixels);
|
||||||
if (bytes.lengthInBytes == 0) {
|
if (bytes.lengthInBytes == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'dart:typed_data';
|
|
||||||
import 'dart:ui' as ui show Codec;
|
import 'dart:ui' as ui show Codec;
|
||||||
|
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
|
@ -45,7 +44,7 @@ class ThumbnailProvider extends ImageProvider<ThumbnailProviderKey> {
|
||||||
|
|
||||||
Future<ui.Codec> _loadAsync(ThumbnailProviderKey key, DecoderCallback decode) async {
|
Future<ui.Codec> _loadAsync(ThumbnailProviderKey key, DecoderCallback decode) async {
|
||||||
final dimPixels = (extent * key.devicePixelRatio).round();
|
final dimPixels = (extent * key.devicePixelRatio).round();
|
||||||
final Uint8List bytes = await ImageFileService.getThumbnail(key.entry, dimPixels, dimPixels);
|
final bytes = await ImageFileService.getThumbnail(key.entry, dimPixels, dimPixels);
|
||||||
if (bytes.lengthInBytes == 0) {
|
if (bytes.lengthInBytes == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'dart:typed_data';
|
|
||||||
import 'dart:ui' as ui show Codec;
|
import 'dart:ui' as ui show Codec;
|
||||||
|
|
||||||
import 'package:aves/model/image_file_service.dart';
|
import 'package:aves/model/image_file_service.dart';
|
||||||
|
@ -36,7 +35,7 @@ class UriImage extends ImageProvider<UriImage> {
|
||||||
Future<ui.Codec> _loadAsync(UriImage key, DecoderCallback decode) async {
|
Future<ui.Codec> _loadAsync(UriImage key, DecoderCallback decode) async {
|
||||||
assert(key == this);
|
assert(key == this);
|
||||||
|
|
||||||
final Uint8List bytes = await ImageFileService.getImage(uri, mimeType);
|
final bytes = await ImageFileService.getImage(uri, mimeType);
|
||||||
if (bytes.lengthInBytes == 0) {
|
if (bytes.lengthInBytes == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,8 +324,8 @@ class FullscreenVerticalPageView extends StatefulWidget {
|
||||||
|
|
||||||
class _FullscreenVerticalPageViewState extends State<FullscreenVerticalPageView> {
|
class _FullscreenVerticalPageViewState extends State<FullscreenVerticalPageView> {
|
||||||
bool _isInitialScale = true;
|
bool _isInitialScale = true;
|
||||||
ValueNotifier<Color> _backgroundColorNotifier = ValueNotifier(Colors.black);
|
final ValueNotifier<Color> _backgroundColorNotifier = ValueNotifier(Colors.black);
|
||||||
ValueNotifier<bool> _infoPageVisibleNotifier = ValueNotifier(false);
|
final ValueNotifier<bool> _infoPageVisibleNotifier = ValueNotifier(false);
|
||||||
|
|
||||||
CollectionLens get collection => widget.collection;
|
CollectionLens get collection => widget.collection;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ class InfoPage extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class InfoPageState extends State<InfoPage> {
|
class InfoPageState extends State<InfoPage> {
|
||||||
ScrollController _scrollController = ScrollController();
|
final ScrollController _scrollController = ScrollController();
|
||||||
bool _scrollStartFromTop = false;
|
bool _scrollStartFromTop = false;
|
||||||
|
|
||||||
CollectionLens get collection => widget.collection;
|
CollectionLens get collection => widget.collection;
|
||||||
|
@ -172,7 +172,7 @@ class SectionRow extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
const double dim = 32;
|
const dim = 32.0;
|
||||||
final buildDivider = () => const SizedBox(
|
final buildDivider = () => const SizedBox(
|
||||||
width: dim,
|
width: dim,
|
||||||
child: Divider(
|
child: Divider(
|
||||||
|
|
|
@ -73,8 +73,8 @@ class _LocationSectionState extends State<LocationSection> {
|
||||||
final showMap = (_loadedUri == entry.uri) || (entry.hasGps && widget.visibleNotifier.value);
|
final showMap = (_loadedUri == entry.uri) || (entry.hasGps && widget.visibleNotifier.value);
|
||||||
if (showMap) {
|
if (showMap) {
|
||||||
_loadedUri = entry.uri;
|
_loadedUri = entry.uri;
|
||||||
String location = '';
|
var location = '';
|
||||||
final List<LocationFilter> filters = [];
|
final filters = <LocationFilter>[];
|
||||||
if (entry.isLocated) {
|
if (entry.isLocated) {
|
||||||
final address = entry.addressDetails;
|
final address = entry.addressDetails;
|
||||||
location = address.addressLine;
|
location = address.addressLine;
|
||||||
|
@ -179,7 +179,7 @@ class ImageMapState extends State<ImageMap> with AutomaticKeepAliveClientMixin {
|
||||||
target: widget.latLng,
|
target: widget.latLng,
|
||||||
zoom: widget.initialZoom,
|
zoom: widget.initialZoom,
|
||||||
),
|
),
|
||||||
onMapCreated: (controller) => setState(() => this._controller = controller),
|
onMapCreated: (controller) => setState(() => _controller = controller),
|
||||||
rotateGesturesEnabled: false,
|
rotateGesturesEnabled: false,
|
||||||
scrollGesturesEnabled: false,
|
scrollGesturesEnabled: false,
|
||||||
zoomGesturesEnabled: false,
|
zoomGesturesEnabled: false,
|
||||||
|
|
|
@ -20,7 +20,7 @@ import 'package:percent_indicator/linear_percent_indicator.dart';
|
||||||
|
|
||||||
class StatsPage extends StatelessWidget {
|
class StatsPage extends StatelessWidget {
|
||||||
final CollectionLens collection;
|
final CollectionLens collection;
|
||||||
final Map<String, int> entryCountPerCity = Map(), entryCountPerCountry = Map(), entryCountPerTag = Map();
|
final Map<String, int> entryCountPerCity = {}, entryCountPerCountry = {}, entryCountPerTag = {};
|
||||||
|
|
||||||
List<ImageEntry> get entries => collection.sortedEntries;
|
List<ImageEntry> get entries => collection.sortedEntries;
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class StatsPage extends StatelessWidget {
|
||||||
final catalogued = entries.where((entry) => entry.isCatalogued);
|
final catalogued = entries.where((entry) => entry.isCatalogued);
|
||||||
final withGps = catalogued.where((entry) => entry.hasGps);
|
final withGps = catalogued.where((entry) => entry.hasGps);
|
||||||
final withGpsPercent = withGps.length / collection.entryCount;
|
final withGpsPercent = withGps.length / collection.entryCount;
|
||||||
final Map<String, int> byMimeTypes = groupBy(entries, (entry) => entry.mimeType).map((k, v) => MapEntry(k, v.length));
|
final byMimeTypes = groupBy(entries, (entry) => entry.mimeType).map<String, int>((k, v) => MapEntry(k, v.length));
|
||||||
final imagesByMimeTypes = Map.fromEntries(byMimeTypes.entries.where((kv) => kv.key.startsWith('image/')));
|
final imagesByMimeTypes = Map.fromEntries(byMimeTypes.entries.where((kv) => kv.key.startsWith('image/')));
|
||||||
final videoByMimeTypes = Map.fromEntries(byMimeTypes.entries.where((kv) => kv.key.startsWith('video/')));
|
final videoByMimeTypes = Map.fromEntries(byMimeTypes.entries.where((kv) => kv.key.startsWith('video/')));
|
||||||
child = ListView(
|
child = ListView(
|
||||||
|
@ -127,9 +127,8 @@ class StatsPage extends StatelessWidget {
|
||||||
];
|
];
|
||||||
|
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
return LayoutBuilder(builder: (context, constraints) {
|
||||||
final mq = MediaQuery.of(context);
|
|
||||||
final availableWidth = constraints.maxWidth;
|
final availableWidth = constraints.maxWidth;
|
||||||
final double dim = max(mimeDonutMinWidth, availableWidth / (availableWidth > 4 * mimeDonutMinWidth ? 4 : 2));
|
final dim = max(mimeDonutMinWidth, availableWidth / (availableWidth > 4 * mimeDonutMinWidth ? 4 : 2));
|
||||||
|
|
||||||
final donut = Container(
|
final donut = Container(
|
||||||
width: dim,
|
width: dim,
|
||||||
|
|
12
pubspec.lock
12
pubspec.lock
|
@ -168,7 +168,7 @@ packages:
|
||||||
name: google_maps_flutter
|
name: google_maps_flutter
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.24+1"
|
version: "0.5.25+2"
|
||||||
image:
|
image:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -266,14 +266,14 @@ packages:
|
||||||
name: pdf
|
name: pdf
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0"
|
version: "1.6.0"
|
||||||
pedantic:
|
pedantic:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: pedantic
|
name: pedantic
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0+1"
|
version: "1.9.0"
|
||||||
percent_indicator:
|
percent_indicator:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -287,14 +287,14 @@ packages:
|
||||||
name: permission_handler
|
name: permission_handler
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.4.0+hotfix.2"
|
version: "5.0.0+hotfix.2"
|
||||||
permission_handler_platform_interface:
|
permission_handler_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_platform_interface
|
name: permission_handler_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "2.0.0"
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -322,7 +322,7 @@ packages:
|
||||||
name: printing
|
name: printing
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.2.1"
|
||||||
provider:
|
provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
Loading…
Reference in a new issue