Skip to content

Commit c3f9de0

Browse files
bstolinskidt-iohkemiride
authored
feat(cat-voices): feature flags (#3706)
* feat(cat-voices): Feature flags system (#3615) * feat: implement feature flags system * refactor: Use enum for feature flag names * refactor * refactor * add tests * update README.md * refactor * refactor * change class name `Feature` to `FeatureFlag` * feat(cat-voices): Dev tools feature flags (#3624) * feat: implement feature flags system * refactor: Use enum for feature flag names * refactor * refactor * add tests * update README.md * refactor * feat: Add feature flags card in DevToolsPage * refactor cubit * feat(cat-voices): voting feature flag (#3657) * feat: implement feature flags system * refactor: Use enum for feature flag names * refactor * refactor * add tests * update README.md * refactor * feat: Add feature flags card in DevToolsPage * refactor cubit * feat: hide part of the voting logic and the page behind the feature flag * fix fests * Update catalyst_voices/apps/voices/lib/pages/account/account_page.dart Co-authored-by: Dominik Toton <[email protected]> * refactor * refactor --------- Co-authored-by: Dominik Toton <[email protected]> * refactor * refactor * refactor --------- Co-authored-by: Dominik Toton <[email protected]> Co-authored-by: Emir Hodzic <[email protected]>
1 parent f2b71f9 commit c3f9de0

File tree

41 files changed

+1347
-26
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1347
-26
lines changed

catalyst_voices/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ This repository contains the Catalyst Voices app and packages.
1515
* [Flavor types](#flavor-types)
1616
* [Environment variables](#environment-variables)
1717
* [Environment config](#environment-config)
18+
* [Feature Flags](#feature-flags)
19+
* [Using Feature Flags with --dart-define](#using-feature-flags-with---dart-define)
1820
* [Code Generation](#code-generation)
1921
* [Running Code Generation](#running-code-generation)
2022
* [Basic Generation](#basic-generation)
@@ -180,6 +182,26 @@ flutter build web --target apps/voices/lib/configs/main_web.dart
180182
Configuration is downloaded dynamically from **gateway** backend where **gateway** base url depends
181183
on used env type.
182184

185+
### Feature Flags
186+
187+
Feature flags allow you to enable or disable specific features at compile-time or runtime.
188+
The feature flag system provides flexible configuration through multiple sources.
189+
190+
All feature flags can be found in the [Features](./packages/internal/catalyst_voices_models/lib/src/feature_flags/features.dart)
191+
class.
192+
193+
#### Using Feature Flags with --dart-define
194+
195+
You can control features at compile-time using `--dart-define` parameters:
196+
197+
```sh
198+
# Enable voting feature
199+
flutter run --dart-define=FEATURE_VOTING=true
200+
201+
# Disable voting feature
202+
flutter run --dart-define=FEATURE_VOTING=false
203+
```
204+
183205
### Code Generation
184206

185207
This project utilizes automatic code generation for the following components:

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ class _AppState extends State<App> {
8585
BlocProvider<VotingBallotBloc>(
8686
create: (_) => Dependencies.instance.get<VotingBallotBloc>(),
8787
),
88+
BlocProvider<FeatureFlagsCubit>(
89+
create: (_) => Dependencies.instance.get<FeatureFlagsCubit>(),
90+
),
8891
];
8992
}
9093
}

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ final class Dependencies extends DependencyProvider {
9494
get<RegistrationProgressNotifier>(),
9595
get<AccessControl>(),
9696
get<AdminTools>(),
97+
get<FeatureFlagsService>(),
9798
);
9899
},
99100
dispose: (cubit) async => cubit.close(),
@@ -114,6 +115,7 @@ final class Dependencies extends DependencyProvider {
114115
get<UserService>(),
115116
get<CampaignService>(),
116117
get<ProposalService>(),
118+
get<FeatureFlagsService>(),
117119
),
118120
)
119121
..registerLazySingleton<VotingCubit>(
@@ -151,6 +153,7 @@ final class Dependencies extends DependencyProvider {
151153
return DiscoveryCubit(
152154
get<CampaignService>(),
153155
get<ProposalService>(),
156+
get<FeatureFlagsService>(),
154157
);
155158
})
156159
..registerFactory<CategoryDetailCubit>(() {
@@ -170,6 +173,7 @@ final class Dependencies extends DependencyProvider {
170173
get<DocumentMapper>(),
171174
get<VotingBallotBuilder>(),
172175
get<VotingService>(),
176+
get<FeatureFlagsService>(),
173177
);
174178
})
175179
..registerFactory<NewProposalCubit>(() {
@@ -207,6 +211,11 @@ final class Dependencies extends DependencyProvider {
207211
get<VotingBallotBuilder>(),
208212
get<VotingService>(),
209213
);
214+
})
215+
..registerFactory<FeatureFlagsCubit>(() {
216+
return FeatureFlagsCubit(
217+
get<FeatureFlagsService>(),
218+
);
210219
});
211220
}
212221

@@ -302,6 +311,12 @@ final class Dependencies extends DependencyProvider {
302311
() => SystemStatusRepository(
303312
get<ApiServices>(),
304313
),
314+
)
315+
..registerLazySingleton<FeatureFlagsRepository>(
316+
() => FeatureFlagsRepository(
317+
get<AppEnvironment>().type,
318+
get<AppConfig>(),
319+
),
305320
);
306321
}
307322

@@ -438,6 +453,14 @@ final class Dependencies extends DependencyProvider {
438453
},
439454
dispose: (mediator) => mediator.dispose(),
440455
);
456+
registerLazySingleton<FeatureFlagsService>(
457+
() {
458+
return FeatureFlagsService(
459+
get<FeatureFlagsRepository>(),
460+
);
461+
},
462+
dispose: (service) => unawaited(service.dispose()),
463+
);
441464
}
442465

443466
void _registerStorages() {

catalyst_voices/apps/voices/lib/pages/account/account_page.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,21 @@ class _AccountPageState extends State<AccountPage>
123123
switch (phaseType) {
124124
case CampaignPhaseType.communityReview:
125125
case CampaignPhaseType.communityVoting:
126-
const VotingRoute($extra: true).go(context);
126+
final isVotingEnabled = context.read<FeatureFlagsCubit>().state.isEnabled(
127+
Features.voting,
128+
);
129+
if (isVotingEnabled) {
130+
const VotingRoute.keychainDeleted().go(context);
131+
} else {
132+
const DiscoveryRoute.keychainDeleted().go(context);
133+
}
127134
case null:
128135
case CampaignPhaseType.proposalSubmission:
129136
case CampaignPhaseType.votingRegistration:
130137
case CampaignPhaseType.reviewRegistration:
131138
case CampaignPhaseType.votingResults:
132139
case CampaignPhaseType.projectOnboarding:
133-
const DiscoveryRoute($extra: true).go(context);
140+
const DiscoveryRoute.keychainDeleted().go(context);
134141
}
135142
}
136143
}

catalyst_voices/apps/voices/lib/pages/account/widgets/account_keychain_tile.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,14 @@ class _AccountKeychainTileState extends State<AccountKeychainTile> {
9494
switch (phaseType) {
9595
case CampaignPhaseType.communityReview:
9696
case CampaignPhaseType.communityVoting:
97-
const VotingRoute($extra: true).go(context);
97+
const VotingRoute.keychainDeleted().go(context);
9898
case null:
9999
case CampaignPhaseType.proposalSubmission:
100100
case CampaignPhaseType.votingRegistration:
101101
case CampaignPhaseType.reviewRegistration:
102102
case CampaignPhaseType.votingResults:
103103
case CampaignPhaseType.projectOnboarding:
104-
const DiscoveryRoute($extra: true).go(context);
104+
const DiscoveryRoute.keychainDeleted().go(context);
105105
}
106106
}
107107
}

catalyst_voices/apps/voices/lib/pages/campaign/admin_tools/campaign_admin_tools_dialog.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ class _BlocFooter extends StatelessWidget {
127127
// since the user can't change it to anything else
128128
offstage: spaces.length <= 1,
129129
child: _Footer(
130+
spaces: spaces,
130131
selectedSpace: selectedSpace,
131132
onSpaceSelected: onSpaceSelected,
132133
),
@@ -208,10 +209,12 @@ class _DraggableCampaignAdminToolsDialogState extends State<DraggableCampaignAdm
208209
}
209210

210211
class _Footer extends StatelessWidget {
212+
final List<Space> spaces;
211213
final Space selectedSpace;
212214
final ValueChanged<Space> onSpaceSelected;
213215

214216
const _Footer({
217+
required this.spaces,
215218
required this.selectedSpace,
216219
required this.onSpaceSelected,
217220
});
@@ -231,7 +234,7 @@ class _Footer extends StatelessWidget {
231234
child: Row(
232235
mainAxisAlignment: MainAxisAlignment.center,
233236
children: <Widget>[
234-
for (final space in Space.values)
237+
for (final space in spaces)
235238
_SpaceItem(
236239
space: space,
237240
isActive: space == selectedSpace,

0 commit comments

Comments
 (0)