162 lines
4.5 KiB
Dart
162 lines
4.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:live_recorder_mobile/app/app_bootstrap_controller.dart';
|
|
import 'package:live_recorder_mobile/app/app_dependencies.dart';
|
|
import 'package:live_recorder_mobile/app/app_scope.dart';
|
|
import 'package:live_recorder_mobile/app/app_theme.dart';
|
|
import 'package:live_recorder_mobile/core/config/api_config.dart';
|
|
import 'package:live_recorder_mobile/core/persistence/app_config_storage.dart';
|
|
import 'package:live_recorder_mobile/core/widgets/app_error_card.dart';
|
|
import 'package:live_recorder_mobile/features/live_recorder/presentation/pages/backend_setup_page.dart';
|
|
import 'package:live_recorder_mobile/features/live_recorder/presentation/pages/login_page.dart';
|
|
import 'package:live_recorder_mobile/features/live_recorder/presentation/pages/mobile_shell_page.dart';
|
|
|
|
class LiveRecorderBootstrap extends StatefulWidget {
|
|
const LiveRecorderBootstrap({
|
|
super.key,
|
|
required this.config,
|
|
});
|
|
|
|
final ApiConfig config;
|
|
|
|
@override
|
|
State<LiveRecorderBootstrap> createState() => _LiveRecorderBootstrapState();
|
|
}
|
|
|
|
class _LiveRecorderBootstrapState extends State<LiveRecorderBootstrap> {
|
|
late final AppBootstrapController<AppDependencies> _bootstrapController =
|
|
AppBootstrapController<AppDependencies>(
|
|
config: widget.config,
|
|
configStorage: AppConfigStorage(),
|
|
dependenciesFactory: (String baseUrl) => AppDependencies.create(baseUrl: baseUrl),
|
|
);
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_bootstrapController.initialize();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_bootstrapController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AnimatedBuilder(
|
|
animation: _bootstrapController,
|
|
builder: (BuildContext context, _) {
|
|
return AppScope(
|
|
backendConfig: _bootstrapController,
|
|
dependencies: _bootstrapController.dependencies,
|
|
child: MaterialApp(
|
|
debugShowCheckedModeBanner: false,
|
|
title: 'LiveRecorder',
|
|
theme: buildLiveRecorderTheme(),
|
|
home: _BootstrapHome(
|
|
bootstrapController: _bootstrapController,
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class _BootstrapHome extends StatelessWidget {
|
|
const _BootstrapHome({
|
|
required this.bootstrapController,
|
|
});
|
|
|
|
final AppBootstrapController<AppDependencies> bootstrapController;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (bootstrapController.isInitializing) {
|
|
return const _LoadingSplashPage();
|
|
}
|
|
|
|
if (bootstrapController.initializationErrorMessage != null) {
|
|
return _BootstrapErrorPage(
|
|
message: bootstrapController.initializationErrorMessage!,
|
|
onRetry: bootstrapController.initialize,
|
|
);
|
|
}
|
|
|
|
if (!bootstrapController.hasConfiguredBackend) {
|
|
return BackendSetupPage(
|
|
bootstrapController: bootstrapController,
|
|
);
|
|
}
|
|
|
|
final dependencies = bootstrapController.dependencies;
|
|
if (dependencies == null) {
|
|
return _BootstrapErrorPage(
|
|
message: '后端配置未能正确加载,请重试',
|
|
onRetry: bootstrapController.initialize,
|
|
);
|
|
}
|
|
|
|
return ListenableBuilder(
|
|
listenable: dependencies.sessionController,
|
|
builder: (BuildContext context, _) {
|
|
if (dependencies.sessionController.isRestoring) {
|
|
return const _LoadingSplashPage();
|
|
}
|
|
|
|
if (dependencies.sessionController.isLoggedIn) {
|
|
return MobileShellPage(
|
|
dependencies: dependencies,
|
|
);
|
|
}
|
|
|
|
return LoginPage(
|
|
sessionController: dependencies.sessionController,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class _LoadingSplashPage extends StatelessWidget {
|
|
const _LoadingSplashPage();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return const Scaffold(
|
|
body: Center(
|
|
child: CircularProgressIndicator(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _BootstrapErrorPage extends StatelessWidget {
|
|
const _BootstrapErrorPage({
|
|
required this.message,
|
|
required this.onRetry,
|
|
});
|
|
|
|
final String message;
|
|
final VoidCallback onRetry;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(24),
|
|
child: ConstrainedBox(
|
|
constraints: const BoxConstraints(maxWidth: 420),
|
|
child: AppErrorCard(
|
|
message: message,
|
|
onRetry: onRetry,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|