From ceccc53a980e26f549e890bee398b27a57dd7cf2 Mon Sep 17 00:00:00 2001 From: Levi Lesches Date: Thu, 20 Jul 2023 19:30:57 -0400 Subject: [PATCH] ;) --- logo.png => assets/logo.png | Bin assets/rover.png | Bin 0 -> 16078 bytes lib/src/data/settings.dart | 14 ++- lib/src/models/data/settings.dart | 3 + .../view/builders/settings_builder.dart | 31 ++++++- lib/src/pages/settings.dart | 8 +- lib/src/pages/splash.dart | 80 +++++++++++++----- pubspec.yaml | 12 +-- 8 files changed, 116 insertions(+), 32 deletions(-) rename logo.png => assets/logo.png (100%) create mode 100644 assets/rover.png diff --git a/logo.png b/assets/logo.png similarity index 100% rename from logo.png rename to assets/logo.png diff --git a/assets/rover.png b/assets/rover.png new file mode 100644 index 0000000000000000000000000000000000000000..a07a7f12728389eabf26647835d1086485b4a0a9 GIT binary patch literal 16078 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 literal 0 HcmV?d00001 diff --git a/lib/src/data/settings.dart b/lib/src/data/settings.dart index 43e628ac5..8a8e26843 100644 --- a/lib/src/data/settings.dart +++ b/lib/src/data/settings.dart @@ -200,14 +200,22 @@ class AutonomySettings { /// /// Implement these! Ask Levi for details. class EasterEggsSettings { + /// Whether to do a SEGA-like intro during boot. + final bool segaIntro; + /// A const constructor. - const EasterEggsSettings(); + const EasterEggsSettings({ + required this.segaIntro, + }); /// Parses easter eggs settings from JSON. - EasterEggsSettings.fromJson(Json? json); // ignore: avoid_unused_constructor_parameters + EasterEggsSettings.fromJson(Json? json) : + segaIntro = json?["segaIntro"] ?? true; /// Serializes these settings to JSON. - Json toJson() => { }; + Json toJson() => { + "segaIntro": segaIntro, + }; } /// Contains the settings for running the dashboard and the rover. diff --git a/lib/src/models/data/settings.dart b/lib/src/models/data/settings.dart index c3fe55aed..56b018aea 100644 --- a/lib/src/models/data/settings.dart +++ b/lib/src/models/data/settings.dart @@ -22,6 +22,9 @@ class SettingsModel extends Model { /// The user's autonomy settings. AutonomySettings get autonomy => all.autonomy; + /// The user's easter egg settings. + EasterEggsSettings get easterEggs => all.easterEggs; + @override Future init() async { all = await services.files.readSettings(); diff --git a/lib/src/models/view/builders/settings_builder.dart b/lib/src/models/view/builders/settings_builder.dart index fdd2f754f..d438475cb 100644 --- a/lib/src/models/view/builders/settings_builder.dart +++ b/lib/src/models/view/builders/settings_builder.dart @@ -211,6 +211,28 @@ class AutonomySettingsBuilder extends ValueBuilder { AutonomySettings get value => AutonomySettings(blockSize: blockSize.value); } +/// A [ValueBuilder] that modifies an [EasterEggsSettings]. +class EasterEggsSettingsBuilder extends ValueBuilder { + /// Whether to show a SEGA intro. See [EasterEggsSettings.segaIntro]. + bool segaIntro; + + /// Fills in the fields with the given [initial] settings. + EasterEggsSettingsBuilder(EasterEggsSettings initial) : + segaIntro = initial.segaIntro; + + @override + bool get isValid => true; + + @override + EasterEggsSettings get value => EasterEggsSettings(segaIntro: segaIntro); + + /// Updates the value of [EasterEggsSettings.segaIntro]. + void updateSegaIntro(bool input) { // ignore: avoid_positional_boolean_parameters + segaIntro = input; + notifyListeners(); + } +} + /// A [ValueBuilder] representing an [ArmSettings]. class SettingsBuilder extends ValueBuilder { /// The [NetworkSettings] view model. @@ -228,6 +250,9 @@ class SettingsBuilder extends ValueBuilder { /// The [AutonomySettings] view model. final AutonomySettingsBuilder autonomy; + /// The [EasterEggsSettings] view model. + final EasterEggsSettingsBuilder easterEggs; + /// Whether the page is loading. bool isLoading = false; @@ -237,13 +262,15 @@ class SettingsBuilder extends ValueBuilder { network = NetworkSettingsBuilder(models.settings.network), arm = ArmSettingsBuilder(models.settings.arm), video = VideoSettingsBuilder(models.settings.video), - science = ScienceSettingsBuilder(models.settings.science) + science = ScienceSettingsBuilder(models.settings.science), + easterEggs = EasterEggsSettingsBuilder(models.settings.easterEggs) { autonomy.addListener(notifyListeners); network.addListener(notifyListeners); arm.addListener(notifyListeners); video.addListener(notifyListeners); science.addListener(notifyListeners); + easterEggs.addListener(notifyListeners); } @override @@ -258,7 +285,7 @@ class SettingsBuilder extends ValueBuilder { autonomy: autonomy.value, network: network.value, video: video.value, - easterEggs: const EasterEggsSettings(), + easterEggs: easterEggs.value, science: science.value, arm: arm.value, ); diff --git a/lib/src/pages/settings.dart b/lib/src/pages/settings.dart index 5b4301d21..875cc50dd 100644 --- a/lib/src/pages/settings.dart +++ b/lib/src/pages/settings.dart @@ -132,10 +132,14 @@ class SettingsPage extends StatelessWidget { ], ), const Divider(), - const ValueEditor( + ValueEditor( name: "Easter eggs", children: [ - ListTile(title: Text("Coming soon!")), + SwitchListTile( + title: const Text("Enable SEGA Intro"), + value: model.easterEggs.segaIntro, + onChanged: model.easterEggs.updateSegaIntro, + ), ], ), const Divider(), diff --git a/lib/src/pages/splash.dart b/lib/src/pages/splash.dart index 3d5a94168..6911cff8c 100644 --- a/lib/src/pages/splash.dart +++ b/lib/src/pages/splash.dart @@ -4,6 +4,7 @@ import "package:flutter/services.dart"; import "package:rover_dashboard/models.dart"; import "package:rover_dashboard/pages.dart"; import "package:rover_dashboard/services.dart"; +import "package:rover_dashboard/widgets.dart"; /// Initializes the dashboard and handles errors. class SplashPage extends StatefulWidget { @@ -11,6 +12,16 @@ class SplashPage extends StatefulWidget { SplashPageState createState() => SplashPageState(); } +/// The state of the SEGA animation. +enum SegaState { + /// The rover is off-screen to the left, facing the right, and the text is transparent. + partOne, + /// The rover is off-screen to the right, facing the right, and the text is 30% opaque. + partTwo, + /// The rover is off-screen to the left, facing the left, and the text is 100% opaque. + partThree, +} + /// Initializes the dashboard and handles errors. class SplashPageState extends State{ /// The error message produced during initialization, if any. @@ -19,12 +30,24 @@ class SplashPageState extends State{ /// The current task, if any. String? current; + /// The state of the SEGA animation. + SegaState state = SegaState.partOne; + @override void initState() { super.initState(); init(); } + /// Starts the SEGA animation. + Future initAnimation() async { + // await Future.delayed(const Duration(milliseconds: 1000)); + setState(() => state = SegaState.partTwo); + await Future.delayed(const Duration(milliseconds: 1000)); + setState(() => state = SegaState.partThree); + await Future.delayed(const Duration(milliseconds: 1000)); + } + /// Calls [Services.init] and [Models.init] while monitoring for errors. Future init() async { try { @@ -37,34 +60,51 @@ class SplashPageState extends State{ current = "models"; await models.init(); + if (models.settings.easterEggs.segaIntro) await initAnimation(); + if (mounted) { + await Navigator.of(context).pushReplacementNamed(Routes.home); + } } catch (error) { setState(() => errorText = error.toString()); rethrow; } - - if (mounted) { - await Navigator.of(context).pushReplacementNamed(Routes.home); - } } @override Widget build(BuildContext context) => Scaffold( - body: Center(child: errorText == null - ? const CircularProgressIndicator() - : Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Spacer(flex: 2), - Text("Something went wrong", style: Theme.of(context).textTheme.displayLarge), - const Spacer(), - Text("The error occurred when trying to initialize $current", style: Theme.of(context).textTheme.headlineLarge), - const SizedBox(height: 24), - Text("Here is the exact error:", style: Theme.of(context).textTheme.titleLarge), - const SizedBox(height: 16), - Text(errorText!), - const Spacer(flex: 2), - ], - ), + body: Stack( + alignment: Alignment.center, + children: [ + AnimatedOpacity( + duration: const Duration(milliseconds: 1000), + opacity: switch (state) { + SegaState.partOne => 0, + SegaState.partTwo => 0.3, + SegaState.partThree => 1, + }, + child: Text("Binghamton University\nRover Team", textAlign: TextAlign.center, style: context.textTheme.displayMedium), + ), + AnimatedAlign( + duration: const Duration(milliseconds: 750), + alignment: switch (state) { + SegaState.partOne => const Alignment(-1.5, 0), + SegaState.partTwo => const Alignment(1.5, 0), + SegaState.partThree => const Alignment(-1.5, 0), + }, + child: Transform.flip( + flipX: switch (state) { + SegaState.partOne => true, + SegaState.partTwo => true, + SegaState.partThree => false, + }, + child: SizedBox( + width: 150, + height: 150, + child: Image.asset("assets/rover.png"), + ), + ), + ), + ], ), ); } diff --git a/pubspec.yaml b/pubspec.yaml index 1d62ea2c8..8ff528b21 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,18 +44,18 @@ dependency_overrides: # Generates icons for the given platforms # Run: flutter pub run icons_launcher:create icons_launcher: - image_path: "logo.png" + image_path: "assets/logo.png" platforms: android: - # adaptive_foreground_image: "logo.png" + # adaptive_foreground_image: "assets/logo.png" # adaptive_background_color: "#000000" - # adaptive_monochrome_image: "logo.png" + # adaptive_monochrome_image: "assets/logo.png" enable: true windows: enable: true flutter_launcher_icons: - image_path: "logo.png" + image_path: "assets/logo.png" android: true windows: generate: true @@ -67,7 +67,7 @@ msix_config: display_name: Dashboard publisher_display_name: Binghamton University Rover Team identity_name: edu.binghamton.rover - logo_path: logo.png + logo_path: assets/logo.png trim_logo: false capabilities: internetClientServer, privateNetworkClientServer, usb, serialcommunication, lowLevel output_name: Dashboard @@ -78,3 +78,5 @@ msix_config: # The following section is specific to Flutter packages. flutter: uses-material-design: true + assets: + - assets/rover.png