feat(update): добавить модуль управления Hard & Soft обновлений (#30)

1. Реализован интерфейс и репозитории для проверки обновлений.
2. Добавлены состояния и кубит для управления процессом обновления.
3. Созданы UI-компоненты для отображения информации об обновлениях.
4. Обновлен README.md с описанием нового модуля и его интеграции
This commit is contained in:
Yuri Petrov
2025-09-26 08:21:42 +03:00
committed by GitHub
parent e1fb99c86f
commit 8710792c4b
20 changed files with 664 additions and 56 deletions

View File

@@ -1,7 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:friflex_starter/app/app_context_ext.dart';
import 'package:friflex_starter/app/app_env.dart';
import 'package:friflex_starter/features/debug/debug_routes.dart';
import 'package:friflex_starter/features/update/domain/state/cubit/update_cubit.dart';
import 'package:friflex_starter/features/update/presentation/components/soft_modal_sheet.dart';
import 'package:friflex_starter/features/update/update_type.dart';
import 'package:go_router/go_router.dart';
/// {@template root_screen}
@@ -13,7 +17,7 @@ import 'package:go_router/go_router.dart';
/// - Отображение кнопки отладки в не-продакшн окружениях
/// - Интеграцию с GoRouter для навигации
/// {@endtemplate}
class RootScreen extends StatelessWidget {
class RootScreen extends StatefulWidget {
/// {@macro root_screen}
const RootScreen({required this.navigationShell, super.key});
@@ -21,6 +25,38 @@ class RootScreen extends StatelessWidget {
/// Содержит информацию о текущем состоянии навигации
final StatefulNavigationShell navigationShell;
@override
State<RootScreen> createState() => _RootScreenState();
}
class _RootScreenState extends State<RootScreen> {
@override
void initState() {
super.initState();
// После построения виджета, проверяем состояние кубита обновлений
// и если есть обновление, то показываем модальное окно
_checkSoftUpdate();
}
/// Проверяет состояние кубита обновлений и показывает модальное окно при наличии мягкого обновления
void _checkSoftUpdate() {
WidgetsBinding.instance.addPostFrameCallback((_) {
final updateState = context.read<UpdateCubit>().state;
// Проверяем только состояние успеха с доступной информацией об обновлении
if (updateState is UpdateSuccessState &&
updateState.updateInfo.updateType == UpdateType.soft) {
SoftUpdateModal.show(
context,
updateEntity: updateState.updateInfo,
onUpdate: () {
// TODO(yura): реализовать логику обновления приложения
},
);
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -32,14 +68,14 @@ class RootScreen extends StatelessWidget {
},
)
: null,
body: navigationShell,
body: widget.navigationShell,
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Главная'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Профиль'),
],
currentIndex: navigationShell.currentIndex,
onTap: navigationShell.goBranch,
currentIndex: widget.navigationShell.currentIndex,
onTap: widget.navigationShell.goBranch,
),
);
}