test fix, tuple record migration wip
This commit is contained in:
parent
7afbdfaa84
commit
1117da068b
13 changed files with 61 additions and 63 deletions
|
@ -13,7 +13,6 @@ import 'package:collection/collection.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/painting.dart';
|
import 'package:flutter/painting.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
|
||||||
|
|
||||||
final Covers covers = Covers._private();
|
final Covers covers = Covers._private();
|
||||||
|
|
||||||
|
@ -40,11 +39,11 @@ class Covers {
|
||||||
|
|
||||||
Set<CoverRow> get all => Set.unmodifiable(_rows);
|
Set<CoverRow> get all => Set.unmodifiable(_rows);
|
||||||
|
|
||||||
Tuple3<int?, String?, Color?>? of(CollectionFilter filter) {
|
(int? entryId, String? packageName, Color? color)? of(CollectionFilter filter) {
|
||||||
if (filter is AlbumFilter && vaults.isLocked(filter.album)) return null;
|
if (filter is AlbumFilter && vaults.isLocked(filter.album)) return null;
|
||||||
|
|
||||||
final row = _rows.firstWhereOrNull((row) => row.filter == filter);
|
final row = _rows.firstWhereOrNull((row) => row.filter == filter);
|
||||||
return row != null ? Tuple3(row.entryId, row.packageName, row.color) : null;
|
return row != null ? (row.entryId, row.packageName, row.color) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> set({
|
Future<void> set({
|
||||||
|
@ -113,7 +112,7 @@ class Covers {
|
||||||
}
|
}
|
||||||
|
|
||||||
AlbumType effectiveAlbumType(String albumPath) {
|
AlbumType effectiveAlbumType(String albumPath) {
|
||||||
final filterPackage = of(AlbumFilter(albumPath, null))?.item2;
|
final filterPackage = of(AlbumFilter(albumPath, null))?.$2;
|
||||||
if (filterPackage != null) {
|
if (filterPackage != null) {
|
||||||
return filterPackage.isEmpty ? AlbumType.regular : AlbumType.app;
|
return filterPackage.isEmpty ? AlbumType.regular : AlbumType.app;
|
||||||
} else {
|
} else {
|
||||||
|
@ -122,7 +121,7 @@ class Covers {
|
||||||
}
|
}
|
||||||
|
|
||||||
String? effectiveAlbumPackage(String albumPath) {
|
String? effectiveAlbumPackage(String albumPath) {
|
||||||
final filterPackage = of(AlbumFilter(albumPath, null))?.item2;
|
final filterPackage = of(AlbumFilter(albumPath, null))?.$2;
|
||||||
return filterPackage ?? appInventory.getAlbumAppPackageName(albumPath);
|
return filterPackage ?? appInventory.getAlbumAppPackageName(albumPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ class AlbumFilter extends CoveredCollectionFilter {
|
||||||
@override
|
@override
|
||||||
Future<Color> color(BuildContext context) {
|
Future<Color> color(BuildContext context) {
|
||||||
// custom color has precedence over others, even custom app color
|
// custom color has precedence over others, even custom app color
|
||||||
final customColor = covers.of(this)?.item3;
|
final customColor = covers.of(this)?.$3;
|
||||||
if (customColor != null) return SynchronousFuture(customColor);
|
if (customColor != null) return SynchronousFuture(customColor);
|
||||||
|
|
||||||
final colors = context.read<AvesColorsData>();
|
final colors = context.read<AvesColorsData>();
|
||||||
|
|
|
@ -157,7 +157,7 @@ abstract class CoveredCollectionFilter extends CollectionFilter {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Color> color(BuildContext context) {
|
Future<Color> color(BuildContext context) {
|
||||||
final customColor = covers.of(this)?.item3;
|
final customColor = covers.of(this)?.$3;
|
||||||
if (customColor != null) {
|
if (customColor != null) {
|
||||||
return SynchronousFuture(customColor);
|
return SynchronousFuture(customColor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,9 +274,9 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
|
||||||
final existingCover = covers.of(oldFilter);
|
final existingCover = covers.of(oldFilter);
|
||||||
await covers.set(
|
await covers.set(
|
||||||
filter: newFilter,
|
filter: newFilter,
|
||||||
entryId: existingCover?.item1,
|
entryId: existingCover?.$1,
|
||||||
packageName: existingCover?.item2,
|
packageName: existingCover?.$2,
|
||||||
color: existingCover?.item3,
|
color: existingCover?.$3,
|
||||||
);
|
);
|
||||||
|
|
||||||
renameNewAlbum(sourceAlbum, destinationAlbum);
|
renameNewAlbum(sourceAlbum, destinationAlbum);
|
||||||
|
@ -547,7 +547,7 @@ abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, Place
|
||||||
}
|
}
|
||||||
|
|
||||||
AvesEntry? coverEntry(CollectionFilter filter) {
|
AvesEntry? coverEntry(CollectionFilter filter) {
|
||||||
final id = covers.of(filter)?.item1;
|
final id = covers.of(filter)?.$1;
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
final entry = visibleEntries.firstWhereOrNull((entry) => entry.id == id);
|
final entry = visibleEntries.firstWhereOrNull((entry) => entry.id == id);
|
||||||
if (entry != null) return entry;
|
if (entry != null) return entry;
|
||||||
|
|
|
@ -14,7 +14,6 @@ import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves_model/aves_model.dart';
|
import 'package:aves_model/aves_model.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
|
||||||
|
|
||||||
mixin LocationMixin on CountryMixin, StateMixin {
|
mixin LocationMixin on CountryMixin, StateMixin {
|
||||||
static const commitCountThreshold = 200;
|
static const commitCountThreshold = 200;
|
||||||
|
@ -96,16 +95,16 @@ mixin LocationMixin on CountryMixin, StateMixin {
|
||||||
// - 652 calls (22%) when approximating to 2 decimal places (~1km - town or village)
|
// - 652 calls (22%) when approximating to 2 decimal places (~1km - town or village)
|
||||||
// cf https://en.wikipedia.org/wiki/Decimal_degrees#Precision
|
// cf https://en.wikipedia.org/wiki/Decimal_degrees#Precision
|
||||||
final latLngFactor = pow(10, 2);
|
final latLngFactor = pow(10, 2);
|
||||||
Tuple2<int, int> approximateLatLng(AvesEntry entry) {
|
(int latitude, int longitude) approximateLatLng(AvesEntry entry) {
|
||||||
// entry has coordinates
|
// entry has coordinates
|
||||||
final catalogMetadata = entry.catalogMetadata!;
|
final catalogMetadata = entry.catalogMetadata!;
|
||||||
final lat = catalogMetadata.latitude!;
|
final lat = catalogMetadata.latitude!;
|
||||||
final lng = catalogMetadata.longitude!;
|
final lng = catalogMetadata.longitude!;
|
||||||
return Tuple2<int, int>((lat * latLngFactor).round(), (lng * latLngFactor).round());
|
return ((lat * latLngFactor).round(), (lng * latLngFactor).round());
|
||||||
}
|
}
|
||||||
|
|
||||||
final located = visibleEntries.where((entry) => entry.hasGps).toSet().difference(todo);
|
final located = visibleEntries.where((entry) => entry.hasGps).toSet().difference(todo);
|
||||||
final knownLocations = <Tuple2<int, int>, AddressDetails?>{};
|
final knownLocations = <(int, int), AddressDetails?>{};
|
||||||
located.forEach((entry) {
|
located.forEach((entry) {
|
||||||
knownLocations.putIfAbsent(approximateLatLng(entry), () => entry.addressDetails);
|
knownLocations.putIfAbsent(approximateLatLng(entry), () => entry.addressDetails);
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,13 +3,12 @@ import 'dart:collection';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
|
||||||
|
|
||||||
final ServicePolicy servicePolicy = ServicePolicy._private();
|
final ServicePolicy servicePolicy = ServicePolicy._private();
|
||||||
|
|
||||||
class ServicePolicy {
|
class ServicePolicy {
|
||||||
final StreamController<QueueState> _queueStreamController = StreamController.broadcast();
|
final StreamController<QueueState> _queueStreamController = StreamController.broadcast();
|
||||||
final Map<Object, Tuple2<int, _Task>> _paused = {};
|
final Map<Object, (int, _Task)> _paused = {};
|
||||||
final SplayTreeMap<int, LinkedHashMap<Object, _Task>> _queues = SplayTreeMap();
|
final SplayTreeMap<int, LinkedHashMap<Object, _Task>> _queues = SplayTreeMap();
|
||||||
final LinkedHashMap<Object, _Task> _runningQueue = LinkedHashMap();
|
final LinkedHashMap<Object, _Task> _runningQueue = LinkedHashMap();
|
||||||
|
|
||||||
|
@ -30,8 +29,8 @@ class ServicePolicy {
|
||||||
key ??= platformCall.hashCode;
|
key ??= platformCall.hashCode;
|
||||||
final toResume = _paused.remove(key);
|
final toResume = _paused.remove(key);
|
||||||
if (toResume != null) {
|
if (toResume != null) {
|
||||||
priority = toResume.item1;
|
priority = toResume.$1;
|
||||||
task = toResume.item2 as _Task<T>;
|
task = toResume.$2 as _Task<T>;
|
||||||
completer = task.completer;
|
completer = task.completer;
|
||||||
} else {
|
} else {
|
||||||
completer = Completer<T>();
|
completer = Completer<T>();
|
||||||
|
@ -56,8 +55,8 @@ class ServicePolicy {
|
||||||
Future<T>? resume<T>(Object key) {
|
Future<T>? resume<T>(Object key) {
|
||||||
final toResume = _paused.remove(key);
|
final toResume = _paused.remove(key);
|
||||||
if (toResume != null) {
|
if (toResume != null) {
|
||||||
final priority = toResume.item1;
|
final priority = toResume.$1;
|
||||||
final task = toResume.item2 as _Task<T>;
|
final task = toResume.$2 as _Task<T>;
|
||||||
_getQueue(priority)[key] = task;
|
_getQueue(priority)[key] = task;
|
||||||
_pickNext();
|
_pickNext();
|
||||||
return task.completer.future;
|
return task.completer.future;
|
||||||
|
@ -97,7 +96,7 @@ class ServicePolicy {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pause(Object key, Iterable<int> priorities) {
|
bool pause(Object key, Iterable<int> priorities) {
|
||||||
return _takeOut(key, priorities, (priority, task) => _paused.putIfAbsent(key, () => Tuple2(priority, task)));
|
return _takeOut(key, priorities, (priority, task) => _paused.putIfAbsent(key, () => (priority, task)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPaused(Object key) => _paused.containsKey(key);
|
bool isPaused(Object key) => _paused.containsKey(key);
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:tuple/tuple.dart';
|
|
||||||
|
|
||||||
int highestPowerOf2(num x) => x < 1 ? 0 : pow(2, (log(x) / ln2).floor()).toInt();
|
int highestPowerOf2(num x) => x < 1 ? 0 : pow(2, (log(x) / ln2).floor()).toInt();
|
||||||
|
|
||||||
int smallestPowerOf2(num x) => x < 1 ? 1 : pow(2, (log(x) / ln2).ceil()).toInt();
|
int smallestPowerOf2(num x) => x < 1 ? 1 : pow(2, (log(x) / ln2).ceil()).toInt();
|
||||||
|
@ -10,16 +8,16 @@ int smallestPowerOf2(num x) => x < 1 ? 1 : pow(2, (log(x) / ln2).ceil()).toInt()
|
||||||
double roundToPrecision(final double value, {required final int decimals}) => (value * pow(10, decimals)).round() / pow(10, decimals);
|
double roundToPrecision(final double value, {required final int decimals}) => (value * pow(10, decimals)).round() / pow(10, decimals);
|
||||||
|
|
||||||
// cf https://en.wikipedia.org/wiki/Intersection_(geometry)#Two_line_segments
|
// cf https://en.wikipedia.org/wiki/Intersection_(geometry)#Two_line_segments
|
||||||
Offset? segmentIntersection(Tuple2<Offset, Offset> s1, Tuple2<Offset, Offset> s2) {
|
Offset? segmentIntersection((Offset, Offset) s1, (Offset, Offset) s2) {
|
||||||
final x1 = s1.item1.dx;
|
final x1 = s1.$1.dx;
|
||||||
final y1 = s1.item1.dy;
|
final y1 = s1.$1.dy;
|
||||||
final x2 = s1.item2.dx;
|
final x2 = s1.$2.dx;
|
||||||
final y2 = s1.item2.dy;
|
final y2 = s1.$2.dy;
|
||||||
|
|
||||||
final x3 = s2.item1.dx;
|
final x3 = s2.$1.dx;
|
||||||
final y3 = s2.item1.dy;
|
final y3 = s2.$1.dy;
|
||||||
final x4 = s2.item2.dx;
|
final x4 = s2.$2.dx;
|
||||||
final y4 = s2.item2.dy;
|
final y4 = s2.$2.dy;
|
||||||
|
|
||||||
final a1 = x2 - x1;
|
final a1 = x2 - x1;
|
||||||
final b1 = -(x4 - x3);
|
final b1 = -(x4 - x3);
|
||||||
|
|
|
@ -4,7 +4,6 @@ import 'dart:math';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
|
||||||
|
|
||||||
class TileExtentController {
|
class TileExtentController {
|
||||||
final String settingsRouteKey;
|
final String settingsRouteKey;
|
||||||
|
@ -102,7 +101,7 @@ class TileExtentController {
|
||||||
|
|
||||||
double get effectiveExtentMax => _extentForColumnCount(_effectiveColumnCountMin());
|
double get effectiveExtentMax => _extentForColumnCount(_effectiveColumnCountMin());
|
||||||
|
|
||||||
Tuple2<int, int> get effectiveColumnRange => Tuple2(_effectiveColumnCountMin(), _effectiveColumnCountMax());
|
(int min, int max) get effectiveColumnRange => (_effectiveColumnCountMin(), _effectiveColumnCountMax());
|
||||||
|
|
||||||
int get columnCount => _effectiveColumnCountForExtent(extentNotifier.value);
|
int get columnCount => _effectiveColumnCountForExtent(extentNotifier.value);
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
|
||||||
if (_collection != null) {
|
if (_collection != null) {
|
||||||
final entries = _collection.sortedEntries;
|
final entries = _collection.sortedEntries;
|
||||||
if (entries.isNotEmpty) {
|
if (entries.isNotEmpty) {
|
||||||
final coverEntries = _collection.filters.map((filter) => covers.of(filter)?.item1).whereNotNull().map((id) => entries.firstWhereOrNull((entry) => entry.id == id)).whereNotNull();
|
final coverEntries = _collection.filters.map((filter) => covers.of(filter)?.$1).whereNotNull().map((id) => entries.firstWhereOrNull((entry) => entry.id == id)).whereNotNull();
|
||||||
_coverEntry = coverEntries.firstOrNull ?? entries.first;
|
_coverEntry = coverEntries.firstOrNull ?? entries.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,8 +70,8 @@ class _TileViewDialogState<S, G, L> extends State<TileViewDialog<S, G, L>> with
|
||||||
|
|
||||||
final extentController = tileExtentController;
|
final extentController = tileExtentController;
|
||||||
final columnRange = extentController.effectiveColumnRange;
|
final columnRange = extentController.effectiveColumnRange;
|
||||||
_columnMin = columnRange.item1;
|
_columnMin = columnRange.$1;
|
||||||
_columnMax = columnRange.item2;
|
_columnMax = columnRange.$2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -326,15 +326,15 @@ abstract class ChipSetActionDelegate<T extends CollectionFilter> with FeedbackMi
|
||||||
if (!await unlockFilter(context, filter)) return;
|
if (!await unlockFilter(context, filter)) return;
|
||||||
|
|
||||||
final existingCover = covers.of(filter);
|
final existingCover = covers.of(filter);
|
||||||
final entryId = existingCover?.item1;
|
final entryId = existingCover?.$1;
|
||||||
final customEntry = entryId != null ? context.read<CollectionSource>().visibleEntries.firstWhereOrNull((entry) => entry.id == entryId) : null;
|
final customEntry = entryId != null ? context.read<CollectionSource>().visibleEntries.firstWhereOrNull((entry) => entry.id == entryId) : null;
|
||||||
final selectedCover = await showDialog<Tuple3<AvesEntry?, String?, Color?>>(
|
final selectedCover = await showDialog<Tuple3<AvesEntry?, String?, Color?>>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CoverSelectionDialog(
|
builder: (context) => CoverSelectionDialog(
|
||||||
filter: filter,
|
filter: filter,
|
||||||
customEntry: customEntry,
|
customEntry: customEntry,
|
||||||
customPackage: existingCover?.item2,
|
customPackage: existingCover?.$2,
|
||||||
customColor: existingCover?.item3,
|
customColor: existingCover?.$3,
|
||||||
),
|
),
|
||||||
routeSettings: const RouteSettings(name: CoverSelectionDialog.routeName),
|
routeSettings: const RouteSettings(name: CoverSelectionDialog.routeName),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:aves/l10n/l10n.dart';
|
||||||
import 'package:aves/model/availability.dart';
|
import 'package:aves/model/availability.dart';
|
||||||
import 'package:aves/model/covers.dart';
|
import 'package:aves/model/covers.dart';
|
||||||
import 'package:aves/model/db/db_metadata.dart';
|
import 'package:aves/model/db/db_metadata.dart';
|
||||||
|
@ -201,7 +202,7 @@ void main() {
|
||||||
|
|
||||||
await covers.set(filter: albumFilter, entryId: image1.id, packageName: null, color: null);
|
await covers.set(filter: albumFilter, entryId: image1.id, packageName: null, color: null);
|
||||||
expect(covers.count, 1);
|
expect(covers.count, 1);
|
||||||
expect(covers.of(albumFilter)?.item1, image1.id);
|
expect(covers.of(albumFilter)?.$1, image1.id);
|
||||||
|
|
||||||
await covers.set(filter: albumFilter, entryId: null, packageName: null, color: null);
|
await covers.set(filter: albumFilter, entryId: null, packageName: null, color: null);
|
||||||
expect(covers.count, 0);
|
expect(covers.count, 0);
|
||||||
|
@ -229,7 +230,7 @@ void main() {
|
||||||
expect(favourites.count, 1);
|
expect(favourites.count, 1);
|
||||||
expect(image1.isFavourite, true);
|
expect(image1.isFavourite, true);
|
||||||
expect(covers.count, 1);
|
expect(covers.count, 1);
|
||||||
expect(covers.of(albumFilter)?.item1, image1.id);
|
expect(covers.of(albumFilter)?.$1, image1.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('favourites and covers are cleared when removing entries', () async {
|
test('favourites and covers are cleared when removing entries', () async {
|
||||||
|
@ -348,7 +349,7 @@ void main() {
|
||||||
expect(favourites.count, 1);
|
expect(favourites.count, 1);
|
||||||
expect(image1.isFavourite, true);
|
expect(image1.isFavourite, true);
|
||||||
expect(covers.count, 1);
|
expect(covers.count, 1);
|
||||||
expect(covers.of(albumFilter)?.item1, image1.id);
|
expect(covers.of(albumFilter)?.$1, image1.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('unique album names', (tester) async {
|
testWidgets('unique album names', (tester) async {
|
||||||
|
@ -369,22 +370,26 @@ void main() {
|
||||||
|
|
||||||
final source = await _initSource();
|
final source = await _initSource();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Builder(
|
Localizations(
|
||||||
builder: (context) {
|
locale: AppLocalizations.supportedLocales.first,
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Elea/Zeno'), 'Elea/Zeno');
|
delegates: AppLocalizations.localizationsDelegates,
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Citium/Zeno'), 'Citium/Zeno');
|
child: Builder(
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Cleanthes'), 'Cleanthes');
|
builder: (context) {
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Chrysippus'), 'Chrysippus');
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Elea/Zeno'), 'Elea/Zeno');
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.removablePath}Pictures/Chrysippus'), 'Chrysippus (${FakeStorageService.removableDescription})');
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Citium/Zeno'), 'Citium/Zeno');
|
||||||
expect(source.getAlbumDisplayName(context, FakeStorageService.primaryRootAlbum), FakeStorageService.primaryDescription);
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Cleanthes'), 'Cleanthes');
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Seneca'), 'Pictures/Seneca');
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Chrysippus'), 'Chrysippus');
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Seneca'), 'Seneca');
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.removablePath}Pictures/Chrysippus'), 'Chrysippus (${FakeStorageService.removableDescription})');
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.removablePath}Pictures/Cicero'), 'Cicero');
|
expect(source.getAlbumDisplayName(context, FakeStorageService.primaryRootAlbum), FakeStorageService.primaryDescription);
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.removablePath}Marcus Aurelius'), 'Marcus Aurelius');
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Seneca'), 'Pictures/Seneca');
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Hannah Arendt'), 'Hannah Arendt');
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Seneca'), 'Seneca');
|
||||||
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Arendt'), 'Arendt');
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.removablePath}Pictures/Cicero'), 'Cicero');
|
||||||
return const Placeholder();
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.removablePath}Marcus Aurelius'), 'Marcus Aurelius');
|
||||||
},
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Hannah Arendt'), 'Hannah Arendt');
|
||||||
|
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Arendt'), 'Arendt');
|
||||||
|
return const Placeholder();
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,6 @@ import 'dart:ui';
|
||||||
|
|
||||||
import 'package:aves/utils/math_utils.dart';
|
import 'package:aves/utils/math_utils.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('highest power of 2 that is smaller than or equal to the number', () {
|
test('highest power of 2 that is smaller than or equal to the number', () {
|
||||||
|
@ -29,8 +28,8 @@ void main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('segment intersection', () {
|
test('segment intersection', () {
|
||||||
const s1 = Tuple2(Offset(1, 1), Offset(3, 2));
|
const s1 = (Offset(1, 1), Offset(3, 2));
|
||||||
const s2 = Tuple2(Offset(1, 4), Offset(2, -1));
|
const s2 = (Offset(1, 4), Offset(2, -1));
|
||||||
expect(segmentIntersection(s1, s2), const Offset(17 / 11, 14 / 11));
|
expect(segmentIntersection(s1, s2), const Offset(17 / 11, 14 / 11));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue