feat: add flutter mobile console and refine login ui
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user