more refactors and logs page handling

This commit is contained in:
shenlong-tanwen
2024-10-23 02:30:46 +05:30
parent 8f47645cdb
commit a0afea04d8
90 changed files with 2386 additions and 584 deletions
+20 -22
View File
@@ -2,7 +2,7 @@
import 'dart:async';
class CollectionUtil {
abstract final class CollectionUtil {
const CollectionUtil();
static int compareToNullable<T extends Comparable>(T? a, T? b) {
@@ -18,22 +18,22 @@ class CollectionUtil {
/// Find the difference between the two lists [first] and [second]
/// Results are passed as callbacks back to the caller during the comparison
static FutureOr<bool> diffLists<T>(
List<T> first,
List<T> second, {
List<T> firstList,
List<T> secondList, {
required int Function(T a, T b) compare,
required FutureOr<bool> Function(T a, T b) both,
required FutureOr<void> Function(T a) onlyFirst,
required FutureOr<void> Function(T b) onlySecond,
}) async {
first.sort(compare);
first.uniqueConsecutive(compare);
second.sort(compare);
second.uniqueConsecutive(compare);
final first =
_uniqueConsecutive(List.of(firstList)..sort(compare), compare);
final second =
_uniqueConsecutive(List.of(secondList)..sort(compare), compare);
bool diff = false;
int i = 0, j = 0;
for (; i < first.length && j < second.length;) {
while (i < first.length && j < second.length) {
final int order = compare(first[i], second[j]);
if (order == 0) {
diff |= await both(first[i++], second[j++]);
@@ -49,27 +49,25 @@ class CollectionUtil {
diff |= i < first.length || j < second.length;
for (; i < first.length; i++) {
onlyFirst(first[i]);
await onlyFirst(first[i]);
}
for (; j < second.length; j++) {
onlySecond(second[j]);
await onlySecond(second[j]);
}
return diff;
}
}
extension _ListExtension<T> on List<T> {
List<T> uniqueConsecutive(int Function(T a, T b) compare) {
int i = 1, j = 1;
for (; i < length; i++) {
if (compare(this[i - 1], this[i]) != 0) {
if (i != j) {
this[j] = this[i];
}
j++;
}
List<T> _uniqueConsecutive<T>(List<T> list, int Function(T a, T b) compare) {
if (list.isEmpty) return list;
List<T> unique = [];
unique.add(list.first);
for (int i = 1; i < list.length; i++) {
if (compare(list[i], list[i - 1]) != 0) {
unique.add(list[i]);
}
length = length == 0 ? 0 : j;
return this;
}
return unique;
}
@@ -1,17 +1,23 @@
import 'package:flutter/material.dart';
@immutable
class SizeConstants {
abstract final class SizeConstants {
const SizeConstants._();
static const s = 8.0;
static const m = 16.0;
static const xm = 25.0;
static const l = 32.0;
static const xl = 64.0;
}
class BodyRatioConstants {
const BodyRatioConstants._();
abstract final class RatioConstants {
const RatioConstants._();
// 0.3
static const oneThird = 1 / 3;
// 0.25
static const quarter = 1 / 4;
// 0.15
static const halfQuarter = 3 / 20;
}
@@ -1,4 +1,4 @@
extension SortIterable<T> on Iterable<T> {
Iterable<T> sortedBy(Comparable Function(T k) key) =>
toList()..sort((a, b) => key(a).compareTo(key(b)));
List.of(this)..sort((a, b) => key(a).compareTo(key(b)));
}
+5 -5
View File
@@ -66,9 +66,9 @@ class ImApiClient extends ApiClient with LogMixin {
return res;
}
UsersApi getUsersApi() => UsersApi(this);
ServerApi getServerApi() => ServerApi(this);
AuthenticationApi getAuthenticationApi() => AuthenticationApi(this);
OAuthApi getOAuthApi() => OAuthApi(this);
SyncApi getSyncApi() => SyncApi(this);
UsersApi get usersApi => UsersApi(this);
ServerApi get serverApi => ServerApi(this);
AuthenticationApi get authenticationApi => AuthenticationApi(this);
OAuthApi get oAuthApi => OAuthApi(this);
SyncApi get syncApi => SyncApi(this);
}
@@ -1,4 +1,5 @@
import 'package:immich_mobile/domain/models/asset.model.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/service_locator.dart';
import 'package:immich_mobile/utils/immich_api_client.dart';
@@ -11,11 +12,15 @@ enum AssetMediaSize {
final String value;
}
class ImImageUrlHelper {
abstract final class ImImageUrlHelper {
const ImImageUrlHelper();
static String get _serverUrl => di<ImApiClient>().basePath;
static String getUserAvatarUrl(final User user) {
return '$_serverUrl/users/${user.id}/profile-image';
}
static String getThumbnailUrl(
final Asset asset, {
AssetMediaSize type = AssetMediaSize.thumbnail,
+4 -4
View File
@@ -40,7 +40,7 @@ class IsolateHelper {
);
}
void postIsolateHandling() {
Future<void> postIsolateHandling() async {
assert(_clientData != null);
// Reconstruct client from cached data
final client = ImApiClient(endpoint: _clientData!.endpoint);
@@ -55,7 +55,7 @@ class IsolateHelper {
);
// Init log manager to continue listening to log events
LogManager.I.init(shouldBuffer: false);
await LogManager.I.init(shouldBuffer: false);
}
static Future<T> run<T>(FutureOr<T> Function() computation) async {
@@ -70,10 +70,10 @@ class IsolateHelper {
DartPluginRegistrant.ensureInitialized();
// Delay to ensure the isolate is ready
await Future.delayed(Durations.short2);
helper.postIsolateHandling();
await helper.postIsolateHandling();
try {
final result = await computation();
// Delay to ensure the isolate is not killed prematurely
// Wait for isolate to end; i.e, logs to be flushed
await Future.delayed(Durations.short2);
return result;
} finally {
+11 -7
View File
@@ -1,3 +1,5 @@
// ignore_for_file: avoid-collection-mutating-methods
import 'dart:async';
import 'package:flutter/foundation.dart';
@@ -13,6 +15,7 @@ import 'package:logging/logging.dart' as logging;
/// in the class.
class LogManager {
LogManager._();
static final LogManager _instance = LogManager._();
static final Map<String, Logger> _loggers = <String, Logger>{};
@@ -40,10 +43,10 @@ class LogManager {
}());
final lm = LogMessage(
logger: record.loggerName,
content: record.message,
level: record.level.toLogLevel(),
createdAt: record.time,
logger: record.loggerName,
error: record.error?.toString(),
stack: record.stackTrace?.toString(),
);
@@ -53,7 +56,7 @@ class LogManager {
_timer ??=
Timer(const Duration(seconds: 5), () => _flushBufferToDatabase());
} else {
di<ILogRepository>().create(lm);
unawaited(di<ILogRepository>().create(lm));
}
}
@@ -61,12 +64,13 @@ class LogManager {
_timer = null;
final buffer = _msgBuffer;
_msgBuffer = [];
di<ILogRepository>().createAll(buffer);
unawaited(di<ILogRepository>().createAll(buffer));
}
void init({bool? shouldBuffer}) {
Future<void> init({bool? shouldBuffer}) async {
_shouldBuffer = shouldBuffer ?? _shouldBuffer;
_subscription = logging.Logger.root.onRecord.listen(_onLogRecord);
await di<ILogRepository>().truncate();
}
Logger get(String? loggerName) => _loggers.putIfAbsent(
@@ -80,14 +84,14 @@ class LogManager {
}
void dispose() {
_subscription.cancel();
unawaited(_subscription.cancel());
}
void clearLogs() {
Future<void> clearLogs() async {
_timer?.cancel();
_timer = null;
_msgBuffer.clear();
di<ILogRepository>().deleteAll();
await di<ILogRepository>().deleteAll();
}
static void setGlobalErrorCallbacks() {
+2 -2
View File
@@ -35,10 +35,10 @@ dynamic upgradeDto(dynamic value, String targetType) {
}
}
addDefault(dynamic value, String keys, dynamic defaultValue) {
addDefault(Map value, String keys, dynamic defaultValue) {
// Loop through the keys and assign the default value if the key is not present
List<String> keyList = keys.split('.');
dynamic current = value;
Map current = value;
for (int i = 0; i < keyList.length - 1; i++) {
if (current[keyList[i]] == null) {
+1 -1
View File
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:immich_mobile/utils/constants/globals.dart';
class SnackbarManager {
abstract final class SnackbarManager {
const SnackbarManager();
static ScaffoldMessengerState? get _s => kScafMessengerKey.currentState;