Initial stab at swapping locales, work in progress
- stubbed in button for testing locale switching, needs design polish and direction on whether the button is available at all times or just in menu - tested and fixed switching on the fly for wonder views, intro, timeline, artifacts, and menu
This commit is contained in:
parent
4f55aa2536
commit
466fe074b8
@ -1,5 +1,6 @@
|
||||
{
|
||||
"appName": "Wonderous",
|
||||
"localeSwapButton": "简体中文",
|
||||
"animatedArrowSemanticSwipe": "Explore details about {title}.",
|
||||
"appBarTitleFactsHistory": "Facts and History",
|
||||
"appBarTitleConstruction": "Construction",
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"appName": "Wonderous",
|
||||
"localeSwapButton": "English",
|
||||
"animatedArrowSemanticSwipe": "查看关于{title}的详细信息。",
|
||||
"appBarTitleFactsHistory": "历史与细节",
|
||||
"appBarTitleConstruction": "建造",
|
||||
|
@ -30,8 +30,11 @@ class AppLogic {
|
||||
// Localizations
|
||||
await localeLogic.load();
|
||||
|
||||
// Data load
|
||||
wondersLogic.init();
|
||||
|
||||
// Timeline
|
||||
await timelineLogic.init();
|
||||
timelineLogic.init();
|
||||
|
||||
// Settings
|
||||
await settingsLogic.load();
|
||||
|
@ -3,6 +3,7 @@ import 'dart:ui';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:intl/intl_standalone.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wonders/common_libs.dart';
|
||||
|
||||
class LocaleLogic {
|
||||
AppLocalizations? _strings;
|
||||
@ -20,6 +21,13 @@ class LocaleLogic {
|
||||
if (AppLocalizations.supportedLocales.contains(locale) == false) {
|
||||
locale = Locale('en');
|
||||
}
|
||||
settingsLogic.currentLocale.value = locale.languageCode;
|
||||
_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ class SettingsLogic with ThrottledSaveLoadMixin {
|
||||
|
||||
late final hasCompletedOnboarding = 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;
|
||||
|
||||
|
@ -3,18 +3,17 @@ import 'package:wonders/logic/common/string_utils.dart';
|
||||
import 'package:wonders/logic/data/timeline_data.dart';
|
||||
|
||||
class TimelineLogic {
|
||||
final List<TimelineEvent> events = [];
|
||||
List<TimelineEvent> events = [];
|
||||
|
||||
Future<void> init() async {
|
||||
events.addAll(GlobalEventsData().globalEvents);
|
||||
|
||||
for (var w in wondersLogic.all) {
|
||||
events.add(
|
||||
TimelineEvent(
|
||||
void init() {
|
||||
events = [
|
||||
...GlobalEventsData().globalEvents,
|
||||
...wondersLogic.all.map(
|
||||
(w) => TimelineEvent(
|
||||
w.startYr,
|
||||
StringUtils.supplant($strings.timelineLabelConstruction, {'{title}': w.title}),
|
||||
),
|
||||
);
|
||||
}
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -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';
|
||||
|
||||
class WondersLogic {
|
||||
late List<WonderData> all = [
|
||||
GreatWallData(),
|
||||
PetraData(),
|
||||
ColosseumData(),
|
||||
ChichenItzaData(),
|
||||
MachuPicchuData(),
|
||||
TajMahalData(),
|
||||
ChristRedeemerData(),
|
||||
PyramidsGizaData(),
|
||||
];
|
||||
List<WonderData> all = [];
|
||||
|
||||
final int timelineStartYear = -3000;
|
||||
final int timelineEndYear = 2200;
|
||||
@ -29,4 +20,17 @@ class WondersLogic {
|
||||
if (result == null) throw ('Could not find data for wonder type $value');
|
||||
return result;
|
||||
}
|
||||
|
||||
void init() {
|
||||
all = [
|
||||
GreatWallData(),
|
||||
PetraData(),
|
||||
ColosseumData(),
|
||||
ChichenItzaData(),
|
||||
MachuPicchuData(),
|
||||
TajMahalData(),
|
||||
ChristRedeemerData(),
|
||||
PyramidsGizaData(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -30,19 +30,25 @@ class WondersApp extends StatelessWidget {
|
||||
const WondersApp({Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp.router(
|
||||
debugShowCheckedModeBanner: false,
|
||||
routerDelegate: appRouter.routerDelegate,
|
||||
routeInformationProvider: appRouter.routeInformationProvider,
|
||||
routeInformationParser: appRouter.routeInformationParser,
|
||||
theme: ThemeData(fontFamily: $styles.text.body.fontFamily),
|
||||
localizationsDelegates: const [
|
||||
AppLocalizations.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
return ValueListenableBuilder<String>(
|
||||
valueListenable: settingsLogic.currentLocale,
|
||||
builder: (_, localeCode, __) {
|
||||
return MaterialApp.router(
|
||||
locale: Locale(localeCode),
|
||||
debugShowCheckedModeBanner: false,
|
||||
routerDelegate: appRouter.routerDelegate,
|
||||
routeInformationProvider: appRouter.routeInformationProvider,
|
||||
routeInformationParser: appRouter.routeInformationParser,
|
||||
theme: ThemeData(fontFamily: $styles.text.body.fontFamily),
|
||||
localizationsDelegates: const [
|
||||
AppLocalizations.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,15 @@ class WondersAppScaffold extends StatelessWidget with GetItMixin {
|
||||
WondersAppScaffold({Key? key, required this.child}) : super(key: key);
|
||||
final Widget child;
|
||||
|
||||
Future<void> _handleSwapLocale() async {
|
||||
final currentLocale = settingsLogic.currentLocale.value;
|
||||
final newLocale = Locale(currentLocale == 'en' ? 'zh' : 'en');
|
||||
settingsLogic.currentLocale.value = newLocale.languageCode;
|
||||
await localeLogic.refreshIfChanged(newLocale);
|
||||
wondersLogic.init();
|
||||
timelineLogic.init();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Animate.defaultDuration = $styles.times.fast;
|
||||
@ -22,6 +31,24 @@ class WondersAppScaffold extends StatelessWidget with GetItMixin {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
//TODO: just some test UI to check swapping behavior, need to get finalized design and location
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: SafeArea(
|
||||
child: TextButton(
|
||||
onPressed: _handleSwapLocale,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: $styles.colors.greyStrong.withOpacity(.7),
|
||||
borderRadius: BorderRadius.all(Radius.circular($styles.corners.md)),
|
||||
),
|
||||
padding: EdgeInsets.all($styles.insets.sm),
|
||||
child: Text($strings.localeSwapButton, style: $styles.text.btn.copyWith(color: $styles.colors.white)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -106,31 +106,35 @@ class HomeMenu extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _buildBottomBtns(BuildContext context) {
|
||||
return SeparatedColumn(
|
||||
separatorBuilder: () => Divider(thickness: 1.5, height: 1).animate().scale(
|
||||
duration: $styles.times.slow,
|
||||
delay: $styles.times.pageTransition + 200.ms,
|
||||
curve: Curves.easeOutBack,
|
||||
),
|
||||
children: [
|
||||
_MenuTextBtn(
|
||||
label: $strings.homeMenuButtonExplore,
|
||||
icon: AppIcons.timeline,
|
||||
onPressed: () => _handleTimelinePressed(context)),
|
||||
_MenuTextBtn(
|
||||
label: $strings.homeMenuButtonView,
|
||||
icon: AppIcons.collection,
|
||||
onPressed: () => _handleCollectionPressed(context)),
|
||||
_MenuTextBtn(
|
||||
label: $strings.homeMenuButtonAbout,
|
||||
icon: AppIcons.info,
|
||||
onPressed: () => _handleAboutPressed(context),
|
||||
),
|
||||
]
|
||||
.animate(interval: 50.ms)
|
||||
.fade(delay: $styles.times.pageTransition + 50.ms)
|
||||
.slide(begin: Offset(0, .1), curve: Curves.easeOut),
|
||||
);
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: settingsLogic.currentLocale,
|
||||
builder: (_, __, ___) {
|
||||
return SeparatedColumn(
|
||||
separatorBuilder: () => Divider(thickness: 1.5, height: 1).animate().scale(
|
||||
duration: $styles.times.slow,
|
||||
delay: $styles.times.pageTransition + 200.ms,
|
||||
curve: Curves.easeOutBack,
|
||||
),
|
||||
children: [
|
||||
_MenuTextBtn(
|
||||
label: $strings.homeMenuButtonExplore,
|
||||
icon: AppIcons.timeline,
|
||||
onPressed: () => _handleTimelinePressed(context)),
|
||||
_MenuTextBtn(
|
||||
label: $strings.homeMenuButtonView,
|
||||
icon: AppIcons.collection,
|
||||
onPressed: () => _handleCollectionPressed(context)),
|
||||
_MenuTextBtn(
|
||||
label: $strings.homeMenuButtonAbout,
|
||||
icon: AppIcons.info,
|
||||
onPressed: () => _handleAboutPressed(context),
|
||||
),
|
||||
]
|
||||
.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) {
|
||||
|
@ -19,11 +19,7 @@ class _IntroScreenState extends State<IntroScreen> {
|
||||
static const double _textHeight = 155;
|
||||
static const double _pageIndicatorHeight = 55;
|
||||
|
||||
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'),
|
||||
];
|
||||
static List<_PageData> pageData = [];
|
||||
|
||||
late final PageController _pageController = PageController()..addListener(_handlePageChanged);
|
||||
final ValueNotifier<int> _currentPage = ValueNotifier(0);
|
||||
@ -51,6 +47,13 @@ class _IntroScreenState extends State<IntroScreen> {
|
||||
|
||||
@override
|
||||
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.
|
||||
// However, we only want the title / description to actually swipe,
|
||||
// so we stack a PageView with that content over top of all the other
|
||||
|
Loading…
x
Reference in New Issue
Block a user