diff --git a/README.md b/README.md
index 43e2ae5..5a0c194 100644
--- a/README.md
+++ b/README.md
@@ -5,29 +5,42 @@ It contains the source code for Aurora Flutter's packages (i.e., packages develo
## Package done
-Packages made or for review
+Package verified
-| Package | Version | OS Version | State | Comment |
-|-------------------------------------------------------------------------------------|----------|------------|---------|---------------------------------------------------------------------|
-| [battery_plus](https://pub.dev/packages/battery_plus) | 4.0.1 | 4.0.2 | Review | - |
-| [device_info_plus](https://pub.dev/packages/device_info_plus) | 9.0.2 | 4.0.2 | Review | - |
-| [flutter_local_notifications](https://pub.dev/packages/flutter_local_notifications) | 14.1.1 | 4.0.2 | Done | - |
-| [flutter_secure_storage](https://pub.dev/packages/flutter_secure_storage) | 8.0.0 | 4.0.2 | Review | Ключь нужно генерировать сейчас самому, например через пин от юзера |
-| [package_info_plus](https://pub.dev/packages/package_info_plus) | 4.0.2 | 4.0.2 | Done | Достать `version` & `build_number` не удалось |
-| [path_provider](https://pub.dev/packages/path_provider) | 2.0.15 | 4.0.2 | Review | - |
-| [shared_preferences](https://pub.dev/packages/shared_preferences) | 2.1.2 | 4.0.2 | Review | - |
-| [sqflite](https://pub.dev/packages/sqflite) | 2.2.6 | 4.0.2 | Review | - |
-| [wakelock](https://pub.dev/packages/wakelock) | 0.6.2 | 4.0.2 | Review | - |
-| xdga_directories | - | 4.0.2 | Review | Аналог [xdg_directories](https://pub.dev/packages/xdg_directories) |
-
-## Package verified
-
-Verified packages on Aurora OS
-
-| Package | Version | OS Version | State | Comment |
-|-------------------------------------------------------------------------|----------|-------------|--------|------------------------------------|
-| [flutter_cache_manager](https://pub.dev/packages/flutter_cache_manager) | 3.3.0 | 4.0.2 | Done | Depends on `path_provider` |
-| [cached_network_image](https://pub.dev/packages/cached_network_image) | 3.2.3 | 4.0.2 | Done | Depends on `flutter_cache_manager` |
+| Package | Version | OS Version | Comment |
+|-------------------------------------------------------------------------------------|-----------|------------|---------------------------------------------------------------------|
+| [flutter_keyboard_visibility](https://pub.dev/packages/flutter_keyboard_visibility) | 5.4.1 | 4.0.2 | Дополнительная фича с получением высоты клавиатуры |
+| [battery_plus](https://pub.dev/packages/battery_plus) | 4.0.1 | 4.0.2 | - |
+| [device_info_plus](https://pub.dev/packages/device_info_plus) | 8.2.2 | 4.0.2 | - |
+| [flutter_local_notifications](https://pub.dev/packages/flutter_local_notifications) | 14.1.1 | 4.0.2 | - |
+| [flutter_secure_storage](https://pub.dev/packages/flutter_secure_storage) | 8.0.0 | 4.0.2 | Ключь нужно генерировать сейчас самому, например через пин от юзера |
+| [package_info_plus](https://pub.dev/packages/package_info_plus) | 3.1.2 | 4.0.2 | Достать `version` & `build_number` не удалось |
+| [path_provider](https://pub.dev/packages/path_provider) | 2.0.15 | 4.0.2 | - |
+| [shared_preferences](https://pub.dev/packages/shared_preferences) | 2.1.2 | 4.0.2 | - |
+| [sqflite](https://pub.dev/packages/sqflite) | 2.2.6 | 4.0.2 | - |
+| [wakelock](https://pub.dev/packages/wakelock) | 0.6.2 | 4.0.2 | - |
+| xdga_directories | 0.0.1 | 4.0.2 | Аналог [xdg_directories](https://pub.dev/packages/xdg_directories) |
+| [flutter_cache_manager](https://pub.dev/packages/flutter_cache_manager) | 3.3.0 | 4.0.2 | Depends on `path_provider` |
+| [cached_network_image](https://pub.dev/packages/cached_network_image) | 3.2.3 | 4.0.2 | Depends on `flutter_cache_manager` |
+| [crypto](https://pub.dev/packages/crypto) | 3.0.2 | 4.0.2 | - |
+| [cupertino_icons](https://pub.dev/packages/cupertino_icons) | 1.0.5 | 4.0.2 | - |
+| [get_it](https://pub.dev/packages/get_it) | 7.6.0 | 4.0.2 | - |
+| [google_fonts](https://pub.dev/packages/google_fonts) | 4.0.4 | 4.0.2 | - |
+| [intl](https://pub.dev/packages/intl) | 0.17.0 | 4.0.2 | - |
+| [photo_view](https://pub.dev/packages/photo_view) | 0.14.0 | 4.0.2 | - |
+| [scoped_model](https://pub.dev/packages/scoped_model) | 2.0.0 | 4.0.2 | - |
+| [dartz](https://pub.dev/packages/dartz) | 0.10.1 | 4.0.2 | - |
+| [freezed](https://pub.dev/packages/freezed) | 2.3.3 | 4.0.2 | - |
+| [equatable](https://pub.dev/packages/equatable) | 2.0.5 | 4.0.2 | - |
+| [flutter_markdown](https://pub.dev/packages/flutter_markdown) | 0.6.15 | 4.0.2 | - |
+| [build_runner](https://pub.dev/packages/build_runner) | 2.3.3 | 4.0.2 | - |
+| [freezed_annotation](https://pub.dev/packages/freezed_annotation) | 2.2.0 | 4.0.2 | - |
+| [json_annotation](https://pub.dev/packages/json_annotation) | 4.8.0 | 4.0.2 | - |
+| [json_serializable](https://pub.dev/packages/json_serializable) | 6.6.1 | 4.0.2 | - |
+| [provider](https://pub.dev/packages/provider) | 6.0.5 | 4.0.2 | - |
+| [qr_flutter](https://pub.dev/packages/qr_flutter) | 4.0.0 | 4.0.2 | - |
+| [rxdart](https://pub.dev/packages/rxdart) | 0.27.7 | 4.0.2 | - |
+| [translator](https://pub.dev/packages/translator) | 0.1.7 | 4.0.2 | - |
## Package in progress
@@ -39,7 +52,6 @@ Started development and its status
| [url_launcher](https://pub.dev/packages/url_launcher) | 6.1.11 | 5.0.0 | Waiting | [OpenURI](https://confluence.omprussia.ru/pages/viewpage.action?pageId=163055648) |
| [sensors_plus](https://pub.dev/packages/sensors_plus) | 3.0.2 | 4.0.2 | Blocked | Нет интерфейса для использования Sensors API без Qt |
-
## Package waiting
Packets waiting in line
diff --git a/packages/device_info_plus/device_info_plus_aurora/example/.gitignore b/example/.gitignore
similarity index 94%
rename from packages/device_info_plus/device_info_plus_aurora/example/.gitignore
rename to example/.gitignore
index 3db3823..bf6a5bc 100644
--- a/packages/device_info_plus/device_info_plus_aurora/example/.gitignore
+++ b/example/.gitignore
@@ -45,3 +45,7 @@ app.*.map.json
# Aurora generated
/aurora/flutter
+
+# Dart generated
+*.g.dart
+*.freezed.dart
diff --git a/example/.metadata b/example/.metadata
new file mode 100644
index 0000000..8a5abeb
--- /dev/null
+++ b/example/.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.
+
+version:
+ revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ channel: aurora
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ - platform: aurora
+ create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+
+ # 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/example/README.md b/example/README.md
new file mode 100644
index 0000000..09bcd04
--- /dev/null
+++ b/example/README.md
@@ -0,0 +1,19 @@
+# Flutter example packages
+
+Demonstrating the operation of Flutter plugins on the Aurora OS.
+
+## Getting Started
+
+```shell
+# Add an alias if it doesn't already exist
+alias flutter-aurora=$HOME/.local/opt/flutter/bin/flutter
+
+# Get dependencies
+flutter-aurora pub get
+
+# Generate internationalizing
+flutter-aurora pub run build_runner build
+
+# Run build
+flutter-aurora build aurora --release # [--release|--debug|--profile]
+```
diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml
new file mode 100644
index 0000000..f9b3034
--- /dev/null
+++ b/example/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:flutter_lints/flutter.yaml
diff --git a/example/android/.gitignore b/example/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/example/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/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle
new file mode 100644
index 0000000..2162396
--- /dev/null
+++ b/example/android/app/build.gradle
@@ -0,0 +1,66 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion getProperty('flutter.compileSdkVersion').toInteger()
+ ndkVersion flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ applicationId "ru.auroraos.flutter_example_packages"
+ minSdkVersion getProperty('flutter.minSdkVersion').toInteger()
+ targetSdkVersion getProperty('flutter.targetSdkVersion').toInteger()
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..22f758d
--- /dev/null
+++ b/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..5be26d7
--- /dev/null
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/kotlin/ru/auroraos/flutter_example_packages/MainActivity.kt b/example/android/app/src/main/kotlin/ru/auroraos/flutter_example_packages/MainActivity.kt
new file mode 100644
index 0000000..619a0b7
--- /dev/null
+++ b/example/android/app/src/main/kotlin/ru/auroraos/flutter_example_packages/MainActivity.kt
@@ -0,0 +1,6 @@
+package ru.auroraos.flutter_example_packages
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/drawable/icon_splash.png b/example/android/app/src/main/res/drawable/icon_splash.png
new file mode 100644
index 0000000..ad245a5
Binary files /dev/null and b/example/android/app/src/main/res/drawable/icon_splash.png differ
diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/drawable/splash.xml b/example/android/app/src/main/res/drawable/splash.xml
new file mode 100644
index 0000000..7be22f0
--- /dev/null
+++ b/example/android/app/src/main/res/drawable/splash.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cc636aa
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dc8a840
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..d32963c
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..334a373
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..dc2e2a1
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..c6a675c
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..ddbe6c1
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..fe0d529
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..6f0c8ab
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..efa2172
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/example/android/app/src/main/res/values-night/colors.xml b/example/android/app/src/main/res/values-night/colors.xml
new file mode 100644
index 0000000..b610850
--- /dev/null
+++ b/example/android/app/src/main/res/values-night/colors.xml
@@ -0,0 +1,4 @@
+
+
+ #000000
+
diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..b81264e
--- /dev/null
+++ b/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/values/colors.xml b/example/android/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..5a0d831
--- /dev/null
+++ b/example/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,4 @@
+
+
+ #ffffff
+
diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..7039d5b
--- /dev/null
+++ b/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..22f758d
--- /dev/null
+++ b/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/example/android/build.gradle b/example/android/build.gradle
new file mode 100644
index 0000000..cf4feca
--- /dev/null
+++ b/example/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+ ext.kotlin_version = '1.8.22'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:7.1.3'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/example/android/gradle.properties b/example/android/gradle.properties
new file mode 100644
index 0000000..7c1c752
--- /dev/null
+++ b/example/android/gradle.properties
@@ -0,0 +1,6 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
+flutter.minSdkVersion=19
+flutter.targetSdkVersion=33
+flutter.compileSdkVersion=33
\ No newline at end of file
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cb24abd
--- /dev/null
+++ b/example/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-7.4-all.zip
diff --git a/example/android/settings.gradle b/example/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/example/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/example/assets/images/large_image.jpg b/example/assets/images/large_image.jpg
new file mode 100644
index 0000000..f49af2f
Binary files /dev/null and b/example/assets/images/large_image.jpg differ
diff --git a/example/assets/images/leading.png b/example/assets/images/leading.png
new file mode 100644
index 0000000..654a57a
Binary files /dev/null and b/example/assets/images/leading.png differ
diff --git a/example/assets/images/logo-head.png b/example/assets/images/logo-head.png
new file mode 100644
index 0000000..93bed9f
Binary files /dev/null and b/example/assets/images/logo-head.png differ
diff --git a/packages/battery_plus/battery_plus_aurora/example/aurora/.gitignore b/example/aurora/.gitignore
similarity index 100%
rename from packages/battery_plus/battery_plus_aurora/example/aurora/.gitignore
rename to example/aurora/.gitignore
diff --git a/packages/wakelock/wakelock_aurora/example/aurora/CMakeLists.txt b/example/aurora/CMakeLists.txt
similarity index 97%
rename from packages/wakelock/wakelock_aurora/example/aurora/CMakeLists.txt
rename to example/aurora/CMakeLists.txt
index 4029b94..be3adf9 100644
--- a/packages/wakelock/wakelock_aurora/example/aurora/CMakeLists.txt
+++ b/example/aurora/CMakeLists.txt
@@ -2,7 +2,7 @@
# License: Proprietary.
cmake_minimum_required(VERSION 3.10)
-project(com.example.wakelock_aurora_example LANGUAGES CXX)
+project(ru.auroraos.flutter_example_packages LANGUAGES CXX)
include(GNUInstallDirs)
diff --git a/example/aurora/desktop/ru.auroraos.flutter_example_packages.desktop b/example/aurora/desktop/ru.auroraos.flutter_example_packages.desktop
new file mode 100644
index 0000000..385dfe0
--- /dev/null
+++ b/example/aurora/desktop/ru.auroraos.flutter_example_packages.desktop
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Type=Application
+Name=Flutter example packages
+Comment=Examples of the flutter plugins for Aurora OS.
+Icon=ru.auroraos.flutter_example_packages
+Exec=/usr/bin/ru.auroraos.flutter_example_packages
+X-Nemo-Application-Type=silica-qt5
+
+[X-Application]
+Permissions=DeviceInfo,UserDirs
+OrganizationName=ru.auroraos
+ApplicationName=flutter_example_packages
diff --git a/example/aurora/icons/108x108.png b/example/aurora/icons/108x108.png
new file mode 100644
index 0000000..a0b871d
Binary files /dev/null and b/example/aurora/icons/108x108.png differ
diff --git a/example/aurora/icons/128x128.png b/example/aurora/icons/128x128.png
new file mode 100644
index 0000000..5a4abc7
Binary files /dev/null and b/example/aurora/icons/128x128.png differ
diff --git a/example/aurora/icons/172x172.png b/example/aurora/icons/172x172.png
new file mode 100644
index 0000000..2979270
Binary files /dev/null and b/example/aurora/icons/172x172.png differ
diff --git a/example/aurora/icons/86x86.png b/example/aurora/icons/86x86.png
new file mode 100644
index 0000000..b4e9f1f
Binary files /dev/null and b/example/aurora/icons/86x86.png differ
diff --git a/packages/battery_plus/battery_plus_aurora/example/aurora/main.cpp b/example/aurora/main.cpp
similarity index 100%
rename from packages/battery_plus/battery_plus_aurora/example/aurora/main.cpp
rename to example/aurora/main.cpp
diff --git a/packages/sqflite/sqflite_aurora/example/aurora/rpm/com.example.sqflite_aurora_example.spec b/example/aurora/rpm/ru.auroraos.flutter_example_packages.spec
similarity index 86%
rename from packages/sqflite/sqflite_aurora/example/aurora/rpm/com.example.sqflite_aurora_example.spec
rename to example/aurora/rpm/ru.auroraos.flutter_example_packages.spec
index 5c0b8ae..2c965f8 100644
--- a/packages/sqflite/sqflite_aurora/example/aurora/rpm/com.example.sqflite_aurora_example.spec
+++ b/example/aurora/rpm/ru.auroraos.flutter_example_packages.spec
@@ -1,8 +1,8 @@
%global __provides_exclude_from ^%{_datadir}/%{name}/lib/.*$
%global __requires_exclude ^lib(dconf|flutter-embedder|maliit-glib|appmanifest-.+|.+_platform_plugin)\\.so.*$
-Name: com.example.sqflite_aurora_example
-Summary: Demonstrates how to use the sqflite_aurora plugin.
+Name: ru.auroraos.flutter_example_packages
+Summary: Examples of the flutter plugins for Aurora OS.
Version: 0.1.0
Release: 1
License: Proprietary
diff --git a/example/data/raw/flutter.svg b/example/data/raw/flutter.svg
new file mode 100644
index 0000000..30c3a1e
--- /dev/null
+++ b/example/data/raw/flutter.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/example/data/raw/gingerbread-man-christmas-treat-candy-cartoon.svg b/example/data/raw/gingerbread-man-christmas-treat-candy-cartoon.svg
new file mode 100644
index 0000000..a14f383
--- /dev/null
+++ b/example/data/raw/gingerbread-man-christmas-treat-candy-cartoon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/example/data/raw/icon.png b/example/data/raw/icon.png
new file mode 100644
index 0000000..cefa8bf
Binary files /dev/null and b/example/data/raw/icon.png differ
diff --git a/example/data/raw/icon.xcf b/example/data/raw/icon.xcf
new file mode 100644
index 0000000..4151ebe
Binary files /dev/null and b/example/data/raw/icon.xcf differ
diff --git a/example/data/raw/icon2.png b/example/data/raw/icon2.png
new file mode 100644
index 0000000..0282c35
Binary files /dev/null and b/example/data/raw/icon2.png differ
diff --git a/example/data/raw/links b/example/data/raw/links
new file mode 100644
index 0000000..6c111aa
--- /dev/null
+++ b/example/data/raw/links
@@ -0,0 +1,3 @@
+https://iconduck.com/icons/94312/flutter
+https://iconduck.com/icons/54169/package
+https://iconduck.com/illustrations/108225/gingerbread-man-christmas-treat-candy-cartoon
diff --git a/example/data/raw/logo-head.svg b/example/data/raw/logo-head.svg
new file mode 100644
index 0000000..ee98409
--- /dev/null
+++ b/example/data/raw/logo-head.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/example/data/raw/package.svg b/example/data/raw/package.svg
new file mode 100644
index 0000000..3626988
--- /dev/null
+++ b/example/data/raw/package.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/example/l10n.yaml b/example/l10n.yaml
new file mode 100644
index 0000000..15338f2
--- /dev/null
+++ b/example/l10n.yaml
@@ -0,0 +1,3 @@
+arb-dir: lib/l10n
+template-arb-file: app_en.arb
+output-localization-file: app_localizations.dart
diff --git a/example/lib/app.dart b/example/lib/app.dart
new file mode 100644
index 0000000..180e1bb
--- /dev/null
+++ b/example/lib/app.dart
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter/material.dart';
+import 'package:flutter_example_packages/base/package/package_page.dart';
+import 'package:flutter_example_packages/packages/packages.dart';
+import 'package:flutter_example_packages/pages/home/page.dart';
+import 'package:flutter_example_packages/theme/theme.dart';
+import 'package:flutter_example_packages/widgets/layouts/page_layout.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+
+/// Main app class
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final routes = {
+ '/': (context) => const HomePage(),
+ };
+ for (var item in packages) {
+ if (item is PackagePage) {
+ routes['/${item.key}'] = (context) => PageLayout(
+ child: item.page.call(),
+ );
+ }
+ }
+
+ return MaterialApp(
+ localizationsDelegates: AppLocalizations.localizationsDelegates,
+ supportedLocales: AppLocalizations.supportedLocales,
+ debugShowCheckedModeBanner: false,
+ theme: appTheme,
+ initialRoute: '/',
+ routes: routes,
+ );
+ }
+}
diff --git a/example/lib/base/build/build.config.dart b/example/lib/base/build/build.config.dart
new file mode 100644
index 0000000..7a72998
--- /dev/null
+++ b/example/lib/base/build/build.config.dart
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+abstract class BuildConfig {
+ bool get isDebug;
+}
diff --git a/example/lib/base/build/build.debug.dart b/example/lib/base/build/build.debug.dart
new file mode 100644
index 0000000..0efafcf
--- /dev/null
+++ b/example/lib/base/build/build.debug.dart
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'build.config.dart';
+
+class BuildDebugConfig implements BuildConfig {
+ @override
+ bool get isDebug => true;
+}
diff --git a/example/lib/base/build/build.release.dart b/example/lib/base/build/build.release.dart
new file mode 100644
index 0000000..c5cd3aa
--- /dev/null
+++ b/example/lib/base/build/build.release.dart
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'build.config.dart';
+
+class BuildReleaseConfig implements BuildConfig {
+ @override
+ bool get isDebug => false;
+}
diff --git a/example/lib/base/di/app_di.dart b/example/lib/base/di/app_di.dart
new file mode 100644
index 0000000..eacc605
--- /dev/null
+++ b/example/lib/base/di/app_di.dart
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter_example_packages/base/build/build.config.dart';
+import 'package:flutter_example_packages/pages/home/model.dart';
+import 'package:get_it/get_it.dart';
+
+final getIt = GetIt.instance;
+
+/// Initialization application DI
+void setupDI(BuildConfig config) {
+ getIt
+ ..registerSingleton(config)
+ ..registerFactory(() => HomeModel());
+}
diff --git a/example/lib/base/package/package.dart b/example/lib/base/package/package.dart
new file mode 100644
index 0000000..0908cdd
--- /dev/null
+++ b/example/lib/base/package/package.dart
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:universal_io/io.dart';
+
+class Package {
+ Package({
+ required this.key,
+ required this.descEN,
+ required this.descRU,
+ required this.version,
+ required this.isPlatformDependent,
+ });
+
+ /// Get brief description of the package
+ String get desc => (Platform.localeName == 'ru_RU' ? descRU : descEN)
+ .replaceAll("\n", " ")
+ .replaceAll(RegExp(' +'), ' ')
+ .trim();
+
+ /// Key package (https://pub.dev/packages/)
+ final String key;
+
+ /// Brief description of the package (EN)
+ final String descEN;
+
+ /// Brief description of the package (RU)
+ final String descRU;
+
+ /// Version package check
+ final String version;
+
+ /// Is the package platform dependent?
+ final bool isPlatformDependent;
+}
diff --git a/example/lib/base/package/package_dialog.dart b/example/lib/base/package/package_dialog.dart
new file mode 100644
index 0000000..3d6b6e6
--- /dev/null
+++ b/example/lib/base/package/package_dialog.dart
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter_example_packages/base/package/package.dart';
+import 'package:universal_io/io.dart';
+
+class PackageDialog extends Package {
+ PackageDialog({
+ required super.key,
+ required super.descEN,
+ required super.descRU,
+ required super.version,
+ required super.isPlatformDependent,
+ required this.messageEN,
+ required this.messageRU,
+ });
+
+ /// Get brief description of the package
+ String get message => (Platform.localeName == 'ru_RU' ? messageRU : messageEN)
+ .replaceAll("\n", " ")
+ .replaceAll(RegExp(' +'), ' ')
+ .trim();
+
+ /// Message show in dialog (EN)
+ final String messageEN;
+
+ /// Message show in dialog (RU)
+ final String messageRU;
+}
diff --git a/example/lib/base/package/package_page.dart b/example/lib/base/package/package_page.dart
new file mode 100644
index 0000000..d0a1c3c
--- /dev/null
+++ b/example/lib/base/package/package_page.dart
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter/material.dart';
+import 'package:flutter_example_packages/base/package/package.dart';
+
+class PackagePage extends Package {
+ PackagePage({
+ required super.key,
+ required super.descEN,
+ required super.descRU,
+ required super.version,
+ required super.isPlatformDependent,
+ required this.page,
+ required this.init,
+ }) {
+ init.call();
+ }
+
+ /// Package preview page
+ final Widget Function() page;
+
+ /// Init callback
+ final void Function() init;
+}
diff --git a/example/lib/extensions/keys_ext.dart b/example/lib/extensions/keys_ext.dart
new file mode 100644
index 0000000..ead4c20
--- /dev/null
+++ b/example/lib/extensions/keys_ext.dart
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter/material.dart';
+
+/// Extensions for [GlobalKey]
+extension ExtGlobalKey on GlobalKey {
+ /// Get height by key
+ double? getHeight() {
+ if (currentContext == null) {
+ return null;
+ }
+ try {
+ final renderBoxRed = currentContext!.findRenderObject() as RenderBox;
+ final sizeRed = renderBoxRed.size;
+ return sizeRed.height;
+ } catch (e) {
+ return 0;
+ }
+ }
+}
diff --git a/example/lib/l10n/app_en.arb b/example/lib/l10n/app_en.arb
new file mode 100644
index 0000000..2647a5f
--- /dev/null
+++ b/example/lib/l10n/app_en.arb
@@ -0,0 +1,226 @@
+{
+ "@_PROVIDER": {},
+ "providerTitle": "Provider",
+ "providerSubtitle": "Simple example use provider package",
+
+ "@_RXDART": {},
+ "rxdartTitle": "Rxdart",
+ "rxdartSubtitle": "Simple example using Rx for Dart",
+
+ "@_TRANSLATOR": {},
+ "translatorTitle": "Translate",
+ "translatorSubtitle": "Translate en -> ru 'Hello!'",
+ "translatorText": "Hello!",
+
+ "@_EQUATABLE": {},
+ "equatableTitleDefault": "It's default class, 46 of lines",
+ "equatableTitleFreezed": "It's equatable class, 26 of lines",
+ "equatableSubtitle": "Methods: toString, operator ==, hashCode.",
+
+ "@_FREEZED": {},
+ "freezedTitleDefault": "It's default class, 74 of lines",
+ "freezedTitleFreezed": "It's freezed class, 21 of lines",
+ "freezedSubtitle": "Methods: fromJson, copyWith, toJson, toString, operator ==, hashCode.",
+
+ "@_DARTZ": {},
+ "dartzTitle": "Convert size",
+ "dartzDesc": "Convert the size grid of Russia to the size grid of Europe.",
+ "dartzErrorReq": "Required field",
+ "dartzErrorInt": "Please enter RUS size (42 - 62)",
+ "dartzErrorFound": "Size not found (42 - 62)",
+ "dartzDefaultValue": "Specify the size and click 'Submit'",
+ "dartzLabel": "Size in RUS",
+ "dartzSubmit": "Submit",
+
+ "@_SQFLITE": {},
+ "sqfliteTitleState": "Database state",
+ "sqfliteTitleInsert": "Database insert",
+ "sqfliteTitleUpdate": "Database update by ID",
+ "sqfliteTitleDelete": "Database delete by ID",
+ "sqfliteTitleError": "ID not found",
+ "sqfliteTitleBtnClear": "Clear",
+ "sqfliteTitleBtnSubmit": "Submit",
+ "sqfliteTitleFieldID": "ID",
+ "sqfliteTitleFieldName": "Name (TEXT)",
+ "sqfliteTitleFieldValue": "Value (INTEGER)",
+ "sqfliteTitleFieldNum": "Num (REAL)",
+ "sqfliteTitleValidateRequired": "Required field",
+ "sqfliteTitleValidateType": "Please enter {type} value",
+ "@sqfliteTitleValidateType": {
+ "placeholders": {
+ "type": {
+ "type": "String",
+ "example": "int"
+ }
+ }
+ },
+
+ "@_BATTERY_PLUS": {},
+ "batteryPlusTitleBatteryLevel": "Battery Level",
+ "batteryPlusDescBatteryLevel": "Battery level in percent 0 - 100.",
+ "batteryPlusTitleBatteryState": "Battery State",
+ "batteryPlusDescBatteryState": "Battery state: full, charging, discharging, unknown.",
+ "batteryPlusTitleBatterySaveMode": "Save Mode",
+ "batteryPlusDescBatterySaveMode": "Check is enable 'Save Mode'.",
+ "batteryPlusTitleBatteryStateLive": "Battery State 'Live'",
+ "batteryPlusDescBatteryStateLive": "Battery change state stream.",
+
+ "@_FLUTTER_KEYBOARD_VISIBILITY": {},
+ "flutterKeyboardVisibilityTitle": "Keyboard",
+ "flutterKeyboardVisibilityDesc": "Stream state keyboard open/close",
+ "flutterKeyboardVisibilityTitleHeight": "Keyboard height",
+ "flutterKeyboardVisibilityDescHeight": "Stream state keyboard height",
+ "flutterKeyboardVisibilityField": "Click for focus",
+ "flutterKeyboardVisibilityButton": "Clear focus",
+
+ "@_DEVICE_INFO_PLUS": {},
+ "deviceInfoPlusTitleID": "ID",
+ "deviceInfoPlusDescID": "Device ID.",
+ "deviceInfoPlusTitleName": "Name",
+ "deviceInfoPlusDescName": "Device name.",
+ "deviceInfoPlusTitleVersion": "Version OS",
+ "deviceInfoPlusDescVersion": "Short OS version.",
+ "deviceInfoPlusTitlePrettyName": "Full Name",
+ "deviceInfoPlusDescPrettyName": "Pretty name OS.",
+ "deviceInfoPlusTitleGNSS": "GNSS",
+ "deviceInfoPlusDescGNSS": "Check is has GNSS.",
+ "deviceInfoPlusTitleNFC": "NFC",
+ "deviceInfoPlusDescNFC": "Check is has NFC.",
+ "deviceInfoPlusTitleBluetooth": "Bluetooth",
+ "deviceInfoPlusDescBluetooth": "Check is has bluetooth.",
+ "deviceInfoPlusTitleWlan": "WLAN",
+ "deviceInfoPlusDescWlan": "Check is has Wireless LAN.",
+ "deviceInfoPlusTitleMaxCpuClockSpeed": "CPU speed",
+ "deviceInfoPlusDescMaxCpuClockSpeed": "Max CPU clock speed.",
+ "deviceInfoPlusTitleNumberCpuCores": "CPU cores",
+ "deviceInfoPlusDescNumberCpuCores": "Number CPU cores.",
+ "deviceInfoPlusTitleBatteryCharge": "Battery charge",
+ "deviceInfoPlusDescBatteryCharge": "Battery level in percent 0-100.",
+ "deviceInfoPlusTitleMainCameraResolution": "Main camera",
+ "deviceInfoPlusDescMainCameraResolution": "Main camera resolution.",
+ "deviceInfoPlusTitleFrontalCameraResolution": "Frontal camera",
+ "deviceInfoPlusDescFrontalCameraResolution": "Frontal camera resolution.",
+ "deviceInfoPlusTitleRamTotalSize": "RAM total",
+ "deviceInfoPlusDescRamTotalSize": "RAM total size.",
+ "deviceInfoPlusTitleRamFreeSize": "RAM free",
+ "deviceInfoPlusDescRamFreeSize": "RAM free size.",
+ "deviceInfoPlusTitleScreenResolution": "Screen",
+ "deviceInfoPlusDescScreenResolution": "Screen resolution.",
+ "deviceInfoPlusTitleOsVersion": "Version OS",
+ "deviceInfoPlusDescOsVersion": "Full OS version.",
+ "deviceInfoPlusTitleDeviceModel": "Device",
+ "deviceInfoPlusDescDeviceModel": "Device name model.",
+
+ "@_FLUTTER_LOCAL_NOTIFICATIONS": {},
+ "flutterLocalNotificationsHintTitle": "Notification title",
+ "flutterLocalNotificationsHintBody": "Notification body",
+ "flutterLocalNotificationsBtn": "Send",
+
+ "@_FLUTTER_SECURE_STORAGE": {},
+ "flutterSecureStorageSuccess": "Data saved successfully",
+ "flutterSecureStorageTitleSave": "Save value",
+ "flutterSecureStorageTitleGet": "Get value",
+ "flutterSecureStorageFieldPass": "Password",
+ "flutterSecureStorageFieldKey": "Key",
+ "flutterSecureStorageFieldValue": "Value",
+ "flutterSecureStorageBtnSave": "Save value",
+ "flutterSecureStorageBtnGet": "Get value",
+
+ "@_PACKAGE_INFO_PLUS": {},
+ "packageInfoPlusTitlePackageName": "Package",
+ "packageInfoPlusDescPackageName": "Package name.",
+ "packageInfoPlusTitleApplicationName": "Name",
+ "packageInfoPlusDescApplicationName": "Application name.",
+
+ "@_PATH_PROVIDER": {},
+ "pathProviderTitleApplicationSupport": "Application Support",
+ "pathProviderDescApplicationSupport": "Directory where the application may place application support files.",
+ "pathProviderTitleTemporary": "Temporary",
+ "pathProviderDescTemporary": "Directory location where user-specific non-essential (cached) data should be written.",
+ "pathProviderTitleApplicationDocuments": "Documents",
+ "pathProviderDescApplicationDocuments": "Directory containing user document files.",
+ "pathProviderTitleDownloads": "Download",
+ "pathProviderDescDownloads": "Directory for user's downloaded files.",
+ "pathProviderTitlePictures": "Pictures",
+ "pathProviderDescPictures": "There is no concept of External in Aurora OS, but this interface allows you to get the StorageDirectory.pictures directory.",
+ "pathProviderTitleMusic": "Music",
+ "pathProviderDescMusic": "There is no concept of External in Aurora OS, but this interface allows you to get the StorageDirectory.music directory.",
+ "pathProviderTitleMovies": "Movies",
+ "pathProviderDescMovies": "There is no concept of External in Aurora OS, but this interface allows you to get the StorageDirectory.movies directory.",
+
+ "@_SHARED_PREFERENCES": {},
+ "sharedPreferencesTitleState": "State",
+ "sharedPreferencesTitleUpdate": "Update",
+ "sharedPreferencesFieldInt": "Int",
+ "sharedPreferencesFieldBool": "Bool",
+ "sharedPreferencesFieldDouble": "Double",
+ "sharedPreferencesFieldString": "String",
+ "sharedPreferencesFieldList": "List",
+ "sharedPreferencesFieldBtnClean": "Clean",
+ "sharedPreferencesFieldBtn": "Save",
+ "sharedPreferencesFieldError": "Please enter {value} value",
+ "@sharedPreferencesFieldError": {
+ "placeholders": {
+ "value": {
+ "type": "String",
+ "example": "int"
+ }
+ }
+ },
+
+ "@_WAKELOCK": {},
+ "wakelockTitle": "Wakelock",
+ "wakelockDesc": "The plugin allows you to enable and toggle the screen wakelock, which prevents the screen from turning off automatically.",
+
+ "@_XDGA_DIRECTORIES": {},
+ "xdgaDirectoriesTitleCacheLocation": "App Data Location",
+ "xdgaDirectoriesDescCacheLocation": "Directory location where persistent application data can be stored.",
+ "xdgaDirectoriesTitleAppDataLocation": "Cache Location",
+ "xdgaDirectoriesDescAppDataLocation": "Directory location where user-specific non-essential (cached) data should be written.",
+ "xdgaDirectoriesTitleDocumentsLocation": "Documents Location",
+ "xdgaDirectoriesDescDocumentsLocation": "Directory containing user document files.",
+ "xdgaDirectoriesTitleDownloadLocation": "Download Location",
+ "xdgaDirectoriesDescDownloadLocation": "Directory for user's downloaded files.",
+ "xdgaDirectoriesTitleMusicLocation": "Music Location",
+ "xdgaDirectoriesDescMusicLocation": "Directory containing the user's music or other audio files.",
+ "xdgaDirectoriesTitlePicturesLocation": "Pictures Location",
+ "xdgaDirectoriesDescPicturesLocation": "Directory containing the user's pictures or photos.",
+ "xdgaDirectoriesTitleGenericDataLocation": "Generic Data Location",
+ "xdgaDirectoriesDescGenericDataLocation": "Directory location where persistent data shared across applications can be stored.",
+ "xdgaDirectoriesTitleMoviesLocation": "Movies Location",
+ "xdgaDirectoriesDescMoviesLocation": "Directory containing the user's movies and videos.",
+
+ "@_COMMON": {},
+ "commonClose": "Close",
+ "commonEmptyValue": "Empty",
+ "commonLoading": "Loading...",
+
+ "@_HOME_SCREEN": {},
+ "homePageTitle": "Flutter Aurora OS",
+ "homeWelcomeTitle": "Welcome!",
+ "homeWelcomeText": "In this application you can find {count} Flutter plugins supporting Aurora OS. If it happens that something is missing for you, you can write to us or add it yourself.",
+ "@homeWelcomeText": {
+ "placeholders": {
+ "count": {
+ "type": "int",
+ "example": "0"
+ }
+ }
+ },
+ "homeListStateDependent": "platform dependent",
+ "homeListStateIndependent": "platform independent",
+ "homeListVersion": "Version: {version}",
+ "@homeListVersion": {
+ "placeholders": {
+ "version": {
+ "type": "String",
+ "example": "1.0.0"
+ }
+ }
+ },
+ "homeSearchTitle": "Search...",
+ "homeSearch": "Search packages",
+ "homeFilter": "Filter",
+ "homeNotFoundTitle": "Not found",
+ "homeNotFoundSubtitle": "What you were looking for is not in the list of verified plugins, but this does not mean that it will not work, check it out and you may want to add it to this list of verified plugins."
+}
diff --git a/example/lib/l10n/app_ru.arb b/example/lib/l10n/app_ru.arb
new file mode 100644
index 0000000..b8bd5e4
--- /dev/null
+++ b/example/lib/l10n/app_ru.arb
@@ -0,0 +1,218 @@
+{
+ "@_PROVIDER": {},
+ "providerTitle": "Provider",
+ "providerSubtitle": "Простой пример использования пакета provider",
+
+ "@_RXDART": {},
+ "rxdartTitle": "Rxdart",
+ "rxdartSubtitle": "Простой пример использования Rx для Dart",
+
+ "@_TRANSLATOR": {},
+ "translatorTitle": "Переводчик",
+ "translatorSubtitle": "Перевод en -> ru 'Hello!'",
+ "translatorText": "Hello!",
+
+ "@_EQUATABLE": {},
+ "equatableTitleDefault": "Класс по умолчанию, 46 строки",
+ "equatableTitleFreezed": "Класс c freezed, 26 строк",
+ "equatableSubtitle": "Методы: toString, operator ==, hashCode.",
+
+ "@_FREEZED": {},
+ "freezedTitleDefault": "Класс по умолчанию, 74 строки",
+ "freezedTitleFreezed": "Класс c freezed, 21 строка",
+ "freezedSubtitle": "Методы: fromJson, copyWith, toJson, toString, operator ==, hashCode.",
+
+ "@_DARTZ": {},
+ "dartzTitle": "Преобразовать размер",
+ "dartzDesc": "Преобразовать размерную сетку России в размерную сетку Европы.",
+ "dartzErrorReq": "Обязательное поле",
+ "dartzErrorInt": "Введите размер RUS (42–62)",
+ "dartzErrorFound": "Размер не найден (42–62)",
+ "dartzDefaultValue": "Укажите размер и нажмите 'Отправить'",
+ "dartzLabel": "Размер в RUS",
+ "dartzSubmit": "Отправить",
+
+ "@_SQFLITE": {},
+ "sqfliteTitleState": "Состояние базы данных",
+ "sqfliteTitleInsert": "Вставка в базу данных",
+ "sqfliteTitleUpdate": "Обновление базы данных по ID",
+ "sqfliteTitleDelete": "Удаление базы данных по ID",
+ "sqfliteTitleError": "ID не найден",
+ "sqfliteTitleBtnClear": "Очистить",
+ "sqfliteTitleBtnSubmit": "Отправить",
+ "sqfliteTitleFieldID": "Идентификатор",
+ "sqfliteTitleFieldName": "Имя (TEXT)",
+ "sqfliteTitleFieldValue": "Значение (INTEGER)",
+ "sqfliteTitleFieldNum": "Число (REAL)",
+ "sqfliteTitleValidateRequired": "Обязательное поле",
+ "sqfliteTitleValidateType": "Введите значение {type}",
+ "@sqfliteTitleValidateType": {
+ "placeholders": {
+ "type": {
+ "type": "String",
+ "example": "int"
+ }
+ }
+ },
+
+ "@_BATTERY_PLUS": {},
+ "batteryPlusTitleBatteryLevel": "Уровень заряда батареи",
+ "batteryPlusDescBatteryLevel": "Уровень заряда батареи в процентах от 0 до 100.",
+ "batteryPlusTitleBatteryState": "Состояние батареи",
+ "batteryPlusDescBatteryState": "Состояния: full, charging, discharging, unknown.",
+ "batteryPlusTitleBatterySaveMode": "Save Mode",
+ "batteryPlusDescBatterySaveMode": "Проверка включен ли режим 'Save Mode'.",
+ "batteryPlusTitleBatteryStateLive": "Состояние батареи 'Live'",
+ "batteryPlusDescBatteryStateLive": "Изменение состояния батареи.",
+
+ "@_FLUTTER_KEYBOARD_VISIBILITY": {},
+ "flutterKeyboardVisibilityTitle": "Клавиатура",
+ "flutterKeyboardVisibilityDesc": "Сигнал при изменении состояния клавиатуры открыта/закрыта",
+ "flutterKeyboardVisibilityTitleHeight": "Высота клавиатуры",
+ "flutterKeyboardVisibilityDescHeight": "Сигнал при изменении высоты клавиатуры",
+ "flutterKeyboardVisibilityField": "Нажмите, чтобы сфокусироваться",
+ "flutterKeyboardVisibilityButton": "Снять фокус",
+
+ "@_DEVICE_INFO_PLUS": {},
+ "deviceInfoPlusTitleID": "ID",
+ "deviceInfoPlusDescID": "Идентификатор устройства.",
+ "deviceInfoPlusTitleName": "Имя",
+ "deviceInfoPlusDescName": "Имя устройства.",
+ "deviceInfoPlusTitleVersion": "Версия ОС",
+ "deviceInfoPlusDescVersion": "Короткое название версии ОС.",
+ "deviceInfoPlusTitlePrettyName": "Полное имя",
+ "deviceInfoPlusDescPrettyName": "Красивое имя ОС.",
+ "deviceInfoPlusTitleGNSS": "GNSS",
+ "deviceInfoPlusDescGNSS": "Проверить наличие GNSS.",
+ "deviceInfoPlusTitleNFC": "NFC",
+ "deviceInfoPlusDescNFC": "Проверить, есть ли NFC.",
+ "deviceInfoPlusTitleBluetooth": "Bluetooth",
+ "deviceInfoPlusDescBluetooth": "Проверьте, есть ли Bluetooth.",
+ "deviceInfoPlusTitleWlan": "WLAN",
+ "deviceInfoPlusDescWlan": "Проверьте, есть ли Wireless LAN.",
+ "deviceInfoPlusTitleMaxCpuClockSpeed": "Частота процессора",
+ "deviceInfoPlusDescMaxCpuClockSpeed": "Максимальная тактовая частота процессора.",
+ "deviceInfoPlusTitleNumberCpuCores": "Ядра ЦП",
+ "deviceInfoPlusDescNumberCpuCores": "Количество ядер ЦП.",
+ "deviceInfoPlusTitleBatteryCharge": "Заряд батареи",
+ "deviceInfoPlusDescBatteryCharge": "Уровень заряда батареи в процентах от 0 до 100.",
+ "deviceInfoPlusTitleMainCameraResolution": "Основная камера",
+ "deviceInfoPlusDescMainCameraResolution": "Разрешение основной камеры.",
+ "deviceInfoPlusTitleFrontalCameraResolution": "Фронтальная камера",
+ "deviceInfoPlusDescFrontalCameraResolution": "Разрешение фронтальной камеры.",
+ "deviceInfoPlusTitleRamTotalSize": "Всего ОЗУ",
+ "deviceInfoPlusDescRamTotalSize": "Общий размер ОЗУ.",
+ "deviceInfoPlusTitleRamFreeSize": "Свободно ОЗУ",
+ "deviceInfoPlusDescRamFreeSize": "Свободный размер ОЗУ.",
+ "deviceInfoPlusTitleScreenResolution": "Экран",
+ "deviceInfoPlusDescScreenResolution": "Разрешение экрана.",
+ "deviceInfoPlusTitleOsVersion": "Версия ОС",
+ "deviceInfoPlusDescOsVersion": "Полное название версия ОС.",
+ "deviceInfoPlusTitleDeviceModel": "Устройство",
+ "deviceInfoPlusDescDeviceModel": "Имя модели устройства.",
+
+ "@_FLUTTER_LOCAL_NOTIFICATIONS": {},
+ "flutterLocalNotificationsHintTitle": "Заголовок уведомления",
+ "flutterLocalNotificationsHintBody": "Текст уведомления",
+ "flutterLocalNotificationsBtn": "Отправить",
+
+ "@_FLUTTER_SECURE_STORAGE": {},
+ "flutterSecureStorageSuccess": "Данные успешно сохранены",
+ "flutterSecureStorageTitleSave": "Сохранить значение",
+ "flutterSecureStorageTitleGet": "Получить значение",
+ "flutterSecureStorageFieldPass": "Пароль",
+ "flutterSecureStorageFieldKey": "Ключ",
+ "flutterSecureStorageFieldValue": "Значение",
+ "flutterSecureStorageBtnSave": "Сохранить значение",
+ "flutterSecureStorageBtnGet": "Получить значение",
+
+ "@_PACKAGE_INFO_PLUS": {},
+ "packageInfoPlusTitlePackageName": "Пакет",
+ "packageInfoPlusDescPackageName": "Имя пакета.",
+ "packageInfoPlusTitleApplicationName": "Имя",
+ "packageInfoPlusDescApplicationName": "Имя приложения.",
+
+ "@_PATH_PROVIDER": {},
+ "pathProviderTitleApplicationSupport": "Поддержка приложений",
+ "pathProviderDescApplicationSupport": "Каталог, в котором приложение может размещать файлы поддержки приложений.",
+ "pathProviderTitleTemporary": "Временный",
+ "pathProviderDescTemporary": "Расположение каталога, куда должны быть записаны второстепенные (кешированные) данные пользователя.",
+ "pathProviderTitleApplicationDocuments": "Документы",
+ "pathProviderDescApplicationDocuments": "Каталог, содержащий файлы пользовательских документов.",
+ "pathProviderTitleDownloads": "Скачать",
+ "pathProviderDescDownloads": "Каталог для загруженных пользователем файлов.",
+ "pathProviderTitlePictures": "Изображения",
+ "pathProviderDescPictures": "В Aurora OS нет концепции External, но этот интерфейс позволяет получить каталог StorageDirectory.pictures.",
+ "pathProviderTitleMusic": "Музыка",
+ "pathProviderDescMusic": "В Aurora OS нет концепции External, но этот интерфейс позволяет получить каталог StorageDirectory.music.",
+ "pathProviderTitleMovies": "Фильмы",
+ "pathProviderDescMovies": "В Aurora OS нет концепции External, но этот интерфейс позволяет получить каталог StorageDirectory.movies.",
+
+ "@_SHARED_PREFERENCES": {},
+ "sharedPreferencesTitleState": "Состояние",
+ "sharedPreferencesTitleUpdate": "Обновить",
+ "sharedPreferencesFieldInt": "Int",
+ "sharedPreferencesFieldBool": "Bool",
+ "sharedPreferencesFieldDouble": "Double",
+ "sharedPreferencesFieldString": "String",
+ "sharedPreferencesFieldList": "Список",
+ "sharedPreferencesFieldBtnClean": "Очистить",
+ "sharedPreferencesFieldBtn": "Сохранить",
+ "sharedPreferencesFieldError": "Пожалуйста, введите {value} значение",
+
+ "@_WAKELOCK": {},
+ "wakelockTitle": "Wakelock",
+ "wakelockDesc": "Плагин позволяет включать и переключать блокировку экрана, которая предотвращает автоматическое выключение экрана.",
+
+ "@_XDGA_DIRECTORIES": {},
+ "xdgaDirectoriesTitleCacheLocation": "App Data Location",
+ "xdgaDirectoriesDescCacheLocation": "Расположение каталога, в котором могут храниться постоянные данные приложения.",
+ "xdgaDirectoriesTitleAppDataLocation": "Cache Location",
+ "xdgaDirectoriesDescAppDataLocation": "Расположение каталога, в котором должны быть записаны второстепенные (кэшированные) данные пользователя.",
+ "xdgaDirectoriesTitleDocumentsLocation": "Documents Location",
+ "xdgaDirectoriesDescDocumentsLocation": "Каталог, содержащий файлы документов пользователя.",
+ "xdgaDirectoriesTitleDownloadLocation": "Download Location",
+ "xdgaDirectoriesDescDownloadLocation": "Каталог для загруженных пользователем файлов.",
+ "xdgaDirectoriesTitleMusicLocation": "Music Location",
+ "xdgaDirectoriesDescMusicLocation": "Каталог, содержащий музыку пользователя или другие аудиофайлы.",
+ "xdgaDirectoriesTitlePicturesLocation": "Pictures Location",
+ "xdgaDirectoriesDescPicturesLocation": "Каталог, содержащий изображения или фотографии пользователя.",
+ "xdgaDirectoriesTitleGenericDataLocation": "Generic Data Location",
+ "xdgaDirectoriesDescGenericDataLocation": "Расположение каталога, в котором могут храниться постоянные данные, совместно используемые приложениями.",
+ "xdgaDirectoriesTitleMoviesLocation": "Movies Location",
+ "xdgaDirectoriesDescMoviesLocation": "Каталог, содержащий фильмы и видео пользователя.",
+
+ "@_COMMON": {},
+ "commonClose": "Закрыть",
+ "commonEmptyValue": "Пусто",
+ "commonLoading": "Загрузка...",
+
+ "@_HOME_SCREEN": {},
+ "homePageTitle": "Flutter ОС Аврора",
+ "homeWelcomeTitle": "Приветствую!",
+ "homeWelcomeText": "В этом приложении вы можете найти {count} плагинов Flutter, поддерживающих ОС Aurora. Если вдруг вам чего-то не хватает, вы можете написать нам или добавить самостоятельно.",
+ "@homeWelcomeText": {
+ "placeholders": {
+ "count": {
+ "type": "int",
+ "example": "0"
+ }
+ }
+ },
+ "homeListStateDependent": "платформо-зависимый",
+ "homeListStateIndependent": "платформонезависимый",
+ "homeListVersion": "Версия: {version}",
+ "@homeListVersion": {
+ "placeholders": {
+ "version": {
+ "type": "String",
+ "example": "1.0.0"
+ }
+ }
+ },
+ "homeSearchTitle": "Поиск...",
+ "homeSearch": "Поиск пакетов",
+ "homeNotFoundTitle": "Не найдено",
+ "homeNotFoundSubtitle": "То что вы искали нет в списке провереных плагинов, но это не означает что он работать не будет, проверьте его и возможно вы захотите добавить его в этот список проверенных плагинов.",
+ "homeFilter": "Фильтр"
+}
diff --git a/example/lib/main.dart b/example/lib/main.dart
new file mode 100644
index 0000000..41f13e7
--- /dev/null
+++ b/example/lib/main.dart
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter/material.dart';
+import 'package:flutter_example_packages/app.dart';
+import 'package:flutter_example_packages/base/build/build.release.dart';
+import 'package:flutter_example_packages/base/di/app_di.dart';
+
+void main() {
+ setupDI(BuildReleaseConfig());
+ runApp(const MyApp());
+}
diff --git a/example/lib/main.release.dart b/example/lib/main.release.dart
new file mode 100644
index 0000000..cf01643
--- /dev/null
+++ b/example/lib/main.release.dart
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter/material.dart';
+import 'package:flutter_example_packages/app.dart';
+import 'package:flutter_example_packages/base/build/build.debug.dart';
+import 'package:flutter_example_packages/base/di/app_di.dart';
+
+void main() {
+ setupDI(BuildDebugConfig());
+ runApp(const MyApp());
+}
diff --git a/example/lib/packages/battery_plus/model.dart b/example/lib/packages/battery_plus/model.dart
new file mode 100644
index 0000000..5817ee6
--- /dev/null
+++ b/example/lib/packages/battery_plus/model.dart
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter/widgets.dart';
+import 'package:scoped_model/scoped_model.dart';
+import 'package:battery_plus/battery_plus.dart';
+
+/// Model for [BatteryPlusPage]
+class BatteryPlusModel extends Model {
+ /// Get [ScopedModel]
+ static BatteryPlusModel of(BuildContext context) =>
+ ScopedModel.of(context);
+
+ final _battery = Battery();
+
+ /// Error
+ String? _error;
+
+ /// Public error
+ String? get error => _error;
+
+ /// Public is error
+ bool get isError => _error != null;
+
+ /// Get battery level in percent 0-100
+ Future getBatteryLevel() async {
+ try {
+ return await _battery.batteryLevel;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Get status
+ Future getBatteryState() async {
+ try {
+ return await _battery.batteryState;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Check is enable save mode
+ Future isInBatterySaveMode() async {
+ try {
+ return await _battery.isInBatterySaveMode;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Stream change state
+ Stream onBatteryStateChanged() async* {
+ try {
+ yield await _battery.batteryState;
+ await for (final state in _battery.onBatteryStateChanged) {
+ yield state;
+ }
+ } catch (e) {
+ _error = e.toString();
+ notifyListeners();
+ }
+ }
+}
diff --git a/example/lib/packages/battery_plus/package.dart b/example/lib/packages/battery_plus/package.dart
new file mode 100644
index 0000000..7b3c9e1
--- /dev/null
+++ b/example/lib/packages/battery_plus/package.dart
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter_example_packages/base/package/package_page.dart';
+import 'package:flutter_example_packages/packages/battery_plus/page.dart';
+import 'package:get_it/get_it.dart';
+
+import 'model.dart';
+
+/// Package values
+final packageBatteryPlus = PackagePage(
+ key: 'battery_plus',
+ descEN: '''
+ A Flutter plugin to access various information about the
+ battery of the device the app is running on.
+ ''',
+ descRU: '''
+ Плагин Flutter для доступа к различной информации о
+ аккумулятор устройства, на котором запущено приложение.
+ ''',
+ version: '4.0.1',
+ isPlatformDependent: true,
+ page: () => BatteryPlusPage(),
+ init: () {
+ GetIt.instance.registerFactory(() => BatteryPlusModel());
+ },
+);
diff --git a/example/lib/packages/battery_plus/page.dart b/example/lib/packages/battery_plus/page.dart
new file mode 100644
index 0000000..bcf08c4
--- /dev/null
+++ b/example/lib/packages/battery_plus/page.dart
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter/material.dart';
+import 'package:flutter_example_packages/base/di/app_di.dart';
+import 'package:flutter_example_packages/base/package/package.dart';
+import 'package:flutter_example_packages/packages/battery_plus/model.dart';
+import 'package:flutter_example_packages/packages/battery_plus/package.dart';
+import 'package:flutter_example_packages/widgets/base/export.dart';
+import 'package:flutter_example_packages/widgets/blocks/block_alert.dart';
+import 'package:flutter_example_packages/widgets/blocks/block_info_package.dart';
+import 'package:flutter_example_packages/widgets/blocks/block_item.dart';
+import 'package:flutter_example_packages/widgets/layouts/block_layout.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+
+class BatteryPlusPage extends AppStatefulWidget {
+ BatteryPlusPage({
+ super.key,
+ });
+
+ final Package package = packageBatteryPlus;
+
+ @override
+ State createState() => _BatteryPlusPageState();
+}
+
+class _BatteryPlusPageState extends AppState {
+ @override
+ Widget buildWide(
+ BuildContext context,
+ MediaQueryData media,
+ AppLocalizations l10n,
+ ) {
+ return BlockLayout(
+ model: getIt(),
+ title: widget.package.key,
+ builder: (context, child, model) {
+ return SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(20),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ BlockInfoPackage(widget.package),
+ BlockAlert(model.error),
+ if (!model.isError)
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ BlockItem(
+ title: l10n.batteryPlusTitleBatteryLevel,
+ desc: l10n.batteryPlusDescBatteryLevel,
+ future: model.getBatteryLevel(),
+ builder: (value) => '$value%',
+ ),
+ BlockItem(
+ title: l10n.batteryPlusTitleBatteryState,
+ desc: l10n.batteryPlusDescBatteryState,
+ future: model.getBatteryState(),
+ builder: (value) =>
+ value.toString().split('.').last.toUpperCase(),
+ ),
+ BlockItem(
+ title: l10n.batteryPlusTitleBatterySaveMode,
+ desc: l10n.batteryPlusDescBatterySaveMode,
+ future: model.isInBatterySaveMode(),
+ ),
+ BlockItem(
+ title: l10n.batteryPlusTitleBatteryStateLive,
+ desc: l10n.batteryPlusDescBatteryStateLive,
+ stream: model.onBatteryStateChanged(),
+ builder: (value) =>
+ value.toString().split('.').last.toUpperCase(),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/example/lib/packages/build_runner/package.dart b/example/lib/packages/build_runner/package.dart
new file mode 100644
index 0000000..942b083
--- /dev/null
+++ b/example/lib/packages/build_runner/package.dart
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter_example_packages/base/package/package_dialog.dart';
+
+/// Package values
+final packageBuildRunner = PackageDialog(
+ key: 'build_runner',
+ descEN: '''
+ The build_runner package provides a concrete way of generating files using
+ Dart code. Files are always generated directly on disk, and rebuilds
+ are incremental - inspired by tools such as Bazel.
+ ''',
+ descRU: '''
+ Пакет build_runner предоставляет конкретный способ создания файлов с
+ использованием кода Dart. Файлы всегда генерируются непосредственно на
+ диске и перестраиваются являются инкрементными — вдохновлены такими
+ инструментами, как Bazel.
+ ''',
+ messageEN: '''
+ This is a platform independent plugin used in this app, should work
+ for you too.
+ ''',
+ messageRU: '''
+ Это плагин независимый от платформы, используется в этом приложении,
+ должен работать и у вас.
+ ''',
+ version: '2.3.3',
+ isPlatformDependent: false,
+);
diff --git a/example/lib/packages/cached_network_image/model.dart b/example/lib/packages/cached_network_image/model.dart
new file mode 100644
index 0000000..1ee4487
--- /dev/null
+++ b/example/lib/packages/cached_network_image/model.dart
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter/widgets.dart';
+import 'package:scoped_model/scoped_model.dart';
+
+/// Model for [CachedNetworkImagePage]
+class CachedNetworkImageModel extends Model {
+ /// Get [ScopedModel]
+ static CachedNetworkImageModel of(BuildContext context) =>
+ ScopedModel.of(context);
+}
diff --git a/example/lib/packages/cached_network_image/package.dart b/example/lib/packages/cached_network_image/package.dart
new file mode 100644
index 0000000..cba869c
--- /dev/null
+++ b/example/lib/packages/cached_network_image/package.dart
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter_example_packages/base/package/package_page.dart';
+import 'package:flutter_example_packages/packages/cached_network_image/page.dart';
+import 'package:get_it/get_it.dart';
+
+import 'model.dart';
+
+/// Package values
+final packageCachedNetworkImage = PackagePage(
+ key: 'cached_network_image',
+ descEN: '''
+ A flutter library to show images from the internet
+ and keep them in the cache directory.
+ ''',
+ descRU: '''
+ Библиотека флаттера для отображения изображений из
+ Интернета и хранения их в каталоге кеша.
+ ''',
+ version: '3.2.3',
+ isPlatformDependent: true,
+ page: () => CachedNetworkImagePage(),
+ init: () {
+ GetIt.instance.registerFactory(
+ () => CachedNetworkImageModel());
+ },
+);
diff --git a/example/lib/packages/cached_network_image/page.dart b/example/lib/packages/cached_network_image/page.dart
new file mode 100644
index 0000000..0788492
--- /dev/null
+++ b/example/lib/packages/cached_network_image/page.dart
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:cached_network_image/cached_network_image.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_example_packages/base/di/app_di.dart';
+import 'package:flutter_example_packages/base/package/package.dart';
+import 'package:flutter_example_packages/packages/cached_network_image/model.dart';
+import 'package:flutter_example_packages/packages/cached_network_image/package.dart';
+import 'package:flutter_example_packages/widgets/base/export.dart';
+import 'package:flutter_example_packages/widgets/blocks/block_info_package.dart';
+import 'package:flutter_example_packages/widgets/layouts/block_layout.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+
+class CachedNetworkImagePage extends AppStatefulWidget {
+ CachedNetworkImagePage({
+ super.key,
+ });
+
+ final Package package = packageCachedNetworkImage;
+
+ @override
+ State createState() => _CachedNetworkImagePageState();
+}
+
+class _CachedNetworkImagePageState extends AppState {
+ @override
+ Widget buildWide(
+ BuildContext context,
+ MediaQueryData media,
+ AppLocalizations l10n,
+ ) {
+ return BlockLayout(
+ model: getIt(),
+ title: widget.package.key,
+ builder: (context, child, model) {
+ return SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(20),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ BlockInfoPackage(widget.package),
+ SizedBox(
+ width: double.infinity,
+ height: 150,
+ child: Center(
+ child: CachedNetworkImage(
+ imageUrl: "https://via.placeholder.com/350x150",
+ placeholder: (context, url) =>
+ const CircularProgressIndicator(),
+ errorWidget: (context, url, error) =>
+ const Icon(Icons.error),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/example/lib/packages/crypto/package.dart b/example/lib/packages/crypto/package.dart
new file mode 100644
index 0000000..fa019cb
--- /dev/null
+++ b/example/lib/packages/crypto/package.dart
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter_example_packages/base/package/package_dialog.dart';
+
+/// Package values
+final packageCrypto = PackageDialog(
+ key: 'crypto',
+ descEN: '''
+ A set of cryptographic hashing functions for Dart.
+ ''',
+ descRU: '''
+ Набор криптографических функций хеширования для Dart.
+ ''',
+ messageEN: '''
+ This is a platform independent plugin used in this app, should work
+ for you too.
+ ''',
+ messageRU: '''
+ Это плагин независимый от платформы, используется в этом приложении,
+ должен работать и у вас.
+ ''',
+ version: '3.0.2',
+ isPlatformDependent: false,
+);
diff --git a/example/lib/packages/cupertino_icons/package.dart b/example/lib/packages/cupertino_icons/package.dart
new file mode 100644
index 0000000..b154ccc
--- /dev/null
+++ b/example/lib/packages/cupertino_icons/package.dart
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter_example_packages/base/package/package_dialog.dart';
+
+/// Package values
+final packageCupertinoIcons = PackageDialog(
+ key: 'cupertino_icons',
+ descEN: '''
+ This is an asset repo containing the default set of icon assets
+ used by Flutter's Cupertino widgets.
+ ''',
+ descRU: '''
+ Это репозиторий ресурсов, содержащий набор ресурсов значков по умолчанию
+ используется виджетами Flutter Cupertino.
+ ''',
+ messageEN: '''
+ This is a platform independent plugin used in this app, should work
+ for you too.
+ ''',
+ messageRU: '''
+ Это плагин независимый от платформы, используется в этом приложении,
+ должен работать и у вас.
+ ''',
+ version: '1.0.5',
+ isPlatformDependent: false,
+);
diff --git a/example/lib/packages/dartz/model.dart b/example/lib/packages/dartz/model.dart
new file mode 100644
index 0000000..0174b47
--- /dev/null
+++ b/example/lib/packages/dartz/model.dart
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:dartz/dartz.dart';
+import 'package:flutter/widgets.dart';
+import 'package:scoped_model/scoped_model.dart';
+
+/// Model for [DartzPage]
+class DartzModel extends Model {
+ /// Get [ScopedModel]
+ static DartzModel of(BuildContext context) =>
+ ScopedModel.of(context);
+
+ /// Example using Option from package dartz
+ Option getEURManSize(int size) {
+ if (size < 42) return none();
+ if (size < 44) return some('XS');
+ if (size < 46) return some('S');
+ if (size < 48) return some('M');
+ if (size < 50) return some('L');
+ if (size < 54) return some('XL');
+ if (size < 56) return some('XXL');
+ if (size < 58) return some('XXXL');
+ if (size <= 62) return some('XXXXL');
+ return none();
+ }
+}
diff --git a/example/lib/packages/dartz/package.dart b/example/lib/packages/dartz/package.dart
new file mode 100644
index 0000000..214a2d9
--- /dev/null
+++ b/example/lib/packages/dartz/package.dart
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:flutter_example_packages/base/package/package_page.dart';
+import 'package:get_it/get_it.dart';
+
+import 'model.dart';
+import 'page.dart';
+
+/// Package values
+final packageDartz = PackagePage(
+ key: 'dartz',
+ descEN: '''
+ Functional programming in Dart.
+ ''',
+ descRU: '''
+ Функциональное программирование в Dart.
+ ''',
+ version: '0.10.1',
+ isPlatformDependent: false,
+ page: () => DartzPage(),
+ init: () {
+ GetIt.instance.registerFactory(() => DartzModel());
+ },
+);
diff --git a/example/lib/packages/dartz/page.dart b/example/lib/packages/dartz/page.dart
new file mode 100644
index 0000000..7fe4870
--- /dev/null
+++ b/example/lib/packages/dartz/page.dart
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'dart:async';
+
+import 'package:flutter/foundation.dart' show kIsAurora;
+import 'package:flutter/material.dart';
+import 'package:flutter_example_packages/base/di/app_di.dart';
+import 'package:flutter_example_packages/base/package/package.dart';
+import 'package:flutter_example_packages/widgets/base/export.dart';
+import 'package:flutter_example_packages/widgets/blocks/block_info_package.dart';
+import 'package:flutter_example_packages/widgets/blocks/block_item.dart';
+import 'package:flutter_example_packages/widgets/layouts/block_layout.dart';
+import 'package:flutter_example_packages/widgets/texts/export.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:flutter_keyboard_visibility_aurora/flutter_keyboard_visibility_aurora.dart';
+
+import 'model.dart';
+import 'package.dart';
+
+class DartzPage extends AppStatefulWidget {
+ DartzPage({
+ super.key,
+ });
+
+ final Package package = packageDartz;
+
+ @override
+ State createState() => _DartzPageState();
+}
+
+class _DartzPageState extends AppState {
+ final TextEditingController _textController = TextEditingController();
+ final _formKey = GlobalKey();
+ String? _sizeEUR;
+ bool _isError = false;
+
+ double _keyboardHeight = 0;
+ StreamSubscription? _streamSub;
+ final _controllerAurora = FlutterKeyboardVisibilityAurora();
+
+ @override
+ void initState() {
+ super.initState();
+ if (kIsAurora) {
+ _streamSub = _controllerAurora.onChangeHeight.listen((event) {
+ setState(() {
+ _keyboardHeight = event;
+ });
+ });
+ }
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ _streamSub?.cancel();
+ }
+
+ @override
+ Widget buildWide(
+ BuildContext context,
+ MediaQueryData media,
+ AppLocalizations l10n,
+ ) {
+ return BlockLayout(
+ model: getIt(),
+ title: widget.package.key,
+ builder: (context, child, model) {
+ return SingleChildScrollView(
+ padding: EdgeInsets.only(bottom: _keyboardHeight),
+ child: Padding(
+ padding: const EdgeInsets.all(20),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ BlockInfoPackage(widget.package),
+ Form(
+ key: _formKey,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ BlockItem(
+ title: l10n.dartzTitle,
+ desc: l10n.dartzDesc,
+ value: _sizeEUR ?? l10n.dartzDefaultValue,
+ ),
+ TextFormField(
+ controller: _textController,
+ keyboardType: TextInputType.number,
+ decoration: InputDecoration(
+ labelText: l10n.dartzLabel,
+ errorText: _isError ? l10n.dartzErrorFound : null,
+ ),
+ validator: (value) {
+ if (value == null || value.isEmpty) {
+ return l10n.dartzErrorReq;
+ }
+ if (int.tryParse(value) == null) {
+ return l10n.dartzErrorInt;
+ }
+ return null;
+ },
+ ),
+ const SizedBox(height: 20),
+ SizedBox(
+ width: double.infinity,
+ child: ElevatedButton(
+ onPressed: () async {
+ if (_formKey.currentState?.validate() == true) {
+ final sizeRU = int.parse(_textController.text);
+ model
+ .getEURManSize(sizeRU)
+ .map(
+ (classification) => setState(() {
+ _isError = false;
+ _sizeEUR = classification;
+ }),
+ )
+ .getOrElse(
+ () => setState(() {
+ _sizeEUR = null;
+ _isError = true;
+ }),
+ );
+ }
+ },
+ child: TextBodyLarge(
+ l10n.dartzSubmit,
+ color: Colors.white,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/example/lib/packages/device_info_plus/model.dart b/example/lib/packages/device_info_plus/model.dart
new file mode 100644
index 0000000..3b7c11e
--- /dev/null
+++ b/example/lib/packages/device_info_plus/model.dart
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2023. Open Mobile Platform LLC.
+ * License: Proprietary.
+ */
+import 'package:device_info_plus/device_info_plus.dart';
+import 'package:device_info_plus_aurora/aurora_device_info.dart';
+import 'package:flutter/widgets.dart';
+import 'package:scoped_model/scoped_model.dart';
+
+/// Model for [DeviceInfoPlusPage]
+class DeviceInfoPlusModel extends Model {
+ /// Get [ScopedModel]
+ static DeviceInfoPlusModel of(BuildContext context) =>
+ ScopedModel.of(context);
+
+ final _deviceInfoPlugin = DeviceInfoPlugin();
+
+ /// Get Aurora info
+ Future get _deviceInfo async =>
+ await _deviceInfoPlugin.linuxInfo as AuroraDeviceInfo;
+
+ /// Error
+ String? _error;
+
+ /// Public error
+ String? get error => _error;
+
+ /// Public is error
+ bool get isError => _error != null;
+
+ /// Get ID name device
+ Future getID() async {
+ try {
+ return (await _deviceInfo).id;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Device name
+ Future getName() async {
+ try {
+ return (await _deviceInfo).name;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Version
+ Future getVersion() async {
+ try {
+ return (await _deviceInfo).version;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Device full name
+ Future getPrettyName() async {
+ try {
+ return (await _deviceInfo).prettyName;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Check has GNSS
+ Future hasGNSS() async {
+ try {
+ return (await _deviceInfo).hasGNSS;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Check has NFC
+ Future hasNFC() async {
+ try {
+ return (await _deviceInfo).hasNFC;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Check has Bluetooth
+ Future hasBluetooth() async {
+ try {
+ return (await _deviceInfo).hasBluetooth;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Check has Wlan
+ Future hasWlan() async {
+ try {
+ return (await _deviceInfo).hasWlan;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Max CPU clock speed
+ Future getMaxCpuClockSpeed() async {
+ try {
+ return (await _deviceInfo).maxCpuClockSpeed;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Number CPU cores
+ Future getNumberCpuCores() async {
+ try {
+ return (await _deviceInfo).numberCpuCores;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Get battery level in percent 0-100
+ Future getBatteryChargePercentage() async {
+ try {
+ return (await _deviceInfo).batteryChargePercentage;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Camera resolution
+ Future getMainCameraResolution() async {
+ try {
+ return (await _deviceInfo).mainCameraResolution;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Frontal camera resolution
+ Future getFrontalCameraResolution() async {
+ try {
+ return (await _deviceInfo).frontalCameraResolution;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// RAM total size
+ Future getRamTotalSize() async {
+ try {
+ return (await _deviceInfo).ramTotalSize;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// RAM free size
+ Future getRamFreeSize() async {
+ try {
+ return (await _deviceInfo).ramFreeSize;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Screen resolution
+ Future getScreenResolution() async {
+ try {
+ return (await _deviceInfo).screenResolution;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Version @todo
+ Future getOsVersion() async {
+ try {
+ return (await _deviceInfo).osVersion;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Device model
+ Future getDeviceModel() async {
+ try {
+ return (await _deviceInfo).deviceModel;
+ } catch (e) {
+ _error = e.toString();
+ }
+ notifyListeners();
+ return null;
+ }
+
+ /// Get map with info about external storage
+ Future