Pārlūkot izejas kodu

dev(mobile): Fix freeze bug on app start (#1732)

* Group by date objects instead of strings

* Change OpenAPI code generation to wrap json decoding in
Change OpenAPI code generation to wrap decodeJson in compute

* Remove orig file

* Fix linter error

* Change drag handle date format

* Order timeline explictly from new to old

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
Matthias Rupp 2 gadi atpakaļ
vecāks
revīzija
6b3892987a

+ 13 - 11
mobile/lib/modules/home/ui/asset_grid/asset_grid_data_structure.dart

@@ -75,22 +75,23 @@ class RenderList {
 
   RenderList(this.elements);
 
-  static Map<String, List<Asset>> _groupAssets(
+  static Map<DateTime, List<Asset>> _groupAssets(
     List<Asset> assets,
     GroupAssetsBy groupBy,
   ) {
-    assets.sortByCompare<DateTime>(
-      (e) => e.createdAt,
-      (a, b) => b.compareTo(a),
-    );
-
     if (groupBy == GroupAssetsBy.day) {
       return assets.groupListsBy(
-        (element) => DateFormat('y-MM-dd').format(element.createdAt.toLocal()),
+        (element) {
+          final date = element.createdAt.toLocal();
+          return DateTime(date.year, date.month, date.day);
+        },
       );
     } else if (groupBy == GroupAssetsBy.month) {
       return assets.groupListsBy(
-        (element) => DateFormat('y-MM').format(element.createdAt.toLocal()),
+        (element) {
+          final date = element.createdAt.toLocal();
+          return DateTime(date.year, date.month);
+        },
       );
     }
 
@@ -113,10 +114,11 @@ class RenderList {
 
     final groups = _groupAssets(allAssets, groupBy);
 
-    groups.forEach((groupName, assets) {
-      try {
-        final date = assets.first.createdAt.toLocal();
+    groups.entries.sortedBy((e) =>e.key).reversed.forEach((entry) {
+      final date = entry.key;
+      final assets = entry.value;
 
+      try {
         // Month title
         if (groupBy == GroupAssetsBy.day &&
             (lastDate == null || lastDate!.month != date.month)) {

+ 1 - 1
mobile/lib/modules/home/ui/asset_grid/immich_asset_grid.dart

@@ -163,7 +163,7 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
   Text _labelBuilder(int pos) {
     final date = widget.renderList.elements[pos].date;
     return Text(
-      DateFormat.yMMMd().format(date),
+      DateFormat.yMMMM().format(date),
       style: const TextStyle(
         color: Colors.white,
         fontWeight: FontWeight.bold,

+ 1 - 1
mobile/openapi/README.md

@@ -3,7 +3,7 @@ Immich API
 
 This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
 
-- API version: 1.45.0
+- API version: 1.46.1
 - Build package: org.openapitools.codegen.languages.DartClientCodegen
 
 ## Requirements

+ 1 - 0
mobile/openapi/lib/api.dart

@@ -14,6 +14,7 @@ import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:flutter/foundation.dart';
 import 'package:http/http.dart';
 import 'package:intl/intl.dart';
 import 'package:meta/meta.dart';

+ 3 - 3
mobile/openapi/lib/api_client.dart

@@ -144,19 +144,19 @@ class ApiClient {
     );
   }
 
-  Future<dynamic> deserializeAsync(String json, String targetType, {bool growable = false,}) async =>
+  Future<dynamic> deserializeAsync(String json, String targetType, {bool growable = false,}) =>
     // ignore: deprecated_member_use_from_same_package
     deserialize(json, targetType, growable: growable);
 
   @Deprecated('Scheduled for removal in OpenAPI Generator 6.x. Use deserializeAsync() instead.')
-  dynamic deserialize(String json, String targetType, {bool growable = false,}) {
+  Future<dynamic> deserialize(String json, String targetType, {bool growable = false,}) async {
     // Remove all spaces. Necessary for regular expressions as well.
     targetType = targetType.replaceAll(' ', ''); // ignore: parameter_assignments
 
     // If the expected target type is String, nothing to do...
     return targetType == 'String'
       ? json
-      : _deserialize(jsonDecode(json), targetType, growable: growable);
+      : _deserialize(await compute((String j) => jsonDecode(j), json), targetType, growable: growable);
   }
 
   // ignore: deprecated_member_use_from_same_package

+ 5 - 1
server/bin/generate-open-api.sh

@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 function mobile {
   rm -rf ../mobile/openapi
@@ -7,6 +7,10 @@ function mobile {
   patch -u native_class.mustache <native_class.mustache.patch
   cd ../../../..
   npx openapi-generator-cli generate -g dart -i ./immich-openapi-specs.json -o ../mobile/openapi -t ./openapi-generator/templates
+
+  # Post generate patches
+  patch --no-backup-if-mismatch -u ../mobile/openapi/lib/api_client.dart <./openapi-generator/patch/api_client.dart.patch
+  patch --no-backup-if-mismatch -u ../mobile/openapi/lib/api.dart <./openapi-generator/patch/api.dart.patch
 }
 
 function web {

+ 8 - 0
server/openapi-generator/patch/api.dart.patch

@@ -0,0 +1,8 @@
+@@ -14,6 +14,7 @@ import 'dart:async';
+ import 'dart:convert';
+ import 'dart:io';
+
++import 'package:flutter/foundation.dart';
+ import 'package:http/http.dart';
+ import 'package:intl/intl.dart';
+ import 'package:meta/meta.dart';

+ 21 - 0
server/openapi-generator/patch/api_client.dart.patch

@@ -0,0 +1,21 @@
+@@ -144,19 +144,19 @@ class ApiClient {
+     );
+   }
+
+-  Future<dynamic> deserializeAsync(String json, String targetType, {bool growable = false,}) async =>
++  Future<dynamic> deserializeAsync(String json, String targetType, {bool growable = false,}) =>
+     // ignore: deprecated_member_use_from_same_package
+     deserialize(json, targetType, growable: growable);
+
+   @Deprecated('Scheduled for removal in OpenAPI Generator 6.x. Use deserializeAsync() instead.')
+-  dynamic deserialize(String json, String targetType, {bool growable = false,}) {
++  Future<dynamic> deserialize(String json, String targetType, {bool growable = false,}) async {
+     // Remove all spaces. Necessary for regular expressions as well.
+     targetType = targetType.replaceAll(' ', ''); // ignore: parameter_assignments
+
+     // If the expected target type is String, nothing to do...
+     return targetType == 'String'
+       ? json
+-      : _deserialize(jsonDecode(json), targetType, growable: growable);
++      : _deserialize(await compute((String j) => jsonDecode(j), json), targetType, growable: growable);
+   }

+ 1 - 1
web/src/api/open-api/api.ts

@@ -4,7 +4,7 @@
  * Immich
  * Immich API
  *
- * The version of the OpenAPI document: 1.45.0
+ * The version of the OpenAPI document: 1.46.1
  * 
  *
  * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

+ 1 - 1
web/src/api/open-api/base.ts

@@ -4,7 +4,7 @@
  * Immich
  * Immich API
  *
- * The version of the OpenAPI document: 1.45.0
+ * The version of the OpenAPI document: 1.46.1
  * 
  *
  * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

+ 1 - 1
web/src/api/open-api/common.ts

@@ -4,7 +4,7 @@
  * Immich
  * Immich API
  *
- * The version of the OpenAPI document: 1.45.0
+ * The version of the OpenAPI document: 1.46.1
  * 
  *
  * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

+ 1 - 1
web/src/api/open-api/configuration.ts

@@ -4,7 +4,7 @@
  * Immich
  * Immich API
  *
- * The version of the OpenAPI document: 1.45.0
+ * The version of the OpenAPI document: 1.46.1
  * 
  *
  * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

+ 1 - 1
web/src/api/open-api/index.ts

@@ -4,7 +4,7 @@
  * Immich
  * Immich API
  *
- * The version of the OpenAPI document: 1.45.0
+ * The version of the OpenAPI document: 1.46.1
  * 
  *
  * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).