Merge branch 'master' into feature/add-android-themed-icon-support

Merged master
This commit is contained in:
Toglefritz 2022-09-08 05:44:34 -05:00
commit 65803c927c
22 changed files with 250 additions and 157 deletions

View File

@ -1,5 +1,6 @@
{ {
"appName": "Wonderous", "appName": "Wonderous",
"localeSwapButton": "简体中文",
"animatedArrowSemanticSwipe": "Explore details about {title}.", "animatedArrowSemanticSwipe": "Explore details about {title}.",
"appBarTitleFactsHistory": "Facts and History", "appBarTitleFactsHistory": "Facts and History",
"appBarTitleConstruction": "Construction", "appBarTitleConstruction": "Construction",

View File

@ -1,5 +1,6 @@
{ {
"appName": "Wonderous", "appName": "Wonderous",
"localeSwapButton": "English",
"animatedArrowSemanticSwipe": "查看关于{title}的详细信息。", "animatedArrowSemanticSwipe": "查看关于{title}的详细信息。",
"appBarTitleFactsHistory": "历史与细节", "appBarTitleFactsHistory": "历史与细节",
"appBarTitleConstruction": "建造", "appBarTitleConstruction": "建造",

View File

@ -30,8 +30,11 @@ class AppLogic {
// Localizations // Localizations
await localeLogic.load(); await localeLogic.load();
// Data load
wondersLogic.init();
// Timeline // Timeline
await timelineLogic.init(); timelineLogic.init();
// Settings // Settings
await settingsLogic.load(); await settingsLogic.load();

View File

@ -1,8 +1,7 @@
import 'dart:ui';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:intl/intl_standalone.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl_standalone.dart';
import 'package:wonders/common_libs.dart';
class LocaleLogic { class LocaleLogic {
AppLocalizations? _strings; AppLocalizations? _strings;
@ -10,6 +9,8 @@ class LocaleLogic {
bool get isLoaded => _strings != null; bool get isLoaded => _strings != null;
bool get isEnglish => strings.localeName == 'en';
Future<void> load() async { Future<void> load() async {
final localeCode = await findSystemLocale(); final localeCode = await findSystemLocale();
Locale locale = Locale(localeCode.split('_')[0]); Locale locale = Locale(localeCode.split('_')[0]);
@ -20,6 +21,13 @@ class LocaleLogic {
if (AppLocalizations.supportedLocales.contains(locale) == false) { if (AppLocalizations.supportedLocales.contains(locale) == false) {
locale = Locale('en'); locale = Locale('en');
} }
settingsLogic.currentLocale.value = locale.languageCode;
_strings = await AppLocalizations.delegate.load(locale); _strings = await AppLocalizations.delegate.load(locale);
} }
Future<void> refreshIfChanged(Locale locale) async {
if (_strings?.localeName != locale.languageCode && AppLocalizations.supportedLocales.contains(locale)) {
_strings = await AppLocalizations.delegate.load(locale);
}
}
} }

View File

@ -1,4 +1,5 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:wonders/common_libs.dart';
import 'package:wonders/logic/common/save_load_mixin.dart'; import 'package:wonders/logic/common/save_load_mixin.dart';
class SettingsLogic with ThrottledSaveLoadMixin { class SettingsLogic with ThrottledSaveLoadMixin {
@ -7,6 +8,7 @@ class SettingsLogic with ThrottledSaveLoadMixin {
late final hasCompletedOnboarding = ValueNotifier<bool>(false)..addListener(scheduleSave); late final hasCompletedOnboarding = ValueNotifier<bool>(false)..addListener(scheduleSave);
late final hasDismissedSearchMessage = ValueNotifier<bool>(false)..addListener(scheduleSave); late final hasDismissedSearchMessage = ValueNotifier<bool>(false)..addListener(scheduleSave);
late final currentLocale = ValueNotifier<String>('en')..addListener(scheduleSave);
final bool useBlurs = defaultTargetPlatform != TargetPlatform.android; final bool useBlurs = defaultTargetPlatform != TargetPlatform.android;
@ -23,4 +25,11 @@ class SettingsLogic with ThrottledSaveLoadMixin {
'hasDismissedSearchMessage': hasDismissedSearchMessage.value, 'hasDismissedSearchMessage': hasDismissedSearchMessage.value,
}; };
} }
Future<void> setLocale(Locale value) async {
currentLocale.value = value.languageCode;
await localeLogic.refreshIfChanged(value);
wondersLogic.init();
timelineLogic.init();
}
} }

View File

@ -3,18 +3,17 @@ import 'package:wonders/logic/common/string_utils.dart';
import 'package:wonders/logic/data/timeline_data.dart'; import 'package:wonders/logic/data/timeline_data.dart';
class TimelineLogic { class TimelineLogic {
final List<TimelineEvent> events = []; List<TimelineEvent> events = [];
Future<void> init() async { void init() {
events.addAll(GlobalEventsData().globalEvents); events = [
...GlobalEventsData().globalEvents,
for (var w in wondersLogic.all) { ...wondersLogic.all.map(
events.add( (w) => TimelineEvent(
TimelineEvent(
w.startYr, w.startYr,
StringUtils.supplant($strings.timelineLabelConstruction, {'{title}': w.title}), StringUtils.supplant($strings.timelineLabelConstruction, {'{title}': w.title}),
), ),
); )
} ];
} }
} }

View File

@ -10,16 +10,7 @@ import 'package:wonders/logic/data/wonders_data/pyramids_giza_data.dart';
import 'package:wonders/logic/data/wonders_data/taj_mahal_data.dart'; import 'package:wonders/logic/data/wonders_data/taj_mahal_data.dart';
class WondersLogic { class WondersLogic {
late List<WonderData> all = [ List<WonderData> all = [];
GreatWallData(),
PetraData(),
ColosseumData(),
ChichenItzaData(),
MachuPicchuData(),
TajMahalData(),
ChristRedeemerData(),
PyramidsGizaData(),
];
final int timelineStartYear = -3000; final int timelineStartYear = -3000;
final int timelineEndYear = 2200; final int timelineEndYear = 2200;
@ -29,4 +20,17 @@ class WondersLogic {
if (result == null) throw ('Could not find data for wonder type $value'); if (result == null) throw ('Could not find data for wonder type $value');
return result; return result;
} }
void init() {
all = [
GreatWallData(),
PetraData(),
ColosseumData(),
ChichenItzaData(),
MachuPicchuData(),
TajMahalData(),
ChristRedeemerData(),
PyramidsGizaData(),
];
}
} }

View File

@ -30,19 +30,25 @@ class WondersApp extends StatelessWidget {
const WondersApp({Key? key}) : super(key: key); const WondersApp({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp.router( return ValueListenableBuilder<String>(
debugShowCheckedModeBanner: false, valueListenable: settingsLogic.currentLocale,
routerDelegate: appRouter.routerDelegate, builder: (_, localeCode, __) {
routeInformationProvider: appRouter.routeInformationProvider, return MaterialApp.router(
routeInformationParser: appRouter.routeInformationParser, locale: Locale(localeCode),
theme: ThemeData(fontFamily: $styles.text.body.fontFamily), debugShowCheckedModeBanner: false,
localizationsDelegates: const [ routerDelegate: appRouter.routerDelegate,
AppLocalizations.delegate, routeInformationProvider: appRouter.routeInformationProvider,
GlobalMaterialLocalizations.delegate, routeInformationParser: appRouter.routeInformationParser,
GlobalWidgetsLocalizations.delegate, theme: ThemeData(fontFamily: $styles.text.body.fontFamily),
GlobalCupertinoLocalizations.delegate, localizationsDelegates: const [
], AppLocalizations.delegate,
supportedLocales: AppLocalizations.supportedLocales, GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
);
}
); );
} }
} }

View File

@ -134,6 +134,9 @@ class _Insets {
@immutable @immutable
class _Shadows { class _Shadows {
final textSoft = [
Shadow(color: Colors.black.withOpacity(.25), offset: Offset(0, 2), blurRadius: 4),
];
final text = [ final text = [
Shadow(color: Colors.black.withOpacity(.6), offset: Offset(0, 2), blurRadius: 2), Shadow(color: Colors.black.withOpacity(.6), offset: Offset(0, 2), blurRadius: 2),
]; ];

View File

@ -52,13 +52,12 @@ class CollectibleItem extends StatelessWidget with GetItMixin {
), ),
) )
.animate(onPlay: (controller) => controller.repeat()) .animate(onPlay: (controller) => controller.repeat())
// TODO SB (Aug 17, 2022): Temporarily removed on Jonahs request, due to a bug in Impeller which should be fixed soon. Re-enable when fixed. .shimmer(delay: 4000.ms, duration: $styles.times.med * 3)
//.shimmer(delay: 4000.ms, duration: $styles.times.med * 3) .shake(curve: Curves.easeInOutCubic, hz: 4)
.shake(delay: 4000.ms, duration: $styles.times.med * 3, curve: Curves.easeInOutCubic, hz: 4)
.scale(begin: 1.0, end: 1.1, duration: $styles.times.med) .scale(begin: 1.0, end: 1.1, duration: $styles.times.med)
.then(delay: $styles.times.med) .then(delay: $styles.times.med)
.scale(begin: 1.0, end: 1 / 1.1), .scale(begin: 1.0, end: 1 / 1.1),
), ),
), ),
), ),
); );

View File

@ -5,7 +5,7 @@ class DiagonalTextPageIndicator extends StatelessWidget {
const DiagonalTextPageIndicator({Key? key, required this.current, required this.total}) : super(key: key); const DiagonalTextPageIndicator({Key? key, required this.current, required this.total}) : super(key: key);
final int current; final int current;
final int total; final int total;
static const double _fontSize = 32; static const double _fontSize = 26;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -21,10 +21,7 @@ class DiagonalTextPageIndicator extends StatelessWidget {
child: Transform.translate( child: Transform.translate(
offset: Offset(-_fontSize * .7, 0), offset: Offset(-_fontSize * .7, 0),
child: SizedBox( child: SizedBox(
width: size, width: size, height: size, child: Text('0$current', style: textStyle, textAlign: TextAlign.right)),
height: size,
child: Text('0$current',
style: textStyle.copyWith(shadows: $styles.shadows.text), textAlign: TextAlign.right)),
), ),
), ),
ClipPath( ClipPath(
@ -38,7 +35,7 @@ class DiagonalTextPageIndicator extends StatelessWidget {
opacity: .5, opacity: .5,
child: Text( child: Text(
'0$total', '0$total',
style: textStyle.copyWith(shadows: $styles.shadows.textStrong), style: textStyle, //.copyWith(shadows: $styles.shadows.textStrong),
), ),
), ),
), ),

View File

@ -0,0 +1,19 @@
import 'package:wonders/common_libs.dart';
class LocaleSwitcher extends StatelessWidget with GetItMixin {
LocaleSwitcher({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final locale = watchX((SettingsLogic s) => s.currentLocale);
Future<void> handleSwapLocale() async {
final newLocale = Locale(locale == 'en' ? 'zh' : 'en');
await settingsLogic.setLocale(newLocale);
}
return AppBtn.from(
padding: EdgeInsets.symmetric(vertical: $styles.insets.sm, horizontal: $styles.insets.sm),
text: $strings.localeSwapButton,
onPressed: handleSwapLocale);
}
}

View File

@ -31,11 +31,10 @@ class _ResultsGrid extends StatelessWidget {
} }
Widget _buildLanguageMessage(BuildContext context) { Widget _buildLanguageMessage(BuildContext context) {
bool isEnglish = localeLogic.strings.localeName == 'en';
return ValueListenableBuilder<bool>( return ValueListenableBuilder<bool>(
valueListenable: settingsLogic.hasDismissedSearchMessage, valueListenable: settingsLogic.hasDismissedSearchMessage,
builder: (_, value, __) { builder: (_, value, __) {
if (isEnglish || value) return SizedBox(); if (localeLogic.isEnglish || value) return SizedBox();
return AppBtn.basic( return AppBtn.basic(
onPressed: () => settingsLogic.hasDismissedSearchMessage.value = true, onPressed: () => settingsLogic.hasDismissedSearchMessage.value = true,
semanticLabel: $strings.resultsSemanticDismiss, semanticLabel: $strings.resultsSemanticDismiss,

View File

@ -9,7 +9,7 @@ class _CollapsingPullQuoteImage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Start transitioning when we are halfway up the screen // Start transitioning when we are halfway up the screen
final collapseStartPx = context.heightPx * 1; final collapseStartPx = context.heightPx * 1;
final collapseEndPx = context.heightPx * .35; final collapseEndPx = context.heightPx * .15;
const double imgHeight = 430; const double imgHeight = 430;
const double outerPadding = 100; const double outerPadding = 100;

View File

@ -28,8 +28,7 @@ class _ScrollingContent extends StatelessWidget {
final String dropChar = value.substring(0, 1); final String dropChar = value.substring(0, 1);
final textScale = MediaQuery.of(context).textScaleFactor; final textScale = MediaQuery.of(context).textScaleFactor;
final double dropCapWidth = StringUtils.measure(dropChar, dropStyle).width * textScale; final double dropCapWidth = StringUtils.measure(dropChar, dropStyle).width * textScale;
final bool isEnglish = localeLogic.strings.localeName == 'en'; //TODO EC: Helper method for localLogic.isEnglish? final bool skipCaps = !localeLogic.isEnglish || MediaQuery.of(context).accessibleNavigation;
final bool skipCaps = !isEnglish || MediaQuery.of(context).accessibleNavigation;
return Semantics( return Semantics(
label: value, label: value,
child: !skipCaps child: !skipCaps

View File

@ -14,6 +14,8 @@ class _TitleText extends StatelessWidget {
children: [ children: [
Gap($styles.insets.md), Gap($styles.insets.md),
Gap(30), Gap(30),
/// Sub-title row
SeparatedRow( SeparatedRow(
padding: EdgeInsets.symmetric(horizontal: $styles.insets.sm), padding: EdgeInsets.symmetric(horizontal: $styles.insets.sm),
separatorBuilder: () => Gap($styles.insets.sm), separatorBuilder: () => Gap($styles.insets.sm),
@ -39,14 +41,23 @@ class _TitleText extends StatelessWidget {
], ],
), ),
Gap($styles.insets.md), Gap($styles.insets.md),
Semantics(sortKey: OrdinalSortKey(0), child: WonderTitleText(data)),
/// Wonder title text
Semantics(
sortKey: OrdinalSortKey(0),
child: WonderTitleText(data),
),
Gap($styles.insets.xs), Gap($styles.insets.xs),
/// Region
Text( Text(
data.regionTitle.toUpperCase(), data.regionTitle.toUpperCase(),
style: $styles.text.title1, style: $styles.text.title1,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
Gap($styles.insets.md), Gap($styles.insets.md),
/// Compass divider
ExcludeSemantics( ExcludeSemantics(
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(horizontal: $styles.insets.md), padding: EdgeInsets.symmetric(horizontal: $styles.insets.md),
@ -61,6 +72,8 @@ class _TitleText extends StatelessWidget {
), ),
), ),
Gap($styles.insets.sm), Gap($styles.insets.sm),
/// Date
Text( Text(
StringUtils.supplant( StringUtils.supplant(
$strings.titleLabelDate, $strings.titleLabelDate,

View File

@ -12,6 +12,7 @@ import 'package:wonders/ui/screens/home_menu/home_menu.dart';
import 'package:wonders/ui/wonder_illustrations/common/animated_clouds.dart'; import 'package:wonders/ui/wonder_illustrations/common/animated_clouds.dart';
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration.dart'; import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration.dart';
import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart'; import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart';
import 'package:wonders/ui/wonder_illustrations/common/wonder_title_text.dart';
part '_vertical_swipe_controller.dart'; part '_vertical_swipe_controller.dart';
part 'widgets/_animated_arrow_button.dart'; part 'widgets/_animated_arrow_button.dart';
@ -143,7 +144,7 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
Stack(children: [ Stack(children: [
/// Foreground gradient-1, gets darker when swiping up /// Foreground gradient-1, gets darker when swiping up
BottomCenter( BottomCenter(
child: _buildSwipeableBgGradient(currentWonder.type.bgColor.withOpacity(.5)), child: _buildSwipeableBgGradient(currentWonder.type.bgColor.withOpacity(.65)),
), ),
/// Foreground decorators /// Foreground decorators
@ -151,69 +152,72 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
/// Foreground gradient-2, gets darker when swiping up /// Foreground gradient-2, gets darker when swiping up
BottomCenter( BottomCenter(
child: _buildSwipeableBgGradient(currentWonder.type.bgColor.withOpacity(.5)), child: _buildSwipeableBgGradient(currentWonder.type.bgColor.withOpacity(1)),
), ),
/// Floating controls / UI /// Floating controls / UI
AnimatedSwitcher( AnimatedSwitcher(
duration: $styles.times.fast, duration: $styles.times.fast,
child: RepaintBoundary( child: RepaintBoundary(
child: OverflowBox( key: ObjectKey(currentWonder),
child: Column( child: IgnorePointer(
mainAxisSize: MainAxisSize.min, ignoringSemantics: false,
children: [ child: OverflowBox(
SizedBox(width: double.infinity), child: Column(
const Spacer(), mainAxisSize: MainAxisSize.min,
children: [
SizedBox(width: double.infinity),
const Spacer(),
/// Title Content /// Title Content
LightText( LightText(
child: MergeSemantics( child: MergeSemantics(
child: Column( child: Transform.translate(
children: [ offset: Offset(0, 30),
/// Page indicator child: Column(
IgnorePointer( children: [
child: DiagonalTextPageIndicator(current: _wonderIndex + 1, total: _numWonders), WonderTitleText(currentWonder, enableShadows: true),
Gap($styles.insets.md),
AppPageIndicator(
count: _numWonders,
controller: _pageController,
color: $styles.colors.white,
dotSize: 8,
onDotPressed: _handlePageIndicatorDotPressed,
semanticPageTitle: $strings.homeSemanticWonder,
),
Gap($styles.insets.md),
],
), ),
Gap($styles.insets.sm), ),
AppPageIndicator(
count: _numWonders,
controller: _pageController,
color: $styles.colors.white,
dotSize: 8,
onDotPressed: _handlePageIndicatorDotPressed,
semanticPageTitle: $strings.homeSemanticWonder,
),
],
), ),
), ),
),
Gap($styles.insets.xs),
/// Animated arrow and background /// Animated arrow and background
/// Wrap in a container that is full-width to make it easier to find for screen readers /// Wrap in a container that is full-width to make it easier to find for screen readers
MergeSemantics( MergeSemantics(
child: Container( child: Container(
width: double.infinity, width: double.infinity,
alignment: Alignment.center, alignment: Alignment.center,
/// Lose state of child objects when index changes, this will re-run all the animated switcher and the arrow anim /// Lose state of child objects when index changes, this will re-run all the animated switcher and the arrow anim
key: ValueKey(_wonderIndex), key: ValueKey(_wonderIndex),
child: Stack( child: Stack(
children: [ children: [
/// Expanding rounded rect that grows in height as user swipes up /// Expanding rounded rect that grows in height as user swipes up
Positioned.fill( Positioned.fill(
child: _buildSwipeableArrowBg(), child: _buildSwipeableArrowBg(),
), ),
/// Arrow Btn that fades in and out /// Arrow Btn that fades in and out
_AnimatedArrowButton(onTap: _showDetailsPage, semanticTitle: currentWonder.title), _AnimatedArrowButton(onTap: _showDetailsPage, semanticTitle: currentWonder.title),
], ],
),
), ),
), ),
), Gap($styles.insets.md),
Gap($styles.insets.md), ],
], ),
), ),
), ),
), ),
@ -306,7 +310,7 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
return _swipeController.buildListener(builder: (swipeAmt, isPointerDown, _) { return _swipeController.buildListener(builder: (swipeAmt, isPointerDown, _) {
return IgnorePointer( return IgnorePointer(
child: FractionallySizedBox( child: FractionallySizedBox(
heightFactor: .5, heightFactor: .6,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
@ -314,7 +318,7 @@ class _HomeScreenState extends State<HomeScreen> with SingleTickerProviderStateM
end: Alignment.bottomCenter, end: Alignment.bottomCenter,
colors: [ colors: [
fgColor.withOpacity(0), fgColor.withOpacity(0),
fgColor.withOpacity(fgColor.opacity * .75 + (isPointerDown ? .05 : 0) + swipeAmt * .20), fgColor.withOpacity(.5 + fgColor.opacity * .25 + (isPointerDown ? .05 : 0) + swipeAmt * .20),
], ],
stops: const [0, 1], stops: const [0, 1],
), ),

View File

@ -4,6 +4,7 @@ import 'package:wonders/common_libs.dart';
import 'package:wonders/logic/data/wonder_data.dart'; import 'package:wonders/logic/data/wonder_data.dart';
import 'package:wonders/ui/common/app_backdrop.dart'; import 'package:wonders/ui/common/app_backdrop.dart';
import 'package:wonders/ui/common/app_icons.dart'; import 'package:wonders/ui/common/app_icons.dart';
import 'package:wonders/ui/common/controls/locale_switcher.dart';
import 'package:wonders/ui/screens/home_menu/about_dialog_content.dart'; import 'package:wonders/ui/screens/home_menu/about_dialog_content.dart';
class HomeMenu extends StatelessWidget { class HomeMenu extends StatelessWidget {
@ -49,11 +50,23 @@ class HomeMenu extends StatelessWidget {
), ),
), ),
/// Back btn SafeArea(
BackBtn.close( child: PaddedRow(
bgColor: Colors.transparent, padding: EdgeInsets.symmetric(
iconColor: $styles.colors.offWhite, horizontal: $styles.insets.md,
).safe(), vertical: $styles.insets.sm,
),
children: [
/// Back btn
BackBtn.close(
bgColor: Colors.transparent,
iconColor: $styles.colors.offWhite,
),
Spacer(),
LocaleSwitcher()
],
),
),
/// Content /// Content
Positioned.fill( Positioned.fill(
@ -75,7 +88,7 @@ class HomeMenu extends StatelessWidget {
), ),
), ),
), ),
) ),
], ],
); );
} }
@ -106,31 +119,35 @@ class HomeMenu extends StatelessWidget {
} }
Widget _buildBottomBtns(BuildContext context) { Widget _buildBottomBtns(BuildContext context) {
return SeparatedColumn( return ValueListenableBuilder(
separatorBuilder: () => Divider(thickness: 1.5, height: 1).animate().scale( valueListenable: settingsLogic.currentLocale,
duration: $styles.times.slow, builder: (_, __, ___) {
delay: $styles.times.pageTransition + 200.ms, return SeparatedColumn(
curve: Curves.easeOutBack, separatorBuilder: () => Divider(thickness: 1.5, height: 1).animate().scale(
), duration: $styles.times.slow,
children: [ delay: $styles.times.pageTransition + 200.ms,
_MenuTextBtn( curve: Curves.easeOutBack,
label: $strings.homeMenuButtonExplore, ),
icon: AppIcons.timeline, children: [
onPressed: () => _handleTimelinePressed(context)), _MenuTextBtn(
_MenuTextBtn( label: $strings.homeMenuButtonExplore,
label: $strings.homeMenuButtonView, icon: AppIcons.timeline,
icon: AppIcons.collection, onPressed: () => _handleTimelinePressed(context)),
onPressed: () => _handleCollectionPressed(context)), _MenuTextBtn(
_MenuTextBtn( label: $strings.homeMenuButtonView,
label: $strings.homeMenuButtonAbout, icon: AppIcons.collection,
icon: AppIcons.info, onPressed: () => _handleCollectionPressed(context)),
onPressed: () => _handleAboutPressed(context), _MenuTextBtn(
), label: $strings.homeMenuButtonAbout,
] icon: AppIcons.info,
.animate(interval: 50.ms) onPressed: () => _handleAboutPressed(context),
.fade(delay: $styles.times.pageTransition + 50.ms) ),
.slide(begin: Offset(0, .1), curve: Curves.easeOut), ]
); .animate(interval: 50.ms)
.fade(delay: $styles.times.pageTransition + 50.ms)
.slide(begin: Offset(0, .1), curve: Curves.easeOut),
);
});
} }
Widget _buildGridBtn(BuildContext context, WonderData btnData) { Widget _buildGridBtn(BuildContext context, WonderData btnData) {

View File

@ -19,11 +19,7 @@ class _IntroScreenState extends State<IntroScreen> {
static const double _textHeight = 155; static const double _textHeight = 155;
static const double _pageIndicatorHeight = 55; static const double _pageIndicatorHeight = 55;
static List<_PageData> pageData = [ static List<_PageData> pageData = [];
_PageData($strings.introTitleJourney, $strings.introDescriptionNavigate, 'camel', '1'),
_PageData($strings.introTitleExplore, $strings.introDescriptionUncover, 'petra', '2'),
_PageData($strings.introTitleDiscover, $strings.introDescriptionLearn, 'statue', '3'),
];
late final PageController _pageController = PageController()..addListener(_handlePageChanged); late final PageController _pageController = PageController()..addListener(_handlePageChanged);
final ValueNotifier<int> _currentPage = ValueNotifier(0); final ValueNotifier<int> _currentPage = ValueNotifier(0);
@ -51,6 +47,13 @@ class _IntroScreenState extends State<IntroScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Set the page data, as strings may have changed based on locale
pageData = [
_PageData($strings.introTitleJourney, $strings.introDescriptionNavigate, 'camel', '1'),
_PageData($strings.introTitleExplore, $strings.introDescriptionUncover, 'petra', '2'),
_PageData($strings.introTitleDiscover, $strings.introDescriptionLearn, 'statue', '3'),
];
// This view uses a full screen PageView to enable swipe navigation. // This view uses a full screen PageView to enable swipe navigation.
// However, we only want the title / description to actually swipe, // However, we only want the title / description to actually swipe,
// so we stack a PageView with that content over top of all the other // so we stack a PageView with that content over top of all the other

View File

@ -17,7 +17,7 @@ class WonderTitleText extends StatelessWidget {
); );
bool smallText = [WonderType.christRedeemer, WonderType.colosseum].contains(data.type); bool smallText = [WonderType.christRedeemer, WonderType.colosseum].contains(data.type);
if (smallText) { if (smallText) {
textStyle = textStyle.copyWith(fontSize: 48); textStyle = textStyle.copyWith(fontSize: 56);
} }
// First, get a list like: ['the\n', 'great wall'] // First, get a list like: ['the\n', 'great wall']
@ -40,12 +40,15 @@ class WonderTitleText extends StatelessWidget {
); );
} }
List<Shadow> shadows = enableShadows ? $styles.shadows.text : []; List<Shadow> shadows = enableShadows ? $styles.shadows.textSoft : [];
return RichText( return Hero(
textAlign: TextAlign.center, tag: 'wonderTitle-$title',
text: TextSpan( child: RichText(
style: textStyle.copyWith(shadows: shadows), textAlign: TextAlign.center,
children: pieces.map(buildTextSpan).toList(), text: TextSpan(
style: textStyle.copyWith(shadows: shadows),
children: pieces.map(buildTextSpan).toList(),
),
), ),
); );
} }

View File

@ -56,17 +56,20 @@ class TajMahalIllustration extends StatelessWidget {
alignment: Alignment(0, config.shortMode ? 1 : -.15), alignment: Alignment(0, config.shortMode ? 1 : -.15),
child: FractionallySizedBox( child: FractionallySizedBox(
widthFactor: config.shortMode ? 1 : 1.7, widthFactor: config.shortMode ? 1 : 1.7,
child: WonderHero(config, 'taj-mg', child: Stack(
child: Stack( children: [
children: [ WonderHero(
Image.asset('$assetPath/taj-mahal.png', opacity: anim, fit: BoxFit.cover), config,
if (!config.shortMode) 'taj-mg',
FractionalTranslation( child: Image.asset('$assetPath/taj-mahal.png', opacity: anim, fit: BoxFit.cover),
translation: Offset(0, 1.33), ),
child: Image.asset('$assetPath/pool.png', opacity: anim, fit: BoxFit.cover), if (!config.shortMode)
), FractionalTranslation(
], translation: Offset(0, 1.33),
)), child: Image.asset('$assetPath/pool.png', opacity: anim, fit: BoxFit.cover),
),
],
),
), ),
), ),
) )

View File

@ -1,6 +1,9 @@
# 1.9.0 # 1.9.0
- Improved support for dynamic text scaling - Improved support for dynamic text scaling
- Improved performance for blend modes and blurs - Improved performance for blend modes and blurs
- Added LocalSwitcher btn in the main Wonders Menu
- Request higher preferred FPS for Android devices
- Fix rendering issues with Chinese fonts
# 1.8.0 # 1.8.0
- Initial release - Initial release