mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
Sort files with directories first in SFTP
This commit is contained in:
83
lib/core/utils/comparator.dart
Normal file
83
lib/core/utils/comparator.dart
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
class ChainComparator<T> {
|
||||||
|
final ChainComparator<T>? _parent;
|
||||||
|
final Comparator<T> _comparator;
|
||||||
|
|
||||||
|
ChainComparator._create(this._parent, this._comparator);
|
||||||
|
ChainComparator.empty() : this._create(null, (a, b) => 0);
|
||||||
|
ChainComparator.create() : this._create(null, (a, b) => 0);
|
||||||
|
|
||||||
|
static ChainComparator<T> comparing<T, F extends Comparable<F>>(
|
||||||
|
F Function(T) extractor) {
|
||||||
|
return ChainComparator._create(
|
||||||
|
null, (a, b) => extractor(a).compareTo(extractor(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare(T a, T b) {
|
||||||
|
final parent = _parent;
|
||||||
|
if (parent != null) {
|
||||||
|
final int result = parent.compare(a, b);
|
||||||
|
if (result != 0) return result;
|
||||||
|
}
|
||||||
|
return _comparator(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
int call(T a, T b) {
|
||||||
|
return compare(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChainComparator<T> thenCompareBy<F extends Comparable<F>>(
|
||||||
|
F Function(T) extractor,
|
||||||
|
{bool reversed = false}) {
|
||||||
|
return ChainComparator._create(
|
||||||
|
this,
|
||||||
|
reversed
|
||||||
|
? (a, b) => extractor(b).compareTo(extractor(a))
|
||||||
|
: (a, b) => extractor(a).compareTo(extractor(b)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChainComparator<T> thenWithComparator(Comparator<T> comparator,
|
||||||
|
{bool reversed = false}) {
|
||||||
|
return ChainComparator._create(
|
||||||
|
this,
|
||||||
|
!reversed ? comparator : (a, b) => comparator(b, a),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChainComparator<T> thenCompareByReversed<F extends Comparable<F>>(
|
||||||
|
F Function(T) extractor) {
|
||||||
|
return ChainComparator._create(
|
||||||
|
this, (a, b) => -extractor(a).compareTo(extractor(b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ChainComparator<T> thenTrueFirst(bool Function(T) f) {
|
||||||
|
return ChainComparator._create(this, (a, b) {
|
||||||
|
final fa = f(a), fb = f(b);
|
||||||
|
return fa == fb ? 0 : (fa ? -1 : 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ChainComparator<T> reversed() {
|
||||||
|
return ChainComparator._create(null, (a, b) => this.compare(b, a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Comparators {
|
||||||
|
static Comparator<String> compareStringCaseInsensitive(
|
||||||
|
{bool uppercaseFirst = false}) {
|
||||||
|
return (String a, String b) {
|
||||||
|
final r = a.toLowerCase().compareTo(b.toLowerCase());
|
||||||
|
if (r != 0) return r;
|
||||||
|
return uppercaseFirst ? a.compareTo(b) : b.compareTo(a);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Comparator.comparing<Type1, Type2>(Type1::getType2)
|
||||||
|
.thenCompare<Type3>(Type1::getType3)
|
||||||
|
.thenCompare<Type4>(Type1::getType4)
|
||||||
|
.thenCompareReversed<Type5>(Type1::getType5)
|
||||||
|
|
||||||
|
*/
|
||||||
@@ -8,6 +8,7 @@ import 'package:toolbox/core/extension/context/dialog.dart';
|
|||||||
import 'package:toolbox/core/extension/context/locale.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/extension/sftpfile.dart';
|
import 'package:toolbox/core/extension/sftpfile.dart';
|
||||||
|
import 'package:toolbox/core/utils/comparator.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
import 'package:toolbox/data/res/logger.dart';
|
import 'package:toolbox/data/res/logger.dart';
|
||||||
import 'package:toolbox/data/res/misc.dart';
|
import 'package:toolbox/data/res/misc.dart';
|
||||||
@@ -800,15 +801,30 @@ enum _SortType {
|
|||||||
List<SftpName> sort(List<SftpName> files) {
|
List<SftpName> sort(List<SftpName> files) {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case _SortType.name:
|
case _SortType.name:
|
||||||
files.sort((a, b) => a.filename.compareTo(b.filename));
|
files.sort(
|
||||||
|
ChainComparator<SftpName>.create()
|
||||||
|
.thenTrueFirst((x) => x.attr.isDirectory)
|
||||||
|
.thenWithComparator((a, b) =>
|
||||||
|
Comparators.compareStringCaseInsensitive()(
|
||||||
|
a.filename, b.filename))
|
||||||
|
.compare,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case _SortType.time:
|
case _SortType.time:
|
||||||
files.sort(
|
files.sort(
|
||||||
(a, b) => (a.attr.modifyTime ?? 0).compareTo(b.attr.modifyTime ?? 0),
|
ChainComparator<SftpName>.create()
|
||||||
|
.thenTrueFirst((x) => x.attr.isDirectory)
|
||||||
|
.thenCompareBy<num>((x) => x.attr.modifyTime ?? 0)
|
||||||
|
.compare,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case _SortType.size:
|
case _SortType.size:
|
||||||
files.sort((a, b) => (a.attr.size ?? 0).compareTo(b.attr.size ?? 0));
|
files.sort(
|
||||||
|
ChainComparator<SftpName>.create()
|
||||||
|
.thenTrueFirst((x) => x.attr.isDirectory)
|
||||||
|
.thenCompareBy<num>((x) => x.attr.size ?? 0)
|
||||||
|
.compare,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return files;
|
return files;
|
||||||
|
|||||||
Reference in New Issue
Block a user