Update events view, add responsiveness, switch to dark mode

This commit is contained in:
Shawn 2022-11-14 11:59:45 -07:00
parent 973d9c61cf
commit 34a0ae7dbf
7 changed files with 195 additions and 77 deletions

View File

@ -158,7 +158,7 @@ class _Corners {
class _Sizes {
double get maxContentWidth1 => 800;
double get maxContentWidth2 => 600;
double get maxContentWidth3 => 400;
double get maxContentWidth3 => 500;
final Size minAppSize = Size(450, 600);
}

View File

@ -1,21 +1,26 @@
import 'package:wonders/common_libs.dart';
import 'package:wonders/logic/common/string_utils.dart';
import 'package:wonders/ui/common/themed_text.dart';
class TimelineEventCard extends StatelessWidget {
const TimelineEventCard({Key? key, required this.year, required this.text}) : super(key: key);
const TimelineEventCard({Key? key, required this.year, required this.text, this.darkMode = false}) : super(key: key);
final int year;
final String text;
final bool darkMode;
@override
Widget build(BuildContext context) {
return MergeSemantics(
child: Padding(
padding: EdgeInsets.only(bottom: $styles.insets.sm),
child: DefaultTextColor(
color: darkMode ? Colors.white : Colors.black,
child: Container(
color: $styles.colors.offWhite,
color: darkMode ? $styles.colors.greyStrong : $styles.colors.offWhite,
padding: EdgeInsets.all($styles.insets.sm),
child: Row(
children: [
/// Date
SizedBox(
width: 75,
child: Column(
@ -26,8 +31,12 @@ class TimelineEventCard extends StatelessWidget {
],
),
),
Center(child: Container(width: 1, height: 50, color: $styles.colors.black)),
/// Divider
Center(child: Container(width: 1, height: 50, color: darkMode ? Colors.white : $styles.colors.black)),
Gap($styles.insets.sm),
/// Text content
Expanded(
child: Text(text, style: $styles.text.bodySmall),
),
@ -35,6 +44,7 @@ class TimelineEventCard extends StatelessWidget {
),
),
),
),
);
}
}

View File

@ -1,8 +1,19 @@
part of '../wonder_events.dart';
class _EventsList extends StatefulWidget {
const _EventsList({Key? key, required this.data}) : super(key: key);
const _EventsList(
{Key? key,
required this.data,
this.topHeight = 0,
this.blurOnScroll = false,
this.showTopGradient = true,
this.showBottomGradient = true})
: super(key: key);
final WonderData data;
final double topHeight;
final bool blurOnScroll;
final bool showTopGradient;
final bool showBottomGradient;
@override
State<_EventsList> createState() => _EventsListState();
@ -16,8 +27,6 @@ class _EventsListState extends State<_EventsList> {
super.dispose();
}
void _handleGlobalTimelinePressed() => context.push(ScreenPaths.timeline(widget.data.type));
@override
Widget build(BuildContext context) {
return PopRouterOnOverScroll(
@ -28,9 +37,9 @@ class _EventsListState extends State<_EventsList> {
AnimatedBuilder(
animation: _scroller,
builder: (_, __) {
bool showBackdrop = true;
bool showBackdrop = widget.blurOnScroll;
double backdropAmt = 0;
if (_scroller.hasClients) {
if (_scroller.hasClients && showBackdrop) {
double blurStart = 50;
double maxScroll = 150;
double scrollPx = _scroller.position.pixels - blurStart;
@ -77,20 +86,22 @@ class _EventsListState extends State<_EventsList> {
for (var e in events.entries) {
final delay = 100.ms + (100 * listItems.length).ms;
listItems.add(
TimelineEventCard(year: e.key, text: e.value)
TimelineEventCard(year: e.key, text: e.value, darkMode: true)
.animate()
.fade(delay: delay, duration: $styles.times.med * 1.5)
.slide(begin: Offset(0, 1), curve: Curves.easeOutBack),
);
}
return SingleChildScrollView(
return Stack(
children: [
SingleChildScrollView(
controller: _scroller,
child: Column(
children: [
IgnorePointer(child: Gap(WonderEvents._topHeight)),
IgnorePointer(child: Gap(widget.topHeight)),
Container(
decoration: BoxDecoration(
color: $styles.colors.white,
color: $styles.colors.black,
borderRadius: BorderRadius.circular($styles.corners.md),
),
padding: EdgeInsets.symmetric(horizontal: $styles.insets.md),
@ -100,16 +111,7 @@ class _EventsListState extends State<_EventsList> {
buildHandle(),
Gap($styles.insets.sm),
...listItems,
Gap($styles.insets.lg),
AppBtn.from(
text: $strings.eventsListButtonOpenGlobal,
expand: true,
onPressed: _handleGlobalTimelinePressed,
semanticLabel: $strings.eventsListButtonOpenGlobal,
),
Gap($styles.insets.xl),
CompassDivider(isExpanded: true),
Gap($styles.insets.md),
HiddenCollectible(widget.data.type, index: 2, size: 150),
Gap(150),
],
@ -117,6 +119,22 @@ class _EventsListState extends State<_EventsList> {
),
],
),
),
/// Vertical gradient on btm
if (widget.showBottomGradient)
Positioned.fill(
child: BottomCenter(
child: ListOverscollGradient(bottomUp: true, size: 100),
),
),
if (widget.showTopGradient)
Positioned.fill(
child: TopCenter(
child: ListOverscollGradient(size: 100),
),
),
],
);
}
}

View File

@ -0,0 +1,20 @@
part of '../wonder_events.dart';
class _TimelineBtn extends StatelessWidget {
const _TimelineBtn({Key? key, required this.type}) : super(key: key);
final WonderType type;
@override
Widget build(BuildContext context) {
void handleBtnPressed() => context.push(ScreenPaths.timeline(type));
return Padding(
padding: EdgeInsets.symmetric(horizontal: $styles.insets.md),
child: AppBtn.from(
text: $strings.eventsListButtonOpenGlobal,
expand: true,
onPressed: handleBtnPressed,
semanticLabel: $strings.eventsListButtonOpenGlobal,
),
);
}
}

View File

@ -1,11 +1,12 @@
part of '../wonder_events.dart';
class _TopContent extends StatelessWidget {
const _TopContent({Key? key, required this.data}) : super(key: key);
class _WonderImageWithTimeline extends StatelessWidget {
const _WonderImageWithTimeline({Key? key, required this.data, required this.height}) : super(key: key);
final WonderData data;
final double height;
Color _fixLuminence(Color color, [double luminence = 0.35]) {
double d = luminence - color.computeLuminance();
Color _fixLuminance(Color color, [double luminance = 0.35]) {
double d = luminance - color.computeLuminance();
if (d <= 0) return color;
int r = color.red, g = color.green, b = color.blue;
return Color.fromARGB(255, (r + (255 - r) * d).toInt(), (g + (255 - g) * d).toInt(), (b + (255 - b) * d).toInt());
@ -14,7 +15,7 @@ class _TopContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SizedBox(
height: WonderEvents._topHeight,
height: height,
child: MergeSemantics(
child: LightText(
child: SeparatedColumn(
@ -45,7 +46,7 @@ class _TopContent extends StatelessWidget {
timelineBuilder: (_, data, isSelected) {
return Container(
decoration: BoxDecoration(
color: isSelected ? _fixLuminence(data.type.fgColor) : Colors.transparent,
color: isSelected ? _fixLuminance(data.type.fgColor) : Colors.transparent,
border: Border.all(color: $styles.colors.greyMedium),
borderRadius: BorderRadius.circular($styles.corners.md),
),

View File

@ -2,7 +2,7 @@ import 'package:wonders/common_libs.dart';
import 'package:wonders/logic/common/string_utils.dart';
import 'package:wonders/logic/data/wonder_data.dart';
import 'package:wonders/ui/common/app_backdrop.dart';
import 'package:wonders/ui/common/compass_divider.dart';
import 'package:wonders/ui/common/app_icons.dart';
import 'package:wonders/ui/common/curved_clippers.dart';
import 'package:wonders/ui/common/hidden_collectible.dart';
import 'package:wonders/ui/common/list_gradient.dart';
@ -13,34 +13,103 @@ import 'package:wonders/ui/common/wonders_timeline_builder.dart';
import 'package:wonders/ui/wonder_illustrations/common/wonder_title_text.dart';
part 'widgets/_events_list.dart';
part 'widgets/_top_content.dart';
part 'widgets/_timeline_btn.dart';
part 'widgets/_wonder_image_with_timeline.dart';
class WonderEvents extends StatelessWidget {
static const double _topHeight = 450;
WonderEvents({Key? key, required this.type}) : super(key: key);
final WonderType type;
late final _data = wondersLogic.getData(type);
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (_, constraints) {
void handleTimelineBtnPressed() => context.push(ScreenPaths.timeline(type));
return LayoutBuilder(builder: (context, constraints) {
return Container(
color: $styles.colors.black,
child: SafeArea(
bottom: false,
child: Center(
child: SizedBox(
width: $styles.sizes.maxContentWidth1,
child: Stack(
children: [
/// Top content, sits underneath scrolling list
_TopContent(data: _data),
/// Scrolling Events list, takes up the full view
_EventsList(data: _data),
Positioned.fill(
top: $styles.insets.lg,
child: context.isLandscape ? _buildLandscape() : _buildPortrait(),
),
Positioned(
right: $styles.insets.lg,
top: $styles.insets.lg,
child: CircleIconBtn(
icon: AppIcons.timeline,
onPressed: handleTimelineBtnPressed,
semanticLabel: $strings.eventsListButtonOpenGlobal)),
],
),
),
);
});
}
/// Landscape layout is a row, with the WonderImage on left and events on the right
Widget _buildLandscape() {
return Row(
children: [
/// WonderImage w/ Timeline btn sits on the left
Expanded(
child: Center(
child: SizedBox(
width: $styles.sizes.maxContentWidth3,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Gap($styles.insets.lg),
Expanded(child: Center(child: _WonderImageWithTimeline(data: _data, height: 500))),
Gap($styles.insets.lg),
SizedBox(width: 300, child: _TimelineBtn(type: type)),
Gap($styles.insets.xl),
],
),
),
),
),
/// Scrolling event list
Expanded(
child: Center(
child: SizedBox(
width: $styles.sizes.maxContentWidth1,
child: _EventsList(data: _data, topHeight: 100, blurOnScroll: false),
),
),
),
],
);
}
/// Portrait layout is a stack with the list scrolling overtop of the WonderImage
Widget _buildPortrait() {
return LayoutBuilder(builder: (_, constraints) {
double topHeight = max(constraints.maxHeight * .55, 200);
return Center(
child: SizedBox(
width: $styles.sizes.maxContentWidth3,
child: Stack(
children: [
/// Top content, sits underneath scrolling list
_WonderImageWithTimeline(height: topHeight, data: _data),
/// Scrolling Events list, takes up the full view
Column(
children: [
Expanded(
child: _EventsList(data: _data, topHeight: topHeight, blurOnScroll: true, showTopGradient: false),
),
Gap($styles.insets.lg),
SizedBox(width: $styles.sizes.maxContentWidth3, child: _TimelineBtn(type: _data.type)),
Gap($styles.insets.xl),
],
),
],
),
),
);

View File

@ -297,7 +297,7 @@ packages:
name: flutter_inappwebview
url: "https://pub.dartlang.org"
source: hosted
version: "5.4.3+7"
version: "5.7.1"
flutter_lints:
dependency: "direct dev"
description: