fix: show only owned assets in places and map (#22585)

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong 2025-10-02 21:11:14 +05:30 committed by GitHub
parent 950f268cb0
commit a2b25b7a74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 44 additions and 19 deletions

View File

@ -84,8 +84,8 @@ class AssetService {
return 1.0; return 1.0;
} }
Future<List<(String, String)>> getPlaces() { Future<List<(String, String)>> getPlaces(String userId) {
return _remoteAssetRepository.getPlaces(); return _remoteAssetRepository.getPlaces(userId);
} }
Future<(int local, int remote)> getAssetCounts() async { Future<(int local, int remote)> getAssetCounts() async {

View File

@ -59,7 +59,8 @@ class TimelineFactory {
TimelineService fromAssets(List<BaseAsset> assets) => TimelineService(_timelineRepository.fromAssets(assets)); TimelineService fromAssets(List<BaseAsset> assets) => TimelineService(_timelineRepository.fromAssets(assets));
TimelineService map(LatLngBounds bounds) => TimelineService(_timelineRepository.map(bounds, groupBy)); TimelineService map(String userId, LatLngBounds bounds) =>
TimelineService(_timelineRepository.map(userId, bounds, groupBy));
} }
class TimelineService { class TimelineService {

View File

@ -81,9 +81,11 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
.getSingleOrNull(); .getSingleOrNull();
} }
Future<List<(String, String)>> getPlaces() { Future<List<(String, String)>> getPlaces(String userId) {
final asset = Subquery( final asset = Subquery(
_db.remoteAssetEntity.select()..orderBy([(row) => OrderingTerm.desc(row.createdAt)]), _db.remoteAssetEntity.select()
..where((row) => row.ownerId.equals(userId))
..orderBy([(row) => OrderingTerm.desc(row.createdAt)]),
"asset", "asset",
); );

View File

@ -431,12 +431,16 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get(); return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get();
} }
TimelineQuery map(LatLngBounds bounds, GroupAssetsBy groupBy) => ( TimelineQuery map(String userId, LatLngBounds bounds, GroupAssetsBy groupBy) => (
bucketSource: () => _watchMapBucket(bounds, groupBy: groupBy), bucketSource: () => _watchMapBucket(userId, bounds, groupBy: groupBy),
assetSource: (offset, count) => _getMapBucketAssets(bounds, offset: offset, count: count), assetSource: (offset, count) => _getMapBucketAssets(userId, bounds, offset: offset, count: count),
); );
Stream<List<Bucket>> _watchMapBucket(LatLngBounds bounds, {GroupAssetsBy groupBy = GroupAssetsBy.day}) { Stream<List<Bucket>> _watchMapBucket(
String userId,
LatLngBounds bounds, {
GroupAssetsBy groupBy = GroupAssetsBy.day,
}) {
if (groupBy == GroupAssetsBy.none) { if (groupBy == GroupAssetsBy.none) {
// TODO: Support GroupAssetsBy.none // TODO: Support GroupAssetsBy.none
throw UnsupportedError("GroupAssetsBy.none is not supported for _watchMapBucket"); throw UnsupportedError("GroupAssetsBy.none is not supported for _watchMapBucket");
@ -455,7 +459,8 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
), ),
]) ])
..where( ..where(
_db.remoteExifEntity.inBounds(bounds) & _db.remoteAssetEntity.ownerId.equals(userId) &
_db.remoteExifEntity.inBounds(bounds) &
_db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline) & _db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline) &
_db.remoteAssetEntity.deletedAt.isNull(), _db.remoteAssetEntity.deletedAt.isNull(),
) )
@ -469,7 +474,12 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
}).watch(); }).watch();
} }
Future<List<BaseAsset>> _getMapBucketAssets(LatLngBounds bounds, {required int offset, required int count}) { Future<List<BaseAsset>> _getMapBucketAssets(
String userId,
LatLngBounds bounds, {
required int offset,
required int count,
}) {
final query = final query =
_db.remoteAssetEntity.select().join([ _db.remoteAssetEntity.select().join([
innerJoin( innerJoin(
@ -479,7 +489,8 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
), ),
]) ])
..where( ..where(
_db.remoteExifEntity.inBounds(bounds) & _db.remoteAssetEntity.ownerId.equals(userId) &
_db.remoteExifEntity.inBounds(bounds) &
_db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline) & _db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline) &
_db.remoteAssetEntity.deletedAt.isNull(), _db.remoteAssetEntity.deletedAt.isNull(),
) )

View File

@ -5,6 +5,7 @@ import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_shee
import 'package:immich_mobile/presentation/widgets/map/map.state.dart'; import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart'; import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
class MapBottomSheet extends StatelessWidget { class MapBottomSheet extends StatelessWidget {
const MapBottomSheet({super.key}); const MapBottomSheet({super.key});
@ -32,8 +33,13 @@ class _ScopedMapTimeline extends StatelessWidget {
return ProviderScope( return ProviderScope(
overrides: [ overrides: [
timelineServiceProvider.overrideWith((ref) { timelineServiceProvider.overrideWith((ref) {
final user = ref.watch(currentUserProvider);
if (user == null) {
throw Exception('User must be logged in to access archive');
}
final bounds = ref.watch(mapStateProvider).bounds; final bounds = ref.watch(mapStateProvider).bounds;
final timelineService = ref.watch(timelineFactoryProvider).map(bounds); final timelineService = ref.watch(timelineFactoryProvider).map(user.id, bounds);
ref.onDispose(timelineService.dispose); ref.onDispose(timelineService.dispose);
return timelineService; return timelineService;
}), }),

View File

@ -3,6 +3,7 @@ import 'package:immich_mobile/domain/services/asset.service.dart';
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart';
import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
final localAssetRepository = Provider<DriftLocalAssetRepository>( final localAssetRepository = Provider<DriftLocalAssetRepository>(
(ref) => DriftLocalAssetRepository(ref.watch(driftProvider)), (ref) => DriftLocalAssetRepository(ref.watch(driftProvider)),
@ -19,9 +20,13 @@ final assetServiceProvider = Provider(
), ),
); );
final placesProvider = FutureProvider<List<(String, String)>>( final placesProvider = FutureProvider<List<(String, String)>>((ref) {
(ref) => AssetService( final assetService = ref.watch(assetServiceProvider);
remoteAssetRepository: ref.watch(remoteAssetRepositoryProvider), final auth = ref.watch(currentUserProvider);
localAssetRepository: ref.watch(localAssetRepository),
).getPlaces(), if (auth == null) {
); return Future.value(const []);
}
return assetService.getPlaces(auth.id);
});