Skip to content

Commit 2a8547a

Browse files
feat(cat-voices): proposals query filtering (#3641)
* docs: capture initial times * chore: remove cacheDocument * turn off logging * chore: use debugPrint instead of logger * feat: bulk documents save * batching sync * chore: move exact ref resoling to getDocumentData instead of index * fix: DocumentRepository * chore: simplify getting documents data * remove getAllDocumentsRefs and getCachedDocumentsRefs from DocumentRepository. Index is only available in DocumentDataRemoteSource * chore: update docs * simplified document index endpoint * remove randomness from LocalCatGateway * indexing by batch size * wip: filtering by types * Rework filtering refs + checking all refs if already cached in parallel * docs * update indexing.csv * update indexing csv * chore: cleanup * trailing new line * chore * move performance tab to docs * bulk saving typed docs in parallel * chore: revert hardcoded timestamp * chore: typos * split _sync into smaller functions + add documentation * little refactor * fix: analyzer * initial v2 tables * wip * wip * feat: database migration * chore: cleanup * bump batch size * cleanup * chore: remove defensive content decoding * chore: daos * spelling * saveAll * test on platform * chore: update build scripts * feat: DocumentsV2Dao methods * simple proposals pagination query * chore: create a JoinedProposalBriefEntity * rename method * feat: exclude hidden proposals * more tests * renaming and splitting logic into smaller parts * feat: per language strategy * remove CatalystDatabaseLanguage in favor of raw queries as they are easier to mange * remove Index Strategy Documentation * handle case where ref is empty * migration now includes indexes * use v2 documents table for saveAll and isCachedBulk * adds ActionType to JoinedProposalBriefEntity * adds versionIds to JoinedProposalBriefEntity * comments count * adds isFavorite to JoinedProposalBriefEntity * add template to JoinedProposalBriefEntity * adds documentsLocalMetadata table for auto updates * Update docs * use v2 proposals query for discovery most recent section * feat: simplify most recent proposals section * add proposal fav status for v2 tables * local proposal fav status update * update fav state locally for faster feedback * self review * fix tests * update times * fix: analyzer * more migration test data * clean up constructors * cleanup * fix: template tests * spelling * fix: spelling * chore: PR review adjustments * add order parameter * ProposalsOrder docs * GetProposalsBriefPage supports order * add filters object * proposalsBriefPage filtering * fix: status filtering * more draft proposals filtering tests * Campaign proposals filter * update docs * expose getVisibleProposalsCount and tests * expose filters parameter * integrate proposals page with v2 queries * chore: increase time diff between proposals * chore: reduce count query tables watched when not needed * local proposals cubit * local proposal fav staus update * docs * fix: add discovery specific colors (#3637) * fix code-generator earthly target * use logger in migration + wrap in transaction * spelling * rename category to categoryId for better consistency * proposals per tab selector * release completed in close * extract early return logic into function --------- Co-authored-by: Ryszard Schossler <[email protected]>
1 parent a91871d commit 2a8547a

File tree

22 files changed

+3202
-406
lines changed

22 files changed

+3202
-406
lines changed

catalyst_voices/apps/voices/lib/app/view/app.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@ class _AppState extends State<App> {
4747
BlocProvider<SessionCubit>(
4848
create: (_) => Dependencies.instance.get<SessionCubit>(),
4949
),
50-
BlocProvider<ProposalsCubit>(
51-
create: (_) => Dependencies.instance.get<ProposalsCubit>(),
52-
),
5350
BlocProvider<VotingCubit>(
5451
create: (_) => Dependencies.instance.get<VotingCubit>(),
5552
),

catalyst_voices/apps/voices/lib/dependency/dependencies.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ final class Dependencies extends DependencyProvider {
113113
blockchainConfig: get<AppConfig>().blockchain,
114114
);
115115
})
116-
..registerLazySingleton<ProposalsCubit>(
116+
..registerFactory<ProposalsCubit>(
117117
() => ProposalsCubit(
118118
get<UserService>(),
119119
get<CampaignService>(),

catalyst_voices/apps/voices/lib/pages/proposals/proposals_page.dart

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:async';
22

33
import 'package:catalyst_voices/common/error_handler.dart';
44
import 'package:catalyst_voices/common/signal_handler.dart';
5+
import 'package:catalyst_voices/dependency/dependencies.dart';
56
import 'package:catalyst_voices/pages/campaign_phase_aware/proposal_submission_phase_aware.dart';
67
import 'package:catalyst_voices/pages/proposals/widgets/proposals_content.dart';
78
import 'package:catalyst_voices/pages/proposals/widgets/proposals_header.dart';
@@ -17,7 +18,7 @@ import 'package:flutter/material.dart';
1718
import 'package:rxdart/rxdart.dart';
1819

1920
class ProposalsPage extends StatefulWidget {
20-
final SignedDocumentRef? categoryId;
21+
final String? categoryId;
2122
final ProposalsPageTab? tab;
2223

2324
const ProposalsPage({
@@ -35,18 +36,28 @@ class _ProposalsPageState extends State<ProposalsPage>
3536
TickerProviderStateMixin,
3637
ErrorHandlerStateMixin<ProposalsCubit, ProposalsPage>,
3738
SignalHandlerStateMixin<ProposalsCubit, ProposalsSignal, ProposalsPage> {
39+
late final _cubit = Dependencies.instance.get<ProposalsCubit>();
3840
late VoicesTabController<ProposalsPageTab> _tabController;
3941
late final PagingController<ProposalBrief> _pagingController;
4042
late final StreamSubscription<List<ProposalsPageTab>> _tabsSubscription;
4143

44+
@override
45+
ProposalsCubit get errorEmitter => _cubit;
46+
47+
@override
48+
ProposalsCubit get signalEmitter => _cubit;
49+
4250
@override
4351
Widget build(BuildContext context) {
44-
return ProposalSubmissionPhaseAware(
45-
activeChild: HeaderAndContentLayout(
46-
header: const ProposalsHeader(),
47-
content: ProposalsContent(
48-
tabController: _tabController,
49-
pagingController: _pagingController,
52+
return BlocProvider.value(
53+
value: _cubit,
54+
child: ProposalSubmissionPhaseAware(
55+
activeChild: HeaderAndContentLayout(
56+
header: const ProposalsHeader(),
57+
content: ProposalsContent(
58+
tabController: _tabController,
59+
pagingController: _pagingController,
60+
),
5061
),
5162
),
5263
);
@@ -59,10 +70,9 @@ class _ProposalsPageState extends State<ProposalsPage>
5970
final tab = widget.tab ?? ProposalsPageTab.total;
6071

6172
if (widget.categoryId != oldWidget.categoryId || widget.tab != oldWidget.tab) {
62-
context.read<ProposalsCubit>().changeFilters(
63-
onlyMy: Optional(tab == ProposalsPageTab.my),
64-
category: Optional(widget.categoryId),
65-
type: tab.filter,
73+
_cubit.changeFilters(
74+
categoryId: Optional(widget.categoryId),
75+
tab: Optional(tab),
6676
);
6777

6878
_doResetPagination();
@@ -75,6 +85,7 @@ class _ProposalsPageState extends State<ProposalsPage>
7585

7686
@override
7787
void dispose() {
88+
unawaited(_cubit.close());
7889
_tabController.dispose();
7990
_pagingController.dispose();
8091
unawaited(_tabsSubscription.cancel());
@@ -105,9 +116,8 @@ class _ProposalsPageState extends State<ProposalsPage>
105116
void initState() {
106117
super.initState();
107118

108-
final proposalsCubit = context.read<ProposalsCubit>();
109119
final sessionCubit = context.read<SessionCubit>();
110-
final supportedTabs = _determineTabs(sessionCubit.state.isProposerUnlock, proposalsCubit.state);
120+
final supportedTabs = _determineTabs(sessionCubit.state.isProposerUnlock, _cubit.state);
111121
final selectedTab = _determineTab(supportedTabs, widget.tab);
112122

113123
_tabController = VoicesTabController(
@@ -123,15 +133,13 @@ class _ProposalsPageState extends State<ProposalsPage>
123133

124134
_tabsSubscription = Rx.combineLatest2(
125135
sessionCubit.watchState().map((e) => e.isProposerUnlock),
126-
proposalsCubit.watchState(),
136+
_cubit.watchState(),
127137
_determineTabs,
128138
).distinct().listen(_updateTabsIfNeeded);
129139

130-
proposalsCubit.init(
131-
onlyMyProposals: selectedTab == ProposalsPageTab.my,
132-
category: widget.categoryId,
133-
type: selectedTab.filter,
134-
order: const Alphabetical(),
140+
_cubit.init(
141+
categoryId: widget.categoryId,
142+
tab: widget.tab ?? ProposalsPageTab.total,
135143
);
136144

137145
_pagingController
@@ -167,15 +175,15 @@ class _ProposalsPageState extends State<ProposalsPage>
167175
ProposalBrief? lastProposalId,
168176
) async {
169177
final request = PageRequest(page: pageKey, size: pageSize);
170-
await context.read<ProposalsCubit>().getProposals(request);
178+
await _cubit.getProposals(request);
171179
}
172180

173181
void _updateRoute({
174182
Optional<String>? categoryId,
175183
ProposalsPageTab? tab,
176184
}) {
177185
Router.neglect(context, () {
178-
final effectiveCategoryId = categoryId.dataOr(widget.categoryId?.id);
186+
final effectiveCategoryId = categoryId.dataOr(widget.categoryId);
179187
final effectiveTab = tab?.name ?? widget.tab?.name;
180188

181189
ProposalsRoute(

catalyst_voices/apps/voices/lib/pages/proposals/widgets/proposals_pagination_tile.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ class ProposalsPaginationTile extends StatelessWidget {
2424
unawaited(route.push(context));
2525
},
2626
onFavoriteChanged: (isFavorite) {
27-
context.read<ProposalsCubit>().onChangeFavoriteProposal(
28-
proposal.selfRef,
29-
isFavorite: isFavorite,
27+
unawaited(
28+
context.read<ProposalsCubit>().onChangeFavoriteProposal(
29+
proposal.selfRef,
30+
isFavorite: isFavorite,
31+
),
3032
);
3133
},
3234
);

catalyst_voices/apps/voices/lib/pages/proposals/widgets/proposals_tabs.dart

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import 'package:catalyst_voices/widgets/tabbar/voices_tab_bar.dart';
33
import 'package:catalyst_voices/widgets/tabbar/voices_tab_controller.dart';
44
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
55
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
6-
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
76
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
87
import 'package:flutter/material.dart';
98

@@ -15,29 +14,6 @@ class ProposalsTabs extends StatelessWidget {
1514
required this.controller,
1615
});
1716

18-
@override
19-
Widget build(BuildContext context) {
20-
return BlocSelector<ProposalsCubit, ProposalsState, ProposalsCount>(
21-
selector: (state) => state.count,
22-
builder: (context, state) {
23-
return _ProposalsTabs(
24-
data: state,
25-
controller: controller,
26-
);
27-
},
28-
);
29-
}
30-
}
31-
32-
class _ProposalsTabs extends StatelessWidget {
33-
final ProposalsCount data;
34-
final VoicesTabController<ProposalsPageTab> controller;
35-
36-
const _ProposalsTabs({
37-
required this.data,
38-
required this.controller,
39-
});
40-
4117
@override
4218
Widget build(BuildContext context) {
4319
return VoicesTabBar(
@@ -51,13 +27,30 @@ class _ProposalsTabs extends StatelessWidget {
5127
VoicesTab(
5228
data: tab,
5329
key: tab.tabKey(),
54-
child: VoicesTabText(tab.noOf(context, count: data.ofType(tab.filter))),
30+
child: _TabText(key: ValueKey('${tab.name}Text'), tab: tab),
5531
),
5632
],
5733
);
5834
}
5935
}
6036

37+
class _TabText extends StatelessWidget {
38+
final ProposalsPageTab tab;
39+
40+
const _TabText({
41+
required super.key,
42+
required this.tab,
43+
});
44+
45+
@override
46+
Widget build(BuildContext context) {
47+
return BlocSelector<ProposalsCubit, ProposalsState, int>(
48+
selector: (state) => state.count[tab] ?? 0,
49+
builder: (context, state) => VoicesTabText(tab.noOf(context, count: state)),
50+
);
51+
}
52+
}
53+
6154
extension on ProposalsPageTab {
6255
String noOf(
6356
BuildContext context, {

catalyst_voices/apps/voices/lib/routes/routing/spaces_route.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,10 @@ final class ProposalsRoute extends GoRouteData with FadePageTransitionMixin {
8484

8585
@override
8686
Widget build(BuildContext context, GoRouterState state) {
87-
final categoryId = this.categoryId;
88-
final categoryRef = categoryId != null ? SignedDocumentRef(id: categoryId) : null;
89-
9087
final tab = ProposalsPageTab.values.asNameMap()[this.tab];
9188

9289
return ProposalsPage(
93-
categoryId: categoryRef,
90+
categoryId: categoryId,
9491
tab: tab,
9592
);
9693
}

catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/discovery/discovery_cubit.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ class DiscoveryCubit extends Cubit<DiscoveryState> with BlocErrorEmitterMixin {
161161
unawaited(_proposalsV2Sub?.cancel());
162162

163163
_proposalsV2Sub = _proposalService
164-
.watchProposalsBriefPage(
164+
.watchProposalsBriefPageV2(
165165
request: const PageRequest(page: 0, size: _maxRecentProposalsCount),
166166
)
167167
.map((page) => page.items)

0 commit comments

Comments
 (0)