Compare commits

..

No commits in common. "b05d3c0b0e7a1b7747c355a2a93c5b51b7348eb9" and "fb4d1b78d6ce5369b16ca4fe9eb9116def22d1e5" have entirely different histories.

26 changed files with 30 additions and 107 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 B

After

Width:  |  Height:  |  Size: 247 KiB

View File

@ -3,7 +3,4 @@
<item> <item>
<bitmap android:gravity="fill" android:src="@drawable/background"/> <bitmap android:gravity="fill" android:src="@drawable/background"/>
</item> </item>
<item>
<bitmap android:gravity="fill|clip_vertical" android:src="@drawable/splash"/>
</item>
</layer-list> </layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 346 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 601 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 B

After

Width:  |  Height:  |  Size: 247 KiB

View File

@ -3,7 +3,4 @@
<item> <item>
<bitmap android:gravity="fill" android:src="@drawable/background"/> <bitmap android:gravity="fill" android:src="@drawable/background"/>
</item> </item>
<item>
<bitmap android:gravity="fill|clip_vertical" android:src="@drawable/splash"/>
</item>
</layer-list> </layer-list>

View File

@ -4,12 +4,11 @@
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:forceDarkAllowed">false</item> <item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">true</item> <item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item> <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<item name="android:windowSplashScreenBackground">#0a0a12</item> <item name="android:windowSplashScreenBackground">#0a0a12</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item> <item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
<item name="android:windowSplashScreenIconBackgroundColor">#0a0a12</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started. <!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your This theme determines the color of the Android Window while your

View File

@ -3,8 +3,8 @@
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:forceDarkAllowed">false</item> <item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">true</item> <item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item> <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style> </style>
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">

View File

@ -4,12 +4,11 @@
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:forceDarkAllowed">false</item> <item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">true</item> <item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item> <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<item name="android:windowSplashScreenBackground">#0a0a12</item> <item name="android:windowSplashScreenBackground">#0a0a12</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item> <item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
<item name="android:windowSplashScreenIconBackgroundColor">#0a0a12</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started. <!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your This theme determines the color of the Android Window while your

View File

@ -3,8 +3,8 @@
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:forceDarkAllowed">false</item> <item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">true</item> <item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item> <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style> </style>
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 B

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 69 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 69 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 346 KiB

After

Width:  |  Height:  |  Size: 69 B

View File

@ -16,19 +16,14 @@
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" image="LaunchBackground" translatesAutoresizingMaskIntoConstraints="NO" id="tWc-Dq-wcI"/> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" image="LaunchBackground" translatesAutoresizingMaskIntoConstraints="NO" id="tWc-Dq-wcI"/>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleAspectFill" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"></imageView>
</subviews> </subviews>
<color key="backgroundColor" red="0.039215686274509803" green="0.039215686274509803" blue="0.07058823529411765" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.04" green="0.04" blue="0.07" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="3T2-ad-Qdv"/>
<constraint firstItem="tWc-Dq-wcI" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="RPx-PI-7Xg"/> <constraint firstItem="tWc-Dq-wcI" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="RPx-PI-7Xg"/>
<constraint firstItem="tWc-Dq-wcI" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="SdS-ul-q2q"/> <constraint firstItem="tWc-Dq-wcI" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="SdS-ul-q2q"/>
<constraint firstAttribute="trailing" secondItem="tWc-Dq-wcI" secondAttribute="trailing" id="Swv-Gf-Rwn"/> <constraint firstAttribute="trailing" secondItem="tWc-Dq-wcI" secondAttribute="trailing" id="Swv-Gf-Rwn"/>
<constraint firstAttribute="trailing" secondItem="YRO-k0-Ey4" secondAttribute="trailing" id="TQA-XW-tRk"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="duK-uY-Gun"/>
<constraint firstItem="tWc-Dq-wcI" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="kV7-tw-vXt"/> <constraint firstItem="tWc-Dq-wcI" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="kV7-tw-vXt"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="xPn-NY-SIU"/>
</constraints> </constraints>
</view> </view>
</viewController> </viewController>
@ -38,7 +33,6 @@
</scene> </scene>
</scenes> </scenes>
<resources> <resources>
<image name="LaunchImage" width="512" height="512"/> <image name="LaunchBackground" width="375" height="812"/>
<image name="LaunchBackground" width="1" height="1"/>
</resources> </resources>
</document> </document>

View File

@ -51,8 +51,6 @@
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>UIStatusBarHidden</key> <key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
</dict> </dict>
</plist> </plist>

View File

@ -197,8 +197,8 @@ class AuthService {
const retryDelay = Duration(seconds: 2); const retryDelay = Duration(seconds: 2);
try { try {
// // 访 App
await Future<void>.delayed(const Duration(milliseconds: 400)); await Future<void>.delayed(const Duration(seconds: 2));
final deviceId = await _getDeviceId(); final deviceId = await _getDeviceId();
_logMsg('init: deviceId=$deviceId'); _logMsg('init: deviceId=$deviceId');

View File

@ -18,8 +18,7 @@ class ReferrerService {
static final Completer<AdjustAttribution?> _attributionCallbackCompleter = static final Completer<AdjustAttribution?> _attributionCallbackCompleter =
Completer<AdjustAttribution?>(); Completer<AdjustAttribution?>();
/// [AuthService.init] getReferrer Adjust Play Install Referrer fallback static const int _adjustTimeoutMs = 15000;
static const int _adjustTimeoutMs = 4500;
/// Adjust attributionCallback getAttributionWithTimeout /// Adjust attributionCallback getAttributionWithTimeout
static void receiveAttributionFromCallback(AdjustAttribution attribution) { static void receiveAttributionFromCallback(AdjustAttribution attribution) {

View File

@ -1,7 +1,4 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
/// [VisibilityDetector] [VideoPlayer] /// Navigator pop [VisibilityDetector] [_MainScaffoldState.didPopNext]
///
/// pop Tab
/// / ext `HomeScreen._requestPlaybackPipeline`
final ValueNotifier<int> homePlaybackResumeNonce = ValueNotifier<int>(0); final ValueNotifier<int> homePlaybackResumeNonce = ValueNotifier<int>(0);

View File

@ -27,7 +27,7 @@ class HomeScreen extends StatefulWidget {
State<HomeScreen> createState() => _HomeScreenState(); State<HomeScreen> createState() => _HomeScreenState();
} }
class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver { class _HomeScreenState extends State<HomeScreen> {
List<CategoryItem> _categories = []; List<CategoryItem> _categories = [];
CategoryItem? _selectedCategory; CategoryItem? _selectedCategory;
List<TaskItem> _tasks = []; List<TaskItem> _tasks = [];
@ -44,13 +44,8 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
/// vs /// vs
bool _visibilityHadMeaningfulReport = false; bool _visibilityHadMeaningfulReport = false;
/// nonce [VideoCard] + [_onHomePlaybackResumeSignal] /// IndexedStack [homePlaybackResumeNonce] [VisibilityDetector]
void _requestPlaybackPipeline() { /// [notifyNow] Modal / pop My Gallery +
if (!mounted || !widget.isActive) return;
homePlaybackResumeNonce.value++;
}
/// [homePlaybackResumeNonce] + [notifyNow]
void _scheduleVisibilityRefresh() { void _scheduleVisibilityRefresh() {
if (!mounted || !widget.isActive) return; if (!mounted || !widget.isActive) return;
void notify() { void notify() {
@ -85,7 +80,6 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance.addObserver(this);
UserState.needShowVideoMenu.addListener(_onExtConfigChanged); UserState.needShowVideoMenu.addListener(_onExtConfigChanged);
UserState.extConfigItems.addListener(_onExtConfigChanged); UserState.extConfigItems.addListener(_onExtConfigChanged);
AuthService.isLoginComplete.addListener(_onExtConfigChanged); AuthService.isLoginComplete.addListener(_onExtConfigChanged);
@ -112,7 +106,6 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
@override @override
void dispose() { void dispose() {
WidgetsBinding.instance.removeObserver(this);
homePlaybackResumeNonce.removeListener(_onHomePlaybackResumeSignal); homePlaybackResumeNonce.removeListener(_onHomePlaybackResumeSignal);
UserState.needShowVideoMenu.removeListener(_onExtConfigChanged); UserState.needShowVideoMenu.removeListener(_onExtConfigChanged);
UserState.extConfigItems.removeListener(_onExtConfigChanged); UserState.extConfigItems.removeListener(_onExtConfigChanged);
@ -127,19 +120,11 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
_scheduleVisibilityRefresh(); _scheduleVisibilityRefresh();
} }
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.resumed && mounted && widget.isActive) {
_requestPlaybackPipeline();
}
}
void _onExtConfigChanged() { void _onExtConfigChanged() {
if (mounted) setState(() {}); if (mounted) setState(() {});
// Timer listener cancel notify // Timer listener cancel notify
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted && widget.isActive) _requestPlaybackPipeline(); if (mounted && widget.isActive) _scheduleVisibilityRefresh();
}); });
} }
@ -154,7 +139,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
static const int _maxConcurrentHomeVideos = 16; static const int _maxConcurrentHomeVideos = 16;
void _onGridCardVisibilityChanged(int index, VisibilityInfo info) { void _onGridCardVisibilityChanged(int index, VisibilityInfo info) {
if (!mounted || !widget.isActive) return; if (!mounted) return;
if (info.visibleFraction >= _videoVisibilityThreshold) { if (info.visibleFraction >= _videoVisibilityThreshold) {
_cardVisibleFraction[index] = info.visibleFraction; _cardVisibleFraction[index] = info.visibleFraction;
_visibilityHadMeaningfulReport = true; _visibilityHadMeaningfulReport = true;
@ -170,7 +155,6 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
} }
void _reconcileVisibleVideoIndicesFromDetector() { void _reconcileVisibleVideoIndicesFromDetector() {
if (!mounted || !widget.isActive) return;
final tasks = _displayTasks; final tasks = _displayTasks;
final scored = <MapEntry<int, double>>[]; final scored = <MapEntry<int, double>>[];
for (final e in _cardVisibleFraction.entries) { for (final e in _cardVisibleFraction.entries) {
@ -216,7 +200,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (widget.isActive && !oldWidget.isActive) { if (widget.isActive && !oldWidget.isActive) {
refreshAccount(); refreshAccount();
_requestPlaybackPipeline(); _scheduleVisibilityRefresh();
} }
} }
@ -316,7 +300,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
setState(() => _categoriesLoading = false); setState(() => _categoriesLoading = false);
// pets [_loadTasks] // pets [_loadTasks]
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted && widget.isActive) _requestPlaybackPipeline(); if (mounted && widget.isActive) _scheduleVisibilityRefresh();
}); });
} }
} }
@ -348,7 +332,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
setState(() => _tasksLoading = false); setState(() => _tasksLoading = false);
// //
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted && widget.isActive) _requestPlaybackPipeline(); if (mounted && widget.isActive) _scheduleVisibilityRefresh();
}); });
} }
} }
@ -368,7 +352,7 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
_visibilityHadMeaningfulReport = false; _visibilityHadMeaningfulReport = false;
}); });
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted && widget.isActive) _requestPlaybackPipeline(); if (mounted && widget.isActive) _scheduleVisibilityRefresh();
}); });
} else { } else {
_loadTasks(c.id); _loadTasks(c.id);
@ -463,8 +447,6 @@ class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
_placeholderImage, _placeholderImage,
videoUrl: task.previewVideoUrl, videoUrl: task.previewVideoUrl,
credits: credits, credits: credits,
playbackResumeListenable:
homePlaybackResumeNonce,
isActive: widget.isActive && isActive: widget.isActive &&
_visibleVideoIndices.contains(index) && _visibleVideoIndices.contains(index) &&
!_userPausedVideoIndices !_userPausedVideoIndices

View File

@ -1,7 +1,6 @@
import 'dart:async' show unawaited; import 'dart:async' show unawaited;
import 'dart:io' show File; import 'dart:io' show File;
import 'package:flutter/foundation.dart' show ValueListenable;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart' import 'package:flutter_cache_manager/flutter_cache_manager.dart'
show DefaultCacheManager, DownloadProgress, FileInfo; show DefaultCacheManager, DownloadProgress, FileInfo;
@ -23,8 +22,6 @@ class VideoCard extends StatefulWidget {
this.showCreditsBadge = true, this.showCreditsBadge = true,
this.showBottomGenerateButton = true, this.showBottomGenerateButton = true,
required this.isActive, required this.isActive,
/// nonce [isActive] /
this.playbackResumeListenable,
required this.onPlayRequested, required this.onPlayRequested,
required this.onStopRequested, required this.onStopRequested,
this.onGenerateSimilar, this.onGenerateSimilar,
@ -38,7 +35,6 @@ class VideoCard extends StatefulWidget {
final bool showCreditsBadge; final bool showCreditsBadge;
final bool showBottomGenerateButton; final bool showBottomGenerateButton;
final bool isActive; final bool isActive;
final ValueListenable<int>? playbackResumeListenable;
final VoidCallback onPlayRequested; final VoidCallback onPlayRequested;
final VoidCallback onStopRequested; final VoidCallback onStopRequested;
final VoidCallback? onGenerateSimilar; final VoidCallback? onGenerateSimilar;
@ -61,7 +57,6 @@ class _VideoCardState extends State<VideoCard> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
widget.playbackResumeListenable?.addListener(_onPlaybackResumeSignal);
if (widget.isActive) { if (widget.isActive) {
WidgetsBinding.instance.addPostFrameCallback((_) => _loadAndPlay()); WidgetsBinding.instance.addPostFrameCallback((_) => _loadAndPlay());
} }
@ -69,43 +64,13 @@ class _VideoCardState extends State<VideoCard> {
@override @override
void dispose() { void dispose() {
widget.playbackResumeListenable?.removeListener(_onPlaybackResumeSignal);
_disposeController(); _disposeController();
super.dispose(); super.dispose();
} }
void _onPlaybackResumeSignal() {
if (!mounted || !widget.isActive) return;
// [homePlaybackResumeNonce] dispose
// [_kickPlaybackAfterGlobalResume] setState
Future.microtask(() {
if (!mounted || !widget.isActive) return;
_kickPlaybackAfterGlobalResume();
});
}
/// Visibility pause [play] [didUpdateWidget]
void _kickPlaybackAfterGlobalResume() {
if (widget.videoUrl == null || widget.videoUrl!.isEmpty) return;
final c = _controller;
if (c != null && c.value.isInitialized) {
c.setVolume(0);
c.setLooping(true);
if (!c.value.isPlaying) {
unawaited(c.play());
}
return;
}
_loadAndPlay();
}
@override @override
void didUpdateWidget(covariant VideoCard oldWidget) { void didUpdateWidget(covariant VideoCard oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (oldWidget.playbackResumeListenable != widget.playbackResumeListenable) {
oldWidget.playbackResumeListenable?.removeListener(_onPlaybackResumeSignal);
widget.playbackResumeListenable?.addListener(_onPlaybackResumeSignal);
}
if (oldWidget.isActive && !widget.isActive) { if (oldWidget.isActive && !widget.isActive) {
_releaseVideoDecoder(); _releaseVideoDecoder();
} else if (!oldWidget.isActive && widget.isActive) { } else if (!oldWidget.isActive && widget.isActive) {

View File

@ -16,7 +16,9 @@ import 'features/recharge/google_play_purchase_service.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
_initAdjust(); _initAdjust();
// await ReferrerService.init()Adjust [AuthService.init] await getReferrer() // Facebook/ App activateApp app.dart AutoLog
// Adjust ReferrerService Adjust.getAttributionWithTimeout
await ReferrerService.init();
SystemChrome.setSystemUIOverlayStyle( SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle( const SystemUiOverlayStyle(
statusBarColor: AppColors.surface, statusBarColor: AppColors.surface,

View File

@ -53,20 +53,14 @@ flutter_launcher_icons:
image_path: "assets/images/logo.png" image_path: "assets/images/logo.png"
remove_alpha_ios: true remove_alpha_ios: true
# 启动屏:与 Android 12+ 统一深色底,避免系统用默认 launcher 图标导致「中间图标过小」;
# android_12 必须单独配 image否则 12+ 只用 ic_launcher圆内显得很小且易有白边感。
flutter_native_splash: flutter_native_splash:
color: "#0a0a12" background_image: "assets/images/splash.png"
image: assets/images/logo.png
android: true android: true
ios: true ios: true
android_gravity: fill|clip_vertical # Android 12+ 使用不同 API不支持全屏背景图需单独配置
ios_content_mode: scaleAspectFill
fullscreen: true
android_12: android_12:
color: "#0a0a12" color: "#0a0a12"
image: assets/images/logo.png image: "assets/images/logo.png"
icon_background_color: "#0a0a12"
flutter: flutter:
uses-material-design: true uses-material-design: true