fix: correct member counts and member removal flow

This commit is contained in:
Lukas Müllner 2026-03-05 10:56:20 +01:00
parent c412eda221
commit bb389d6f78
2 changed files with 49 additions and 25 deletions

View file

@ -0,0 +1,7 @@
-- Run this in Supabase SQL Editor to allow a read-only viewer role.
alter table public.collection_members
drop constraint if exists collection_members_role_check;
alter table public.collection_members
add constraint collection_members_role_check
check (role in ('owner', 'member', 'viewer'));

View file

@ -115,17 +115,33 @@ class CollectionService {
itemCounts[collectionId] = (itemCounts[collectionId] ?? 0) + 1;
}
// Fetch all members for these collections in a single query and count them in memory.
final memberCounts = <String, int>{};
await Future.wait(collectionIdList.map((collectionId) async {
try {
final rows = await supabase.rpc('get_collection_members', params: {
'p_collection_id': collectionId,
});
memberCounts[collectionId] = (rows as List).length;
} catch (_) {
// Keep fallback below when RPC fails.
}
}));
// Fallback member count for collections where RPC did not return data.
final unresolvedIds = collectionIdList
.where((id) => !memberCounts.containsKey(id))
.toList(growable: false);
if (unresolvedIds.isNotEmpty) {
final members = await supabase
.from('collection_members')
.select('id, collection_id')
.inFilter('collection_id', collectionIdList);
.inFilter('collection_id', unresolvedIds);
final memberCounts = <String, int>{};
for (final member in members) {
final collectionId = member['collection_id'] as String;
memberCounts[collectionId] = (memberCounts[collectionId] ?? 0) + 1;
}
}
final collections = <Collection>[];
@ -316,11 +332,22 @@ class CollectionService {
throw Exception('This user is already a member of this collection.');
}
try {
await supabase.from('collection_members').insert({
'collection_id': collectionId,
'user_id': userId,
'role': normalizedRole,
});
} catch (e) {
final message = e.toString();
if (normalizedRole == 'viewer' &&
message.contains('collection_members_role_check')) {
throw Exception(
'Viewer role is not enabled in your database yet. Please apply the viewer-role migration first.',
);
}
rethrow;
}
}
/// Remove a member from a collection.
@ -343,17 +370,7 @@ class CollectionService {
throw Exception('Only the collection owner can remove members.');
}
final target = await supabase
.from('collection_members')
.select('role, user_id')
.eq('user_id', memberUserId)
.eq('collection_id', collectionId)
.maybeSingle();
if (target == null) {
throw Exception('Member not found.');
}
if (target['role'] == 'owner') {
if (memberUserId == collection['owner_id']) {
throw Exception('Collection owner cannot be removed.');
}