Skip to content

Commit 673d4f1

Browse files
Merge feat/campaign_total_ask into chore/remove_old_daos
2 parents c3f69fd + 5819aa4 commit 673d4f1

File tree

22 files changed

+1323
-145
lines changed

22 files changed

+1323
-145
lines changed

catalyst_voices/apps/voices/lib/pages/category/category_page.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ class _CategoryDetailContent extends StatelessWidget {
141141
}
142142

143143
class _CategoryDetailError extends StatelessWidget {
144-
final SignedDocumentRef categoryId;
144+
final SignedDocumentRef categoryRef;
145145

146-
const _CategoryDetailError({required this.categoryId});
146+
const _CategoryDetailError({required this.categoryRef});
147147

148148
@override
149149
Widget build(BuildContext context) {
@@ -167,7 +167,7 @@ class _CategoryDetailError extends StatelessWidget {
167167
? null
168168
: () {
169169
unawaited(
170-
context.read<CategoryDetailCubit>().getCategoryDetail(categoryId),
170+
context.read<CategoryDetailCubit>().getCategoryDetail(categoryRef),
171171
);
172172
},
173173
),
@@ -189,7 +189,7 @@ class _CategoryPageState extends State<CategoryPage> {
189189
children: [
190190
const _CategoryDetailContent(),
191191
_CategoryDetailError(
192-
categoryId: widget.categoryRef,
192+
categoryRef: widget.categoryRef,
193193
),
194194
].constrainedDelegate(),
195195
),

catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposal/proposal_cubit.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ final class ProposalCubit extends Cubit<ProposalState>
4949
_cache = _cache.copyWith(
5050
activeAccountId: Optional(_userService.user.activeAccount?.catalystId),
5151
);
52-
_activeAccountIdSub = _userService.watchUser
53-
.map((event) => event.activeAccount?.catalystId)
52+
_activeAccountIdSub = _userService.watchUnlockedActiveAccount
53+
.map((activeAccount) => activeAccount?.catalystId)
5454
.distinct()
5555
.listen(_handleActiveAccountIdChanged);
5656
}

catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/proposal_builder/proposal_builder_bloc.dart

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,9 @@ final class ProposalBuilderBloc extends Bloc<ProposalBuilderEvent, ProposalBuild
8282
accountPublicStatus: Optional(activeAccount?.publicStatus),
8383
);
8484

85-
_activeAccountSub = _userService.watchUser
86-
.map((event) => event.activeAccount)
87-
.distinct()
88-
.listen(
89-
(value) => add(RebuildActiveAccountProposalEvent(account: value)),
90-
);
85+
_activeAccountSub = _userService.watchUnlockedActiveAccount.listen(
86+
(value) => add(RebuildActiveAccountProposalEvent(account: value)),
87+
);
9188

9289
_isMaxProposalsLimitReachedSub = _proposalService.watchMaxProposalsLimitReached().listen((
9390
event,

catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/session/session_cubit.dart

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
77
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
88
import 'package:collection/collection.dart';
99
import 'package:flutter/foundation.dart';
10-
import 'package:rxdart/rxdart.dart';
1110

1211
bool _alwaysAllowRegistration = kDebugMode;
1312

@@ -51,11 +50,8 @@ final class SessionCubit extends Cubit<SessionState>
5150
.distinct()
5251
.listen(_handleUserSettings);
5352

54-
_keychainUnlockedSub = _userService.watchUser
55-
.map((user) => user.activeAccount)
56-
.switchMap((account) {
57-
return account?.keychain.watchIsUnlocked ?? Stream.value(false);
58-
})
53+
_keychainUnlockedSub = _userService.watchUnlockedActiveAccount
54+
.map((account) => account != null)
5955
.distinct()
6056
.listen(_onActiveKeychainUnlockChanged);
6157

@@ -229,8 +225,6 @@ final class SessionCubit extends Cubit<SessionState>
229225
);
230226
}
231227

232-
// TODO(damian-molinski): Refactor active account stream so it emits null when account
233-
// keychain is locked.
234228
void _emitAccountBasedSignal() {
235229
final account = _account;
236230

catalyst_voices/packages/internal/catalyst_voices_models/lib/src/proposals/proposals_filters_v2.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ final class ProposalsCampaignFilters extends Equatable {
1717
return ProposalsCampaignFilters(categoriesIds: categoriesIds);
1818
}
1919

20+
factory ProposalsCampaignFilters.from(Campaign campaign) {
21+
final categoriesIds = campaign.categories.map((e) => e.selfRef.id).toSet();
22+
return ProposalsCampaignFilters(categoriesIds: categoriesIds);
23+
}
24+
2025
@override
2126
List<Object?> get props => [categoriesIds];
2227

catalyst_voices/packages/internal/catalyst_voices_services/lib/src/proposal/proposal_service.dart

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -403,16 +403,36 @@ final class ProposalServiceImpl implements ProposalService {
403403

404404
@override
405405
Stream<bool> watchMaxProposalsLimitReached() {
406-
// TODO(damian-molinski): watch active account id + active campaign
407-
const filters = ProposalsFiltersV2(
408-
status: ProposalStatusFilter.aFinal,
409-
author: null,
410-
campaign: null,
406+
final activeAccountId = _userService.watchUnlockedActiveAccount
407+
.map((account) => account?.catalystId)
408+
.distinct();
409+
final activeCampaign = _activeCampaignObserver.watchCampaign.distinct();
410+
411+
return Rx.combineLatest2<CatalystId?, Campaign?, ProposalsFiltersV2?>(
412+
activeAccountId,
413+
activeCampaign,
414+
(author, campaign) {
415+
if (author == null || campaign == null) {
416+
return null;
417+
}
418+
419+
return ProposalsFiltersV2(
420+
status: ProposalStatusFilter.aFinal,
421+
author: author,
422+
campaign: ProposalsCampaignFilters.from(campaign),
423+
);
424+
},
425+
).distinct().switchMap(
426+
(filters) {
427+
if (filters == null) {
428+
return Stream.value(true);
429+
}
430+
431+
return _proposalRepository
432+
.watchProposalsCountV2(filters: filters)
433+
.map((event) => event >= ProposalDocument.maxSubmittedProposalsPerUser);
434+
},
411435
);
412-
413-
return _proposalRepository
414-
.watchProposalsCountV2(filters: filters)
415-
.map((event) => event >= ProposalDocument.maxSubmittedProposalsPerUser);
416436
}
417437

418438
@override
@@ -458,10 +478,12 @@ final class ProposalServiceImpl implements ProposalService {
458478
}
459479

460480
@override
461-
Stream<List<DetailProposal>> watchUserProposals() async* {
462-
yield* _userService.watchUser.distinct().switchMap((user) {
463-
final authorId = user.activeAccount?.catalystId;
464-
if (!_isProposer(user) || authorId == null) {
481+
Stream<List<DetailProposal>> watchUserProposals() {
482+
return _userService.watchUnlockedActiveAccount.distinct().switchMap((account) {
483+
if (account == null) return const Stream.empty();
484+
485+
final authorId = account.catalystId;
486+
if (!account.hasRole(AccountRole.proposer)) {
465487
return const Stream.empty();
466488
}
467489

@@ -589,10 +611,6 @@ final class ProposalServiceImpl implements ProposalService {
589611
return account.catalystId;
590612
}
591613

592-
bool _isProposer(User user) {
593-
return user.activeAccount?.roles.contains(AccountRole.proposer) ?? false;
594-
}
595-
596614
ProposalBriefData _mapJoinedProposalBriefData(
597615
JoinedProposalBriefData data,
598616
List<Vote> draftVotes,

catalyst_voices/packages/internal/catalyst_voices_services/lib/src/user/user_service.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:catalyst_voices_services/catalyst_voices_services.dart';
77
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
88
import 'package:collection/collection.dart';
99
import 'package:flutter/foundation.dart';
10+
import 'package:rxdart/rxdart.dart';
1011

1112
/// [UserService] allows to manage user accounts.
1213
/// [watchUser] returns a stream of user changes which allows to react to user changes.
@@ -19,6 +20,9 @@ abstract interface class UserService implements ActiveAware {
1920

2021
User get user;
2122

23+
/// Returns [Account] when keychain is unlocked, otherwise returns `null`.
24+
Stream<Account?> get watchUnlockedActiveAccount;
25+
2226
Stream<User> get watchUser;
2327

2428
Future<void> dispose();
@@ -115,6 +119,15 @@ final class UserServiceImpl implements UserService {
115119
@override
116120
User get user => _userObserver.user;
117121

122+
@override
123+
Stream<Account?> get watchUnlockedActiveAccount =>
124+
watchUser.map((e) => e.activeAccount).switchMap((account) {
125+
if (account == null) return Stream.value(null);
126+
127+
final isUnlockedStream = account.keychain.watchIsUnlocked;
128+
return isUnlockedStream.map((isUnlocked) => isUnlocked ? account : null);
129+
}).distinct();
130+
118131
@override
119132
Stream<User> get watchUser => _userObserver.watchUser;
120133

catalyst_voices/packages/internal/catalyst_voices_services/test/src/proposal/proposal_service_test.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,15 @@ void main() {
6060
keychain: MockKeychain(),
6161
isActive: true,
6262
);
63-
final user = User.optional(accounts: [account]);
63+
final campaign = Campaign.f15();
6464
const proposalsCount = ProposalDocument.maxSubmittedProposalsPerUser + 1;
6565

66-
when(() => mockUserService.watchUser).thenAnswer((_) => Stream.value(user));
66+
when(
67+
() => mockUserService.watchUnlockedActiveAccount,
68+
).thenAnswer((_) => Stream.value(account));
69+
when(
70+
() => mockActiveCampaignObserver.watchCampaign,
71+
).thenAnswer((_) => Stream.value(campaign));
6772

6873
when(
6974
() => mockProposalRepository.watchProposalsCountV2(

0 commit comments

Comments
 (0)