128 lines
3.8 KiB
Dart
128 lines
3.8 KiB
Dart
import 'dart:async';
|
||
|
||
import 'package:flutter/material.dart';
|
||
import 'package:google_fonts/google_fonts.dart';
|
||
|
||
import 'core/auth/auth_service.dart';
|
||
import 'core/theme/app_colors.dart';
|
||
import 'core/theme/app_theme.dart';
|
||
import 'features/shell/main_screen.dart';
|
||
|
||
class App extends StatelessWidget {
|
||
const App({super.key, required this.title});
|
||
|
||
final String title;
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return MaterialApp(
|
||
title: title,
|
||
debugShowCheckedModeBanner: false,
|
||
theme: buildFunyMeeTheme(),
|
||
home: const MainScreen(),
|
||
builder: (context, child) {
|
||
return Stack(
|
||
fit: StackFit.expand,
|
||
children: [
|
||
SafeArea(
|
||
top: false,
|
||
left: false,
|
||
right: false,
|
||
bottom: false,
|
||
child: child ?? const SizedBox.shrink(),
|
||
),
|
||
ValueListenableBuilder<bool>(
|
||
valueListenable: AuthService.isLoginComplete,
|
||
builder: (context, done, _) {
|
||
if (done) return const SizedBox.shrink();
|
||
return const _StartupLoginOverlay();
|
||
},
|
||
),
|
||
],
|
||
);
|
||
},
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 对齐 app_client:首帧即进入壳层,登录完成前遮罩 + 久等网络提示。
|
||
class _StartupLoginOverlay extends StatefulWidget {
|
||
const _StartupLoginOverlay();
|
||
|
||
@override
|
||
State<_StartupLoginOverlay> createState() => _StartupLoginOverlayState();
|
||
}
|
||
|
||
class _StartupLoginOverlayState extends State<_StartupLoginOverlay> {
|
||
static const _longWaitAfter = Duration(seconds: 22);
|
||
Timer? _longWaitTimer;
|
||
bool _showNetworkHint = false;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_longWaitTimer = Timer(_longWaitAfter, () {
|
||
if (mounted) setState(() => _showNetworkHint = true);
|
||
});
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_longWaitTimer?.cancel();
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Positioned.fill(
|
||
child: AbsorbPointer(
|
||
child: Container(
|
||
color: Colors.black.withValues(alpha: 0.22),
|
||
child: Center(
|
||
child: Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 28),
|
||
child: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
const CircularProgressIndicator(color: AppColors.primary),
|
||
const SizedBox(height: 16),
|
||
Text(
|
||
'Signing in…',
|
||
style: GoogleFonts.inter(
|
||
color: Colors.white.withValues(alpha: 0.92),
|
||
fontSize: 15,
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
if (_showNetworkHint) ...[
|
||
const SizedBox(height: 22),
|
||
Text(
|
||
'Network is slow or unavailable',
|
||
textAlign: TextAlign.center,
|
||
style: GoogleFonts.inter(
|
||
color: Colors.white.withValues(alpha: 0.96),
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
const SizedBox(height: 10),
|
||
Text(
|
||
'Check Wi‑Fi or mobile data. If the connection is fine, the server may be busy—try again shortly.',
|
||
textAlign: TextAlign.center,
|
||
style: GoogleFonts.inter(
|
||
color: Colors.white.withValues(alpha: 0.78),
|
||
fontSize: 14,
|
||
height: 1.4,
|
||
),
|
||
),
|
||
],
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|