LCOV - code coverage report
Current view: top level - src - reorderable.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 26 28 92.9 %
Date: 2023-05-22 12:02:26 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:math';
       2             : 
       3             : import 'package:event_db/event_db.dart';
       4             : import 'package:tuple/tuple.dart';
       5             : 
       6             : /// A [GenericModel] that has an [ordinal] parameter. When used with a
       7             : /// [ReorderableMap], by default greater ordinal values should be shown first.
       8             : ///
       9             : /// This is to make it convenient to add a custom sort feature.
      10             : mixin OrdereableModel on GenericModel {
      11             :   /// Compared with other instances of [OrdereableModel] to set the custom sort.
      12             :   int get ordinal;
      13             :   set ordinal(int value);
      14             : 
      15             :   /// Add this to your implementation of the
      16             :   /// [getGetterSetterMap] function of [GenericModel]
      17           0 :   Tuple2<Getter<dynamic>, Setter<dynamic>> get ordinalGetterSetter =>
      18           4 :       Tuple2(() => ordinal, (val) => ordinal = val as int? ?? 0);
      19             : }
      20             : 
      21             : /// Records a movement of an [OrdereableModel].
      22             : class ListMovement<T extends OrdereableModel> {
      23             :   /// Records a movement of an [OrdereableModel]
      24           0 :   ListMovement(this.moved, this.to);
      25             : 
      26             :   /// The [OrdereableModel] that was moved.
      27             :   final T moved;
      28             : 
      29             :   /// The location in the list that [moved] was moved to.
      30             :   final int to;
      31             : }
      32             : 
      33             : /// Adds functions to [GenericModelMap] specifically for [OrdereableModel]
      34             : ///
      35             : /// This is to make it more convenient to work with [OrdereableModel]s
      36             : extension ReorderableMap<T extends OrdereableModel> on GenericModelMap<T> {
      37             :   /// Automatically sets the ordinal of the given [model] based on the existing
      38             :   /// models in [map]
      39           1 :   T setOrdinalOfNewEntry(T model) {
      40           4 :     return model..ordinal = map.entries.length;
      41             :   }
      42             : 
      43             :   /// Returns a [List] of keys sorted based on the ordinal value of the
      44             :   /// [OrdereableModel]s in [map]
      45           4 :   List<String> get defaultOrderedKeyList => map.keys.toList()
      46           9 :     ..sort((a, b) => map[b]!.ordinal.compareTo(map[a]!.ordinal));
      47             : 
      48             :   /// Returns a [List] of [T] sorted based on the ordinal value of the
      49             :   /// [OrdereableModel]s in [map]
      50           1 :   List<T> get defaultOrderedList =>
      51           8 :       map.values.toList()..sort((a, b) => b.ordinal.compareTo(a.ordinal));
      52             : 
      53             :   /// Reorders the [model] to have the [newOrdinal] value for ordinal
      54             :   ///
      55             :   /// This will automatically change the ordinal value for the other [T] in
      56             :   /// [map]. This will also automatically update [repository]
      57           1 :   Future<Iterable<T>> reorder(
      58             :     T model,
      59             :     int newOrdinal, {
      60             :     String? databaseName,
      61             :   }) async {
      62           1 :     final list = defaultOrderedKeyList;
      63             : 
      64           2 :     final checkedOrdinal = min(newOrdinal, list.length);
      65           2 :     final initialOrdinal = list.indexOf(model.id!);
      66             : 
      67           1 :     if (checkedOrdinal == initialOrdinal) {
      68           1 :       return [];
      69             :     }
      70             : 
      71             :     final updatedModels = <T>{};
      72             : 
      73           3 :     for (var i = 0; i < list.length; i++) {
      74           1 :       final pastOldIndex = i >= initialOrdinal;
      75           1 :       final pastNewIndex = i >= checkedOrdinal;
      76             : 
      77             :       if (!pastOldIndex && !pastNewIndex) {
      78             :         continue;
      79             :       }
      80             :       if (pastNewIndex && pastOldIndex) {
      81             :         break;
      82             :       }
      83           3 :       final updatedModel = map[list[i]]!;
      84           1 :       updatedModels.add(updatedModel);
      85             :       if (pastNewIndex) {
      86           4 :         updatedModel.ordinal = list.length - i - 2;
      87             :       }
      88             :       if (pastOldIndex) {
      89           3 :         updatedModel.ordinal = list.length - i;
      90             :       }
      91             :     }
      92           1 :     updatedModels.add(model);
      93           3 :     model.ordinal = list.length -
      94           1 :         checkedOrdinal -
      95           1 :         (checkedOrdinal > initialOrdinal ? 0 : 1);
      96             : 
      97           1 :     return Future.wait(
      98           3 :       updatedModels.map((e) => updateModel(e, databaseName: databaseName)),
      99             :     );
     100             :   }
     101             : }

Generated by: LCOV version 1.14