Skip to content

chore(cat-voices): ultrawide screens #2485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:catalyst_voices/pages/discovery/sections/stay_involved.dart';
import 'package:catalyst_voices/pages/discovery/state_selectors/campaign_categories_state_selector.dart';
import 'package:catalyst_voices/pages/discovery/state_selectors/current_campaign_selector.dart';
import 'package:catalyst_voices/pages/discovery/state_selectors/most_recent_proposals_selector.dart';
import 'package:catalyst_voices/widgets/common/infrastructure/voices_wide_screen_constrained.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
import 'package:flutter/material.dart';

Expand Down Expand Up @@ -36,7 +37,12 @@ class _Body extends StatelessWidget {
const CampaignCategoriesStateSelector(),
const StayInvolved(),
const MostRecentProposalsSelector(),
],
].constrainedDelegate(
excludePredicate: (widget) =>
widget is CampaignHeroSection ||
widget is MostRecentProposalsSelector ||
widget is HowItWorks,
),
),
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class CurrentCampaign extends StatelessWidget {
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 120, top: 64, right: 120),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ class _LatestProposalsState extends State<MostRecentProposals> {
Widget build(BuildContext context) {
return Container(
key: const Key('MostRecentProposals'),
constraints: const BoxConstraints(maxHeight: 900),
constraints: const BoxConstraints.tightFor(
height: 800,
width: double.infinity,
),
decoration: BoxDecoration(
image: DecorationImage(
image: CatalystImage.asset(
Expand All @@ -87,80 +90,83 @@ class _LatestProposalsState extends State<MostRecentProposals> {
fit: BoxFit.cover,
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 72),
Text(
key: const Key('MostRecentProposalsTitle'),
context.l10n.mostRecent,
style: context.textTheme.headlineLarge?.copyWith(
color: ThemeBuilder.buildTheme().colors.textOnPrimaryWhite,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 100),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 72),
Text(
key: const Key('MostRecentProposalsTitle'),
context.l10n.mostRecent,
style: context.textTheme.headlineLarge?.copyWith(
color: ThemeBuilder.buildTheme().colors.textOnPrimaryWhite,
),
),
),
const SizedBox(height: 48),
MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onHorizontalDragUpdate: _onHorizontalDrag,
child: SizedBox(
height: 440,
child: Center(
child: ListView.separated(
controller: _scrollController,
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 120),
scrollDirection: Axis.horizontal,
itemCount: widget.proposals.length,
itemBuilder: (context, index) {
final proposal = widget.proposals[index];
final ref = proposal.ref;
return Skeletonizer(
enabled: widget.isLoading,
child: PendingProposalCard(
key: Key('PendingProposalCard_$ref'),
proposal: proposal,
onTap: () {
unawaited(
ProposalRoute(
proposalId: ref.id,
version: ref.version,
).push(context),
);
},
onFavoriteChanged: (value) async {
final bloc = context.read<DiscoveryCubit>();
if (value) {
await bloc.addFavorite(ref);
} else {
await bloc.removeFavorite(ref);
}
},
isFavorite: proposal.isFavorite,
),
);
},
separatorBuilder: (context, index) =>
const SizedBox(width: 24),
const SizedBox(height: 48),
MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onHorizontalDragUpdate: _onHorizontalDrag,
child: SizedBox(
height: 440,
width: 1200,
child: Center(
child: ListView.separated(
controller: _scrollController,
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: widget.proposals.length,
itemBuilder: (context, index) {
final proposal = widget.proposals[index];
final ref = proposal.ref;
return Skeletonizer(
enabled: widget.isLoading,
child: PendingProposalCard(
key: Key('PendingProposalCard_$ref'),
proposal: proposal,
onTap: () {
unawaited(
ProposalRoute(
proposalId: ref.id,
version: ref.version,
).push(context),
);
},
onFavoriteChanged: (value) async {
final bloc = context.read<DiscoveryCubit>();
if (value) {
await bloc.addFavorite(ref);
} else {
await bloc.removeFavorite(ref);
}
},
isFavorite: proposal.isFavorite,
),
);
},
separatorBuilder: (context, index) =>
const SizedBox(width: 24),
),
),
),
),
),
),
const SizedBox(height: 16),
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 360),
child: VoicesSlider(
key: const Key('MostRecentProposalsSlider'),
value: _scrollPercentage,
onChanged: _onSliderChanged,
const SizedBox(height: 16),
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 360),
child: VoicesSlider(
key: const Key('MostRecentProposalsSlider'),
value: _scrollPercentage,
onChanged: _onSliderChanged,
),
),
),
const SizedBox(height: 16),
const _ViewAllProposalsButton(),
const SizedBox(height: 72),
],
const SizedBox(height: 16),
const _ViewAllProposalsButton(),
const SizedBox(height: 72),
],
),
),
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'package:flutter/material.dart';

bool _defaultExcludePredicate(Widget child) => false;

typedef ExcludeWidgetPredicate = bool Function(Widget child);

class VoicesWideScreenConstrained extends StatelessWidget {
/// Width of the screen. Defaults to 1440. When child has padding
/// of horizontal 120 so actual content is 1200
final double maxWidth;
final Color? backgroundColor;
final Widget child;

const VoicesWideScreenConstrained({
super.key,
this.maxWidth = 1440,
this.backgroundColor,
required this.child,
});

@override
Widget build(BuildContext context) {
Widget content = Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: maxWidth),
child: child,
),
);

if (backgroundColor != null) {
content = ColoredBox(
color: backgroundColor!,
child: content,
);
}

return content;
}
}

extension ConstrainedListExtension on List<Widget> {
List<Widget> constrainedDelegate({
double maxWidth = 1440,
ExcludeWidgetPredicate excludePredicate = _defaultExcludePredicate,
}) {
return map((widget) {
if (excludePredicate(widget)) {
return widget;
}

return VoicesWideScreenConstrained(
maxWidth: maxWidth,
child: widget,
);
}).toList();
}
}

extension ConstrainedWidgetExtension on Widget {
Widget withBackground(Color color) {
return VoicesWideScreenConstrained(
backgroundColor: color,
child: this,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ extension CampaignTimelineX on CampaignTimeline {
'''Participants submit initial proposals for ideas to solve challenges. A set amount of ada is allocated to the new funding round.''',
timeline: DateRange(
from: DateTime.utc(2025, 4, 30, 13, 20),
to: DateTime.utc(2025, 5, 7, 17, 00),
to: DateTime.utc(2025, 5, 13, 17, 00),
),
stage: CampaignTimelineStage.proposalSubmission,
),
Expand Down Expand Up @@ -84,15 +84,5 @@ extension CampaignTimelineX on CampaignTimeline {
),
stage: CampaignTimelineStage.votingResults,
),
CampaignTimeline(
title: 'Project Onboarding',
description:
'''Votes are tallied and the results revealed. Voters and community reviewers receive their rewards.''',
timeline: DateRange(
from: DateTime.utc(2025, 5, 15, 17, 00),
to: null,
),
stage: CampaignTimelineStage.projectOnboarding,
),
];
}
Loading