Skip to content

Commit e21d737

Browse files
authored
chore(cat-voices): Ui changes in workspace page/ disable stream when user is not login (#2173)
* feat: if user is not proposer close user proposal stream * refactor(campaign-timeline): simplify gradient and cleanup event handlers in timeline components * fix: unused comment * fix(campaign-timeline-test): adjust card height for consistent rendering in tests (#2181) * fix(campaign-timeline): unify workspace colors for ongoing campaigns in campaign timeline card
1 parent 1894823 commit e21d737

File tree

9 files changed

+145
-219
lines changed

9 files changed

+145
-219
lines changed

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ class StayInvolved extends StatelessWidget {
2424
padding: EdgeInsets.symmetric(horizontal: 120, vertical: 72),
2525
child: Column(
2626
mainAxisSize: MainAxisSize.min,
27-
crossAxisAlignment: CrossAxisAlignment.start,
27+
crossAxisAlignment: CrossAxisAlignment.stretch,
2828
children: [
2929
_Header(),
3030
SizedBox(height: 24),
3131
Wrap(
32+
alignment: WrapAlignment.center,
3233
spacing: 16,
3334
runSpacing: 16,
3435
children: [
@@ -157,13 +158,18 @@ class _StayInvolvedCard extends StatelessWidget {
157158
padding: const EdgeInsets.symmetric(horizontal: 32),
158159
decoration: BoxDecoration(
159160
borderRadius: BorderRadius.circular(12),
160-
gradient: const LinearGradient(
161+
gradient: LinearGradient(
161162
begin: Alignment.topCenter,
162163
end: Alignment.bottomCenter,
163-
colors: [
164-
Color(0xFFD1EAFF),
165-
Color(0xFFCAD6FE),
166-
],
164+
colors: Theme.of(context).brightness == Brightness.light
165+
? [
166+
const Color(0xFFD1EAFF),
167+
const Color(0xFFCAD6FE),
168+
]
169+
: [
170+
const Color(0xFF2D3953),
171+
const Color(0xFF242C42),
172+
],
167173
),
168174
),
169175
child: Column(

catalyst_voices/apps/voices/lib/pages/workspace/header/workspace_header.dart

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ class _ViewComments extends StatelessWidget {
105105
}
106106

107107
class _WorkspaceHeaderState extends State<WorkspaceHeader> {
108-
bool _isTimelineExpanded = false;
109108
bool _isTimelineVisible = true;
110109

111110
@override
@@ -153,7 +152,6 @@ class _WorkspaceHeaderState extends State<WorkspaceHeader> {
153152
const _ViewComments(),
154153
Expanded(
155154
child: Container(
156-
height: _isTimelineExpanded ? 340 : 190,
157155
padding: const EdgeInsets.all(16),
158156
decoration: BoxDecoration(
159157
color: theme.colorScheme.surface,
@@ -171,11 +169,6 @@ class _WorkspaceHeaderState extends State<WorkspaceHeader> {
171169
return CampaignTimeline(
172170
timelineItems: timelineItems,
173171
placement: CampaignTimelinePlacement.workspace,
174-
onExpandedChanged: (isExpanded) {
175-
setState(() {
176-
_isTimelineExpanded = isExpanded;
177-
});
178-
},
179172
);
180173
},
181174
),
@@ -193,9 +186,6 @@ class _WorkspaceHeaderState extends State<WorkspaceHeader> {
193186
void _toggleTimelineVisibility() {
194187
setState(() {
195188
_isTimelineVisible = !_isTimelineVisible;
196-
if (!_isTimelineVisible) {
197-
_isTimelineExpanded = false;
198-
}
199189
});
200190
}
201191
}

catalyst_voices/apps/voices/lib/widgets/campaign_timeline/campaign_timeline.dart

Lines changed: 21 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@ import 'package:flutter/material.dart';
55
class CampaignTimeline extends StatefulWidget {
66
final List<CampaignTimelineViewModel> timelineItems;
77
final CampaignTimelinePlacement placement;
8-
final ValueChanged<bool>? onExpandedChanged;
98
final SizedBox horizontalPadding;
109

1110
const CampaignTimeline({
1211
super.key,
1312
required this.timelineItems,
1413
required this.placement,
15-
this.onExpandedChanged,
1614
this.horizontalPadding = const SizedBox.shrink(),
1715
});
1816

@@ -22,40 +20,31 @@ class CampaignTimeline extends StatefulWidget {
2220

2321
class CampaignTimelineState extends State<CampaignTimeline> {
2422
final _scrollController = ScrollController();
25-
final Set<int> _expandedIndices = {};
2623

2724
@override
2825
Widget build(BuildContext context) {
29-
return MouseRegion(
30-
cursor: SystemMouseCursors.click,
31-
child: SizedBox(
32-
height: _expandedIndices.isNotEmpty ? 300 : 150,
33-
child: GestureDetector(
34-
onHorizontalDragUpdate: _handleHorizontalScroll,
35-
// Why not ListView? It forces children to full height
36-
// (parent constraint).The SingleChildScrollView+Row
37-
// reserves natural card heights from content.
38-
child: SingleChildScrollView(
39-
controller: _scrollController,
40-
physics: const BouncingScrollPhysics(),
41-
scrollDirection: Axis.horizontal,
42-
child: Row(
43-
mainAxisSize: MainAxisSize.min,
44-
crossAxisAlignment: CrossAxisAlignment.start,
45-
children: [
46-
widget.horizontalPadding,
47-
...widget.timelineItems.asMap().entries.map(
48-
(entry) => CampaignTimelineCard(
49-
timelineItem: entry.value,
50-
placement: widget.placement,
51-
onExpandedChanged: (isExpanded) {
52-
_onCardExpanded(isExpanded, entry);
53-
},
54-
),
26+
return GestureDetector(
27+
onHorizontalDragUpdate: _handleHorizontalScroll,
28+
behavior: HitTestBehavior.translucent,
29+
child: MouseRegion(
30+
cursor: SystemMouseCursors.click,
31+
child: SingleChildScrollView(
32+
scrollDirection: Axis.horizontal,
33+
controller: _scrollController,
34+
physics: const BouncingScrollPhysics(),
35+
child: Row(
36+
mainAxisSize: MainAxisSize.min,
37+
crossAxisAlignment: CrossAxisAlignment.start,
38+
children: [
39+
widget.horizontalPadding,
40+
...widget.timelineItems.asMap().entries.map(
41+
(entry) => CampaignTimelineCard(
42+
timelineItem: entry.value,
43+
placement: widget.placement,
5544
),
56-
widget.horizontalPadding,
57-
],
58-
),
45+
),
46+
widget.horizontalPadding,
47+
],
5948
),
6049
),
6150
),
@@ -83,18 +72,4 @@ class CampaignTimelineState extends State<CampaignTimeline> {
8372
_scrollController.offset - details.delta.dx,
8473
);
8574
}
86-
87-
void _onCardExpanded(
88-
bool isExpanded,
89-
MapEntry<int, CampaignTimelineViewModel> entry,
90-
) {
91-
setState(() {
92-
if (isExpanded) {
93-
_expandedIndices.add(entry.key);
94-
} else {
95-
_expandedIndices.remove(entry.key);
96-
}
97-
});
98-
widget.onExpandedChanged?.call(_expandedIndices.isNotEmpty);
99-
}
10075
}

catalyst_voices/apps/voices/lib/widgets/campaign_timeline/campaign_timeline_card.dart

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@ import 'package:flutter/material.dart';
1010
class CampaignTimelineCard extends StatefulWidget {
1111
final CampaignTimelineViewModel timelineItem;
1212
final CampaignTimelinePlacement placement;
13-
final ValueChanged<bool>? onExpandedChanged;
1413

1514
const CampaignTimelineCard({
1615
super.key,
1716
required this.timelineItem,
1817
required this.placement,
19-
this.onExpandedChanged,
2018
});
2119

2220
@override
@@ -37,17 +35,18 @@ class CampaignTimelineCardState extends State<CampaignTimelineCard> {
3735

3836
return GestureDetector(
3937
onTap: _toggleExpanded,
40-
child: SizedBox(
38+
behavior: HitTestBehavior.opaque,
39+
child: Container(
40+
constraints: const BoxConstraints(minHeight: 150),
4141
width: 288,
42-
height: _isExpanded ? 300 : 150,
4342
child: Card(
4443
key: const Key('TimelineCard'),
4544
color:
4645
widget.placement.backgroundColor(context, isOngoing: _isOngoing),
4746
shape: OutlineInputBorder(
48-
borderSide: BorderSide(
49-
color: _isOngoing ? colors.primary : Colors.white,
50-
width: _isOngoing ? 2 : 1,
47+
borderSide: widget.placement.borderSide(
48+
context,
49+
isOngoing: _isOngoing,
5150
),
5251
borderRadius: BorderRadius.circular(8),
5352
),
@@ -78,42 +77,40 @@ class CampaignTimelineCardState extends State<CampaignTimelineCard> {
7877
maxLines: 1,
7978
overflow: TextOverflow.ellipsis,
8079
),
81-
Expanded(
82-
child: Row(
83-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
84-
children: [
85-
Expanded(
86-
child: Text(
87-
key: const Key('TimelineCardDate'),
88-
DateFormatter.formatDateRange(
89-
MaterialLocalizations.of(context),
90-
context.l10n,
91-
widget.timelineItem.timeline,
92-
),
93-
style: context.textTheme.bodyMedium?.copyWith(
94-
color: context.colors.sysColorsNeutralN60,
95-
),
96-
maxLines: 1,
97-
overflow: TextOverflow.ellipsis,
80+
Row(
81+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
82+
children: [
83+
Expanded(
84+
child: Text(
85+
key: const Key('TimelineCardDate'),
86+
DateFormatter.formatDateRange(
87+
MaterialLocalizations.of(context),
88+
context.l10n,
89+
widget.timelineItem.timeline,
90+
),
91+
style: context.textTheme.bodyMedium?.copyWith(
92+
color: context.colors.sysColorsNeutralN60,
9893
),
94+
maxLines: 1,
95+
overflow: TextOverflow.ellipsis,
9996
),
100-
if (_isOngoing) ...[
101-
const SizedBox(width: 8),
102-
Offstage(
103-
offstage: !_isOngoing,
104-
child: VoicesChip.round(
105-
backgroundColor: colors.primary,
106-
content: Text(
107-
context.l10n.ongoing,
108-
style: context.textTheme.labelSmall?.copyWith(
109-
color: Colors.white,
110-
),
97+
),
98+
if (_isOngoing) ...[
99+
const SizedBox(width: 8),
100+
Offstage(
101+
offstage: !_isOngoing,
102+
child: VoicesChip.round(
103+
backgroundColor: colors.primary,
104+
content: Text(
105+
context.l10n.ongoing,
106+
style: context.textTheme.labelSmall?.copyWith(
107+
color: Colors.white,
111108
),
112109
),
113110
),
114-
],
111+
),
115112
],
116-
),
113+
],
117114
),
118115
const SizedBox(height: 16),
119116
AnimatedSwitcher(
@@ -138,7 +135,6 @@ class CampaignTimelineCardState extends State<CampaignTimelineCard> {
138135
void _toggleExpanded() {
139136
setState(() {
140137
_isExpanded = !_isExpanded;
141-
widget.onExpandedChanged?.call(_isExpanded);
142138
});
143139
}
144140
}
@@ -151,16 +147,27 @@ enum CampaignTimelinePlacement {
151147
BuildContext context, {
152148
required bool isOngoing,
153149
}) {
154-
final colorScheme = context.colorScheme;
155150
final colors = Theme.of(context).colors;
156151

157152
return switch ((this, isOngoing)) {
158-
(discovery, _) => colorScheme.onPrimary,
159-
// TODO(minikin): Discuss color inconsistency with the design team.
160-
// The color on Figma files is #E3E8FA (measured),
161-
//but the color on the design system is #123CD3 with alpha 0.12.
162-
(workspace, true) => VoicesColors.lightIconsPrimary.withAlpha(31),
163-
(workspace, false) => colors.iconsBackgroundVariant,
153+
(discovery, _) => colors.onSurfaceNeutralOpaqueLv0,
154+
(workspace, true) => colors.onSurfaceNeutralOpaqueLv0,
155+
(workspace, false) => colors.onSurfaceNeutralOpaqueLv1,
156+
};
157+
}
158+
159+
BorderSide borderSide(
160+
BuildContext context, {
161+
required bool isOngoing,
162+
}) {
163+
final colorScheme = context.colorScheme;
164+
165+
return switch ((this, isOngoing)) {
166+
(discovery, true) => BorderSide(
167+
color: colorScheme.primary,
168+
width: 2,
169+
),
170+
(_, _) => BorderSide.none,
164171
};
165172
}
166173
}

catalyst_voices/apps/voices/test/widgets/campaign_timeline/campaign_timeline_card_test.dart

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -89,36 +89,6 @@ void main() {
8989
},
9090
);
9191

92-
testWidgets(
93-
'calls onExpandedChanged when tapped',
94-
(tester) async {
95-
var expanded = false;
96-
final widget = CampaignTimelineCard(
97-
timelineItem: timelineItem,
98-
placement: CampaignTimelinePlacement.discovery,
99-
onExpandedChanged: (isExpanded) => expanded = isExpanded,
100-
);
101-
102-
await tester.pumpApp(
103-
widget,
104-
voicesColors: lightVoicesColorScheme,
105-
);
106-
await tester.pumpAndSettle();
107-
108-
final gestureDetector = find
109-
.descendant(
110-
of: find.byType(CampaignTimelineCard),
111-
matching: find.byType(GestureDetector),
112-
)
113-
.first;
114-
115-
await tester.tap(gestureDetector);
116-
await tester.pumpAndSettle();
117-
118-
expect(expanded, isTrue);
119-
},
120-
);
121-
12292
testWidgets(
12393
'shows ongoing chip for current timeline',
12494
(tester) async {

0 commit comments

Comments
 (0)