mirror of
https://github.com/immich-app/immich.git
synced 2025-11-27 07:10:00 +09:00
fix(mobile): 14983 Images upload to shared album with common name (#15127)
Some checks are pending
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Docker / pre-job (push) Waiting to run
Docker / Re-Tag ML () (push) Blocked by required conditions
Docker / Re-Tag ML (-armnn) (push) Blocked by required conditions
Docker / Re-Tag ML (-cuda) (push) Blocked by required conditions
Docker / Re-Tag ML (-openvino) (push) Blocked by required conditions
Docker / Re-Tag Server () (push) Blocked by required conditions
Docker / Build and Push ML (armnn, linux/arm64, -armnn) (push) Blocked by required conditions
Docker / Build and Push ML (cpu, linux/amd64,linux/arm64) (push) Blocked by required conditions
Docker / Build and Push ML (cuda, linux/amd64, -cuda) (push) Blocked by required conditions
Docker / Build and Push ML (openvino, linux/amd64, -openvino) (push) Blocked by required conditions
Docker / Build and Push Server (cpu, linux/amd64,linux/arm64) (push) Blocked by required conditions
Docker / Docker Build & Push Server Success (push) Blocked by required conditions
Docker / Docker Build & Push ML Success (push) Blocked by required conditions
Docs build / pre-job (push) Waiting to run
Docs build / Docs Build (push) Blocked by required conditions
Static Code Analysis / pre-job (push) Waiting to run
Static Code Analysis / Run Dart Code Analysis (push) Blocked by required conditions
Test / pre-job (push) Waiting to run
Test / Test & Lint Server (push) Blocked by required conditions
Test / Unit Test CLI (push) Blocked by required conditions
Test / Unit Test CLI (Windows) (push) Blocked by required conditions
Test / Test & Lint Web (push) Blocked by required conditions
Test / End-to-End Lint (push) Blocked by required conditions
Test / Medium Tests (Server) (push) Blocked by required conditions
Test / End-to-End Tests (Server & CLI) (push) Blocked by required conditions
Test / End-to-End Tests (Web) (push) Blocked by required conditions
Test / Unit Test Mobile (push) Blocked by required conditions
Test / Unit Test ML (push) Blocked by required conditions
Test / ShellCheck (push) Waiting to run
Test / OpenAPI Clients (push) Waiting to run
Test / TypeORM Checks (push) Waiting to run
Some checks are pending
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Docker / pre-job (push) Waiting to run
Docker / Re-Tag ML () (push) Blocked by required conditions
Docker / Re-Tag ML (-armnn) (push) Blocked by required conditions
Docker / Re-Tag ML (-cuda) (push) Blocked by required conditions
Docker / Re-Tag ML (-openvino) (push) Blocked by required conditions
Docker / Re-Tag Server () (push) Blocked by required conditions
Docker / Build and Push ML (armnn, linux/arm64, -armnn) (push) Blocked by required conditions
Docker / Build and Push ML (cpu, linux/amd64,linux/arm64) (push) Blocked by required conditions
Docker / Build and Push ML (cuda, linux/amd64, -cuda) (push) Blocked by required conditions
Docker / Build and Push ML (openvino, linux/amd64, -openvino) (push) Blocked by required conditions
Docker / Build and Push Server (cpu, linux/amd64,linux/arm64) (push) Blocked by required conditions
Docker / Docker Build & Push Server Success (push) Blocked by required conditions
Docker / Docker Build & Push ML Success (push) Blocked by required conditions
Docs build / pre-job (push) Waiting to run
Docs build / Docs Build (push) Blocked by required conditions
Static Code Analysis / pre-job (push) Waiting to run
Static Code Analysis / Run Dart Code Analysis (push) Blocked by required conditions
Test / pre-job (push) Waiting to run
Test / Test & Lint Server (push) Blocked by required conditions
Test / Unit Test CLI (push) Blocked by required conditions
Test / Unit Test CLI (Windows) (push) Blocked by required conditions
Test / Test & Lint Web (push) Blocked by required conditions
Test / End-to-End Lint (push) Blocked by required conditions
Test / Medium Tests (Server) (push) Blocked by required conditions
Test / End-to-End Tests (Server & CLI) (push) Blocked by required conditions
Test / End-to-End Tests (Web) (push) Blocked by required conditions
Test / Unit Test Mobile (push) Blocked by required conditions
Test / Unit Test ML (push) Blocked by required conditions
Test / ShellCheck (push) Waiting to run
Test / OpenAPI Clients (push) Waiting to run
Test / TypeORM Checks (push) Waiting to run
* Initial look at fixing issue where images are uploaded to the wrong album if a shared album conflicts with a local users album. * Use owner instead of shared flag when fetching albums. * Fix issue with refreshRemoteAlbums getting shared items twice and removed incorrect isShared comment. Using `getAll(shared: true)` gets all shared albums the user can access (regardless of owner, despite the previous comment). Using `getAll(shared: null)` gets all albums (incuding shared = true and shared = false). I presume the intent here was to get albums that were shared (and not mine), and not shared (ie: mine), but the logic is way off. It also just then combines them - so makes more sense to just get them in a single call. * Fix formatting. * Fixed tests. * Revert "Fixed tests." This reverts commitc38f5af5ac. * Revert "Fix issue with refreshRemoteAlbums getting shared items twice and removed incorrect isShared comment." This reverts commit979ce90abf. * Added comments to explain why filters behave the way they do for getAll() albums. --------- Co-authored-by: Tom graham <tomg@questps.com.au> Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
@@ -13,6 +13,7 @@ abstract interface class IAlbumRepository implements IDatabaseRepository {
|
|||||||
String name, {
|
String name, {
|
||||||
bool? shared,
|
bool? shared,
|
||||||
bool? remote,
|
bool? remote,
|
||||||
|
bool? owner,
|
||||||
});
|
});
|
||||||
|
|
||||||
Future<List<Album>> getAll({
|
Future<List<Album>> getAll({
|
||||||
|
|||||||
@@ -46,8 +46,18 @@ class AlbumNotifier extends StateNotifier<List<Album>> {
|
|||||||
) =>
|
) =>
|
||||||
_albumService.createAlbum(albumTitle, assets, []);
|
_albumService.createAlbum(albumTitle, assets, []);
|
||||||
|
|
||||||
Future<Album?> getAlbumByName(String albumName, {bool remoteOnly = false}) =>
|
Future<Album?> getAlbumByName(
|
||||||
_albumService.getAlbumByName(albumName, remoteOnly);
|
String albumName, {
|
||||||
|
bool? remote,
|
||||||
|
bool? shared,
|
||||||
|
bool? owner,
|
||||||
|
}) =>
|
||||||
|
_albumService.getAlbumByName(
|
||||||
|
albumName,
|
||||||
|
remote: remote,
|
||||||
|
shared: shared,
|
||||||
|
owner: owner,
|
||||||
|
);
|
||||||
|
|
||||||
/// Create an album on the server with the same name as the selected album for backup
|
/// Create an album on the server with the same name as the selected album for backup
|
||||||
/// First this will check if the album already exists on the server with name
|
/// First this will check if the album already exists on the server with name
|
||||||
@@ -55,7 +65,7 @@ class AlbumNotifier extends StateNotifier<List<Album>> {
|
|||||||
Future<void> createSyncAlbum(
|
Future<void> createSyncAlbum(
|
||||||
String albumName,
|
String albumName,
|
||||||
) async {
|
) async {
|
||||||
final album = await getAlbumByName(albumName, remoteOnly: true);
|
final album = await getAlbumByName(albumName, remote: true, owner: true);
|
||||||
if (album != null) {
|
if (album != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,25 @@ class AlbumRepository extends DatabaseRepository implements IAlbumRepository {
|
|||||||
Future<Album> create(Album album) => txn(() => db.albums.store(album));
|
Future<Album> create(Album album) => txn(() => db.albums.store(album));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Album?> getByName(String name, {bool? shared, bool? remote}) {
|
Future<Album?> getByName(
|
||||||
|
String name, {
|
||||||
|
bool? shared,
|
||||||
|
bool? remote,
|
||||||
|
bool? owner,
|
||||||
|
}) {
|
||||||
var query = db.albums.filter().nameEqualTo(name);
|
var query = db.albums.filter().nameEqualTo(name);
|
||||||
if (shared != null) {
|
if (shared != null) {
|
||||||
query = query.sharedEqualTo(shared);
|
query = query.sharedEqualTo(shared);
|
||||||
}
|
}
|
||||||
|
if (owner == true) {
|
||||||
|
query = query.owner(
|
||||||
|
(q) => q.isarIdEqualTo(Store.get(StoreKey.currentUser).isarId),
|
||||||
|
);
|
||||||
|
} else if (owner == false) {
|
||||||
|
query = query.owner(
|
||||||
|
(q) => q.not().isarIdEqualTo(Store.get(StoreKey.currentUser).isarId),
|
||||||
|
);
|
||||||
|
}
|
||||||
if (remote == true) {
|
if (remote == true) {
|
||||||
query = query.localIdIsNull();
|
query = query.localIdIsNull();
|
||||||
} else if (remote == false) {
|
} else if (remote == false) {
|
||||||
|
|||||||
@@ -170,7 +170,12 @@ class AlbumService {
|
|||||||
try {
|
try {
|
||||||
await _userService.refreshUsers();
|
await _userService.refreshUsers();
|
||||||
final (sharedAlbum, ownedAlbum) = await (
|
final (sharedAlbum, ownedAlbum) = await (
|
||||||
|
// Note: `shared: true` is required to get albums that don't belong to
|
||||||
|
// us due to unusual behaviour on the API but this will also return our
|
||||||
|
// own shared albums
|
||||||
_albumApiRepository.getAll(shared: true),
|
_albumApiRepository.getAll(shared: true),
|
||||||
|
// Passing null (or nothing) for `shared` returns only albums that
|
||||||
|
// explicitly belong to us
|
||||||
_albumApiRepository.getAll(shared: null)
|
_albumApiRepository.getAll(shared: null)
|
||||||
).wait;
|
).wait;
|
||||||
|
|
||||||
@@ -212,7 +217,7 @@ class AlbumService {
|
|||||||
for (int round = 0;; round++) {
|
for (int round = 0;; round++) {
|
||||||
final proposedName = "$baseName${round == 0 ? "" : " ($round)"}";
|
final proposedName = "$baseName${round == 0 ? "" : " ($round)"}";
|
||||||
|
|
||||||
if (null == await _albumRepository.getByName(proposedName)) {
|
if (null == await _albumRepository.getByName(proposedName, owner: true)) {
|
||||||
return proposedName;
|
return proposedName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -408,8 +413,18 @@ class AlbumService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Album?> getAlbumByName(String name, bool remoteOnly) =>
|
Future<Album?> getAlbumByName(
|
||||||
_albumRepository.getByName(name, remote: remoteOnly ? true : null);
|
String name, {
|
||||||
|
bool? remote,
|
||||||
|
bool? shared,
|
||||||
|
bool? owner,
|
||||||
|
}) =>
|
||||||
|
_albumRepository.getByName(
|
||||||
|
name,
|
||||||
|
remote: remote,
|
||||||
|
shared: shared,
|
||||||
|
owner: owner,
|
||||||
|
);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Add the uploaded asset to the selected albums
|
/// Add the uploaded asset to the selected albums
|
||||||
@@ -419,7 +434,7 @@ class AlbumService {
|
|||||||
List<String> assetIds,
|
List<String> assetIds,
|
||||||
) async {
|
) async {
|
||||||
for (final albumName in albumNames) {
|
for (final albumName in albumNames) {
|
||||||
Album? album = await getAlbumByName(albumName, true);
|
Album? album = await getAlbumByName(albumName, remote: true, owner: true);
|
||||||
album ??= await createAlbum(albumName, []);
|
album ??= await createAlbum(albumName, []);
|
||||||
if (album != null && album.remoteId != null) {
|
if (album != null && album.remoteId != null) {
|
||||||
await _albumApiRepository.addAssets(album.remoteId!, assetIds);
|
await _albumApiRepository.addAssets(album.remoteId!, assetIds);
|
||||||
|
|||||||
Reference in New Issue
Block a user