mirror of
https://github.com/smmarty/friflex_flutter_starter.git
synced 2025-12-22 01:20:46 +00:00
refactor(app): Обновить описание и структуру файлов конфигурации, улучшить документацию (#14)
Co-authored-by: PetrovY <y.petrov@friflex.com>
This commit is contained in:
@@ -12,22 +12,43 @@ import 'package:friflex_starter/l10n/gen/app_localizations.dart';
|
||||
import 'package:friflex_starter/l10n/localization_notifier.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
/// Класс приложения
|
||||
/// {@template app}
|
||||
/// Главный виджет приложения, управляющий инициализацией зависимостей
|
||||
/// и отображением основного интерфейса приложения.
|
||||
///
|
||||
/// Отвечает за:
|
||||
/// - Инициализацию зависимостей приложения
|
||||
/// - Отображение экрана загрузки во время инициализации
|
||||
/// - Обработку ошибок инициализации
|
||||
/// - Настройку провайдеров для темы и локализации
|
||||
/// {@endtemplate}
|
||||
class App extends StatefulWidget {
|
||||
/// {@macro app}
|
||||
const App({required this.router, required this.initDependencies, super.key});
|
||||
|
||||
/// Роутер приложения
|
||||
/// Роутер приложения для навигации между экранами
|
||||
final GoRouter router;
|
||||
|
||||
/// Функция для инициализации зависимостей
|
||||
/// Функция для инициализации зависимостей приложения
|
||||
/// Возвращает Future с контейнером зависимостей
|
||||
final Future<DiContainer> Function() initDependencies;
|
||||
|
||||
@override
|
||||
State<App> createState() => _AppState();
|
||||
}
|
||||
|
||||
/// {@template app_state}
|
||||
/// Состояние главного виджета приложения.
|
||||
///
|
||||
/// Управляет процессом инициализации зависимостей и отображением
|
||||
/// соответствующих экранов в зависимости от состояния инициализации.
|
||||
/// {@endtemplate}
|
||||
class _AppState extends State<App> {
|
||||
/// {@macro app_state}
|
||||
_AppState();
|
||||
|
||||
/// Мутабельная Future для инициализации зависимостей
|
||||
/// Позволяет перезапускать инициализацию при ошибках
|
||||
late Future<DiContainer> _initFuture;
|
||||
|
||||
@override
|
||||
@@ -83,6 +104,8 @@ class _AppState extends State<App> {
|
||||
);
|
||||
}
|
||||
|
||||
/// Метод для перезапуска инициализации зависимостей
|
||||
/// Вызывается при ошибках инициализации для повторной попытки
|
||||
void _retryInit() {
|
||||
setState(() {
|
||||
_initFuture = widget.initDependencies();
|
||||
@@ -90,9 +113,17 @@ class _AppState extends State<App> {
|
||||
}
|
||||
}
|
||||
|
||||
/// {@template app_internal}
|
||||
/// Внутренний виджет приложения, отображающий основной интерфейс
|
||||
/// после успешной инициализации зависимостей.
|
||||
///
|
||||
/// Настраивает MaterialApp с роутером, темами и локализацией.
|
||||
/// {@endtemplate}
|
||||
class _App extends StatelessWidget {
|
||||
/// {@macro app_internal}
|
||||
const _App({required this.router});
|
||||
|
||||
/// Роутер приложения для навигации
|
||||
final GoRouter router;
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,12 +1,45 @@
|
||||
import 'package:envied/envied.dart';
|
||||
import 'package:friflex_starter/app/app_config/i_app_config.dart';
|
||||
import 'package:friflex_starter/app/app_env.dart';
|
||||
|
||||
part 'app_config.g.dart';
|
||||
|
||||
/// Класс для реализации конфигурации с моковыми данными
|
||||
/// {@template i_app_config}
|
||||
/// Интерфейс для конфигурации приложения.
|
||||
///
|
||||
/// Определяет обязательные параметры для всех реализаций конфигурации:
|
||||
/// - Наименование конфигурации
|
||||
/// - Базовый URL для API
|
||||
/// - Тип окружения (dev, prod, stage)
|
||||
/// - Секретный ключ для шифрования данных
|
||||
/// {@endtemplate}
|
||||
abstract interface class IAppConfig {
|
||||
/// {@macro i_app_config}
|
||||
IAppConfig();
|
||||
|
||||
/// Наименование сервиса конфигурации
|
||||
String get name => 'IAppConfig';
|
||||
|
||||
/// Основной адрес для запросов к API
|
||||
String get baseUrl;
|
||||
|
||||
/// Тип окружения (dev, prod, stage)
|
||||
AppEnv get env;
|
||||
|
||||
/// Секретный ключ для шифрования данных
|
||||
String get secretKey;
|
||||
}
|
||||
|
||||
/// {@template app_config_dev}
|
||||
/// Класс для реализации конфигурации приложения в режиме разработки.
|
||||
///
|
||||
/// Использует переменные окружения из файла env/dev.env.
|
||||
/// Предназначен для локальной разработки и тестирования.
|
||||
/// {@endtemplate}
|
||||
@Envied(name: 'Dev', path: 'env/dev.env')
|
||||
class AppConfigDev implements IAppConfig {
|
||||
/// {@macro app_config_dev}
|
||||
AppConfigDev();
|
||||
|
||||
@override
|
||||
AppEnv get env => AppEnv.dev;
|
||||
|
||||
@@ -22,9 +55,17 @@ class AppConfigDev implements IAppConfig {
|
||||
final String secretKey = _Dev.secretKey;
|
||||
}
|
||||
|
||||
/// Класс для реализации конфигурации с продакшн данными
|
||||
/// {@template app_config_prod}
|
||||
/// Класс для реализации конфигурации приложения в продакшн режиме.
|
||||
///
|
||||
/// Использует переменные окружения из файла env/prod.env.
|
||||
/// Предназначен для финальной сборки приложения.
|
||||
/// {@endtemplate}
|
||||
@Envied(name: 'Prod', path: 'env/prod.env')
|
||||
class AppConfigProd implements IAppConfig {
|
||||
/// {@macro app_config_prod}
|
||||
AppConfigProd();
|
||||
|
||||
@override
|
||||
AppEnv get env => AppEnv.prod;
|
||||
|
||||
@@ -40,9 +81,17 @@ class AppConfigProd implements IAppConfig {
|
||||
final String secretKey = _Prod.secretKey;
|
||||
}
|
||||
|
||||
/// Класс для реализации конфигурации с стейдж данными
|
||||
/// {@template app_config_stage}
|
||||
/// Класс для реализации конфигурации приложения в стейдж режиме.
|
||||
///
|
||||
/// Использует переменные окружения из файла env/stage.env.
|
||||
/// Предназначен для тестирования в среде, близкой к продакшн.
|
||||
/// {@endtemplate}
|
||||
@Envied(name: 'Stage', path: 'env/stage.env')
|
||||
class AppConfigStage implements IAppConfig {
|
||||
/// {@macro app_config_stage}
|
||||
AppConfigStage();
|
||||
|
||||
@override
|
||||
AppEnv get env => AppEnv.stage;
|
||||
|
||||
|
||||
@@ -24,11 +24,13 @@ final class _Dev {
|
||||
4081271699,
|
||||
];
|
||||
|
||||
static final String secretKey = String.fromCharCodes(List<int>.generate(
|
||||
_envieddatasecretKey.length,
|
||||
(int i) => i,
|
||||
growable: false,
|
||||
).map((int i) => _envieddatasecretKey[i] ^ _enviedkeysecretKey[i]));
|
||||
static final String secretKey = String.fromCharCodes(
|
||||
List<int>.generate(
|
||||
_envieddatasecretKey.length,
|
||||
(int i) => i,
|
||||
growable: false,
|
||||
).map((int i) => _envieddatasecretKey[i] ^ _enviedkeysecretKey[i]),
|
||||
);
|
||||
}
|
||||
|
||||
// coverage:ignore-file
|
||||
@@ -65,11 +67,13 @@ final class _Prod {
|
||||
655048645,
|
||||
];
|
||||
|
||||
static final String baseUrl = String.fromCharCodes(List<int>.generate(
|
||||
_envieddatabaseUrl.length,
|
||||
(int i) => i,
|
||||
growable: false,
|
||||
).map((int i) => _envieddatabaseUrl[i] ^ _enviedkeybaseUrl[i]));
|
||||
static final String baseUrl = String.fromCharCodes(
|
||||
List<int>.generate(
|
||||
_envieddatabaseUrl.length,
|
||||
(int i) => i,
|
||||
growable: false,
|
||||
).map((int i) => _envieddatabaseUrl[i] ^ _enviedkeybaseUrl[i]),
|
||||
);
|
||||
|
||||
static const List<int> _enviedkeysecretKey = <int>[
|
||||
359753139,
|
||||
@@ -85,11 +89,13 @@ final class _Prod {
|
||||
3044498279,
|
||||
];
|
||||
|
||||
static final String secretKey = String.fromCharCodes(List<int>.generate(
|
||||
_envieddatasecretKey.length,
|
||||
(int i) => i,
|
||||
growable: false,
|
||||
).map((int i) => _envieddatasecretKey[i] ^ _enviedkeysecretKey[i]));
|
||||
static final String secretKey = String.fromCharCodes(
|
||||
List<int>.generate(
|
||||
_envieddatasecretKey.length,
|
||||
(int i) => i,
|
||||
growable: false,
|
||||
).map((int i) => _envieddatasecretKey[i] ^ _enviedkeysecretKey[i]),
|
||||
);
|
||||
}
|
||||
|
||||
// coverage:ignore-file
|
||||
@@ -128,11 +134,13 @@ final class _Stage {
|
||||
568662398,
|
||||
];
|
||||
|
||||
static final String baseUrl = String.fromCharCodes(List<int>.generate(
|
||||
_envieddatabaseUrl.length,
|
||||
(int i) => i,
|
||||
growable: false,
|
||||
).map((int i) => _envieddatabaseUrl[i] ^ _enviedkeybaseUrl[i]));
|
||||
static final String baseUrl = String.fromCharCodes(
|
||||
List<int>.generate(
|
||||
_envieddatabaseUrl.length,
|
||||
(int i) => i,
|
||||
growable: false,
|
||||
).map((int i) => _envieddatabaseUrl[i] ^ _enviedkeybaseUrl[i]),
|
||||
);
|
||||
|
||||
static const List<int> _enviedkeysecretKey = <int>[
|
||||
2132342089,
|
||||
@@ -150,9 +158,11 @@ final class _Stage {
|
||||
1192880631,
|
||||
];
|
||||
|
||||
static final String secretKey = String.fromCharCodes(List<int>.generate(
|
||||
_envieddatasecretKey.length,
|
||||
(int i) => i,
|
||||
growable: false,
|
||||
).map((int i) => _envieddatasecretKey[i] ^ _enviedkeysecretKey[i]));
|
||||
static final String secretKey = String.fromCharCodes(
|
||||
List<int>.generate(
|
||||
_envieddatasecretKey.length,
|
||||
(int i) => i,
|
||||
growable: false,
|
||||
).map((int i) => _envieddatasecretKey[i] ^ _enviedkeysecretKey[i]),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,2 @@
|
||||
import 'package:friflex_starter/app/app_env.dart';
|
||||
|
||||
/// Класс для описания интерфейса конфигурации
|
||||
abstract interface class IAppConfig {
|
||||
/// Наименование сервиса
|
||||
String get name => 'IAppConfig';
|
||||
|
||||
/// Основной адрес для запросов к API
|
||||
String get baseUrl;
|
||||
|
||||
/// Тип окружения
|
||||
AppEnv get env;
|
||||
|
||||
/// Секретный ключ для шифрования данных
|
||||
String get secretKey;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:friflex_starter/app/app_config/i_app_config.dart';
|
||||
import 'package:friflex_starter/app/app_config/app_config.dart';
|
||||
import 'package:friflex_starter/app/http/i_http_client.dart';
|
||||
|
||||
import 'package:friflex_starter/features/debug/i_debug_service.dart';
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
/// Тип функции для построения виджета с учетом темы
|
||||
typedef ThemeBuilder = Widget Function();
|
||||
|
||||
/// Виджет для подписки на изменение темы приложения
|
||||
/// {@template theme_consumer}
|
||||
/// Виджет для подписки на изменения темы приложения.
|
||||
///
|
||||
/// Автоматически перестраивает дочерние виджеты при изменении темы,
|
||||
/// обеспечивая реактивность интерфейса к изменениям настроек темы.
|
||||
/// {@endtemplate}
|
||||
class ThemeConsumer extends StatelessWidget {
|
||||
/// {@macro theme_consumer}
|
||||
const ThemeConsumer({required this.builder, super.key});
|
||||
|
||||
/// Функция для построения виджета с учетом текущей темы
|
||||
final ThemeBuilder builder;
|
||||
|
||||
@override
|
||||
@@ -19,12 +27,29 @@ class ThemeConsumer extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// Класс для управления темой приложения
|
||||
/// {@template theme_notifier}
|
||||
/// Класс для управления темой приложения.
|
||||
///
|
||||
/// Отвечает за:
|
||||
/// - Хранение текущего режима темы (светлая/темная/системная)
|
||||
/// - Уведомление подписчиков об изменениях темы
|
||||
/// - Переключение между режимами темы
|
||||
/// {@endtemplate}
|
||||
final class ThemeNotifier extends ChangeNotifier {
|
||||
/// {@macro theme_notifier}
|
||||
ThemeNotifier();
|
||||
|
||||
/// Текущий режим темы приложения
|
||||
/// По умолчанию используется системная тема
|
||||
ThemeMode _themeMode = ThemeMode.system;
|
||||
|
||||
/// Получение текущего режима темы
|
||||
ThemeMode get themeMode => _themeMode;
|
||||
|
||||
/// Метод для переключения темы приложения.
|
||||
///
|
||||
/// Переключает между светлой и темной темой.
|
||||
/// Если текущая тема светлая, переключает на темную и наоборот.
|
||||
void changeTheme() {
|
||||
_themeMode = _themeMode == ThemeMode.light
|
||||
? ThemeMode.dark
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// {@template h_box}
|
||||
/// HBox виджет для вертикального отступа (Надстройка над SizedBox)
|
||||
/// Виджет для создания вертикального отступа.
|
||||
///
|
||||
/// Надстройка над SizedBox, предназначенная для создания
|
||||
/// отступов по вертикали с более понятным названием.
|
||||
/// {@endtemplate}
|
||||
class HBox extends SizedBox {
|
||||
/// {@macro h_box}
|
||||
@@ -9,7 +12,10 @@ class HBox extends SizedBox {
|
||||
}
|
||||
|
||||
/// {@template w_box}
|
||||
/// WBox виджет для вертикального отступа (Надстройка над SizedBox)
|
||||
/// Виджет для создания горизонтального отступа.
|
||||
///
|
||||
/// Надстройка над SizedBox, предназначенная для создания
|
||||
/// отступов по горизонтали с более понятным названием.
|
||||
/// {@endtemplate}
|
||||
class WBox extends SizedBox {
|
||||
/// {@macro w_box}
|
||||
|
||||
Reference in New Issue
Block a user