Skip to content

Commit

Permalink
refactor: load groups normalised
Browse files Browse the repository at this point in the history
  • Loading branch information
borgoat committed Jan 28, 2024
1 parent 3612526 commit fd9f155
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 23 deletions.
39 changes: 18 additions & 21 deletions lib/epics/groups.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import 'package:rxdart/rxdart.dart';
import 'package:supabase/supabase.dart';

createGroupsEpics(GroupsRepository groups) => combineEpics<AppState>([
_createRefreshRetrieveAllGroupsEpic(groups),
_createRetrieveAllGroupsEpic(groups),
_createRetrieveOneGroupEpic(groups),
_createCreateOneGroupEpic(groups),
Expand Down Expand Up @@ -48,30 +47,28 @@ Stream<dynamic> _loadGroupOnGroupDetailsOpenEpic(
.whereType<GroupDetailsOpenAction>()
.map((action) => RequestRetrieveOne<Group>(action.groupId));

/// Let user refresh the groups, with an action including a Completer, to handle the refresh indicator.
Epic<AppState> _createRefreshRetrieveAllGroupsEpic(GroupsRepository groups) {
return (Stream<dynamic> actions, EpicStore<AppState> store) => actions
.whereType<GroupRefreshAllAction>()
.asyncMap(
(action) => groups
.getUserGroups()
.then<dynamic>(
(groups) => SuccessRetrieveAll(groups.toList(growable: false)))
.catchError((error) => FailRetrieveAll(error))
.whenComplete(() => action.completer.complete()),
);
}

/// Fetch all the groups from the database
/// Load all groups for the current user, together with their members and profiles.
/// If the action includes a Completer, complete, to handle the refresh indicator.
Epic<AppState> _createRetrieveAllGroupsEpic(GroupsRepository groups) {
return (Stream<dynamic> actions, EpicStore<AppState> store) => actions
.whereType<RequestRetrieveAll<Group>>()
.asyncMap(
.where((action) =>
action is GroupRefreshAllAction ||
action is RequestRetrieveAll<Group>)
.switchMap(
(action) => groups
.getUserGroups()
.then<dynamic>(
(groups) => SuccessRetrieveAll(groups.toList(growable: false)))
.catchError((error) => FailRetrieveAll(error)),
.whenComplete(() => action is GroupRefreshAllAction
? action.completer.complete()
: null)
.asStream() // TODO Would it be easier to dispatch 1 action here, and then rethink reducers?
.expand(
(userGroups) => [
SuccessRetrieveAll(userGroups.groups.toList(growable: false)),
SuccessRetrieveMany(userGroups.members.toList(growable: false)),
SuccessRetrieveMany(
userGroups.profiles.toList(growable: false)),
],
),
);
}

Expand Down
21 changes: 19 additions & 2 deletions lib/repositories/groups.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,29 @@ import 'supabase.dart';
class GroupsRepository extends SupabaseRepository with Postgrest {
GroupsRepository({required super.supabase}) : super(tableName: Tables.groups);

Future<Iterable<Group>> getUserGroups() async {
Future<
({
Iterable<Group> groups,
Iterable<Member> members,
Iterable<Profile> profiles,
})> getUserGroups() async {
return table()
.select('*, members!inner(*,profiles!inner(*))')
// TODO(borgoat): should filter by profile_id but return all members
// .eq('members.profile_id', supabase.auth.currentUser!.id)
.withConverter((data) => data.map(Group.fromJson));
.withConverter((data) {
final groups = <Group>{};
final members = <Member>{};
final profiles = <Profile>{};
for (var value in data) {
groups.add(Group.fromJson(value));
for (var member in value['members']) {
members.add(Member.fromJson(member));
profiles.add(Profile.fromJson(member['profiles']));
}
}
return (groups: groups, members: members, profiles: profiles);
});
}

Future<Group> getGroupById(int id) async {
Expand Down

0 comments on commit fd9f155

Please sign in to comment.