more refactors and logs page handling
This commit is contained in:
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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,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;
|
||||
|
||||
Reference in New Issue
Block a user