diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..79c113f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,45 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.build/
+.buildlog/
+.history
+.svn/
+.swiftpm/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.pub-cache/
+.pub/
+/build/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/.metadata b/.metadata
new file mode 100644
index 0000000..8af9f15
--- /dev/null
+++ b/.metadata
@@ -0,0 +1,30 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: "17025dd88227cd9532c33fa78f5250d548d87e9a"
+ channel: "stable"
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
+ base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
+ - platform: android
+ create_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
+ base_revision: 17025dd88227cd9532c33fa78f5250d548d87e9a
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..251c85f
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,23 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "dev",
+ "type": "dart",
+ "request": "launch",
+ "program": "${workspaceFolder}/lib/targets/dev.dart",
+ },
+ {
+ "name": "stage",
+ "type": "dart",
+ "request": "launch",
+ "program": "${workspaceFolder}/lib/targets/stage.dart",
+ },
+ {
+ "name": "prod",
+ "type": "dart",
+ "request": "launch",
+ "program": "${workspaceFolder}/lib/targets/prod.dart",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..a3a0436
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,42 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build_runner --delete-conflicting-outputs",
+ "type": "shell",
+ "command": "dart",
+ "args": [
+ "run",
+ "build_runner",
+ "build",
+ "--delete-conflicting-outputs"
+ ],
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "presentation": {
+ "reveal": "always"
+ },
+ "problemMatcher": []
+ },
+ {
+ "label": "build_runner clean",
+ "type": "shell",
+ "command": "dart",
+ "args": [
+ "run",
+ "build_runner",
+ "clean"
+ ],
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "presentation": {
+ "reveal": "always"
+ },
+ "problemMatcher": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/README copy.md b/README copy.md
new file mode 100644
index 0000000..cbdd835
--- /dev/null
+++ b/README copy.md
@@ -0,0 +1,16 @@
+# friflex_starter
+
+A new Flutter project.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
+
+For help getting started with Flutter development, view the
+[online documentation](https://docs.flutter.dev/), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..45d8890
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,10 @@
+include: package:friflex_lint_rules/analysis_options.yaml
+
+analyzer:
+ exclude:
+ - "**/*.g.dart"
+ - "**/*.freezed.dart"
+ - "**/*.yaml"
+ - "app_services/aurora/**"
+ - "/app_services/aurora/**"
+ - "**/app_services/aurora/**"
\ No newline at end of file
diff --git a/android/.gitignore b/android/.gitignore
new file mode 100644
index 0000000..55afd91
--- /dev/null
+++ b/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/to/reference-keystore
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/android/app/build.gradle b/android/app/build.gradle
new file mode 100644
index 0000000..84cdd0d
--- /dev/null
+++ b/android/app/build.gradle
@@ -0,0 +1,44 @@
+plugins {
+ id "com.android.application"
+ id "kotlin-android"
+ // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
+ id "dev.flutter.flutter-gradle-plugin"
+}
+
+android {
+ namespace = "com.pym.miniapp.friflex_starter"
+ compileSdk = flutter.compileSdkVersion
+ ndkVersion = flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId = "com.pym.miniapp.friflex_starter"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://flutter.dev/to/review-gradle-config.
+ minSdk = flutter.minSdkVersion
+ targetSdk = flutter.targetSdkVersion
+ versionCode = flutter.versionCode
+ versionName = flutter.versionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig = signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source = "../.."
+}
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..399f698
--- /dev/null
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..bed9e2e
--- /dev/null
+++ b/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/com/pym/miniapp/friflex_starter/MainActivity.kt b/android/app/src/main/kotlin/com/pym/miniapp/friflex_starter/MainActivity.kt
new file mode 100644
index 0000000..d8adb02
--- /dev/null
+++ b/android/app/src/main/kotlin/com/pym/miniapp/friflex_starter/MainActivity.kt
@@ -0,0 +1,5 @@
+package com.pym.miniapp.friflex_starter
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity()
diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..399f698
--- /dev/null
+++ b/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 0000000..d2ffbff
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,18 @@
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = "../build"
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(":app")
+}
+
+tasks.register("clean", Delete) {
+ delete rootProject.buildDir
+}
diff --git a/android/gradle.properties b/android/gradle.properties
new file mode 100644
index 0000000..2597170
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..7bb2df6
--- /dev/null
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
diff --git a/android/settings.gradle b/android/settings.gradle
new file mode 100644
index 0000000..b9e43bd
--- /dev/null
+++ b/android/settings.gradle
@@ -0,0 +1,25 @@
+pluginManagement {
+ def flutterSdkPath = {
+ def properties = new Properties()
+ file("local.properties").withInputStream { properties.load(it) }
+ def flutterSdkPath = properties.getProperty("flutter.sdk")
+ assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+ return flutterSdkPath
+ }()
+
+ includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
+
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+plugins {
+ id "dev.flutter.flutter-plugin-loader" version "1.0.0"
+ id "com.android.application" version "8.1.0" apply false
+ id "org.jetbrains.kotlin.android" version "1.8.22" apply false
+}
+
+include ":app"
diff --git a/app_services/aurora/app_services/.gitignore b/app_services/aurora/app_services/.gitignore
new file mode 100644
index 0000000..ac5aa98
--- /dev/null
+++ b/app_services/aurora/app_services/.gitignore
@@ -0,0 +1,29 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+build/
diff --git a/app_services/aurora/app_services/.metadata b/app_services/aurora/app_services/.metadata
new file mode 100644
index 0000000..2b37703
--- /dev/null
+++ b/app_services/aurora/app_services/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: "7482962148e8d758338d8a28f589f317e1e42ba4"
+ channel: "stable"
+
+project_type: package
diff --git a/app_services/aurora/app_services/README.md b/app_services/aurora/app_services/README.md
new file mode 100644
index 0000000..a03f3bd
--- /dev/null
+++ b/app_services/aurora/app_services/README.md
@@ -0,0 +1 @@
+# Базовые сервисы для приложения
\ No newline at end of file
diff --git a/app_services/aurora/app_services/analysis_options.yaml b/app_services/aurora/app_services/analysis_options.yaml
new file mode 100644
index 0000000..6e32909
--- /dev/null
+++ b/app_services/aurora/app_services/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:friflex_lint_rules/analysis_options.yaml
\ No newline at end of file
diff --git a/app_services/aurora/app_services/lib/app_services.dart b/app_services/aurora/app_services/lib/app_services.dart
new file mode 100644
index 0000000..7b6c1ee
--- /dev/null
+++ b/app_services/aurora/app_services/lib/app_services.dart
@@ -0,0 +1,4 @@
+library app_services;
+
+export 'src/app_path_provider.dart';
+export 'src/app_secure_storage.dart';
diff --git a/app_services/aurora/app_services/lib/src/app_path_provider.dart b/app_services/aurora/app_services/lib/src/app_path_provider.dart
new file mode 100644
index 0000000..8dbc387
--- /dev/null
+++ b/app_services/aurora/app_services/lib/src/app_path_provider.dart
@@ -0,0 +1,13 @@
+import 'package:i_app_services/i_app_services.dart';
+import 'package:path_provider/path_provider.dart';
+
+/// Класс для Aurora реализации сервиса работы с путями
+class AppPathProvider implements IPathProvider {
+ /// Наименование сервиса
+ static const name = 'AuroraAppPathProvider';
+
+ @override
+ Future getAppDocumentsDirectoryPath() async {
+ return (await getApplicationDocumentsDirectory()).path;
+ }
+}
diff --git a/app_services/aurora/app_services/lib/src/app_secure_storage.dart b/app_services/aurora/app_services/lib/src/app_secure_storage.dart
new file mode 100644
index 0000000..02ce805
--- /dev/null
+++ b/app_services/aurora/app_services/lib/src/app_secure_storage.dart
@@ -0,0 +1,48 @@
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:flutter_secure_storage_aurora/flutter_secure_storage_aurora.dart';
+import 'package:i_app_services/i_app_services.dart';
+
+/// Класс для Aurora реализации сервис по работе с защищенным хранилищем
+final class AppSecureStorage implements ISecureStorage {
+ /// Создает сервис для работы с защищенным хранилищем
+ ///
+ /// Принимает:
+ /// - [secretKey] - ключ шифрования данных
+ AppSecureStorage({required this.secretKey}){
+ FlutterSecureStorageAurora.setSecret(secretKey);
+ }
+
+ @override
+ final String secretKey;
+
+ @override
+ String get name => 'AuroraAppSecureStorage';
+
+ /// Экземпляр хранилища данных
+ final _box = const FlutterSecureStorage();
+
+ @override
+ Future clear() async {
+ await _box.deleteAll();
+ }
+
+ @override
+ Future delete(String key) async {
+ await _box.delete(key: key);
+ }
+
+ @override
+ Future exists(String key) {
+ return _box.containsKey(key: key);
+ }
+
+ @override
+ Future read(String key) async {
+ return _box.read(key: key);
+ }
+
+ @override
+ Future write(String key, String value) async {
+ await _box.write(key: key, value: value);
+ }
+}
diff --git a/app_services/aurora/app_services/pubspec.yaml b/app_services/aurora/app_services/pubspec.yaml
new file mode 100644
index 0000000..d3ca044
--- /dev/null
+++ b/app_services/aurora/app_services/pubspec.yaml
@@ -0,0 +1,37 @@
+name: app_services
+description: "Google сервисы для приложения"
+version: 0.0.1
+publish_to: none
+
+environment:
+ sdk: ^3.5.0
+ flutter: ^3.24.0
+
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+ # Зависимости для сервиса защищенного хранилища
+ flutter_secure_storage: 8.0.0
+ flutter_secure_storage_aurora:
+ git:
+ url: https://gitlab.com/omprussia/flutter/flutter-community-plugins/flutter_secure_storage_aurora.git
+ ref: aurora-0.5.3
+
+ # для работы с путями в хранилища
+ path_provider: 2.1.4
+ path_provider_aurora:
+ git:
+ url: https://gitlab.com/omprussia/flutter/packages.git
+ ref: aurora-path_provider_aurora-0.6.0
+ path: packages/path_provider_aurora
+
+ # Обязательные интерфейсы
+ i_app_services:
+ path: ../../i_app_services
+
+dev_dependencies:
+ friflex_lint_rules:
+ hosted: https://pub.friflex.com
+ version: 4.0.1
diff --git a/app_services/gms/app_services/.gitignore b/app_services/gms/app_services/.gitignore
new file mode 100644
index 0000000..ac5aa98
--- /dev/null
+++ b/app_services/gms/app_services/.gitignore
@@ -0,0 +1,29 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+build/
diff --git a/app_services/gms/app_services/.metadata b/app_services/gms/app_services/.metadata
new file mode 100644
index 0000000..2b37703
--- /dev/null
+++ b/app_services/gms/app_services/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: "7482962148e8d758338d8a28f589f317e1e42ba4"
+ channel: "stable"
+
+project_type: package
diff --git a/app_services/gms/app_services/README.md b/app_services/gms/app_services/README.md
new file mode 100644
index 0000000..a03f3bd
--- /dev/null
+++ b/app_services/gms/app_services/README.md
@@ -0,0 +1 @@
+# Базовые сервисы для приложения
\ No newline at end of file
diff --git a/app_services/gms/app_services/analysis_options.yaml b/app_services/gms/app_services/analysis_options.yaml
new file mode 100644
index 0000000..6e32909
--- /dev/null
+++ b/app_services/gms/app_services/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:friflex_lint_rules/analysis_options.yaml
\ No newline at end of file
diff --git a/app_services/gms/app_services/lib/app_services.dart b/app_services/gms/app_services/lib/app_services.dart
new file mode 100644
index 0000000..7b6c1ee
--- /dev/null
+++ b/app_services/gms/app_services/lib/app_services.dart
@@ -0,0 +1,4 @@
+library app_services;
+
+export 'src/app_path_provider.dart';
+export 'src/app_secure_storage.dart';
diff --git a/app_services/gms/app_services/lib/src/app_path_provider.dart b/app_services/gms/app_services/lib/src/app_path_provider.dart
new file mode 100644
index 0000000..58b250a
--- /dev/null
+++ b/app_services/gms/app_services/lib/src/app_path_provider.dart
@@ -0,0 +1,13 @@
+import 'package:i_app_services/i_app_services.dart';
+import 'package:path_provider/path_provider.dart';
+
+/// Класс для базовой реализации сервиса работы с путями
+class AppPathProvider implements IPathProvider {
+ /// Наименование сервиса
+ static const name = 'GmsAppPathProvider';
+
+ @override
+ Future getAppDocumentsDirectoryPath() async {
+ return (await getApplicationDocumentsDirectory()).path;
+ }
+}
diff --git a/app_services/gms/app_services/lib/src/app_secure_storage.dart b/app_services/gms/app_services/lib/src/app_secure_storage.dart
new file mode 100644
index 0000000..be6e233
--- /dev/null
+++ b/app_services/gms/app_services/lib/src/app_secure_storage.dart
@@ -0,0 +1,44 @@
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+import 'package:i_app_services/i_app_services.dart';
+
+/// Класс для базовой реализации сервис по работе с защищенным хранилищем
+final class AppSecureStorage implements ISecureStorage {
+ /// Создает сервис для работы с защищенным хранилищем
+ ///
+ /// Принимает:
+ /// - [secretKey] - ключ шифрования данных
+ AppSecureStorage({required this.secretKey});
+
+ @override
+ final String secretKey;
+
+ static const name = 'GmsAppSecureStorage';
+
+ /// Экземпляр хранилища данных
+ final _box = const FlutterSecureStorage();
+
+ @override
+ Future clear() async {
+ await _box.deleteAll();
+ }
+
+ @override
+ Future delete(String key) async {
+ await _box.delete(key: key);
+ }
+
+ @override
+ Future exists(String key) {
+ return _box.containsKey(key: key);
+ }
+
+ @override
+ Future read(String key) async {
+ return _box.read(key: key);
+ }
+
+ @override
+ Future write(String key, String value) async {
+ await _box.write(key: key, value: value);
+ }
+}
diff --git a/app_services/gms/app_services/pubspec.yaml b/app_services/gms/app_services/pubspec.yaml
new file mode 100644
index 0000000..35fdc93
--- /dev/null
+++ b/app_services/gms/app_services/pubspec.yaml
@@ -0,0 +1,35 @@
+name: app_services
+description: "Google сервисы для приложения"
+version: 0.0.1
+publish_to: none
+
+environment:
+ sdk: ^3.5.0
+ flutter: ^3.24.0
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+ # Зависимости для сервиса логирования
+ talker_flutter: 4.6.4
+ talker_dio_logger: 4.6.4
+ talker_bloc_logger: 4.6.4
+
+ # Зависимости для сервиса защищенного хранилища
+ flutter_secure_storage: 9.2.4
+
+ # Зависимости для сервиса незащищенного хранилища
+ shared_preferences: 2.3.5
+
+ # для работы с путями в хранилища
+ path_provider: 2.1.5
+
+ # Обязательные интерфейсы
+ i_app_services:
+ path: ../../i_app_services
+
+dev_dependencies:
+ friflex_lint_rules:
+ hosted: https://pub.friflex.com
+ version: 4.0.1
diff --git a/app_services/i_app_services/.gitignore b/app_services/i_app_services/.gitignore
new file mode 100644
index 0000000..ac5aa98
--- /dev/null
+++ b/app_services/i_app_services/.gitignore
@@ -0,0 +1,29 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+build/
diff --git a/app_services/i_app_services/README.md b/app_services/i_app_services/README.md
new file mode 100644
index 0000000..3814655
--- /dev/null
+++ b/app_services/i_app_services/README.md
@@ -0,0 +1 @@
+# Хранит в себе все интерфейсы для реализации общих сервисов
\ No newline at end of file
diff --git a/app_services/i_app_services/analysis_options.yaml b/app_services/i_app_services/analysis_options.yaml
new file mode 100644
index 0000000..45d8890
--- /dev/null
+++ b/app_services/i_app_services/analysis_options.yaml
@@ -0,0 +1,10 @@
+include: package:friflex_lint_rules/analysis_options.yaml
+
+analyzer:
+ exclude:
+ - "**/*.g.dart"
+ - "**/*.freezed.dart"
+ - "**/*.yaml"
+ - "app_services/aurora/**"
+ - "/app_services/aurora/**"
+ - "**/app_services/aurora/**"
\ No newline at end of file
diff --git a/app_services/i_app_services/lib/i_app_services.dart b/app_services/i_app_services/lib/i_app_services.dart
new file mode 100644
index 0000000..887d570
--- /dev/null
+++ b/app_services/i_app_services/lib/i_app_services.dart
@@ -0,0 +1,4 @@
+library i_app_services;
+
+export 'src/i_path_provider.dart';
+export 'src/i_secure_storage.dart';
diff --git a/app_services/i_app_services/lib/src/i_debug_service.dart b/app_services/i_app_services/lib/src/i_debug_service.dart
new file mode 100644
index 0000000..2fb5137
--- /dev/null
+++ b/app_services/i_app_services/lib/src/i_debug_service.dart
@@ -0,0 +1,60 @@
+import 'package:flutter/material.dart';
+
+/// Интерфейс для сервиса отладки
+abstract interface class IDebugService {
+ /// Наименование сервиса
+ static const name = 'IDebugService';
+
+ /// Метод для создания обработчика для BLoC
+ Object createBlocObserver();
+
+ /// Метод для создания обработчика для роутера
+ NavigatorObserver createRouterObserver();
+
+ /// Метод для создания обработчика для http-клиентов
+ Object createHttpInterceptor();
+
+ /// Метод для логгирования предупреждений
+ ///
+ /// Принимает:
+ /// - [message] - сообщение для логгирования в формате [String]
+ void warning(String message);
+
+ /// Метод для логгирования ошибок
+ ///
+ /// Принимает:
+ /// - [message] - сообщение для логгирования в формате [String]
+ /// - [exception] - исключение
+ /// - [stackTrace] - стек вызова
+ void error(String message, [Object? exception, StackTrace? stackTrace]);
+
+ /// Метод для обработки ошибок
+ ///
+ /// Принимает:
+ /// - [error] - исключение
+ /// - [stackTrace] - стек вызова
+ /// - [message] - сообщение для логгирования в формате [String]
+ void handleError(Object error, [StackTrace? stackTrace, String? message]);
+
+ /// Метод для логгирования информативных сообщений
+ ///
+ /// Принимает:
+ /// - [message] - сообщение для логгирования в формате [String]
+ void info(String message);
+
+ /// Метод для логгирования сообщений
+ ///
+ /// Принимает:
+ /// - [message] - сообщение для логгирования в формате [String]
+ void log(String message);
+
+ /// Метод для открытия окна отладки
+ ///
+ /// Принимает:
+ /// - [context] - для определения навигатора по нему
+ /// - [useRootNavigator] - при true, открывает окно в корневом навигаторе
+ Future openDebugScreen(
+ BuildContext context, {
+ bool useRootNavigator = false,
+ });
+}
diff --git a/app_services/i_app_services/lib/src/i_path_provider.dart b/app_services/i_app_services/lib/src/i_path_provider.dart
new file mode 100644
index 0000000..c51123b
--- /dev/null
+++ b/app_services/i_app_services/lib/src/i_path_provider.dart
@@ -0,0 +1,9 @@
+/// Класс для описания интерфейса сервиса
+/// для получения пути хранения файлов
+abstract interface class IPathProvider {
+ /// Наименования интерфейса
+ static const name = 'IPathProvider';
+
+ /// Получение path на внутренне хранилище приложения
+ Future getAppDocumentsDirectoryPath();
+}
diff --git a/app_services/i_app_services/lib/src/i_secure_storage.dart b/app_services/i_app_services/lib/src/i_secure_storage.dart
new file mode 100644
index 0000000..bfed248
--- /dev/null
+++ b/app_services/i_app_services/lib/src/i_secure_storage.dart
@@ -0,0 +1,44 @@
+/// Класс интерфейса для работы с защищенным хранилищем
+abstract interface class ISecureStorage {
+ /// Описывает обязательные параметры имплементаций
+ ///
+ /// Требует:
+ /// - [secretKey] - секретный ключ для шифрования данных
+ const ISecureStorage._({
+ required this.secretKey,
+ });
+
+ /// Секретный ключ для шифрования данных
+ final String secretKey;
+
+ /// Наименования интерфейса
+ static const name = 'ISecureStorage';
+
+ /// Метод для получения значения из защищенного хранилища
+ ///
+ /// Принимает:
+ /// - [key] - ключ
+ Future read(String key);
+
+ /// Метод для записи значения в защищенное хранилище
+ ///
+ /// Принимает:
+ /// - [key] - ключ
+ /// - [value] - значение
+ Future write(String key, String value);
+
+ /// Метод для удаления значения из защищенного хранилища
+ ///
+ /// Принимает:
+ /// - [key] - ключ
+ Future delete(String key);
+
+ /// Метод для очистки защищенного хранилища
+ Future clear();
+
+ /// Метод для проверки наличия значения в защищенном хранилище
+ ///
+ /// Принимает:
+ /// - [key] - ключ
+ Future exists(String key);
+}
diff --git a/app_services/i_app_services/pubspec.yaml b/app_services/i_app_services/pubspec.yaml
new file mode 100644
index 0000000..8ef39b2
--- /dev/null
+++ b/app_services/i_app_services/pubspec.yaml
@@ -0,0 +1,17 @@
+name: i_app_services
+description: "Хранит в себе все интерфейсы для реализации общих сервисов"
+version: 0.0.1
+publish_to: "none"
+
+environment:
+ sdk: ^3.5.0
+ flutter: ^3.24.0
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+dev_dependencies:
+ friflex_lint_rules:
+ hosted: https://pub.friflex.com
+ version: 4.0.1
diff --git a/env/dev.env b/env/dev.env
new file mode 100644
index 0000000..1fe86a9
--- /dev/null
+++ b/env/dev.env
@@ -0,0 +1,3 @@
+baseUrl="https://dev"
+secretKey="dev"
+
diff --git a/env/prod.env b/env/prod.env
new file mode 100644
index 0000000..75da368
--- /dev/null
+++ b/env/prod.env
@@ -0,0 +1,2 @@
+baseUrl="https://prod"
+secretKey="prod"
\ No newline at end of file
diff --git a/env/stage.env b/env/stage.env
new file mode 100644
index 0000000..e69a5da
--- /dev/null
+++ b/env/stage.env
@@ -0,0 +1,2 @@
+baseUrl="https://stage"
+secretKey="stage"
\ No newline at end of file
diff --git a/l10n.yaml b/l10n.yaml
new file mode 100644
index 0000000..4e6692e
--- /dev/null
+++ b/l10n.yaml
@@ -0,0 +1,3 @@
+arb-dir: lib/l10n
+template-arb-file: app_en.arb
+output-localization-file: app_localizations.dart
\ No newline at end of file
diff --git a/lib/app/app.dart b/lib/app/app.dart
new file mode 100644
index 0000000..8d610cf
--- /dev/null
+++ b/lib/app/app.dart
@@ -0,0 +1,89 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:friflex_starter/app/app_context_ext.dart';
+import 'package:friflex_starter/app/theme/app_theme.dart';
+import 'package:friflex_starter/app/theme/theme_notifier.dart';
+import 'package:friflex_starter/di/di_container.dart';
+import 'package:friflex_starter/l10n/localization_notifier.dart';
+import 'package:go_router/go_router.dart';
+import 'package:provider/provider.dart';
+
+/// Класс для реализации объекта приложения
+class App extends StatelessWidget {
+ /// Создает экземпляр приложения
+ ///
+ /// Принимает:
+ /// - [diContainer] - набор зависимостей приложения
+ /// - [router] - экземпляр роутера приложения
+ const App({
+ super.key,
+ required this.diContainer,
+ required this.router,
+ });
+
+ /// Набор зависимостей приложения
+ final DiContainer diContainer;
+
+ /// Экземпляр роутера приложения
+ final GoRouter router;
+
+ @override
+ Widget build(BuildContext context) {
+ return AppProviders(
+ diContainer: diContainer,
+ child: LocalizationConsumer(
+ builder: () => ThemeConsumer(
+ builder: () => _App(router: router),
+ ),
+ ),
+ );
+ }
+}
+
+/// Класс для реализации объекта приложения
+class _App extends StatelessWidget {
+ const _App({required this.router});
+
+ final GoRouter router;
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp.router(
+ routerConfig: router,
+ darkTheme: AppTheme.dark,
+ theme: AppTheme.light,
+ themeMode: context.theme.themeMode,
+ locale: context.localization.locale,
+ localizationsDelegates: AppLocalizations.localizationsDelegates,
+ supportedLocales: AppLocalizations.supportedLocales,
+ );
+ }
+}
+
+/// Класс для реализации провайдеров приложения
+final class AppProviders extends StatelessWidget {
+ const AppProviders({
+ super.key,
+ required this.child,
+ required this.diContainer,
+ });
+
+ final Widget child;
+ final DiContainer diContainer;
+
+ @override
+ Widget build(BuildContext context) {
+ return MultiProvider(
+ providers: [
+ Provider.value(value: diContainer), // Передаем контейнер зависимостей
+ ChangeNotifierProvider(
+ create: (_) => ThemeNotifier(),
+ ), // Провайдер для темы
+ ChangeNotifierProvider(
+ create: (_) => LocalizationNotifier(),
+ ), // Провайдер для локализации
+ ],
+ child: child,
+ );
+ }
+}
diff --git a/lib/app/app_config/app_config.dart b/lib/app/app_config/app_config.dart
new file mode 100644
index 0000000..201e316
--- /dev/null
+++ b/lib/app/app_config/app_config.dart
@@ -0,0 +1,59 @@
+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';
+
+/// Класс для реализации конфигурации с моковыми данными
+@Envied(name: 'Dev', path: 'env/dev.env')
+class AppConfigDev implements IAppConfig {
+ @override
+ AppEnv get env => AppEnv.dev;
+
+ @override
+ String get name => 'AppConfigDev';
+
+ @override
+ @EnviedField()
+ final String baseUrl = _Dev.baseUrl;
+
+ @override
+ @EnviedField(obfuscate: true)
+ final String secretKey = _Dev.secretKey;
+}
+
+/// Класс для реализации конфигурации с продакшн данными
+@Envied(name: 'Prod', path: 'env/prod.env')
+class AppConfigProd implements IAppConfig {
+ @override
+ AppEnv get env => AppEnv.prod;
+
+ @override
+ String get name => 'AppConfigProd';
+
+ @override
+ @EnviedField(obfuscate: true)
+ final String baseUrl = _Prod.baseUrl;
+
+ @override
+ @EnviedField(obfuscate: true)
+ final String secretKey = _Prod.secretKey;
+}
+
+/// Класс для реализации конфигурации с стейдж данными
+@Envied(name: 'Stage', path: 'env/stage.env')
+class AppConfigStage implements IAppConfig {
+ @override
+ AppEnv get env => AppEnv.stage;
+
+ @override
+ String get name => 'AppConfigStage';
+
+ @override
+ @EnviedField(obfuscate: true)
+ final String baseUrl = _Stage.baseUrl;
+
+ @override
+ @EnviedField(obfuscate: true)
+ final String secretKey = _Stage.secretKey;
+}
diff --git a/lib/app/app_config/app_config.g.dart b/lib/app/app_config/app_config.g.dart
new file mode 100644
index 0000000..ca2c5fa
--- /dev/null
+++ b/lib/app/app_config/app_config.g.dart
@@ -0,0 +1,158 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'app_config.dart';
+
+// **************************************************************************
+// EnviedGenerator
+// **************************************************************************
+
+// coverage:ignore-file
+// ignore_for_file: type=lint
+// generated_from: env/dev.env
+final class _Dev {
+ static const String baseUrl = 'https://dev';
+
+ static const List _enviedkeysecretKey = [
+ 45820206,
+ 4292305074,
+ 1553598735,
+ ];
+
+ static const List _envieddatasecretKey = [
+ 45820234,
+ 4292305111,
+ 1553598841,
+ ];
+
+ static final String secretKey = String.fromCharCodes(List.generate(
+ _envieddatasecretKey.length,
+ (int i) => i,
+ growable: false,
+ ).map((int i) => _envieddatasecretKey[i] ^ _enviedkeysecretKey[i]));
+}
+
+// coverage:ignore-file
+// ignore_for_file: type=lint
+// generated_from: env/prod.env
+final class _Prod {
+ static const List _enviedkeybaseUrl = [
+ 3619294633,
+ 560029786,
+ 3178585068,
+ 3377720392,
+ 977735066,
+ 2142081055,
+ 1298585806,
+ 933917938,
+ 1244996901,
+ 1950368931,
+ 2147265964,
+ 2338251746,
+ ];
+
+ static const List _envieddatabaseUrl = [
+ 3619294657,
+ 560029742,
+ 3178584984,
+ 3377720376,
+ 977735145,
+ 2142081061,
+ 1298585825,
+ 933917917,
+ 1244996949,
+ 1950368977,
+ 2147265987,
+ 2338251654,
+ ];
+
+ static final String baseUrl = String.fromCharCodes(List.generate(
+ _envieddatabaseUrl.length,
+ (int i) => i,
+ growable: false,
+ ).map((int i) => _envieddatabaseUrl[i] ^ _enviedkeybaseUrl[i]));
+
+ static const List _enviedkeysecretKey = [
+ 2449171331,
+ 2315988352,
+ 1037757119,
+ 3159274193,
+ ];
+
+ static const List _envieddatasecretKey = [
+ 2449171443,
+ 2315988466,
+ 1037757136,
+ 3159274165,
+ ];
+
+ static final String secretKey = String.fromCharCodes(List.generate(
+ _envieddatasecretKey.length,
+ (int i) => i,
+ growable: false,
+ ).map((int i) => _envieddatasecretKey[i] ^ _enviedkeysecretKey[i]));
+}
+
+// coverage:ignore-file
+// ignore_for_file: type=lint
+// generated_from: env/stage.env
+final class _Stage {
+ static const List _enviedkeybaseUrl = [
+ 443716089,
+ 3928907238,
+ 1851881210,
+ 3858110087,
+ 3324475128,
+ 1601592105,
+ 2404110281,
+ 1092690431,
+ 1025677374,
+ 3283672546,
+ 425122182,
+ 3412521909,
+ 1297182020,
+ ];
+
+ static const List _envieddatabaseUrl = [
+ 443715985,
+ 3928907154,
+ 1851881102,
+ 3858110199,
+ 3324475019,
+ 1601592083,
+ 2404110310,
+ 1092690384,
+ 1025677389,
+ 3283672470,
+ 425122279,
+ 3412521938,
+ 1297181985,
+ ];
+
+ static final String baseUrl = String.fromCharCodes(List.generate(
+ _envieddatabaseUrl.length,
+ (int i) => i,
+ growable: false,
+ ).map((int i) => _envieddatabaseUrl[i] ^ _enviedkeybaseUrl[i]));
+
+ static const List _enviedkeysecretKey = [
+ 58874248,
+ 3497500657,
+ 3833421599,
+ 555777488,
+ 132619188,
+ ];
+
+ static const List _envieddatasecretKey = [
+ 58874363,
+ 3497500549,
+ 3833421694,
+ 555777463,
+ 132619217,
+ ];
+
+ static final String secretKey = String.fromCharCodes(List.generate(
+ _envieddatasecretKey.length,
+ (int i) => i,
+ growable: false,
+ ).map((int i) => _envieddatasecretKey[i] ^ _enviedkeysecretKey[i]));
+}
diff --git a/lib/app/app_config/i_app_config.dart b/lib/app/app_config/i_app_config.dart
new file mode 100644
index 0000000..884b5fb
--- /dev/null
+++ b/lib/app/app_config/i_app_config.dart
@@ -0,0 +1,16 @@
+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;
+}
diff --git a/lib/app/app_context_ext.dart b/lib/app/app_context_ext.dart
new file mode 100644
index 0000000..822af51
--- /dev/null
+++ b/lib/app/app_context_ext.dart
@@ -0,0 +1,24 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:friflex_starter/app/theme/theme_notifier.dart';
+import 'package:friflex_starter/di/di_container.dart';
+import 'package:friflex_starter/l10n/localization_notifier.dart';
+import 'package:provider/provider.dart';
+
+/// Класс, реализующий расширение для контекста приложения
+extension AppContextExt on BuildContext {
+ /// Метод для получения экземпляра DIContainer
+ DiContainer get di => read();
+
+ /// Геттер для получения цветовой схемы
+ ColorScheme get colors => Theme.of(this).colorScheme;
+
+ /// Геттер для получения темы
+ ThemeNotifier get theme => read();
+
+ /// Геттер для получения локализации
+ AppLocalizations get l10n => AppLocalizations.of(this)!;
+
+ /// Геттер для получения управления локализацией
+ LocalizationNotifier get localization => read();
+}
diff --git a/lib/app/app_env.dart b/lib/app/app_env.dart
new file mode 100644
index 0000000..e1620bd
--- /dev/null
+++ b/lib/app/app_env.dart
@@ -0,0 +1,12 @@
+/// Перечислимый тип окружений сборки
+enum AppEnv {
+ /// Тестовое окружение (моковое)
+ dev,
+
+ /// Стейдж окружение (тестовое окружение, которое имеет возможность
+ /// как обращаться в сеть, так и использовать моковые данные)
+ stage,
+
+ /// Продакшен окружение
+ prod,
+}
diff --git a/lib/app/http/app_http_client.dart b/lib/app/http/app_http_client.dart
new file mode 100644
index 0000000..542e003
--- /dev/null
+++ b/lib/app/http/app_http_client.dart
@@ -0,0 +1,146 @@
+import 'package:dio/dio.dart';
+import 'package:friflex_starter/app/app_config/i_app_config.dart';
+import 'package:friflex_starter/app/app_env.dart';
+import 'package:friflex_starter/app/http/i_http_client.dart';
+import 'package:friflex_starter/features/debug/i_debug_service.dart';
+
+/// Класс для реализации HTTP-клиента для управления запросами
+final class AppHttpClient implements IHttpClient {
+ /// Создает HTTP клиент
+ ///
+ /// Принимает:
+ /// - [debugService] - сервис для логирования запросов
+ /// - [appConfig] - конфигурация приложения
+ AppHttpClient({
+ required IDebugService debugService,
+ required IAppConfig appConfig,
+ }) {
+ _httpClient = Dio();
+ _appConfig = appConfig;
+
+ _httpClient.options
+ ..baseUrl = appConfig.baseUrl
+ ..connectTimeout = const Duration(seconds: 5)
+ ..sendTimeout = const Duration(seconds: 7)
+ ..receiveTimeout = const Duration(seconds: 10)
+ ..headers = {
+ 'Content-Type': 'application/json',
+ };
+
+ // Добавление интерцептора для логирования запросов
+ if (appConfig.env != AppEnv.prod) {
+ final interceptor = debugService.createHttpInterceptor();
+ if (interceptor is Interceptor) {
+ _httpClient.interceptors.add(interceptor);
+ }
+ }
+ }
+
+ /// Конфигурация приложения
+ late final IAppConfig _appConfig;
+
+ /// Экземпляр HTTP клиента
+ late final Dio _httpClient;
+
+ @override
+ Future get(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ }) async {
+ _httpClient.options.baseUrl = _appConfig.baseUrl;
+
+ return _httpClient.get(
+ path,
+ data: data,
+ queryParameters: queryParameters,
+ options: options,
+ );
+ }
+
+ @override
+ Future post(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ }) async {
+ _httpClient.options.baseUrl = _appConfig.baseUrl;
+
+ return _httpClient.post(
+ path,
+ data: data,
+ queryParameters: queryParameters,
+ options: options,
+ );
+ }
+
+ @override
+ Future patch(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ }) async {
+ _httpClient.options.baseUrl = _appConfig.baseUrl;
+
+ return _httpClient.patch(
+ path,
+ data: data,
+ queryParameters: queryParameters,
+ options: options,
+ );
+ }
+
+ @override
+ Future put(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ }) async {
+ _httpClient.options.baseUrl = _appConfig.baseUrl;
+
+ return _httpClient.put(
+ path,
+ data: data,
+ queryParameters: queryParameters,
+ options: options,
+ );
+ }
+
+ @override
+ Future delete(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ }) async {
+ _httpClient.options.baseUrl = _appConfig.baseUrl;
+
+ return _httpClient.delete(
+ path,
+ data: data,
+ queryParameters: queryParameters,
+ options: options,
+ );
+ }
+
+ @override
+ Future head(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ }) async {
+ _httpClient.options.baseUrl = _appConfig.baseUrl;
+
+ return _httpClient.head(
+ path,
+ data: data,
+ queryParameters: queryParameters,
+ options: options,
+ );
+ }
+}
diff --git a/lib/app/http/i_http_client.dart b/lib/app/http/i_http_client.dart
new file mode 100644
index 0000000..34d8315
--- /dev/null
+++ b/lib/app/http/i_http_client.dart
@@ -0,0 +1,94 @@
+import 'package:dio/dio.dart';
+
+/// Класс для описания интерфейса сервиса по управлению HTTP запросами
+abstract interface class IHttpClient {
+ /// Описывает поля HTTP клиента
+ const IHttpClient();
+
+ /// Наименование сервиса
+ static const name = 'IHttpClient';
+
+ /// Метод для реализации запроса GET
+ ///
+ /// Принимает:
+ /// - [path] - путь к ресурсу
+ /// - [data] - тело запроса
+ /// - [queryParameters] - параметры запроса
+ /// - [options] - конфигурация запроса
+ Future get(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ });
+
+ /// Метод для реализации запроса POST
+ ///
+ /// Принимает:
+ /// - [path] - путь к ресурсу
+ /// - [data] - тело запроса
+ /// - [queryParameters] - параметры запроса
+ /// - [options] - конфигурация запроса
+ Future post(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ });
+
+ /// Метод для реализации запроса PATCH
+ ///
+ /// Принимает:
+ /// - [path] - путь к ресурсу
+ /// - [data] - тело запроса
+ /// - [queryParameters] - параметры запроса
+ /// - [options] - конфигурация запроса
+ Future patch(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ });
+
+ /// Метод для реализации запроса PUT
+ ///
+ /// Принимает:
+ /// - [path] - путь к ресурсу
+ /// - [data] - тело запроса
+ /// - [queryParameters] - параметры запроса
+ /// - [options] - конфигурация запроса
+ Future put(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ });
+
+ /// Метод для реализации запроса DELETE
+ ///
+ /// Принимает:
+ /// - [path] - путь к ресурсу
+ /// - [data] - тело запроса
+ /// - [queryParameters] - параметры запроса
+ /// - [options] - конфигурация запроса
+ Future delete(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ });
+
+ /// Метод для реализации запроса POST
+ ///
+ /// Принимает:
+ /// - [path] - путь к ресурсу
+ /// - [data] - тело запроса
+ /// - [queryParameters] - параметры запроса
+ /// - [options] - конфигурация запроса
+ Future head(
+ String path, {
+ Object? data,
+ Map? queryParameters,
+ Options? options,
+ });
+}
diff --git a/lib/app/theme/app_colors_scheme.dart b/lib/app/theme/app_colors_scheme.dart
new file mode 100644
index 0000000..4c0f093
--- /dev/null
+++ b/lib/app/theme/app_colors_scheme.dart
@@ -0,0 +1,9 @@
+import 'package:flutter/material.dart';
+
+/// Класс, реализующий расширение для добавления токенов в цветовую схему
+extension AppColorsScheme on ColorScheme {
+ bool get _isDark => brightness == Brightness.dark;
+
+ // Тестовый цвет
+ Color get testColor => _isDark ? Colors.green : Colors.red;
+}
diff --git a/lib/app/theme/app_theme.dart b/lib/app/theme/app_theme.dart
new file mode 100644
index 0000000..4a88777
--- /dev/null
+++ b/lib/app/theme/app_theme.dart
@@ -0,0 +1,10 @@
+import 'package:flutter/material.dart';
+
+/// Класс для конфигурации светлой/темной темы приложения
+abstract class AppTheme {
+ /// Геттер для получения светлой темы
+ static ThemeData get light => ThemeData.light();
+
+ /// Геттер для получения темной темы
+ static ThemeData get dark => ThemeData.dark();
+}
diff --git a/lib/app/theme/theme_notifier.dart b/lib/app/theme/theme_notifier.dart
new file mode 100644
index 0000000..a53ab66
--- /dev/null
+++ b/lib/app/theme/theme_notifier.dart
@@ -0,0 +1,33 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+typedef ThemeBuilder = Widget Function();
+
+/// Виджет для подписки на изменение темы приложения
+class ThemeConsumer extends StatelessWidget {
+ const ThemeConsumer({super.key, required this.builder});
+
+ final ThemeBuilder builder;
+
+ @override
+ Widget build(BuildContext context) {
+ return Consumer(
+ builder: (_, __, ___) {
+ return builder();
+ },
+ );
+ }
+}
+
+/// Класс для управления темой приложения
+final class ThemeNotifier extends ChangeNotifier {
+ ThemeMode _themeMode = ThemeMode.system;
+
+ ThemeMode get themeMode => _themeMode;
+
+ void changeTheme() {
+ _themeMode =
+ _themeMode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light;
+ notifyListeners();
+ }
+}
diff --git a/lib/di/di_base_repo.dart b/lib/di/di_base_repo.dart
new file mode 100644
index 0000000..f7f100f
--- /dev/null
+++ b/lib/di/di_base_repo.dart
@@ -0,0 +1,6 @@
+/// Миксин репозитория в приложении.
+/// Каждый интерфейс репозитория в приложении должен подмешивать текущий класс
+mixin class DiBaseRepo {
+ /// Наименование репозитория
+ String get name => 'DiBaseRepo';
+}
diff --git a/lib/di/di_container.dart b/lib/di/di_container.dart
new file mode 100644
index 0000000..f4c54ad
--- /dev/null
+++ b/lib/di/di_container.dart
@@ -0,0 +1,103 @@
+import 'package:app_services/app_services.dart';
+import 'package:friflex_starter/app/app_config/app_config.dart';
+import 'package:friflex_starter/app/app_config/i_app_config.dart';
+import 'package:friflex_starter/app/app_env.dart';
+import 'package:friflex_starter/app/http/app_http_client.dart';
+import 'package:friflex_starter/app/http/i_http_client.dart';
+import 'package:friflex_starter/di/di_repositories.dart';
+import 'package:friflex_starter/di/di_typedefs.dart';
+import 'package:friflex_starter/features/debug/i_debug_service.dart';
+import 'package:i_app_services/i_app_services.dart';
+
+/// {@template dependencies_container}
+/// Контейнер для зависимостей
+/// {@macro composition_process}
+/// {@endtemplate}
+final class DiContainer {
+ /// {@macro dependencies_container}
+ DiContainer({required this.env, required IDebugService dService})
+ : debugService = dService;
+ final AppEnv env;
+
+ /// Сервис для отладки, получаем из конструктора
+ late final IDebugService debugService;
+
+ /// Сервис для работы с путями
+ late final IPathProvider pathProvider;
+
+ /// Конфигурация приложения
+ late final IAppConfig appConfig;
+
+ /// Сервис для работы с локальным хранилищем
+ late final ISecureStorage secureStorage;
+
+ /// Сервис для работы с HTTP запросами
+ late final IHttpClient httpClient;
+
+ late final DiRepositories repositories;
+
+ /// Метод для инициализации зависимостей
+ Future init({
+ required OnProgress onProgress,
+ required OnComplete onComplete,
+ required OnError onError,
+ }) async {
+ // Инициализация сервисов
+ await _initServices(
+ onComplete: onComplete,
+ onError: onError,
+ onProgress: onProgress,
+ );
+
+ // Инициализация репозиториев
+ repositories = DiRepositories();
+ repositories.init(
+ onProgress: onProgress,
+ onComplete: onComplete,
+ onError: onError,
+ diContainer: this,
+ );
+
+ onComplete('Инициализация зависимостей завершена!');
+ }
+
+ /// Метод для инициализации сервисов
+ Future _initServices({
+ required OnComplete onComplete,
+ required OnError onError,
+ required OnProgress onProgress,
+ }) async {
+ appConfig = switch (env) {
+ AppEnv.dev => AppConfigDev(),
+ AppEnv.prod => AppConfigProd(),
+ AppEnv.stage => AppConfigStage()
+ };
+
+ httpClient = AppHttpClient(
+ debugService: debugService,
+ appConfig: appConfig,
+ );
+
+ try {
+ pathProvider = AppPathProvider();
+ onProgress(AppPathProvider.name);
+ } on Object catch (error, stackTrace) {
+ onError(
+ 'Ошибка инициализации ${IPathProvider.name}',
+ error: error,
+ stackTrace: stackTrace,
+ );
+ }
+
+ try {
+ secureStorage = AppSecureStorage(secretKey: appConfig.secretKey);
+ onProgress(AppSecureStorage.name);
+ } on Object catch (error, stackTrace) {
+ onError(
+ 'Ошибка инициализации ${ISecureStorage.name}',
+ error: error,
+ stackTrace: stackTrace,
+ );
+ }
+ }
+}
diff --git a/lib/di/di_repositories.dart b/lib/di/di_repositories.dart
new file mode 100644
index 0000000..289c7b7
--- /dev/null
+++ b/lib/di/di_repositories.dart
@@ -0,0 +1,115 @@
+import 'package:friflex_starter/app/app_env.dart';
+import 'package:friflex_starter/di/di_base_repo.dart';
+import 'package:friflex_starter/di/di_container.dart';
+import 'package:friflex_starter/di/di_typedefs.dart';
+import 'package:friflex_starter/features/auth/data/repository/auth_mock_repository.dart';
+import 'package:friflex_starter/features/auth/data/repository/auth_repository.dart';
+import 'package:friflex_starter/features/auth/domain/repository/i_auth_repository.dart';
+import 'package:friflex_starter/features/main/data/repository/main_mock_repository.dart';
+import 'package:friflex_starter/features/main/data/repository/main_repository.dart';
+import 'package:friflex_starter/features/main/domain/repository/i_main_repository.dart';
+
+/// Список названий моковых репозиториев, которые должны быть подменены
+/// для использования в сборке stage окружения
+///
+/// Для того, чтобы репозиторий был автоматически подменен на моковый в stage
+/// сборке, необходимо в этом списке указать название мокового репозитория,
+/// обращаясь к соответствующему полю name.
+///
+/// Пример:
+/// ```
+/// [ AuthCheckRepositoryMock().name, ]
+/// ```
+final List _mockReposToSwitch = [];
+
+/// Класс для инициализации репозиториев в приложении
+///
+/// По умолчанию репозиторию присваивается моковая реализация.
+/// В зависимости от окружения либо выполняется подмена репозиторий,
+/// либо используется моковый.
+final class DiRepositories {
+ /// Интерфейс для работы с репозиторием авторизации
+ late final IAuthRepository authRepository;
+
+ /// Интерфейс для работы с репозиторием главного сервиса
+ late final IMainRepository mainRepository;
+
+ /// Метод для инициализации репозиториев в приложении
+ ///
+ /// Принимает:
+ /// - [onProgress] - обратный вызов при прогрессе
+ /// - [onComplete] - обратный вызов при успешной инициализации
+ /// - [diContainer] - контейнер зависимостей
+ void init({
+ required OnProgress onProgress,
+ required OnComplete onComplete,
+ required OnError onError,
+ required DiContainer diContainer,
+ }) {
+ try {
+ //Инициализация репозитория авторизации
+ authRepository = lazyInitRepo(
+ mockFactory: AuthMockRepository.new,
+ mainFactory: () => AuthRepository(
+ httpClient: diContainer.httpClient,
+ ),
+ onProgress: onProgress,
+ environment: diContainer.env,
+ );
+ onProgress(authRepository.name);
+ } on Object catch (error, stackTrace) {
+ onError(
+ 'Ошибка инициализации репозитория $IAuthRepository',
+ error: error,
+ stackTrace: stackTrace,
+ );
+ }
+
+ try {
+ // Инициализация репозитория сервиса управления токеном доступа
+ mainRepository = lazyInitRepo(
+ mockFactory: MainMockRepository.new,
+ mainFactory: () => MainRepository(
+ httpClient: diContainer.httpClient,
+ ),
+ onProgress: onProgress,
+ environment: diContainer.env,
+ );
+ onProgress(mainRepository.name);
+ } on Object catch (error, stackTrace) {
+ onError(
+ 'Ошибка инициализации репозитория $IMainRepository',
+ error: error,
+ stackTrace: stackTrace,
+ );
+ }
+
+ onComplete(
+ 'Инициализация репозиториев завершена! Было подменено репозиториев - ${_mockReposToSwitch.length} (${_mockReposToSwitch.join(', ')})',
+ );
+ }
+
+ /// Метод для ленивой инициализации конкретного репозитория по типу [Т].
+ /// В зависимости от окружения инициализируется моковый или сетевой репозиторий.
+ ///
+ /// Принимает:
+ /// - [mockFactory] - функция - фабрика для инициализации репозитория для управления моковыми запросами
+ /// - [mainFactory] - функция - фабрика для инициализации основного репозиторий
+ /// - [onProgress] - обратный вызов при прогрессе
+ T lazyInitRepo({
+ required AppEnv environment,
+ required T Function() mainFactory,
+ required T Function() mockFactory,
+ required OnProgress onProgress,
+ }) {
+ final repo = switch (environment) {
+ AppEnv.dev => mockFactory(),
+ AppEnv.prod => mainFactory(),
+ AppEnv.stage => _mockReposToSwitch.contains(mockFactory().name)
+ ? mockFactory()
+ : mainFactory(),
+ };
+ onProgress(repo.name);
+ return repo;
+ }
+}
diff --git a/lib/di/di_typedefs.dart b/lib/di/di_typedefs.dart
new file mode 100644
index 0000000..52c9e08
--- /dev/null
+++ b/lib/di/di_typedefs.dart
@@ -0,0 +1,12 @@
+/// Обратный вызов при ошибки инициализации
+typedef OnError = void Function(
+ String message, {
+ Object? error,
+ StackTrace? stackTrace,
+});
+
+/// Обратный вызов при прогрессе
+typedef OnProgress = void Function(String name);
+
+/// Обратный вызов при успешной инициализации
+typedef OnComplete = void Function(String msg);
diff --git a/lib/features/auth/data/repository/auth_mock_repository.dart b/lib/features/auth/data/repository/auth_mock_repository.dart
new file mode 100644
index 0000000..de31710
--- /dev/null
+++ b/lib/features/auth/data/repository/auth_mock_repository.dart
@@ -0,0 +1,9 @@
+import '../../domain/repository/i_auth_repository.dart';
+
+/// {@template AuthMockRepository}
+///
+/// {@endtemplate}
+final class AuthMockRepository implements IAuthRepository {
+ @override
+ String get name => 'AuthMockRepository';
+}
diff --git a/lib/features/auth/data/repository/auth_repository.dart b/lib/features/auth/data/repository/auth_repository.dart
new file mode 100644
index 0000000..947f091
--- /dev/null
+++ b/lib/features/auth/data/repository/auth_repository.dart
@@ -0,0 +1,15 @@
+import 'package:friflex_starter/app/http/i_http_client.dart';
+
+import '../../domain/repository/i_auth_repository.dart';
+
+/// {@template AuthRepository}
+///
+/// {@endtemplate}
+final class AuthRepository implements IAuthRepository {
+ final IHttpClient httpClient;
+
+ AuthRepository({required this.httpClient});
+
+ @override
+ String get name => 'AuthRepository';
+}
diff --git a/lib/features/auth/domain/repository/i_auth_repository.dart b/lib/features/auth/domain/repository/i_auth_repository.dart
new file mode 100644
index 0000000..d9c3f01
--- /dev/null
+++ b/lib/features/auth/domain/repository/i_auth_repository.dart
@@ -0,0 +1,6 @@
+import 'package:friflex_starter/di/di_base_repo.dart';
+
+/// {@template IAuthRepository}
+///
+/// {@endtemplate}
+abstract interface class IAuthRepository with DiBaseRepo {}
diff --git a/lib/features/auth/presentation/screens/auth_screen.dart b/lib/features/auth/presentation/screens/auth_screen.dart
new file mode 100644
index 0000000..813e7b3
--- /dev/null
+++ b/lib/features/auth/presentation/screens/auth_screen.dart
@@ -0,0 +1,21 @@
+import 'package:flutter/material.dart';
+
+/// {@template AuthScreen}
+///
+/// {@endtemplate}
+class AuthScreen extends StatelessWidget {
+ /// {@macro AuthScreen}
+ const AuthScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('AuthScreen'),
+ ),
+ body: const Center(
+ child: Text('AuthScreen'),
+ ),
+ );
+ }
+}
diff --git a/lib/features/debug/app_debug_service.dart b/lib/features/debug/app_debug_service.dart
new file mode 100644
index 0000000..a7d6a40
--- /dev/null
+++ b/lib/features/debug/app_debug_service.dart
@@ -0,0 +1,60 @@
+import 'package:flutter/material.dart';
+import 'package:friflex_starter/features/debug/i_debug_service.dart';
+import 'package:talker_bloc_logger/talker_bloc_logger.dart';
+import 'package:talker_dio_logger/talker_dio_logger_interceptor.dart';
+import 'package:talker_flutter/talker_flutter.dart';
+
+/// Класс реализации интерфейса дебаг сервиса
+class AppDebugService implements IDebugService {
+ /// Наименование сервиса
+ static const name = 'GmsDebugService';
+
+ final Talker _talker = TalkerFlutter.init();
+
+ @override
+ TalkerBlocObserver createBlocObserver() =>
+ TalkerBlocObserver(talker: _talker);
+
+ @override
+ TalkerDioLogger createHttpInterceptor() => TalkerDioLogger(talker: _talker);
+
+ @override
+ TalkerRouteObserver createRouterObserver() => TalkerRouteObserver(_talker);
+
+ @override
+ void error(String msg, [Object? exception, StackTrace? stackTrace]) {
+ _talker.error(msg, exception, stackTrace);
+ }
+
+ @override
+ void handleError(Object error, [StackTrace? stackTrace, String? message]) {
+ _talker.handle(error, stackTrace, message);
+ }
+
+ @override
+ void info(String message) {
+ _talker.info(message);
+ }
+
+ @override
+ void log(String message) {
+ _talker.log(message);
+ }
+
+ @override
+ void warning(String message) {
+ _talker.warning(message);
+ }
+
+ @override
+ Future openDebugScreen(
+ BuildContext context, {
+ bool useRootNavigator = false,
+ }) {
+ return Navigator.of(context).push(
+ MaterialPageRoute(
+ builder: (context) => TalkerScreen(talker: _talker),
+ ),
+ );
+ }
+}
diff --git a/lib/features/debug/debug_routes.dart b/lib/features/debug/debug_routes.dart
new file mode 100644
index 0000000..a82d94c
--- /dev/null
+++ b/lib/features/debug/debug_routes.dart
@@ -0,0 +1,32 @@
+import 'package:flutter/widgets.dart';
+import 'package:friflex_starter/features/debug/debug_screen.dart';
+import 'package:go_router/go_router.dart';
+
+abstract final class DebugRoutes {
+ /// Название роута страницы профиля пользователя
+ static const String debugScreenName = 'debug_screen';
+
+ /// Путь роута страницы профиля пользователя
+ static const String _debugScreenPath = '/debug';
+
+ /// Метод для построения ветки роутов по фиче профиля пользователя
+ ///
+ /// Принимает:
+ /// - [routes] - вложенные роуты
+ static StatefulShellBranch buildShellBranch({
+ List routes = const [],
+ List? observers,
+ }) =>
+ StatefulShellBranch(
+ initialLocation: _debugScreenPath,
+ observers: observers,
+ routes: [
+ GoRoute(
+ path: _debugScreenPath,
+ name: debugScreenName,
+ builder: (context, state) => const DebugScreen(),
+ routes: routes,
+ ),
+ ],
+ );
+}
diff --git a/lib/features/debug/debug_screen.dart b/lib/features/debug/debug_screen.dart
new file mode 100644
index 0000000..304392e
--- /dev/null
+++ b/lib/features/debug/debug_screen.dart
@@ -0,0 +1,45 @@
+import 'package:flutter/material.dart';
+import 'package:friflex_starter/app/app_context_ext.dart';
+
+class DebugScreen extends StatelessWidget {
+ const DebugScreen({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('Debug Screen')),
+ body: Center(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ ElevatedButton(
+ onPressed: () {
+ throw Exception(
+ 'Тестовая ошибка Exception для отладки FlutterError',);
+ },
+ child: const Text('Вызывать ошибку FlutterError'),
+ ),
+ const SizedBox(height: 16),
+ ElevatedButton(
+ onPressed: () async {
+ await callError();
+ },
+ child: const Text('Вызывать ошибку PlatformDispatcher'),
+ ),
+ const SizedBox(height: 16),
+ ElevatedButton(
+ onPressed: () async {
+ await context.di.debugService.openDebugScreen(context);
+ },
+ child: const Text('Вызывать Talker'),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ Future callError() async {
+ throw Exception('Тестовая ошибка Exception для отладки PlatformDispatcher');
+ }
+}
diff --git a/lib/features/debug/i_debug_service.dart b/lib/features/debug/i_debug_service.dart
new file mode 100644
index 0000000..2fb5137
--- /dev/null
+++ b/lib/features/debug/i_debug_service.dart
@@ -0,0 +1,60 @@
+import 'package:flutter/material.dart';
+
+/// Интерфейс для сервиса отладки
+abstract interface class IDebugService {
+ /// Наименование сервиса
+ static const name = 'IDebugService';
+
+ /// Метод для создания обработчика для BLoC
+ Object createBlocObserver();
+
+ /// Метод для создания обработчика для роутера
+ NavigatorObserver createRouterObserver();
+
+ /// Метод для создания обработчика для http-клиентов
+ Object createHttpInterceptor();
+
+ /// Метод для логгирования предупреждений
+ ///
+ /// Принимает:
+ /// - [message] - сообщение для логгирования в формате [String]
+ void warning(String message);
+
+ /// Метод для логгирования ошибок
+ ///
+ /// Принимает:
+ /// - [message] - сообщение для логгирования в формате [String]
+ /// - [exception] - исключение
+ /// - [stackTrace] - стек вызова
+ void error(String message, [Object? exception, StackTrace? stackTrace]);
+
+ /// Метод для обработки ошибок
+ ///
+ /// Принимает:
+ /// - [error] - исключение
+ /// - [stackTrace] - стек вызова
+ /// - [message] - сообщение для логгирования в формате [String]
+ void handleError(Object error, [StackTrace? stackTrace, String? message]);
+
+ /// Метод для логгирования информативных сообщений
+ ///
+ /// Принимает:
+ /// - [message] - сообщение для логгирования в формате [String]
+ void info(String message);
+
+ /// Метод для логгирования сообщений
+ ///
+ /// Принимает:
+ /// - [message] - сообщение для логгирования в формате [String]
+ void log(String message);
+
+ /// Метод для открытия окна отладки
+ ///
+ /// Принимает:
+ /// - [context] - для определения навигатора по нему
+ /// - [useRootNavigator] - при true, открывает окно в корневом навигаторе
+ Future openDebugScreen(
+ BuildContext context, {
+ bool useRootNavigator = false,
+ });
+}
diff --git a/lib/features/error/error_screen.dart b/lib/features/error/error_screen.dart
new file mode 100644
index 0000000..04419bf
--- /dev/null
+++ b/lib/features/error/error_screen.dart
@@ -0,0 +1,23 @@
+import 'package:flutter/material.dart';
+
+/// {@template ErrorScreen}
+/// Экран, когда в приложении произошла фатальная ошибка
+/// {@endtemplate}
+class ErrorScreen extends StatelessWidget {
+ /// {@macro ErrorScreen}
+ const ErrorScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return const MaterialApp(
+ home: Scaffold(
+ body: Center(
+ child: Text(
+ 'Что-то пошло не так, попробуйте перезагрузить приложение',
+ textAlign: TextAlign.center,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/features/main/data/repository/main_mock_repository.dart b/lib/features/main/data/repository/main_mock_repository.dart
new file mode 100644
index 0000000..9eada70
--- /dev/null
+++ b/lib/features/main/data/repository/main_mock_repository.dart
@@ -0,0 +1,9 @@
+import '../../domain/repository/i_main_repository.dart';
+
+/// {@template MainMockRepository}
+///
+/// {@endtemplate}
+final class MainMockRepository implements IMainRepository {
+ @override
+ String get name => 'MainMockRepository';
+}
\ No newline at end of file
diff --git a/lib/features/main/data/repository/main_repository.dart b/lib/features/main/data/repository/main_repository.dart
new file mode 100644
index 0000000..68778e5
--- /dev/null
+++ b/lib/features/main/data/repository/main_repository.dart
@@ -0,0 +1,15 @@
+import 'package:friflex_starter/app/http/i_http_client.dart';
+
+import '../../domain/repository/i_main_repository.dart';
+
+/// {@template MainRepository}
+///
+/// {@endtemplate}
+final class MainRepository implements IMainRepository {
+ final IHttpClient httpClient;
+
+ MainRepository({required this.httpClient});
+
+ @override
+ String get name => 'MainRepository';
+}
diff --git a/lib/features/main/domain/repository/i_main_repository.dart b/lib/features/main/domain/repository/i_main_repository.dart
new file mode 100644
index 0000000..aa3afb9
--- /dev/null
+++ b/lib/features/main/domain/repository/i_main_repository.dart
@@ -0,0 +1,6 @@
+import 'package:friflex_starter/di/di_base_repo.dart';
+
+/// {@template IMainRepository}
+///
+/// {@endtemplate}
+abstract interface class IMainRepository with DiBaseRepo{}
\ No newline at end of file
diff --git a/lib/features/main/presentation/main_routes.dart b/lib/features/main/presentation/main_routes.dart
new file mode 100644
index 0000000..a942189
--- /dev/null
+++ b/lib/features/main/presentation/main_routes.dart
@@ -0,0 +1,32 @@
+import 'package:flutter/widgets.dart';
+import 'package:friflex_starter/features/main/presentation/screens/main_screen.dart';
+import 'package:go_router/go_router.dart';
+
+abstract final class MainRoutes {
+ /// Название роута главной страницы
+ static const String mainScreenName = 'main_screen';
+
+ /// Путь роута страницы профиля пользователя
+ static const String _mainScreenPath = '/main';
+
+ /// Метод для построения ветки роутов по фиче профиля пользователя
+ ///
+ /// Принимает:
+ /// - [routes] - вложенные роуты
+ static StatefulShellBranch buildShellBranch({
+ List routes = const [],
+ List? observers,
+ }) =>
+ StatefulShellBranch(
+ initialLocation: _mainScreenPath,
+ observers: observers,
+ routes: [
+ GoRoute(
+ path: _mainScreenPath,
+ name: mainScreenName,
+ builder: (context, state) => const MainScreen(),
+ routes: routes,
+ ),
+ ],
+ );
+}
diff --git a/lib/features/main/presentation/screens/main_screen.dart b/lib/features/main/presentation/screens/main_screen.dart
new file mode 100644
index 0000000..dd50b93
--- /dev/null
+++ b/lib/features/main/presentation/screens/main_screen.dart
@@ -0,0 +1,73 @@
+import 'package:flutter/material.dart';
+import 'package:friflex_starter/app/app_context_ext.dart';
+import 'package:friflex_starter/app/theme/app_colors_scheme.dart';
+
+class MainScreen extends StatelessWidget {
+ const MainScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Main Screen'),
+ ),
+ body: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ const SizedBox(height: 16),
+ Text(
+ 'Окружение: ${context.di.appConfig.env.name}',
+ ),
+ const SizedBox(height: 16),
+ ElevatedButton(
+ onPressed: () {
+ context.theme.changeTheme();
+ },
+ child: const Text('Сменить тему'),
+ ),
+ const SizedBox(height: 16),
+ ColoredBox(
+ color: context.colors.testColor,
+ child: const SizedBox(height: 100, width: 100),
+ ),
+ const SizedBox(height: 16),
+ Text(
+ 'Текущая тема: ${context.theme.themeMode}',
+ ),
+ const SizedBox(height: 16),
+ Text(
+ 'Текущий репозиторий: ${context.di.repositories.authRepository.name}',
+ ),
+ const SizedBox(height: 16),
+ ElevatedButton(
+ onPressed: () {
+ context.localization.changeLocal(
+ const Locale('ru', 'RU'),
+ );
+ },
+ child: const Text('Сменить язык на Rусский'),
+ ),
+ const SizedBox(height: 16),
+ ElevatedButton(
+ onPressed: () {
+ context.localization.changeLocal(
+ const Locale('en', 'EN'),
+ );
+ },
+ child: const Text('Сменить язык на Английский'),
+ ),
+ const SizedBox(height: 16),
+ Text(
+ 'Тестовое слово: ${context.l10n.helloWorld}',
+ ),
+ const SizedBox(height: 16),
+ Text(
+ 'Текущий язык: ${context.l10n.localeName}',
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/features/root/root_screen.dart b/lib/features/root/root_screen.dart
new file mode 100644
index 0000000..7797e6a
--- /dev/null
+++ b/lib/features/root/root_screen.dart
@@ -0,0 +1,32 @@
+import 'package:flutter/material.dart';
+import 'package:go_router/go_router.dart';
+
+/// Класс для реализации корневой страницы приложения
+class RootScreen extends StatelessWidget {
+ /// Создает корневую страницу приложения
+ ///
+ /// Принимает:
+ /// - [navigationShell] - текущая ветка навигации
+ const RootScreen({
+ super.key,
+ required this.navigationShell,
+ });
+
+ /// Текущая ветка навигации
+ final StatefulNavigationShell navigationShell;
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: navigationShell,
+ bottomNavigationBar: BottomNavigationBar(
+ items: const [
+ BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
+ BottomNavigationBarItem(icon: Icon(Icons.bug_report), label: 'Debug'),
+ ],
+ currentIndex: navigationShell.currentIndex,
+ onTap: navigationShell.goBranch,
+ ),
+ );
+ }
+}
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
new file mode 100644
index 0000000..3975c9d
--- /dev/null
+++ b/lib/l10n/app_en.arb
@@ -0,0 +1,6 @@
+{
+ "helloWorld": "Hello World!",
+ "@helloWorld": {
+ "description": "The conventional newborn programmer greeting"
+ }
+}
\ No newline at end of file
diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb
new file mode 100644
index 0000000..8a5bfbe
--- /dev/null
+++ b/lib/l10n/app_ru.arb
@@ -0,0 +1,6 @@
+{
+ "helloWorld": "Привет, мир!",
+ "@helloWorld": {
+ "description": "Обычное приветствие новичка-программиста"
+ }
+}
\ No newline at end of file
diff --git a/lib/l10n/localization_notifier.dart b/lib/l10n/localization_notifier.dart
new file mode 100644
index 0000000..7c47b95
--- /dev/null
+++ b/lib/l10n/localization_notifier.dart
@@ -0,0 +1,32 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+typedef LocalizationBuilder = Widget Function();
+
+/// Виджет для перестройки виджета в зависимости от локализации
+class LocalizationConsumer extends StatelessWidget {
+ const LocalizationConsumer({super.key, required this.builder});
+
+ final LocalizationBuilder builder;
+
+ @override
+ Widget build(BuildContext context) {
+ return Consumer(
+ builder: (_, __, ___) {
+ return builder();
+ },
+ );
+ }
+}
+
+/// Класс для управления локализацией
+final class LocalizationNotifier extends ChangeNotifier {
+ Locale _locale = const Locale('en', 'US');
+
+ Locale get locale => _locale;
+
+ void changeLocal(Locale locale) {
+ _locale = locale;
+ notifyListeners();
+ }
+}
diff --git a/lib/main.dart b/lib/main.dart
new file mode 100644
index 0000000..6e22de4
--- /dev/null
+++ b/lib/main.dart
@@ -0,0 +1,4 @@
+import 'package:friflex_starter/app/app_env.dart';
+import 'package:friflex_starter/runner/app_runner.dart';
+
+void main() => AppRunner(AppEnv.prod).run();
diff --git a/lib/router/app_router.dart b/lib/router/app_router.dart
new file mode 100644
index 0000000..4420ec5
--- /dev/null
+++ b/lib/router/app_router.dart
@@ -0,0 +1,41 @@
+import 'package:flutter/cupertino.dart';
+import 'package:friflex_starter/features/debug/debug_routes.dart';
+import 'package:friflex_starter/features/debug/i_debug_service.dart';
+import 'package:friflex_starter/features/main/presentation/main_routes.dart';
+import 'package:friflex_starter/features/root/root_screen.dart';
+import 'package:go_router/go_router.dart';
+
+/// Класс, реализующий роутер приложения и все поля классов
+class AppRouter {
+ /// Конструктор для инициализации роутера
+ const AppRouter();
+
+ /// Ключ для доступа к корневому навигатору приложения
+ static final rootNavigatorKey = GlobalKey();
+
+ /// Начальный роут приложения
+ static String get initialLocation => '/main';
+
+ /// Метод для создания экземпляра GoRouter
+ static GoRouter createRouter(IDebugService debugService) {
+ return GoRouter(
+ navigatorKey: rootNavigatorKey,
+ debugLogDiagnostics: true,
+ initialLocation: initialLocation,
+ observers: [
+ debugService.createRouterObserver(),
+ ],
+ routes: [
+ StatefulShellRoute.indexedStack(
+ parentNavigatorKey: rootNavigatorKey,
+ builder: (context, state, navigationShell) =>
+ RootScreen(navigationShell: navigationShell),
+ branches: [
+ MainRoutes.buildShellBranch(),
+ DebugRoutes.buildShellBranch(),
+ ],
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/runner/app_runner.dart b/lib/runner/app_runner.dart
new file mode 100644
index 0000000..259bf8e
--- /dev/null
+++ b/lib/runner/app_runner.dart
@@ -0,0 +1,107 @@
+import 'dart:async';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:friflex_starter/app/app.dart';
+import 'package:friflex_starter/app/app_env.dart';
+import 'package:friflex_starter/di/di_container.dart';
+import 'package:friflex_starter/features/debug/app_debug_service.dart';
+import 'package:friflex_starter/features/debug/i_debug_service.dart';
+import 'package:friflex_starter/features/error/error_screen.dart';
+import 'package:friflex_starter/router/app_router.dart';
+import 'package:friflex_starter/runner/timer_runner.dart';
+import 'package:go_router/go_router.dart';
+
+part 'errors_handlers.dart';
+
+/// Класс, реализующий раннер для конфигурирования приложения при запуске
+///
+/// Порядок инициализации:
+/// 1. _initApp - инициализация конфигурации приложения
+/// 2. инициализация репозиториев приложения (будет позже)
+/// 3. runApp - запуск приложения
+/// 4. _onAppLoaded - после запуска приложения
+class AppRunner {
+ /// Создает экземпляр раннера приложения
+ ///
+ /// Принимает:
+ /// - [env] - тип окружения сборки приложения
+ AppRunner(this.env);
+
+ /// Тип окружения сборки приложения¬
+ final AppEnv env;
+
+ /// Контейнер зависимостей приложения
+ late final IDebugService _debugService;
+
+ /// Роутер приложения
+ late final GoRouter router;
+
+ /// Таймер для отслеживания времени инициализации приложения
+ late final TimerRunner _timerRunner;
+
+ /// Метод для запуска приложения
+ Future run() async {
+ WidgetsFlutterBinding.ensureInitialized();
+ // Инициализация сервиса отладки
+ _debugService = AppDebugService();
+
+ _timerRunner = TimerRunner(_debugService);
+
+ // Инициализация приложения
+ await _initApp();
+
+ // Инициализация метода обработки ошибок
+ _initErrorHandlers(_debugService);
+
+ // Инициализация репозиториев и сервисов
+ final diContainer = await _initDependencies(_debugService);
+
+ // Инициализация роутера
+ router = AppRouter.createRouter(_debugService);
+
+ runApp(
+ App(diContainer: diContainer, router: router),
+ );
+ await _onAppLoaded();
+ }
+
+ /// Метод инициализации приложения,
+ /// выполняется до запуска приложения
+ Future _initApp() async {
+ // Запрет на поворот экрана
+ await SystemChrome.setPreferredOrientations(
+ [DeviceOrientation.portraitUp],
+ );
+
+ // Заморозка первого кадра (сплеш)
+ WidgetsBinding.instance.deferFirstFrame();
+ }
+
+ /// Метод срабатывает после запуска приложения
+ Future _onAppLoaded() async {
+ // Разморозка первого кадра (сплеш)
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ WidgetsBinding.instance.allowFirstFrame();
+ });
+
+ _timerRunner.stop();
+ }
+
+ /// Метод для инициализации зависимостей приложения
+ Future _initDependencies(IDebugService debugService) async {
+ debugService.log('Тип сборки: ${env.name}');
+ final diContainer = DiContainer(
+ env: env,
+ dService: debugService,
+ );
+ await diContainer.init(
+ onProgress: _timerRunner.logOnProgress,
+ onComplete: _timerRunner.logOnComplete,
+ onError: _timerRunner.logOnError,
+ );
+
+ return diContainer;
+ }
+}
diff --git a/lib/runner/errors_handlers.dart b/lib/runner/errors_handlers.dart
new file mode 100644
index 0000000..2d00ced
--- /dev/null
+++ b/lib/runner/errors_handlers.dart
@@ -0,0 +1,27 @@
+part of 'app_runner.dart';
+
+/// Метод инициализации обработчиков ошибок
+void _initErrorHandlers(IDebugService debugService) {
+ // Обработка ошибок в приложении
+ FlutterError.onError = (details) {
+ _showErrorScreen();
+ debugService.handleError(details.exception, details.stack,
+ 'FlutterError.onError: ${details.exceptionAsString()}',);
+ };
+ // Обработка асинхронных ошибок в приложении
+ PlatformDispatcher.instance.onError = (error, stack) {
+ _showErrorScreen();
+ debugService.handleError(error, stack, 'PlatformDispatcher: $error');
+ return true;
+ };
+}
+/// Метод для показа экрана ошибки
+void _showErrorScreen() {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ AppRouter.rootNavigatorKey.currentState?.push(
+ MaterialPageRoute(
+ builder: (_) => const ErrorScreen(),
+ ),
+ );
+ });
+}
diff --git a/lib/runner/timer_runner.dart b/lib/runner/timer_runner.dart
new file mode 100644
index 0000000..24794e5
--- /dev/null
+++ b/lib/runner/timer_runner.dart
@@ -0,0 +1,49 @@
+import 'package:friflex_starter/features/debug/i_debug_service.dart';
+
+/// {@template TimerRunner}
+/// Класс для подсчета времени запуска приложения
+/// {@endtemplate}
+class TimerRunner {
+ /// {@macro TimerRunner}
+ TimerRunner(this._debugService) {
+ _stopwatch.start();
+ }
+
+ /// Сервис для отладки
+ final IDebugService _debugService;
+
+ /// Секундомер для подсчета времени инициализации
+ final _stopwatch = Stopwatch();
+
+ /// Метод для остановки секундомера и вывода времени
+ /// полной инициализации приложения
+ void stop() {
+ _stopwatch.stop();
+ _debugService.log(
+ 'Время инициализации приложения: ${_stopwatch.elapsedMilliseconds} мс',
+ );
+ }
+
+ /// Метод для обработки прогресса инициализации зависимостей
+ void logOnProgress(String name) {
+ _debugService.log(
+ '$name успешная инициализация, прогресс: ${_stopwatch.elapsedMilliseconds} мс',
+ );
+ }
+
+ /// Метод для обработки прогресса инициализации зависимостей
+ void logOnComplete(String message) {
+ _debugService.log(
+ '$message, прогресс: ${_stopwatch.elapsedMilliseconds} мс',
+ );
+ }
+
+ /// Метод для обработки прогресса инициализации зависимостей
+ void logOnError(
+ String message, {
+ Object? error,
+ StackTrace? stackTrace,
+ }) {
+ _debugService.error(message, error, stackTrace);
+ }
+}
diff --git a/lib/targets/dev.dart b/lib/targets/dev.dart
new file mode 100644
index 0000000..95804b7
--- /dev/null
+++ b/lib/targets/dev.dart
@@ -0,0 +1,4 @@
+import 'package:friflex_starter/app/app_env.dart';
+import 'package:friflex_starter/runner/app_runner.dart';
+
+void main() => AppRunner(AppEnv.dev).run();
diff --git a/lib/targets/prod.dart b/lib/targets/prod.dart
new file mode 100644
index 0000000..37ff7f0
--- /dev/null
+++ b/lib/targets/prod.dart
@@ -0,0 +1,5 @@
+
+import 'package:friflex_starter/app/app_env.dart';
+import 'package:friflex_starter/runner/app_runner.dart';
+
+void main() => AppRunner(AppEnv.prod).run();
diff --git a/lib/targets/stage.dart b/lib/targets/stage.dart
new file mode 100644
index 0000000..151e7cb
--- /dev/null
+++ b/lib/targets/stage.dart
@@ -0,0 +1,5 @@
+
+import 'package:friflex_starter/app/app_env.dart';
+import 'package:friflex_starter/runner/app_runner.dart';
+
+void main() => AppRunner(AppEnv.stage).run();
diff --git a/pubspec.lock b/pubspec.lock
new file mode 100644
index 0000000..c9a69fe
--- /dev/null
+++ b/pubspec.lock
@@ -0,0 +1,1018 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ _fe_analyzer_shared:
+ dependency: transitive
+ description:
+ name: _fe_analyzer_shared
+ sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
+ url: "https://pub.dev"
+ source: hosted
+ version: "76.0.0"
+ _macros:
+ dependency: transitive
+ description: dart
+ source: sdk
+ version: "0.3.3"
+ analyzer:
+ dependency: transitive
+ description:
+ name: analyzer
+ sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.11.0"
+ ansicolor:
+ dependency: transitive
+ description:
+ name: ansicolor
+ sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.3"
+ app_services:
+ dependency: "direct main"
+ description:
+ path: "app_services/gms/app_services"
+ relative: true
+ source: path
+ version: "0.0.1"
+ args:
+ dependency: transitive
+ description:
+ name: args
+ sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.6.0"
+ async:
+ dependency: transitive
+ description:
+ name: async
+ sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.11.0"
+ bloc:
+ dependency: transitive
+ description:
+ name: bloc
+ sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.1.4"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ build:
+ dependency: transitive
+ description:
+ name: build
+ sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.2"
+ build_config:
+ dependency: transitive
+ description:
+ name: build_config
+ sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.2"
+ build_daemon:
+ dependency: transitive
+ description:
+ name: build_daemon
+ sha256: "294a2edaf4814a378725bfe6358210196f5ea37af89ecd81bfa32960113d4948"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.3"
+ build_resolvers:
+ dependency: transitive
+ description:
+ name: build_resolvers
+ sha256: "99d3980049739a985cf9b21f30881f46db3ebc62c5b8d5e60e27440876b1ba1e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.3"
+ build_runner:
+ dependency: "direct dev"
+ description:
+ name: build_runner
+ sha256: "74691599a5bc750dc96a6b4bfd48f7d9d66453eab04c7f4063134800d6a5c573"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.14"
+ build_runner_core:
+ dependency: transitive
+ description:
+ name: build_runner_core
+ sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021"
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.0.0"
+ built_collection:
+ dependency: transitive
+ description:
+ name: built_collection
+ sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.1.1"
+ built_value:
+ dependency: transitive
+ description:
+ name: built_value
+ sha256: "28a712df2576b63c6c005c465989a348604960c0958d28be5303ba9baa841ac2"
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.9.3"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ checked_yaml:
+ dependency: transitive
+ description:
+ name: checked_yaml
+ sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.3"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ code_builder:
+ dependency: transitive
+ description:
+ name: code_builder
+ sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.10.1"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.19.0"
+ convert:
+ dependency: transitive
+ description:
+ name: convert
+ sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.2"
+ cross_file:
+ dependency: transitive
+ description:
+ name: cross_file
+ sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.3.4+2"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.6"
+ cupertino_icons:
+ dependency: "direct main"
+ description:
+ name: cupertino_icons
+ sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.8"
+ dart_style:
+ dependency: transitive
+ description:
+ name: dart_style
+ sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.7"
+ dio:
+ dependency: "direct main"
+ description:
+ name: dio
+ sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.7.0"
+ dio_web_adapter:
+ dependency: transitive
+ description:
+ name: dio_web_adapter
+ sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.0"
+ envied:
+ dependency: "direct main"
+ description:
+ name: envied
+ sha256: "08a9012e5d93e1a816919a52e37c7b8367e73ebb8d52d1ca7dd6fcd875a2cd2c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.1"
+ envied_generator:
+ dependency: "direct dev"
+ description:
+ name: envied_generator
+ sha256: "9a49ca9f3744069661c4f2c06993647699fae2773bca10b593fbb3228d081027"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.1"
+ equatable:
+ dependency: transitive
+ description:
+ name: equatable
+ sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.7"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.1"
+ ffi:
+ dependency: transitive
+ description:
+ name: ffi
+ sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.3"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.1"
+ fixnum:
+ dependency: transitive
+ description:
+ name: fixnum
+ sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_bloc:
+ dependency: "direct main"
+ description:
+ name: flutter_bloc
+ sha256: "890c51c8007f0182360e523518a0c732efb89876cb4669307af7efada5b55557"
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.1.1"
+ flutter_lints:
+ dependency: transitive
+ description:
+ name: flutter_lints
+ sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.3"
+ flutter_localizations:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_secure_storage:
+ dependency: transitive
+ description:
+ name: flutter_secure_storage
+ sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea"
+ url: "https://pub.dev"
+ source: hosted
+ version: "9.2.4"
+ flutter_secure_storage_linux:
+ dependency: transitive
+ description:
+ name: flutter_secure_storage_linux
+ sha256: bf7404619d7ab5c0a1151d7c4e802edad8f33535abfbeff2f9e1fe1274e2d705
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.2"
+ flutter_secure_storage_macos:
+ dependency: transitive
+ description:
+ name: flutter_secure_storage_macos
+ sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.3"
+ flutter_secure_storage_platform_interface:
+ dependency: transitive
+ description:
+ name: flutter_secure_storage_platform_interface
+ sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.2"
+ flutter_secure_storage_web:
+ dependency: transitive
+ description:
+ name: flutter_secure_storage_web
+ sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.1"
+ flutter_secure_storage_windows:
+ dependency: transitive
+ description:
+ name: flutter_secure_storage_windows
+ sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.2"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_web_plugins:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ friflex_lint_rules:
+ dependency: "direct dev"
+ description:
+ name: friflex_lint_rules
+ sha256: "27c92a58f63313a2d512db812ecbddc8f671c86af13b2e52d8fd27cf2ee5b731"
+ url: "https://pub.friflex.com"
+ source: hosted
+ version: "4.0.1"
+ frontend_server_client:
+ dependency: transitive
+ description:
+ name: frontend_server_client
+ sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.0"
+ glob:
+ dependency: transitive
+ description:
+ name: glob
+ sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ go_router:
+ dependency: "direct main"
+ description:
+ name: go_router
+ sha256: "7c2d40b59890a929824f30d442e810116caf5088482629c894b9e4478c67472d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "14.6.3"
+ graphs:
+ dependency: transitive
+ description:
+ name: graphs
+ sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.2"
+ group_button:
+ dependency: transitive
+ description:
+ name: group_button
+ sha256: "0610fcf28ed122bfb4b410fce161a390f7f2531d55d1d65c5375982001415940"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.3.4"
+ http_multi_server:
+ dependency: transitive
+ description:
+ name: http_multi_server
+ sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.2"
+ http_parser:
+ dependency: transitive
+ description:
+ name: http_parser
+ sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.2"
+ i_app_services:
+ dependency: "direct main"
+ description:
+ path: "app_services/i_app_services"
+ relative: true
+ source: path
+ version: "0.0.1"
+ intl:
+ dependency: "direct main"
+ description:
+ name: intl
+ sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.19.0"
+ io:
+ dependency: transitive
+ description:
+ name: io
+ sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.5"
+ js:
+ dependency: transitive
+ description:
+ name: js
+ sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.6.7"
+ json_annotation:
+ dependency: transitive
+ description:
+ name: json_annotation
+ sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.9.0"
+ leak_tracker:
+ dependency: transitive
+ description:
+ name: leak_tracker
+ sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
+ url: "https://pub.dev"
+ source: hosted
+ version: "10.0.7"
+ leak_tracker_flutter_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_flutter_testing
+ sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.8"
+ leak_tracker_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_testing
+ sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ lints:
+ dependency: transitive
+ description:
+ name: lints
+ sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ macros:
+ dependency: transitive
+ description:
+ name: macros
+ sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.3-main.0"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.12.16+1"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.11.1"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.15.0"
+ mime:
+ dependency: transitive
+ description:
+ name: mime
+ sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.0"
+ nested:
+ dependency: transitive
+ description:
+ name: nested
+ sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
+ package_config:
+ dependency: transitive
+ description:
+ name: package_config
+ sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.9.0"
+ path_provider:
+ dependency: transitive
+ description:
+ name: path_provider
+ sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.5"
+ path_provider_android:
+ dependency: transitive
+ description:
+ name: path_provider_android
+ sha256: "4adf4fd5423ec60a29506c76581bc05854c55e3a0b72d35bb28d661c9686edf2"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.15"
+ path_provider_foundation:
+ dependency: transitive
+ description:
+ name: path_provider_foundation
+ sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ path_provider_linux:
+ dependency: transitive
+ description:
+ name: path_provider_linux
+ sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.1"
+ path_provider_platform_interface:
+ dependency: transitive
+ description:
+ name: path_provider_platform_interface
+ sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ path_provider_windows:
+ dependency: transitive
+ description:
+ name: path_provider_windows
+ sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.0"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.6"
+ plugin_platform_interface:
+ dependency: transitive
+ description:
+ name: plugin_platform_interface
+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.8"
+ pool:
+ dependency: transitive
+ description:
+ name: pool
+ sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.5.1"
+ provider:
+ dependency: "direct main"
+ description:
+ name: provider
+ sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.1.2"
+ pub_semver:
+ dependency: transitive
+ description:
+ name: pub_semver
+ sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.5"
+ pubspec_parse:
+ dependency: transitive
+ description:
+ name: pubspec_parse
+ sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.5.0"
+ recase:
+ dependency: transitive
+ description:
+ name: recase
+ sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.0"
+ share_plus:
+ dependency: transitive
+ description:
+ name: share_plus
+ sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da
+ url: "https://pub.dev"
+ source: hosted
+ version: "10.1.4"
+ share_plus_platform_interface:
+ dependency: transitive
+ description:
+ name: share_plus_platform_interface
+ sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.0.2"
+ shared_preferences:
+ dependency: transitive
+ description:
+ name: shared_preferences
+ sha256: a752ce92ea7540fc35a0d19722816e04d0e72828a4200e83a98cf1a1eb524c9a
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.5"
+ shared_preferences_android:
+ dependency: transitive
+ description:
+ name: shared_preferences_android
+ sha256: "138b7bbbc7f59c56236e426c37afb8f78cbc57b094ac64c440e0bb90e380a4f5"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.2"
+ shared_preferences_foundation:
+ dependency: transitive
+ description:
+ name: shared_preferences_foundation
+ sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.5.4"
+ shared_preferences_linux:
+ dependency: transitive
+ description:
+ name: shared_preferences_linux
+ sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ shared_preferences_platform_interface:
+ dependency: transitive
+ description:
+ name: shared_preferences_platform_interface
+ sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ shared_preferences_web:
+ dependency: transitive
+ description:
+ name: shared_preferences_web
+ sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.2"
+ shared_preferences_windows:
+ dependency: transitive
+ description:
+ name: shared_preferences_windows
+ sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ shelf:
+ dependency: transitive
+ description:
+ name: shelf
+ sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.2"
+ shelf_web_socket:
+ dependency: transitive
+ description:
+ name: shelf_web_socket
+ sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.1"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ source_gen:
+ dependency: transitive
+ description:
+ name: source_gen
+ sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.5.0"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.10.0"
+ sprintf:
+ dependency: transitive
+ description:
+ name: sprintf
+ sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.0"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.12.0"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ stream_transform:
+ dependency: transitive
+ description:
+ name: stream_transform
+ sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ talker:
+ dependency: transitive
+ description:
+ name: talker
+ sha256: "4c3b9b7b8c8882fc30253bbbe7c75d2f68d63ea35b7c1b6be2debe4a323c2ec9"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.6.4"
+ talker_bloc_logger:
+ dependency: "direct main"
+ description:
+ name: talker_bloc_logger
+ sha256: c14510bfb36af5d1648683a2707bb5bbb2858e3cabd549e363262db100bae374
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.6.4"
+ talker_dio_logger:
+ dependency: "direct main"
+ description:
+ name: talker_dio_logger
+ sha256: b0d2c3486d1f17cb9eb187ee91bc23e5d7c438b80464432c3deb809d29228f8d
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.6.4"
+ talker_flutter:
+ dependency: "direct main"
+ description:
+ name: talker_flutter
+ sha256: f23d184bc1ea675ed0fe1bfda636707f155f0596e898a7709bc488ead2c546b3
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.6.4"
+ talker_logger:
+ dependency: transitive
+ description:
+ name: talker_logger
+ sha256: "27e4d0ba5c6950643a2500ad6c2e189099d0b9912f67389a49155e48fc2d9a55"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.6.4"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.1"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.3"
+ timing:
+ dependency: transitive
+ description:
+ name: timing
+ sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.2"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.0"
+ url_launcher_linux:
+ dependency: transitive
+ description:
+ name: url_launcher_linux
+ sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.1"
+ url_launcher_platform_interface:
+ dependency: transitive
+ description:
+ name: url_launcher_platform_interface
+ sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.2"
+ url_launcher_web:
+ dependency: transitive
+ description:
+ name: url_launcher_web
+ sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.0"
+ url_launcher_windows:
+ dependency: transitive
+ description:
+ name: url_launcher_windows
+ sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.4"
+ uuid:
+ dependency: transitive
+ description:
+ name: uuid
+ sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.5.1"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ vm_service:
+ dependency: transitive
+ description:
+ name: vm_service
+ sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
+ url: "https://pub.dev"
+ source: hosted
+ version: "14.3.0"
+ watcher:
+ dependency: transitive
+ description:
+ name: watcher
+ sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ web:
+ dependency: transitive
+ description:
+ name: web
+ sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
+ web_socket:
+ dependency: transitive
+ description:
+ name: web_socket
+ sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.6"
+ web_socket_channel:
+ dependency: transitive
+ description:
+ name: web_socket_channel
+ sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ win32:
+ dependency: transitive
+ description:
+ name: win32
+ sha256: "154360849a56b7b67331c21f09a386562d88903f90a1099c5987afc1912e1f29"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.10.0"
+ xdg_directories:
+ dependency: transitive
+ description:
+ name: xdg_directories
+ sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
+ yaml:
+ dependency: transitive
+ description:
+ name: yaml
+ sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.3"
+sdks:
+ dart: ">=3.6.0 <4.0.0"
+ flutter: ">=3.27.0"
diff --git a/pubspec.yaml b/pubspec.yaml
new file mode 100644
index 0000000..46ade01
--- /dev/null
+++ b/pubspec.yaml
@@ -0,0 +1,85 @@
+name: friflex_starter
+description: "A new Flutter project."
+
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+version: 1.0.0+1
+
+environment:
+ sdk: ^3.6.0
+
+dependencies:
+ flutter:
+ sdk: flutter
+ cupertino_icons: 1.0.8
+ envied: 1.0.1
+ go_router: 14.6.3
+ flutter_bloc: 8.1.1
+ provider: 6.1.2
+ dio: 5.7.0
+ intl: 0.19.0
+ flutter_localizations:
+ sdk: flutter
+
+ # Зависимости для сервиса логирования
+ talker_flutter: 4.6.4
+ talker_dio_logger: 4.6.4
+ talker_bloc_logger: 4.6.4
+
+ ### основной сервис с интерфейсами
+ i_app_services:
+ path: ./app_services/i_app_services
+
+ app_services:
+ ### Базовая реализация ###
+ path: app_services/gms/app_services
+
+
+ ### Аврора реализация ###
+ #path: app_services/aurora/app_services
+ ### Telegram реализация ###
+ #path: app_services/telegram/app_services
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+ friflex_lint_rules:
+ hosted: https://pub.friflex.com
+ version: 4.0.1
+ envied_generator: 1.0.1
+ build_runner: 2.4.14
+
+flutter:
+ uses-material-design: true
+ generate: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/to/resolution-aware-images
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/to/asset-from-package
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/to/font-from-package