Browse Source

feat(sort_box,neon_files,neon_news,neon_notes): recursive sort

Signed-off-by: Nikolas Rimikis <rimikis.nikolas@gmail.com>
pull/591/head
Nikolas Rimikis 1 year ago
parent
commit
a7d861f0a1
No known key found for this signature in database
GPG Key ID: 85ED1DE9786A4FF2
  1. 8
      packages/neon/neon_files/lib/sort/files.dart
  2. 8
      packages/neon/neon_news/lib/sort/articles.dart
  3. 8
      packages/neon/neon_news/lib/sort/feeds.dart
  4. 8
      packages/neon/neon_news/lib/sort/folders.dart
  5. 4
      packages/neon/neon_notes/lib/sort/categories.dart
  6. 4
      packages/neon/neon_notes/lib/sort/notes.dart
  7. 42
      packages/sort_box/lib/sort_box.dart
  8. 100
      packages/sort_box/test/sort_box_test.dart

8
packages/neon/neon_files/lib/sort/files.dart

@ -7,7 +7,11 @@ final filesSortBox = SortBox<FilesSortProperty, WebDavFile>(
FilesSortProperty.size: (final file) => file.size ?? 0, FilesSortProperty.size: (final file) => file.size ?? 0,
}, },
{ {
FilesSortProperty.modifiedDate: Box(FilesSortProperty.name, SortBoxOrder.ascending), FilesSortProperty.modifiedDate: {
FilesSortProperty.size: Box(FilesSortProperty.name, SortBoxOrder.ascending), Box(FilesSortProperty.name, SortBoxOrder.ascending),
},
FilesSortProperty.size: {
Box(FilesSortProperty.name, SortBoxOrder.ascending),
},
}, },
); );

8
packages/neon/neon_news/lib/sort/articles.dart

@ -7,7 +7,11 @@ final articlesSortBox = SortBox<ArticlesSortProperty, NewsArticle>(
ArticlesSortProperty.byFeed: (final article) => article.feedId, ArticlesSortProperty.byFeed: (final article) => article.feedId,
}, },
{ {
ArticlesSortProperty.alphabetical: Box(ArticlesSortProperty.publishDate, SortBoxOrder.descending), ArticlesSortProperty.alphabetical: {
ArticlesSortProperty.byFeed: Box(ArticlesSortProperty.alphabetical, SortBoxOrder.ascending), Box(ArticlesSortProperty.publishDate, SortBoxOrder.descending),
},
ArticlesSortProperty.byFeed: {
Box(ArticlesSortProperty.alphabetical, SortBoxOrder.ascending),
},
}, },
); );

8
packages/neon/neon_news/lib/sort/feeds.dart

@ -6,7 +6,11 @@ final feedsSortBox = SortBox<FeedsSortProperty, NewsFeed>(
FeedsSortProperty.unreadCount: (final feed) => feed.unreadCount ?? 0, FeedsSortProperty.unreadCount: (final feed) => feed.unreadCount ?? 0,
}, },
{ {
FeedsSortProperty.alphabetical: Box(FeedsSortProperty.unreadCount, SortBoxOrder.descending), FeedsSortProperty.alphabetical: {
FeedsSortProperty.unreadCount: Box(FeedsSortProperty.alphabetical, SortBoxOrder.ascending), Box(FeedsSortProperty.unreadCount, SortBoxOrder.descending),
},
FeedsSortProperty.unreadCount: {
Box(FeedsSortProperty.alphabetical, SortBoxOrder.ascending),
},
}, },
); );

8
packages/neon/neon_news/lib/sort/folders.dart

@ -6,8 +6,12 @@ final foldersSortBox = SortBox<FoldersSortProperty, FolderFeedsWrapper>(
FoldersSortProperty.unreadCount: (final folderFeedsWrapper) => folderFeedsWrapper.$3, FoldersSortProperty.unreadCount: (final folderFeedsWrapper) => folderFeedsWrapper.$3,
}, },
{ {
FoldersSortProperty.alphabetical: Box(FoldersSortProperty.unreadCount, SortBoxOrder.descending), FoldersSortProperty.alphabetical: {
FoldersSortProperty.unreadCount: Box(FoldersSortProperty.alphabetical, SortBoxOrder.ascending), Box(FoldersSortProperty.unreadCount, SortBoxOrder.descending),
},
FoldersSortProperty.unreadCount: {
Box(FoldersSortProperty.alphabetical, SortBoxOrder.ascending),
},
}, },
); );

4
packages/neon/neon_notes/lib/sort/categories.dart

@ -6,7 +6,9 @@ final categoriesSortBox = SortBox<CategoriesSortProperty, NoteCategory>(
CategoriesSortProperty.notesCount: (final category) => category.count, CategoriesSortProperty.notesCount: (final category) => category.count,
}, },
{ {
CategoriesSortProperty.notesCount: Box(CategoriesSortProperty.alphabetical, SortBoxOrder.ascending), CategoriesSortProperty.notesCount: {
Box(CategoriesSortProperty.alphabetical, SortBoxOrder.ascending),
},
}, },
); );

4
packages/neon/neon_notes/lib/sort/notes.dart

@ -6,6 +6,8 @@ final notesSortBox = SortBox<NotesSortProperty, NotesNote>(
NotesSortProperty.lastModified: (final note) => note.modified, NotesSortProperty.lastModified: (final note) => note.modified,
}, },
{ {
NotesSortProperty.alphabetical: Box(NotesSortProperty.lastModified, SortBoxOrder.descending), NotesSortProperty.alphabetical: {
Box(NotesSortProperty.lastModified, SortBoxOrder.descending),
},
}, },
); );

42
packages/sort_box/lib/sort_box.dart

@ -5,40 +5,42 @@ typedef ComparableGetter<T> = Comparable Function(T);
class SortBox<T extends Enum, R> { class SortBox<T extends Enum, R> {
SortBox( SortBox(
this._properties, this._properties,
this._secondaryBoxes, this._boxes,
); );
final Map<T, ComparableGetter<R>> _properties; final Map<T, ComparableGetter<R>> _properties;
final Map<T, Box<T>> _secondaryBoxes; final Map<T, Set<Box<T>>> _boxes;
List<R> sort(final List<R> input, final Box<T> box) { List<R> sort(final List<R> input, final Box<T> box) {
if (input.length <= 1) { if (input.length <= 1) {
return input; return input;
} }
final comparableGetter = _properties[box.property]!; final sorted = input
final secondaryBox = _secondaryBoxes[box.property]; ..sort((final item1, final item2) => _compare(item1, item2, box, _boxes[box.property]?.iterator));
final comparableGetter2 = _properties[secondaryBox?.property];
return sorted;
}
return input int _compare(
..sort( final R item1,
(final item1, final item2) { final R item2,
final first = _compare(item1, item2, box.order, comparableGetter); final Box<T> box,
final Iterator<Box<T>>? iterator,
) {
final comparableGetter = _properties[box.property]!;
if (first == 0 && secondaryBox != null) { final comparable1 = comparableGetter(item1);
return _compare(item1, item2, secondaryBox.order, comparableGetter2!); final comparable2 = comparableGetter(item2);
}
return first; final order =
}, box.order == SortBoxOrder.ascending ? comparable1.compareTo(comparable2) : comparable2.compareTo(comparable1);
);
}
int _compare(final R item1, final R item2, final SortBoxOrder order, final ComparableGetter<R> getter) { if (order == 0 && iterator != null && iterator.moveNext()) {
final comparable1 = getter(item1); return _compare(item1, item2, iterator.current, iterator);
final comparable2 = getter(item2); }
return order == SortBoxOrder.ascending ? comparable1.compareTo(comparable2) : comparable2.compareTo(comparable1); return order;
} }
} }

100
packages/sort_box/test/sort_box_test.dart

@ -4,16 +4,19 @@ import 'package:test/test.dart';
enum FruitSort { enum FruitSort {
alphabetical, alphabetical,
count, count,
price,
} }
class Fruit { class Fruit {
Fruit( const Fruit(
this.name, this.name,
this.count, this.count, [
); this.price,
]);
final String name; final String name;
final int count; final int count;
final int? price;
@override @override
String toString() => 'Fruit(name: $name, count: $count)'; String toString() => 'Fruit(name: $name, count: $count)';
@ -24,21 +27,30 @@ void main() {
{ {
FruitSort.alphabetical: (final fruit) => fruit.name.toLowerCase(), FruitSort.alphabetical: (final fruit) => fruit.name.toLowerCase(),
FruitSort.count: (final fruit) => fruit.count, FruitSort.count: (final fruit) => fruit.count,
FruitSort.price: (final fruit) => fruit.price!,
}, },
{ {
FruitSort.alphabetical: Box(FruitSort.count, SortBoxOrder.ascending), FruitSort.alphabetical: {
FruitSort.count: Box(FruitSort.alphabetical, SortBoxOrder.ascending), Box(FruitSort.count, SortBoxOrder.ascending),
},
FruitSort.count: {
Box(FruitSort.alphabetical, SortBoxOrder.ascending),
},
FruitSort.price: {
Box(FruitSort.alphabetical, SortBoxOrder.descending),
Box(FruitSort.count, SortBoxOrder.ascending),
},
}, },
); );
group('Primary', () { group('Primary', () {
test('Alphabetical', () { test('Alphabetical', () {
final fruits = [ final fruits = [
Fruit('Apple', 1), const Fruit('Apple', 1),
Fruit('Banana', 2), const Fruit('Banana', 2),
Fruit('Apple', 3), const Fruit('Apple', 3),
Fruit('Banana', 4), const Fruit('Banana', 4),
Fruit('Apple', 5), const Fruit('Apple', 5),
]; ];
final sorted = sortBox.sort(fruits, Box(FruitSort.alphabetical, SortBoxOrder.ascending)); final sorted = sortBox.sort(fruits, Box(FruitSort.alphabetical, SortBoxOrder.ascending));
@ -52,11 +64,11 @@ void main() {
test('Count', () { test('Count', () {
final fruits = [ final fruits = [
Fruit('Apple', 1), const Fruit('Apple', 1),
Fruit('Banana', 5), const Fruit('Banana', 5),
Fruit('Apple', 4), const Fruit('Apple', 4),
Fruit('Banana', 2), const Fruit('Banana', 2),
Fruit('Apple', 3), const Fruit('Apple', 3),
]; ];
final sorted = sortBox.sort(fruits, Box(FruitSort.count, SortBoxOrder.ascending)); final sorted = sortBox.sort(fruits, Box(FruitSort.count, SortBoxOrder.ascending));
@ -73,11 +85,11 @@ void main() {
group('Secondary', () { group('Secondary', () {
test('Alphabetical', () { test('Alphabetical', () {
final fruits = [ final fruits = [
Fruit('Apple', 1), const Fruit('Apple', 1),
Fruit('Banana', 2), const Fruit('Banana', 2),
Fruit('Apple', 2), const Fruit('Apple', 2),
Fruit('Banana', 1), const Fruit('Banana', 1),
Fruit('Apple', 2), const Fruit('Apple', 2),
]; ];
final sorted = sortBox.sort(fruits, Box(FruitSort.count, SortBoxOrder.ascending)); final sorted = sortBox.sort(fruits, Box(FruitSort.count, SortBoxOrder.ascending));
@ -94,11 +106,11 @@ void main() {
test('Count', () { test('Count', () {
final fruits = [ final fruits = [
Fruit('Apple', 3), const Fruit('Apple', 3),
Fruit('Banana', 4), const Fruit('Banana', 4),
Fruit('Apple', 1), const Fruit('Apple', 1),
Fruit('Banana', 2), const Fruit('Banana', 2),
Fruit('Apple', 5), const Fruit('Apple', 5),
]; ];
final sorted = sortBox.sort(fruits, Box(FruitSort.alphabetical, SortBoxOrder.ascending)); final sorted = sortBox.sort(fruits, Box(FruitSort.alphabetical, SortBoxOrder.ascending));
@ -116,11 +128,11 @@ void main() {
test('Primary all equal', () { test('Primary all equal', () {
final fruits = [ final fruits = [
Fruit('Coconut', 1), const Fruit('Coconut', 1),
Fruit('Banana', 1), const Fruit('Banana', 1),
Fruit('Apple', 1), const Fruit('Apple', 1),
Fruit('Elderberry', 1), const Fruit('Elderberry', 1),
Fruit('Damson', 1), const Fruit('Damson', 1),
]; ];
final sorted = sortBox.sort(fruits, Box(FruitSort.count, SortBoxOrder.ascending)); final sorted = sortBox.sort(fruits, Box(FruitSort.count, SortBoxOrder.ascending));
@ -130,4 +142,32 @@ void main() {
} }
}); });
}); });
group('Third', () {
test('Count', () {
final fruits = [
const Fruit('Apple', 1, 3),
const Fruit('Banana', 2, 2),
const Fruit('Apple', 2, 0),
const Fruit('Banana', 1, 3),
const Fruit('Apple', 2, 3),
];
final sorted = sortBox.sort(fruits, Box(FruitSort.price, SortBoxOrder.ascending));
final price = [0, 2, 3, 3, 3];
for (var i = 0; i < 5; i++) {
expect(sorted[i].price, price[i]);
}
final names = ['Apple', 'Banana', 'Banana', 'Apple', 'Apple'];
for (var i = 0; i < 5; i++) {
expect(sorted[i].name, names[i]);
}
final counts = [2, 2, 1, 1, 2];
for (var i = 0; i < 5; i++) {
expect(sorted[i].count, counts[i]);
}
});
});
} }

Loading…
Cancel
Save