hash/== with equatable
This commit is contained in:
parent
d04adf52a2
commit
62c199c745
35 changed files with 224 additions and 480 deletions
|
@ -55,6 +55,10 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
applicationId appId
|
||||
// minSdkVersion constraints:
|
||||
// - Flutter & other plugins: 16
|
||||
// - google_maps_flutter v2.0.5: 20
|
||||
// - Aves native: 19
|
||||
minSdkVersion 20
|
||||
targetSdkVersion 30
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:ui' as ui show Codec;
|
||||
|
||||
import 'package:aves/services/android_app_service.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
@ -49,23 +50,18 @@ class AppIconImage extends ImageProvider<AppIconImageKey> {
|
|||
}
|
||||
}
|
||||
|
||||
class AppIconImageKey {
|
||||
@immutable
|
||||
class AppIconImageKey extends Equatable {
|
||||
final String packageName;
|
||||
final double size;
|
||||
final double scale;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [packageName, size, scale];
|
||||
|
||||
const AppIconImageKey({
|
||||
required this.packageName,
|
||||
required this.size,
|
||||
this.scale = 1.0,
|
||||
});
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is AppIconImageKey && other.packageName == packageName && other.size == size && other.scale == scale;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(packageName, size, scale);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:math';
|
|||
import 'dart:ui' as ui show Codec;
|
||||
|
||||
import 'package:aves/services/services.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
@ -62,7 +63,8 @@ class RegionProvider extends ImageProvider<RegionProviderKey> {
|
|||
void pause() => imageFileService.cancelRegion(key);
|
||||
}
|
||||
|
||||
class RegionProviderKey {
|
||||
@immutable
|
||||
class RegionProviderKey extends Equatable {
|
||||
// do not store the entry as it is, because the key should be constant
|
||||
// but the entry attributes may change over time
|
||||
final String uri, mimeType;
|
||||
|
@ -72,6 +74,9 @@ class RegionProviderKey {
|
|||
final Rectangle<int> region;
|
||||
final Size imageSize;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [uri, pageId, rotationDegrees, isFlipped, sampleSize, region, imageSize];
|
||||
|
||||
const RegionProviderKey({
|
||||
required this.uri,
|
||||
required this.mimeType,
|
||||
|
@ -83,24 +88,6 @@ class RegionProviderKey {
|
|||
required this.imageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is RegionProviderKey && other.uri == uri && other.mimeType == mimeType && other.pageId == pageId && other.rotationDegrees == rotationDegrees && other.isFlipped == isFlipped && other.sampleSize == sampleSize && other.region == region && other.imageSize == imageSize;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(
|
||||
uri,
|
||||
mimeType,
|
||||
pageId,
|
||||
rotationDegrees,
|
||||
isFlipped,
|
||||
sampleSize,
|
||||
region,
|
||||
imageSize,
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{uri=$uri, mimeType=$mimeType, pageId=$pageId, rotationDegrees=$rotationDegrees, isFlipped=$isFlipped, sampleSize=$sampleSize, region=$region, imageSize=$imageSize}';
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:ui' as ui show Codec;
|
||||
|
||||
import 'package:aves/services/services.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
@ -63,7 +64,8 @@ class ThumbnailProvider extends ImageProvider<ThumbnailProviderKey> {
|
|||
void pause() => imageFileService.cancelThumbnail(key);
|
||||
}
|
||||
|
||||
class ThumbnailProviderKey {
|
||||
@immutable
|
||||
class ThumbnailProviderKey extends Equatable {
|
||||
// do not store the entry as it is, because the key should be constant
|
||||
// but the entry attributes may change over time
|
||||
final String uri, mimeType;
|
||||
|
@ -73,6 +75,9 @@ class ThumbnailProviderKey {
|
|||
final int dateModifiedSecs;
|
||||
final double extent;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [uri, pageId, dateModifiedSecs, extent];
|
||||
|
||||
const ThumbnailProviderKey({
|
||||
required this.uri,
|
||||
required this.mimeType,
|
||||
|
@ -83,20 +88,6 @@ class ThumbnailProviderKey {
|
|||
this.extent = 0,
|
||||
});
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is ThumbnailProviderKey && other.uri == uri && other.pageId == pageId && other.dateModifiedSecs == dateModifiedSecs && other.extent == extent;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(
|
||||
uri,
|
||||
pageId,
|
||||
dateModifiedSecs,
|
||||
extent,
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{uri=$uri, mimeType=$mimeType, pageId=$pageId, rotationDegrees=$rotationDegrees, isFlipped=$isFlipped, dateModifiedSecs=$dateModifiedSecs, extent=$extent}';
|
||||
}
|
||||
|
|
|
@ -3,15 +3,20 @@ import 'dart:ui' as ui show Codec;
|
|||
|
||||
import 'package:aves/services/services.dart';
|
||||
import 'package:aves/utils/pedantic.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class UriImage extends ImageProvider<UriImage> {
|
||||
@immutable
|
||||
class UriImage extends ImageProvider<UriImage> with EquatableMixin {
|
||||
final String uri, mimeType;
|
||||
final int? pageId, rotationDegrees, expectedContentLength;
|
||||
final bool isFlipped;
|
||||
final double scale;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [uri, pageId, rotationDegrees, isFlipped, scale];
|
||||
|
||||
const UriImage({
|
||||
required this.uri,
|
||||
required this.mimeType,
|
||||
|
@ -71,22 +76,6 @@ class UriImage extends ImageProvider<UriImage> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is UriImage && other.uri == uri && other.mimeType == mimeType && other.rotationDegrees == rotationDegrees && other.isFlipped == isFlipped && other.pageId == pageId && other.scale == scale;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(
|
||||
uri,
|
||||
mimeType,
|
||||
rotationDegrees,
|
||||
isFlipped,
|
||||
pageId,
|
||||
scale,
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{uri=$uri, mimeType=$mimeType, rotationDegrees=$rotationDegrees, isFlipped=$isFlipped, pageId=$pageId, scale=$scale}';
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:aves/model/filters/album.dart';
|
|||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/services/services.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
@ -77,10 +78,13 @@ class Covers with ChangeNotifier {
|
|||
}
|
||||
|
||||
@immutable
|
||||
class CoverRow {
|
||||
class CoverRow extends Equatable {
|
||||
final CollectionFilter filter;
|
||||
final int contentId;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [filter, contentId];
|
||||
|
||||
const CoverRow({
|
||||
required this.filter,
|
||||
required this.contentId,
|
||||
|
@ -99,16 +103,4 @@ class CoverRow {
|
|||
'filter': filter.toJson(),
|
||||
'contentId': contentId,
|
||||
};
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is CoverRow && other.filter == filter && other.contentId == contentId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(filter, contentId);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{filter=$filter, contentId=$contentId}';
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:aves/model/entry.dart';
|
||||
import 'package:aves/services/services.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
final Favourites favourites = Favourites._private();
|
||||
|
@ -62,10 +62,13 @@ class Favourites with ChangeNotifier {
|
|||
}
|
||||
|
||||
@immutable
|
||||
class FavouriteRow {
|
||||
class FavouriteRow extends Equatable {
|
||||
final int contentId;
|
||||
final String path;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [contentId, path];
|
||||
|
||||
const FavouriteRow({
|
||||
required this.contentId,
|
||||
required this.path,
|
||||
|
@ -82,16 +85,4 @@ class FavouriteRow {
|
|||
'contentId': contentId,
|
||||
'path': path,
|
||||
};
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is FavouriteRow && other.contentId == contentId && other.path == path;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(contentId, path);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{contentId=$contentId, path=$path}';
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@ class AlbumFilter extends CollectionFilter {
|
|||
final String album;
|
||||
final String? displayName;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [album];
|
||||
|
||||
const AlbumFilter(this.album, this.displayName);
|
||||
|
||||
AlbumFilter.fromMap(Map<String, dynamic> json)
|
||||
|
@ -78,16 +81,4 @@ class AlbumFilter extends CollectionFilter {
|
|||
// key `album-{path}` is expected by test driver
|
||||
@override
|
||||
String get key => '$type-$album';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is AlbumFilter && other.album == album;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(type, album);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{album=$album}';
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@ class FavouriteFilter extends CollectionFilter {
|
|||
|
||||
static const instance = FavouriteFilter._private();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
|
||||
const FavouriteFilter._private();
|
||||
|
||||
@override
|
||||
|
@ -37,13 +40,4 @@ class FavouriteFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
String get key => type;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is FavouriteFilter;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => type.hashCode;
|
||||
}
|
||||
|
|
|
@ -11,10 +11,12 @@ import 'package:aves/model/filters/tag.dart';
|
|||
import 'package:aves/model/filters/type.dart';
|
||||
import 'package:aves/utils/color_utils.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
abstract class CollectionFilter implements Comparable<CollectionFilter> {
|
||||
@immutable
|
||||
abstract class CollectionFilter extends Equatable implements Comparable<CollectionFilter> {
|
||||
static const List<String> categoryOrder = [
|
||||
QueryFilter.type,
|
||||
FavouriteFilter.type,
|
||||
|
@ -88,20 +90,15 @@ abstract class CollectionFilter implements Comparable<CollectionFilter> {
|
|||
}
|
||||
}
|
||||
|
||||
class FilterGridItem<T extends CollectionFilter> {
|
||||
@immutable
|
||||
class FilterGridItem<T extends CollectionFilter> with EquatableMixin {
|
||||
final T filter;
|
||||
final AvesEntry? entry;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [filter, entry?.uri];
|
||||
|
||||
const FilterGridItem(this.filter, this.entry);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is FilterGridItem && other.filter == filter && other.entry == entry;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(filter, entry);
|
||||
}
|
||||
|
||||
typedef EntryFilter = bool Function(AvesEntry);
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:aves/model/filters/filters.dart';
|
|||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class LocationFilter extends CollectionFilter {
|
||||
|
@ -10,14 +9,17 @@ class LocationFilter extends CollectionFilter {
|
|||
static const locationSeparator = ';';
|
||||
|
||||
final LocationLevel level;
|
||||
String _location;
|
||||
String? _countryCode;
|
||||
late EntryFilter _test;
|
||||
late final String _location;
|
||||
late final String? _countryCode;
|
||||
late final EntryFilter _test;
|
||||
|
||||
LocationFilter(this.level, this._location) {
|
||||
final split = _location.split(locationSeparator);
|
||||
if (split.isNotEmpty) _location = split[0];
|
||||
if (split.length > 1) _countryCode = split[1];
|
||||
@override
|
||||
List<Object?> get props => [level, _location, _countryCode];
|
||||
|
||||
LocationFilter(this.level, String location) {
|
||||
final split = location.split(locationSeparator);
|
||||
_location = split.isNotEmpty ? split[0] : location;
|
||||
_countryCode = split.length > 1 ? split[1] : null;
|
||||
|
||||
if (_location.isEmpty) {
|
||||
_test = (entry) => !entry.hasGps;
|
||||
|
@ -75,18 +77,6 @@ class LocationFilter extends CollectionFilter {
|
|||
@override
|
||||
String get key => '$type-$level-$_location';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is LocationFilter && other.level == level && other._location == _location;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(type, level, _location);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{level=$level, location=$_location}';
|
||||
|
||||
// U+0041 Latin Capital letter A
|
||||
// U+1F1E6 🇦 REGIONAL INDICATOR SYMBOL LETTER A
|
||||
static const _countryCodeToFlagDiff = 0x1F1E6 - 0x0041;
|
||||
|
|
|
@ -3,20 +3,22 @@ import 'package:aves/ref/mime_types.dart';
|
|||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/utils/mime_utils.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class MimeFilter extends CollectionFilter {
|
||||
static const type = 'mime';
|
||||
|
||||
final String mime;
|
||||
late EntryFilter _test;
|
||||
late String _label;
|
||||
late IconData _icon;
|
||||
late final EntryFilter _test;
|
||||
late final String _label;
|
||||
late final IconData _icon;
|
||||
|
||||
static final image = MimeFilter(MimeTypes.anyImage);
|
||||
static final video = MimeFilter(MimeTypes.anyVideo);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [mime];
|
||||
|
||||
MimeFilter(this.mime) {
|
||||
IconData? icon;
|
||||
var lowMime = mime.toLowerCase();
|
||||
|
@ -73,16 +75,4 @@ class MimeFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
String get key => '$type-$mime';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is MimeFilter && other.mime == mime;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(type, mime);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{mime=$mime}';
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class PathFilter extends CollectionFilter {
|
||||
static const type = 'path';
|
||||
|
||||
final String path;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [path];
|
||||
|
||||
const PathFilter(this.path);
|
||||
|
||||
PathFilter.fromMap(Map<String, dynamic> json)
|
||||
|
@ -31,16 +32,4 @@ class PathFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
String get key => '$type-$path';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is PathFilter && other.path == path;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(type, path);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{path=$path}';
|
||||
}
|
||||
|
|
|
@ -12,7 +12,10 @@ class QueryFilter extends CollectionFilter {
|
|||
|
||||
final String query;
|
||||
final bool colorful;
|
||||
late EntryFilter _test;
|
||||
late final EntryFilter _test;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [query];
|
||||
|
||||
QueryFilter(this.query, {this.colorful = true}) {
|
||||
var upQuery = query.toUpperCase();
|
||||
|
@ -63,16 +66,4 @@ class QueryFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
String get key => '$type-$query';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is QueryFilter && other.query == query;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(type, query);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{query=$query}';
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class TagFilter extends CollectionFilter {
|
||||
static const type = 'tag';
|
||||
|
||||
final String tag;
|
||||
late EntryFilter _test;
|
||||
late final EntryFilter _test;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [tag];
|
||||
|
||||
TagFilter(this.tag) {
|
||||
if (tag.isEmpty) {
|
||||
|
@ -49,16 +51,4 @@ class TagFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
String get key => '$type-$tag';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is TagFilter && other.tag == tag;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(type, tag);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{tag=$tag}';
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class TypeFilter extends CollectionFilter {
|
||||
|
@ -14,8 +13,8 @@ class TypeFilter extends CollectionFilter {
|
|||
static const _sphericalVideo = 'spherical_video'; // subset of videos
|
||||
|
||||
final String itemType;
|
||||
late EntryFilter _test;
|
||||
late IconData _icon;
|
||||
late final EntryFilter _test;
|
||||
late final IconData _icon;
|
||||
|
||||
static final animated = TypeFilter._private(_animated);
|
||||
static final geotiff = TypeFilter._private(_geotiff);
|
||||
|
@ -23,12 +22,19 @@ class TypeFilter extends CollectionFilter {
|
|||
static final panorama = TypeFilter._private(_panorama);
|
||||
static final sphericalVideo = TypeFilter._private(_sphericalVideo);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [itemType];
|
||||
|
||||
TypeFilter._private(this.itemType) {
|
||||
switch (itemType) {
|
||||
case _animated:
|
||||
_test = (entry) => entry.isAnimated;
|
||||
_icon = AIcons.animated;
|
||||
break;
|
||||
case _geotiff:
|
||||
_test = (entry) => entry.isGeotiff;
|
||||
_icon = AIcons.geo;
|
||||
break;
|
||||
case _motionPhoto:
|
||||
_test = (entry) => entry.isMotionPhoto;
|
||||
_icon = AIcons.motionPhoto;
|
||||
|
@ -41,10 +47,6 @@ class TypeFilter extends CollectionFilter {
|
|||
_test = (entry) => entry.isVideo && entry.is360;
|
||||
_icon = AIcons.threeSixty;
|
||||
break;
|
||||
case _geotiff:
|
||||
_test = (entry) => entry.isGeotiff;
|
||||
_icon = AIcons.geo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,16 +93,4 @@ class TypeFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
String get key => '$type-$itemType';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is TypeFilter && other.itemType == itemType;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(type, itemType);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{itemType=$itemType}';
|
||||
}
|
||||
|
|
|
@ -1,41 +1,25 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
@immutable
|
||||
class SectionKey {
|
||||
const SectionKey();
|
||||
}
|
||||
|
||||
class EntryAlbumSectionKey extends SectionKey {
|
||||
class EntryAlbumSectionKey extends SectionKey with EquatableMixin {
|
||||
final String? directory;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [directory];
|
||||
|
||||
const EntryAlbumSectionKey(this.directory);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is EntryAlbumSectionKey && other.directory == directory;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => directory.hashCode;
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{directory=$directory}';
|
||||
}
|
||||
|
||||
class EntryDateSectionKey extends SectionKey {
|
||||
class EntryDateSectionKey extends SectionKey with EquatableMixin {
|
||||
final DateTime? date;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [date];
|
||||
|
||||
const EntryDateSectionKey(this.date);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is EntryDateSectionKey && other.date == date;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => date.hashCode;
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{date=$date}';
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@immutable
|
||||
class ImageOpEvent {
|
||||
class ImageOpEvent extends Equatable {
|
||||
final bool success;
|
||||
final String uri;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [success, uri];
|
||||
|
||||
const ImageOpEvent({
|
||||
required this.success,
|
||||
required this.uri,
|
||||
|
@ -17,18 +21,6 @@ class ImageOpEvent {
|
|||
uri: map['uri'],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is ImageOpEvent && other.success == success && other.uri == uri;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(success, uri);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{success=$success, uri=$uri}';
|
||||
}
|
||||
|
||||
class MoveOpEvent extends ImageOpEvent {
|
||||
|
@ -55,6 +47,9 @@ class MoveOpEvent extends ImageOpEvent {
|
|||
class ExportOpEvent extends MoveOpEvent {
|
||||
final int? pageId;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [success, uri, pageId];
|
||||
|
||||
const ExportOpEvent({required bool success, required String uri, this.pageId, required Map newFields})
|
||||
: super(
|
||||
success: success,
|
||||
|
@ -70,16 +65,4 @@ class ExportOpEvent extends MoveOpEvent {
|
|||
newFields: map['newFields'] ?? {},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is ExportOpEvent && other.success == success && other.uri == uri && other.pageId == pageId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(success, uri, pageId);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{success=$success, uri=$uri, pageId=$pageId, newFields=$newFields}';
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:aves/services/services.dart';
|
|||
import 'package:aves/utils/change_notifier.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
|
@ -155,9 +156,12 @@ class StorageVolume {
|
|||
}
|
||||
|
||||
@immutable
|
||||
class VolumeRelativeDirectory {
|
||||
class VolumeRelativeDirectory extends Equatable {
|
||||
final String volumePath, relativeDir;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [volumePath, relativeDir];
|
||||
|
||||
const VolumeRelativeDirectory({
|
||||
required this.volumePath,
|
||||
required this.relativeDir,
|
||||
|
@ -187,13 +191,4 @@ class VolumeRelativeDirectory {
|
|||
final volume = androidFileUtils.storageVolumes.firstWhereOrNull((volume) => volume.path == volumePath);
|
||||
return volume?.getDescription(context) ?? volumePath;
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is VolumeRelativeDirectory && other.volumePath == volumePath && other.relativeDir == relativeDir;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(volumePath, relativeDir);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ class Constants {
|
|||
Dependency(
|
||||
name: 'AndroidSVG',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/BigBadaboom/androidsvg/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/BigBadaboom/androidsvg',
|
||||
),
|
||||
Dependency(
|
||||
|
@ -56,19 +55,16 @@ class Constants {
|
|||
Dependency(
|
||||
name: 'CWAC-Document',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/commonsguy/cwac-document/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/commonsguy/cwac-document',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Glide',
|
||||
license: 'Apache 2.0, BSD 2-Clause',
|
||||
licenseUrl: 'https://github.com/bumptech/glide/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/bumptech/glide',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Metadata Extractor',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/drewnoakes/metadata-extractor/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/drewnoakes/metadata-extractor',
|
||||
),
|
||||
];
|
||||
|
@ -77,49 +73,44 @@ class Constants {
|
|||
Dependency(
|
||||
name: 'Connectivity Plus',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/fluttercommunity/plus_plugins/blob/main/packages/connectivity_plus/LICENSE',
|
||||
licenseUrl: 'https://github.com/fluttercommunity/plus_plugins/blob/main/packages/connectivity_plus/connectivity_plus/LICENSE',
|
||||
sourceUrl: 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/connectivity_plus',
|
||||
),
|
||||
Dependency(
|
||||
name: 'FlutterFire (Core, Crashlytics)',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/FirebaseExtended/flutterfire/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/FirebaseExtended/flutterfire',
|
||||
),
|
||||
Dependency(
|
||||
name: 'fijkplayer (Aves fork)',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/deckerst/fijkplayer/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/deckerst/fijkplayer',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Google API Availability',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/Baseflow/flutter-google-api-availability/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/Baseflow/flutter-google-api-availability',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Google Maps for Flutter',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/flutter/plugins/blob/master/packages/google_maps_flutter/google_maps_flutter/LICENSE',
|
||||
sourceUrl: 'https://github.com/flutter/plugins/blob/master/packages/google_maps_flutter/google_maps_flutter',
|
||||
sourceUrl: 'https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Package Info Plus',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/package_info_plus/LICENSE',
|
||||
licenseUrl: 'https://github.com/fluttercommunity/plus_plugins/blob/main/packages/package_info_plus/package_info_plus/LICENSE',
|
||||
sourceUrl: 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/package_info_plus',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Permission Handler',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/Baseflow/flutter-permission-handler/blob/develop/permission_handler/LICENSE',
|
||||
sourceUrl: 'https://github.com/Baseflow/flutter-permission-handler',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Printing',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/DavBfr/dart_pdf/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/DavBfr/dart_pdf',
|
||||
),
|
||||
Dependency(
|
||||
|
@ -130,21 +121,19 @@ class Constants {
|
|||
),
|
||||
Dependency(
|
||||
name: 'sqflite',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/tekartik/sqflite/blob/master/sqflite/LICENSE',
|
||||
license: 'BSD 2-Clause',
|
||||
sourceUrl: 'https://github.com/tekartik/sqflite',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Streams Channel (Aves fork)',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/deckerst/aves_streams_channel/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/deckerst/aves_streams_channel',
|
||||
),
|
||||
Dependency(
|
||||
name: 'URL Launcher',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/flutter/plugins/blob/master/packages/url_launcher/url_launcher/LICENSE',
|
||||
sourceUrl: 'https://github.com/flutter/plugins/blob/master/packages/url_launcher/url_launcher',
|
||||
sourceUrl: 'https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher',
|
||||
),
|
||||
];
|
||||
|
||||
|
@ -152,37 +141,31 @@ class Constants {
|
|||
Dependency(
|
||||
name: 'Charts',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/google/charts/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/google/charts',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Decorated Icon',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/benPesso/flutter_decorated_icon/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/benPesso/flutter_decorated_icon',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Expansion Tile Card (Aves fork)',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/deckerst/expansion_tile_card/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/deckerst/expansion_tile_card',
|
||||
),
|
||||
Dependency(
|
||||
name: 'FlexColorPicker',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/rydmike/flex_color_picker/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/rydmike/flex_color_picker',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Flutter Highlight',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/git-touch/highlight/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/git-touch/highlight',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Flutter Map',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/fleaflet/flutter_map/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/fleaflet/flutter_map',
|
||||
),
|
||||
Dependency(
|
||||
|
@ -194,19 +177,16 @@ class Constants {
|
|||
Dependency(
|
||||
name: 'Flutter Staggered Animations',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/mobiten/flutter_staggered_animations/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/mobiten/flutter_staggered_animations',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Material Design Icons Flutter',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/ziofat/material_design_icons_flutter/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/ziofat/material_design_icons_flutter',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Overlay Support',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/boyan01/overlay_support/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/boyan01/overlay_support',
|
||||
),
|
||||
Dependency(
|
||||
|
@ -218,19 +198,16 @@ class Constants {
|
|||
Dependency(
|
||||
name: 'Panorama',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/zesage/panorama/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/zesage/panorama',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Percent Indicator',
|
||||
license: 'BSD 2-Clause',
|
||||
licenseUrl: 'https://github.com/diegoveloper/flutter_percent_indicator/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/diegoveloper/flutter_percent_indicator/',
|
||||
sourceUrl: 'https://github.com/diegoveloper/flutter_percent_indicator',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Provider',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/rrousselGit/provider/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/rrousselGit/provider',
|
||||
),
|
||||
];
|
||||
|
@ -239,19 +216,21 @@ class Constants {
|
|||
Dependency(
|
||||
name: 'Collection',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/dart-lang/collection/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/dart-lang/collection',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Country Code',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/denixport/dart.country/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/denixport/dart.country',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Equatable',
|
||||
license: 'MIT',
|
||||
sourceUrl: 'https://github.com/felangel/equatable',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Event Bus',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/marcojakob/dart-event-bus/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/marcojakob/dart-event-bus',
|
||||
),
|
||||
Dependency(
|
||||
|
@ -263,49 +242,41 @@ class Constants {
|
|||
Dependency(
|
||||
name: 'Get It',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/fluttercommunity/get_it/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/fluttercommunity/get_it',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Github',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/SpinlockLabs/github.dart/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/SpinlockLabs/github.dart',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Intl',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/dart-lang/intl/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/dart-lang/intl',
|
||||
),
|
||||
Dependency(
|
||||
name: 'LatLong2',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/jifalops/dart-latlong/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/jifalops/dart-latlong',
|
||||
),
|
||||
Dependency(
|
||||
name: 'PDF for Dart and Flutter',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/DavBfr/dart_pdf/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/DavBfr/dart_pdf',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Tuple',
|
||||
license: 'BSD 2-Clause',
|
||||
licenseUrl: 'https://github.com/dart-lang/tuple/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/dart-lang/tuple',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Version',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/dartninja/version/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/dartninja/version',
|
||||
),
|
||||
Dependency(
|
||||
name: 'XML',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/renggli/dart-xml/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/renggli/dart-xml',
|
||||
),
|
||||
];
|
||||
|
@ -320,7 +291,7 @@ class Dependency {
|
|||
const Dependency({
|
||||
required this.name,
|
||||
required this.license,
|
||||
required this.licenseUrl,
|
||||
String? licenseUrl,
|
||||
required this.sourceUrl,
|
||||
});
|
||||
}) : licenseUrl = licenseUrl ?? '$sourceUrl/blob/master/LICENSE';
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
|
|||
import 'package:aves/widgets/common/providers/highlight_info_provider.dart';
|
||||
import 'package:aves/widgets/home_page.dart';
|
||||
import 'package:aves/widgets/welcome_page.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -50,6 +51,7 @@ class _AvesAppState extends State<AvesApp> {
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
EquatableConfig.stringify = true;
|
||||
initPlatformServices();
|
||||
_appSetup = _setup();
|
||||
_mediaStoreChangeChannel.receiveBroadcastStream().listen((event) => _onMediaStoreChange(event as String?));
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:math';
|
|||
import 'package:aves/model/source/section_keys.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
@ -221,13 +222,17 @@ class SectionedListLayout<T> {
|
|||
String toString() => '$runtimeType#${shortHash(this)}{sectionCount=${sections.length} columnCount=$columnCount, tileExtent=$tileExtent}';
|
||||
}
|
||||
|
||||
class SectionLayout {
|
||||
@immutable
|
||||
class SectionLayout extends Equatable {
|
||||
final SectionKey sectionKey;
|
||||
final int firstIndex, lastIndex, bodyFirstIndex;
|
||||
final double minOffset, maxOffset, bodyMinOffset;
|
||||
final double headerExtent, tileExtent, spacing, mainAxisStride;
|
||||
final IndexedWidgetBuilder builder;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [sectionKey, firstIndex, lastIndex, minOffset, maxOffset, headerExtent, tileExtent, spacing];
|
||||
|
||||
const SectionLayout({
|
||||
required this.sectionKey,
|
||||
required this.firstIndex,
|
||||
|
@ -263,15 +268,6 @@ class SectionLayout {
|
|||
if (scrollOffset < 0) return firstIndex;
|
||||
return bodyFirstIndex + (scrollOffset / mainAxisStride).ceil() - 1;
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is SectionLayout && runtimeType == other.runtimeType && sectionKey == other.sectionKey && firstIndex == other.firstIndex && lastIndex == other.lastIndex && minOffset == other.minOffset && maxOffset == other.maxOffset && headerExtent == other.headerExtent && tileExtent == other.tileExtent && spacing == other.spacing;
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(sectionKey, firstIndex, lastIndex, minOffset, maxOffset, headerExtent, tileExtent, spacing);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{sectionKey=$sectionKey, firstIndex=$firstIndex, lastIndex=$lastIndex, minOffset=$minOffset, maxOffset=$maxOffset, headerExtent=$headerExtent, tileExtent=$tileExtent, spacing=$spacing}';
|
||||
}
|
||||
|
||||
class _GridRow extends MultiChildRenderObjectWidget {
|
||||
|
|
|
@ -1,28 +1,22 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@immutable
|
||||
class MagnifierState {
|
||||
const MagnifierState({
|
||||
required this.position,
|
||||
required this.scale,
|
||||
required this.source,
|
||||
});
|
||||
|
||||
class MagnifierState extends Equatable {
|
||||
final Offset position;
|
||||
final double? scale;
|
||||
final ChangeSource source;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is MagnifierState && runtimeType == other.runtimeType && position == other.position && scale == other.scale;
|
||||
List<Object?> get props => [position, scale, source];
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(position, scale, source);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{position: $position, scale: $scale, source: $source}';
|
||||
const MagnifierState({
|
||||
required this.position,
|
||||
required this.scale,
|
||||
required this.source,
|
||||
});
|
||||
}
|
||||
|
||||
enum ChangeSource { internal, gesture, animation }
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:aves/widgets/common/magnifier/magnifier.dart';
|
|||
import 'package:aves/widgets/common/magnifier/pan/corner_hit_detector.dart';
|
||||
import 'package:aves/widgets/common/magnifier/scale/scale_boundaries.dart';
|
||||
import 'package:aves/widgets/common/magnifier/scale/state.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// Internal widget in which controls all animations lifecycle, core responses
|
||||
|
@ -276,17 +277,21 @@ class _MagnifierCoreState extends State<MagnifierCore> with TickerProviderStateM
|
|||
}
|
||||
}
|
||||
|
||||
class _CenterWithOriginalSizeDelegate extends SingleChildLayoutDelegate {
|
||||
@immutable
|
||||
class _CenterWithOriginalSizeDelegate extends SingleChildLayoutDelegate with EquatableMixin {
|
||||
final Size subjectSize;
|
||||
final Alignment basePosition;
|
||||
final bool applyScale;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [subjectSize, basePosition, applyScale];
|
||||
|
||||
const _CenterWithOriginalSizeDelegate(
|
||||
this.subjectSize,
|
||||
this.basePosition,
|
||||
this.applyScale,
|
||||
);
|
||||
|
||||
final Size subjectSize;
|
||||
final Alignment basePosition;
|
||||
final bool applyScale;
|
||||
|
||||
@override
|
||||
Offset getPositionForChild(Size size, Size childSize) {
|
||||
final childWidth = applyScale ? subjectSize.width : childSize.width;
|
||||
|
@ -309,10 +314,4 @@ class _CenterWithOriginalSizeDelegate extends SingleChildLayoutDelegate {
|
|||
bool shouldRelayout(_CenterWithOriginalSizeDelegate oldDelegate) {
|
||||
return oldDelegate != this;
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is _CenterWithOriginalSizeDelegate && runtimeType == other.runtimeType && subjectSize == other.subjectSize && basePosition == other.basePosition && applyScale == other.applyScale;
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(subjectSize, basePosition, applyScale);
|
||||
}
|
||||
|
|
|
@ -2,17 +2,22 @@ import 'dart:ui';
|
|||
|
||||
import 'package:aves/widgets/common/magnifier/controller/controller.dart';
|
||||
import 'package:aves/widgets/common/magnifier/scale/scale_level.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// Internal class to wrap custom scale boundaries (min, max and initial)
|
||||
/// Also, stores values regarding the two sizes: the container and the child.
|
||||
class ScaleBoundaries {
|
||||
@immutable
|
||||
class ScaleBoundaries extends Equatable {
|
||||
final ScaleLevel _minScale;
|
||||
final ScaleLevel _maxScale;
|
||||
final ScaleLevel _initialScale;
|
||||
final Size viewportSize;
|
||||
final Size childSize;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [_minScale, _maxScale, _initialScale, viewportSize, childSize];
|
||||
|
||||
const ScaleBoundaries({
|
||||
required ScaleLevel minScale,
|
||||
required ScaleLevel maxScale,
|
||||
|
@ -57,13 +62,4 @@ class ScaleBoundaries {
|
|||
Offset childToStatePosition(double scale, Offset childPosition) {
|
||||
return (_childCenter - childPosition) * scale;
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is ScaleBoundaries && runtimeType == other.runtimeType && _minScale == other._minScale && _maxScale == other._maxScale && _initialScale == other._initialScale && viewportSize == other.viewportSize && childSize == other.childSize;
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(_minScale, _maxScale, _initialScale, viewportSize, childSize);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{viewportSize=$viewportSize, childSize=$childSize, initialScale=$initialScale, minScale=$minScale, maxScale=$maxScale}';
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
class ScaleLevel {
|
||||
@immutable
|
||||
class ScaleLevel extends Equatable {
|
||||
final ScaleReference ref;
|
||||
final double factor;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [ref, factor];
|
||||
|
||||
const ScaleLevel({
|
||||
this.ref = ScaleReference.absolute,
|
||||
this.factor = 1.0,
|
||||
|
@ -15,18 +20,6 @@ class ScaleLevel {
|
|||
static double scaleForContained(Size containerSize, Size childSize) => min(containerSize.width / childSize.width, containerSize.height / childSize.height);
|
||||
|
||||
static double scaleForCovering(Size containerSize, Size childSize) => max(containerSize.width / childSize.width, containerSize.height / childSize.height);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{ref=$ref, factor=$factor}';
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is ScaleLevel && other.ref == ref && other.factor == factor;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(ref, factor);
|
||||
}
|
||||
|
||||
enum ScaleReference { absolute, contained, covered }
|
||||
|
|
|
@ -1,29 +1,24 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:aves/widgets/common/magnifier/controller/state.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@immutable
|
||||
class ScaleStateChange {
|
||||
const ScaleStateChange({
|
||||
required this.state,
|
||||
required this.source,
|
||||
this.childFocalPoint,
|
||||
});
|
||||
|
||||
class ScaleStateChange extends Equatable {
|
||||
final ScaleState state;
|
||||
final ChangeSource source;
|
||||
final Offset? childFocalPoint;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is ScaleStateChange && runtimeType == other.runtimeType && state == other.state && childFocalPoint == other.childFocalPoint;
|
||||
List<Object?> get props => [state, source, childFocalPoint];
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(state, source, childFocalPoint);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{scaleState: $state, source: $source, childFocalPoint: $childFocalPoint}';
|
||||
const ScaleStateChange({
|
||||
required this.state,
|
||||
required this.source,
|
||||
this.childFocalPoint,
|
||||
});
|
||||
}
|
||||
|
||||
enum ScaleState {
|
||||
|
|
|
@ -2,29 +2,20 @@ import 'package:aves/model/source/section_keys.dart';
|
|||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/utils/android_file_utils.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ChipSectionKey extends SectionKey {
|
||||
class ChipSectionKey extends SectionKey with EquatableMixin {
|
||||
final String title;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [title];
|
||||
|
||||
const ChipSectionKey({
|
||||
this.title = '',
|
||||
});
|
||||
|
||||
Widget? get leading => null;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is ChipSectionKey && other.title == title;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => title.hashCode;
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{title=$title}';
|
||||
}
|
||||
|
||||
class AlbumImportanceSectionKey extends ChipSectionKey {
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
import 'package:aves/model/entry.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class HeroInfo {
|
||||
@immutable
|
||||
class HeroInfo extends Equatable {
|
||||
// hero tag should include a collection identifier, so that it animates
|
||||
// between different views of the entry in the same collection (e.g. thumbnails <-> viewer)
|
||||
// but not between different collection instances, even with the same attributes (e.g. reloading collection page via drawer)
|
||||
final int? collectionId;
|
||||
final AvesEntry? entry;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [collectionId, entry?.uri];
|
||||
|
||||
const HeroInfo(this.collectionId, this.entry);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is HeroInfo && other.collectionId == collectionId && other.entry == entry;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(collectionId, entry);
|
||||
}
|
||||
|
|
|
@ -12,13 +12,18 @@ import 'package:aves/widgets/viewer/info/metadata/xmp_ns/photoshop.dart';
|
|||
import 'package:aves/widgets/viewer/info/metadata/xmp_ns/tiff.dart';
|
||||
import 'package:aves/widgets/viewer/info/metadata/xmp_ns/xmp.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class XmpNamespace {
|
||||
@immutable
|
||||
class XmpNamespace extends Equatable {
|
||||
final String namespace;
|
||||
final Map<String, String> rawProps;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [namespace];
|
||||
|
||||
const XmpNamespace(this.namespace, this.rawProps);
|
||||
|
||||
factory XmpNamespace.create(String namespace, Map<String, String> rawProps) {
|
||||
|
@ -119,20 +124,6 @@ class XmpNamespace {
|
|||
String formatValue(XmpProp prop) => prop.value;
|
||||
|
||||
Map<String, InfoLinkHandler> linkifyValues(List<XmpProp> props) => {};
|
||||
|
||||
// identity
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is XmpNamespace && other.namespace == namespace;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => namespace.hashCode;
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType#${shortHash(this)}{namespace=$namespace}';
|
||||
}
|
||||
|
||||
class XmpProp {
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import 'package:aves/widgets/viewer/visual/subtitle/span.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@immutable
|
||||
class StyledSubtitleLine with Diagnosticable {
|
||||
class StyledSubtitleLine extends Equatable with Diagnosticable {
|
||||
final List<StyledSubtitleSpan> spans;
|
||||
final List<Path>? clip;
|
||||
final Offset? position;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [spans, clip, position];
|
||||
|
||||
const StyledSubtitleLine({
|
||||
required this.spans,
|
||||
this.clip,
|
||||
|
@ -33,17 +37,4 @@ class StyledSubtitleLine with Diagnosticable {
|
|||
properties.add(DiagnosticsProperty<List<Path>>('clip', clip));
|
||||
properties.add(DiagnosticsProperty<Offset>('position', position));
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is StyledSubtitleLine && other.spans == spans && other.clip == clip && other.position == position;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(
|
||||
spans,
|
||||
clip,
|
||||
position,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
import 'package:aves/widgets/viewer/visual/subtitle/style.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@immutable
|
||||
class StyledSubtitleSpan with Diagnosticable {
|
||||
class StyledSubtitleSpan extends Equatable with Diagnosticable {
|
||||
final TextSpan textSpan;
|
||||
final SubtitleStyle extraStyle;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [textSpan, extraStyle];
|
||||
|
||||
const StyledSubtitleSpan({
|
||||
required this.textSpan,
|
||||
required this.extraStyle,
|
||||
|
@ -28,16 +32,4 @@ class StyledSubtitleSpan with Diagnosticable {
|
|||
properties.add(DiagnosticsProperty<TextSpan>('textSpan', textSpan));
|
||||
properties.add(DiagnosticsProperty<SubtitleStyle>('extraStyle', extraStyle));
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is StyledSubtitleSpan && other.textSpan == textSpan && other.extraStyle == extraStyle;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(
|
||||
textSpan,
|
||||
extraStyle,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@immutable
|
||||
class SubtitleStyle with Diagnosticable {
|
||||
class SubtitleStyle extends Equatable with Diagnosticable {
|
||||
final TextAlign? hAlign;
|
||||
final TextAlignVertical? vAlign;
|
||||
final Color? borderColor;
|
||||
|
@ -15,6 +16,23 @@ class SubtitleStyle with Diagnosticable {
|
|||
|
||||
bool get shearing => (shearX ?? 0) != 0 || (shearY ?? 0) != 0;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
hAlign,
|
||||
vAlign,
|
||||
borderColor,
|
||||
borderWidth,
|
||||
edgeBlur,
|
||||
rotationX,
|
||||
rotationY,
|
||||
rotationZ,
|
||||
scaleX,
|
||||
scaleY,
|
||||
shearX,
|
||||
shearY,
|
||||
drawingPaths?.length,
|
||||
];
|
||||
|
||||
const SubtitleStyle({
|
||||
this.hAlign,
|
||||
this.vAlign,
|
||||
|
@ -80,27 +98,4 @@ class SubtitleStyle with Diagnosticable {
|
|||
properties.add(DoubleProperty('shearY', shearY));
|
||||
properties.add(DiagnosticsProperty<List<Path>>('drawingPaths', drawingPaths));
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is SubtitleStyle && other.hAlign == hAlign && other.vAlign == vAlign && other.borderColor == borderColor && other.borderWidth == borderWidth && other.edgeBlur == edgeBlur && other.rotationX == rotationX && other.rotationY == rotationY && other.rotationZ == rotationZ && other.scaleX == scaleX && other.scaleY == scaleY && other.shearX == shearX && other.shearY == shearY && other.drawingPaths == drawingPaths;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(
|
||||
hAlign,
|
||||
vAlign,
|
||||
borderColor,
|
||||
borderWidth,
|
||||
edgeBlur,
|
||||
rotationX,
|
||||
rotationY,
|
||||
rotationZ,
|
||||
scaleX,
|
||||
scaleY,
|
||||
shearX,
|
||||
shearY,
|
||||
drawingPaths?.length,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -183,6 +183,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
equatable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: equatable
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
event_bus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -17,6 +17,7 @@ dependencies:
|
|||
connectivity_plus:
|
||||
country_code:
|
||||
decorated_icon:
|
||||
equatable:
|
||||
event_bus:
|
||||
expansion_tile_card:
|
||||
git:
|
||||
|
|
Loading…
Reference in a new issue