mirror of
https://github.com/immich-app/immich.git
synced 2025-12-06 04:41:40 -08:00
Compare commits
1 Commits
v1.139.1
...
fix/timeli
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19c9f932ea |
@@ -10,6 +10,7 @@ import 'package:immich_mobile/domain/services/setting.service.dart';
|
|||||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
||||||
import 'package:immich_mobile/utils/async_mutex.dart';
|
import 'package:immich_mobile/utils/async_mutex.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
typedef TimelineAssetSource = Future<List<BaseAsset>> Function(
|
typedef TimelineAssetSource = Future<List<BaseAsset>> Function(
|
||||||
int index,
|
int index,
|
||||||
@@ -77,6 +78,7 @@ class TimelineService {
|
|||||||
int _bufferOffset = 0;
|
int _bufferOffset = 0;
|
||||||
List<BaseAsset> _buffer = [];
|
List<BaseAsset> _buffer = [];
|
||||||
StreamSubscription? _bucketSubscription;
|
StreamSubscription? _bucketSubscription;
|
||||||
|
final _log = Logger('TimelineService');
|
||||||
|
|
||||||
int _totalAssets = 0;
|
int _totalAssets = 0;
|
||||||
int get totalAssets => _totalAssets;
|
int get totalAssets => _totalAssets;
|
||||||
@@ -128,10 +130,10 @@ class TimelineService {
|
|||||||
|
|
||||||
Stream<List<Bucket>> Function() get watchBuckets => _bucketSource;
|
Stream<List<Bucket>> Function() get watchBuckets => _bucketSource;
|
||||||
|
|
||||||
Future<List<BaseAsset>> loadAssets(int index, int count) =>
|
Future<List<BaseAsset>?> loadAssets(int index, int count) =>
|
||||||
_mutex.run(() => _loadAssets(index, count));
|
_mutex.run(() => _loadAssets(index, count));
|
||||||
|
|
||||||
Future<List<BaseAsset>> _loadAssets(int index, int count) async {
|
Future<List<BaseAsset>?> _loadAssets(int index, int count) async {
|
||||||
if (hasRange(index, count)) {
|
if (hasRange(index, count)) {
|
||||||
return getAssets(index, count);
|
return getAssets(index, count);
|
||||||
}
|
}
|
||||||
@@ -169,9 +171,10 @@ class TimelineService {
|
|||||||
index + count <= _bufferOffset + _buffer.length &&
|
index + count <= _bufferOffset + _buffer.length &&
|
||||||
index + count <= _totalAssets;
|
index + count <= _totalAssets;
|
||||||
|
|
||||||
List<BaseAsset> getAssets(int index, int count) {
|
List<BaseAsset>? getAssets(int index, int count) {
|
||||||
if (!hasRange(index, count)) {
|
if (!hasRange(index, count)) {
|
||||||
throw RangeError('TimelineService::getAssets Index out of range');
|
_log.warning('TimelineService::getAssets Index out of range');
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
int start = index - _bufferOffset;
|
int start = index - _bufferOffset;
|
||||||
return _buffer.slice(start, start + count);
|
return _buffer.slice(start, start + count);
|
||||||
|
|||||||
@@ -107,19 +107,22 @@ class _FixedSegmentRow extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (timelineService.hasRange(assetIndex, assetCount)) {
|
if (timelineService.hasRange(assetIndex, assetCount)) {
|
||||||
return _buildAssetRow(
|
final assets = timelineService.getAssets(assetIndex, assetCount);
|
||||||
context,
|
if (assets == null) {
|
||||||
timelineService.getAssets(assetIndex, assetCount),
|
return _buildPlaceholder(context);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
return _buildAssetRow(context, assets);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FutureBuilder<List<BaseAsset>>(
|
return FutureBuilder<List<BaseAsset>?>(
|
||||||
future: timelineService.loadAssets(assetIndex, assetCount),
|
future: timelineService.loadAssets(assetIndex, assetCount),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.connectionState != ConnectionState.done) {
|
if (snapshot.connectionState != ConnectionState.done ||
|
||||||
|
snapshot.data == null) {
|
||||||
return _buildPlaceholder(context);
|
return _buildPlaceholder(context);
|
||||||
}
|
}
|
||||||
return _buildAssetRow(context, snapshot.requireData);
|
return _buildAssetRow(context, snapshot.data!);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,8 +112,9 @@ class _BulkSelectIconButton extends ConsumerWidget {
|
|||||||
List<BaseAsset> bucketAssets;
|
List<BaseAsset> bucketAssets;
|
||||||
try {
|
try {
|
||||||
bucketAssets = ref
|
bucketAssets = ref
|
||||||
.watch(timelineServiceProvider)
|
.watch(timelineServiceProvider)
|
||||||
.getAssets(assetOffset, bucket.assetCount);
|
.getAssets(assetOffset, bucket.assetCount) ??
|
||||||
|
[];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
bucketAssets = <BaseAsset>[];
|
bucketAssets = <BaseAsset>[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||||
@@ -130,7 +129,7 @@ class MultiSelectNotifier extends Notifier<MultiSelectState> {
|
|||||||
final assets = await _timelineService.loadAssets(offset, bucketCount);
|
final assets = await _timelineService.loadAssets(offset, bucketCount);
|
||||||
final selectedAssets = state.selectedAssets.toSet();
|
final selectedAssets = state.selectedAssets.toSet();
|
||||||
|
|
||||||
selectedAssets.addAll(assets);
|
selectedAssets.addAll(assets ?? []);
|
||||||
|
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
selectedAssets: selectedAssets,
|
selectedAssets: selectedAssets,
|
||||||
@@ -141,14 +140,14 @@ class MultiSelectNotifier extends Notifier<MultiSelectState> {
|
|||||||
final assets = await _timelineService.loadAssets(offset, bucketCount);
|
final assets = await _timelineService.loadAssets(offset, bucketCount);
|
||||||
final selectedAssets = state.selectedAssets.toSet();
|
final selectedAssets = state.selectedAssets.toSet();
|
||||||
|
|
||||||
selectedAssets.removeAll(assets);
|
selectedAssets.removeAll(assets ?? []);
|
||||||
|
|
||||||
state = state.copyWith(selectedAssets: selectedAssets);
|
state = state.copyWith(selectedAssets: selectedAssets);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleBucketSelection(int offset, int bucketCount) async {
|
void toggleBucketSelection(int offset, int bucketCount) async {
|
||||||
final assets = await _timelineService.loadAssets(offset, bucketCount);
|
final assets = await _timelineService.loadAssets(offset, bucketCount);
|
||||||
toggleBucketSelectionByAssets(assets);
|
toggleBucketSelectionByAssets(assets ?? []);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleBucketSelectionByAssets(List<BaseAsset> bucketAssets) {
|
void toggleBucketSelectionByAssets(List<BaseAsset> bucketAssets) {
|
||||||
|
|||||||
Reference in New Issue
Block a user