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.modifiedDate: Box(FilesSortProperty.name, SortBoxOrder.ascending),
FilesSortProperty.size: Box(FilesSortProperty.name, SortBoxOrder.ascending),
FilesSortProperty.modifiedDate: {
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.alphabetical: Box(ArticlesSortProperty.publishDate, SortBoxOrder.descending),
ArticlesSortProperty.byFeed: Box(ArticlesSortProperty.alphabetical, SortBoxOrder.ascending),
ArticlesSortProperty.alphabetical: {
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.alphabetical: Box(FeedsSortProperty.unreadCount, SortBoxOrder.descending),
FeedsSortProperty.unreadCount: Box(FeedsSortProperty.alphabetical, SortBoxOrder.ascending),
FeedsSortProperty.alphabetical: {
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.alphabetical: Box(FoldersSortProperty.unreadCount, SortBoxOrder.descending),
FoldersSortProperty.unreadCount: Box(FoldersSortProperty.alphabetical, SortBoxOrder.ascending),
FoldersSortProperty.alphabetical: {
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: 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.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> {
SortBox(
this._properties,
this._secondaryBoxes,
this._boxes,
);
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) {
if (input.length <= 1) {
return input;
}
final comparableGetter = _properties[box.property]!;
final secondaryBox = _secondaryBoxes[box.property];
final comparableGetter2 = _properties[secondaryBox?.property];
final sorted = input
..sort((final item1, final item2) => _compare(item1, item2, box, _boxes[box.property]?.iterator));
return sorted;
}
return input
..sort(
(final item1, final item2) {
final first = _compare(item1, item2, box.order, comparableGetter);
int _compare(
final R item1,
final R item2,
final Box<T> box,
final Iterator<Box<T>>? iterator,
) {
final comparableGetter = _properties[box.property]!;
if (first == 0 && secondaryBox != null) {
return _compare(item1, item2, secondaryBox.order, comparableGetter2!);
}
final comparable1 = comparableGetter(item1);
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) {
final comparable1 = getter(item1);
final comparable2 = getter(item2);
if (order == 0 && iterator != null && iterator.moveNext()) {
return _compare(item1, item2, iterator.current, iterator);
}
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 {
alphabetical,
count,
price,
}
class Fruit {
Fruit(
const Fruit(
this.name,
this.count,
);
this.count, [
this.price,
]);
final String name;
final int count;
final int? price;
@override
String toString() => 'Fruit(name: $name, count: $count)';
@ -24,21 +27,30 @@ void main() {
{
FruitSort.alphabetical: (final fruit) => fruit.name.toLowerCase(),
FruitSort.count: (final fruit) => fruit.count,
FruitSort.price: (final fruit) => fruit.price!,
},
{
FruitSort.alphabetical: Box(FruitSort.count, SortBoxOrder.ascending),
FruitSort.count: Box(FruitSort.alphabetical, SortBoxOrder.ascending),
FruitSort.alphabetical: {
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', () {
test('Alphabetical', () {
final fruits = [
Fruit('Apple', 1),
Fruit('Banana', 2),
Fruit('Apple', 3),
Fruit('Banana', 4),
Fruit('Apple', 5),
const Fruit('Apple', 1),
const Fruit('Banana', 2),
const Fruit('Apple', 3),
const Fruit('Banana', 4),
const Fruit('Apple', 5),
];
final sorted = sortBox.sort(fruits, Box(FruitSort.alphabetical, SortBoxOrder.ascending));
@ -52,11 +64,11 @@ void main() {
test('Count', () {
final fruits = [
Fruit('Apple', 1),
Fruit('Banana', 5),
Fruit('Apple', 4),
Fruit('Banana', 2),
Fruit('Apple', 3),
const Fruit('Apple', 1),
const Fruit('Banana', 5),
const Fruit('Apple', 4),
const Fruit('Banana', 2),
const Fruit('Apple', 3),
];
final sorted = sortBox.sort(fruits, Box(FruitSort.count, SortBoxOrder.ascending));
@ -73,11 +85,11 @@ void main() {
group('Secondary', () {
test('Alphabetical', () {
final fruits = [
Fruit('Apple', 1),
Fruit('Banana', 2),
Fruit('Apple', 2),
Fruit('Banana', 1),
Fruit('Apple', 2),
const Fruit('Apple', 1),
const Fruit('Banana', 2),
const Fruit('Apple', 2),
const Fruit('Banana', 1),
const Fruit('Apple', 2),
];
final sorted = sortBox.sort(fruits, Box(FruitSort.count, SortBoxOrder.ascending));
@ -94,11 +106,11 @@ void main() {
test('Count', () {
final fruits = [
Fruit('Apple', 3),
Fruit('Banana', 4),
Fruit('Apple', 1),
Fruit('Banana', 2),
Fruit('Apple', 5),
const Fruit('Apple', 3),
const Fruit('Banana', 4),
const Fruit('Apple', 1),
const Fruit('Banana', 2),
const Fruit('Apple', 5),
];
final sorted = sortBox.sort(fruits, Box(FruitSort.alphabetical, SortBoxOrder.ascending));
@ -116,11 +128,11 @@ void main() {
test('Primary all equal', () {
final fruits = [
Fruit('Coconut', 1),
Fruit('Banana', 1),
Fruit('Apple', 1),
Fruit('Elderberry', 1),
Fruit('Damson', 1),
const Fruit('Coconut', 1),
const Fruit('Banana', 1),
const Fruit('Apple', 1),
const Fruit('Elderberry', 1),
const Fruit('Damson', 1),
];
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