diff --git a/android/app/src/main/kotlin/com/codel1417/tail_app/MainActivity.kt b/android/app/src/main/kotlin/com/codel1417/tail_app/MainActivity.kt index 11c5a241..2804fb34 100644 --- a/android/app/src/main/kotlin/com/codel1417/tail_app/MainActivity.kt +++ b/android/app/src/main/kotlin/com/codel1417/tail_app/MainActivity.kt @@ -1,5 +1,7 @@ package com.codel1417.tail_app +import android.os.Build +import android.os.Bundle import android.view.KeyEvent import android.view.KeyEvent.KEYCODE_VOLUME_DOWN import android.view.KeyEvent.KEYCODE_VOLUME_UP @@ -8,6 +10,13 @@ import io.flutter.embedding.android.FlutterActivity class MainActivity : FlutterActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + window.setDecorFitsSystemWindows(false) + } + } override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { if (keyCode == KEYCODE_VOLUME_DOWN && eventSink != null) { diff --git a/lib/Frontend/pages/intro.dart b/lib/Frontend/pages/intro.dart index d3139278..157078a5 100644 --- a/lib/Frontend/pages/intro.dart +++ b/lib/Frontend/pages/intro.dart @@ -46,6 +46,7 @@ class OnBoardingPageState extends ConsumerState { @override Widget build(BuildContext context) { + setupSystemColor(context); var pageDecoration = PageDecoration( titleTextStyle: const TextStyle(fontSize: 28.0, fontWeight: FontWeight.w700), bodyTextStyle: const TextStyle(fontSize: 19.0), @@ -59,177 +60,174 @@ class OnBoardingPageState extends ConsumerState { bodyFlex: 6, safeArea: 0, ); - - return SafeArea( - child: ValueListenableBuilder( - valueListenable: isBluetoothEnabled, - builder: (BuildContext context, bool bluetoothEnabled, Widget? child) { - return IntroductionScreen( - key: introKey, - canProgress: (page) { - if (page == 2 && !bluetoothAccepted && bluetoothEnabled) { - return false; - } else if (page == 1 && !privacyAccepted) { - return false; - } - return true; - }, - globalBackgroundColor: Theme.of(context).canvasColor, - allowImplicitScrolling: true, - globalHeader: Align( - alignment: Alignment.topRight, - child: SafeArea( - child: Padding( - padding: const EdgeInsets.only(top: 16, right: 16), - child: InkWell( - child: _buildImage(Assets.tCLogoTransparentNoText.path, 60), - onLongPress: () { - _introLogger.info("Open Logs"); - context.push("/settings/developer/logs"); - }, - ), + return ValueListenableBuilder( + valueListenable: isBluetoothEnabled, + builder: (BuildContext context, bool bluetoothEnabled, Widget? child) { + return IntroductionScreen( + key: introKey, + canProgress: (page) { + if (page == 2 && !bluetoothAccepted && bluetoothEnabled) { + return false; + } else if (page == 1 && !privacyAccepted) { + return false; + } + return true; + }, + globalBackgroundColor: Theme.of(context).canvasColor, + allowImplicitScrolling: true, + globalHeader: Align( + alignment: Alignment.topRight, + child: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 16, right: 16), + child: InkWell( + child: _buildImage(Assets.tCLogoTransparentNoText.path, 60), + onLongPress: () { + _introLogger.info("Open Logs"); + context.push("/settings/developer/logs"); + }, ), ), ), - pages: [ - PageViewModel( - title: homeWelcomeMessageTitle(), - body: homeWelcomeMessage(), - image: LottieLazyLoad( - asset: Assets.tailcostickers.tailCoStickersFile144834354, - width: MediaQuery.of(context).size.width, - ), - decoration: pageDecoration, + ), + pages: [ + PageViewModel( + title: homeWelcomeMessageTitle(), + body: homeWelcomeMessage(), + image: LottieLazyLoad( + asset: Assets.tailcostickers.tailCoStickersFile144834354, + width: MediaQuery.of(context).size.width, ), - PageViewModel( - title: morePrivacyPolicyLinkTitle(), - body: onboardingPrivacyPolicyDescription(), - image: LottieLazyLoad( - asset: Assets.tailcostickers.tailCoStickersFile144834359, - width: MediaQuery.of(context).size.width, - ), - footer: ButtonBar( - alignment: MainAxisAlignment.center, - children: [ - ElevatedButton( - onPressed: () async { - await launchUrl(Uri.parse('https://github.com/Codel1417/tail_app/blob/master/PRIVACY.md')); - }, - child: Text( - onboardingPrivacyPolicyViewButtonLabel(), - ), - ), - FilledButton( - onPressed: privacyAccepted - ? null - : () { - setState(() { - _introLogger.info("Accepted Privacy Policy"); - privacyAccepted = true; - HiveProxy.put(settings, allowErrorReporting, true); - HiveProxy.put(settings, allowAnalytics, true); - introKey.currentState?.next(); - }); - }, - child: Text( - onboardingPrivacyPolicyAcceptButtonLabel(), - ), - ) - ], - ), - decoration: pageDecoration, + decoration: pageDecoration, + ), + PageViewModel( + title: morePrivacyPolicyLinkTitle(), + body: onboardingPrivacyPolicyDescription(), + image: LottieLazyLoad( + asset: Assets.tailcostickers.tailCoStickersFile144834359, + width: MediaQuery.of(context).size.width, ), - PageViewModel( - title: onboardingBluetoothTitle(), - body: onboardingBluetoothDescription(), - image: LottieLazyLoad( - asset: Assets.tailcostickers.tailCoStickersFile144834357, - width: MediaQuery.of(context).size.width, - ), - footer: ButtonBar( - alignment: MainAxisAlignment.center, - children: [ - FilledButton( - onPressed: bluetoothEnabled - ? null - : () { - AppSettings.openAppSettings(type: AppSettingsType.bluetooth); - }, - child: Text( - onboardingBluetoothEnableButtonLabel(), - ), + footer: ButtonBar( + alignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: () async { + await launchUrl(Uri.parse('https://github.com/Codel1417/tail_app/blob/master/PRIVACY.md')); + }, + child: Text( + onboardingPrivacyPolicyViewButtonLabel(), ), - FilledButton( - onPressed: bluetoothAccepted - ? null - : () async { - if (await getBluetoothPermission(_introLogger)) { - setState( - () { - // Start FlutterBluePlus - if (!ref.exists(initFlutterBluePlusProvider)) { - ref.read(initFlutterBluePlusProvider); - } - bluetoothAccepted = true; - }, - ); - introKey.currentState?.next(); - } - }, - child: Text( - onboardingBluetoothRequestButtonLabel(), - ), - ) - ], - ), - decoration: pageDecoration, - ), - PageViewModel( - title: onboardingCompletedTitle(), - body: "", - image: LottieLazyLoad( - asset: Assets.tailcostickers.tailCoStickersFile144834338, - width: MediaQuery.of(context).size.width, - ), - decoration: pageDecoration.copyWith( - bodyFlex: 2, - imageFlex: 4, - bodyAlignment: Alignment.bottomCenter, - imageAlignment: Alignment.topCenter, - imagePadding: const EdgeInsets.symmetric(vertical: 32), - contentMargin: const EdgeInsets.only(top: 32), - ), - reverse: true, + ), + FilledButton( + onPressed: privacyAccepted + ? null + : () { + setState(() { + _introLogger.info("Accepted Privacy Policy"); + privacyAccepted = true; + HiveProxy.put(settings, allowErrorReporting, true); + HiveProxy.put(settings, allowAnalytics, true); + introKey.currentState?.next(); + }); + }, + child: Text( + onboardingPrivacyPolicyAcceptButtonLabel(), + ), + ) + ], ), - ], - onDone: () => _onIntroEnd(context), - onSkip: () => _onIntroEnd(context), - // You can override onSkip callback - //rtl: true, // Display as right-to-left - back: const Icon(Icons.arrow_back), - next: const Icon( - Icons.arrow_forward, - key: Key('nextPage'), + decoration: pageDecoration, ), - done: FilledButton( - onPressed: () { - _onIntroEnd(context); - }, - child: Text(onboardingDoneButtonLabel(), style: const TextStyle(fontWeight: FontWeight.w600)), + PageViewModel( + title: onboardingBluetoothTitle(), + body: onboardingBluetoothDescription(), + image: LottieLazyLoad( + asset: Assets.tailcostickers.tailCoStickersFile144834357, + width: MediaQuery.of(context).size.width, + ), + footer: ButtonBar( + alignment: MainAxisAlignment.center, + children: [ + FilledButton( + onPressed: bluetoothEnabled + ? null + : () { + AppSettings.openAppSettings(type: AppSettingsType.bluetooth); + }, + child: Text( + onboardingBluetoothEnableButtonLabel(), + ), + ), + FilledButton( + onPressed: bluetoothAccepted + ? null + : () async { + if (await getBluetoothPermission(_introLogger)) { + setState( + () { + // Start FlutterBluePlus + if (!ref.exists(initFlutterBluePlusProvider)) { + ref.read(initFlutterBluePlusProvider); + } + bluetoothAccepted = true; + }, + ); + introKey.currentState?.next(); + } + }, + child: Text( + onboardingBluetoothRequestButtonLabel(), + ), + ) + ], + ), + decoration: pageDecoration, ), - dotsFlex: 1, - controlsPadding: const EdgeInsets.symmetric(vertical: 32), - dotsDecorator: DotsDecorator( - size: const Size.square(10.0), - activeSize: const Size(40.0, 10.0), - activeColor: Theme.of(context).colorScheme.primary, - color: Theme.of(context).colorScheme.tertiary, - spacing: const EdgeInsets.symmetric(horizontal: 3.0), - activeShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50.0)), + PageViewModel( + title: onboardingCompletedTitle(), + body: "", + image: LottieLazyLoad( + asset: Assets.tailcostickers.tailCoStickersFile144834338, + width: MediaQuery.of(context).size.width, + ), + decoration: pageDecoration.copyWith( + bodyFlex: 2, + imageFlex: 4, + bodyAlignment: Alignment.bottomCenter, + imageAlignment: Alignment.topCenter, + imagePadding: const EdgeInsets.symmetric(vertical: 32), + contentMargin: const EdgeInsets.only(top: 32), + ), + reverse: true, ), - ); - }, - ), + ], + onDone: () => _onIntroEnd(context), + onSkip: () => _onIntroEnd(context), + // You can override onSkip callback + //rtl: true, // Display as right-to-left + back: const Icon(Icons.arrow_back), + next: const Icon( + Icons.arrow_forward, + key: Key('nextPage'), + ), + done: FilledButton( + onPressed: () { + _onIntroEnd(context); + }, + child: Text(onboardingDoneButtonLabel(), style: const TextStyle(fontWeight: FontWeight.w600)), + ), + dotsFlex: 1, + controlsPadding: const EdgeInsets.symmetric(vertical: 32), + dotsDecorator: DotsDecorator( + size: const Size.square(10.0), + activeSize: const Size(40.0, 10.0), + activeColor: Theme.of(context).colorScheme.primary, + color: Theme.of(context).colorScheme.tertiary, + spacing: const EdgeInsets.symmetric(horizontal: 3.0), + activeShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50.0)), + ), + ); + }, ); } } diff --git a/lib/Frontend/pages/shell.dart b/lib/Frontend/pages/shell.dart index e44187c1..55c06a41 100644 --- a/lib/Frontend/pages/shell.dart +++ b/lib/Frontend/pages/shell.dart @@ -2,7 +2,6 @@ import 'package:fading_edge_scrollview/fading_edge_scrollview.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flex_color_picker/flex_color_picker.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -63,7 +62,7 @@ class _NavigationDrawerExampleState extends ConsumerState setupSystemColor(BuildContext context) async { + final SystemUiOverlayStyle dark = SystemUiOverlayStyle( + statusBarColor: Colors.transparent /*Android=23*/, + statusBarBrightness: Brightness.light /*iOS*/, + statusBarIconBrightness: Brightness.dark /*Android=23*/, + systemStatusBarContrastEnforced: false /*Android=29*/, + systemNavigationBarColor: Colors.transparent /*Android=27*/, + systemNavigationBarDividerColor: Colors.transparent.withAlpha(1) /*Android=28,不能用全透明 */, + systemNavigationBarIconBrightness: Brightness.dark /*Android=27*/, + systemNavigationBarContrastEnforced: false /*Android=29*/, + ); + final SystemUiOverlayStyle light = SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + // 23 + statusBarIconBrightness: Brightness.dark, + // 23 + systemNavigationBarColor: Colors.transparent, + // 27 + systemStatusBarContrastEnforced: false /*Android=29*/, + systemNavigationBarDividerColor: Colors.transparent.withAlpha(1) /* 不能用全透明 */, + // 28 + systemNavigationBarIconBrightness: Brightness.dark, + // 27 + systemNavigationBarContrastEnforced: false, // 29 + ); + if (Theme.of(context).colorScheme.brightness == Brightness.light) { + SystemChrome.setSystemUIOverlayStyle(light); + } else { + SystemChrome.setSystemUIOverlayStyle(dark); + } + await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); +} diff --git a/lib/main.dart b/lib/main.dart index f9a2e566..09eab65b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,7 +6,6 @@ import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:feedback_sentry/feedback_sentry.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -217,11 +216,7 @@ class _TailAppState extends State { child: ValueListenableBuilder( valueListenable: SentryHive.box(settings).listenable(keys: [appColor]), builder: (BuildContext context, value, Widget? child) { - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - SystemUiOverlayStyle( - systemNavigationBarColor: Colors.black.withOpacity(0.002), // Navigation bar - statusBarColor: Colors.black.withOpacity(0.002), // Status bar - ); + setupSystemColor(context); Future(() => FlutterNativeSplash.remove()); //remove the splash screen one frame later Color color = Color(HiveProxy.getOrDefault(settings, appColor, defaultValue: appColorDefault)); return MaterialApp.router(