chore: style grid

This commit is contained in:
shenlong-tanwen
2024-09-13 04:00:50 +05:30
parent 419d3669a2
commit 53974e7276
23 changed files with 344 additions and 127 deletions
@@ -1,5 +1,5 @@
import 'package:immich_mobile/domain/models/asset.model.dart';
import 'package:immich_mobile/domain/models/render_list.model.dart';
import 'package:immich_mobile/domain/services/render_list.service.dart';
abstract class IAssetRepository {
/// Batch insert asset
@@ -1,42 +1,70 @@
import 'package:intl/intl.dart';
enum RenderListGroupBy { month, day }
sealed class RenderListElement {
const RenderListElement();
const RenderListElement({required this.date});
final DateTime date;
@override
bool operator ==(covariant RenderListElement other) {
if (identical(this, other)) return true;
return date == other.date;
}
@override
int get hashCode => date.hashCode;
}
class RenderListMonthHeaderElement extends RenderListElement {
final String header;
late final String header;
const RenderListMonthHeaderElement({required this.header});
RenderListMonthHeaderElement({required super.date}) {
final formatter = DateTime.now().year == date.year
? DateFormat.MMMM()
: DateFormat.yMMMM();
header = formatter.format(date);
}
@override
bool operator ==(covariant RenderListMonthHeaderElement other) {
if (identical(this, other)) return true;
return super == other && header == other.header;
}
@override
int get hashCode => super.hashCode ^ date.hashCode;
}
class RenderListDayHeaderElement extends RenderListElement {
final String header;
const RenderListDayHeaderElement({required this.header});
const RenderListDayHeaderElement({required super.date, required this.header});
@override
bool operator ==(covariant RenderListDayHeaderElement other) {
if (identical(this, other)) return true;
return super == other && header == other.header;
}
@override
int get hashCode => super.hashCode ^ date.hashCode;
}
class RenderListAssetElement extends RenderListElement {
final DateTime date;
final int assetCount;
final int assetOffset;
const RenderListAssetElement({
required this.date,
required super.date,
required this.assetCount,
required this.assetOffset,
});
RenderListAssetElement copyWith({
DateTime? date,
int? assetCount,
int? assetOffset,
}) {
return RenderListAssetElement(
date: date ?? this.date,
assetCount: assetCount ?? this.assetCount,
assetOffset: assetOffset ?? this.assetOffset,
);
}
@override
String toString() =>
'RenderListAssetElement(date: $date, assetCount: $assetCount, assetOffset: $assetOffset)';
@@ -45,12 +73,12 @@ class RenderListAssetElement extends RenderListElement {
bool operator ==(covariant RenderListAssetElement other) {
if (identical(this, other)) return true;
return other.date == date &&
return super == other &&
other.assetCount == assetCount &&
other.assetOffset == assetOffset;
}
@override
int get hashCode =>
date.hashCode ^ assetCount.hashCode ^ assetOffset.hashCode;
super.hashCode ^ assetCount.hashCode ^ assetOffset.hashCode;
}
@@ -4,12 +4,11 @@ import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/entities/asset.entity.drift.dart';
import 'package:immich_mobile/domain/interfaces/asset.interface.dart';
import 'package:immich_mobile/domain/models/asset.model.dart';
import 'package:immich_mobile/domain/models/render_list.model.dart';
import 'package:immich_mobile/domain/models/render_list_element.model.dart';
import 'package:immich_mobile/domain/repositories/database.repository.dart';
import 'package:immich_mobile/domain/services/render_list.service.dart';
import 'package:immich_mobile/utils/extensions/drift.extension.dart';
import 'package:immich_mobile/utils/mixins/log_context.mixin.dart';
import 'package:intl/intl.dart';
class RemoteAssetDriftRepository with LogContext implements IAssetRepository {
final DriftDatabaseRepository _db;
@@ -66,7 +65,6 @@ class RemoteAssetDriftRepository with LogContext implements IAssetRepository {
..orderBy([OrderingTerm.desc(createdTimeExp)]);
int lastAssetOffset = 0;
final monthFormatter = DateFormat.yMMMM();
return query
.expand((row) {
@@ -76,9 +74,7 @@ class RemoteAssetDriftRepository with LogContext implements IAssetRepository {
lastAssetOffset += assetCount;
return [
RenderListMonthHeaderElement(
header: monthFormatter.format(createdTime),
),
RenderListMonthHeaderElement(date: createdTime),
RenderListAssetElement(
date: createdTime,
assetCount: assetCount,
@@ -2,21 +2,21 @@ import 'package:immich_mobile/domain/interfaces/store.interface.dart';
import 'package:immich_mobile/domain/models/app_setting.model.dart';
class AppSettingService {
final IStoreRepository store;
final IStoreRepository _store;
const AppSettingService(this.store);
const AppSettingService(this._store);
Future<T> getSetting<T>(AppSetting<T> setting) async {
final value = await store.tryGet(setting.storeKey);
final value = await _store.tryGet(setting.storeKey);
return value ?? setting.defaultValue;
}
Future<bool> setSetting<T>(AppSetting<T> setting, T value) async {
return await store.set(setting.storeKey, value);
return await _store.set(setting.storeKey, value);
}
Stream<T> watchSetting<T>(AppSetting<T> setting) {
return store
return _store
.watch(setting.storeKey)
.map((value) => value ?? setting.defaultValue);
}
@@ -5,15 +5,16 @@ import 'package:immich_mobile/domain/interfaces/asset.interface.dart';
import 'package:immich_mobile/domain/models/asset.model.dart';
import 'package:immich_mobile/domain/models/render_list_element.model.dart';
import 'package:immich_mobile/service_locator.dart';
import 'package:immich_mobile/utils/constants/globals.dart';
class RenderList {
final List<RenderListElement> elements;
final int totalCount;
/// global offset of assets in [_buf]
/// offset of the assets from last section in [_buf]
int _bufOffset = 0;
/// reference to batch of assets loaded from DB with offset [_bufOffset]
/// assets cache loaded from DB with offset [_bufOffset]
List<Asset> _buf = [];
RenderList({required this.elements, required this.totalCount});
@@ -25,21 +26,18 @@ class RenderList {
assert(count > 0);
assert(offset + count <= totalCount);
// general case: we have the query to load assets via offset from the DB on demand
// the requested slice (offset:offset+count) is not contained in the cache buffer `_buf`
// thus, fill the buffer with a new batch of assets that at least contains the requested
// assets and some more
if (offset < _bufOffset || offset + count > _bufOffset + _buf.length) {
// the requested slice (offset:offset+count) is not contained in the cache buffer `_buf`
// thus, fill the buffer with a new batch of assets that at least contains the requested
// assets and some more
final bool forward = _bufOffset < offset;
// if the requested offset is greater than the cached offset, the user scrolls forward "down"
const batchSize = 256;
const oppositeSize = 64;
// make sure to load a meaningful amount of data (and not only the requested slice)
// otherwise, each call to [loadAssets] would result in DB call trashing performance
// fills small requests to [batchSize], adds some legroom into the opposite scroll direction for large requests
final len = math.max(batchSize, count + oppositeSize);
final len =
math.max(kRenderListBatchSize, count + kRenderListOppositeBatchSize);
// when scrolling forward, start shortly before the requested offset...
// when scrolling backward, end shortly after the requested offset...
// ... to guard against the user scrolling in the other direction
@@ -47,9 +45,10 @@ class RenderList {
final start = math.max(
0,
forward
? offset - oppositeSize
: (len > batchSize ? offset : offset + count - len),
? offset - kRenderListOppositeBatchSize
: (len > kRenderListBatchSize ? offset : offset + count - len),
);
// load the calculated batch (start:start+len) from the DB and put it into the buffer
_buf =
await di<IAssetRepository>().fetchAssets(offset: start, limit: len);
@@ -58,6 +57,7 @@ class RenderList {
assert(_bufOffset <= offset);
assert(_bufOffset + _buf.length >= offset + count);
}
// return the requested slice from the buffer (we made sure before that the assets are loaded!)
return _buf.slice(offset - _bufOffset, offset - _bufOffset + count);
}
@@ -6,32 +6,29 @@ import 'package:immich_mobile/domain/repositories/database.repository.dart';
import 'package:immich_mobile/service_locator.dart';
import 'package:immich_mobile/utils/constants/globals.dart';
import 'package:immich_mobile/utils/immich_api_client.dart';
import 'package:immich_mobile/utils/log_manager.dart';
import 'package:immich_mobile/utils/isolate_helper.dart';
import 'package:immich_mobile/utils/mixins/log_context.mixin.dart';
import 'package:logging/logging.dart';
import 'package:openapi/api.dart';
class SyncService with LogContext {
final ImmichApiClient _appClient;
final DriftDatabaseRepository _db;
SyncService(this._appClient, this._db);
SyncService(this._db);
Future<bool> doFullSyncForUserDrift(
User user, {
DateTime? updatedUtil,
int? limit,
}) async {
final clientData = _appClient.clientData;
final helper = IsolateHelper()..preIsolateHandling();
try {
await _db.computeWithDatabase(
connect: (connection) => DriftDatabaseRepository(connection),
computation: (database) async {
ServiceLocator.configureServicesForIsolate(database: database);
LogManager.I.init();
helper.postIsolateHandling(database: database);
final logger = Logger("SyncService <Isolate>");
final syncClient =
ImmichApiClient.clientData(clientData).getSyncApi();
final syncClient = di<ImmichApiClient>().getSyncApi();
final chunkSize = limit ?? kFullSyncChunkSize;
final updatedTill = updatedUtil ?? DateTime.now().toUtc();