@ -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' |
@ -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] |
||||
``` |
@ -0,0 +1 @@
|
||||
include: package:flutter_lints/flutter.yaml |
@ -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 |
@ -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" |
||||
} |
@ -0,0 +1,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||
package="ru.auroraos.flutter_example_packages"> |
||||
<!-- The INTERNET permission is required for development. Specifically, |
||||
the Flutter tool needs it to communicate with the running application |
||||
to allow setting breakpoints, to provide hot reload, etc. |
||||
--> |
||||
<uses-permission android:name="android.permission.INTERNET"/> |
||||
</manifest> |
@ -0,0 +1,35 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||
package="ru.auroraos.flutter_example_packages"> |
||||
<application |
||||
android:label="Flutter example packages" |
||||
android:name="${applicationName}" |
||||
android:icon="@mipmap/ic_launcher" |
||||
android:roundIcon="@mipmap/ic_launcher_round"> |
||||
<activity |
||||
android:name=".MainActivity" |
||||
android:exported="true" |
||||
android:launchMode="singleTop" |
||||
android:theme="@style/LaunchTheme" |
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" |
||||
android:hardwareAccelerated="true" |
||||
android:windowSoftInputMode="adjustResize"> |
||||
<!-- Specifies an Android theme to apply to this Activity as soon as |
||||
the Android process has started. This theme is visible to the user |
||||
while the Flutter UI initializes. After that, this theme continues |
||||
to determine the Window background behind the Flutter UI. --> |
||||
<meta-data |
||||
android:name="io.flutter.embedding.android.NormalTheme" |
||||
android:resource="@style/NormalTheme" |
||||
/> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN"/> |
||||
<category android:name="android.intent.category.LAUNCHER"/> |
||||
</intent-filter> |
||||
</activity> |
||||
<!-- Don't delete the meta-data below. |
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> |
||||
<meta-data |
||||
android:name="flutterEmbedding" |
||||
android:value="2" /> |
||||
</application> |
||||
</manifest> |
@ -0,0 +1,6 @@
|
||||
package ru.auroraos.flutter_example_packages |
||||
|
||||
import io.flutter.embedding.android.FlutterActivity |
||||
|
||||
class MainActivity: FlutterActivity() { |
||||
} |
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<!-- Modify this file to customize your launch splash screen --> |
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item android:drawable="?android:colorBackground" /> |
||||
|
||||
<!-- You can insert your own image assets here --> |
||||
<!-- <item> |
||||
<bitmap |
||||
android:gravity="center" |
||||
android:src="@mipmap/launch_image" /> |
||||
</item> --> |
||||
</layer-list> |
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<!-- Modify this file to customize your launch splash screen --> |
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item android:drawable="@android:color/white" /> |
||||
|
||||
<!-- You can insert your own image assets here --> |
||||
<!-- <item> |
||||
<bitmap |
||||
android:gravity="center" |
||||
android:src="@mipmap/launch_image" /> |
||||
</item> --> |
||||
</layer-list> |
@ -0,0 +1,11 @@
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:opacity="opaque"> |
||||
<item android:drawable="@color/bg_splash" /> |
||||
|
||||
<item |
||||
android:width="150dp" |
||||
android:height="150dp" |
||||
android:drawable="@drawable/icon_splash" |
||||
android:gravity="center" /> |
||||
|
||||
</layer-list> |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 14 KiB |
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
<color name="bg_splash">#000000</color> |
||||
</resources> |
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on --> |
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> |
||||
<!-- Show a splash screen on the activity. Automatically removed when |
||||
the Flutter engine draws its first frame --> |
||||
<item name="android:windowBackground">@drawable/splash</item> |
||||
</style> |
||||
<!-- Theme applied to the Android Window as soon as the process has started. |
||||
This theme determines the color of the Android Window while your |
||||
Flutter UI initializes, as well as behind your Flutter UI while its |
||||
running. |
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. --> |
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar"> |
||||
<item name="android:windowBackground">?android:colorBackground</item> |
||||
</style> |
||||
</resources> |
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
<color name="bg_splash">#ffffff</color> |
||||
</resources> |
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off --> |
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar"> |
||||
<!-- Show a splash screen on the activity. Automatically removed when |
||||
the Flutter engine draws its first frame --> |
||||
<item name="android:windowBackground">@drawable/splash</item> |
||||
</style> |
||||
<!-- Theme applied to the Android Window as soon as the process has started. |
||||
This theme determines the color of the Android Window while your |
||||
Flutter UI initializes, as well as behind your Flutter UI while its |
||||
running. |
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. --> |
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar"> |
||||
<item name="android:windowBackground">?android:colorBackground</item> |
||||
</style> |
||||
</resources> |
@ -0,0 +1,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||
package="ru.auroraos.flutter_example_packages"> |
||||
<!-- The INTERNET permission is required for development. Specifically, |
||||
the Flutter tool needs it to communicate with the running application |
||||
to allow setting breakpoints, to provide hot reload, etc. |
||||
--> |
||||
<uses-permission android:name="android.permission.INTERNET"/> |
||||
</manifest> |
@ -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 |
||||
} |
@ -0,0 +1,6 @@
|
||||
org.gradle.jvmargs=-Xmx1536M |
||||
android.useAndroidX=true |
||||
android.enableJetifier=true |
||||
flutter.minSdkVersion=19 |
||||
flutter.targetSdkVersion=33 |
||||
flutter.compileSdkVersion=33 |
@ -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 |
@ -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" |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 18 KiB |
@ -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 |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 3.8 KiB |
@ -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 |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 13 KiB |
@ -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 |
@ -0,0 +1,3 @@
|
||||
arb-dir: lib/l10n |
||||
template-arb-file: app_en.arb |
||||
output-localization-file: app_localizations.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 = <String, WidgetBuilder>{ |
||||
'/': (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, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,7 @@
|
||||
/* |
||||
* Copyright (c) 2023. Open Mobile Platform LLC. |
||||
* License: Proprietary. |
||||
*/ |
||||
abstract class BuildConfig { |
||||
bool get isDebug; |
||||
} |
@ -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; |
||||
} |
@ -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; |
||||
} |
@ -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()); |
||||
} |
@ -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/<KEY>) |
||||
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; |
||||
} |
@ -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; |
||||
} |
@ -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; |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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." |
||||
} |
@ -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": "Фильтр" |
||||
} |
@ -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()); |
||||
} |
@ -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()); |
||||
} |
@ -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<BatteryPlusModel>(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<int?> getBatteryLevel() async { |
||||
try { |
||||
return await _battery.batteryLevel; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Get status |
||||
Future<BatteryState?> getBatteryState() async { |
||||
try { |
||||
return await _battery.batteryState; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Check is enable save mode |
||||
Future<bool?> isInBatterySaveMode() async { |
||||
try { |
||||
return await _battery.isInBatterySaveMode; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Stream change state |
||||
Stream<BatteryState> onBatteryStateChanged() async* { |
||||
try { |
||||
yield await _battery.batteryState; |
||||
await for (final state in _battery.onBatteryStateChanged) { |
||||
yield state; |
||||
} |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
@ -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>(() => BatteryPlusModel()); |
||||
}, |
||||
); |
@ -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<BatteryPlusPage> createState() => _BatteryPlusPageState(); |
||||
} |
||||
|
||||
class _BatteryPlusPageState extends AppState<BatteryPlusPage> { |
||||
@override |
||||
Widget buildWide( |
||||
BuildContext context, |
||||
MediaQueryData media, |
||||
AppLocalizations l10n, |
||||
) { |
||||
return BlockLayout<BatteryPlusModel>( |
||||
model: getIt<BatteryPlusModel>(), |
||||
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(), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -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, |
||||
); |
@ -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<CachedNetworkImageModel>(context); |
||||
} |
@ -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>( |
||||
() => CachedNetworkImageModel()); |
||||
}, |
||||
); |
@ -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<CachedNetworkImagePage> createState() => _CachedNetworkImagePageState(); |
||||
} |
||||
|
||||
class _CachedNetworkImagePageState extends AppState<CachedNetworkImagePage> { |
||||
@override |
||||
Widget buildWide( |
||||
BuildContext context, |
||||
MediaQueryData media, |
||||
AppLocalizations l10n, |
||||
) { |
||||
return BlockLayout<CachedNetworkImageModel>( |
||||
model: getIt<CachedNetworkImageModel>(), |
||||
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), |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -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, |
||||
); |
@ -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, |
||||
); |
@ -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<DartzModel>(context); |
||||
|
||||
/// Example using Option from package dartz |
||||
Option<String> 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(); |
||||
} |
||||
} |
@ -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>(() => DartzModel()); |
||||
}, |
||||
); |
@ -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<DartzPage> createState() => _DartzPageState(); |
||||
} |
||||
|
||||
class _DartzPageState extends AppState<DartzPage> { |
||||
final TextEditingController _textController = TextEditingController(); |
||||
final _formKey = GlobalKey<FormState>(); |
||||
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<DartzModel>( |
||||
model: getIt<DartzModel>(), |
||||
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, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -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<DeviceInfoPlusModel>(context); |
||||
|
||||
final _deviceInfoPlugin = DeviceInfoPlugin(); |
||||
|
||||
/// Get Aurora info |
||||
Future<AuroraDeviceInfo> 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<String?> getID() async { |
||||
try { |
||||
return (await _deviceInfo).id; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Device name |
||||
Future<String?> getName() async { |
||||
try { |
||||
return (await _deviceInfo).name; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Version |
||||
Future<String?> getVersion() async { |
||||
try { |
||||
return (await _deviceInfo).version; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Device full name |
||||
Future<String?> getPrettyName() async { |
||||
try { |
||||
return (await _deviceInfo).prettyName; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Check has GNSS |
||||
Future<bool?> hasGNSS() async { |
||||
try { |
||||
return (await _deviceInfo).hasGNSS; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Check has NFC |
||||
Future<bool?> hasNFC() async { |
||||
try { |
||||
return (await _deviceInfo).hasNFC; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Check has Bluetooth |
||||
Future<bool?> hasBluetooth() async { |
||||
try { |
||||
return (await _deviceInfo).hasBluetooth; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Check has Wlan |
||||
Future<bool?> hasWlan() async { |
||||
try { |
||||
return (await _deviceInfo).hasWlan; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Max CPU clock speed |
||||
Future<int?> getMaxCpuClockSpeed() async { |
||||
try { |
||||
return (await _deviceInfo).maxCpuClockSpeed; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Number CPU cores |
||||
Future<int?> getNumberCpuCores() async { |
||||
try { |
||||
return (await _deviceInfo).numberCpuCores; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Get battery level in percent 0-100 |
||||
Future<int?> getBatteryChargePercentage() async { |
||||
try { |
||||
return (await _deviceInfo).batteryChargePercentage; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Camera resolution |
||||
Future<double?> getMainCameraResolution() async { |
||||
try { |
||||
return (await _deviceInfo).mainCameraResolution; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Frontal camera resolution |
||||
Future<double?> getFrontalCameraResolution() async { |
||||
try { |
||||
return (await _deviceInfo).frontalCameraResolution; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// RAM total size |
||||
Future<int?> getRamTotalSize() async { |
||||
try { |
||||
return (await _deviceInfo).ramTotalSize; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// RAM free size |
||||
Future<int?> getRamFreeSize() async { |
||||
try { |
||||
return (await _deviceInfo).ramFreeSize; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Screen resolution |
||||
Future<String?> getScreenResolution() async { |
||||
try { |
||||
return (await _deviceInfo).screenResolution; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Version @todo |
||||
Future<String?> getOsVersion() async { |
||||
try { |
||||
return (await _deviceInfo).osVersion; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Device model |
||||
Future<String?> getDeviceModel() async { |
||||
try { |
||||
return (await _deviceInfo).deviceModel; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Get map with info about external storage |
||||
Future<Map<String, dynamic>?> getExternalStorage() async { |
||||
try { |
||||
return (await _deviceInfo).externalStorage; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Get map with info about internal storage |
||||
Future<Map<String, dynamic>?> getInternalStorage() async { |
||||
try { |
||||
return (await _deviceInfo).internalStorage; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
|
||||
/// Get map with info about SIM cards |
||||
Future<List<Map<String, dynamic>>?> getSimCards() async { |
||||
try { |
||||
return (await _deviceInfo).simCards; |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* 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/device_info_plus/page.dart'; |
||||
import 'package:get_it/get_it.dart'; |
||||
|
||||
import 'model.dart'; |
||||
|
||||
/// Package values |
||||
final packageDeviceInfoPlus = PackagePage( |
||||
key: 'device_info_plus', |
||||
descEN: ''' |
||||
Get current device information from within the Flutter application. |
||||
''', |
||||
descRU: ''' |
||||
Получите текущую информацию об устройстве из приложения Flutter. |
||||
''', |
||||
version: '8.2.2', |
||||
isPlatformDependent: true, |
||||
page: () => DeviceInfoPlusPage(), |
||||
init: () { |
||||
GetIt.instance |
||||
.registerFactory<DeviceInfoPlusModel>(() => DeviceInfoPlusModel()); |
||||
}, |
||||
); |
@ -0,0 +1,150 @@
|
||||
/* |
||||
* 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/device_info_plus/model.dart'; |
||||
import 'package:flutter_example_packages/packages/device_info_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 DeviceInfoPlusPage extends AppStatefulWidget { |
||||
DeviceInfoPlusPage({ |
||||
super.key, |
||||
}); |
||||
|
||||
final Package package = packageDeviceInfoPlus; |
||||
|
||||
@override |
||||
State<DeviceInfoPlusPage> createState() => _DeviceInfoPlusPageState(); |
||||
} |
||||
|
||||
class _DeviceInfoPlusPageState extends AppState<DeviceInfoPlusPage> { |
||||
@override |
||||
Widget buildWide( |
||||
BuildContext context, |
||||
MediaQueryData media, |
||||
AppLocalizations l10n, |
||||
) { |
||||
return BlockLayout<DeviceInfoPlusModel>( |
||||
model: getIt<DeviceInfoPlusModel>(), |
||||
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.deviceInfoPlusTitleID, |
||||
desc: l10n.deviceInfoPlusDescID, |
||||
future: model.getID(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleName, |
||||
desc: l10n.deviceInfoPlusDescName, |
||||
future: model.getName(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleVersion, |
||||
desc: l10n.deviceInfoPlusDescVersion, |
||||
future: model.getVersion(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitlePrettyName, |
||||
desc: l10n.deviceInfoPlusDescName, |
||||
future: model.getPrettyName(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleGNSS, |
||||
desc: l10n.deviceInfoPlusDescGNSS, |
||||
future: model.hasGNSS(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleNFC, |
||||
desc: l10n.deviceInfoPlusDescNFC, |
||||
future: model.hasNFC(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleBluetooth, |
||||
desc: l10n.deviceInfoPlusDescBluetooth, |
||||
future: model.hasBluetooth(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleWlan, |
||||
desc: l10n.deviceInfoPlusDescWlan, |
||||
future: model.hasWlan(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleMaxCpuClockSpeed, |
||||
desc: l10n.deviceInfoPlusDescMaxCpuClockSpeed, |
||||
future: model.getMaxCpuClockSpeed(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleNumberCpuCores, |
||||
desc: l10n.deviceInfoPlusDescNumberCpuCores, |
||||
future: model.getNumberCpuCores(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleBatteryCharge, |
||||
desc: l10n.deviceInfoPlusDescBatteryCharge, |
||||
future: model.getBatteryChargePercentage(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleMainCameraResolution, |
||||
desc: l10n.deviceInfoPlusDescMainCameraResolution, |
||||
future: model.getMainCameraResolution(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleFrontalCameraResolution, |
||||
desc: l10n.deviceInfoPlusDescFrontalCameraResolution, |
||||
future: model.getFrontalCameraResolution(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleRamTotalSize, |
||||
desc: l10n.deviceInfoPlusDescRamTotalSize, |
||||
future: model.getRamTotalSize(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleRamFreeSize, |
||||
desc: l10n.deviceInfoPlusDescRamFreeSize, |
||||
future: model.getRamFreeSize(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleScreenResolution, |
||||
desc: l10n.deviceInfoPlusDescScreenResolution, |
||||
future: model.getScreenResolution(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleOsVersion, |
||||
desc: l10n.deviceInfoPlusDescOsVersion, |
||||
future: model.getOsVersion(), |
||||
), |
||||
BlockItem( |
||||
title: l10n.deviceInfoPlusTitleDeviceModel, |
||||
desc: l10n.deviceInfoPlusDescDeviceModel, |
||||
future: model.getDeviceModel(), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* Copyright (c) 2023. Open Mobile Platform LLC. |
||||
* License: Proprietary. |
||||
*/ |
||||
import 'package:flutter/widgets.dart'; |
||||
import 'package:flutter_example_packages/packages/equatable/user_entity.dart'; |
||||
import 'package:flutter_example_packages/packages/equatable/user_entity_equatable.dart'; |
||||
import 'package:scoped_model/scoped_model.dart'; |
||||
|
||||
/// Model for [EquatablePage] |
||||
class EquatableModel extends Model { |
||||
/// Get [ScopedModel] |
||||
static EquatableModel of(BuildContext context) => |
||||
ScopedModel.of<EquatableModel>(context); |
||||
|
||||
UserEntity userEntity = const UserEntity( |
||||
name: 'Default', |
||||
email: 'default@yandex.ru', |
||||
age: 12, |
||||
); |
||||
|
||||
UserEntityEquatable userEntityEquatable = const UserEntityEquatable( |
||||
name: 'Equatable', |
||||
email: 'default@yandex.ru', |
||||
age: 12, |
||||
); |
||||
} |
@ -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:get_it/get_it.dart'; |
||||
|
||||
import 'model.dart'; |
||||
import 'page.dart'; |
||||
|
||||
/// Package values |
||||
final packageEquatable = PackagePage( |
||||
key: 'equatable', |
||||
descEN: ''' |
||||
Being able to compare objects in Dart often involves having to override |
||||
the == operator as well as hashCode. |
||||
''', |
||||
descRU: ''' |
||||
Возможность сравнивать объекты в Dart часто требует переопределения |
||||
оператора ==, а также hashCode. |
||||
''', |
||||
version: '2.0.5', |
||||
isPlatformDependent: false, |
||||
page: () => EquatablePage(), |
||||
init: () { |
||||
GetIt.instance.registerFactory<EquatableModel>(() => EquatableModel()); |
||||
}, |
||||
); |
@ -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/theme/radius.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_example_packages/widgets/texts/export.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
|
||||
import 'model.dart'; |
||||
import 'package.dart'; |
||||
|
||||
class EquatablePage extends AppStatefulWidget { |
||||
EquatablePage({ |
||||
super.key, |
||||
}); |
||||
|
||||
final Package package = packageEquatable; |
||||
|
||||
@override |
||||
State<EquatablePage> createState() => _EquatablePageState(); |
||||
} |
||||
|
||||
class _EquatablePageState extends AppState<EquatablePage> { |
||||
@override |
||||
Widget buildWide( |
||||
BuildContext context, |
||||
MediaQueryData media, |
||||
AppLocalizations l10n, |
||||
) { |
||||
return BlockLayout<EquatableModel>( |
||||
model: getIt<EquatableModel>(), |
||||
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), |
||||
TextTitleLarge(l10n.equatableTitleDefault), |
||||
const SizedBox(height: 8), |
||||
TextBodyMedium(l10n.equatableSubtitle), |
||||
const SizedBox(height: 14), |
||||
Container( |
||||
width: double.infinity, |
||||
decoration: BoxDecoration( |
||||
color: Colors.blue.shade50, |
||||
borderRadius: AppRadius.small, |
||||
), |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(10), |
||||
child: TextBodyMedium(model.userEntity.toString()), |
||||
), |
||||
), |
||||
const SizedBox(height: 20), |
||||
TextTitleLarge(l10n.equatableTitleFreezed), |
||||
const SizedBox(height: 8), |
||||
TextBodyMedium(l10n.equatableSubtitle), |
||||
const SizedBox(height: 14), |
||||
Container( |
||||
width: double.infinity, |
||||
decoration: BoxDecoration( |
||||
color: Colors.blue.shade50, |
||||
borderRadius: AppRadius.small, |
||||
), |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(10), |
||||
child: TextBodyMedium(model.userEntityEquatable.toString()), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,45 @@
|
||||
/* |
||||
* Copyright (c) 2023. Open Mobile Platform LLC. |
||||
* License: Proprietary. |
||||
*/ |
||||
import 'package:flutter/foundation.dart'; |
||||
|
||||
@immutable |
||||
class UserEntity { |
||||
const UserEntity({ |
||||
required this.name, |
||||
required this.email, |
||||
required this.age, |
||||
}); |
||||
|
||||
final String name; |
||||
final String email; |
||||
final int age; |
||||
|
||||
@override |
||||
String toString() { |
||||
return 'UserEntity(' |
||||
'$name,' |
||||
'$email,' |
||||
'$age' |
||||
')'; |
||||
} |
||||
|
||||
@override |
||||
bool operator ==(dynamic other) { |
||||
return other is UserEntity && |
||||
other.name == name && |
||||
other.email == email && |
||||
other.age == age; |
||||
} |
||||
|
||||
@override |
||||
int get hashCode { |
||||
return Object.hash( |
||||
runtimeType, |
||||
name, |
||||
email, |
||||
age, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,25 @@
|
||||
/* |
||||
* Copyright (c) 2023. Open Mobile Platform LLC. |
||||
* License: Proprietary. |
||||
*/ |
||||
import 'package:equatable/equatable.dart'; |
||||
import 'package:flutter/foundation.dart'; |
||||
|
||||
@immutable |
||||
class UserEntityEquatable extends Equatable { |
||||
const UserEntityEquatable({ |
||||
required this.name, |
||||
required this.email, |
||||
required this.age, |
||||
}); |
||||
|
||||
final String name; |
||||
final String email; |
||||
final int age; |
||||
|
||||
@override |
||||
List<Object> get props => [name, email, age]; |
||||
|
||||
@override |
||||
bool get stringify => true; |
||||
} |
@ -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 packageFlutterCacheManager = PackageDialog( |
||||
key: 'flutter_cache_manager', |
||||
descEN: ''' |
||||
CacheManager v2 introduced some breaking changes when configuring |
||||
a custom CacheManager. |
||||
''', |
||||
descRU: ''' |
||||
В CacheManager v2 были внесены некоторые критические изменения при |
||||
настройке пользовательского CacheManager. |
||||
''', |
||||
messageEN: ''' |
||||
This is a platform dependent plugin, used in a plugin |
||||
cached_network_image should work for you too. |
||||
''', |
||||
messageRU: ''' |
||||
Это плагин зависимый от платформы, используется в плагине |
||||
cached_network_image, должен работать и у вас. |
||||
''', |
||||
version: '3.3.0', |
||||
isPlatformDependent: true, |
||||
); |
@ -0,0 +1,58 @@
|
||||
/* |
||||
* Copyright (c) 2023. Open Mobile Platform LLC. |
||||
* License: Proprietary. |
||||
*/ |
||||
import 'package:flutter/widgets.dart'; |
||||
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; |
||||
import 'package:flutter_keyboard_visibility_aurora/flutter_keyboard_visibility_aurora.dart'; |
||||
import 'package:scoped_model/scoped_model.dart'; |
||||
import 'package:flutter/foundation.dart' show kIsAurora; |
||||
|
||||
/// Model for [FlutterKeyboardVisibilityPage] |
||||
class FlutterKeyboardVisibilityModel extends Model { |
||||
/// Get [ScopedModel] |
||||
static FlutterKeyboardVisibilityModel of(BuildContext context) => |
||||
ScopedModel.of<FlutterKeyboardVisibilityModel>(context); |
||||
|
||||
final _controller = KeyboardVisibilityController(); |
||||
final _controllerAurora = FlutterKeyboardVisibilityAurora(); |
||||
|
||||
/// Error |
||||
String? _error; |
||||
|
||||
/// Public error |
||||
String? get error => _error; |
||||
|
||||
/// Public is error |
||||
bool get isError => _error != null; |
||||
|
||||
/// Stream change visibility |
||||
Stream<bool> onChangeKeyboard() async* { |
||||
try { |
||||
yield _controller.isVisible; |
||||
await for (final state in _controller.onChange) { |
||||
yield state; |
||||
} |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
|
||||
/// Stream change height |
||||
Stream<double> onChangeKeyboardHeight() async* { |
||||
if (kIsAurora) { |
||||
try { |
||||
yield await _controllerAurora.height; |
||||
await for (final state in _controllerAurora.onChangeHeight) { |
||||
yield state; |
||||
} |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
notifyListeners(); |
||||
} |
||||
} else { |
||||
yield 0; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* 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 'page.dart'; |
||||
import 'model.dart'; |
||||
|
||||
/// Package values |
||||
final packageFlutterKeyboardVisibility = PackagePage( |
||||
key: 'flutter_keyboard_visibility', |
||||
descEN: ''' |
||||
React to keyboard visibility changes. |
||||
''', |
||||
descRU: ''' |
||||
Реагировать на изменения видимости клавиатуры. |
||||
''', |
||||
version: '5.4.1', |
||||
isPlatformDependent: true, |
||||
page: () => FlutterKeyboardVisibilityPage(), |
||||
init: () { |
||||
GetIt.instance.registerFactory<FlutterKeyboardVisibilityModel>( |
||||
() => FlutterKeyboardVisibilityModel()); |
||||
}, |
||||
); |
@ -0,0 +1,123 @@
|
||||
/* |
||||
* 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_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_example_packages/widgets/texts/export.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
|
||||
import 'model.dart'; |
||||
import 'package.dart'; |
||||
|
||||
class FlutterKeyboardVisibilityPage extends AppStatefulWidget { |
||||
FlutterKeyboardVisibilityPage({ |
||||
super.key, |
||||
}); |
||||
|
||||
final Package package = packageFlutterKeyboardVisibility; |
||||
|
||||
@override |
||||
State<FlutterKeyboardVisibilityPage> createState() => |
||||
_FlutterKeyboardVisibilityPageState(); |
||||
} |
||||
|
||||
class _FlutterKeyboardVisibilityPageState |
||||
extends AppState<FlutterKeyboardVisibilityPage> { |
||||
double _keyboardHeight = 0; |
||||
StreamSubscription? _streamSub; |
||||
final model = getIt<FlutterKeyboardVisibilityModel>(); |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
if (kIsAurora) { |
||||
_streamSub = model.onChangeKeyboardHeight().listen((height) { |
||||
setState(() { |
||||
_keyboardHeight = height; |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
_streamSub?.cancel(); |
||||
} |
||||
|
||||
@override |
||||
Widget buildWide( |
||||
BuildContext context, |
||||
MediaQueryData media, |
||||
AppLocalizations l10n, |
||||
) { |
||||
return BlockLayout<FlutterKeyboardVisibilityModel>( |
||||
model: model, |
||||
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), |
||||
BlockAlert(model.error), |
||||
if (!model.isError) |
||||
Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
TextField( |
||||
decoration: InputDecoration( |
||||
hintText: l10n.flutterKeyboardVisibilityField, |
||||
), |
||||
), |
||||
const SizedBox(height: 20), |
||||
SizedBox( |
||||
width: 140, |
||||
child: ElevatedButton( |
||||
onPressed: () => FocusScope.of(context).unfocus(), |
||||
child: TextBodyLarge( |
||||
l10n.flutterKeyboardVisibilityButton, |
||||
color: Colors.white, |
||||
), |
||||
), |
||||
), |
||||
const SizedBox(height: 20), |
||||
Visibility( |
||||
visible: kIsAurora, |
||||
child: BlockItem( |
||||
title: l10n.flutterKeyboardVisibilityTitleHeight, |
||||
desc: l10n.flutterKeyboardVisibilityDescHeight, |
||||
value: _keyboardHeight, |
||||
builder: (value) => value.toInt().toString(), |
||||
), |
||||
), |
||||
const SizedBox(height: 20), |
||||
BlockItem( |
||||
title: l10n.flutterKeyboardVisibilityTitle, |
||||
desc: l10n.flutterKeyboardVisibilityDesc, |
||||
stream: model.onChangeKeyboard(), |
||||
builder: (value) => value.toString().toUpperCase(), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,49 @@
|
||||
/* |
||||
* Copyright (c) 2023. Open Mobile Platform LLC. |
||||
* License: Proprietary. |
||||
*/ |
||||
import 'package:flutter/widgets.dart'; |
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; |
||||
import 'package:scoped_model/scoped_model.dart'; |
||||
|
||||
/// Model for [FlutterLocalNotificationsPage] |
||||
class FlutterLocalNotificationsModel extends Model { |
||||
/// Get [ScopedModel] |
||||
static FlutterLocalNotificationsModel of(BuildContext context) => |
||||
ScopedModel.of<FlutterLocalNotificationsModel>(context); |
||||
|
||||
final FlutterLocalNotificationsPlugin notification = |
||||
FlutterLocalNotificationsPlugin(); |
||||
|
||||
final notificationID = 1; |
||||
|
||||
/// Error |
||||
String? _error; |
||||
|
||||
/// Public error |
||||
String? get error => _error; |
||||
|
||||
/// Public is error |
||||
bool get isError => _error != null; |
||||
|
||||
/// Show local notification |
||||
Future<void> showNotification({ |
||||
required String title, |
||||
required String body, |
||||
}) async { |
||||
try { |
||||
// Cansel if already run |
||||
await notification.cancel(notificationID); |
||||
// Show notification |
||||
await notification.show( |
||||
notificationID, |
||||
title, |
||||
body, |
||||
null, |
||||
); |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
notifyListeners(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* 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/flutter_local_notifications/page.dart'; |
||||
import 'package:get_it/get_it.dart'; |
||||
|
||||
import 'model.dart'; |
||||
|
||||
/// Package values |
||||
final packageFlutterLocalNotifications = PackagePage( |
||||
key: 'flutter_local_notifications', |
||||
descEN: ''' |
||||
A cross platform plugin for displaying local notifications. |
||||
''', |
||||
descRU: ''' |
||||
Кроссплатформенный плагин для отображения локальных уведомлений. |
||||
''', |
||||
version: '14.1.1', |
||||
isPlatformDependent: true, |
||||
page: () => FlutterLocalNotificationsPage(), |
||||
init: () { |
||||
GetIt.instance.registerFactory<FlutterLocalNotificationsModel>( |
||||
() => FlutterLocalNotificationsModel()); |
||||
}, |
||||
); |
@ -0,0 +1,96 @@
|
||||
/* |
||||
* 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/flutter_local_notifications/model.dart'; |
||||
import 'package:flutter_example_packages/packages/flutter_local_notifications/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/layouts/block_layout.dart'; |
||||
import 'package:flutter_example_packages/widgets/texts/export.dart'; |
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; |
||||
|
||||
class FlutterLocalNotificationsPage extends AppStatefulWidget { |
||||
FlutterLocalNotificationsPage({ |
||||
super.key, |
||||
}); |
||||
|
||||
final Package package = packageFlutterLocalNotifications; |
||||
|
||||
@override |
||||
State<FlutterLocalNotificationsPage> createState() => |
||||
_FlutterLocalNotificationsPageState(); |
||||
} |
||||
|
||||
class _FlutterLocalNotificationsPageState |
||||
extends AppState<FlutterLocalNotificationsPage> { |
||||
final TextEditingController _titleController = TextEditingController(); |
||||
final TextEditingController _bodyController = TextEditingController(); |
||||
|
||||
@override |
||||
Widget buildWide( |
||||
BuildContext context, |
||||
MediaQueryData media, |
||||
AppLocalizations l10n, |
||||
) { |
||||
return BlockLayout<FlutterLocalNotificationsModel>( |
||||
model: getIt<FlutterLocalNotificationsModel>(), |
||||
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: [ |
||||
TextField( |
||||
controller: _titleController, |
||||
decoration: InputDecoration( |
||||
hintText: l10n.flutterLocalNotificationsHintTitle, |
||||
), |
||||
), |
||||
const SizedBox(height: 16), |
||||
TextField( |
||||
controller: _bodyController, |
||||
decoration: InputDecoration( |
||||
hintText: l10n.flutterLocalNotificationsHintBody, |
||||
), |
||||
), |
||||
const SizedBox(height: 20), |
||||
SizedBox( |
||||
width: double.infinity, |
||||
child: ElevatedButton( |
||||
onPressed: () => model.showNotification( |
||||
title: _titleController.text.isEmpty |
||||
? l10n.flutterLocalNotificationsHintTitle |
||||
: _titleController.text, |
||||
body: _bodyController.text.isEmpty |
||||
? l10n.flutterLocalNotificationsHintBody |
||||
: _bodyController.text, |
||||
), |
||||
child: TextBodyLarge( |
||||
l10n.flutterLocalNotificationsBtn, |
||||
color: Colors.white, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,44 @@
|
||||
/* |
||||
* Copyright (c) 2023. Open Mobile Platform LLC. |
||||
* License: Proprietary. |
||||
*/ |
||||
import 'package:flutter/widgets.dart'; |
||||
import 'package:scoped_model/scoped_model.dart'; |
||||
|
||||
/// Model for [FlutterMarkdownPage] |
||||
class FlutterMarkdownModel extends Model { |
||||
/// Get [ScopedModel] |
||||
static FlutterMarkdownModel of(BuildContext context) => |
||||
ScopedModel.of<FlutterMarkdownModel>(context); |
||||
|
||||
final String data = ''' |
||||
An h1 header |
||||
============ |
||||
|
||||
Paragraphs are separated by a blank line. |
||||
|
||||
2nd paragraph. *Italic*, **bold**, and `monospace`. Itemized lists |
||||
look like: |
||||
|
||||
* this one |
||||
* that one |
||||
* the other one |
||||
|
||||
Note that --- not considering the asterisk --- the actual text |
||||
content starts at 4-columns in. |
||||
|
||||
> Block quotes are |
||||
> written like so. |
||||
> |
||||
> They can span multiple paragraphs, |
||||
> if you like. |
||||
|
||||
Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., "it's all |
||||
in chapters 12--14"). Three dots ... will be converted to an ellipsis. |
||||
Unicode is supported. ☺ |
||||
|
||||
## Image |
||||
|
||||
![Minion](https://github.com/keygenqt/awesome-aurora/blob/master/docs/assets/images/common/aurora.png?raw=true) |
||||
'''; |
||||
} |
@ -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:get_it/get_it.dart'; |
||||
|
||||
import 'model.dart'; |
||||
import 'page.dart'; |
||||
|
||||
/// Package values |
||||
final packageFlutterMarkdown = PackagePage( |
||||
key: 'flutter_markdown', |
||||
descEN: ''' |
||||
A markdown renderer for Flutter. It supports the original format, |
||||
but no inline HTML. |
||||
''', |
||||
descRU: ''' |
||||
Рендерер уценки для Flutter. Он поддерживает исходный формат, |
||||
но не поддерживает встроенный HTML. |
||||
''', |
||||
version: '0.6.15', |
||||
isPlatformDependent: false, |
||||
page: () => FlutterMarkdownPage(), |
||||
init: () { |
||||
GetIt.instance |
||||
.registerFactory<FlutterMarkdownModel>(() => FlutterMarkdownModel()); |
||||
}, |
||||
); |
@ -0,0 +1,67 @@
|
||||
/* |
||||
* 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/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'; |
||||
import 'package:flutter_markdown/flutter_markdown.dart'; |
||||
|
||||
import 'model.dart'; |
||||
import 'package.dart'; |
||||
|
||||
class FlutterMarkdownPage extends AppStatefulWidget { |
||||
FlutterMarkdownPage({ |
||||
super.key, |
||||
}); |
||||
|
||||
final Package package = packageFlutterMarkdown; |
||||
|
||||
@override |
||||
State<FlutterMarkdownPage> createState() => _FlutterMarkdownPageState(); |
||||
} |
||||
|
||||
class _FlutterMarkdownPageState extends AppState<FlutterMarkdownPage> { |
||||
final ScrollController _scrollController = ScrollController(); |
||||
|
||||
@override |
||||
Widget buildWide( |
||||
BuildContext context, |
||||
MediaQueryData media, |
||||
AppLocalizations l10n, |
||||
) { |
||||
return BlockLayout<FlutterMarkdownModel>( |
||||
model: getIt<FlutterMarkdownModel>(), |
||||
title: widget.package.key, |
||||
builder: (context, child, model) { |
||||
return Column( |
||||
children: [ |
||||
Flexible( |
||||
flex: 0, |
||||
child: Padding( |
||||
padding: const EdgeInsets.only( |
||||
top: 20, |
||||
left: 20, |
||||
right: 20, |
||||
), |
||||
child: BlockInfoPackage(widget.package), |
||||
), |
||||
), |
||||
Flexible( |
||||
flex: 1, |
||||
child: Markdown( |
||||
controller: _scrollController, |
||||
padding: const EdgeInsets.all(20.0), |
||||
data: model.data, |
||||
), |
||||
), |
||||
], |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,109 @@
|
||||
/* |
||||
* Copyright (c) 2023. Open Mobile Platform LLC. |
||||
* License: Proprietary. |
||||
*/ |
||||
import 'dart:convert'; |
||||
|
||||
import 'package:crypto/crypto.dart'; |
||||
import 'package:flutter/widgets.dart'; |
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; |
||||
import 'package:flutter_secure_storage_aurora/flutter_secure_storage_aurora.dart'; |
||||
import 'package:scoped_model/scoped_model.dart'; |
||||
|
||||
/// Model for [FlutterSecureStoragePage] |
||||
class FlutterSecureStorageModel extends Model { |
||||
/// Get [ScopedModel] |
||||
static FlutterSecureStorageModel of(BuildContext context) => |
||||
ScopedModel.of<FlutterSecureStorageModel>(context); |
||||
|
||||
final _secureStorage = const FlutterSecureStorage(); |
||||
|
||||
/// Error |
||||
String? _error; |
||||
|
||||
/// Public error |
||||
String? get error => _error; |
||||
|
||||
/// Public is error |
||||
bool get isError => _error != null; |
||||
|
||||
/// Save success |
||||
bool _isSuccess = false; |
||||
|
||||
/// Public success |
||||
bool get isSuccess => _isSuccess; |
||||
|
||||
/// Value for read form secure storage |
||||
String _readValue = ""; |
||||
|
||||
/// Public read value |
||||
String get readValue => _readValue; |
||||
|
||||
// Get data from secure storage |
||||
Future<void> read({ |
||||
required String key, |
||||
required String password, |
||||
}) async { |
||||
try { |
||||
// Update secret key |
||||
_updateByPassword(password); |
||||
// Read data |
||||
_readValue = await _secureStorage.read(key: key) ?? "Not found"; |
||||
} catch (e) { |
||||
_readValue = "Error password"; |
||||
} |
||||
notifyListeners(); |
||||
} |
||||
|
||||
// Write new data in secure storage |
||||
Future<void> write({ |
||||
required String key, |
||||
required String value, |
||||
required String password, |
||||
}) async { |
||||
try { |
||||
// Update secret key |
||||
_updateByPassword(password); |
||||
// Clear old data |
||||
await _secureStorage.deleteAll(); |
||||
// Save new data |
||||
await _secureStorage.write(key: key, value: value); |
||||
// Show success |
||||
_isSuccess = true; |
||||
// Close success |
||||
Future.delayed(const Duration(milliseconds: 1500), () { |
||||
_isSuccess = false; |
||||
notifyListeners(); |
||||
}); |
||||
} catch (e) { |
||||
_error = e.toString(); |
||||
} |
||||
notifyListeners(); |
||||
} |
||||
|
||||
/// Update password |
||||
void _updateByPassword( |
||||
String password, |
||||
) { |
||||
// https://pub.dev/packages/encrypt |
||||
// Encrypter(AES(key)) |
||||
// secure-random --length 16 --base 16 |
||||
// You can generate a secret key based on user data, as an example of a hash pin-code |
||||
FlutterSecureStorageAurora.setSecret( |
||||
_getPasswordFromString(password), |
||||
); |
||||
} |
||||
|
||||
/// Generate secure key 32 length from string password |
||||
String _getPasswordFromString( |
||||
String password, |
||||
) { |
||||
return md5.convert(utf8.encode(password)).toString(); |
||||
} |
||||
|
||||
/// Clear value if change values |
||||
void clearReadValue() { |
||||
_readValue = ""; |
||||
notifyListeners(); |
||||
} |
||||
} |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* 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/flutter_secure_storage/page.dart'; |
||||
import 'package:get_it/get_it.dart'; |
||||
|
||||
import 'model.dart'; |
||||
|
||||
/// Package values |
||||
final packageFlutterSecureStorage = PackagePage( |
||||
key: 'flutter_secure_storage', |
||||
descEN: ''' |
||||
Flutter Secure Storage provides API to store data in secure storage. |
||||
''', |
||||
descRU: ''' |
||||
Flutter Secure Storage предоставляет API для хранения данных в безопасном хранилище. |
||||
''', |
||||
version: '8.0.0', |
||||
isPlatformDependent: true, |
||||
page: () => FlutterSecureStoragePage(), |
||||
init: () { |
||||
GetIt.instance.registerFactory<FlutterSecureStorageModel>( |
||||
() => FlutterSecureStorageModel()); |
||||
}, |
||||
); |
@ -0,0 +1,213 @@
|
||||
/* |
||||
* 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/packages/flutter_secure_storage/model.dart'; |
||||
import 'package:flutter_example_packages/packages/flutter_secure_storage/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/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'; |
||||
|
||||
class FlutterSecureStoragePage extends AppStatefulWidget { |
||||
FlutterSecureStoragePage({ |
||||
super.key, |
||||
}); |
||||
|
||||
final Package package = packageFlutterSecureStorage; |
||||
|
||||
@override |
||||
State<FlutterSecureStoragePage> createState() => |
||||
_FlutterSecureStoragePageState(); |
||||
} |
||||
|
||||
class _FlutterSecureStoragePageState |
||||
extends AppState<FlutterSecureStoragePage> { |
||||
double _keyboardHeight = 0; |
||||
StreamSubscription? _streamSub; |
||||
final _controllerAurora = FlutterKeyboardVisibilityAurora(); |
||||
|
||||
bool _isValidSave = false; |
||||
final TextEditingController _passSaveController = TextEditingController(); |
||||
final TextEditingController _keySaveController = TextEditingController(); |
||||
final TextEditingController _valueSaveController = TextEditingController(); |
||||
|
||||
bool _isValidGet = false; |
||||
final TextEditingController _passGetController = TextEditingController(); |
||||
final TextEditingController _keyGetController = TextEditingController(); |
||||
final TextEditingController _valueGetController = TextEditingController(); |
||||
|
||||
void _validateSave() { |
||||
setState(() { |
||||
_isValidSave = _passSaveController.text.isNotEmpty && |
||||
_keySaveController.text.isNotEmpty && |
||||
_valueSaveController.text.isNotEmpty; |
||||
}); |
||||
} |
||||
|
||||
void _validateGet() { |
||||
setState(() { |
||||
_isValidGet = _passGetController.text.isNotEmpty && |
||||
_keyGetController.text.isNotEmpty; |
||||
}); |
||||
} |
||||
|
||||
@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<FlutterSecureStorageModel>( |
||||
model: getIt<FlutterSecureStorageModel>(), |
||||
title: widget.package.key, |
||||
builder: (context, child, model) { |
||||
// update read only value |
||||
_valueGetController.text = model.readValue; |
||||
// return widget |
||||
return SingleChildScrollView( |
||||
padding: EdgeInsets.only(bottom: _keyboardHeight), |
||||
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: [ |
||||
TextTitleLarge(l10n.flutterSecureStorageTitleSave), |
||||
const SizedBox(height: 14), |
||||
if (model.isSuccess) |
||||
BlockAlert( |
||||
l10n.flutterSecureStorageSuccess, |
||||
color: Colors.lightGreen, |
||||
), |
||||
const SizedBox(height: 6), |
||||
TextField( |
||||
controller: _passSaveController, |
||||
decoration: InputDecoration( |
||||
labelText: l10n.flutterSecureStorageFieldPass, |
||||
), |
||||
onChanged: (_) => _validateSave(), |
||||
), |
||||
const SizedBox(height: 16), |
||||
TextField( |
||||
controller: _keySaveController, |
||||
decoration: InputDecoration( |
||||
labelText: l10n.flutterSecureStorageFieldKey, |
||||
), |
||||
onChanged: (_) => _validateSave(), |
||||
), |
||||
const SizedBox(height: 16), |
||||
TextField( |
||||
controller: _valueSaveController, |
||||
decoration: InputDecoration( |
||||
labelText: l10n.flutterSecureStorageFieldValue, |
||||
), |
||||
onChanged: (_) => _validateSave(), |
||||
), |
||||
const SizedBox(height: 20), |
||||
SizedBox( |
||||
width: double.infinity, |
||||
child: ElevatedButton( |
||||
onPressed: _isValidSave |
||||
? () => model.write( |
||||
key: _keySaveController.text, |
||||
value: _valueSaveController.text, |
||||
password: _passSaveController.text, |
||||
) |
||||
: null, |
||||
child: TextBodyLarge( |
||||
l10n.flutterSecureStorageBtnSave, |
||||
color: Colors.white, |
||||
), |
||||
), |
||||
), |
||||
const SizedBox(height: 30), |
||||
TextTitleLarge(l10n.flutterSecureStorageTitleGet), |
||||
const SizedBox(height: 16), |
||||
TextField( |
||||
controller: _passGetController, |
||||
decoration: InputDecoration( |
||||
labelText: l10n.flutterSecureStorageFieldPass, |
||||
), |
||||
onChanged: (_) { |
||||
_validateGet(); |
||||
model.clearReadValue(); |
||||
}, |
||||
), |
||||
const SizedBox(height: 16), |
||||
TextField( |
||||
controller: _keyGetController, |
||||
decoration: InputDecoration( |
||||
labelText: l10n.flutterSecureStorageFieldKey, |
||||
), |
||||
onChanged: (_) { |
||||
_validateGet(); |
||||
model.clearReadValue(); |
||||
}), |
||||
const SizedBox(height: 16), |
||||
TextField( |
||||
enabled: false, |
||||
readOnly: true, |
||||
controller: _valueGetController, |
||||
decoration: InputDecoration( |
||||
labelText: l10n.flutterSecureStorageFieldValue, |
||||
), |
||||
), |
||||
const SizedBox(height: 20), |
||||
SizedBox( |
||||
width: double.infinity, |
||||
child: ElevatedButton( |
||||
onPressed: _isValidGet |
||||
? () => model.read( |
||||
key: _keyGetController.text, |
||||
password: _passGetController.text, |
||||
) |
||||
: null, |
||||
child: TextBodyLarge( |
||||
l10n.flutterSecureStorageBtnGet, |
||||
color: Colors.white, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |