feat: home grid
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
extension ExpandQuery<T> on Selectable<T> {
|
||||
/// Expands this selectable by the [expand] function.
|
||||
///
|
||||
/// Each entry emitted by this [Selectable] will be transformed by the
|
||||
/// [expander] and then emitted to the selectable returned.
|
||||
Selectable<N> expand<N>(Iterable<N> Function(T) expander) {
|
||||
return _ExpandedSelectable<T, N>(this, expander);
|
||||
}
|
||||
}
|
||||
|
||||
class _ExpandedSelectable<S, T> extends Selectable<T> {
|
||||
final Selectable<S> _source;
|
||||
final Iterable<T> Function(S) expander;
|
||||
|
||||
_ExpandedSelectable(this._source, this.expander);
|
||||
|
||||
@override
|
||||
Future<List<T>> get() {
|
||||
return _source.get().then(_mapResults);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<List<T>> watch() {
|
||||
return _source.watch().map(_mapResults);
|
||||
}
|
||||
|
||||
List<T> _mapResults(List<S> results) => results.expand<T>(expander).toList();
|
||||
}
|
||||
@@ -13,19 +13,21 @@ import 'package:immich_mobile/utils/mixins/log_context.mixin.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
@immutable
|
||||
class ImmichApiClientData {
|
||||
class ImApiClientData {
|
||||
final String endpoint;
|
||||
final Map<String, String> headersMap;
|
||||
|
||||
const ImmichApiClientData({required this.endpoint, required this.headersMap});
|
||||
const ImApiClientData({required this.endpoint, required this.headersMap});
|
||||
}
|
||||
|
||||
class ImmichApiClient extends ApiClient with LogContext {
|
||||
ImmichApiClient({required String endpoint}) : super(basePath: endpoint);
|
||||
|
||||
/// Used to recreate the client in Isolates
|
||||
ImmichApiClientData get clientData =>
|
||||
ImmichApiClientData(endpoint: basePath, headersMap: defaultHeaderMap);
|
||||
ImApiClientData get clientData =>
|
||||
ImApiClientData(endpoint: basePath, headersMap: defaultHeaderMap);
|
||||
|
||||
Map<String, String> get headers => defaultHeaderMap;
|
||||
|
||||
Future<void> init({String? accessToken}) async {
|
||||
final token =
|
||||
@@ -47,7 +49,7 @@ class ImmichApiClient extends ApiClient with LogContext {
|
||||
addDefaultHeader(kImmichHeaderDeviceType, Platform.operatingSystem);
|
||||
}
|
||||
|
||||
factory ImmichApiClient.clientData(ImmichApiClientData data) {
|
||||
factory ImmichApiClient.clientData(ImApiClientData data) {
|
||||
final client = ImmichApiClient(endpoint: data.endpoint);
|
||||
|
||||
for (final entry in data.headersMap.entries) {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import 'package:immich_mobile/domain/models/asset.model.dart';
|
||||
import 'package:immich_mobile/service_locator.dart';
|
||||
import 'package:immich_mobile/utils/immich_api_client.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
class ImImageUrlHelper {
|
||||
const ImImageUrlHelper();
|
||||
|
||||
static String get _serverUrl => di<ImmichApiClient>().basePath;
|
||||
|
||||
static String getThumbnailUrl(
|
||||
final Asset asset, {
|
||||
AssetMediaSize type = AssetMediaSize.thumbnail,
|
||||
}) {
|
||||
return _getThumbnailUrlForRemoteId(asset.remoteId!, type: type);
|
||||
}
|
||||
|
||||
static String getThumbnailCacheKey(
|
||||
final Asset asset, {
|
||||
AssetMediaSize type = AssetMediaSize.thumbnail,
|
||||
}) {
|
||||
return _getThumbnailCacheKeyForRemoteId(asset.remoteId!, type: type);
|
||||
}
|
||||
|
||||
static String _getThumbnailCacheKeyForRemoteId(
|
||||
final String id, {
|
||||
AssetMediaSize type = AssetMediaSize.thumbnail,
|
||||
}) {
|
||||
if (type == AssetMediaSize.thumbnail) {
|
||||
return 'thumbnail-image-$id';
|
||||
}
|
||||
return 'preview-image-$id';
|
||||
}
|
||||
|
||||
static String _getThumbnailUrlForRemoteId(
|
||||
final String id, {
|
||||
AssetMediaSize type = AssetMediaSize.thumbnail,
|
||||
}) {
|
||||
return '$_serverUrl/assets/$id/thumbnail?size=${type.value}';
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,6 @@ import 'package:immich_mobile/domain/interfaces/log.interface.dart';
|
||||
import 'package:immich_mobile/domain/models/log.model.dart';
|
||||
import 'package:immich_mobile/service_locator.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:stack_trace/stack_trace.dart' as stack_trace;
|
||||
|
||||
/// [LogManager] is a custom logger that is built on top of the [logging] package.
|
||||
/// The logs are written to the database and onto console, using `debugPrint` method.
|
||||
@@ -29,7 +27,7 @@ class LogManager {
|
||||
debugPrint('[${record.level.name}] [${record.time}] ${record.message}');
|
||||
if (record.error != null && record.stackTrace != null) {
|
||||
debugPrint('${record.error}');
|
||||
debugPrintStack(stackTrace: record.stackTrace);
|
||||
debugPrint('${record.stackTrace}');
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
@@ -76,12 +74,6 @@ class LogManager {
|
||||
}
|
||||
|
||||
static void setGlobalErrorCallbacks() {
|
||||
FlutterError.demangleStackTrace = (StackTrace stack) {
|
||||
if (stack is stack_trace.Trace) return stack.vmTrace;
|
||||
if (stack is stack_trace.Chain) return stack.toTrace().vmTrace;
|
||||
return stack;
|
||||
};
|
||||
|
||||
FlutterError.onError = (details) {
|
||||
Logger("FlutterError").severe(
|
||||
'Unknown framework error occured in library ${details.library ?? "<unknown>"} at node ${details.context ?? "<unkown>"}',
|
||||
|
||||
Reference in New Issue
Block a user