Skip to content

Commit d1786de

Browse files
feat(cat-voices): CatalystIdText with a label (#2634)
* feat: CatalystIdText label * chore: fix tests
1 parent ac04e1f commit d1786de

File tree

13 files changed

+272
-228
lines changed

13 files changed

+272
-228
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ class _AccountHeaderTile extends StatelessWidget {
5353
CatalystIdText(
5454
data,
5555
isCompact: false,
56+
showLabel: true,
57+
labelGap: 4,
58+
labelStyle: context.textTheme.titleSmall,
5659
backgroundColor: context.colors.onSurfaceNeutralOpaqueLv2,
5760
),
5861
],
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import 'package:catalyst_voices/widgets/widgets.dart';
2+
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
3+
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
4+
import 'package:flutter/material.dart';
5+
6+
class SessionAccountCatalystId extends StatelessWidget {
7+
const SessionAccountCatalystId({super.key});
8+
9+
@override
10+
Widget build(BuildContext context) {
11+
return BlocSelector<SessionCubit, SessionState, CatalystId?>(
12+
selector: (state) => state.account?.catalystId,
13+
builder: (context, catalystId) {
14+
if (catalystId == null) {
15+
return const SizedBox.shrink();
16+
}
17+
18+
return CatalystIdText(
19+
catalystId,
20+
isCompact: true,
21+
showLabel: true,
22+
);
23+
},
24+
);
25+
}
26+
}

catalyst_voices/apps/voices/lib/pages/discovery/sections/stay_involved.dart

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@ import 'dart:async';
22

33
import 'package:catalyst_voices/common/constants/constants.dart';
44
import 'package:catalyst_voices/common/ext/build_context_ext.dart';
5-
import 'package:catalyst_voices/widgets/buttons/copy_catalyst_id_button.dart';
6-
import 'package:catalyst_voices/widgets/buttons/voices_filled_button.dart';
7-
import 'package:catalyst_voices/widgets/snackbar/voices_snackbar.dart';
8-
import 'package:catalyst_voices/widgets/snackbar/voices_snackbar_type.dart';
5+
import 'package:catalyst_voices/pages/discovery/sections/session_account_catalyst_id.dart';
96
import 'package:catalyst_voices/widgets/text/voting_start_at_time_text.dart';
7+
import 'package:catalyst_voices/widgets/widgets.dart';
108
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
119
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
1210
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
13-
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
1411
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
1512
import 'package:flutter/material.dart';
16-
import 'package:flutter/services.dart';
1713

1814
class StayInvolved extends StatelessWidget {
1915
const StayInvolved({super.key});
@@ -43,69 +39,55 @@ class StayInvolved extends StatelessWidget {
4339
}
4440
}
4541

46-
class __ReviewerCardState extends State<_ReviewerCard> {
42+
class _Header extends StatelessWidget {
43+
const _Header();
44+
45+
@override
46+
Widget build(BuildContext context) {
47+
return Text(
48+
context.l10n.stayInvolved,
49+
style: context.textTheme.headlineMedium,
50+
);
51+
}
52+
}
53+
54+
class _ReviewerCard extends StatelessWidget {
55+
const _ReviewerCard();
56+
4757
@override
4858
Widget build(BuildContext context) {
4959
return _StayInvolvedCard(
5060
icon: VoicesAssets.icons.clipboardCheck,
5161
title: '${context.l10n.turnOpinionsIntoActions} ${context.l10n.becomeReviewer}!',
5262
description: context.l10n.stayInvolvedReviewerDescription,
63+
additionalInfo: const _CopyCatalystIdTipText(),
5364
actions: Row(
5465
children: [
55-
CopyCatalystIdButton(
56-
onTap: () => _handleCopyCatalystId(context),
57-
),
58-
const SizedBox(height: 4),
5966
_StayInvolvedActionButton(
6067
title: context.l10n.becomeReviewer,
6168
urlString: VoicesConstants.becomeReviewerUrl,
6269
trailing: VoicesAssets.icons.externalLink.buildIcon(),
6370
),
71+
const SizedBox(width: 24),
72+
const SessionAccountCatalystId(),
6473
],
6574
),
6675
);
6776
}
68-
69-
void _copyToClipboard(CatalystId? text) {
70-
unawaited(Clipboard.setData(ClipboardData(text: text.toString())));
71-
}
72-
73-
void _handleCopyCatalystId(BuildContext context) {
74-
final catalystId = context.read<SessionCubit>().state.account?.catalystId;
75-
_copyToClipboard(catalystId);
76-
_showSuccessSnackbar(context);
77-
}
78-
79-
void _showSuccessSnackbar(BuildContext context) {
80-
VoicesSnackBar.hideCurrent(context);
81-
82-
VoicesSnackBar(
83-
type: VoicesSnackBarType.success,
84-
behavior: SnackBarBehavior.floating,
85-
message: context.l10n.copied,
86-
).show(context);
87-
}
8877
}
8978

90-
class _Header extends StatelessWidget {
91-
const _Header();
79+
class _CopyCatalystIdTipText extends StatelessWidget {
80+
const _CopyCatalystIdTipText();
9281

9382
@override
9483
Widget build(BuildContext context) {
95-
return Text(
96-
context.l10n.stayInvolved,
97-
style: context.textTheme.headlineMedium,
84+
return TipText(
85+
context.l10n.tipCopyCatalystIdForReviewTool,
86+
style: context.textTheme.bodyMedium?.copyWith(color: context.colors.textOnPrimaryLevel1),
9887
);
9988
}
10089
}
10190

102-
class _ReviewerCard extends StatefulWidget {
103-
const _ReviewerCard();
104-
105-
@override
106-
State<_ReviewerCard> createState() => __ReviewerCardState();
107-
}
108-
10991
class _StayInvolvedActionButton extends StatelessWidget with LaunchUrlMixin {
11092
final String title;
11193
final String urlString;

catalyst_voices/apps/voices/lib/pages/spaces/appbar/account_popup/session_account_popup_catalyst_id.dart

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@ class SessionAccountPopupCatalystId extends StatelessWidget {
1010
Widget build(BuildContext context) {
1111
return BlocSelector<SessionCubit, SessionState, CatalystId?>(
1212
selector: (state) => state.account?.catalystId,
13-
builder: (context, state) {
14-
if (state == null) {
15-
return const Offstage();
13+
builder: (context, catalystId) {
14+
if (catalystId == null) {
15+
return const SizedBox.shrink();
1616
}
17-
return CatalystIdText(state, isCompact: true);
17+
18+
return CatalystIdText(
19+
catalystId,
20+
isCompact: true,
21+
showLabel: true,
22+
);
1823
},
1924
);
2025
}

catalyst_voices/apps/voices/lib/pages/spaces/drawer/opportunities_drawer.dart

Lines changed: 69 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
1-
import 'dart:async';
2-
31
import 'package:catalyst_voices/common/constants/constants.dart';
42
import 'package:catalyst_voices/common/ext/build_context_ext.dart';
5-
import 'package:catalyst_voices/widgets/buttons/copy_catalyst_id_button.dart';
6-
import 'package:catalyst_voices/widgets/snackbar/voices_snackbar.dart';
7-
import 'package:catalyst_voices/widgets/snackbar/voices_snackbar_type.dart';
3+
import 'package:catalyst_voices/pages/spaces/drawer/session_account_drawer_catalyst_id.dart';
84
import 'package:catalyst_voices/widgets/widgets.dart';
95
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
10-
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
116
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
12-
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
137
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
148
import 'package:flutter/material.dart';
15-
import 'package:flutter/services.dart';
169

1710
class OpportunitiesDrawer extends StatelessWidget {
1811
const OpportunitiesDrawer({super.key});
@@ -57,58 +50,46 @@ class _BecomeReviewerCard extends StatelessWidget with LaunchUrlMixin {
5750
Widget build(BuildContext context) {
5851
return _OpportunityCard(
5952
background: VoicesAssets.images.opportunities.reviewer.path,
60-
child: Padding(
61-
padding: const EdgeInsets.only(
62-
top: 28,
63-
left: 24,
64-
),
65-
child: Column(
66-
mainAxisSize: MainAxisSize.min,
67-
crossAxisAlignment: CrossAxisAlignment.start,
68-
children: [
69-
SizedBox(
70-
width: 198,
71-
child: Text(
72-
context.l10n.turnOpinionsIntoActions,
73-
style: context.textTheme.headlineMedium?.copyWith(
74-
color: context.colorScheme.primary,
75-
),
76-
),
77-
),
78-
const SizedBox(height: 15),
79-
CopyCatalystIdButton(onTap: () => _handleCopyCatalystId(context)),
80-
const SizedBox(height: 4),
81-
_OpportunityActionButton(
82-
onTap: () async {
83-
await launchUri(VoicesConstants.becomeReviewerUrl.getUri());
84-
},
85-
title: context.l10n.becomeReviewer,
86-
trailing: VoicesAssets.icons.externalLink.buildIcon(),
53+
widthFactor: 0.6,
54+
alignment: Alignment.centerLeft,
55+
child: Column(
56+
mainAxisSize: MainAxisSize.min,
57+
crossAxisAlignment: CrossAxisAlignment.stretch,
58+
children: [
59+
Text(
60+
context.l10n.turnOpinionsIntoActions,
61+
style: context.textTheme.headlineMedium?.copyWith(
62+
color: context.colorScheme.primary,
63+
height: 1,
8764
),
88-
],
89-
),
65+
),
66+
const SizedBox(height: 16),
67+
const _CopyCatalystIdTipText(),
68+
const SizedBox(height: 16),
69+
const SessionAccountDrawerCatalystId(),
70+
const SizedBox(height: 20),
71+
_OpportunityActionButton(
72+
onTap: () async {
73+
await launchUri(VoicesConstants.becomeReviewerUrl.getUri());
74+
},
75+
title: context.l10n.becomeReviewer,
76+
trailing: VoicesAssets.icons.externalLink.buildIcon(),
77+
),
78+
],
9079
),
9180
);
9281
}
82+
}
9383

94-
void _copyToClipboard(CatalystId? text) {
95-
unawaited(Clipboard.setData(ClipboardData(text: text.toString())));
96-
}
97-
98-
void _handleCopyCatalystId(BuildContext context) {
99-
final catalystId = context.read<SessionCubit>().state.account?.catalystId;
100-
_copyToClipboard(catalystId);
101-
_showSuccessSnackbar(context);
102-
}
103-
104-
void _showSuccessSnackbar(BuildContext context) {
105-
VoicesSnackBar.hideCurrent(context);
84+
class _CopyCatalystIdTipText extends StatelessWidget {
85+
const _CopyCatalystIdTipText();
10686

107-
VoicesSnackBar(
108-
type: VoicesSnackBarType.success,
109-
behavior: SnackBarBehavior.floating,
110-
message: context.l10n.copied,
111-
).show(context);
87+
@override
88+
Widget build(BuildContext context) {
89+
return TipText(
90+
context.l10n.tipCopyCatalystIdForReviewTool,
91+
style: context.textTheme.bodyMedium?.copyWith(color: context.colors.textOnPrimaryLevel1),
92+
);
11293
}
11394
}
11495

@@ -167,25 +148,33 @@ class _OpportunityActionButton extends StatelessWidget {
167148

168149
class _OpportunityCard extends StatelessWidget {
169150
final String background;
151+
final double widthFactor;
152+
final Alignment alignment;
170153
final Widget child;
171154

172155
const _OpportunityCard({
173156
required this.background,
157+
required this.widthFactor,
158+
required this.alignment,
174159
required this.child,
175160
});
176161

177162
@override
178163
Widget build(BuildContext context) {
179164
return Container(
180-
constraints: BoxConstraints.tight(const Size(426, 260)),
181165
decoration: BoxDecoration(
182166
borderRadius: BorderRadius.circular(16),
183167
image: DecorationImage(
184168
image: CatalystImage.asset(background).image,
185169
fit: BoxFit.cover,
186170
),
187171
),
188-
child: child,
172+
padding: const EdgeInsets.symmetric(vertical: 28, horizontal: 24),
173+
alignment: alignment,
174+
child: FractionallySizedBox(
175+
widthFactor: widthFactor,
176+
child: child,
177+
),
189178
);
190179
}
191180
}
@@ -197,39 +186,32 @@ class _RegisterAsVoter extends StatelessWidget with LaunchUrlMixin {
197186
Widget build(BuildContext context) {
198187
return _OpportunityCard(
199188
background: VoicesAssets.images.opportunities.voter.path,
200-
child: Align(
201-
alignment: Alignment.topRight,
202-
child: Padding(
203-
padding: const EdgeInsets.only(
204-
top: 44,
205-
right: 24,
189+
widthFactor: 0.55,
190+
alignment: Alignment.centerRight,
191+
child: Column(
192+
mainAxisSize: MainAxisSize.min,
193+
crossAxisAlignment: CrossAxisAlignment.stretch,
194+
children: [
195+
const SizedBox(height: 16),
196+
Text(
197+
context.l10n.f14Voting,
198+
style: context.textTheme.headlineMedium?.copyWith(
199+
color: context.colorScheme.primary,
200+
height: 1,
201+
),
206202
),
207-
child: Column(
208-
mainAxisSize: MainAxisSize.min,
209-
crossAxisAlignment: CrossAxisAlignment.start,
210-
children: [
211-
SizedBox(
212-
width: 198,
213-
child: Text(
214-
context.l10n.f14Voting,
215-
style: context.textTheme.headlineMedium?.copyWith(
216-
color: context.colorScheme.primary,
217-
),
218-
),
219-
),
220-
const SizedBox(height: 20),
221-
_OpportunityActionButton(
222-
onTap: () async {
223-
await launchUri(
224-
VoicesConstants.votingRegistrationUrl.getUri(),
225-
);
226-
},
227-
title: context.l10n.votingRegistration,
228-
trailing: VoicesAssets.icons.externalLink.buildIcon(),
229-
),
230-
],
203+
const SizedBox(height: 28),
204+
_OpportunityActionButton(
205+
onTap: () async {
206+
await launchUri(
207+
VoicesConstants.votingRegistrationUrl.getUri(),
208+
);
209+
},
210+
title: context.l10n.votingRegistration,
211+
trailing: VoicesAssets.icons.externalLink.buildIcon(),
231212
),
232-
),
213+
const SizedBox(height: 16),
214+
],
233215
),
234216
);
235217
}

0 commit comments

Comments
 (0)