Fix crash, goldens, demo status bar icon color (#936)

## Description

For 2.10.1 release:

1. Fix a common crash when opening a demo for the first time, caused by
feature discovery. `shared_preferences` had undesireable asynchronous
behavior, so I replaced it with `get_storage`.

2. I also wanted to fix the goldens test, but found the `Positioned`
widget around the settings icon was unnecessarily adding padding, so
removed it.

<img width="400" alt="image"
src="https://user-images.githubusercontent.com/6655696/234592889-8a82bf98-49d8-42d8-a7b4-b24eda263a38.png">

3. Fix the demo status bar icon color in light mode to use the correct
`SystemUiOverlayStyle`.


## Tests

Tested manually

## Issues
Fixes Firebase-detected crash
diff --git a/lib/feature_discovery/feature_discovery.dart b/lib/feature_discovery/feature_discovery.dart
index 353d758..288c78b 100644
--- a/lib/feature_discovery/feature_discovery.dart
+++ b/lib/feature_discovery/feature_discovery.dart
@@ -4,9 +4,11 @@
 
 import 'package:flutter/material.dart';
 import 'package:flutter/scheduler.dart';
-
 import 'package:gallery/feature_discovery/animation.dart';
 import 'package:gallery/feature_discovery/overlay.dart';
+import 'package:get_storage/get_storage.dart';
+
+const _featureHighlightShownKey = 'feature_highlight_shown';
 
 /// [Widget] to enforce a global lock system for [FeatureDiscovery] widgets.
 ///
@@ -269,7 +271,15 @@
 
     initAnimationControllers();
     initAnimations();
-    showOverlay = widget.showOverlay;
+
+    final localStorage = GetStorage();
+    final featureHiglightShown =
+        localStorage.read<bool>(_featureHighlightShownKey) ?? false;
+    localStorage.write(_featureHighlightShownKey, true);
+    showOverlay = widget.showOverlay && !featureHiglightShown;
+    if (showOverlay) {
+      localStorage.write(_featureHighlightShownKey, true);
+    }
   }
 
   void initAnimationControllers() {
diff --git a/lib/feature_discovery/overlay.dart b/lib/feature_discovery/overlay.dart
index 131836d..f52ca00 100644
--- a/lib/feature_discovery/overlay.dart
+++ b/lib/feature_discovery/overlay.dart
@@ -5,7 +5,6 @@
 import 'dart:math';
 
 import 'package:flutter/material.dart';
-
 import 'package:gallery/feature_discovery/animation.dart';
 
 const contentHeight = 80.0;
@@ -311,6 +310,7 @@
 
   @override
   Widget build(BuildContext context) {
+    final ThemeData theme = Theme.of(context);
     return Positioned(
       left: center.dx,
       top: center.dy,
@@ -323,8 +323,10 @@
             child: Container(
               height: radius * 2,
               width: radius * 2,
-              decoration: const BoxDecoration(
-                color: Colors.white,
+              decoration: BoxDecoration(
+                color: theme.brightness == Brightness.dark
+                    ? theme.colorScheme.primary
+                    : Colors.white,
                 shape: BoxShape.circle,
               ),
               child: child,
diff --git a/lib/main.dart b/lib/main.dart
index 89cdfee..9bd98b7 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -16,6 +16,7 @@
 import 'package:gallery/pages/splash.dart';
 import 'package:gallery/routes.dart';
 import 'package:gallery/themes/gallery_theme_data.dart';
+import 'package:get_storage/get_storage.dart';
 import 'package:google_fonts/google_fonts.dart';
 
 import 'firebase_options.dart';
@@ -25,6 +26,7 @@
 
 void main() async {
   GoogleFonts.config.allowRuntimeFetching = false;
+  await GetStorage.init();
 
   if (defaultTargetPlatform != TargetPlatform.linux &&
       defaultTargetPlatform != TargetPlatform.windows) {
diff --git a/lib/pages/backdrop.dart b/lib/pages/backdrop.dart
index d36de51..840d0c5 100644
--- a/lib/pages/backdrop.dart
+++ b/lib/pages/backdrop.dart
@@ -221,14 +221,10 @@
               ),
             ),
           ],
-          Positioned(
-            top: 12,
-            right: 0,
-            child: _SettingsIcon(
-              animationController: _iconController,
-              toggleSettings: _toggleSettings,
-              isSettingsOpenNotifier: _isSettingsOpenNotifier,
-            ),
+          _SettingsIcon(
+            animationController: _iconController,
+            toggleSettings: _toggleSettings,
+            isSettingsOpenNotifier: _isSettingsOpenNotifier,
           ),
         ],
       ),
diff --git a/lib/pages/demo.dart b/lib/pages/demo.dart
index 00d4b2b..b06f98f 100644
--- a/lib/pages/demo.dart
+++ b/lib/pages/demo.dart
@@ -2,11 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' show Platform;
-
 import 'package:dual_screen/dual_screen.dart';
 import 'package:flutter/cupertino.dart';
-import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_gen/gen_l10n/gallery_localizations.dart';
@@ -21,11 +18,8 @@
 import 'package:gallery/themes/gallery_theme_data.dart';
 import 'package:gallery/themes/material_demo_theme_data.dart';
 import 'package:google_fonts/google_fonts.dart';
-import 'package:shared_preferences/shared_preferences.dart';
 import 'package:url_launcher/url_launcher_string.dart';
 
-const _demoViewedCountKey = 'demoViewedCountKey';
-
 enum _DemoState {
   normal,
   options,
@@ -94,8 +88,6 @@
   final RestorableInt _configIndex = RestorableInt(0);
 
   bool? _isDesktop;
-  bool _showFeatureHighlight = true;
-  late int _demoViewedCount;
 
   late AnimationController _codeBackgroundColorController;
 
@@ -114,19 +106,6 @@
 
   bool get _hasOptions => widget.demo.configurations.length > 1;
 
-  bool get _isSupportedSharedPreferencesPlatform =>
-      !kIsWeb && (Platform.isAndroid || Platform.isIOS);
-
-  // Only show the feature highlight on Android/iOS, in mobile layout, non-test
-  // mode, and only on the first and fourth time the demo page is viewed.
-  bool _showFeatureHighlightForPlatform(BuildContext context) {
-    return _showFeatureHighlight &&
-        _isSupportedSharedPreferencesPlatform &&
-        !isDisplayDesktop(context) &&
-        !GalleryOptions.of(context).isTestMode &&
-        (_demoViewedCount == 0 || _demoViewedCount == 3);
-  }
-
   @override
   void initState() {
     super.initState();
@@ -134,12 +113,6 @@
       vsync: this,
       duration: const Duration(milliseconds: 300),
     );
-    SharedPreferences.getInstance().then((preferences) {
-      setState(() {
-        _demoViewedCount = preferences.getInt(_demoViewedCountKey) ?? 0;
-        preferences.setInt(_demoViewedCountKey, _demoViewedCount + 1);
-      });
-    });
   }
 
   @override
@@ -245,8 +218,10 @@
     final appBarPadding = isDesktop ? 20.0 : 0.0;
     final currentDemoState = _DemoState.values[_demoStateIndex.value];
     final localizations = GalleryLocalizations.of(context)!;
+    final options = GalleryOptions.of(context);
 
     final appBar = AppBar(
+      systemOverlayStyle: options.resolvedSystemUiOverlayStyle(),
       backgroundColor: Colors.transparent,
       leading: Padding(
         padding: EdgeInsetsDirectional.only(start: appBarPadding),
@@ -265,22 +240,12 @@
             icon: FeatureDiscovery(
               title: localizations.demoOptionsFeatureTitle,
               description: localizations.demoOptionsFeatureDescription,
-              showOverlay: _showFeatureHighlightForPlatform(context),
+              showOverlay: !isDisplayDesktop(context) && !options.isTestMode,
               color: colorScheme.primary,
-              onDismiss: () {
-                setState(() {
-                  _showFeatureHighlight = false;
-                });
-              },
-              onTap: () {
-                setState(() {
-                  _showFeatureHighlight = false;
-                });
-              },
+              onTap: () => _handleTap(_DemoState.options),
               child: Icon(
                 Icons.tune,
-                color: currentDemoState == _DemoState.options ||
-                        _showFeatureHighlightForPlatform(context)
+                color: currentDemoState == _DemoState.options
                     ? selectedIconColor
                     : iconColor,
               ),
@@ -361,7 +326,7 @@
         break;
       case _DemoState.code:
         final codeTheme = GoogleFonts.robotoMono(
-          fontSize: 12 * GalleryOptions.of(context).textScaleFactor(context),
+          fontSize: 12 * options.textScaleFactor(context),
         );
         section = CodeStyle(
           baseStyle: codeTheme.copyWith(color: const Color(0xFFFAFBFB)),
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index fe519ea..9438fd6 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -9,7 +9,6 @@
 import firebase_crashlytics
 import package_info_plus
 import path_provider_foundation
-import shared_preferences_foundation
 import url_launcher_macos
 
 func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
@@ -17,6 +16,5 @@
   FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin"))
   FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
   PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
-  SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
   UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
 }
diff --git a/macos/Podfile.lock b/macos/Podfile.lock
index 69ee27b..7056c0d 100644
--- a/macos/Podfile.lock
+++ b/macos/Podfile.lock
@@ -66,9 +66,6 @@
   - PromisesObjC (2.2.0)
   - PromisesSwift (2.2.0):
     - PromisesObjC (= 2.2.0)
-  - shared_preferences_foundation (0.0.1):
-    - Flutter
-    - FlutterMacOS
   - url_launcher_macos (0.0.1):
     - FlutterMacOS
 
@@ -78,7 +75,6 @@
   - FlutterMacOS (from `Flutter/ephemeral`)
   - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
   - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
-  - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
   - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
 
 SPEC REPOS:
@@ -107,8 +103,6 @@
     :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
   path_provider_foundation:
     :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
-  shared_preferences_foundation:
-    :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
   url_launcher_macos:
     :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
 
@@ -130,7 +124,6 @@
   path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
   PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
   PromisesSwift: cf9eb58666a43bbe007302226e510b16c1e10959
-  shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
   url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
 
 PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
diff --git a/pubspec.lock b/pubspec.lock
index 8a7cb1e..2ac011e 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -295,6 +295,22 @@
     description: flutter
     source: sdk
     version: "0.0.0"
+  get:
+    dependency: transitive
+    description:
+      name: get
+      sha256: "2ba20a47c8f1f233bed775ba2dd0d3ac97b4cf32fc17731b3dfc672b06b0e92a"
+      url: "https://pub.dev"
+    source: hosted
+    version: "4.6.5"
+  get_storage:
+    dependency: "direct main"
+    description:
+      name: get_storage
+      sha256: "39db1fffe779d0c22b3a744376e86febe4ade43bf65e06eab5af707dc84185a2"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.1"
   glob:
     dependency: transitive
     description:
@@ -575,62 +591,6 @@
       url: "https://pub.dev"
     source: hosted
     version: "2.0.0"
-  shared_preferences:
-    dependency: "direct main"
-    description:
-      name: shared_preferences
-      sha256: "858aaa72d8f61637d64e776aca82e1c67e6d9ee07979123c5d17115031c1b13b"
-      url: "https://pub.dev"
-    source: hosted
-    version: "2.1.0"
-  shared_preferences_android:
-    dependency: transitive
-    description:
-      name: shared_preferences_android
-      sha256: "7fa90471a6875d26ad78c7e4a675874b2043874586891128dc5899662c97db46"
-      url: "https://pub.dev"
-    source: hosted
-    version: "2.1.2"
-  shared_preferences_foundation:
-    dependency: transitive
-    description:
-      name: shared_preferences_foundation
-      sha256: "0c1c16c56c9708aa9c361541a6f0e5cc6fc12a3232d866a687a7b7db30032b07"
-      url: "https://pub.dev"
-    source: hosted
-    version: "2.2.1"
-  shared_preferences_linux:
-    dependency: transitive
-    description:
-      name: shared_preferences_linux
-      sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa"
-      url: "https://pub.dev"
-    source: hosted
-    version: "2.2.0"
-  shared_preferences_platform_interface:
-    dependency: transitive
-    description:
-      name: shared_preferences_platform_interface
-      sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d
-      url: "https://pub.dev"
-    source: hosted
-    version: "2.2.0"
-  shared_preferences_web:
-    dependency: transitive
-    description:
-      name: shared_preferences_web
-      sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5"
-      url: "https://pub.dev"
-    source: hosted
-    version: "2.1.0"
-  shared_preferences_windows:
-    dependency: transitive
-    description:
-      name: shared_preferences_windows
-      sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173"
-      url: "https://pub.dev"
-    source: hosted
-    version: "2.2.0"
   shelf:
     dependency: transitive
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 6a79b6d..ec86f62 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,7 +1,7 @@
 name: gallery
 description: A resource to help developers evaluate and use Flutter.
 repository: https://github.com/flutter/gallery
-version: 2.10.0+021000 # See README.md for details on versioning.
+version: 2.10.1+021001 # See README.md for details on versioning.
 
 environment:
   flutter: ^3.10.0-10.0.pre.17 # Keep relatively close to master channel version
@@ -23,6 +23,7 @@
   firebase_core: ^2.7.0
   firebase_crashlytics: ^3.1.1
   firebase_performance: ^0.9.0+14
+  get_storage: ^2.1.1
   google_fonts: ^4.0.1
   intl: any # An exact version pin will be provided by the Flutter SDK
   meta: ^1.7.0
@@ -31,7 +32,6 @@
   provider: ^6.0.2
   rally_assets: ^3.0.1
   scoped_model: ^2.0.0
-  shared_preferences: ^2.0.15
   shrine_images: ^2.0.1
   transparent_image: ^2.0.1
   url_launcher: ^6.1.2
diff --git a/test_goldens/flutter_test_config.dart b/test_goldens/flutter_test_config.dart
index 36634ff..87f1a15 100644
--- a/test_goldens/flutter_test_config.dart
+++ b/test_goldens/flutter_test_config.dart
@@ -6,7 +6,6 @@
 import 'dart:io';
 
 import 'package:flutter_test/flutter_test.dart';
-import 'package:shared_preferences/shared_preferences.dart';
 
 import 'testing/font_loader.dart';
 
@@ -21,10 +20,6 @@
   };
 
   TestWidgetsFlutterBinding.ensureInitialized();
-  // Disabling the warning because @visibleForTesting doesn't take the testing
-  // framework into account.
-  // ignore: invalid_use_of_visible_for_testing_member
-  SharedPreferences.setMockInitialValues(<String, String>{});
   await loadFonts();
   await testMain();
 }
diff --git a/test_goldens/goldens/demo_desktop_dark.png b/test_goldens/goldens/demo_desktop_dark.png
index 1c2074d..a89407d 100644
--- a/test_goldens/goldens/demo_desktop_dark.png
+++ b/test_goldens/goldens/demo_desktop_dark.png
Binary files differ
diff --git a/test_goldens/goldens/demo_desktop_light.png b/test_goldens/goldens/demo_desktop_light.png
index ea17e8e..dbfb4f7 100644
--- a/test_goldens/goldens/demo_desktop_light.png
+++ b/test_goldens/goldens/demo_desktop_light.png
Binary files differ
diff --git a/test_goldens/goldens/demo_mobile_dark.png b/test_goldens/goldens/demo_mobile_dark.png
index 880e831..ee45c89 100644
--- a/test_goldens/goldens/demo_mobile_dark.png
+++ b/test_goldens/goldens/demo_mobile_dark.png
Binary files differ
diff --git a/test_goldens/goldens/demo_mobile_light.png b/test_goldens/goldens/demo_mobile_light.png
index b33d241..e9d77c6 100644
--- a/test_goldens/goldens/demo_mobile_light.png
+++ b/test_goldens/goldens/demo_mobile_light.png
Binary files differ
diff --git a/test_goldens/goldens/home_page_desktop_dark.png b/test_goldens/goldens/home_page_desktop_dark.png
index 3737c31..68abe6e 100644
--- a/test_goldens/goldens/home_page_desktop_dark.png
+++ b/test_goldens/goldens/home_page_desktop_dark.png
Binary files differ
diff --git a/test_goldens/goldens/home_page_desktop_light.png b/test_goldens/goldens/home_page_desktop_light.png
index 1fcd9b1..25b0a7a 100644
--- a/test_goldens/goldens/home_page_desktop_light.png
+++ b/test_goldens/goldens/home_page_desktop_light.png
Binary files differ
diff --git a/test_goldens/goldens/home_page_mobile_dark.png b/test_goldens/goldens/home_page_mobile_dark.png
index d6d6e32..815c010 100644
--- a/test_goldens/goldens/home_page_mobile_dark.png
+++ b/test_goldens/goldens/home_page_mobile_dark.png
Binary files differ
diff --git a/test_goldens/goldens/home_page_mobile_light.png b/test_goldens/goldens/home_page_mobile_light.png
index d60e50c..9ba23f8 100644
--- a/test_goldens/goldens/home_page_mobile_light.png
+++ b/test_goldens/goldens/home_page_mobile_light.png
Binary files differ
diff --git a/test_goldens/goldens/shrine_desktop.png b/test_goldens/goldens/shrine_desktop.png
index 3cff9d4..a3a9793 100644
--- a/test_goldens/goldens/shrine_desktop.png
+++ b/test_goldens/goldens/shrine_desktop.png
Binary files differ
diff --git a/test_goldens/goldens/shrine_mobile.png b/test_goldens/goldens/shrine_mobile.png
index b2820e4..f7ca89a 100644
--- a/test_goldens/goldens/shrine_mobile.png
+++ b/test_goldens/goldens/shrine_mobile.png
Binary files differ