commit 41acad6275971c401caea65cf7a741c5b2159057 Author: Taha Saad Date: Mon Sep 11 15:11:35 2023 +0300 add project structure diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0fa6b67 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..fe11f50 --- /dev/null +++ b/.metadata @@ -0,0 +1,45 @@ +# 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: 2ad6cd72c040113b47ee9055e722606a490ef0da + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + base_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + - platform: android + create_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + base_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + - platform: ios + create_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + base_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + - platform: linux + create_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + base_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + - platform: macos + create_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + base_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + - platform: web + create_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + base_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + - platform: windows + create_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + base_revision: 2ad6cd72c040113b47ee9055e722606a490ef0da + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..03eb7e8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "snonoconnect", + "request": "launch", + "type": "dart" + }, + { + "name": "snonoconnect (profile mode)", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "snonoconnect (release mode)", + "request": "launch", + "type": "dart", + "flutterMode": "release" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6e15e87 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true + }, + "hide-files.files": [], + "cmake.sourceDirectory": "/Users/snonosystems/development/fiberx/linux" +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..850ec84 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# sas4 + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..4689fc3 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,85 @@ +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 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: 'com.google.gms.google-services' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + + def keystoreProperties = new Properties() + def keystorePropertiesFile = rootProject.file('key.properties') + if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + } + +android { + compileSdkVersion 33 + 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 { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.snonoapps.iq" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion 19 + targetSdkVersion flutter.targetSdkVersion + versionCode 1 + versionName flutterVersionName + } + + signingConfigs { + release { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + } + buildTypes { + release { + signingConfig signingConfigs.release + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation platform('com.google.firebase:firebase-bom:31.2.0') + implementation 'com.google.firebase:firebase-analytics-ktx' +} diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..1c840a6 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,39 @@ +{ + "project_info": { + "project_number": "386498163901", + "project_id": "fiberx-33e52", + "storage_bucket": "fiberx-33e52.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:386498163901:android:8a8fcc8a5c22b6688773d4", + "android_client_info": { + "package_name": "com.snonosystems.fiberx" + } + }, + "oauth_client": [ + { + "client_id": "386498163901-re4k28ohjdoqei4b8kvc4tca6cvuh13v.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCIaBD9mJCGVSoDbZpYBkz5f0V9qQBy8w0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "386498163901-re4k28ohjdoqei4b8kvc4tca6cvuh13v.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..f0fffb4 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..5da1a38 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/snonoapps/iq/MainActivity.kt b/android/app/src/main/kotlin/com/snonoapps/iq/MainActivity.kt new file mode 100644 index 0000000..73f6900 --- /dev/null +++ b/android/app/src/main/kotlin/com/snonoapps/iq/MainActivity.kt @@ -0,0 +1,6 @@ +package com.snonoapps.iq + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-hdpi/android12splash.png b/android/app/src/main/res/drawable-hdpi/android12splash.png new file mode 100644 index 0000000..8c838b0 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-hdpi/splash.png b/android/app/src/main/res/drawable-hdpi/splash.png new file mode 100644 index 0000000..8c838b0 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-mdpi/android12splash.png b/android/app/src/main/res/drawable-mdpi/android12splash.png new file mode 100644 index 0000000..f7925a2 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-mdpi/splash.png b/android/app/src/main/res/drawable-mdpi/splash.png new file mode 100644 index 0000000..f7925a2 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-night-hdpi/android12splash.png b/android/app/src/main/res/drawable-night-hdpi/android12splash.png new file mode 100644 index 0000000..8c838b0 Binary files /dev/null and b/android/app/src/main/res/drawable-night-hdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-mdpi/android12splash.png b/android/app/src/main/res/drawable-night-mdpi/android12splash.png new file mode 100644 index 0000000..f7925a2 Binary files /dev/null and b/android/app/src/main/res/drawable-night-mdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-xhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xhdpi/android12splash.png new file mode 100644 index 0000000..240e8b5 Binary files /dev/null and b/android/app/src/main/res/drawable-night-xhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png new file mode 100644 index 0000000..f806779 Binary files /dev/null and b/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png new file mode 100644 index 0000000..4ecf2c8 Binary files /dev/null and b/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-v21/background.png b/android/app/src/main/res/drawable-v21/background.png new file mode 100644 index 0000000..b980fdc Binary files /dev/null and b/android/app/src/main/res/drawable-v21/background.png differ diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..3cc4948 --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/android/app/src/main/res/drawable-xhdpi/android12splash.png b/android/app/src/main/res/drawable-xhdpi/android12splash.png new file mode 100644 index 0000000..240e8b5 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/splash.png b/android/app/src/main/res/drawable-xhdpi/splash.png new file mode 100644 index 0000000..240e8b5 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/android12splash.png b/android/app/src/main/res/drawable-xxhdpi/android12splash.png new file mode 100644 index 0000000..f806779 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/splash.png b/android/app/src/main/res/drawable-xxhdpi/splash.png new file mode 100644 index 0000000..f806779 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/android12splash.png b/android/app/src/main/res/drawable-xxxhdpi/android12splash.png new file mode 100644 index 0000000..4ecf2c8 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/splash.png b/android/app/src/main/res/drawable-xxxhdpi/splash.png new file mode 100644 index 0000000..4ecf2c8 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable/background.png b/android/app/src/main/res/drawable/background.png new file mode 100644 index 0000000..b980fdc Binary files /dev/null and b/android/app/src/main/res/drawable/background.png differ diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..3cc4948 --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png new file mode 100644 index 0000000..4f10ff6 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/launcher_icon.png b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png new file mode 100644 index 0000000..010ffc6 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png new file mode 100644 index 0000000..cca8dd0 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png new file mode 100644 index 0000000..c121320 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png new file mode 100644 index 0000000..8fbddd6 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/values-night-v31/styles.xml b/android/app/src/main/res/values-night-v31/styles.xml new file mode 100644 index 0000000..8a36c87 --- /dev/null +++ b/android/app/src/main/res/values-night-v31/styles.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..3c4a1fe --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/android/app/src/main/res/values-v31/styles.xml b/android/app/src/main/res/values-v31/styles.xml new file mode 100644 index 0000000..f36a093 --- /dev/null +++ b/android/app/src/main/res/values-v31/styles.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..847e1be --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..f0fffb4 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..a2171a4 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.8.0' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.2.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + // classpath 'com.google.gms:google-services:4.3.15' + + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3c472b9 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/assets/1/icon.svg b/assets/1/icon.svg new file mode 100644 index 0000000..dfb6059 --- /dev/null +++ b/assets/1/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/2/icon.png b/assets/2/icon.png new file mode 100644 index 0000000..0c78a09 Binary files /dev/null and b/assets/2/icon.png differ diff --git a/assets/2/icon.svg b/assets/2/icon.svg new file mode 100644 index 0000000..923e4c4 --- /dev/null +++ b/assets/2/icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/2/icon11.png b/assets/2/icon11.png new file mode 100644 index 0000000..007afbd Binary files /dev/null and b/assets/2/icon11.png differ diff --git a/assets/animated_autologin.json b/assets/animated_autologin.json new file mode 100644 index 0000000..432177a --- /dev/null +++ b/assets/animated_autologin.json @@ -0,0 +1 @@ +{"v":"5.5.7","meta":{"g":"LottieFiles AE 0.1.20","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":610,"w":128,"h":128,"nm":"GPS Radar - 128 Pixels Slowed Down (RS 2) ","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Line Globe - Curved Lines 6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":490,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":550,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":610,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":670,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":489,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":490,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":670,"s":[100]},{"t":671,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":550,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":610,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,28],[-14.667,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":670,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,28],[14.667,0],[0,-28]],"c":false}]},{"t":730,"s":[{"i":[[0,0],[-0.053,21.2],[7.28,-0.96]],"o":[[7.28,0.92],[0.054,-21.32],[0,0]],"v":[[0,28],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":549,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":550,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":730,"s":[100]},{"t":731,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":488,"op":731,"st":488,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Line Globe - Curved Lines 5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":368,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":428,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":488,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":548,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":367,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":368,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":548,"s":[100]},{"t":549,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":428,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":488,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,28],[-14.667,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":548,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,28],[14.667,0],[0,-28]],"c":false}]},{"t":608,"s":[{"i":[[0,0],[-0.053,21.2],[7.28,-0.96]],"o":[[7.28,0.92],[0.054,-21.32],[0,0]],"v":[[0,28],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":427,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":428,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":608,"s":[100]},{"t":609,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":366,"op":609,"st":366,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Line Globe - Curved Lines 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":246,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":306,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":366,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":426,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":245,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":246,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":426,"s":[100]},{"t":427,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":306,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":366,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,28],[-14.667,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":426,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,28],[14.667,0],[0,-28]],"c":false}]},{"t":486,"s":[{"i":[[0,0],[-0.053,21.2],[7.28,-0.96]],"o":[[7.28,0.92],[0.054,-21.32],[0,0]],"v":[[0,28],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":305,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":306,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":486,"s":[100]},{"t":487,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":244,"op":487,"st":244,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Line Globe - Curved Lines 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":124,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":184,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":244,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":304,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":123,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":124,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":304,"s":[100]},{"t":305,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":184,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":244,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,28],[-14.667,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":304,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,28],[14.667,0],[0,-28]],"c":false}]},{"t":364,"s":[{"i":[[0,0],[-0.053,21.2],[7.28,-0.96]],"o":[[7.28,0.92],[0.054,-21.32],[0,0]],"v":[[0,28],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":183,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":184,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":364,"s":[100]},{"t":365,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":122,"op":365,"st":122,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Line Globe - Curved Lines 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":62,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":122,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":182,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":182,"s":[100]},{"t":183,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":62,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":122,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,28],[-14.667,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":182,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,28],[14.667,0],[0,-28]],"c":false}]},{"t":242,"s":[{"i":[[0,0],[-0.053,21.2],[7.28,-0.96]],"o":[[7.28,0.92],[0.054,-21.32],[0,0]],"v":[[0,28],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":61,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":62,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":242,"s":[100]},{"t":243,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":243,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Line Globe - Curved Lines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":62,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":122,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":123,"s":[100]},{"t":124,"s":[23]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":62,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":62,"s":[100]},{"t":63,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":124,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Line Globe - Base","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[24,-14.667],[0,-14.667],[-24,-14.667]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top Line","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[24,14.667],[0,14.667],[-24,14.667]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom Line","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[28,0],[-28,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Middle Line","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,15.464],[15.464,0],[0,-15.464],[-15.464,0]],"o":[[0,-15.464],[-15.464,0],[0,15.464],[15.464,0]],"v":[[28,0],[0,-28],[-28,0],[0,28]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Circle Body","np":2,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":620,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Satellite SIgnal","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-3.264,0],[-1.826,-2.431]],"o":[[1.826,-2.427],[3.267,0],[0,0]],"v":[[-7.995,38],[0,34],[8,38.007]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10.031,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30.098,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":42.137,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":62.203,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":88.289,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108.357,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120.393,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":140.461,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":166.547,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":186.613,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":198.652,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":218.719,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":244.801,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":264.869,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":276.906,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":296.973,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":323.057,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":343.125,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":355.164,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":375.232,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":401.318,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":421.381,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":433.422,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":453.488,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":479.574,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":499.637,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":511.676,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":531.744,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":557.828,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":577.893,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":589.932,"s":[100]},{"t":610,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"2nd Signal","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.373,0],[-1.266,-1.812]],"o":[[1.266,-1.812],[2.373,0],[0,0]],"v":[[-5.741,40],[0,37],[5.741,40]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20.068,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":32.107,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":52.172,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":78.256,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":98.324,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":110.363,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":130.426,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156.512,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":176.578,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":188.619,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":208.682,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":234.768,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":254.836,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":266.875,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":286.943,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":313.027,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":333.094,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":345.131,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":365.199,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":391.281,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":411.348,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":423.387,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":443.453,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":469.539,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":489.607,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":501.643,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":521.711,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":547.797,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":567.863,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":579.902,"s":[100]},{"t":599.96875,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"1st Panel","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":620,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Dash & gap Line","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":610,"s":[360]}],"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":34,"nm":"Puppet","np":6,"mn":"ADBE FreePin3","ix":1,"en":1,"ef":[{"ty":7,"nm":"Puppet Engine","mn":"ADBE FreePin3 Puppet Engine","ix":1,"v":{"a":0,"k":2,"ix":1}},{"ty":0,"nm":"Mesh Rotation Refinement","mn":"ADBE FreePin3 Auto Rotate Pins","ix":2,"v":{"a":0,"k":20,"ix":2}},{"ty":7,"nm":"On Transparent","mn":"ADBE FreePin3 On Transparent","ix":3,"v":{"a":0,"k":0,"ix":3}},{"ty":60,"nm":"arap","np":3,"mn":"ADBE FreePin3 ARAP Group","ix":4,"en":1,"ef":[{"ty":6,"nm":"Auto-traced Shapes","mn":"ADBE FreePin3 Outlines","ix":1,"v":0},{"ty":1,"nm":"Mesh","np":1,"mn":"ADBE FreePin3 Mesh Group","ix":2,"en":1,"ef":[]}]}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.638,0.23],[0,0],[-2.657,-0.743]],"o":[[-2.538,-0.71],[0,0],[2.761,0.241],[0,0]],"v":[[11.58,-41.502],[3.78,-42.918],[3.954,-44.914],[12.118,-43.432]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.531,-0.732],[0,0],[-2.759,0.265],[0,0]],"o":[[0,0],[2.65,-0.766],[0,0],[-2.636,0.253]],"v":[[-11.938,-41.4],[-12.493,-43.325],[-4.341,-44.879],[-4.15,-42.884]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.367,1.169],[0,0],[-2.216,-1.663]],"o":[[-2.118,-1.588],[0,0],[2.478,1.224],[0,0]],"v":[[25.746,-34.51],[18.987,-38.666],[19.871,-40.463],[26.944,-36.114]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.104,-1.607],[0,0],[-2.466,1.245],[0,0]],"o":[[0,0],[2.202,-1.681],[0,0],[-2.356,1.189]],"v":[[-26.041,-34.287],[-27.252,-35.881],[-20.218,-40.289],[-19.319,-38.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.791,1.948],[0,0],[-1.47,-2.345]],"o":[[-1.404,-2.241],[0,0],[1.874,2.038],[0,0]],"v":[[36.447,-22.871],[31.632,-29.184],[33.103,-30.542],[38.142,-23.936]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":2,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.385,-2.253],[0,0],[-1.857,2.054],[0,0]],"o":[[0,0],[1.449,-2.358],[0,0],[-1.775,1.963]],"v":[[-36.642,-22.557],[-38.345,-23.608],[-33.362,-30.256],[-31.88,-28.911]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":2,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.968,2.462],[0,0],[-0.52,-2.721]],"o":[[-0.497,-2.599],[0,0],[1.013,2.577],[0,0]],"v":[[42.231,-8.156],[40.023,-15.783],[41.884,-16.518],[44.195,-8.533]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 7","np":2,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.475,-2.604],[0,0],[-0.991,2.586],[0,0]],"o":[[0,0],[0.497,-2.725],[0,0],[-0.946,2.471]],"v":[[-42.299,-7.789],[-44.267,-8.149],[-42.025,-16.154],[-40.158,-15.436]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 8","np":2,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.502,-2.709],[0,0],[0,2.66],[0,0],[0,0],[0,0]],"o":[[0,0],[0.48,-2.589],[0,0],[0,0],[0,0],[0,2.789]],"v":[[44.243,8.276],[42.276,7.91],[43,0],[42.999,-0.249],[44.999,-0.26],[45,-0.006]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 9","np":2,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.008,2.781],[0,0],[-0.487,-2.589]],"o":[[-0.51,-2.709],[0,0],[0.008,2.659],[0,0]],"v":[[-44.22,8.405],[-45,0.129],[-43,0.124],[-42.254,8.033]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 10","np":2,"cix":2,"bm":0,"ix":10,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.458,-2.358],[0,0],[-0.953,2.466],[0,0]],"o":[[0,0],[1.394,-2.252],[0,0],[-0.998,2.581]],"v":[[38.278,23.718],[36.578,22.661],[40.114,15.551],[41.979,16.275]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 11","np":2,"cix":2,"bm":0,"ix":11,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.004,2.577],[0,0],[-1.4,-2.248]],"o":[[-1.465,-2.354],[0,0],[0.959,2.462],[0,0]],"v":[[-38.209,23.826],[-41.931,16.395],[-40.068,15.667],[-36.512,22.766]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 12","np":2,"cix":2,"bm":0,"ix":12,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.203,-1.672],[0,0],[-1.78,1.959],[0,0]],"o":[[0,0],[2.105,-1.599],[0,0],[-1.863,2.048]],"v":[[27.149,35.959],[25.941,34.362],[31.797,29.002],[33.276,30.353]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 13","np":2,"cix":2,"bm":0,"ix":13,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.868,2.043],[0,0],[-2.11,-1.593]],"o":[[-2.208,-1.666],[0,0],[1.785,1.953],[0,0]],"v":[[-27.048,36.036],[-33.19,30.446],[-31.715,29.092],[-25.845,34.436]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 14","np":2,"cix":2,"bm":0,"ix":14,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.66,-0.761],[0,0],[-2.362,1.184],[0,0]],"o":[[0,0],[2.541,-0.727],[0,0],[-2.473,1.239]],"v":[[12.368,43.363],[11.819,41.435],[19.208,38.556],[20.103,40.348]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 15","np":1,"cix":2,"bm":0,"ix":15,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.478,1.234],[0,0],[-2.542,-0.717]],"o":[[-2.661,-0.752],[0,0],[2.368,1.179],[0,0]],"v":[[-12.243,43.397],[-19.988,40.404],[-19.098,38.609],[-11.7,41.467]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 16","np":1,"cix":2,"bm":0,"ix":16,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.404,0],[1.35,0.121],[0,0],[-2.618,0.244],[0,0]],"o":[[-1.359,0],[0,0],[2.623,0.236],[0,0],[-1.391,0.129]],"v":[[0,45.086],[-4.082,44.903],[-3.903,42.907],[4.027,42.895],[4.212,44.891]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 17","np":1,"cix":2,"bm":0,"ix":17,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":620,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Satellite - Rouded Square 2","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.105,0],[0,0],[0,1.105],[0,0],[-1.105,0],[0,0],[0,-1.105],[0,0]],"o":[[0,0],[-1.105,0],[0,0],[0,-1.105],[0,0],[1.105,0],[0,0],[0,1.105]],"v":[[-11,49],[-23,49],[-25,47],[-25,43],[-23,41],[-11,41],[-9,43],[-9,47]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-13,46],[-13,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-17,46],[-17,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-21,46],[-21,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.105,0],[0,0],[0,1.105],[0,0],[-1.105,0],[0,0],[0,-1.105],[0,0]],"o":[[0,0],[-1.105,0],[0,0],[0,-1.105],[0,0],[1.105,0],[0,0],[0,1.105]],"v":[[23,49],[11,49],[9,47],[9,43],[11,41],[23,41],[25,43],[25,47]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[21,46],[21,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[17,46],[17,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[13,46],[13,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4,45],[-9,45]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4,45],[9,45]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.105,0],[0,0],[0,-1.105],[0,0],[-1.105,0],[0,0],[0,1.105],[0,0]],"o":[[0,0],[-1.105,0],[0,0],[0,1.105],[0,0],[1.105,0],[0,0],[0,-1.105]],"v":[[2,41],[-2,41],[-4,43],[-4,47],[-2,49],[2,49],[4,47],[4,43]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":620,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":3,"nm":"Dashed Line","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":610,"s":[360]}],"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":620,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/assets/animated_autologin1.json b/assets/animated_autologin1.json new file mode 100644 index 0000000..e72e747 --- /dev/null +++ b/assets/animated_autologin1.json @@ -0,0 +1 @@ +{"v":"5.5.7","meta":{"g":"LottieFiles AE 0.1.20","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":610,"w":128,"h":128,"nm":"GPS Radar - 128 Pixels Slowed Down (RS 2) ","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Line Globe - Curved Lines 6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":490,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":550,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":610,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":670,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":489,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":490,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":670,"s":[100]},{"t":671,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":550,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":610,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,28],[-14.667,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":670,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,28],[14.667,0],[0,-28]],"c":false}]},{"t":730,"s":[{"i":[[0,0],[-0.053,21.2],[7.28,-0.96]],"o":[[7.28,0.92],[0.054,-21.32],[0,0]],"v":[[0,28],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":549,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":550,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":730,"s":[100]},{"t":731,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":488,"op":731,"st":488,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Line Globe - Curved Lines 5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":368,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":428,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":488,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":548,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":367,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":368,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":548,"s":[100]},{"t":549,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":428,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":488,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,28],[-14.667,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":548,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,28],[14.667,0],[0,-28]],"c":false}]},{"t":608,"s":[{"i":[[0,0],[-0.053,21.2],[7.28,-0.96]],"o":[[7.28,0.92],[0.054,-21.32],[0,0]],"v":[[0,28],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":427,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":428,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":608,"s":[100]},{"t":609,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":366,"op":609,"st":366,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Line Globe - Curved Lines 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":246,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":306,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":366,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":426,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":245,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":246,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":426,"s":[100]},{"t":427,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":306,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":366,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,28],[-14.667,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":426,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,28],[14.667,0],[0,-28]],"c":false}]},{"t":486,"s":[{"i":[[0,0],[-0.053,21.2],[7.28,-0.96]],"o":[[7.28,0.92],[0.054,-21.32],[0,0]],"v":[[0,28],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":305,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":306,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":486,"s":[100]},{"t":487,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":244,"op":487,"st":244,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Line Globe - Curved Lines 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":124,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":184,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":244,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":304,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":123,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":124,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":304,"s":[100]},{"t":305,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":184,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":244,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,28],[-14.667,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":304,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,28],[14.667,0],[0,-28]],"c":false}]},{"t":364,"s":[{"i":[[0,0],[-0.053,21.2],[7.28,-0.96]],"o":[[7.28,0.92],[0.054,-21.32],[0,0]],"v":[[0,28],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":183,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":184,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":364,"s":[100]},{"t":365,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":122,"op":365,"st":122,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Line Globe - Curved Lines 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":62,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":122,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":182,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":182,"s":[100]},{"t":183,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":62,"s":[{"i":[[0,0],[0,15.75],[-15.2,0]],"o":[[-15.2,0],[0,-15.765],[0,0]],"v":[[0,28],[-28.022,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":122,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,28],[-14.667,0],[0,-28]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":182,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,28],[14.667,0],[0,-28]],"c":false}]},{"t":242,"s":[{"i":[[0,0],[-0.053,21.2],[7.28,-0.96]],"o":[[7.28,0.92],[0.054,-21.32],[0,0]],"v":[[0,28],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":61,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":62,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":242,"s":[100]},{"t":243,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":243,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Line Globe - Curved Lines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[{"i":[[0,0],[0,19],[-1.36,0.88]],"o":[[-1.64,-1],[0,-19.08],[0,0]],"v":[[0,27.912],[-13.067,0],[0,-27.848]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":62,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":122,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":123,"s":[100]},{"t":124,"s":[23]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[{"i":[[0,0],[0,19.44],[1.08,0.68]],"o":[[1.36,-0.84],[0,-19.48],[0,0]],"v":[[0,27.912],[13.467,0],[0,-27.82]],"c":false}]},{"t":62,"s":[{"i":[[0,0],[-0.053,15.76],[15.16,0]],"o":[[15.16,0],[0.053,-15.76],[0,0]],"v":[[0,27.995],[28.048,0],[0,-28]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":62,"s":[100]},{"t":63,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Line 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":124,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Line Globe - Base","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[24,-14.667],[0,-14.667],[-24,-14.667]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top Line","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[24,14.667],[0,14.667],[-24,14.667]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom Line","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[28,0],[-28,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Middle Line","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,15.464],[15.464,0],[0,-15.464],[-15.464,0]],"o":[[0,-15.464],[-15.464,0],[0,15.464],[15.464,0]],"v":[[28,0],[0,-28],[-28,0],[0,28]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Circle Body","np":2,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":620,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Satellite SIgnal","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-3.264,0],[-1.826,-2.431]],"o":[[1.826,-2.427],[3.267,0],[0,0]],"v":[[-7.995,38],[0,34],[8,38.007]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10.031,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30.098,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":42.137,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":62.203,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":88.289,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108.357,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120.393,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":140.461,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":166.547,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":186.613,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":198.652,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":218.719,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":244.801,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":264.869,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":276.906,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":296.973,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":323.057,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":343.125,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":355.164,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":375.232,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":401.318,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":421.381,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":433.422,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":453.488,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":479.574,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":499.637,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":511.676,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":531.744,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":557.828,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":577.893,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":589.932,"s":[100]},{"t":610,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"2nd Signal","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.373,0],[-1.266,-1.812]],"o":[[1.266,-1.812],[2.373,0],[0,0]],"v":[[-5.741,40],[0,37],[5.741,40]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20.068,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":32.107,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":52.172,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":78.256,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":98.324,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":110.363,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":130.426,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156.512,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":176.578,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":188.619,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":208.682,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":234.768,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":254.836,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":266.875,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":286.943,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":313.027,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":333.094,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":345.131,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":365.199,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":391.281,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":411.348,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":423.387,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":443.453,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":469.539,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":489.607,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":501.643,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":521.711,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":547.797,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":567.863,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":579.902,"s":[100]},{"t":599.96875,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"1st Panel","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":620,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Dash & gap Line","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":610,"s":[360]}],"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ef":[{"ty":34,"nm":"Puppet","np":6,"mn":"ADBE FreePin3","ix":1,"en":1,"ef":[{"ty":7,"nm":"Puppet Engine","mn":"ADBE FreePin3 Puppet Engine","ix":1,"v":{"a":0,"k":2,"ix":1}},{"ty":0,"nm":"Mesh Rotation Refinement","mn":"ADBE FreePin3 Auto Rotate Pins","ix":2,"v":{"a":0,"k":20,"ix":2}},{"ty":7,"nm":"On Transparent","mn":"ADBE FreePin3 On Transparent","ix":3,"v":{"a":0,"k":0,"ix":3}},{"ty":60,"nm":"arap","np":3,"mn":"ADBE FreePin3 ARAP Group","ix":4,"en":1,"ef":[{"ty":6,"nm":"Auto-traced Shapes","mn":"ADBE FreePin3 Outlines","ix":1,"v":0},{"ty":1,"nm":"Mesh","np":1,"mn":"ADBE FreePin3 Mesh Group","ix":2,"en":1,"ef":[]}]}]}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.638,0.23],[0,0],[-2.657,-0.743]],"o":[[-2.538,-0.71],[0,0],[2.761,0.241],[0,0]],"v":[[11.58,-41.502],[3.78,-42.918],[3.954,-44.914],[12.118,-43.432]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.531,-0.732],[0,0],[-2.759,0.265],[0,0]],"o":[[0,0],[2.65,-0.766],[0,0],[-2.636,0.253]],"v":[[-11.938,-41.4],[-12.493,-43.325],[-4.341,-44.879],[-4.15,-42.884]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.367,1.169],[0,0],[-2.216,-1.663]],"o":[[-2.118,-1.588],[0,0],[2.478,1.224],[0,0]],"v":[[25.746,-34.51],[18.987,-38.666],[19.871,-40.463],[26.944,-36.114]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.104,-1.607],[0,0],[-2.466,1.245],[0,0]],"o":[[0,0],[2.202,-1.681],[0,0],[-2.356,1.189]],"v":[[-26.041,-34.287],[-27.252,-35.881],[-20.218,-40.289],[-19.319,-38.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.791,1.948],[0,0],[-1.47,-2.345]],"o":[[-1.404,-2.241],[0,0],[1.874,2.038],[0,0]],"v":[[36.447,-22.871],[31.632,-29.184],[33.103,-30.542],[38.142,-23.936]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":2,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.385,-2.253],[0,0],[-1.857,2.054],[0,0]],"o":[[0,0],[1.449,-2.358],[0,0],[-1.775,1.963]],"v":[[-36.642,-22.557],[-38.345,-23.608],[-33.362,-30.256],[-31.88,-28.911]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":2,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.968,2.462],[0,0],[-0.52,-2.721]],"o":[[-0.497,-2.599],[0,0],[1.013,2.577],[0,0]],"v":[[42.231,-8.156],[40.023,-15.783],[41.884,-16.518],[44.195,-8.533]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 7","np":2,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.475,-2.604],[0,0],[-0.991,2.586],[0,0]],"o":[[0,0],[0.497,-2.725],[0,0],[-0.946,2.471]],"v":[[-42.299,-7.789],[-44.267,-8.149],[-42.025,-16.154],[-40.158,-15.436]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 8","np":2,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.502,-2.709],[0,0],[0,2.66],[0,0],[0,0],[0,0]],"o":[[0,0],[0.48,-2.589],[0,0],[0,0],[0,0],[0,2.789]],"v":[[44.243,8.276],[42.276,7.91],[43,0],[42.999,-0.249],[44.999,-0.26],[45,-0.006]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 9","np":2,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.008,2.781],[0,0],[-0.487,-2.589]],"o":[[-0.51,-2.709],[0,0],[0.008,2.659],[0,0]],"v":[[-44.22,8.405],[-45,0.129],[-43,0.124],[-42.254,8.033]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 10","np":2,"cix":2,"bm":0,"ix":10,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.458,-2.358],[0,0],[-0.953,2.466],[0,0]],"o":[[0,0],[1.394,-2.252],[0,0],[-0.998,2.581]],"v":[[38.278,23.718],[36.578,22.661],[40.114,15.551],[41.979,16.275]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 11","np":2,"cix":2,"bm":0,"ix":11,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.004,2.577],[0,0],[-1.4,-2.248]],"o":[[-1.465,-2.354],[0,0],[0.959,2.462],[0,0]],"v":[[-38.209,23.826],[-41.931,16.395],[-40.068,15.667],[-36.512,22.766]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 12","np":2,"cix":2,"bm":0,"ix":12,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.203,-1.672],[0,0],[-1.78,1.959],[0,0]],"o":[[0,0],[2.105,-1.599],[0,0],[-1.863,2.048]],"v":[[27.149,35.959],[25.941,34.362],[31.797,29.002],[33.276,30.353]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 13","np":2,"cix":2,"bm":0,"ix":13,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.868,2.043],[0,0],[-2.11,-1.593]],"o":[[-2.208,-1.666],[0,0],[1.785,1.953],[0,0]],"v":[[-27.048,36.036],[-33.19,30.446],[-31.715,29.092],[-25.845,34.436]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 14","np":2,"cix":2,"bm":0,"ix":14,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.66,-0.761],[0,0],[-2.362,1.184],[0,0]],"o":[[0,0],[2.541,-0.727],[0,0],[-2.473,1.239]],"v":[[12.368,43.363],[11.819,41.435],[19.208,38.556],[20.103,40.348]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 15","np":1,"cix":2,"bm":0,"ix":15,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.478,1.234],[0,0],[-2.542,-0.717]],"o":[[-2.661,-0.752],[0,0],[2.368,1.179],[0,0]],"v":[[-12.243,43.397],[-19.988,40.404],[-19.098,38.609],[-11.7,41.467]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 16","np":1,"cix":2,"bm":0,"ix":16,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.404,0],[1.35,0.121],[0,0],[-2.618,0.244],[0,0]],"o":[[-1.359,0],[0,0],[2.623,0.236],[0,0],[-1.391,0.129]],"v":[[0,45.086],[-4.082,44.903],[-3.903,42.907],[4.027,42.895],[4.212,44.891]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 17","np":1,"cix":2,"bm":0,"ix":17,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":620,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Satellite - Rouded Square 2","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.105,0],[0,0],[0,1.105],[0,0],[-1.105,0],[0,0],[0,-1.105],[0,0]],"o":[[0,0],[-1.105,0],[0,0],[0,-1.105],[0,0],[1.105,0],[0,0],[0,1.105]],"v":[[-11,49],[-23,49],[-25,47],[-25,43],[-23,41],[-11,41],[-9,43],[-9,47]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-13,46],[-13,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-17,46],[-17,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-21,46],[-21,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.105,0],[0,0],[0,1.105],[0,0],[-1.105,0],[0,0],[0,-1.105],[0,0]],"o":[[0,0],[-1.105,0],[0,0],[0,-1.105],[0,0],[1.105,0],[0,0],[0,1.105]],"v":[[23,49],[11,49],[9,47],[9,43],[11,41],[23,41],[25,43],[25,47]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[21,46],[21,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[17,46],[17,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[13,46],[13,44]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4,45],[-9,45]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4,45],[9,45]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.105,0],[0,0],[0,-1.105],[0,0],[-1.105,0],[0,0],[0,1.105],[0,0]],"o":[[0,0],[-1.105,0],[0,0],[0,1.105],[0,0],[1.105,0],[0,0],[0,-1.105]],"v":[[2,41],[-2,41],[-4,43],[-4,47],[-2,49],[2,49],[4,47],[4,43]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":620,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":3,"nm":"Dashed Line","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":610,"s":[360]}],"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":620,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/assets/app_icon/1.png b/assets/app_icon/1.png new file mode 100644 index 0000000..d70d6e7 Binary files /dev/null and b/assets/app_icon/1.png differ diff --git a/assets/app_icon/ic_launcherplay 3.png b/assets/app_icon/ic_launcherplay 3.png new file mode 100644 index 0000000..1b69b9e Binary files /dev/null and b/assets/app_icon/ic_launcherplay 3.png differ diff --git a/assets/autologin_fail.svg b/assets/autologin_fail.svg new file mode 100644 index 0000000..a1bcbd6 --- /dev/null +++ b/assets/autologin_fail.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/autologin_loading.svg b/assets/autologin_loading.svg new file mode 100644 index 0000000..ec7b657 --- /dev/null +++ b/assets/autologin_loading.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/background.png b/assets/background.png new file mode 100644 index 0000000..b4e213f Binary files /dev/null and b/assets/background.png differ diff --git a/assets/background.svg b/assets/background.svg new file mode 100644 index 0000000..e3804a2 --- /dev/null +++ b/assets/background.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/d/connectivity.png b/assets/d/connectivity.png new file mode 100644 index 0000000..9307b76 Binary files /dev/null and b/assets/d/connectivity.png differ diff --git a/assets/d/connectivity.svg b/assets/d/connectivity.svg new file mode 100644 index 0000000..6879dd7 --- /dev/null +++ b/assets/d/connectivity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/dataflow.svg b/assets/dataflow.svg new file mode 100644 index 0000000..94a26c7 --- /dev/null +++ b/assets/dataflow.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/dot.png b/assets/dot.png new file mode 100644 index 0000000..341134d Binary files /dev/null and b/assets/dot.png differ diff --git a/assets/drawer icons/icon1.svg b/assets/drawer icons/icon1.svg new file mode 100644 index 0000000..62800e7 --- /dev/null +++ b/assets/drawer icons/icon1.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/drawer icons/icon2.svg b/assets/drawer icons/icon2.svg new file mode 100644 index 0000000..7daffeb --- /dev/null +++ b/assets/drawer icons/icon2.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/drawer icons/icon3.svg b/assets/drawer icons/icon3.svg new file mode 100644 index 0000000..a38f989 --- /dev/null +++ b/assets/drawer icons/icon3.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/drawer icons/icon4.svg b/assets/drawer icons/icon4.svg new file mode 100644 index 0000000..bcc54fb --- /dev/null +++ b/assets/drawer icons/icon4.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/drawer icons/icon5.svg b/assets/drawer icons/icon5.svg new file mode 100644 index 0000000..41b9358 --- /dev/null +++ b/assets/drawer icons/icon5.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/drawer icons/icon6.svg b/assets/drawer icons/icon6.svg new file mode 100644 index 0000000..f11f83e --- /dev/null +++ b/assets/drawer icons/icon6.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/drawer icons/icon7.svg b/assets/drawer icons/icon7.svg new file mode 100644 index 0000000..d052c79 --- /dev/null +++ b/assets/drawer icons/icon7.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/drawer icons/icon8.svg b/assets/drawer icons/icon8.svg new file mode 100644 index 0000000..475ef9f --- /dev/null +++ b/assets/drawer icons/icon8.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/email.svg b/assets/email.svg new file mode 100644 index 0000000..a1b7734 --- /dev/null +++ b/assets/email.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/email_box.svg b/assets/email_box.svg new file mode 100644 index 0000000..f25e999 --- /dev/null +++ b/assets/email_box.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/entered_name_icon.png b/assets/entered_name_icon.png new file mode 100644 index 0000000..23c967d Binary files /dev/null and b/assets/entered_name_icon.png differ diff --git a/assets/facebook.svg b/assets/facebook.svg new file mode 100644 index 0000000..e793947 --- /dev/null +++ b/assets/facebook.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/filter.svg b/assets/filter.svg new file mode 100644 index 0000000..33ebce3 --- /dev/null +++ b/assets/filter.svg @@ -0,0 +1,2 @@ + + diff --git a/assets/global.svg b/assets/global.svg new file mode 100644 index 0000000..0572667 --- /dev/null +++ b/assets/global.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/headphone.svg b/assets/headphone.svg new file mode 100644 index 0000000..0b99a9d --- /dev/null +++ b/assets/headphone.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/help_icon.png b/assets/help_icon.png new file mode 100644 index 0000000..41f7751 Binary files /dev/null and b/assets/help_icon.png differ diff --git a/assets/help_icon.svg b/assets/help_icon.svg new file mode 100644 index 0000000..83b1582 --- /dev/null +++ b/assets/help_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/home_icons/active.svg b/assets/home_icons/active.svg new file mode 100644 index 0000000..f23b702 --- /dev/null +++ b/assets/home_icons/active.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/home_icons/connected.svg b/assets/home_icons/connected.svg new file mode 100644 index 0000000..d45f67f --- /dev/null +++ b/assets/home_icons/connected.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/home_icons/disconnected.svg b/assets/home_icons/disconnected.svg new file mode 100644 index 0000000..5839539 --- /dev/null +++ b/assets/home_icons/disconnected.svg @@ -0,0 +1,17 @@ + + + + Group + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/home_icons/remaining_days.svg b/assets/home_icons/remaining_days.svg new file mode 100644 index 0000000..538c21b --- /dev/null +++ b/assets/home_icons/remaining_days.svg @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/assets/home_icons/unactive.svg b/assets/home_icons/unactive.svg new file mode 100644 index 0000000..98acd96 --- /dev/null +++ b/assets/home_icons/unactive.svg @@ -0,0 +1,488 @@ + + + + + + + + + + diff --git a/assets/icon.svg b/assets/icon.svg new file mode 100644 index 0000000..dfb6059 --- /dev/null +++ b/assets/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/image1.png b/assets/image1.png new file mode 100644 index 0000000..718b5bd Binary files /dev/null and b/assets/image1.png differ diff --git a/assets/image2.jpg b/assets/image2.jpg new file mode 100644 index 0000000..84345f5 Binary files /dev/null and b/assets/image2.jpg differ diff --git a/assets/info-circle.svg b/assets/info-circle.svg new file mode 100644 index 0000000..e879b91 --- /dev/null +++ b/assets/info-circle.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/instagram.svg b/assets/instagram.svg new file mode 100644 index 0000000..96ca7a1 --- /dev/null +++ b/assets/instagram.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/instgram.svg b/assets/instgram.svg new file mode 100644 index 0000000..a7bf9d2 --- /dev/null +++ b/assets/instgram.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/isp.json b/assets/isp.json new file mode 100644 index 0000000..55a9979 --- /dev/null +++ b/assets/isp.json @@ -0,0 +1,20 @@ +{ + "status": 200, + "data": [ + { + "id": 4, + "name": "HRINS", + "server_address": "sas.hrins.net" + }, + { + "id": 5, + "name": "Halasat", + "server_address": "192.168.255.254" + }, + { + "id": 6, + "name": "Halasat FTTH", + "server_address": "10.80.10.36" + } + ] +} \ No newline at end of file diff --git a/assets/left-arrow.svg b/assets/left-arrow.svg new file mode 100644 index 0000000..cb7a4eb --- /dev/null +++ b/assets/left-arrow.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/linkedin.svg b/assets/linkedin.svg new file mode 100644 index 0000000..208204a --- /dev/null +++ b/assets/linkedin.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000..39e8db2 Binary files /dev/null and b/assets/logo.png differ diff --git a/assets/next.svg b/assets/next.svg new file mode 100644 index 0000000..5018b2f --- /dev/null +++ b/assets/next.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/notifications.svg b/assets/notifications.svg new file mode 100644 index 0000000..a3d1987 --- /dev/null +++ b/assets/notifications.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/notifs.svg b/assets/notifs.svg new file mode 100644 index 0000000..10c9681 --- /dev/null +++ b/assets/notifs.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/package.svg b/assets/package.svg new file mode 100644 index 0000000..a38f989 --- /dev/null +++ b/assets/package.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/password_icon.png b/assets/password_icon.png new file mode 100644 index 0000000..47a3555 Binary files /dev/null and b/assets/password_icon.png differ diff --git a/assets/placeholder.png b/assets/placeholder.png new file mode 100644 index 0000000..fb1c7f2 Binary files /dev/null and b/assets/placeholder.png differ diff --git a/assets/remove.svg b/assets/remove.svg new file mode 100644 index 0000000..36f2ad7 --- /dev/null +++ b/assets/remove.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/sms.svg b/assets/sms.svg new file mode 100644 index 0000000..36547f7 --- /dev/null +++ b/assets/sms.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/speedometer.svg b/assets/speedometer.svg new file mode 100644 index 0000000..c32e5ab --- /dev/null +++ b/assets/speedometer.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/success_fill.svg b/assets/success_fill.svg new file mode 100644 index 0000000..33bebd8 --- /dev/null +++ b/assets/success_fill.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/assets/support_float.svg b/assets/support_float.svg new file mode 100644 index 0000000..7b6700e --- /dev/null +++ b/assets/support_float.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/support_icon.svg b/assets/support_icon.svg new file mode 100644 index 0000000..72aeaa6 --- /dev/null +++ b/assets/support_icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/trafic.svg b/assets/trafic.svg new file mode 100644 index 0000000..7daffeb --- /dev/null +++ b/assets/trafic.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/wireless-router.png b/assets/wireless-router.png new file mode 100644 index 0000000..de683d7 Binary files /dev/null and b/assets/wireless-router.png differ diff --git a/assets/wireless-router.svg b/assets/wireless-router.svg new file mode 100644 index 0000000..111e307 --- /dev/null +++ b/assets/wireless-router.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/youtube.svg b/assets/youtube.svg new file mode 100644 index 0000000..0868ac9 --- /dev/null +++ b/assets/youtube.svg @@ -0,0 +1,4 @@ + + + + diff --git a/fonts/Inter/Inter-Black.ttf b/fonts/Inter/Inter-Black.ttf new file mode 100644 index 0000000..3774270 Binary files /dev/null and b/fonts/Inter/Inter-Black.ttf differ diff --git a/fonts/Inter/Inter-Bold.ttf b/fonts/Inter/Inter-Bold.ttf new file mode 100644 index 0000000..76a215c Binary files /dev/null and b/fonts/Inter/Inter-Bold.ttf differ diff --git a/fonts/Inter/Inter-ExtraBold.ttf b/fonts/Inter/Inter-ExtraBold.ttf new file mode 100644 index 0000000..7ae3a4e Binary files /dev/null and b/fonts/Inter/Inter-ExtraBold.ttf differ diff --git a/fonts/Inter/Inter-ExtraLight.ttf b/fonts/Inter/Inter-ExtraLight.ttf new file mode 100644 index 0000000..131929e Binary files /dev/null and b/fonts/Inter/Inter-ExtraLight.ttf differ diff --git a/fonts/Inter/Inter-Light.ttf b/fonts/Inter/Inter-Light.ttf new file mode 100644 index 0000000..b9c460d Binary files /dev/null and b/fonts/Inter/Inter-Light.ttf differ diff --git a/fonts/Inter/Inter-Medium.ttf b/fonts/Inter/Inter-Medium.ttf new file mode 100644 index 0000000..06ae9e9 Binary files /dev/null and b/fonts/Inter/Inter-Medium.ttf differ diff --git a/fonts/Inter/Inter-Regular.ttf b/fonts/Inter/Inter-Regular.ttf new file mode 100644 index 0000000..cc73944 Binary files /dev/null and b/fonts/Inter/Inter-Regular.ttf differ diff --git a/fonts/Inter/Inter-SemiBold.ttf b/fonts/Inter/Inter-SemiBold.ttf new file mode 100644 index 0000000..278ceaa Binary files /dev/null and b/fonts/Inter/Inter-SemiBold.ttf differ diff --git a/fonts/Inter/Inter-Thin.ttf b/fonts/Inter/Inter-Thin.ttf new file mode 100644 index 0000000..e12ed49 Binary files /dev/null and b/fonts/Inter/Inter-Thin.ttf differ diff --git a/fonts/MarkaziText/MarkaziText-Bold.ttf b/fonts/MarkaziText/MarkaziText-Bold.ttf new file mode 100644 index 0000000..f0f1417 Binary files /dev/null and b/fonts/MarkaziText/MarkaziText-Bold.ttf differ diff --git a/fonts/MarkaziText/MarkaziText-Medium.ttf b/fonts/MarkaziText/MarkaziText-Medium.ttf new file mode 100644 index 0000000..63cb1e0 Binary files /dev/null and b/fonts/MarkaziText/MarkaziText-Medium.ttf differ diff --git a/fonts/MarkaziText/MarkaziText-Regular.ttf b/fonts/MarkaziText/MarkaziText-Regular.ttf new file mode 100644 index 0000000..5915cc8 Binary files /dev/null and b/fonts/MarkaziText/MarkaziText-Regular.ttf differ diff --git a/fonts/MarkaziText/MarkaziText-SemiBold.ttf b/fonts/MarkaziText/MarkaziText-SemiBold.ttf new file mode 100644 index 0000000..e40ce01 Binary files /dev/null and b/fonts/MarkaziText/MarkaziText-SemiBold.ttf differ diff --git a/fonts/ReadexPro/ReadexPro-Bold.ttf b/fonts/ReadexPro/ReadexPro-Bold.ttf new file mode 100644 index 0000000..df8a387 Binary files /dev/null and b/fonts/ReadexPro/ReadexPro-Bold.ttf differ diff --git a/fonts/ReadexPro/ReadexPro-ExtraLight.ttf b/fonts/ReadexPro/ReadexPro-ExtraLight.ttf new file mode 100644 index 0000000..1130b4a Binary files /dev/null and b/fonts/ReadexPro/ReadexPro-ExtraLight.ttf differ diff --git a/fonts/ReadexPro/ReadexPro-Light.ttf b/fonts/ReadexPro/ReadexPro-Light.ttf new file mode 100644 index 0000000..99ff896 Binary files /dev/null and b/fonts/ReadexPro/ReadexPro-Light.ttf differ diff --git a/fonts/ReadexPro/ReadexPro-Medium.ttf b/fonts/ReadexPro/ReadexPro-Medium.ttf new file mode 100644 index 0000000..e9bd094 Binary files /dev/null and b/fonts/ReadexPro/ReadexPro-Medium.ttf differ diff --git a/fonts/ReadexPro/ReadexPro-Regular.ttf b/fonts/ReadexPro/ReadexPro-Regular.ttf new file mode 100644 index 0000000..58ca55e Binary files /dev/null and b/fonts/ReadexPro/ReadexPro-Regular.ttf differ diff --git a/fonts/ReadexPro/ReadexPro-SemiBold.ttf b/fonts/ReadexPro/ReadexPro-SemiBold.ttf new file mode 100644 index 0000000..c565027 Binary files /dev/null and b/fonts/ReadexPro/ReadexPro-SemiBold.ttf differ diff --git a/fonts/Roboto/Roboto-Black.ttf b/fonts/Roboto/Roboto-Black.ttf new file mode 100644 index 0000000..43a00e0 Binary files /dev/null and b/fonts/Roboto/Roboto-Black.ttf differ diff --git a/fonts/Roboto/Roboto-BlackItalic.ttf b/fonts/Roboto/Roboto-BlackItalic.ttf new file mode 100644 index 0000000..5082cdc Binary files /dev/null and b/fonts/Roboto/Roboto-BlackItalic.ttf differ diff --git a/fonts/Roboto/Roboto-Bold.ttf b/fonts/Roboto/Roboto-Bold.ttf new file mode 100644 index 0000000..3742457 Binary files /dev/null and b/fonts/Roboto/Roboto-Bold.ttf differ diff --git a/fonts/Roboto/Roboto-BoldItalic.ttf b/fonts/Roboto/Roboto-BoldItalic.ttf new file mode 100644 index 0000000..e85e7fb Binary files /dev/null and b/fonts/Roboto/Roboto-BoldItalic.ttf differ diff --git a/fonts/Roboto/Roboto-Italic.ttf b/fonts/Roboto/Roboto-Italic.ttf new file mode 100644 index 0000000..c9df607 Binary files /dev/null and b/fonts/Roboto/Roboto-Italic.ttf differ diff --git a/fonts/Roboto/Roboto-Light.ttf b/fonts/Roboto/Roboto-Light.ttf new file mode 100644 index 0000000..0e97751 Binary files /dev/null and b/fonts/Roboto/Roboto-Light.ttf differ diff --git a/fonts/Roboto/Roboto-LightItalic.ttf b/fonts/Roboto/Roboto-LightItalic.ttf new file mode 100644 index 0000000..3ad14fa Binary files /dev/null and b/fonts/Roboto/Roboto-LightItalic.ttf differ diff --git a/fonts/Roboto/Roboto-Medium.ttf b/fonts/Roboto/Roboto-Medium.ttf new file mode 100644 index 0000000..e89b0b7 Binary files /dev/null and b/fonts/Roboto/Roboto-Medium.ttf differ diff --git a/fonts/Roboto/Roboto-MediumItalic.ttf b/fonts/Roboto/Roboto-MediumItalic.ttf new file mode 100644 index 0000000..a5a41d3 Binary files /dev/null and b/fonts/Roboto/Roboto-MediumItalic.ttf differ diff --git a/fonts/Roboto/Roboto-Regular.ttf b/fonts/Roboto/Roboto-Regular.ttf new file mode 100644 index 0000000..3d6861b Binary files /dev/null and b/fonts/Roboto/Roboto-Regular.ttf differ diff --git a/fonts/Roboto/Roboto-Thin.ttf b/fonts/Roboto/Roboto-Thin.ttf new file mode 100644 index 0000000..7d084ae Binary files /dev/null and b/fonts/Roboto/Roboto-Thin.ttf differ diff --git a/fonts/Roboto/Roboto-ThinItalic.ttf b/fonts/Roboto/Roboto-ThinItalic.ttf new file mode 100644 index 0000000..c173389 Binary files /dev/null and b/fonts/Roboto/Roboto-ThinItalic.ttf differ diff --git a/fonts/tunisia/HacenTunisia.ttf b/fonts/tunisia/HacenTunisia.ttf new file mode 100644 index 0000000..439fa06 Binary files /dev/null and b/fonts/tunisia/HacenTunisia.ttf differ diff --git a/fonts/tunisia/HacenTunisiaBd.ttf b/fonts/tunisia/HacenTunisiaBd.ttf new file mode 100644 index 0000000..22538ff Binary files /dev/null and b/fonts/tunisia/HacenTunisiaBd.ttf differ diff --git a/fonts/tunisia/HacenTunisiaLt.ttf b/fonts/tunisia/HacenTunisiaLt.ttf new file mode 100644 index 0000000..d81bc69 Binary files /dev/null and b/fonts/tunisia/HacenTunisiaLt.ttf differ diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..9625e10 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..ec97fc6 --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..c4855bf --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..88359b2 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '11.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..61ff2aa --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,137 @@ +PODS: + - Firebase/CoreOnly (10.12.0): + - FirebaseCore (= 10.12.0) + - Firebase/Messaging (10.12.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 10.12.0) + - firebase_core (2.15.0): + - Firebase/CoreOnly (= 10.12.0) + - Flutter + - firebase_messaging (14.6.5): + - Firebase/Messaging (= 10.12.0) + - firebase_core + - Flutter + - FirebaseCore (10.12.0): + - FirebaseCoreInternal (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Logger (~> 7.8) + - FirebaseCoreInternal (10.12.0): + - "GoogleUtilities/NSData+zlib (~> 7.8)" + - FirebaseInstallations (10.12.0): + - FirebaseCore (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - PromisesObjC (~> 2.1) + - FirebaseMessaging (10.12.0): + - FirebaseCore (~> 10.0) + - FirebaseInstallations (~> 10.0) + - GoogleDataTransport (~> 9.2) + - GoogleUtilities/AppDelegateSwizzler (~> 7.8) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Reachability (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - nanopb (< 2.30910.0, >= 2.30908.0) + - Flutter (1.0.0) + - flutter_inappwebview (0.0.1): + - Flutter + - flutter_inappwebview/Core (= 0.0.1) + - OrderedSet (~> 5.0) + - flutter_inappwebview/Core (0.0.1): + - Flutter + - OrderedSet (~> 5.0) + - geolocator_apple (1.2.0): + - Flutter + - GoogleDataTransport (9.2.3): + - GoogleUtilities/Environment (~> 7.7) + - nanopb (< 2.30910.0, >= 2.30908.0) + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/AppDelegateSwizzler (7.11.4): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (7.11.4): + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.11.4): + - GoogleUtilities/Environment + - GoogleUtilities/Network (7.11.4): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (7.11.4)" + - GoogleUtilities/Reachability (7.11.4): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (7.11.4): + - GoogleUtilities/Logger + - nanopb (2.30909.0): + - nanopb/decode (= 2.30909.0) + - nanopb/encode (= 2.30909.0) + - nanopb/decode (2.30909.0) + - nanopb/encode (2.30909.0) + - OrderedSet (5.0.0) + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - PromisesObjC (2.3.1) + - url_launcher_ios (0.0.1): + - Flutter + +DEPENDENCIES: + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) + - Flutter (from `Flutter`) + - flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`) + - geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + +SPEC REPOS: + trunk: + - Firebase + - FirebaseCore + - FirebaseCoreInternal + - FirebaseInstallations + - FirebaseMessaging + - GoogleDataTransport + - GoogleUtilities + - nanopb + - OrderedSet + - PromisesObjC + +EXTERNAL SOURCES: + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" + Flutter: + :path: Flutter + flutter_inappwebview: + :path: ".symlinks/plugins/flutter_inappwebview/ios" + geolocator_apple: + :path: ".symlinks/plugins/geolocator_apple/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + +SPEC CHECKSUMS: + Firebase: 07150e75d142fb9399f6777fa56a187b17f833a0 + firebase_core: e477125798fc37cd4ab43ca6a8536bf7e0929c00 + firebase_messaging: 334d68c3a36b6d4d5cd91e4f42509e0d4ae49828 + FirebaseCore: f86a1394906b97ac445ae49c92552a9425831bed + FirebaseCoreInternal: 950500ad8a08963657f6d8c67b579740c06d6aa1 + FirebaseInstallations: 7b99ef103f013624444c614397038219c45f8e63 + FirebaseMessaging: bb2c4f6422a753038fe137d90ae7c1af57251316 + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721 + geolocator_apple: cc556e6844d508c95df1e87e3ea6fa4e58c50401 + GoogleDataTransport: f0308f5905a745f94fb91fea9c6cbaf3831cb1bd + GoogleUtilities: c63691989bf362ba0505507da00eeb326192e83e + nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 + OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c + path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4 + url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 + +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 + +COCOAPODS: 1.12.1 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..2348838 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,583 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 991AA65E8CEDD6EDEF1668A0 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AB9C9FFB4EFB630F2EE59CB /* Pods_Runner.framework */; }; + F576DF182A8B6CF200030EA0 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F576DF172A8B6CF200030EA0 /* GoogleService-Info.plist */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 8AB9C9FFB4EFB630F2EE59CB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B284B5EA3DFDCC3500DD317F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + C9934765649B8EEC45FDD483 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + D48C177588361A7402C4F0D8 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + F507F9C02A7148A800E62CE1 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + F576DF172A8B6CF200030EA0 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../../Downloads/untitled folder/GoogleService-Info.plist"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 991AA65E8CEDD6EDEF1668A0 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7D57AA31AE360377E795E0FD /* Pods */ = { + isa = PBXGroup; + children = ( + D48C177588361A7402C4F0D8 /* Pods-Runner.debug.xcconfig */, + C9934765649B8EEC45FDD483 /* Pods-Runner.release.xcconfig */, + B284B5EA3DFDCC3500DD317F /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 7D57AA31AE360377E795E0FD /* Pods */, + B1B058A1F7376C6C764A0CA1 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + F507F9C02A7148A800E62CE1 /* Runner.entitlements */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + F576DF172A8B6CF200030EA0 /* GoogleService-Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + B1B058A1F7376C6C764A0CA1 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8AB9C9FFB4EFB630F2EE59CB /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + BB1FC663FDD45527FFCCE186 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 6309B449E68083B436CB1983 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + packageReferences = ( + F576DF142A8B648F00030EA0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, + ); + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + F576DF182A8B6CF200030EA0 /* GoogleService-Info.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 6309B449E68083B436CB1983 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + BB1FC663FDD45527FFCCE186 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = HLNH6QDB83; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.2.0; + PRODUCT_BUNDLE_IDENTIFIER = com.snonosystems.fiberx; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = HLNH6QDB83; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.2.0; + PRODUCT_BUNDLE_IDENTIFIER = com.snonosystems.fiberx; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = HLNH6QDB83; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.2.0; + PRODUCT_BUNDLE_IDENTIFIER = com.snonosystems.fiberx; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + F576DF142A8B648F00030EA0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 10.0.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..96a58bd --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,104 @@ +{ + "pins" : [ + { + "identity" : "abseil-cpp-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/abseil-cpp-binary.git", + "state" : { + "revision" : "bfc0b6f81adc06ce5121eb23f628473638d67c5c", + "version" : "1.2022062300.0" + } + }, + { + "identity" : "firebase-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/firebase-ios-sdk", + "state" : { + "revision" : "df2171b0c6afb9e9d4f7e07669d558c510b9f6be", + "version" : "10.13.0" + } + }, + { + "identity" : "googleappmeasurement", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleAppMeasurement.git", + "state" : { + "revision" : "03b9beee1a61f62d32c521e172e192a1663a5e8b", + "version" : "10.13.0" + } + }, + { + "identity" : "googledatatransport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleDataTransport.git", + "state" : { + "revision" : "aae45a320fd0d11811820335b1eabc8753902a40", + "version" : "9.2.5" + } + }, + { + "identity" : "googleutilities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleUtilities.git", + "state" : { + "revision" : "c38ce365d77b04a9a300c31061c5227589e5597b", + "version" : "7.11.5" + } + }, + { + "identity" : "grpc-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/grpc-binary.git", + "state" : { + "revision" : "f1b366129d1125be7db83247e003fc333104b569", + "version" : "1.50.2" + } + }, + { + "identity" : "gtm-session-fetcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/gtm-session-fetcher.git", + "state" : { + "revision" : "d415594121c9e8a4f9d79cecee0965cf35e74dbd", + "version" : "3.1.1" + } + }, + { + "identity" : "leveldb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/leveldb.git", + "state" : { + "revision" : "0706abcc6b0bd9cedfbb015ba840e4a780b5159b", + "version" : "1.22.2" + } + }, + { + "identity" : "nanopb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/nanopb.git", + "state" : { + "revision" : "819d0a2173aff699fb8c364b6fb906f7cdb1a692", + "version" : "2.30909.0" + } + }, + { + "identity" : "promises", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/promises.git", + "state" : { + "revision" : "e70e889c0196c76d22759eb50d6a0270ca9f1d9e", + "version" : "2.3.1" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "ce20dc083ee485524b802669890291c0d8090170", + "version" : "1.22.1" + } + } + ], + "version" : 2 +} diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..f3d88ac --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..96a58bd --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,104 @@ +{ + "pins" : [ + { + "identity" : "abseil-cpp-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/abseil-cpp-binary.git", + "state" : { + "revision" : "bfc0b6f81adc06ce5121eb23f628473638d67c5c", + "version" : "1.2022062300.0" + } + }, + { + "identity" : "firebase-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/firebase-ios-sdk", + "state" : { + "revision" : "df2171b0c6afb9e9d4f7e07669d558c510b9f6be", + "version" : "10.13.0" + } + }, + { + "identity" : "googleappmeasurement", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleAppMeasurement.git", + "state" : { + "revision" : "03b9beee1a61f62d32c521e172e192a1663a5e8b", + "version" : "10.13.0" + } + }, + { + "identity" : "googledatatransport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleDataTransport.git", + "state" : { + "revision" : "aae45a320fd0d11811820335b1eabc8753902a40", + "version" : "9.2.5" + } + }, + { + "identity" : "googleutilities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleUtilities.git", + "state" : { + "revision" : "c38ce365d77b04a9a300c31061c5227589e5597b", + "version" : "7.11.5" + } + }, + { + "identity" : "grpc-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/grpc-binary.git", + "state" : { + "revision" : "f1b366129d1125be7db83247e003fc333104b569", + "version" : "1.50.2" + } + }, + { + "identity" : "gtm-session-fetcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/gtm-session-fetcher.git", + "state" : { + "revision" : "d415594121c9e8a4f9d79cecee0965cf35e74dbd", + "version" : "3.1.1" + } + }, + { + "identity" : "leveldb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/leveldb.git", + "state" : { + "revision" : "0706abcc6b0bd9cedfbb015ba840e4a780b5159b", + "version" : "1.22.2" + } + }, + { + "identity" : "nanopb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/nanopb.git", + "state" : { + "revision" : "819d0a2173aff699fb8c364b6fb906f7cdb1a692", + "version" : "2.30909.0" + } + }, + { + "identity" : "promises", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/promises.git", + "state" : { + "revision" : "e70e889c0196c76d22759eb50d6a0270ca9f1d9e", + "version" : "2.3.1" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "ce20dc083ee485524b802669890291c0d8090170", + "version" : "1.22.1" + } + } + ], + "version" : 2 +} diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..077fc08 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,15 @@ +import UIKit +import Flutter +import Firebase + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + FirebaseApp.configure() + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..73fdd3e --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "filename" : "ic_launcherplay 4 (2)-20@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "ic_launcherplay 4 (2)-20@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "filename" : "ic_launcherplay 4 (2)-29@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "ic_launcherplay 4 (2)-29@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "ic_launcherplay 4 (2)-40@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "ic_launcherplay 4 (2)-40@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "ic_launcherplay 4 (2)-60@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "ic_launcherplay 4 (2)-60@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "ic_launcherplay 4 (2)-20.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "filename" : "ic_launcherplay 4 (2)-20@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "ic_launcherplay 4 (2)-29.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "ic_launcherplay 4 (2)-29@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "ic_launcherplay 4 (2)-40.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "filename" : "ic_launcherplay 4 (2)-40@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "ic_launcherplay 4 (2)-76.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "filename" : "ic_launcherplay 4 (2)-76@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "filename" : "ic_launcherplay 4 (2)-83.5@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "filename" : "ic_launcherplay 4 (2)-1024.png", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-1024.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-1024.png new file mode 100644 index 0000000..44763f2 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-1024.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-20.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-20.png new file mode 100644 index 0000000..2f03657 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-20.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-20@2x.png new file mode 100644 index 0000000..62d3fec Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-20@3x.png new file mode 100644 index 0000000..424fd38 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-29.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-29.png new file mode 100644 index 0000000..2d44ce9 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-29.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-29@2x.png new file mode 100644 index 0000000..0a0b4e7 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-29@3x.png new file mode 100644 index 0000000..fb94127 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-40.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-40.png new file mode 100644 index 0000000..62d3fec Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-40.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-40@2x.png new file mode 100644 index 0000000..993a297 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-40@3x.png new file mode 100644 index 0000000..9c54ae6 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-60@2x.png new file mode 100644 index 0000000..9c54ae6 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-60@3x.png new file mode 100644 index 0000000..cc4bd8c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-76.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-76.png new file mode 100644 index 0000000..a6064c1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-76.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-76@2x.png new file mode 100644 index 0000000..59ce260 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-83.5@2x.png new file mode 100644 index 0000000..b2aef8c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/ic_launcherplay 4 (2)-83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/Contents.json b/ios/Runner/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ios/Runner/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json new file mode 100644 index 0000000..9f447e1 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "background.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png new file mode 100644 index 0000000..b980fdc Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..00cabce --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "LaunchImage.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "LaunchImage@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "LaunchImage@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..f7925a2 Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..240e8b5 Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..f806779 Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..5a37630 --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..9867a9a --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..a6c5491 --- /dev/null +++ b/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 386498163901-dnl8uav988huioahp1ir16f3lobrc9vh.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.386498163901-dnl8uav988huioahp1ir16f3lobrc9vh + ANDROID_CLIENT_ID + 386498163901-e9vr5tgfntjscrbvftnumtnddnht5jee.apps.googleusercontent.com + API_KEY + AIzaSyBG0kMBiy8QGhBx8YVje5YZf4P3FFaamCI + GCM_SENDER_ID + 386498163901 + PLIST_VERSION + 1 + BUNDLE_ID + com.snonosystems.fiberx + PROJECT_ID + fiberx-33e52 + STORAGE_BUCKET + fiberx-33e52.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:386498163901:ios:1dbaee9572c255528773d4 + + \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..4402ca2 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,64 @@ + + + + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + IQ + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + IQ + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSLocationAlwaysUsageDescription + This app needs access to location when in the background. + NSLocationWhenInUseUsageDescription + This app needs access to location when open. + FirebaseAppDelegateProxyEnabled + no + UIApplicationSupportsIndirectInputEvents + + UIBackgroundModes + + fetch + remote-notification + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + UIStatusBarHidden + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements new file mode 100644 index 0000000..903def2 --- /dev/null +++ b/ios/Runner/Runner.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + diff --git a/lib/app.dart b/lib/app.dart new file mode 100644 index 0000000..da47e8f --- /dev/null +++ b/lib/app.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:overlay_support/overlay_support.dart'; +import 'package:responsive_framework/responsive_framework.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/translations.dart'; +import 'package:IQ/app/modules/selectISP/models/isp_model.dart'; +import 'package:IQ/app/modules/selectISP/views/select_isp_view.dart'; +import 'package:IQ/app/routes/app_pages.dart'; +import 'package:IQ/main.dart'; + +// ignore: must_be_immutable +class MyApp extends StatelessWidget { + MyApp({super.key}); + + @override + Widget build(BuildContext context) => _buildApp(context); + + ISPsData isp = ISPsData( + name: "FiberX", + serverAddress: "172.16.12.108", + ); + Widget _buildApp(BuildContext context) { + selectedISP = isp; + storage.write('selectedISP', selectedISP?.toJson()); + url = 'https://${selectedISP?.serverAddress}/user/api/index.php/api'; + liveDataUrl = + 'http://${selectedISP?.serverAddress}/userlivetraffic/ucp/traffic?token='; + storage.write('baseUrl', url); + storage.write('liveDataUrl', liveDataUrl); + return OverlaySupport( + child: GetMaterialApp( + title: "", + initialRoute: Routes.AUTOLOGIN, + translations: Translation(), + locale: Locale(defaultLocale), + getPages: AppPages.routes, + debugShowCheckedModeBanner: false, + builder: (context, navigator) => ResponsiveWrapper.builder( + Theme(data: ThemeData(fontFamily: 'DefaultFont'), child: navigator!), + maxWidth: 1200, + minWidth: 480, + defaultScale: true, + breakpoints: [ + const ResponsiveBreakpoint.resize(480, name: MOBILE), + const ResponsiveBreakpoint.autoScale(800, name: TABLET), + const ResponsiveBreakpoint.resize(1000, name: DESKTOP), + ], + ), + ), + ); + } +} diff --git a/lib/app/global/ar_strings.dart b/lib/app/global/ar_strings.dart new file mode 100644 index 0000000..d6da422 --- /dev/null +++ b/lib/app/global/ar_strings.dart @@ -0,0 +1,108 @@ +const Map ar = { + "back_twice": "يرجى الرجوع مرتين للخروج", + "days_ago": "أيام مضت", + "hours_ago": "ساعات مضت", + "minutes_ago": "دقائق مضت", + "seconds_ago": "ثواني مضت", + "just_now": "الآن", + "oops_snack": "حدث خطأ", + "select_isp_title": 'اختر مجهز الخدمة', + "next_button": "التالي", + "adding_isp": "اضافة مجهز خدمة", + "back_button": "رجوع", + "save_button": "حفظ", + "provider_name": "اسم المجهز", + "provider_address": "عنوان السيرفر (IP or domain)", + "provider_name_validation": "اسم المجهز مطلوب", + "provider_address_validation": "يجب ادخال عنوان السيرفر", + "auto_login": "محاولة التسجيل التلقائي", + "autoLogin_failed": "لا يمكن الاتصال مع المجهز", + "autologin_failed_messageNull": "السيرفر غير متوفر", + "autologin_failed_message0": "لا يوجد اتصال بالإنترنت", + "autologin_failed_message_2": "السيرفر غير متوفر", + "autologin_failed_message-1": "عنوان IP غير صالح", + "retry_autoLogin_button": "اعادة المحاولة", + "change_provider": "تغيير المجهز", + "login_massage": "للاستمرار يرجى", + "login_title": "تسجيل الدخول", + "login_username": "اسم الدخول", + "login_password": "كلمة المرور", + "remember_me": "حفظ معلومات تسجيل الدخول", + "login_button": "دخول", + "provider_unreachable": "لا يمكن الوصول للمجهز", + "no_connect": "لا يوجد اتصال", + "ip_address_invalid": "عنوان IP غير صالح", + "login_failed": "يرجى ادخال اسم مستخدم وكلمة المرور صحيحة", + "unentered_login_credentials": "يرجى ادخال اسم مستخدم وكلمة المرور", + "enter_captcha": "يرجى ادخال رمز التوثيق", + "captcha_hint": "ادخل رمز التوثيق", + "captcha_validation": "يرجى ادخال رمز التوثيق", + "captcha_dialog_cancel_button": "الغاء", + "captcha_dialog_ok_button": "تحقق", + "remaining_days": "الأيام المتبقية", + "account_information": "معلومات الحساب", + "username": "اسم الدخول", + "fullname": "الاسم الكامل", + "subscription_price": "سعر الاشتراك", + "subscription_expire": "تاريخ الانتهاء", + "available_balance": "الرصيد المتوفر", + "home_notifs": "التنبيهات", + "empty_home_notifs": "لم تصلك تنبيهات الى الان", + "subscription_type": "اشتراكك من نوع", + "connectionStatusText": "متصل", + "connectionStatusTextOffiline": "غير متصل", + "!connectionStatusText": "غير متصل", + "activiationStatusText": "الاشتراك منتهي", + "!activiationStatusText": "الاشتراك فعال", + "activiationStatusTextactive": "فعال", + "floatButtonActivation": "تفعيل", + "!floatButtonActivation": "تعبئة بطاقة", + "drawer_wifi_test": "اختبار سبيد تست", + + "drawer_home": "الرئيسية", + "drawer_dataUsage": "استهلاك البيانات", + "drawer_dataStream": "تدفق البيانات", + "drawer_availablePackages": "الباقات المتوفرة", + "drawer_payments": "المدفوعات", + "drawer_support": "الاتصال بنا", + "drawer_notifications": "الاشعارات", + "drawer_logout": "تسجيل الخروج", + "drawer_aboutApp": "عن فايبر اكس", + "data_usage_title": "مخطط الاستهلاك", + "data_usage_screen_title": ";كمية البيانات المستهلكة اليوم", + "data_stream_screen_title": "تدفق البيانات", + "available_packages": "الباقات المتوفرة", + "current_subscription": "الاشتراك الحالي", + "payments": "المدفوعات", + "support": "الدعم", + "new_support_ticket": "تكت جديد", + "send": "إرسال", + "subject": "الموضوع", + "message": "إكتب الرسالة هنا", + 'subject_input_error': 'الموضوع مطلوب', + 'subject_input_num': 'الموضوع يجب ان لا يكون اقل من 5 احرف', + 'message_input_error': 'الرسالة مطلوبة', + 'message_input_num': 'الرسالة يجب ان لا تقل عن 10 احرف', + "new_ticket_title": "أخبرنا كيف يمكننا مساعدتك", + "no_tickets": "لا توجد تكتس حتى الآن، انشئ تكت جديد", + "ticket_status_waiting": "في انتظار", + "ticket_status_closed": "مغلق", + "ticket_status_solved": "محلول", + "empty_support": "لا توجد تكتس حتى الآن", + "empty_payments": "لا توجد مدفوعات حتى الآن", + "empty_notifications": "لا توجد اشعارات حتى الآن", + "notifications": "الاشعارات", + "card_top-up": "تعبئة بطاقة", + 'card_secret_num': 'ادخل الرمز السري للبطاقة', + 'card_secret_num_validation': 'يجب ادخال الرمز السري', + "entered_card_secret_num": "موافق", + "backfrom_card_secret_num": "رجوع", + "Top_up_status": "تم تعبئة البطاقة بنجاح", + "Top_up_status_waiting": "... جاري التعبئة", + "wrong_entered_card_secret_num_error": + "رقم البطاقة الذي ادخلته غير صالح او خطأ. يرجى التأكد من الرقم", + "unknown_error": "غير مسموح الدخول", + "remaining_traffic": "البيانات المتبقية", + 'dont_have_username': "ليس لديك اسم مستخدم؟", + 'call_center': "مركز الاتصال", +}; diff --git a/lib/app/global/convert_to_ago.dart b/lib/app/global/convert_to_ago.dart new file mode 100644 index 0000000..1cbc90a --- /dev/null +++ b/lib/app/global/convert_to_ago.dart @@ -0,0 +1,17 @@ +import 'package:get/get.dart'; + +String convertToAgo(DateTime input) { + Duration diff = DateTime.now().difference(input); + + if (diff.inDays >= 1) { + return '${diff.inDays} ' + 'days_ago'.tr; + } else if (diff.inHours >= 1) { + return '${diff.inHours} ' + 'hours_ago'.tr; + } else if (diff.inMinutes >= 1) { + return '${diff.inMinutes} ' + 'minutes_ago'.tr; + } else if (diff.inSeconds >= 1) { + return '${diff.inSeconds} ' + 'seconds_ago'.tr; + } else { + return 'just_now'.tr; + } +} diff --git a/lib/app/global/converted_bytes.dart b/lib/app/global/converted_bytes.dart new file mode 100644 index 0000000..276efba --- /dev/null +++ b/lib/app/global/converted_bytes.dart @@ -0,0 +1,9 @@ +import 'dart:math'; + +String formatBytes(int bytes, int decimals) { + if (bytes <= 0) return "0 B"; + const suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; + var i = (log(bytes) / log(1024)).floor(); + return ((bytes / pow(1024, i)).toStringAsFixed(decimals)) + ' ' + suffixes[i]; +} + diff --git a/lib/app/global/en_string.dart b/lib/app/global/en_string.dart new file mode 100644 index 0000000..4364b2c --- /dev/null +++ b/lib/app/global/en_string.dart @@ -0,0 +1,104 @@ +const Map en = { + "back_twice": "Back twice to exit", + "days_ago": "days ago", + "hours_ago": "hours ago", + "minutes_ago": "minutes ago", + "seconds_ago": "seconds ago", + "just_now": "just now", + "oops_snack": "Oops", + "select_isp_title": 'Select Your ISP', + "next_button": "Next", + "adding_isp": "Add an ISP", + "back_button": "back", + "save_button": "save", + "provider_name": "Provider Name", + "provider_address": "Provider Address (IP or domain)", + "provider_name_validation": "provider name is required", + "provider_address_validation": "provider address is required", + "auto_login": "trying auto login...", + "autoLogin_failed": "provider failed to connect", + "autologin_failed_messageNull": "server is unreachable", + "autologin_failed_message0": "No Internet Connection", + "autologin_failed_message_2": "server is unreachable", + "autologin_failed_message_1": "invalid ip address", + "retry_autoLogin_button": "try again", + "change_provider": "change provider", + "login_massage": "Proceed with", + "login_title": "Login", + "login_username": "username", + "login_password": "password", + "remember_me": "save login info", + "login_button": "Login", + "provider_unreachable": "provider is unreachable", + "no_connect": "no connection", + "ip_address_invalid": "invalid ip address", + "login_failed": "Invalid username or password", + "unentered_login_credentials": "please enter username and password", + "enter_captcha": "please enter captcha", + "captcha_hint": "enter captcha", + "captcha_validation": "please enter captcha", + "captcha_dialog_cancel_button": "Cancel", + "captcha_dialog_ok_button": "Submit", + "remaining_days": ".Days rem", + "account_information": "Account Information", + "username": "username", + "fullname": "full name", + "subscription_price": "subscription price", + "subscription_expire": "expires on", + "available_balance": "available balance", + "home_notifs": "Notifications", + "drawer_wifi_test": "Speed Test", + "empty_home_notifs": "No Notifications Yet", + "subscription_type": "Service Profile", + "connectionStatusText": "Online", + "connectionStatusTextOffiline": "Offline", + "activiationStatusText": "Expired", + "activiationStatusTextactive": "Active", + "floatButtonActivation": "Activate", + "!floatButtonActivation": "Redeem card", + "drawer_home": "Home", + "drawer_dataUsage": "Data usage", + "drawer_dataStream": "Live traffic", + "drawer_availablePackages": "Available Packages", + "drawer_entertainment": "Entertainment", + "drawer_support": "Contact us", + "drawer_notifications": "Notifications", + "drawer_logout": "Logout", + "drawer_aboutApp": "About FiberX", + "data_usage_title": "Data Usage Chart", + "data_usage_screen_title": "Data Usage (Today)", + "data_stream_screen_title": "Live traffic", + "available_packages": "Available Packages", + "current_subscription": "active", + "payments": "Payments", + "support": "Support", + "new_support_ticket": "new ticket", + "send": "send", + "subject": "subject", + "message": "Write your message here...", + 'subject_input_error': 'Subject is required', + 'subject_input_num': 'Subject must be at least 5 characters', + 'message_input_error': 'Message is required', + 'message_input_num': 'Message must be at least 10 characters', + "new_ticket_title": "Tell us how we can help you", + "no_tickets": "No tickets yet, create a new one", + "ticket_status_waiting": "waiting", + "ticket_status_closed": "closed", + "ticket_status_solved": "solved", + "empty_payments": "there are no payments yet", + "empty_support": "there are no support tickets yet", + "empty_notifications": "there are no notifications yet", + "notifications": "Notifications", + "card_top-up": "Redeem Card", + 'card_secret_num': 'enter pin code', + 'card_secret_num_validation': 'PIN code required', + "Top_up_status": "Card Redeemed Successfully", + "Top_up_status_waiting": "... processing", + "wrong_entered_card_secret_num_error": "Wrong PIN code", + "entered_card_secret_num": "Submit", + "backfrom_card_secret_num": "back", + "unknown_error": "Unknown Error", + "remaining_traffic": "remaining traffic", + 'dont_have_username': "Don't have a username?", + 'call_center': "Call Center", +}; diff --git a/lib/app/global/global_snackbar.dart b/lib/app/global/global_snackbar.dart new file mode 100644 index 0000000..e9754a2 --- /dev/null +++ b/lib/app/global/global_snackbar.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; + +SnackBar snackBar = SnackBar( + content: TextWidget( + text: snackBarText, + fontSize: 20, + fontWeight: FontWeight.w600, + color: Colors.white, + softWrap: true, + textAlign: TextAlign.center, + ), + padding: const EdgeInsets.all(20), + backgroundColor: brandColor.withOpacity(0.8), + dismissDirection: DismissDirection.horizontal, +); diff --git a/lib/app/global/login_snackbar.dart b/lib/app/global/login_snackbar.dart new file mode 100644 index 0000000..3810160 --- /dev/null +++ b/lib/app/global/login_snackbar.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/global/text_widget.dart'; + +SnackbarController snack(String text) => Get.snackbar( + '', + '', + titleText: Center( + child: TextWidget( + text: 'oops_snack'.tr, + fontSize: 18, + color: Colors.white, + ), + ), + messageText: Center( + child: TextWidget( + text: text, + fontSize: 16, + color: Colors.white, + ), + ), + backgroundColor: Colors.red.withOpacity(0.5), + colorText: Colors.white, + snackPosition: SnackPosition.BOTTOM, + margin: const EdgeInsets.all(10), + borderRadius: 10, + borderColor: Colors.white, + borderWidth: 1, + duration: const Duration(seconds: 3), + ); diff --git a/lib/app/global/single_box.dart b/lib/app/global/single_box.dart new file mode 100644 index 0000000..1f1fd3d --- /dev/null +++ b/lib/app/global/single_box.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:IQ/app/global/text_widget.dart'; + +class SingleBox extends StatelessWidget { + const SingleBox({ + Key? key, + this.text, + this.text2, + }) : super(key: key); + + final String? text; + final String? text2; + @override + Widget build(BuildContext context) { + return Column( + children: [ + SvgPicture.asset( + '$text', + height: 60, + width: 60, + ), + const SizedBox(height: 5), + TextWidget( + fontSize: 16, + textAlign: TextAlign.center, + text: text2, + fontWeight: FontWeight.w500, + ), + ], + ); + } +} diff --git a/lib/app/global/single_card.dart b/lib/app/global/single_card.dart new file mode 100644 index 0000000..8e60182 --- /dev/null +++ b/lib/app/global/single_card.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; + +class SingleCard extends StatelessWidget { + const SingleCard({ + Key? key, + this.text, + this.text2, + }) : super(key: key); + final String? text; + final String? text2; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextWidget( + text: text, + fontSize: 20, + fontWeight: FontWeight.w400, + color: brandColor, + ), + TextWidget( + text: text2, + fontWeight: FontWeight.w400, + fontSize: 16, + color: Colors.grey, + ), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 10, + ), + child: const Divider(), + ), + ], + ); + } +} diff --git a/lib/app/global/snono_encrypt.dart b/lib/app/global/snono_encrypt.dart new file mode 100644 index 0000000..7a8dc75 --- /dev/null +++ b/lib/app/global/snono_encrypt.dart @@ -0,0 +1,47 @@ +import 'dart:typed_data'; +import 'package:encrypt/encrypt.dart' as encrypt_lib; +import 'dart:convert'; +import 'package:crypto/crypto.dart'; + +class AES { + static String encrypt({String? data, String? passpharse}) { + try { + var salt = [1, 2, 3, 4, 5, 6, 7, 8]; + + List salted = []; + List dx = []; + while (salted.length < 48) { + dx = generateMd5(dx + utf8.encode(passpharse!) + salt.toList()); + salted = salted + dx; + } + + var key = salted.sublist(0, 32); + var iv = salted.sublist(32); + + // encrypt part + final kkey = encrypt_lib.Key(Uint8List.fromList(key)); + final iiv = encrypt_lib.IV(Uint8List.fromList(iv)); + + final encrypter = encrypt_lib.Encrypter( + encrypt_lib.AES( + kkey, + mode: encrypt_lib.AESMode.cbc, + ), + ); + final encrypted = encrypter.encrypt( + data!, + iv: iiv, + ); + var aesEncode = encrypted.bytes; + String encoded = base64 + .encode(utf8.encode("Salted__") + salt.toList() + aesEncode.toList()); + return encoded; + } catch (e) { + return ''; + } + } + + static List generateMd5(List input) { + return md5.convert(input).bytes; + } +} diff --git a/lib/app/global/static_informs.dart b/lib/app/global/static_informs.dart new file mode 100644 index 0000000..9047cd8 --- /dev/null +++ b/lib/app/global/static_informs.dart @@ -0,0 +1,22 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +widthSize(context) => MediaQuery.of(context).size.width; +heightSize(context) => MediaQuery.of(context).size.height; + +Color backgroundColor = const Color(0xffE5E5E5); +Color borderColor = const Color(0xffD7D7D7); +// Color brandColor = const Color.fromRGBO(215, 132, 42, 1); +Color brandColor = const Color.fromRGBO(83, 49, 145, 1); +Color secondaryColor = const Color.fromRGBO(215, 132, 42, 1); +// Color secondaryColor = const Color.fromRGBO(0, 58, 72, 1); +Color labeledColor = const Color.fromRGBO(196, 196, 196, 1); +String defaultLocale = Platform.localeName.split('_')[0]; + +TextDirection textDirection = + defaultLocale == "en" ? TextDirection.ltr : TextDirection.rtl; +String snackBarText = 'back_twice'.tr; + +// +93787204545 \ No newline at end of file diff --git a/lib/app/global/text_field.dart b/lib/app/global/text_field.dart new file mode 100644 index 0000000..ab69483 --- /dev/null +++ b/lib/app/global/text_field.dart @@ -0,0 +1,228 @@ +// ignore_for_file: must_be_immutable + +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; + +class BuildTextField extends StatelessWidget { + BuildTextField({ + Key? key, + required this.name, + this.controller, + this.enabled, + this.expands, + this.initialValue, + this.keyboardType, + this.maxLines, + this.minLines, + this.maxLength, + this.obscureText, + this.onChanged, + this.onEditingComplete, + this.onTap, + this.readOnly, + this.textAlign, + this.textDirection, + this.validator, + this.labelText, + this.border, + this.contentPadding, + this.errorMaxLines, + this.errorText, + this.fillColor, + this.filled, + this.focusColor, + this.hintMaxLines, + this.hintText, + this.hintTextDirection, + this.icon, + this.iconColor, + this.isDense, + this.label, + this.prefix, + this.prefixIcon, + this.prefixIconColor, + this.prefixText, + this.suffix, + this.suffixIcon, + this.suffixIconColor, + this.suffixText, + this.alignLabelWithHint, + this.margin, + this.signup, + this.autoFocus, + this.counter, + this.showCursor, + this.width, + this.height, + this.focusNode, + this.inputColor, + }) : super(key: key); + + final String? name; + final TextEditingController? controller; + final bool? enabled; + final bool? expands; + final String? initialValue; + final TextInputType? keyboardType; + final int? maxLines; + final int? minLines; + final int? maxLength; + final bool? obscureText; + final void Function(String?)? onChanged; + final void Function()? onEditingComplete; + final void Function()? onTap; + final bool? readOnly; + final TextAlign? textAlign; + final TextDirection? textDirection; + final String? Function(String?)? validator; + final String? labelText; + InputBorder? border; + final EdgeInsetsGeometry? contentPadding; + final int? errorMaxLines; + final String? errorText; + final Color? fillColor; + final bool? filled; + final Color? focusColor; + final int? hintMaxLines; + final String? hintText; + final TextDirection? hintTextDirection; + final Widget? icon; + final Color? iconColor; + final bool? isDense; + final bool? autoFocus; + final bool? showCursor; + final Widget? label; + final Widget? prefix; + final Widget? prefixIcon; + final Color? prefixIconColor; + final String? prefixText; + final Widget? suffix; + final Widget? suffixIcon; + final Color? suffixIconColor; + final String? suffixText; + final bool? alignLabelWithHint; + final EdgeInsetsGeometry? margin; + final Widget? counter; + bool? signup = true; + final double? width; + final double? height; + final FocusNode? focusNode; + final Color? inputColor; + signupBorder() { + if (signup == true) { + border = OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular(10), + ), + borderSide: BorderSide( + color: borderColor, + width: 2, + ), + ); + return border; + } else { + border = const UnderlineInputBorder( + borderSide: BorderSide(color: Colors.white), + ); + return border; + } + } + + @override + Widget build(BuildContext context) { + signupBorder(); + return Container( + margin: margin, + // width: width, + // height: height, + child: FormBuilderTextField( + name: name!, + focusNode: focusNode, + autofocus: autoFocus ?? false, + controller: controller, + enabled: enabled ?? true, + expands: expands ?? false, + initialValue: initialValue, + keyboardType: keyboardType, + maxLines: maxLines ?? 1, + minLines: minLines, + maxLength: maxLength, + obscureText: obscureText ?? false, + onChanged: onChanged, + onEditingComplete: onEditingComplete, + onTap: onTap, + readOnly: readOnly ?? false, + textAlign: textAlign ?? TextAlign.start, + textDirection: textDirection ?? TextDirection.ltr, + validator: validator, + autovalidateMode: AutovalidateMode.onUserInteraction, + showCursor: showCursor, + decoration: InputDecoration( + /// + label: label, + icon: icon, + prefix: prefix, + suffix: suffix, + labelText: labelText, + errorText: errorText, + hintText: hintText, + prefixText: prefixText, + suffixText: suffixText, + prefixIcon: prefixIcon, + suffixIcon: suffixIcon, + + /// + border: border, + disabledBorder: border, + enabledBorder: border, + errorBorder: border, + focusedBorder: border, + focusedErrorBorder: border, + + /// + contentPadding: contentPadding, + errorMaxLines: errorMaxLines, + hintMaxLines: hintMaxLines, + hintTextDirection: hintTextDirection, + alignLabelWithHint: alignLabelWithHint, + counter: counter, + + /// + filled: filled, + isDense: isDense, + fillColor: fillColor, + focusColor: focusColor, + iconColor: iconColor, + prefixIconColor: prefixIconColor, + suffixIconColor: suffixIconColor, + + /// + labelStyle: buildTextStyle( + color: labeledColor, + fontSize: 15, + ), + prefixStyle: buildTextStyle( + color: Colors.white, + ), + suffixStyle: buildTextStyle( + color: Colors.white, + ), + errorStyle: buildTextStyle( + fontSize: 12, + color: const Color(0xffC4C4C4), + ), + hintStyle: buildTextStyle( + color: const Color(0xffD7D7D7), + fontSize: 19, + ), + ), + style: buildTextStyle( + fontSize: 20, + color: inputColor ?? Colors.white, + ), + ), + ); + } +} diff --git a/lib/app/global/text_widget.dart b/lib/app/global/text_widget.dart new file mode 100644 index 0000000..a847de6 --- /dev/null +++ b/lib/app/global/text_widget.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; + +class TextWidget extends StatelessWidget { + const TextWidget({ + Key? key, + this.text, + this.fontSize, + this.color, + this.fontWeight, + this.fontFamily, + this.textAlign, + this.decoration, + this.overflow, + this.softWrap, + }) : super(key: key); + final String? text; + final double? fontSize; + final Color? color; + final FontWeight? fontWeight; + final String? fontFamily; + final TextAlign? textAlign; + final TextDecoration? decoration; + final TextOverflow? overflow; + final bool? softWrap; + @override + Widget build(BuildContext context) { + return Text( + text ?? '', + style: buildTextStyle( + fontSize: fontSize, + color: color, + fontWeight: fontWeight, + fontFamily: fontFamily, + ), + + overflow: overflow, + softWrap: softWrap ?? true, + textAlign: textAlign ?? TextAlign.center, + ); + } +} + +TextStyle buildTextStyle({ + double? fontSize, + Color? color, + FontWeight? fontWeight, + double? letterSpacing, + double? wordSpacing, + List? shadows, + Color? backgroundColor, + double? height, + String? fontFamily, +}) { + return TextStyle( + letterSpacing: letterSpacing, + wordSpacing: wordSpacing, + fontSize: fontSize ?? 17, + color: color ?? Colors.black, + shadows: shadows, + fontFamily: fontFamily, + backgroundColor: backgroundColor, + fontWeight: fontWeight, + height: height, + overflow: TextOverflow.fade, + ); +} diff --git a/lib/app/global/translations.dart b/lib/app/global/translations.dart new file mode 100644 index 0000000..bc4b842 --- /dev/null +++ b/lib/app/global/translations.dart @@ -0,0 +1,11 @@ +import 'package:get/get.dart'; +import 'package:IQ/app/global/ar_strings.dart'; +import 'package:IQ/app/global/en_string.dart'; + +class Translation extends Translations { + @override + Map> get keys => { + 'en': en, + 'ar': ar, + }; +} diff --git a/lib/app/modules/LiveData/bindings/live_data_binding.dart b/lib/app/modules/LiveData/bindings/live_data_binding.dart new file mode 100644 index 0000000..385dac2 --- /dev/null +++ b/lib/app/modules/LiveData/bindings/live_data_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/live_data_controller.dart'; + +class LiveDataBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => LiveDataController(), + ); + } +} diff --git a/lib/app/modules/LiveData/controllers/live_data_controller.dart b/lib/app/modules/LiveData/controllers/live_data_controller.dart new file mode 100644 index 0000000..d917680 --- /dev/null +++ b/lib/app/modules/LiveData/controllers/live_data_controller.dart @@ -0,0 +1,18 @@ +// ignore_for_file: unnecessary_overrides + +import 'package:get/get.dart'; + +class LiveDataController extends GetxController { + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() {} +} diff --git a/lib/app/modules/LiveData/models/livedata.dart b/lib/app/modules/LiveData/models/livedata.dart new file mode 100644 index 0000000..99f3f36 --- /dev/null +++ b/lib/app/modules/LiveData/models/livedata.dart @@ -0,0 +1,21 @@ +class LiveData { + LiveData({ + this.time, + this.rxRate, + this.rx, + this.tx, + this.txRate, + }); + int? time; + int? rxRate; + int? rx; + int? tx; + int? txRate; + + LiveData.fromJson(Map json) { + rx = json['rx']; + rxRate = json['rx_rate']; + tx = json['tx']; + txRate = json['tx_rate']; + } +} diff --git a/lib/app/modules/LiveData/views/live_data_view.dart b/lib/app/modules/LiveData/views/live_data_view.dart new file mode 100644 index 0000000..4af7349 --- /dev/null +++ b/lib/app/modules/LiveData/views/live_data_view.dart @@ -0,0 +1,312 @@ +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:IQ/app/global/converted_bytes.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/LiveData/models/livedata.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; +import 'package:IQ/main.dart'; +import 'package:syncfusion_flutter_charts/charts.dart'; +import 'package:flutter/material.dart' as td; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:get/get.dart'; +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:flutter_client_sse/flutter_client_sse.dart'; +import 'dart:async'; + +class LiveDataView extends StatefulWidget { + const LiveDataView({super.key}); + + @override + State createState() => _LiveDataViewState(); +} + +class _LiveDataViewState extends State { + final GlobalKey scaffoldKey = GlobalKey(); + List chartData = []; + late ChartSeriesController _rxChartSeriesController; + late ChartSeriesController _txChartSeriesController; + LiveData? liveData; + TooltipBehavior? tooltipBehavior; + var liveDataUrl = storage.read('liveDataUrl'); + var token = storage.read('token'); + bool isDataLoaded = false; + + getLiveData() { + // I edit on the package on stream closing + SSEClient.subscribeToSSE( + url: "$liveDataUrl$token", + header: { + "Cookie": + 'jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE2NDMyMTAyMzEsImV4cCI6MTY0MzgxNTAzMX0.U0aCAM2fKE1OVnGFbgAU_UVBvNwOMMquvPY8QaLD138; Path=/; Expires=Wed, 02 Feb 2022 15:17:11 GMT; HttpOnly; SameSite=Strict', + "Accept": "text/event-stream", + "Cache-Control": "no-cache", + }, + ).listen((event) { + liveData = LiveData.fromJson(jsonDecode(event.data!)); + }); + } + + int count = 19; + + void _updateDataSource(Timer timer) { + chartData.add( + LiveData( + time: count++, + rxRate: (liveData?.rxRate)! * 8, + txRate: (liveData?.txRate)! * 8, + rx: liveData?.rx, + tx: liveData?.tx, + ), + ); + chartData.removeAt(0); + + _rxChartSeriesController.updateDataSource( + addedDataIndexes: [chartData.length - 1], + removedDataIndexes: [0], + ); + _txChartSeriesController.updateDataSource( + addedDataIndexes: [chartData.length - 1], + removedDataIndexes: [0], + ); + } + + List getCartData() { + List sampleChartData = []; + for (int i = 1; i < 19; i++) { + sampleChartData.add( + LiveData( + time: i, + rxRate: 0, + txRate: 0, + rx: 0, + tx: 0, + ), + ); + } + return sampleChartData; + } + + @override + void initState() { + chartData = getCartData(); + getLiveData(); + if (liveData != null) { + Timer.periodic(const Duration(seconds: 1), _updateDataSource); + } + tooltipBehavior = TooltipBehavior(enable: true); + super.initState(); + } + + @override + void dispose() { + super.dispose(); + isDataLoaded = false; + SSEClient.unsubscribeFromSSE(); + } + + @override + Widget build(BuildContext context) { + var stackedContainer = Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox(height: MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/dataflow.svg', + color: Colors.white, + fit: BoxFit.contain, + height: 80, + width: 80, + ), + TextWidget( + text: 'data_stream_screen_title'.tr, + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.w300, + textAlign: TextAlign.center, + ), + const SizedBox(height: 10), + ], + ), + ], + ), + ); + return Directionality( + textDirection: + defaultLocale != "en" ? td.TextDirection.ltr : td.TextDirection.rtl, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: Stack( + children: [ + Column( + children: [ + const SizedBox(height: 270), + Container( + height: 400, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + border: Border.all( + color: borderColor, + width: 1, + ), + ), + padding: const EdgeInsets.all(20), + margin: const EdgeInsets.only(right: 10, left: 10), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 20), + margin: const EdgeInsets.symmetric(vertical: 20), + child: SfCartesianChart( + legend: Legend( + isVisible: true, + position: LegendPosition.bottom, + ), + tooltipBehavior: tooltipBehavior, + backgroundColor: Colors.white, + borderColor: borderColor, + borderWidth: 0, + isTransposed: false, + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + plotAreaBackgroundColor: Colors.white, + plotAreaBorderColor: borderColor, + plotAreaBorderWidth: 0, + selectionGesture: ActivationMode.singleTap, + selectionType: SelectionType.point, + enableAxisAnimation: true, + primaryXAxis: NumericAxis( + majorGridLines: const MajorGridLines(width: 0), + edgeLabelPlacement: EdgeLabelPlacement.shift, + interval: 3, + title: AxisTitle(text: 'Time (seconds)'), + ), + primaryYAxis: NumericAxis( + axisLabelFormatter: (AxisLabelRenderDetails details) { + return ChartAxisLabel( + formatBytes(details.value.toInt(), 0), + details.textStyle, + ); + }, + borderWidth: 1, + borderColor: Colors.white, + edgeLabelPlacement: EdgeLabelPlacement.shift, + labelAlignment: LabelAlignment.center, + majorGridLines: MajorGridLines( + width: 1, + color: borderColor, + ), + axisLine: const AxisLine(width: 0), + majorTickLines: const MajorTickLines(size: 0), + ), + series: >[ + LineSeries( + name: "Upload", + onRendererCreated: + (ChartSeriesController chartSeriesController) { + _txChartSeriesController = chartSeriesController; + }, + dataSource: chartData, + color: brandColor, + xValueMapper: (LiveData data, _) => data.time, + yValueMapper: (LiveData data, _) => data.txRate, + ), + LineSeries( + name: "Download", + onRendererCreated: + (ChartSeriesController chartSeriesController) { + _rxChartSeriesController = chartSeriesController; + }, + dataSource: chartData, + color: const Color.fromARGB(255, 255, 12, 12), + xValueMapper: (LiveData data, _) => data.time, + yValueMapper: (LiveData data, _) => data.rxRate, + ), + ], + ), + ), + ), + ], + ), + stackedContainer, + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/about/about_view.dart b/lib/app/modules/about/about_view.dart new file mode 100644 index 0000000..d533121 --- /dev/null +++ b/lib/app/modules/about/about_view.dart @@ -0,0 +1,181 @@ +import 'package:IQ/app/modules/about/controllers/about_controller.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get_state_manager/src/simple/get_view.dart'; +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; + +class AboutView extends GetView { + AboutView({Key? key}) : super(key: key); + final GlobalKey scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Directionality( + textDirection: + defaultLocale != "en" ? TextDirection.ltr : TextDirection.rtl, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: Stack( + children: [ + Container( + margin: const EdgeInsets.only(top: 250), + child: Column( + children: [ + const SizedBox(height: 35), + Container( + margin: const EdgeInsets.symmetric(horizontal: 15), + alignment: Alignment.centerLeft, + child: TextWidget( + text: 'About FiberX', + fontSize: 18, + fontWeight: FontWeight.w500, + color: brandColor, + ), + ), + Container( + margin: const EdgeInsets.all(15), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 15, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: Colors.grey, width: 1), + ), + child: const TextWidget( + text: + "شركة رائدة في مجال الاتصالات وشريك رسمي لوزارة الاتصالات العراقية. المنجز والمنفذ والمشغل الفعلي لمشروع FTTH في محافظة واسط والبصرة.", + fontSize: 16, + fontWeight: FontWeight.w400, + color: Colors.black, + textAlign: TextAlign.right, + ), + ), + ], + ), + ), + Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Stack( + children: [ + Container( + height: 230, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState + ?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Container( + alignment: Alignment.center, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 30), + SvgPicture.asset( + 'assets/info-circle.svg', + height: 50, + width: 50, + color: Colors.white, + ), + const SizedBox(height: 20), + const TextWidget( + text: "About FiberX", + fontSize: 28, + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/about/bindings/about_binding.dart b/lib/app/modules/about/bindings/about_binding.dart new file mode 100644 index 0000000..388e1fe --- /dev/null +++ b/lib/app/modules/about/bindings/about_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/about_controller.dart'; + +class AboutBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AboutController(), + ); + } +} diff --git a/lib/app/modules/about/controllers/about_controller.dart b/lib/app/modules/about/controllers/about_controller.dart new file mode 100644 index 0000000..86920c5 --- /dev/null +++ b/lib/app/modules/about/controllers/about_controller.dart @@ -0,0 +1,38 @@ +// ignore_for_file: unnecessary_overrides + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/global/static_informs.dart'; + +class AboutController extends GetxController with WidgetsBindingObserver { + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + snackBarText = 'back_twice'.tr; + } + } + + @override + void onInit() { + WidgetsBinding.instance.addObserver(this); + + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} diff --git a/lib/app/modules/autologin/bindings/autologin_binding.dart b/lib/app/modules/autologin/bindings/autologin_binding.dart new file mode 100644 index 0000000..ec06a45 --- /dev/null +++ b/lib/app/modules/autologin/bindings/autologin_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/autologin_controller.dart'; + +class AutologinBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AutologinController(), + ); + } +} diff --git a/lib/app/modules/autologin/controllers/autologin_controller.dart b/lib/app/modules/autologin/controllers/autologin_controller.dart new file mode 100644 index 0000000..779f687 --- /dev/null +++ b/lib/app/modules/autologin/controllers/autologin_controller.dart @@ -0,0 +1,160 @@ +// ignore_for_file: unnecessary_overrides +import 'dart:async'; +import 'dart:io'; +import 'package:http/http.dart' as http; + +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/modules/home/controllers/home_controller.dart'; +import 'package:IQ/app/modules/selectISP/views/select_isp_view.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; +import 'package:IQ/app/routes/app_pages.dart'; +import 'package:IQ/main.dart'; + +class AutologinController extends GetxController with WidgetsBindingObserver { + String errorText = ''; + + reloadAutologin() async { + errorText = ''; + update(); + var ispDetected = await detectISP(); + await makeOperationsAfterDetecting(ispDetected); + } + + Future detectISP() async { + String str = ""; + try { + http.Request response; + response = http.Request( + 'GET', + Uri.parse( + 'http://connect.snono-systems.com/index.php/api/fiberx/detect', + ), + ); + http.StreamedResponse request = await response.send(); + if (request.statusCode != 200) { + storage.remove('token'); + // Get.offAllNamed(Routes.SELECT_I_S_P); + return "${request.statusCode}"; + } + String res = await request.stream.bytesToString(); + debugPrint("detectISP: $res"); + str = jsonDecode(res)["data"]; + return str; + } catch (e) { + if (e is SocketException) { + str = "0"; + return str; + } else if (e is TimeoutException) { + str = "-2"; + return str; + } + } + return str; + } + + fetch() async { + var value = await APIService.get( + 'auth/autoLogin?device_id=$deviceId&lat=$lat&long=$long', + false, + ).timeout( + const Duration(seconds: 8), + onTimeout: () { + errorText = ''; + update(); + }, + ); + if (value == null) { + errorText = 'autologin_failed_messageNull'.tr; + update(); + return; + } + + if (value.runtimeType == int) { + if (value == 0) { + errorText = 'autologin_failed_message0'.tr; + } + if (value == -2) { + errorText = 'autologin_failed_message_2'.tr; + } + if (value == -1) { + errorText = 'autologin_failed_message_1'.tr; + } + update(); + + return; + } + var decodedValue = jsonDecode(value); + if (decodedValue.toString().contains('token')) { + token = decodedValue["token"]; + storage.write('token', token); + Get.lazyPut( + () => HomeController(), + ); + Future.delayed( + const Duration(seconds: 2), + () { + Get.offAllNamed(Routes.HOME); + }, + ); + } else { + errorText = value; + Future.delayed( + const Duration(seconds: 1), + () { + Get.offAllNamed(Routes.LOGIN); + }, + ); + } + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + textDirection = + defaultLocale == "en" ? TextDirection.ltr : TextDirection.rtl; + } + } + + makeOperationsAfterDetecting(String ispDetected) async { + if (ispDetected != "0" || ispDetected != "-2") { + url = 'https://$ispDetected/user/api/index.php/api'; + liveDataUrl = 'http://$ispDetected/userlivetraffic/ucp/traffic?token='; + storage.write('baseUrl', url); + storage.write('liveDataUrl', liveDataUrl); + fetch(); + debugPrint("#url: $url"); + } else { + debugPrint("@url: $url"); + Future.delayed(const Duration(seconds: 2), () { + Get.offAllNamed(Routes.LOGIN); + }); + } + } + + @override + void onInit() async { + super.onInit(); + var ispDetected = await detectISP(); + await makeOperationsAfterDetecting(ispDetected); + return; + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} diff --git a/lib/app/modules/autologin/views/autologin_view.dart b/lib/app/modules/autologin/views/autologin_view.dart new file mode 100644 index 0000000..57077ed --- /dev/null +++ b/lib/app/modules/autologin/views/autologin_view.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; + +import '../controllers/autologin_controller.dart'; + +class AutologinView extends GetView { + const AutologinView({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: brandColor, + appBar: AppBar( + backgroundColor: brandColor, + elevation: 0, + leading: Container(), + ), + body: WillPopScope( + onWillPop: () async { + return false; + }, + child: GetBuilder( + init: AutologinController(), + builder: (AutologinController c) { + return Stack( + alignment: Alignment.topCenter, + children: [ + if (c.errorText != '') + SvgPicture.asset( + 'assets/2/icon.svg', + height: 80, + width: 80, + ), + SizedBox( + width: widthSize(context), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (c.errorText != '') + SizedBox( + height: 120 + + MediaQuery.of(context).viewPadding.top + + AppBar().preferredSize.height, + ), + if (c.errorText == '') const Spacer(flex: 2), + c.errorText == '' + ? SvgPicture.asset("assets/autologin_loading.svg") + : Column( + children: [ + SvgPicture.asset( + 'assets/autologin_fail.svg', + height: 220, + width: 220, + ), + const SizedBox(height: 20), + TextWidget( + color: Colors.white, + fontSize: 20, + fontWeight: FontWeight.w300, + text: "autoLogin_failed".tr, + ), + const SizedBox(height: 20), + ], + ), + const Spacer(), + if (c.errorText == '') + Visibility( + visible: c.errorText == '', + child: Column( + children: [ + const SizedBox(height: 30), + TextWidget( + color: Colors.white, + fontSize: 18, + text: "auto_login".tr, + ), + ], + ), + ), + const Spacer(), + Container(), + const SizedBox(height: 30), + ], + ), + ), + ], + ); + }), + ), + ); + } +} diff --git a/lib/app/modules/availablePackages/bindings/available_packages_binding.dart b/lib/app/modules/availablePackages/bindings/available_packages_binding.dart new file mode 100644 index 0000000..1774cbc --- /dev/null +++ b/lib/app/modules/availablePackages/bindings/available_packages_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/available_packages_controller.dart'; + +class AvailablePackagesBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => AvailablePackagesController(), + ); + } +} diff --git a/lib/app/modules/availablePackages/controllers/available_packages_controller.dart b/lib/app/modules/availablePackages/controllers/available_packages_controller.dart new file mode 100644 index 0000000..ef32aa5 --- /dev/null +++ b/lib/app/modules/availablePackages/controllers/available_packages_controller.dart @@ -0,0 +1,79 @@ +// ignore_for_file: unnecessary_overrides, unrelated_type_equality_checks + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/modules/home/providers/language_currency.dart'; +import 'package:IQ/app/modules/home/providers/packages.dart'; +import 'package:IQ/app/modules/home/providers/service.dart'; + +import '../../home/models/packages_model.dart'; + +class AvailablePackagesController extends GetxController + with WidgetsBindingObserver { + final GlobalKey scaffoldKey = GlobalKey(); + bool fetchPackagesData = false; + // ignore: prefer_typing_uninitialized_variables + var fetchLoadingPackagesDataVar; + + Future onRefresh() async { + fetchPackagesData = false; + packages = null; + fetchLoadingPackagesDataVar = fetchLoadingPackagesData(); + update(); + } + + fetchLoadingPackagesData() async { + await getUserPackagesInforms(); + if (getUserPackagesInformsLoads) { + fetchPackagesData = true; + listOfPackages = packages?.data ?? []; + update(); + } + } + + String activiationType = '${service?.data?.profileName}'; + String subscriptionCurrency = languagesCurrencyModel?.data?.currency ?? ''; + String profileName = service?.data?.profileName ?? ''; + final oCcy = NumberFormat.currency( + locale: 'ar', + customPattern: '#,### \u00a4', + decimalDigits: 0, + symbol: '', + ); + String subscribed = languagesCurrencyModel?.data?.currency ?? ''; + List? listOfPackages = packages?.data ?? []; + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + snackBarText = 'back_twice'.tr; + } + } + + @override + void onInit() { + fetchLoadingPackagesDataVar = fetchLoadingPackagesData(); + WidgetsBinding.instance.addObserver(this); + + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} diff --git a/lib/app/modules/availablePackages/views/available_packages_view.dart b/lib/app/modules/availablePackages/views/available_packages_view.dart new file mode 100644 index 0000000..f21985d --- /dev/null +++ b/lib/app/modules/availablePackages/views/available_packages_view.dart @@ -0,0 +1,293 @@ +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; + +import '../controllers/available_packages_controller.dart'; + +class AvailablePackagesView extends GetView { + AvailablePackagesView({Key? key}) : super(key: key); + final GlobalKey scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + var stackedContainer = Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox(height: MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Container( + margin: const EdgeInsets.only(top: 10), + child: Align( + alignment: Alignment.bottomCenter, + child: Column( + children: [ + SvgPicture.asset( + 'assets/package.svg', + color: Colors.white, + height: 60, + width: 60, + ), + const SizedBox(height: 3), + TextWidget( + text: 'available_packages'.tr, + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.w300, + textAlign: TextAlign.center, + ), + const SizedBox(height: 10), + ], + ), + ), + ) + ], + ), + ); + return Directionality( + textDirection: + defaultLocale != "en" ? TextDirection.ltr : TextDirection.rtl, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: GetBuilder( + builder: (AvailablePackagesController availablePackagesController) { + return RefreshIndicator( + onRefresh: controller.onRefresh, + triggerMode: RefreshIndicatorTriggerMode.anywhere, + backgroundColor: Colors.white, + color: brandColor, + child: availablePackagesController.fetchPackagesData + ? Stack( + children: [ + Container( + margin: const EdgeInsets.only(top: 270), + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: controller.listOfPackages?.map( + (e) { + Widget widget(Color color) => Container( + height: 150, + margin: const EdgeInsets.only( + right: 25, + left: 25, + top: 10, + bottom: 5, + ), + padding: const EdgeInsets.only( + top: 5, + bottom: 5, + left: 10, + right: 10, + ), + decoration: BoxDecoration( + borderRadius: + const BorderRadius.all( + Radius.circular(20), + ), + color: Colors.white, + border: Border.all( + color: color, + width: 2, + ), + ), + child: Center( + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Column( + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + TextWidget( + text: controller + .subscriptionCurrency, + fontSize: 14, + ), + const SizedBox(height: 5), + TextWidget( + text: controller.oCcy + .format(e.price), + fontSize: 20, + ), + ], + ), + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + SizedBox( + width: 300, + child: TextWidget( + text: e.name, + fontSize: 24, + softWrap: true, + textAlign: + defaultLocale == + "en" + ? TextAlign + .left + : TextAlign + .right, + color: brandColor, + ), + ), + const SizedBox(height: 5), + TextWidget( + text: e.description, + fontSize: 15, + softWrap: false, + overflow: + TextOverflow.fade, + color: const Color( + 0xff7A7A7A), + ), + ], + ), + ), + ], + ), + ), + ); + if (e.name == controller.profileName) { + return Stack( + children: [ + widget(Colors.green), + Container( + height: 40, + width: defaultLocale == "en" + ? 85 + : 150, + margin: defaultLocale == "en" + ? const EdgeInsets.only( + right: 60, + ) + : const EdgeInsets.only( + left: 50, + ), + padding: const EdgeInsets.all(10), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + color: Color(0xff0B9721), + ), + child: Center( + child: TextWidget( + text: 'current_subscription'.tr, + color: Colors.white, + fontSize: 14, + ), + ), + ), + ], + ); + } + return widget(borderColor); + }, + ).toList() as List, + ), + ), + ), + stackedContainer + ], + ) + : Stack( + children: [ + Center( + child: CircularProgressIndicator( + color: brandColor, + ), + ), + stackedContainer + ], + ), + ); + }, + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/contact_us/bindings/contact_us_binding.dart b/lib/app/modules/contact_us/bindings/contact_us_binding.dart new file mode 100644 index 0000000..d995f08 --- /dev/null +++ b/lib/app/modules/contact_us/bindings/contact_us_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/contact_us_controller.dart'; + +class ContactUsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => ContactUsController(), + ); + } +} diff --git a/lib/app/modules/contact_us/controllers/contact_us_controller.dart b/lib/app/modules/contact_us/controllers/contact_us_controller.dart new file mode 100644 index 0000000..2d5ad28 --- /dev/null +++ b/lib/app/modules/contact_us/controllers/contact_us_controller.dart @@ -0,0 +1,38 @@ +// ignore_for_file: unnecessary_overrides + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/global/static_informs.dart'; + +class ContactUsController extends GetxController with WidgetsBindingObserver { + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + snackBarText = 'back_twice'.tr; + } + } + + @override + void onInit() { + WidgetsBinding.instance.addObserver(this); + + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} diff --git a/lib/app/modules/contact_us/views/contact_us_view.dart b/lib/app/modules/contact_us/views/contact_us_view.dart new file mode 100644 index 0000000..d34cd94 --- /dev/null +++ b/lib/app/modules/contact_us/views/contact_us_view.dart @@ -0,0 +1,635 @@ +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../controllers/contact_us_controller.dart'; + +class ContactUsView extends GetView { + ContactUsView({Key? key}) : super(key: key); + final GlobalKey scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Directionality( + textDirection: + defaultLocale != "en" ? TextDirection.ltr : TextDirection.rtl, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: Stack( + children: [ + Container( + margin: const EdgeInsets.only(top: 250), + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 35), + Container( + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + color: const Color(0xffF8F9FA), + borderRadius: BorderRadius.circular(13), + border: Border.all( + color: const Color(0xff8C5EF6).withOpacity(0.02), + width: 2, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const TextWidget( + text: "Phone Number", + fontSize: 16, + color: Color(0xff616F76), + ), + const SizedBox(height: 6), + Directionality( + textDirection: TextDirection.ltr, + child: Row( + children: [ + Row( + children: [ + Container( + margin: const EdgeInsets.only( + right: 12), + child: const TextWidget( + text: "Kut", + fontSize: 16, + color: Color(0xff6E6E6E), + ), + ), + InkWell( + onTap: () async { + await launchUrl( + Uri.parse('tel:6095'), + mode: LaunchMode + .externalApplication, + ); + }, + child: const TextWidget( + text: "6095", + fontSize: 18, + color: Color(0xff0C212C), + ), + ), + ], + ), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 12, + ), + child: Image.asset("assets/dot.png"), + ), + Row( + children: [ + Container( + margin: const EdgeInsets.only( + right: 12), + child: const TextWidget( + text: "Basra", + fontSize: 16, + color: Color(0xff6E6E6E), + ), + ), + InkWell( + onTap: () async { + await launchUrl( + Uri.parse('tel:6096'), + mode: LaunchMode + .externalApplication, + ); + }, + child: const TextWidget( + text: "6096", + fontSize: 18, + color: Color(0xff0C212C), + ), + ), + ], + ), + ], + ), + ), + ], + ), + const SizedBox(width: 16), + Container( + width: 50, + height: 50, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: brandColor, + shape: BoxShape.circle, + ), + child: SvgPicture.asset( + "assets/headphone.svg", + color: Colors.white, + height: 30, + width: 30, + ), + ), + ], + ), + ), + // email + const SizedBox(height: 16), + InkWell( + onTap: () async { + await launchUrl( + Uri.parse('mailto:info@fiberx.iq'), + mode: LaunchMode.externalApplication, + ); + }, + child: Container( + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + color: const Color(0xffF8F9FA), + borderRadius: BorderRadius.circular(13), + border: Border.all( + color: const Color(0xff8C5EF6).withOpacity(0.02), + width: 2, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextWidget( + text: "Email", + fontSize: 16, + color: Color(0xff616F76), + ), + SizedBox(height: 6), + TextWidget( + text: "Info@fiberx.iq", + fontSize: 18, + color: Color(0xff0C212C), + ), + ], + ), + const SizedBox(width: 28), + Container( + width: 50, + height: 50, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: brandColor, + shape: BoxShape.circle, + ), + child: SvgPicture.asset( + "assets/sms.svg", + color: Colors.white, + height: 30, + width: 30, + ), + ), + ], + ), + ), + ), + // facebook + const SizedBox(height: 16), + InkWell( + onTap: () async { + await launchUrl( + Uri.parse('https://www.facebook.com/FIBERX.IQ'), + mode: LaunchMode.externalApplication, + ); + }, + child: Container( + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + color: const Color(0xffF8F9FA), + borderRadius: BorderRadius.circular(13), + border: Border.all( + color: const Color(0xff8C5EF6).withOpacity(0.02), + width: 2, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextWidget( + text: "Facebook", + fontSize: 16, + color: Color(0xff616F76), + ), + SizedBox(height: 6), + TextWidget( + text: "fb.com/FIBERX.IQ", + fontSize: 18, + color: Color(0xff0C212C), + ), + ], + ), + const SizedBox(width: 28), + Container( + width: 50, + height: 50, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: brandColor, + shape: BoxShape.circle, + ), + child: SvgPicture.asset( + "assets/facebook.svg", + color: Colors.white, + height: 30, + width: 30, + ), + ), + ], + ), + ), + ), + // instgram + const SizedBox(height: 16), + InkWell( + onTap: () async { + await launchUrl( + Uri.parse('https://www.instagram.com/fiberx_iq/'), + mode: LaunchMode.externalApplication, + ); + }, + child: Container( + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + color: const Color(0xffF8F9FA), + borderRadius: BorderRadius.circular(13), + border: Border.all( + color: const Color(0xff8C5EF6).withOpacity(0.02), + width: 2, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextWidget( + text: "Instagram", + fontSize: 16, + color: Color(0xff616F76), + ), + SizedBox(height: 6), + TextWidget( + text: "instagram.com/fiberx_iq", + fontSize: 18, + color: Color(0xff0C212C), + ), + ], + ), + const SizedBox(width: 28), + Container( + width: 50, + height: 50, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: brandColor, + shape: BoxShape.circle, + ), + child: SvgPicture.asset( + "assets/instgram.svg", + color: Colors.white, + height: 30, + width: 30, + ), + ), + ], + ), + ), + ), + // linkedin + const SizedBox(height: 16), + InkWell( + onTap: () async { + await launchUrl( + Uri.parse( + 'https://www.linkedin.com/company/fiberx-iq/'), + mode: LaunchMode.externalApplication, + ); + }, + child: Container( + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + color: const Color(0xffF8F9FA), + borderRadius: BorderRadius.circular(13), + border: Border.all( + color: const Color(0xff8C5EF6).withOpacity(0.02), + width: 2, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextWidget( + text: "LinkedIn", + fontSize: 16, + color: Color(0xff616F76), + ), + SizedBox(height: 6), + TextWidget( + text: "linkedin.com/company/fiberx-iq", + fontSize: 18, + color: Color(0xff0C212C), + ), + ], + ), + const SizedBox(width: 28), + Container( + width: 50, + height: 50, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: brandColor, + shape: BoxShape.circle, + ), + child: SvgPicture.asset( + "assets/linkedin.svg", + color: Colors.white, + height: 30, + width: 30, + ), + ), + ], + ), + ), + ), + // youtube + const SizedBox(height: 16), + InkWell( + onTap: () async { + await launchUrl( + Uri.parse('https://www.youtube.com/@FiberXIRAQ'), + mode: LaunchMode.externalApplication, + ); + }, + child: Container( + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + color: const Color(0xffF8F9FA), + borderRadius: BorderRadius.circular(13), + border: Border.all( + color: const Color(0xff8C5EF6).withOpacity(0.02), + width: 2, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextWidget( + text: "Youtube", + fontSize: 16, + color: Color(0xff616F76), + ), + SizedBox(height: 6), + TextWidget( + text: "FiberXIRAQ", + fontSize: 18, + color: Color(0xff0C212C), + ), + ], + ), + const SizedBox(width: 28), + Container( + width: 50, + height: 50, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: brandColor, + shape: BoxShape.circle, + ), + child: SvgPicture.asset( + "assets/youtube.svg", + color: Colors.white, + height: 30, + width: 30, + ), + ), + ], + ), + ), + ), + // website + const SizedBox(height: 16), + InkWell( + onTap: () async { + await launchUrl( + Uri.parse('https://fiberx.iq/'), + mode: LaunchMode.externalApplication, + ); + }, + child: Container( + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(horizontal: 20), + decoration: BoxDecoration( + color: const Color(0xffF8F9FA), + borderRadius: BorderRadius.circular(13), + border: Border.all( + color: const Color(0xff8C5EF6).withOpacity(0.02), + width: 2, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextWidget( + text: "Website", + fontSize: 16, + color: Color(0xff616F76), + ), + SizedBox(height: 6), + TextWidget( + text: "fiberx.iq", + fontSize: 18, + color: Color(0xff0C212C), + ), + ], + ), + const SizedBox(width: 28), + Container( + width: 50, + height: 50, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: brandColor, + shape: BoxShape.circle, + ), + child: SvgPicture.asset( + "assets/global.svg", + color: Colors.white, + height: 30, + width: 30, + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Stack( + children: [ + Container( + height: 230, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState + ?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Container( + alignment: Alignment.center, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 30), + SvgPicture.asset( + 'assets/drawer icons/icon5.svg', + height: 50, + width: 50, + color: Colors.white, + ), + const SizedBox(height: 20), + const TextWidget( + text: "Contact Us", + fontSize: 28, + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/dataUsage/bindings/data_usage_binding.dart b/lib/app/modules/dataUsage/bindings/data_usage_binding.dart new file mode 100644 index 0000000..075f34c --- /dev/null +++ b/lib/app/modules/dataUsage/bindings/data_usage_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/data_usage_controller.dart'; + +class DataUsageBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => DataUsageController(), + ); + } +} diff --git a/lib/app/modules/dataUsage/controllers/data_usage_controller.dart b/lib/app/modules/dataUsage/controllers/data_usage_controller.dart new file mode 100644 index 0000000..ac5334e --- /dev/null +++ b/lib/app/modules/dataUsage/controllers/data_usage_controller.dart @@ -0,0 +1,22 @@ +// ignore_for_file: unnecessary_overrides + + +import 'package:get/get.dart'; + +class DataUsageController extends GetxController { + + @override + void onInit() { + + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + } +} diff --git a/lib/app/modules/dataUsage/views/data_usage_view.dart b/lib/app/modules/dataUsage/views/data_usage_view.dart new file mode 100644 index 0000000..9c0c358 --- /dev/null +++ b/lib/app/modules/dataUsage/views/data_usage_view.dart @@ -0,0 +1,454 @@ +import 'dart:io'; + +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' as td; +import 'package:flutter_svg/flutter_svg.dart'; + +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; +import 'package:IQ/app/global/converted_bytes.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; +import 'package:IQ/app/modules/home/models/traffic_model.dart'; +import 'package:IQ/app/modules/home/providers/traffic.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; +import 'package:syncfusion_flutter_charts/charts.dart'; + +import '../controllers/data_usage_controller.dart'; +import 'dart:convert'; + +import 'package:IQ/app/global/snono_encrypt.dart'; + +class DataUsageView extends StatefulWidget { + const DataUsageView({Key? key}) : super(key: key); + + @override + State createState() => _DataUsageViewState(); +} + +DateTime monthOfData = DateTime.now(); + +class _DataUsageViewState extends State + with WidgetsBindingObserver { + final GlobalKey scaffoldKey = GlobalKey(); + bool fetchDataUsageData = false; + + Future? getTraffic; + bool? changeMonthLoading; + Traffic? traffic; + List? list = []; + Future? getTrafficInforms() async { + await getTodayTraffic(); + setState(() {}); + + String payload = AES.encrypt( + data: jsonEncode({ + "report_type": "daily", + "month": monthOfData.month, + "year": monthOfData.year, + "user_id": null, + }), + passpharse: 'abcdefghijuklmno0123456789012345', + ); + var value = await APIService.post('traffic', payload); + traffic = Traffic.fromJson(jsonDecode(value)); + chartData = traffic?.data?.totalReal?.map( + (e) { + DateTime lastDayOfMonth = DateTime( + monthOfData.year, + monthOfData.month + 1, + 0, + ); + int? day; + // ignore: unnecessary_null_comparison + if (day == null) { + day = (traffic?.data?.totalReal?.indexOf(e))! + 1; + } else { + if ((traffic?.data?.totalReal?.indexOf(e))! > 0 && + (traffic?.data?.totalReal?.indexOf(e))! < lastDayOfMonth.day) { + day = (traffic?.data?.totalReal?.indexOf(e))! + 7; + } + } + return DataUsage( + DateTime( + monthOfData.year, + monthOfData.month, + day, + ), + e.toDouble(), + ); + }, + ).toList(); + changeMonthLoading = false; + fetchDataUsageData = true; + setState(() {}); + return traffic; + } + + List? chartData; + TooltipBehavior? tooltipBehavior; + String directionsImage = + defaultLocale == "en" ? 'assets/next.svg' : "assets/left-arrow.svg"; + String directionsImage2 = + defaultLocale == "en" ? 'assets/left-arrow.svg' : "assets/next.svg"; + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + directionsImage = + defaultLocale == "en" ? 'assets/next.svg' : "assets/left-arrow.svg"; + directionsImage2 = + defaultLocale == "en" ? 'assets/left-arrow.svg' : "assets/next.svg"; + snackBarText = 'back_twice'.tr; + } + } + + @override + void initState() { + getTraffic = getTrafficInforms(); + tooltipBehavior = TooltipBehavior(enable: true); + WidgetsBinding.instance.addObserver(this); + super.initState(); + } + + @override + void dispose() { + super.dispose(); + WidgetsBinding.instance.removeObserver(this); + } + + @override + Widget build(BuildContext context) { + var stackedContainer = Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox(height: MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + TextWidget( + text: 'data_usage_screen_title'.tr, + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.w300, + textAlign: TextAlign.center, + ), + SvgPicture.asset( + 'assets/trafic.svg', + color: Colors.white, + fit: BoxFit.contain, + height: 60, + width: 60, + ), + Directionality( + textDirection: defaultLocale == "en" + ? td.TextDirection.ltr + : td.TextDirection.rtl, + child: TextWidget( + text: totalGBs, + // text: '$totalGBs', + color: Colors.white, + fontSize: 32, + fontWeight: FontWeight.bold, + textAlign: TextAlign.center, + ), + ), + ], + ), + ], + ), + ); + return Directionality( + textDirection: + defaultLocale != "en" ? td.TextDirection.ltr : td.TextDirection.rtl, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: fetchDataUsageData + ? Stack( + children: [ + Column( + children: [ + const SizedBox(height: 270), + Container( + margin: defaultLocale == "en" + ? const EdgeInsets.only( + left: 15, + bottom: 10, + ) + : const EdgeInsets.only( + right: 15, + bottom: 10, + ), + child: Align( + alignment: defaultLocale == "en" + ? Alignment.centerLeft + : Alignment.centerRight, + child: TextWidget( + text: 'data_usage_title'.tr, + fontSize: 22, + color: brandColor, + fontWeight: FontWeight.w400, + ), + ), + ), + Container( + height: 400, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + border: Border.all( + color: borderColor, + width: 1, + ), + ), + padding: const EdgeInsets.all(20), + margin: const EdgeInsets.only(right: 10, left: 10), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 20), + margin: const EdgeInsets.symmetric(vertical: 20), + child: GetBuilder( + builder: (DataUsageController c) { + return changeMonthLoading == null || + changeMonthLoading != true + ? SfCartesianChart( + tooltipBehavior: tooltipBehavior, + backgroundColor: Colors.white, + borderColor: borderColor, + borderWidth: 0, + isTransposed: false, + margin: const EdgeInsets.symmetric( + horizontal: 15), + plotAreaBackgroundColor: Colors.white, + plotAreaBorderColor: borderColor, + plotAreaBorderWidth: 0, + selectionGesture: + ActivationMode.singleTap, + selectionType: SelectionType.point, + enableAxisAnimation: true, + primaryXAxis: DateTimeAxis( + edgeLabelPlacement: + EdgeLabelPlacement.shift, + borderWidth: 1, + borderColor: Colors.white, + labelAlignment: LabelAlignment.center, + majorGridLines: const MajorGridLines( + width: 0, + color: Colors.transparent, + ), + ), + primaryYAxis: NumericAxis( + axisLabelFormatter: + (AxisLabelRenderDetails details) { + return ChartAxisLabel( + formatBytes( + details.value.toInt(), 0), + details.textStyle, + ); + }, + borderWidth: 1, + borderColor: Colors.white, + labelAlignment: LabelAlignment.center, + majorGridLines: MajorGridLines( + width: 1, color: borderColor), + ), + series: [ + LineSeries( + name: 'Total', + dataSource: chartData ?? [], + xValueMapper: + (DataUsage xAxis, _) => + xAxis.monthDay, + yValueMapper: + (DataUsage yAxis, _) => + yAxis.bytes, + color: brandColor, + enableTooltip: true, + ), + ], + ) + : Center( + child: CircularProgressIndicator( + color: brandColor, + ), + ); + }, + ), + ), + ), + Container( + margin: const EdgeInsets.only(top: 25), + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + style: ButtonStyle( + shape: MaterialStateProperty.all( + const CircleBorder(), + ), + ), + onPressed: () { + if (monthOfData.month > 1) { + changeMonthLoading = true; + chartData = []; + monthOfData = DateTime( + monthOfData.year, + monthOfData.month - 1, + ); + getTraffic = getTrafficInforms(); + setState(() {}); + } + }, + child: SvgPicture.asset( + directionsImage, + height: 35, + width: 35, + ), + ), + const SizedBox(width: 50), + GetBuilder( + builder: (DataUsageController c) { + return TextWidget( + text: DateFormat('MMMM').format( + DateTime( + monthOfData.year, + monthOfData.month, + ), + ), + fontSize: 22, + color: Colors.black, + fontWeight: FontWeight.w500, + ); + }, + ), + const SizedBox(width: 50), + TextButton( + style: ButtonStyle( + shape: MaterialStateProperty.all( + const CircleBorder(), + ), + ), + onPressed: () { + if (monthOfData.month < 12) { + changeMonthLoading = true; + chartData = []; + monthOfData = DateTime( + monthOfData.year, + monthOfData.month + 1, + ); + getTraffic = getTrafficInforms(); + setState(() {}); + } + }, + child: SvgPicture.asset( + directionsImage2, + height: 35, + width: 35, + ), + ), + ], + ), + ), + ), + ], + ), + stackedContainer, + ], + ) + : Stack( + children: [ + Center( + child: CircularProgressIndicator( + color: brandColor, + ), + ), + stackedContainer, + ], + ), + ), + ), + ); + } +} + +class DataUsage { + DataUsage(this.monthDay, this.bytes); + final DateTime monthDay; + final double bytes; +} diff --git a/lib/app/modules/drawerSide/bindings/drawer_side_binding.dart b/lib/app/modules/drawerSide/bindings/drawer_side_binding.dart new file mode 100644 index 0000000..37ed46a --- /dev/null +++ b/lib/app/modules/drawerSide/bindings/drawer_side_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/drawer_side_controller.dart'; + +class DrawerSideBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => DrawerSideController(), + ); + } +} diff --git a/lib/app/modules/drawerSide/controllers/drawer_side_controller.dart b/lib/app/modules/drawerSide/controllers/drawer_side_controller.dart new file mode 100644 index 0000000..e30b52c --- /dev/null +++ b/lib/app/modules/drawerSide/controllers/drawer_side_controller.dart @@ -0,0 +1,19 @@ +// ignore_for_file: unnecessary_overrides + +import 'package:get/get.dart'; + +class DrawerSideController extends GetxController { + + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() {} +} diff --git a/lib/app/modules/drawerSide/views/drawer_side_view.dart b/lib/app/modules/drawerSide/views/drawer_side_view.dart new file mode 100644 index 0000000..39c5c3d --- /dev/null +++ b/lib/app/modules/drawerSide/views/drawer_side_view.dart @@ -0,0 +1,287 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/login/bindings/login_binding.dart'; +import 'package:IQ/app/modules/login/views/login_view.dart'; +import 'package:IQ/app/routes/app_pages.dart'; +import 'package:IQ/main.dart'; + +class DrawerSideView extends StatefulWidget { + const DrawerSideView({Key? key}) : super(key: key); + + @override + State createState() => _DrawerSideViewState(); +} + +class _DrawerSideViewState extends State + with WidgetsBindingObserver { + final List itemsStrings = [ + 'drawer_home'.tr, + 'drawer_dataUsage'.tr, + // 'drawer_dataStream'.tr, + 'drawer_availablePackages'.tr, + 'drawer_wifi_test'.tr, + 'drawer_notifications'.tr, + 'drawer_logout'.tr, + 'drawer_support'.tr, + 'drawer_aboutApp'.tr, + ]; + + final List itemsIcons = [ + 'assets/drawer icons/icon1.svg', + 'assets/drawer icons/icon2.svg', + // 'assets/dataflow.svg', + 'assets/drawer icons/icon3.svg', + 'assets/drawer icons/icon2.svg', + 'assets/drawer icons/icon6.svg', + 'assets/drawer icons/icon7.svg', + 'assets/drawer icons/icon5.svg', + 'assets/drawer icons/icon8.svg', + ]; + AlignmentGeometry alignment = + defaultLocale == "en" ? Alignment.centerLeft : Alignment.centerRight; + EdgeInsetsGeometry? marginAbout = defaultLocale == "en" + ? const EdgeInsets.only( + left: 60.0, + ) + : const EdgeInsets.only( + right: 80.0, + ); + EdgeInsetsGeometry? marginOthers = defaultLocale == "en" + ? const EdgeInsets.only(left: 60.0, top: 5) + : const EdgeInsets.only(right: 80.0, top: 5); + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + alignment = + defaultLocale == "en" ? Alignment.centerLeft : Alignment.centerRight; + marginOthers = defaultLocale == "en" + ? const EdgeInsets.only(left: 60.0, top: 5) + : const EdgeInsets.only(right: 80.0, top: 5); + } + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + } + + @override + void dispose() { + super.dispose(); + WidgetsBinding.instance.removeObserver(this); + } + + @override + Widget build(BuildContext context) { + return SizedBox( + width: widthSize(context) * 0.8, + child: Drawer( + backgroundColor: Colors.white, + child: Stack( + children: [ + SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 250), + ...itemsStrings.map( + (item) { + return Container( + margin: const EdgeInsets.symmetric(vertical: 8.0), + child: TextButton( + onPressed: () { + if (item == 'drawer_logout'.tr) { + Get.back(); + storage.remove('token'); + isExpired = false; + token = null; + setState(() {}); + Get.offAll( + () => LoginView(), + binding: LoginBinding(), + ); + } else if (item == 'drawer_dataUsage'.tr) { + Get.back(); + Future.delayed( + const Duration(milliseconds: 300), + () => Get.offNamed(Routes.DATA_USAGE), + ); + } + // else if (item == 'drawer_dataStream'.tr) { + // Get.back(); + // Future.delayed( + // const Duration(milliseconds: 300), + // () => Get.offNamed(Routes.LIVE_DATA), + // ); + // } + else if (item == 'drawer_availablePackages'.tr) { + Get.back(); + Future.delayed( + const Duration(milliseconds: 300), + () => Get.offNamed(Routes.AVAILABLE_PACKAGES), + ); + } else if (item == 'drawer_wifi_test'.tr) { + Get.back(); + Future.delayed( + const Duration(milliseconds: 300), + () => Get.offNamed(Routes.WIFI_TEST), + ); + } else if (item == 'drawer_notifications'.tr) { + Get.back(); + Future.delayed( + const Duration(milliseconds: 300), + () => Get.offNamed(Routes.NOTIFICATIONS_SCREEN), + ); + } else if (item == 'drawer_support'.tr) { + Get.back(); + Future.delayed( + const Duration(milliseconds: 300), + () => Get.offNamed(Routes.CONTACT_US), + ); + } else if (item == 'drawer_aboutApp'.tr) { + Get.back(); + Future.delayed( + const Duration(milliseconds: 300), + () => Get.offNamed(Routes.ABOUT), + ); + } else { + Get.back(); + Future.delayed( + const Duration(milliseconds: 300), + () => Get.offNamed(Routes.HOME), + ); + } + }, + child: item != "drawer_aboutApp".tr + ? Stack( + alignment: const Alignment(0, -2.5), + children: [ + if (item == "drawer_support".tr) + Align( + child: Container( + margin: const EdgeInsets.only( + right: 10, + left: 10, + ), + child: const Divider(), + ), + ), + Container( + margin: marginOthers, + child: Align( + alignment: alignment, + child: TextWidget( + color: Colors.black87, + fontSize: 18, + text: item, + fontWeight: FontWeight.normal, + textAlign: TextAlign.right, + ), + ), + ), + Container( + margin: + const EdgeInsets.only(right: 25.0), + child: Align( + alignment: alignment, + child: item != 'drawer_dataStream'.tr + ? SvgPicture.asset( + itemsIcons[ + itemsStrings.indexOf(item)], + color: Colors.black, + width: 33, + height: 33, + ) + : SvgPicture.asset( + itemsIcons[ + itemsStrings.indexOf(item)], + color: Colors.black, + width: 25, + height: 25, + ), + ), + ), + ], + ) + : Stack( + children: [ + Container( + margin: marginAbout, + child: Align( + alignment: defaultLocale == "en" + ? Alignment.centerLeft + : Alignment.centerRight, + child: TextWidget( + color: Colors.black87, + fontSize: 18, + text: item, + fontWeight: FontWeight.normal, + textAlign: TextAlign.right, + ), + ), + ), + Container( + margin: + const EdgeInsets.only(right: 25.0), + child: Align( + alignment: defaultLocale == "en" + ? Alignment.centerLeft + : Alignment.centerRight, + child: SvgPicture.asset( + itemsIcons[ + itemsStrings.indexOf(item)], + color: Colors.black, + width: 33, + height: 33, + ), + ), + ), + ], + ), + ), + ); + }, + ) + ], + ), + ), + Container( + height: 250, + width: widthSize(context), + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + ), + Container( + margin: const EdgeInsets.only(top: 80), + child: Align( + alignment: Alignment.topCenter, + child: SvgPicture.asset( + 'assets/2/icon.svg', + height: 60, + width: 60, + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/modules/fillCard/bindings/fill_card_binding.dart b/lib/app/modules/fillCard/bindings/fill_card_binding.dart new file mode 100644 index 0000000..6caad50 --- /dev/null +++ b/lib/app/modules/fillCard/bindings/fill_card_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/fill_card_controller.dart'; + +class FillCardBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => FillCardController(), + ); + } +} diff --git a/lib/app/modules/fillCard/controllers/fill_card_controller.dart b/lib/app/modules/fillCard/controllers/fill_card_controller.dart new file mode 100644 index 0000000..f194a12 --- /dev/null +++ b/lib/app/modules/fillCard/controllers/fill_card_controller.dart @@ -0,0 +1,143 @@ +// ignore_for_file: unnecessary_overrides + +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/global/login_snackbar.dart'; +import 'package:IQ/app/global/snono_encrypt.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +class FillCardController extends GetxController with WidgetsBindingObserver { + final formKey = GlobalKey(); + + String? secretNumber; + bool inputsEntered = false; + bool succeededFill = false; + onChangeSecretNumberInput(secretNumberInput) { + secretNumber = secretNumberInput; + update(); + } + + Future redeemSecretNumber() async { + if (secretNumber != null) { + inputsEntered = true; + update(); + if (!(formKey.currentState?.validate())!) { + inputsEntered = true; + update(); + return; + } + + String payload = AES.encrypt( + data: jsonEncode({"pin": "$secretNumber"}), + passpharse: 'abcdefghijuklmno0123456789012345', + ); + + var value = await APIService.post('redeem', payload, true).timeout( + const Duration(seconds: 10), + onTimeout: () { + inputsEntered = false; + update(); + snack('autologin_failed_messageNull'.tr); + }, + ); + if (value.runtimeType == int) { + if (value == 0) { + secretNumber = null; + inputsEntered = false; + update(); + + snack('autologin_failed_message0'.tr); + } + if (value == -2) { + secretNumber = null; + inputsEntered = false; + update(); + snack('autologin_failed_message'.tr); + } + if (value == 401) { + secretNumber = null; + inputsEntered = false; + update(); + snack('autologin_failed_messageNull'.tr); + } + return; + } + + var data = jsonDecode(value); + debugPrint("value = $value"); + + if (data["status"] == 200) { + inputsEntered = false; + succeededFill = true; + secretNumber = null; + update(); + FocusManager.instance.primaryFocus?.unfocus(); + return; + } else { + inputsEntered = false; + succeededFill = false; + secretNumber = null; + update(); + FocusManager.instance.primaryFocus?.unfocus(); + Get.defaultDialog( + title: '', + titlePadding: const EdgeInsets.all(0), + content: TextWidget( + text: 'wrong_entered_card_secret_num_error'.tr, + color: Colors.black, + fontSize: 18, + ), + actions: [ + TextButton( + onPressed: () { + Get.back(); + }, + child: TextWidget( + text: 'entered_card_secret_num'.tr, + color: brandColor, + fontSize: 20, + ), + ) + ], + ); + } + } + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + textDirection = + defaultLocale == "en" ? TextDirection.ltr : TextDirection.rtl; + snackBarText = 'back_twice'.tr; + } + } + + @override + void onInit() { + WidgetsBinding.instance.addObserver(this); + + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} diff --git a/lib/app/modules/fillCard/views/fill_card_view.dart b/lib/app/modules/fillCard/views/fill_card_view.dart new file mode 100644 index 0000000..38ff9fa --- /dev/null +++ b/lib/app/modules/fillCard/views/fill_card_view.dart @@ -0,0 +1,317 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_field.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; +import 'package:IQ/app/modules/home/controllers/home_controller.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; +import 'package:IQ/app/routes/app_pages.dart'; + +import '../controllers/fill_card_controller.dart'; + +class FillCardView extends GetView { + FillCardView({Key? key}) : super(key: key); + final GlobalKey scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Directionality( + textDirection: + defaultLocale == "en" ? TextDirection.rtl : TextDirection.ltr, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: GetBuilder( + builder: (FillCardController c) { + return Stack( + children: [ + !c.inputsEntered + ? !c.succeededFill + ? Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 330), + Container( + margin: + const EdgeInsets.symmetric(horizontal: 22), + child: Align( + alignment: defaultLocale == "en" + ? Alignment.centerLeft + : Alignment.centerRight, + child: TextWidget( + text: 'card_top-up'.tr, + textAlign: TextAlign.left, + fontSize: 22, + fontWeight: FontWeight.w500, + color: brandColor, + ), + ), + ), + FormBuilder( + key: controller.formKey, + child: BuildTextField( + hintTextDirection: textDirection, + textDirection: textDirection, + onChanged: + controller.onChangeSecretNumberInput, + signup: true, + filled: true, + inputColor: Colors.black, + fillColor: Colors.white, + height: heightSize(context) * 0.1, + name: 'card_secret_number', + hintText: 'card_secret_num'.tr, + obscureText: false, + margin: const EdgeInsets.only( + top: 20, + right: 20.0, + left: 20.0, + ), + onEditingComplete: () { + FocusScope.of(context).unfocus(); + }, + validator: FormBuilderValidators.compose( + [ + FormBuilderValidators.required( + errorText: + 'card_secret_num_validation'.tr, + ), + ], + ), + keyboardType: TextInputType.number, + errorMaxLines: 2, + ), + ), + const SizedBox(height: 20), + Container( + width: widthSize(context), + height: 60, + decoration: const BoxDecoration( + gradient: LinearGradient( + colors: [ + Color(0xFF4009C0), + Color(0xFF8C5EF6) + ], // Gradient colors + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + borderRadius: + BorderRadius.all(Radius.circular(5)), + ), + margin: const EdgeInsets.symmetric( + horizontal: 15, vertical: 29), + child: TextButton( + onPressed: controller.redeemSecretNumber, + child: GetBuilder( + builder: (HomeController c) { + return TextWidget( + text: 'entered_card_secret_num'.tr, + fontSize: 18, + fontWeight: FontWeight.normal, + color: Colors.white, + ); + }, + ), + ), + ), + const Spacer(), + TextButton( + onPressed: () { + Get.offNamed(Routes.HOME); + }, + child: Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: brandColor, + width: 1, + ), + ), + ), + child: TextWidget( + color: brandColor, + fontSize: 26, + text: 'backfrom_card_secret_num'.tr, + fontWeight: FontWeight.w400, + ), + ), + ), + const SizedBox(height: 30), + ], + ) + : Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 330), + SvgPicture.asset( + 'assets/success_fill.svg', + width: 200, + height: 200, + ), + const SizedBox(height: 20), + TextWidget( + text: 'Top_up_status'.tr, + color: brandColor, + fontSize: 22, + ), + const Spacer(), + TextButton( + onPressed: () { + Get.offNamed(Routes.HOME); + }, + child: Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: brandColor, + width: 1, + ), + ), + ), + child: TextWidget( + color: brandColor, + fontSize: 20, + text: 'backfrom_card_secret_num'.tr, + fontWeight: FontWeight.w400, + ), + ), + ), + const SizedBox(height: 20), + ], + ), + ) + : Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 330), + CircularProgressIndicator( + color: brandColor, + strokeWidth: 2, + ), + const SizedBox(height: 30), + TextWidget( + text: 'Top_up_status_waiting'.tr, + color: Colors.black, + fontSize: 22, + ), + ], + ), + ), + Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + SizedBox( + height: MediaQuery.of(context).viewPadding.top, + ), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Container( + margin: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + TextWidget( + text: 'subscription_type'.tr, + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.w300, + textAlign: TextAlign.start, + ), + const SizedBox(height: 5), + GetBuilder( + init: HomeController(), + builder: (HomeController c) { + return TextWidget( + text: c.profileName ?? ' . . . ', + color: Colors.white, + fontSize: 32, + fontWeight: FontWeight.bold, + textAlign: TextAlign.center, + ); + }), + ], + ), + ), + const SizedBox(height: 5), + ], + ), + ), + ], + ); + }, + ), + ), + ); + } +} diff --git a/lib/app/modules/home/bindings/home_binding.dart b/lib/app/modules/home/bindings/home_binding.dart new file mode 100644 index 0000000..d08a80d --- /dev/null +++ b/lib/app/modules/home/bindings/home_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/home_controller.dart'; + +class HomeBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => HomeController(), + ); + } +} diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart new file mode 100644 index 0000000..41cd8a0 --- /dev/null +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -0,0 +1,269 @@ +// ignore_for_file: unnecessary_overrides, unrelated_type_equality_checks + +import 'dart:io'; + +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' as td; +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; +import 'package:logger/logger.dart'; +import 'package:overlay_support/overlay_support.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/modules/home/models/notifications_model.dart'; +import 'package:IQ/app/modules/home/providers/dashboard.dart'; +import 'package:IQ/app/modules/home/providers/language_currency.dart'; +import 'package:IQ/app/modules/home/providers/notifications.dart'; +import 'package:IQ/app/modules/home/providers/service.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; + +String? mtoken = ""; + +class HomeController extends GetxController with WidgetsBindingObserver { + final GlobalKey key = GlobalKey(); + int current = 0; + final slidersImages = [ + "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg", + "https://www.whoa.in/201604-Whoa/-natural-wallpaper-ultra-hd-4k-images-wallpapers.jpg", + "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg", + "https://www.whoa.in/201604-Whoa/-natural-wallpaper-ultra-hd-4k-images-wallpapers.jpg", + "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg", + "https://www.whoa.in/201604-Whoa/-natural-wallpaper-ultra-hd-4k-images-wallpapers.jpg", + ]; + onPageChanged(index, _) { + current = index; + update(); + } + + /// + late final FirebaseMessaging _messaging; + PushNotification? notificationInfo; + Future _firebaseMessagingBackgroundHandler( + RemoteMessage message) async {} + + void registerNotification() async { + // 2. Instantiate Firebase Messaging + _messaging = FirebaseMessaging.instance; + + FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); + + // 3. On iOS, this helps to take the user permissions + NotificationSettings settings = await _messaging.requestPermission( + alert: true, + badge: true, + provisional: false, + sound: true, + ); + + if (settings.authorizationStatus == AuthorizationStatus.authorized) { + // For handling the received notifications + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + // Parse the message received + PushNotification notification = PushNotification( + title: message.notification?.title, + body: message.notification?.body, + ); + + notificationInfo = notification; + update(); + + if (notificationInfo != null) { + // For displaying the notification as an overlay + showSimpleNotification( + Text(notificationInfo!.title!), + subtitle: Text(notificationInfo!.body!), + background: Colors.cyan.shade700, + duration: const Duration(seconds: 2), + ); + } + }); + } else {} + } + +// For handling notification when the app is in terminated state + checkForInitialMessage() async { + await FirebaseMessaging.instance.getToken().then((token) { + Logger().e("token : $token"); + mtoken = token; + }); + + RemoteMessage? initialMessage = + await FirebaseMessaging.instance.getInitialMessage(); + + if (initialMessage != null) { + PushNotification notification = PushNotification( + title: initialMessage.notification?.title, + body: initialMessage.notification?.body, + ); + notificationInfo = notification; + update(); + } + } + + // + String remainingDays = dashboard?.data?.remainingDays ?? ''; + String remainingIcon = "assets/home_icons/remaining_days.svg"; + String? profileName = service?.data?.profileName ?? ' . . . '; + String fullName = + '${user?.data?.firstname ?? ""} ${user?.data?.lastname ?? ""}'; + String loginName = '${user?.data?.username}'; + String subscriptionPrice = ''; + String expireDate = + '${service?.data?.expiration?.split(' ')[1]} ${service?.data?.expiration?.split(' ')[0]}'; + + int? remainingTraffic = dashboard?.data?.remainingTraffic; + + String availableBalance = + '${languagesCurrencyModel?.data?.currency ?? ''} ${dashboard?.data?.balance}'; + + /// + String connectionIcon = "assets/home_icons/connected.svg"; + String connectionStatusText = 'connectionStatusText'.tr; + String? floatButtonActivation; + String activiationIcon = "assets/home_icons/active.svg"; + String activiationStatusText = 'activiationStatusText'.tr; + + activationStatus() { + final oCcy = NumberFormat.currency( + locale: 'ar', + customPattern: '#,### \u00a4', + decimalDigits: 0, + symbol: '${languagesCurrencyModel?.data?.currency}', + ); + remainingDays = dashboard?.data?.remainingDays ?? ''; + remainingIcon = "assets/home_icons/remaining_days.svg"; + profileName = service?.data?.profileName ?? ' . . . '; + fullName = '${user?.data?.firstname ?? ""} ${user?.data?.lastname ?? ""}'; + loginName = '${user?.data?.username}'; + + subscriptionPrice = oCcy.format(service?.data?.price); + expireDate = + '${service?.data?.expiration?.split(' ')[1]} ${service?.data?.expiration?.split(' ')[0]}'; + availableBalance = + '${languagesCurrencyModel?.data?.currency ?? ''} ${dashboard?.data?.balance}'; + remainingTraffic = dashboard?.data?.remainingTraffic; + + if (dashboard?.data?.remainingDays != '') { + if (dashboard?.data?.remainingDays != '0') { + remainingDays = dashboard?.data?.remainingDays ?? '!'; + } else { + remainingDays = '!'; + } + } else { + remainingDays = '!'; + } + if (service?.data?.status != null) { + if (service?.data?.status == true) { + connectionIcon = "assets/home_icons/connected.svg"; + connectionStatusText = 'connectionStatusText'.tr; + } else { + connectionIcon = "assets/home_icons/disconnected.svg"; + connectionStatusText = 'connectionStatusTextOffiline'.tr; + } + } else { + connectionIcon = "assets/home_icons/disconnected.svg"; + connectionStatusText = 'connectionStatusTextOffiline'.tr; + } + if (service?.data?.subscriptionStatus?.status != null) { + if (service?.data?.subscriptionStatus?.status == true) { + activiationIcon = "assets/home_icons/active.svg"; + activiationStatusText = 'activiationStatusTextactive'.tr; + floatButtonActivation = '!floatButtonActivation'.tr; + } else { + activiationIcon = "assets/home_icons/unactive.svg"; + activiationStatusText = 'activiationStatusText'.tr; + floatButtonActivation = 'floatButtonActivation'.tr; + } + } else { + activiationIcon = "assets/home_icons/unactive.svg"; + activiationStatusText = 'activiationStatusTextactive'.tr; + floatButtonActivation = 'floatButtonActivation'.tr; + } + update(); + } + + Future onRefresh() async { + dashboard = null; + user = null; + service = null; + languagesCurrencyModel = null; + fetchHomeData = false; + notifications = null; + fetchLoadingHomeDataVar = fetchLoadingHomeData(); + update(); + } + +// ignore: prefer_typing_uninitialized_variables + var fetchLoadingHomeDataVar; + bool fetchHomeData = false; + fetchLoadingHomeData() async { + await getLanguageCurrencyInforms(); + await getUserDashboardInforms(); + await getUserNotificationsInforms("/2"); + await getUserServiceInforms(); + await getUserInforms(); + if (getUserDashboardInformsLoads && + getUserServiceInformsLoads && + getUserInformsLoads && + getUserNotificationsInformsLoads) { + activationStatus(); + fetchHomeData = true; + update(); + } + } + + /// + List? listOfNotification = notifications?.data; + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + textDirection = + defaultLocale != "en" ? td.TextDirection.ltr : td.TextDirection.rtl; + snackBarText = 'back_twice'.tr; + onRefresh(); + } + } + + @override + @override + void onInit() { + fetchLoadingHomeDataVar = fetchLoadingHomeData(); + WidgetsBinding.instance.addObserver(this); + registerNotification(); + checkForInitialMessage(); + FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { + PushNotification notification = PushNotification( + title: message.notification?.title, + body: message.notification?.body, + ); + notificationInfo = notification; + update(); + }); + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} + +class PushNotification { + PushNotification({ + this.title, + this.body, + }); + String? title; + String? body; +} diff --git a/lib/app/modules/home/models/dashboard_model.dart b/lib/app/modules/home/models/dashboard_model.dart new file mode 100644 index 0000000..8225921 --- /dev/null +++ b/lib/app/modules/home/models/dashboard_model.dart @@ -0,0 +1,33 @@ +class Dashboard { + int? status; + Data? data; + + Dashboard({this.status, this.data}); + + Dashboard.fromJson(Map json) { + status = json['status']; + data = json['data'] != null ? Data.fromJson(json['data']) : null; + } +} + +class Data { + String? remainingDays; + int? remainingTraffic; + String? balance; + Data({ + this.remainingDays, + this.remainingTraffic, + this.balance, + }); + + Data.fromJson(Map json) { + remainingDays = "${json['remaining_days']}"; + + if (json['remaining_traffic'].runtimeType == String) { + remainingTraffic = null; + } else { + remainingTraffic = json['remaining_traffic']; + } + balance = json['balance']; + } +} diff --git a/lib/app/modules/home/models/languages_currency_model.dart b/lib/app/modules/home/models/languages_currency_model.dart new file mode 100644 index 0000000..72cc083 --- /dev/null +++ b/lib/app/modules/home/models/languages_currency_model.dart @@ -0,0 +1,26 @@ +class LanguagesCurrencyModel { + int? status; + Data? data; + + LanguagesCurrencyModel({this.status, this.data}); + + LanguagesCurrencyModel.fromJson(Map json) { + status = json['status']; + data = json['data'] != null ? Data.fromJson(json['data']) : null; + } +} + +class Data { + String? currency; + int? requiresCaptcha; + + Data({ + this.currency, + this.requiresCaptcha, + }); + + Data.fromJson(Map json) { + currency = json['currency']; + requiresCaptcha = json['requires_captcha']; + } +} diff --git a/lib/app/modules/home/models/notifications_model.dart b/lib/app/modules/home/models/notifications_model.dart new file mode 100644 index 0000000..9f935c3 --- /dev/null +++ b/lib/app/modules/home/models/notifications_model.dart @@ -0,0 +1,34 @@ +class Notifications { + int? status; + List? data; + + Notifications({this.status, this.data}); + + Notifications.fromJson(Map json) { + status = json['status']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(Data.fromJson(v)); + }); + } + } +} + +class Data { + String? subject; + String? message; + String? createdAt; + + Data({ + this.subject, + this.message, + this.createdAt, + }); + + Data.fromJson(Map json) { + subject = json['subject']; + message = json['message']; + createdAt = json['created_at']; + } +} diff --git a/lib/app/modules/home/models/packages_model.dart b/lib/app/modules/home/models/packages_model.dart new file mode 100644 index 0000000..5c866b4 --- /dev/null +++ b/lib/app/modules/home/models/packages_model.dart @@ -0,0 +1,34 @@ +class Packages { + int? status; + List? data; + + Packages({this.status, this.data}); + + Packages.fromJson(Map json) { + status = json['status']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(Data.fromJson(v)); + }); + } + } +} + +class Data { + String? name; + String? description; + int? price; + + Data({ + this.name, + this.description, + this.price, + }); + + Data.fromJson(Map json) { + name = json['name']; + description = json['description']; + price = json['price']; + } +} diff --git a/lib/app/modules/home/models/service_model.dart b/lib/app/modules/home/models/service_model.dart new file mode 100644 index 0000000..14b71ec --- /dev/null +++ b/lib/app/modules/home/models/service_model.dart @@ -0,0 +1,50 @@ +// ignore_for_file: prefer_typing_uninitialized_variables + +class Service { + int? status; + Data? data; + + Service({this.status, this.data}); + + Service.fromJson(Map json) { + status = json['status']; + data = json['data'] != null ? Data.fromJson(json['data']) : null; + } +} + +class Data { + String? profileName; + String? expiration; + bool? status; + int? price; + SubscriptionStatus? subscriptionStatus; + + Data({ + this.profileName, + this.status, + this.price, + this.subscriptionStatus, + }); + + Data.fromJson(Map json) { + profileName = json['profile_name']; + expiration = json['expiration']; + status = json['status']; + price = json['price']; + subscriptionStatus = json['subscription_status'] != null + ? SubscriptionStatus.fromJson(json['subscription_status']) + : null; + } +} + +class SubscriptionStatus { + bool? status; + + SubscriptionStatus({ + this.status, + }); + + SubscriptionStatus.fromJson(Map json) { + status = json['status']; + } +} diff --git a/lib/app/modules/home/models/single_ticket.dart b/lib/app/modules/home/models/single_ticket.dart new file mode 100644 index 0000000..93db377 --- /dev/null +++ b/lib/app/modules/home/models/single_ticket.dart @@ -0,0 +1,158 @@ +class SingleTicket { + int? status; + Data? data; + + SingleTicket({this.status, this.data}); + + SingleTicket.fromJson(Map json) { + status = json['status']; + data = json['data'] != null ? Data.fromJson(json['data']) : null; + } + + Map toJson() { + final Map data = {}; + data['status'] = status; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + return data; + } +} + +class Data { + String? subject; + List? messages; + + Data({this.subject, this.messages}); + + Data.fromJson(Map json) { + subject = json['subject']; + if (json['messages'] != null) { + messages = []; + json['messages'].forEach((v) { + messages!.add(Messages.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + data['subject'] = subject; + if (messages != null) { + data['messages'] = messages!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Messages { + int? id; + int? threadId; + String? message; + int? userId; + int? managerId; + String? createdAt; + String? deletedAt; + String? updatedAt; + UserDetails? userDetails; + ManagerDetails? managerDetails; + + Messages({ + this.id, + this.threadId, + this.message, + this.userId, + this.managerId, + this.createdAt, + this.deletedAt, + this.updatedAt, + this.userDetails, + this.managerDetails, + }); + + Messages.fromJson(Map json) { + id = json['id']; + threadId = json['thread_id']; + message = json['message']; + userId = json['user_id']; + managerId = json['manager_id']; + createdAt = json['created_at']; + deletedAt = json['deleted_at']; + updatedAt = json['updated_at']; + userDetails = json['user_details'] != null + ? UserDetails.fromJson(json['user_details']) + : null; + managerDetails = json['manager_details'] != null + ? ManagerDetails.fromJson(json['manager_details']) + : null; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['thread_id'] = threadId; + data['message'] = message; + data['user_id'] = userId; + data['manager_id'] = managerId; + data['created_at'] = createdAt; + data['deleted_at'] = deletedAt; + data['updated_at'] = updatedAt; + if (userDetails != null) { + data['user_details'] = userDetails!.toJson(); + } + if (managerDetails != null) { + data['manager_details'] = managerDetails!.toJson(); + } + return data; + } +} + +class UserDetails { + int? id; + String? username; + String? firstname; + String? lastname; + + UserDetails({this.id, this.username, this.firstname, this.lastname}); + + UserDetails.fromJson(Map json) { + id = json['id']; + username = json['username']; + firstname = json['firstname']; + lastname = json['lastname']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['username'] = username; + data['firstname'] = firstname; + data['lastname'] = lastname; + return data; + } +} + +class ManagerDetails { + int? id; + String? username; + String? firstname; + String? lastname; + + ManagerDetails({this.id, this.username, this.firstname, this.lastname}); + + ManagerDetails.fromJson(Map json) { + id = json['id']; + username = json['username']; + firstname = json['firstname']; + lastname = json['lastname']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['username'] = username; + data['firstname'] = firstname; + data['lastname'] = lastname; + return data; + } +} diff --git a/lib/app/modules/home/models/support_model.dart b/lib/app/modules/home/models/support_model.dart new file mode 100644 index 0000000..1b6f654 --- /dev/null +++ b/lib/app/modules/home/models/support_model.dart @@ -0,0 +1,83 @@ +class Support { + int? status; + List? data; + + Support({this.status, this.data}); + + Support.fromJson(Map json) { + status = json['status']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(Data.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + data['status'] = status; + if (this.data != null) { + data['data'] = this.data!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Data { + int? id; + String? subject; + int? createdByUserId; + int? managerId; + int? closed; + int? solved; + int? managerSeen; + int? userSeen; + String? createdAt; + String? deletedAt; + String? updatedAt; + + Data({ + this.id, + this.subject, + this.createdByUserId, + this.managerId, + this.closed, + this.solved, + this.managerSeen, + this.userSeen, + this.createdAt, + this.deletedAt, + this.updatedAt, + }); + + Data.fromJson(Map json) { + id = json['id']; + subject = json['subject']; + createdByUserId = json['created_by_user_id']; + managerId = json['manager_id']; + closed = json['closed']; + solved = json['solved']; + managerSeen = json['manager_seen']; + userSeen = json['user_seen']; + createdAt = json['created_at']; + deletedAt = json['deleted_at']; + updatedAt = json['updated_at']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['subject'] = subject; + data['created_by_user_id'] = createdByUserId; + data['manager_id'] = managerId; + data['closed'] = closed; + data['solved'] = solved; + data['manager_seen'] = managerSeen; + data['user_seen'] = userSeen; + data['created_at'] = createdAt; + data['deleted_at'] = deletedAt; + data['updated_at'] = updatedAt; + return data; + } +} diff --git a/lib/app/modules/home/models/traffic_model.dart b/lib/app/modules/home/models/traffic_model.dart new file mode 100644 index 0000000..a51dbe9 --- /dev/null +++ b/lib/app/modules/home/models/traffic_model.dart @@ -0,0 +1,23 @@ +class Traffic { + int? status; + Data? data; + + Traffic({this.status, this.data}); + + Traffic.fromJson(Map json) { + status = json['status']; + data = json['data'] != null ? Data.fromJson(json['data']) : null; + } +} + +class Data { + List? totalReal; + + Data({ + this.totalReal, + }); + + Data.fromJson(Map json) { + totalReal = json['total_real'].cast(); + } +} diff --git a/lib/app/modules/home/models/user_model.dart b/lib/app/modules/home/models/user_model.dart new file mode 100644 index 0000000..b1e66cc --- /dev/null +++ b/lib/app/modules/home/models/user_model.dart @@ -0,0 +1,32 @@ +class User { + int? status; + Data? data; + + User({ + this.status, + this.data, + }); + + User.fromJson(Map json) { + status = json['status']; + data = json['data'] != null ? Data.fromJson(json['data']) : null; + } +} + +class Data { + String? username; + String? firstname; + String? lastname; + + Data({ + this.username, + this.firstname, + this.lastname, + }); + + Data.fromJson(Map json) { + username = json['username']; + firstname = json['firstname']; + lastname = json['lastname']; + } +} diff --git a/lib/app/modules/home/providers/add_new_ticket.dart b/lib/app/modules/home/providers/add_new_ticket.dart new file mode 100644 index 0000000..ff4f2cf --- /dev/null +++ b/lib/app/modules/home/providers/add_new_ticket.dart @@ -0,0 +1,22 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:IQ/app/global/snono_encrypt.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +// ignore: prefer_typing_uninitialized_variables +var addedTicketResponse; +bool getUseraddedTicketInformsLoads = false; +Future getUseraddedTicketInforms( + String? subjectInput, + String? messageInput, +) async { + String payload = AES.encrypt( + data: jsonEncode({"subject": subjectInput, "message": messageInput}), + passpharse: 'abcdefghijuklmno0123456789012345', + ); + var value = await APIService.post('ticket', payload, true); + addedTicketResponse = value; + getUseraddedTicketInformsLoads = true; + return addedTicketResponse; +} diff --git a/lib/app/modules/home/providers/add_reply_ticket.dart b/lib/app/modules/home/providers/add_reply_ticket.dart new file mode 100644 index 0000000..0f9b82e --- /dev/null +++ b/lib/app/modules/home/providers/add_reply_ticket.dart @@ -0,0 +1,22 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:IQ/app/global/snono_encrypt.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +// ignore: prefer_typing_uninitialized_variables +var sendReplyTicketResponse; +bool getUserSendReplyTicketInformsLoads = false; +Future getUserSendReplyTicketInforms( + int? ticketId, + String? messageInput, +) async { + String payload = AES.encrypt( + data: jsonEncode({"message": messageInput}), + passpharse: 'abcdefghijuklmno0123456789012345', + ); + var value = await APIService.post('ticket/$ticketId', payload, true); + sendReplyTicketResponse = value; + getUserSendReplyTicketInformsLoads = true; + return sendReplyTicketResponse; +} diff --git a/lib/app/modules/home/providers/dashboard.dart b/lib/app/modules/home/providers/dashboard.dart new file mode 100644 index 0000000..67bc367 --- /dev/null +++ b/lib/app/modules/home/providers/dashboard.dart @@ -0,0 +1,15 @@ +import 'dart:convert'; + +import 'package:IQ/app/modules/home/models/dashboard_model.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; +import 'package:logger/logger.dart'; + +Dashboard? dashboard; +bool getUserDashboardInformsLoads = false; +getUserDashboardInforms() async { + var value = await APIService.get('dashboard', true); + Logger().d("value = $value"); + dashboard = Dashboard.fromJson(jsonDecode(value)); + getUserDashboardInformsLoads = true; + return dashboard; +} diff --git a/lib/app/modules/home/providers/language_currency.dart b/lib/app/modules/home/providers/language_currency.dart new file mode 100644 index 0000000..665e8cc --- /dev/null +++ b/lib/app/modules/home/providers/language_currency.dart @@ -0,0 +1,28 @@ +import 'dart:convert'; +import 'dart:typed_data'; +import 'package:IQ/app/modules/home/models/languages_currency_model.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +LanguagesCurrencyModel? languagesCurrencyModel; +Uint8List? captcha; +int? isCaptcha; +getLanguageCurrencyInforms() async { + var value = await APIService.get('resources/config', false); + languagesCurrencyModel = LanguagesCurrencyModel.fromJson(jsonDecode(value)); + isCaptcha = languagesCurrencyModel?.data?.requiresCaptcha; + return languagesCurrencyModel; +} + +getcaptcha(String uuid) async { + var value = await APIService.get('login/captcha/$uuid', false); + captcha = dataFromBase64String(jsonDecode(value)["data"]); + return captcha; +} + +Uint8List dataFromBase64String(String base64String) { + return base64Decode(base64String); +} + +String base64String(Uint8List data) { + return base64Encode(data); +} diff --git a/lib/app/modules/home/providers/notifications.dart b/lib/app/modules/home/providers/notifications.dart new file mode 100644 index 0000000..b659269 --- /dev/null +++ b/lib/app/modules/home/providers/notifications.dart @@ -0,0 +1,13 @@ +import 'dart:convert'; + +import 'package:IQ/app/modules/home/models/notifications_model.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +Notifications? notifications; +bool getUserNotificationsInformsLoads = false; +getUserNotificationsInforms(String amount) async { + var value = await APIService.get('notifications$amount', true); + notifications = Notifications.fromJson(jsonDecode(value)); + getUserNotificationsInformsLoads = true; + return notifications; +} diff --git a/lib/app/modules/home/providers/packages.dart b/lib/app/modules/home/providers/packages.dart new file mode 100644 index 0000000..3b1c0be --- /dev/null +++ b/lib/app/modules/home/providers/packages.dart @@ -0,0 +1,16 @@ +import 'dart:convert'; + +import 'package:logger/logger.dart'; +import 'package:IQ/app/modules/home/models/packages_model.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +Packages? packages; +bool getUserPackagesInformsLoads = false; + +getUserPackagesInforms() async { + var value = await APIService.get('packages', true); + packages = Packages.fromJson(jsonDecode(value)); + getUserPackagesInformsLoads = true; + Logger().e("packages ${packages?.data?.length}"); + return packages; +} diff --git a/lib/app/modules/home/providers/service.dart b/lib/app/modules/home/providers/service.dart new file mode 100644 index 0000000..7c9bfdb --- /dev/null +++ b/lib/app/modules/home/providers/service.dart @@ -0,0 +1,14 @@ +import 'dart:convert'; + +import 'package:IQ/app/modules/home/models/service_model.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +Service? service; +bool getUserServiceInformsLoads = false; + +getUserServiceInforms() async { + var value = await APIService.get('service', true); + service = Service.fromJson(jsonDecode(value)); + getUserServiceInformsLoads = true; + return service; +} diff --git a/lib/app/modules/home/providers/single_ticket_provider.dart b/lib/app/modules/home/providers/single_ticket_provider.dart new file mode 100644 index 0000000..ff4681e --- /dev/null +++ b/lib/app/modules/home/providers/single_ticket_provider.dart @@ -0,0 +1,14 @@ +import 'dart:convert'; + +import 'package:IQ/app/modules/home/models/single_ticket.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +SingleTicket? singleTicket; +bool getUserSupportTicketsLoads = false; + +getUserSupportTicketsInforms(ticketId) async { + var value = await APIService.get('ticket/$ticketId', true); + singleTicket = SingleTicket.fromJson(jsonDecode(value)); + getUserSupportTicketsLoads = true; + return singleTicket; +} diff --git a/lib/app/modules/home/providers/support.dart b/lib/app/modules/home/providers/support.dart new file mode 100644 index 0000000..753d36e --- /dev/null +++ b/lib/app/modules/home/providers/support.dart @@ -0,0 +1,16 @@ +import 'dart:convert'; + +import 'package:logger/logger.dart'; +import 'package:IQ/app/modules/home/models/support_model.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +Support? supportTickets; +bool getUserSupportInformsLoads = false; + +getUserSupportInforms() async { + var value = await APIService.get('ticket', true); + Logger().e("supportTickets $value"); + supportTickets = Support.fromJson(jsonDecode(value)); + getUserSupportInformsLoads = true; + return supportTickets; +} diff --git a/lib/app/modules/home/providers/traffic.dart b/lib/app/modules/home/providers/traffic.dart new file mode 100644 index 0000000..a3c187e --- /dev/null +++ b/lib/app/modules/home/providers/traffic.dart @@ -0,0 +1,41 @@ +import 'package:IQ/app/global/converted_bytes.dart'; +import 'package:IQ/app/modules/home/models/traffic_model.dart'; +import 'dart:convert'; + +import 'package:IQ/app/global/snono_encrypt.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +String? totalGBs; +bool getTodayTrafficLoads = false; + +getTodayTraffic() async { + String payload = AES.encrypt( + data: jsonEncode({ + "report_type": "daily", + "month": DateTime.now().month, + "year": DateTime.now().year, + "user_id": null, + }), + passpharse: 'abcdefghijuklmno0123456789012345', + ); + var value = await APIService.post('traffic', payload); + + Traffic responseData = Traffic.fromJson(jsonDecode(value)); + String totalGBsNums = formatBytes( + (responseData.data?.totalReal?[DateTime.now().day - 1]) ?? 0, + 0, + ).split(' ')[0]; + String totalGBsStrs = formatBytes( + (responseData.data?.totalReal?[DateTime.now().day - 1]) ?? 0, + 0, + ).split(' ')[1]; + + totalGBs = + // defaultLocale != "en" + // ? + '$totalGBsNums $totalGBsStrs' + // : '$totalGBsStrs $totalGBsNums' + ; + // totalGBs = 0; + getTodayTrafficLoads = true; +} diff --git a/lib/app/modules/home/providers/user.dart b/lib/app/modules/home/providers/user.dart new file mode 100644 index 0000000..a41d81e --- /dev/null +++ b/lib/app/modules/home/providers/user.dart @@ -0,0 +1,14 @@ +import 'dart:convert'; + +import 'package:IQ/app/modules/home/models/user_model.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; + +User? user; +bool getUserInformsLoads = false; + +getUserInforms() async { + var value = await APIService.get('user', true); + user = User.fromJson(jsonDecode(value)); + getUserInformsLoads = true; + return user; +} diff --git a/lib/app/modules/home/views/home_view.dart b/lib/app/modules/home/views/home_view.dart new file mode 100644 index 0000000..bbad54c --- /dev/null +++ b/lib/app/modules/home/views/home_view.dart @@ -0,0 +1,1009 @@ +import 'dart:math'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:carousel_slider/carousel_slider.dart'; +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/global/converted_bytes.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/single_box.dart'; +import 'package:IQ/app/global/single_card.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; +import 'package:IQ/app/modules/home/providers/notifications.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; +import 'package:IQ/app/modules/home/widgets/shimmer_icon.dart'; +import 'package:IQ/app/modules/home/widgets/shimmer_text.dart'; +import 'package:IQ/app/modules/home/widgets/shimmer_text_widget.dart'; +import 'package:IQ/app/routes/app_pages.dart'; +import 'package:shimmer/shimmer.dart'; + +import '../controllers/home_controller.dart'; + +class HomeView extends GetView { + HomeView({Key? key}) : super(key: key); + final GlobalKey scaffoldKey = GlobalKey(); + + String formatBytesForRemainingTraffic(int bytes, int decimals) { + if (bytes <= 0) return "0 B"; + const suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; + var i = (log(bytes) / log(1024)).floor(); + return suffixes[i] + + ' ' + + ((bytes / pow(1024, i)).toStringAsFixed(decimals)); + } + + @override + Widget build(BuildContext context) { + return Directionality( + textDirection: + defaultLocale != "en" ? TextDirection.ltr : TextDirection.rtl, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: GetBuilder( + builder: (HomeController homeController) { + return RefreshIndicator( + onRefresh: controller.onRefresh, + triggerMode: RefreshIndicatorTriggerMode.anywhere, + backgroundColor: Colors.white, + color: brandColor, + child: homeController.fetchHomeData + ? Stack( + children: [ + SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 270), + GetBuilder( + builder: (c) { + return Column( + children: [ + SizedBox( + child: CarouselSlider( + options: CarouselOptions( + height: 200, + viewportFraction: 1.0, + enableInfiniteScroll: true, + autoPlay: true, + autoPlayAnimationDuration: + const Duration( + milliseconds: 200), + scrollPhysics: + const AlwaysScrollableScrollPhysics(), + onPageChanged: c.onPageChanged, + ), + items: c.slidersImages.map((image) { + return Builder( + builder: + (BuildContext context) { + return Container( + margin: const EdgeInsets + .symmetric( + horizontal: 15, + ), + width: + MediaQuery.of(context) + .size + .width - + 18, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular( + 10), + ), + child: ClipRRect( + borderRadius: + BorderRadius.circular( + 10), + child: CachedNetworkImage( + imageUrl: image, + fit: BoxFit.fill, + placeholder: (_, __) => + Image.asset( + "assets/placeholder.png", + ), + ), + ), + ); + }, + ); + }).toList(), + ), + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: List.generate( + c.slidersImages.length, + (int index) { + return Container( + width: 8.0, + height: 8.0, + margin: + const EdgeInsets.symmetric( + horizontal: 6, + ), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: c.current == index + ? const Color(0xff503296) + : const Color(0xffCACFEA), + ), + ); + }), + ) + + // Row( + // mainAxisAlignment: + // MainAxisAlignment.center, + // children: c.slidersImages.map((url) { + // int index = + // c.slidersImages.indexOf(url); + // print( + // "Building indicator with index $index and current ${c.current}"); + // return Container( + // width: 8.0, + // height: 8.0, + // margin: + // const EdgeInsets.symmetric( + // horizontal: 6, + // ), + // decoration: BoxDecoration( + // shape: BoxShape.rectangle, + // color: c.current == index + // ? const Color(0xff503296) + // : const Color(0xffCACFEA), + // ), + // ); + // }).toList(), + // ), + ], + ); + }, + ), + const SizedBox(height: 20), + Container( + height: 150, + margin: const EdgeInsets.symmetric( + horizontal: 15), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + color: Colors.white, + border: Border.all( + color: borderColor, + width: 2, + ), + ), + child: Column( + children: [ + const SizedBox(height: 30), + Container( + margin: const EdgeInsets.only( + top: 10, + right: 15, + left: 15, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Column( + children: [ + Stack( + alignment: Alignment.center, + children: [ + SvgPicture.asset( + controller.remainingIcon, + height: 60, + width: 60, + ), + Container( + margin: + const EdgeInsets.only( + top: 10), + child: TextWidget( + text: controller + .remainingDays, + fontSize: 18, + fontWeight: + FontWeight.bold, + color: controller + .remainingDays == + '!' + ? Colors.red + : Colors.black, + ), + ), + ], + ), + const SizedBox(height: 5), + TextWidget( + fontSize: 16, + text: 'remaining_days'.tr, + fontWeight: FontWeight.w500, + ), + ], + ), + Container( + padding: + const EdgeInsets.symmetric( + horizontal: 40, + ), + decoration: BoxDecoration( + border: Border( + left: BorderSide( + color: Colors.grey + .withOpacity(0.3), + width: 1, + ), + right: BorderSide( + color: Colors.grey + .withOpacity(0.3), + width: 1, + ), + ), + ), + child: SingleBox( + text: controller.connectionIcon, + text2: controller + .connectionStatusText, + ), + ), + SingleBox( + text: controller.activiationIcon, + text2: controller + .activiationStatusText, + ), + ], + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Column( + children: [ + Container( + margin: const EdgeInsets.symmetric( + horizontal: 35), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container(), + TextWidget( + text: 'account_information'.tr, + fontSize: 23, + fontWeight: FontWeight.w500, + color: brandColor, + ), + ], + ), + ), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, vertical: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 25, + ), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + color: Colors.white, + border: Border.all( + color: borderColor, + width: 2, + ), + ), + child: Column( + children: [ + SingleCard( + text: controller.loginName, + text2: 'username'.tr, + ), + SingleCard( + text: controller.fullName, + text2: 'fullname'.tr, + ), + SingleCard( + text: controller.subscriptionPrice, + text2: 'subscription_price'.tr, + ), + SingleCard( + text: controller.expireDate, + text2: 'subscription_expire'.tr, + ), + controller.remainingTraffic != null + ? Column( + crossAxisAlignment: + CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + Directionality( + textDirection: + defaultLocale == "en" + ? TextDirection + .ltr + : TextDirection + .rtl, + child: TextWidget( + text: formatBytes( + controller + .remainingTraffic ?? + 0, + 0), + fontSize: 20, + fontWeight: + FontWeight.w400, + color: brandColor, + ), + ), + TextWidget( + text: 'remaining_traffic' + .tr, + fontWeight: + FontWeight.w400, + fontSize: 16, + color: Colors.grey, + ), + Container( + margin: const EdgeInsets + .symmetric( + horizontal: 10, + ), + child: const Divider(), + ), + ], + ) + : Container(), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container(), + Column( + crossAxisAlignment: + CrossAxisAlignment.end, + // mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextWidget( + text: controller + .availableBalance, + fontSize: 20, + fontWeight: FontWeight.w400, + color: brandColor, + ), + TextWidget( + text: + 'available_balance'.tr, + fontWeight: FontWeight.w400, + fontSize: 16, + color: Colors.grey, + ), + ], + ), + ], + ) + ], + ), + ), + Container( + margin: const EdgeInsets.only( + right: 35, + left: 35, + top: 20, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container(), + TextWidget( + text: 'home_notifs'.tr, + fontSize: 23, + fontWeight: FontWeight.w500, + color: brandColor, + ), + ], + ), + ), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, vertical: 10), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + border: Border.all( + color: borderColor, + width: 2, + ), + color: Colors.white, + ), + // ignore: prefer_is_empty + child: notifications?.data?.length != 0 + ? Column( + children: notifications?.data + ?.map((e) { + return Column( + children: [ + TextButton( + onPressed: () => Get + .offNamed(Routes + .NOTIFICATIONS_SCREEN), + child: ListTile( + trailing: SvgPicture + .asset( + 'assets/help_icon.svg', + height: 35, + width: 35, + ), + title: Container( + margin: + const EdgeInsets + .only( + top: 5, + ), + child: TextWidget( + text: e.subject, + fontSize: 16, + overflow: + TextOverflow + .ellipsis, + textAlign: + TextAlign + .right, + softWrap: false, + fontWeight: + FontWeight + .w400, + color: + brandColor, + ), + ), + subtitle: + TextWidget( + text: e.message, + fontWeight: + FontWeight + .w400, + textAlign: + TextAlign + .right, + fontSize: 14, + color: + Colors.grey, + ), + leading: const Icon( + Icons + .arrow_back_ios, + size: 35, + ), + ), + ), + // ignore: prefer_is_empty + (controller.listOfNotification + ?.length != + 0) + ? controller.listOfNotification + ?.last != + e + ? Container( + margin: const EdgeInsets + .symmetric( + horizontal: + 10, + ), + child: + const Divider(), + ) + : Container() + : Container(), + ], + ); + }).toList() ?? + [], + ) + : Container( + // margin: , + padding: const EdgeInsets.all(15), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceEvenly, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Container(), + TextWidget( + text: + "empty_home_notifs".tr, + fontSize: 20, + fontWeight: FontWeight.w400, + color: + const Color(0xff484848), + ), + SvgPicture.asset( + "assets/notifs.svg", + height: 50, + width: 50, + ), + ], + ), + ), + ), + ], + ), + const SizedBox(height: 100), + ], + ), + ), + Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + SizedBox( + height: + MediaQuery.of(context).viewPadding.top, + ), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState + ?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 20), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + TextWidget( + text: 'subscription_type'.tr, + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.w300, + textAlign: TextAlign.start, + ), + const SizedBox(height: 5), + TextWidget( + text: + controller.profileName ?? ' . . . ', + color: Colors.white, + fontSize: 32, + fontWeight: FontWeight.bold, + textAlign: TextAlign.start, + ), + ], + ), + ), + const SizedBox(height: 5), + ], + ), + ), + ], + ) + : Stack( + children: [ + SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 250), + Container( + height: 150, + margin: const EdgeInsets.symmetric( + horizontal: 15), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + color: Colors.white, + border: Border.all( + color: borderColor, + width: 2, + ), + ), + child: Column( + children: [ + const SizedBox(height: 30), + Shimmer.fromColors( + baseColor: Colors.grey.withOpacity(0.3), + highlightColor: Colors.white, + enabled: true, + child: Container( + margin: const EdgeInsets.only( + top: 10, + right: 15, + left: 15, + ), + child: const Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + ShiimerIcon(), + ShiimerIcon(), + ShiimerIcon(), + ], + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + Column( + children: [ + Align( + alignment: Alignment.centerRight, + child: Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, vertical: 10), + child: Shimmer.fromColors( + baseColor: + Colors.grey.withOpacity(0.3), + highlightColor: Colors.white, + enabled: true, + child: const ShimmerText(), + ), + ), + ), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + vertical: 10, + ), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 25, + ), + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + color: Colors.white, + border: Border.all( + color: borderColor, + width: 2, + ), + ), + child: Column( + children: [ + const ShimmerTextWidget(), + const ShimmerTextWidget(), + const ShimmerTextWidget(), + const ShimmerTextWidget(), + Align( + alignment: Alignment.centerRight, + child: Column( + children: [ + Shimmer.fromColors( + baseColor: Colors.grey + .withOpacity(0.3), + highlightColor: Colors.white, + enabled: true, + child: const ShimmerText(), + ), + const SizedBox(height: 5), + Shimmer.fromColors( + baseColor: Colors.grey + .withOpacity(0.3), + highlightColor: Colors.white, + enabled: true, + child: const ShimmerText(), + ), + ], + ), + ), + ], + ), + ), + // ignore: prefer_is_empty + Align( + alignment: Alignment.centerRight, + child: Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, vertical: 10), + child: Shimmer.fromColors( + baseColor: + Colors.grey.withOpacity(0.3), + highlightColor: Colors.white, + enabled: true, + child: const ShimmerText(), + ), + ), + ), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, vertical: 10), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(20), + ), + border: Border.all( + color: borderColor, + width: 2, + ), + color: Colors.white, + ), + child: Column( + children: notifications?.data?.map((e) { + return Column( + children: [ + TextButton( + onPressed: () {}, + child: ListTile( + title: Align( + alignment: Alignment + .centerRight, + child: + Shimmer.fromColors( + baseColor: Colors.grey + .withOpacity(0.3), + highlightColor: + Colors.white, + enabled: true, + child: Container( + height: 6, + width: 300, + decoration: + const BoxDecoration( + color: + Colors.grey, + shape: BoxShape + .rectangle, + ), + ), + ), + ), + subtitle: Align( + alignment: Alignment + .centerRight, + child: + Shimmer.fromColors( + baseColor: Colors.grey + .withOpacity(0.3), + highlightColor: + Colors.white, + enabled: true, + child: Container( + height: 6, + width: 150, + decoration: + const BoxDecoration( + color: + Colors.grey, + shape: BoxShape + .rectangle, + ), + ), + ), + ), + ), + ), + if (controller + .listOfNotification + ?.last != + e) + Container( + margin: const EdgeInsets + .symmetric( + horizontal: 10, + ), + child: const Divider(), + ), + ], + ); + }).toList() ?? + [], + ), + ), + ], + ), + const SizedBox(height: 100), + ], + ), + ), + Container( + height: 230, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: + MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.only(right: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, right: 15), + child: Row( + children: [ + Text( + user?.data?.firstname ?? + ' . . . ', + style: const TextStyle( + fontSize: 22, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + ], + ), + ), + const SizedBox(width: 10), + IconButton( + onPressed: () { + scaffoldKey.currentState + ?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ), + Column( + children: [ + TextWidget( + text: 'subscription_type'.tr, + color: Colors.white, + fontSize: 20, + fontWeight: FontWeight.w300, + textAlign: TextAlign.center, + ), + const SizedBox(height: 5), + TextWidget( + text: controller.profileName, + color: Colors.white, + fontSize: 34, + fontWeight: FontWeight.bold, + textAlign: TextAlign.center, + ), + ], + ), + const SizedBox(height: 5), + ], + ), + ), + ], + ), + ); + }, + ), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + floatingActionButtonAnimator: FloatingActionButtonAnimator.scaling, + floatingActionButton: GetBuilder( + builder: (homeController) { + return homeController.fetchHomeData + ? Container( + width: widthSize(context), + height: 60, + decoration: const BoxDecoration( + gradient: LinearGradient( + colors: [ + Color(0xFF4009C0), + Color(0xFF8C5EF6) + ], // Gradient colors + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + borderRadius: BorderRadius.all(Radius.circular(5)), + ), + margin: const EdgeInsets.symmetric( + horizontal: 15, vertical: 29), + child: TextButton( + onPressed: () { + Get.toNamed(Routes.FILL_CARD); + }, + child: GetBuilder( + builder: (HomeController c) { + return TextWidget( + text: controller.floatButtonActivation, + fontSize: 18, + fontWeight: FontWeight.normal, + color: Colors.white, + ); + }, + ), + ), + ) + : Container(); + }, + ), + ), + ); + } +} diff --git a/lib/app/modules/home/widgets/shimmer_icon.dart b/lib/app/modules/home/widgets/shimmer_icon.dart new file mode 100644 index 0000000..8daba1c --- /dev/null +++ b/lib/app/modules/home/widgets/shimmer_icon.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +class ShiimerIcon extends StatelessWidget { + const ShiimerIcon({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Container( + height: 70, + width: 70, + decoration: const BoxDecoration( + color: Colors.grey, + shape: BoxShape.circle, + ), + ), + const SizedBox(height: 10), + Container( + height: 10, + width: 70, + decoration: const BoxDecoration( + color: Colors.grey, + shape: BoxShape.rectangle, + ), + ), + ], + ); + } +} diff --git a/lib/app/modules/home/widgets/shimmer_text.dart b/lib/app/modules/home/widgets/shimmer_text.dart new file mode 100644 index 0000000..fc4b64b --- /dev/null +++ b/lib/app/modules/home/widgets/shimmer_text.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +class ShimmerText extends StatelessWidget { + const ShimmerText({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 6, + width: 70, + decoration: const BoxDecoration( + color: Colors.grey, + shape: BoxShape.rectangle, + ), + ); + } +} diff --git a/lib/app/modules/home/widgets/shimmer_text_widget.dart b/lib/app/modules/home/widgets/shimmer_text_widget.dart new file mode 100644 index 0000000..cf71bf3 --- /dev/null +++ b/lib/app/modules/home/widgets/shimmer_text_widget.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:IQ/app/modules/home/widgets/shimmer_text.dart'; +import 'package:shimmer/shimmer.dart'; + +class ShimmerTextWidget extends StatelessWidget { + const ShimmerTextWidget({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Shimmer.fromColors( + baseColor: Colors.grey.withOpacity(0.3), + highlightColor: Colors.white, + enabled: true, + child: const ShimmerText(), + ), + const SizedBox(height: 5), + Shimmer.fromColors( + baseColor: Colors.grey.withOpacity(0.3), + highlightColor: Colors.white, + enabled: true, + child: const ShimmerText(), + ), + const SizedBox(height: 5), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 10, + ), + child: const Divider( + color: Colors.white, + ), + ), + ], + ); + } +} diff --git a/lib/app/modules/login/bindings/login_binding.dart b/lib/app/modules/login/bindings/login_binding.dart new file mode 100644 index 0000000..ac119f4 --- /dev/null +++ b/lib/app/modules/login/bindings/login_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/login_controller.dart'; + +class LoginBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => LoginController(), + ); + } +} diff --git a/lib/app/modules/login/controllers/login_controller.dart b/lib/app/modules/login/controllers/login_controller.dart new file mode 100644 index 0000000..1bb30c5 --- /dev/null +++ b/lib/app/modules/login/controllers/login_controller.dart @@ -0,0 +1,325 @@ +// ignore_for_file: unnecessary_overrides, prefer_typing_uninitialized_variables + +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:get/get.dart'; +import 'package:logger/logger.dart'; +import 'package:IQ/app/global/login_snackbar.dart'; +import 'package:IQ/app/global/snono_encrypt.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_field.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/home/providers/language_currency.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; +import 'package:IQ/app/routes/app_pages.dart'; +import 'package:IQ/main.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:uuid/uuid.dart'; + +String? uuid = const Uuid().v1(); + +class LoginController extends GetxController with WidgetsBindingObserver { + bool inputsEntered = false; + + var encryptedText, decryptedText; + var formKey = GlobalKey(); + String? enteredName; + TextEditingController nameController = TextEditingController( + text: storage.read('username') ?? '', + ); + String? enteredPassword; + String? enteredCaptcha; + TextEditingController passwordController = TextEditingController( + text: storage.read('password') ?? '', + ); + bool? checkedCheckbox = false; + resetCaptcha() async { + uuid = null; + captcha = null; + enteredCaptcha = null; + if (isCaptcha == 1) { + uuid = const Uuid().v1(); + await getcaptcha(uuid.toString()); + } + } + + onChangedCheckbox(val) { + checkedCheckbox = val; + update(); + } + + onPressedCallCenter() async { + const url = "tel:+93787204545"; + await launchUrl(Uri.parse(url)); + } + + onChangedEnteredName(val) { + enteredName = val; + update(); + } + + onChangedPassword(val) { + enteredPassword = val; + update(); + } + + bool isObscure = true; + onPressedEye() { + isObscure = !isObscure; + update(); + } + + Future login() async { + String payload = AES.encrypt( + data: jsonEncode({ + "username": enteredName, + "password": enteredPassword, + "language": "en", + "captcha_text": enteredCaptcha, + "session_id": uuid, + "device_id": deviceId, + }), + passpharse: 'abcdefghijuklmno0123456789012345', + ); + + var value = await APIService.post('auth/login', payload, false).timeout( + const Duration(seconds: 6), + onTimeout: () { + inputsEntered = false; + update(); + snack('provider_unreachable'.tr); + }, + ); + Logger().d("login $value"); + if (value.runtimeType == int) { + inputsEntered = false; + update(); + + switch (value) { + case 0: + snack('no_connect'.tr); + break; + case -2: + snack('provider_unreachable'.tr); + break; + case -1: + snack('ip_address_invalid'.tr); + break; + case 401: + snack('login_failed'.tr); + break; + case 403: + snack('login_failed'.tr); + break; + case -3: + snack('unknown_error'.tr); + break; + default: + snack('unknown_error'.tr); + break; + } + + await resetCaptcha(); + return; + } + + if (value == null) { + snack('login_failed'.tr); + inputsEntered = false; + update(); + await resetCaptcha(); + return; + } + + var data = jsonDecode(value); + if (data['status'] == -3) { + snack('unknown_error'.tr); + inputsEntered = false; + update(); + } else { + if (data['status'] == 200) { + token = data["token"]; + storage.write('token', token); + await resetCaptcha(); + if (checkedCheckbox == true) { + storage.write('username', enteredName); + storage.write('password', enteredPassword); + storage.write('remember', checkedCheckbox); + update(); + } + Future.delayed( + const Duration(seconds: 2), + () { + inputsEntered = false; + update(); + Get.offNamed(Routes.HOME); + }, + ); + } + } + } + + onPressedEnter() { + if (checkedCheckbox == false) { + storage.remove('username'); + storage.remove('password'); + storage.remove('remember'); + } + enteredName = nameController.text; + enteredPassword = passwordController.text; + + if (enteredName == null || + enteredPassword == null || + (enteredName?.isEmpty)! || + (enteredPassword?.isEmpty)!) { + snack('unentered_login_credentials'.tr); + return; + } + if (isCaptcha == 1) { + Get.defaultDialog( + title: 'enter_captcha'.tr, + backgroundColor: brandColor, + titlePadding: const EdgeInsets.only(top: 15), + titleStyle: buildTextStyle( + color: Colors.white, + fontSize: 20, + fontWeight: FontWeight.w600, + ), + content: SizedBox( + width: Get.width, + child: Column( + children: [ + Container( + width: 200, + decoration: BoxDecoration( + border: Border.all( + color: Colors.white.withOpacity(0.5), + width: 1, + ), + ), + child: Image.memory( + captcha!, + width: 200, + frameBuilder: + (context, child, frame, wasSynchronouslyLoaded) { + if (wasSynchronouslyLoaded) { + return child; + } + return AnimatedOpacity( + child: child, + opacity: frame == null ? 0 : 1, + duration: const Duration(milliseconds: 500), + ); + }, + ), + ), + FormBuilder( + key: formKey, + child: Directionality( + textDirection: TextDirection.rtl, + child: BuildTextField( + name: 'captcha', + hintText: 'captcha_hint'.tr, + margin: const EdgeInsets.all(30), + textDirection: TextDirection.rtl, + onChanged: (val) { + enteredCaptcha = val; + update(); + }, + onEditingComplete: () { + FocusScope.of(Get.context!).unfocus(); + }, + validator: FormBuilderValidators.compose( + [ + FormBuilderValidators.required( + errorText: 'captcha_validation'.tr, + ), + ], + ), + ), + ), + ), + ], + ), + ), + contentPadding: const EdgeInsets.all(10), + onWillPop: () async { + await resetCaptcha(); + return true; + }, + actions: [ + TextButton( + child: TextWidget( + text: 'captcha_dialog_cancel_button'.tr, + color: Colors.white, + ), + onPressed: () async { + Get.back(); + await resetCaptcha(); + }, + ), + ElevatedButton( + child: TextWidget( + text: 'captcha_dialog_ok_button'.tr, + color: brandColor, + ), + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(Colors.white), + ), + onPressed: () { + if ((formKey.currentState?.validate())!) { + inputsEntered = true; + update(); + Get.back(); + login(); + } + }, + ), + ], + ); + } else { + inputsEntered = true; + update(); + login(); + } + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + textDirection = + defaultLocale == "en" ? TextDirection.ltr : TextDirection.rtl; + snackBarText = 'back_twice'.tr; + } + } + + @override + void onInit() async { + WidgetsBinding.instance.addObserver(this); + if (storage.read('remember') != null) { + checkedCheckbox = + storage.read('remember').toString().toLowerCase() == 'true'; + } + + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} diff --git a/lib/app/modules/login/views/login_view.dart b/lib/app/modules/login/views/login_view.dart new file mode 100644 index 0000000..66e03a8 --- /dev/null +++ b/lib/app/modules/login/views/login_view.dart @@ -0,0 +1,243 @@ +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_svg/svg.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; +import 'package:IQ/app/global/text_field.dart'; +import 'package:IQ/main.dart'; + +import '../controllers/login_controller.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; + +// ignore: must_be_immutable +class LoginView extends GetView { + LoginView({Key? key}) : super(key: key); + LoginController c = Get.put(LoginController()); + @override + Widget build(BuildContext context) { + var loginScreen = Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: brandColor, + appBar: AppBar( + backgroundColor: brandColor, + elevation: 0, + leading: Container(), + ), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Stack( + alignment: Alignment.topCenter, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 110 + + MediaQuery.of(context).viewPadding.top + + AppBar().preferredSize.height, + ), + Container( + margin: const EdgeInsets.symmetric(horizontal: 35.0), + child: TextWidget( + color: labeledColor, + fontSize: 22, + text: "login_massage".tr, + ), + ), + const Spacer(), + Container( + margin: const EdgeInsets.symmetric(horizontal: 35.0), + child: TextWidget( + color: Colors.white, + fontSize: 32, + fontWeight: FontWeight.bold, + text: 'login_title'.tr, + ), + ), + const Spacer(), + FormBuilder( + child: Column( + children: [ + BuildTextField( + signup: false, + height: heightSize(context) * 0.1, + name: 'entered name', + controller: c.nameController, + suffixIcon: Image.asset( + 'assets/entered_name_icon.png', + height: 50, + width: 50, + color: Colors.white, + ), + labelText: 'login_username'.tr, + margin: const EdgeInsets.only( + right: 30.0, + left: 30.0, + bottom: 10.0, + ), + errorMaxLines: 2, + onEditingComplete: () { + FocusScope.of(context).unfocus(); + }, + keyboardType: TextInputType.text, + onChanged: c.onChangedEnteredName, + textDirection: textDirection, + showCursor: true, + ), + GetBuilder(builder: (LoginController co) { + return BuildTextField( + signup: false, + height: heightSize(context) * 0.1, + name: 'password', + textDirection: textDirection, + controller: c.passwordController, + margin: const EdgeInsets.only( + right: 30.0, + left: 30.0, + bottom: 10.0, + ), + obscureText: co.isObscure, + showCursor: true, + suffix: SizedBox( + width: 100, + child: Row( + children: [ + IconButton( + iconSize: 25, + icon: Icon( + c.isObscure + ? Icons.visibility_off + : Icons.visibility, + color: Colors.white, + ), + onPressed: controller.onPressedEye, + ), + Image.asset( + 'assets/password_icon.png', + height: 50, + width: 50, + color: Colors.white, + ) + ], + ), + ), + labelText: 'login_password'.tr, + onEditingComplete: () { + FocusScope.of(context).unfocus(); + }, + keyboardType: TextInputType.text, + errorMaxLines: 2, + onChanged: c.onChangedPassword, + ); + }), + ], + ), + ), + const Spacer(), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15.0, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + GetBuilder( + init: LoginController(), + builder: (LoginController c) { + return Checkbox( + value: c.checkedCheckbox ?? + storage + .read('remember') + .toString() + .toLowerCase() == + 'true', + onChanged: c.onChangedCheckbox, + fillColor: MaterialStateProperty.all( + Colors.white, + ), + activeColor: Colors.white, + checkColor: Colors.black, + ); + }), + TextWidget( + text: 'remember_me'.tr, + color: Colors.white, + fontSize: 20, + ), + ], + ), + Container(), + ], + ), + ), + const Spacer(), + Center( + child: Container( + margin: const EdgeInsets.only( + bottom: 10.0, + ), + width: 400, + height: 55, + child: ElevatedButton( + style: ButtonStyle( + // backgroundColor: + // MaterialStateProperty.all(secondaryColor), + + backgroundColor: + MaterialStateProperty.all(Colors.white), + ), + child: TextWidget( + fontSize: 28, + color: brandColor, + fontWeight: FontWeight.bold, + text: 'login_button'.tr, + ), + onPressed: controller.onPressedEnter, + ), + ), + ), + const Spacer(), + Container(), + const Spacer(flex: 2), + ], + ), + SvgPicture.asset( + 'assets/2/icon.svg', + height: 80, + width: 80, + ), + ], + ), + ), + ), + ); + return GetBuilder( + builder: (LoginController c) { + return c.inputsEntered == true + ? Stack( + children: [ + Opacity( + opacity: 0.3, + child: AbsorbPointer( + absorbing: true, + child: loginScreen, + ), + ), + Align( + alignment: Alignment.center, + child: SvgPicture.asset("assets/autologin_loading.svg"), + ), + ], + ) + : loginScreen; + }, + ); + } +} diff --git a/lib/app/modules/new_ticket/bindings/new_ticket_binding.dart b/lib/app/modules/new_ticket/bindings/new_ticket_binding.dart new file mode 100644 index 0000000..c0dc60c --- /dev/null +++ b/lib/app/modules/new_ticket/bindings/new_ticket_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/new_ticket_controller.dart'; + +class NewTicketBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => NewTicketController(), + ); + } +} diff --git a/lib/app/modules/new_ticket/controllers/new_ticket_controller.dart b/lib/app/modules/new_ticket/controllers/new_ticket_controller.dart new file mode 100644 index 0000000..92571f9 --- /dev/null +++ b/lib/app/modules/new_ticket/controllers/new_ticket_controller.dart @@ -0,0 +1,58 @@ +// ignore_for_file: unnecessary_overrides + +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/modules/home/providers/add_new_ticket.dart'; +import 'package:IQ/app/routes/app_pages.dart'; + +class NewTicketController extends GetxController { + final formKey = GlobalKey(); + bool inputsEntered = false; + @override + void onInit() { + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + super.onClose(); + } + + sendTicket() async { + if ((formKey.currentState?.validate())!) { + inputsEntered = true; + update(); + await getUseraddedTicketInforms(subjectStr, messageStr); + if (getUseraddedTicketInformsLoads) { + inputsEntered = false; + update(); + Get.offAllNamed(Routes.SUPPORT); + } else { + inputsEntered = false; + update(); + Get.snackbar('Error', 'Please try again later'); + } + } else { + inputsEntered = false; + update(); + } + } + + String? subjectStr; + onChangeSubject(String? subjectInput) { + subjectStr = subjectInput; + update(); + } + + String? messageStr; + onChangeMessage(String? messageInput) { + messageStr = messageInput; + update(); + } +} diff --git a/lib/app/modules/new_ticket/views/new_ticket_view.dart b/lib/app/modules/new_ticket/views/new_ticket_view.dart new file mode 100644 index 0000000..0f25964 --- /dev/null +++ b/lib/app/modules/new_ticket/views/new_ticket_view.dart @@ -0,0 +1,324 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; + +import 'package:get/get.dart'; + +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; + +import '../controllers/new_ticket_controller.dart'; + +class NewTicketView extends GetView { + NewTicketView({Key? key}) : super(key: key); + final GlobalKey scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + var stackedContainer = Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox(height: MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Container( + margin: const EdgeInsets.only(top: 10), + child: Align( + alignment: Alignment.bottomCenter, + child: Column( + children: [ + SvgPicture.asset( + 'assets/support_icon.svg', + color: Colors.white, + height: 90, + width: 90, + ), + const SizedBox(height: 15), + TextWidget( + text: 'support'.tr, + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.w300, + textAlign: TextAlign.center, + ), + const SizedBox(height: 10), + ], + ), + ), + ) + ], + ), + ); + return Directionality( + textDirection: + defaultLocale == "en" ? TextDirection.rtl : TextDirection.ltr, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: GetBuilder( + builder: (NewTicketController newTicketController) { + return Stack( + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Container( + width: widthSize(context), + height: 60, + margin: const EdgeInsets.symmetric( + horizontal: 20, vertical: 20), + child: TextButton( + onPressed: () { + controller.sendTicket(); + }, + style: ButtonStyle( + shape: MaterialStateProperty.all( + const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(15), + ), + ), + ), + backgroundColor: MaterialStateProperty.all( + brandColor, + ), + ), + child: !newTicketController.inputsEntered + ? TextWidget( + text: "send".tr, + fontSize: 18, + fontWeight: FontWeight.normal, + color: Colors.white, + ) + : const CircularProgressIndicator( + color: Colors.white, + ), + ), + ), + ), + FormBuilder( + key: controller.formKey, + child: Container( + margin: const EdgeInsets.only(top: 250), + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const SizedBox(height: 30), + Container( + margin: const EdgeInsets.symmetric(horizontal: 20), + child: TextWidget( + text: 'new_ticket_title'.tr, + fontSize: 22, + fontWeight: FontWeight.normal, + textAlign: TextAlign.right, + ), + ), + const SizedBox(height: 60), + Container( + height: 80, + margin: const EdgeInsets.only( + right: 20.0, + left: 20.0, + ), + child: FormBuilderTextField( + textDirection: textDirection, + autovalidateMode: + AutovalidateMode.onUserInteraction, + onChanged: controller.onChangeSubject, + name: 'ticket_subject', + onEditingComplete: () { + FocusScope.of(context).unfocus(); + }, + textAlign: defaultLocale == "en" + ? TextAlign.left + : TextAlign.right, + validator: FormBuilderValidators.compose( + [ + FormBuilderValidators.required( + errorText: 'subject_input_error'.tr, + ), + FormBuilderValidators.minLength( + 5, + errorText: 'subject_input_num'.tr, + ), + ], + ), + keyboardType: TextInputType.text, + style: buildTextStyle( + fontSize: 20, + color: Colors.black, + ), + decoration: InputDecoration( + hintTextDirection: defaultLocale == "en" + ? TextDirection.ltr + : TextDirection.rtl, + fillColor: Colors.white, + hintText: 'subject'.tr, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(15), + borderSide: const BorderSide( + color: Colors.black, + ), + ), + errorMaxLines: 2, + filled: true, + isDense: true, + errorStyle: buildTextStyle( + fontSize: 12, + color: + const Color.fromARGB(255, 184, 184, 184), + ), + hintStyle: buildTextStyle( + color: + const Color.fromARGB(255, 184, 184, 184), + fontSize: 19, + ), + ), + ), + ), + const SizedBox(height: 28), + Container( + height: 325, + margin: const EdgeInsets.only( + right: 20.0, + left: 20.0, + ), + child: FormBuilderTextField( + textDirection: textDirection, + textAlign: defaultLocale == "en" + ? TextAlign.left + : TextAlign.right, + autovalidateMode: + AutovalidateMode.onUserInteraction, + textAlignVertical: TextAlignVertical.top, + onChanged: controller.onChangeMessage, + name: 'ticket_message', + onEditingComplete: () { + FocusScope.of(context).unfocus(); + }, + validator: FormBuilderValidators.compose( + [ + FormBuilderValidators.required( + errorText: 'message_input_error'.tr, + ), + FormBuilderValidators.minLength( + 10, + errorText: 'message_input_num'.tr, + ), + ], + ), + expands: true, + minLines: null, + maxLines: null, + style: buildTextStyle( + fontSize: 20, + color: Colors.black, + ), + keyboardType: TextInputType.multiline, + textInputAction: TextInputAction.newline, + decoration: InputDecoration( + hintTextDirection: defaultLocale == "en" + ? TextDirection.ltr + : TextDirection.rtl, + fillColor: Colors.white, + hintText: 'message'.tr, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(15), + borderSide: const BorderSide( + color: Colors.black, + ), + ), + filled: true, + hintStyle: buildTextStyle( + color: + const Color.fromARGB(255, 184, 184, 184), + fontSize: 19, + ), + errorMaxLines: 2, + isDense: true, + errorStyle: buildTextStyle( + fontSize: 12, + color: + const Color.fromARGB(255, 184, 184, 184), + ), + ), + ), + ), + ], + ), + ), + ), + ), + stackedContainer, + ], + ); + }, + ), + ), + ); + } +} diff --git a/lib/app/modules/notificationsScreen/bindings/notifications_screen_binding.dart b/lib/app/modules/notificationsScreen/bindings/notifications_screen_binding.dart new file mode 100644 index 0000000..d7b0a39 --- /dev/null +++ b/lib/app/modules/notificationsScreen/bindings/notifications_screen_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/notifications_screen_controller.dart'; + +class NotificationsScreenBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => NotificationsScreenController(), + ); + } +} diff --git a/lib/app/modules/notificationsScreen/controllers/notifications_screen_controller.dart b/lib/app/modules/notificationsScreen/controllers/notifications_screen_controller.dart new file mode 100644 index 0000000..9342eb6 --- /dev/null +++ b/lib/app/modules/notificationsScreen/controllers/notifications_screen_controller.dart @@ -0,0 +1,69 @@ +// ignore_for_file: unnecessary_overrides + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/modules/home/models/notifications_model.dart'; +import 'package:IQ/app/modules/home/providers/language_currency.dart'; +import 'package:IQ/app/modules/home/providers/notifications.dart'; +import 'package:IQ/app/modules/home/providers/service.dart'; + +class NotificationsScreenController extends GetxController + with WidgetsBindingObserver { + bool fetchNotifsData = false; + // ignore: prefer_typing_uninitialized_variables + var fetchLoadingNotifsDataVar; + + Future onRefresh() async { + fetchNotifsData = false; + notifications = null; + fetchLoadingNotifsDataVar = fetchLoadingNotifsData(); + update(); + } + + fetchLoadingNotifsData() async { + await getUserNotificationsInforms(""); + if (getUserNotificationsInformsLoads) { + fetchNotifsData = true; + listOfNotifs = notifications?.data ?? []; + update(); + } + } + + String activiationType = '${service?.data?.profileName}'; + String subscriptionCurrency = languagesCurrencyModel?.data?.currency ?? ''; + String profileName = service?.data?.profileName ?? ''; + + List? listOfNotifs = notifications?.data ?? []; + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + snackBarText = 'back_twice'.tr; + } + } + + @override + void onInit() { + fetchLoadingNotifsDataVar = fetchLoadingNotifsData(); + WidgetsBinding.instance.addObserver(this); + + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} diff --git a/lib/app/modules/notificationsScreen/views/notifications_screen_view.dart b/lib/app/modules/notificationsScreen/views/notifications_screen_view.dart new file mode 100644 index 0000000..d29b1a1 --- /dev/null +++ b/lib/app/modules/notificationsScreen/views/notifications_screen_view.dart @@ -0,0 +1,269 @@ +import 'package:flutter/material.dart'; +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/global/convert_to_ago.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; + +import '../controllers/notifications_screen_controller.dart'; + +class NotificationsScreenView extends GetView { + NotificationsScreenView({Key? key}) : super(key: key); + final GlobalKey scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + var stackedContainer = Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox(height: MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Container( + margin: const EdgeInsets.only(top: 10), + child: Align( + alignment: Alignment.bottomCenter, + child: Column( + children: [ + SvgPicture.asset( + 'assets/notifications.svg', + color: Colors.white, + height: 60, + width: 60, + ), + const SizedBox(height: 3), + TextWidget( + text: 'notifications'.tr, + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.w300, + textAlign: TextAlign.center, + ), + const SizedBox(height: 10), + ], + ), + ), + ) + ], + ), + ); + return Directionality( + textDirection: + defaultLocale == "en" ? TextDirection.rtl : TextDirection.ltr, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: GetBuilder( + builder: + (NotificationsScreenController notificationsScreenController) { + return RefreshIndicator( + onRefresh: controller.onRefresh, + triggerMode: RefreshIndicatorTriggerMode.anywhere, + backgroundColor: Colors.white, + color: brandColor, + child: notificationsScreenController.fetchNotifsData + ? Stack( + children: [ + Container( + margin: const EdgeInsets.only(top: 270), + child: (controller.listOfNotifs?.isNotEmpty)! + ? SingleChildScrollView( + physics: + const AlwaysScrollableScrollPhysics(), + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: controller.listOfNotifs?.map( + (e) { + return Container( + padding: const EdgeInsets.all(15), + margin: const EdgeInsets.all(15), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: borderColor, + width: 2, + ), + borderRadius: + BorderRadius.circular(20), + ), + child: Center( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment + .end, + children: [ + TextWidget( + text: e.subject, + fontSize: 24, + fontWeight: + FontWeight.w500, + color: Colors.black, + textAlign: + TextAlign.right, + ), + const SizedBox( + height: 10), + TextWidget( + text: e.message, + fontSize: 18, + textAlign: + TextAlign.right, + color: const Color( + 0xff7A7A7A), + // overflow: + // TextOverflow.ellipsis, + ), + const SizedBox( + height: 25), + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + crossAxisAlignment: + CrossAxisAlignment + .center, + children: [ + TextWidget( + text: + convertToAgo( + DateTime.parse( + e.createdAt ?? + ''), + ), + color: brandColor, + fontSize: 16, + ), + const TextWidget( + text: '', + color: + Colors.grey, + fontSize: 16, + ), + ], + ), + ], + ), + ], + ), + ), + ); + }, + ).toList() as List)) + : Center( + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + TextWidget( + text: 'empty_notifications'.tr, + color: Colors.grey, + fontSize: 24, + fontWeight: FontWeight.w500, + textAlign: TextAlign.center, + ), + const SizedBox(height: 15), + InkWell( + child: const Icon( + Icons.refresh, + color: Colors.grey, + size: 50, + ), + onTap: controller.onRefresh, + ), + ], + ), + ), + ), + stackedContainer + ], + ) + : Stack( + children: [ + Center( + child: CircularProgressIndicator( + color: brandColor, + ), + ), + stackedContainer + ], + ), + ); + }, + ), + ), + ), + ); + } +} diff --git a/lib/app/modules/selectISP/bindings/select_isp_binding.dart b/lib/app/modules/selectISP/bindings/select_isp_binding.dart new file mode 100644 index 0000000..cdb07c8 --- /dev/null +++ b/lib/app/modules/selectISP/bindings/select_isp_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/select_isp_controller.dart'; + +class SelectISPBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SelectISPController(), + ); + } +} diff --git a/lib/app/modules/selectISP/controllers/select_isp_controller.dart b/lib/app/modules/selectISP/controllers/select_isp_controller.dart new file mode 100644 index 0000000..72c1dd7 --- /dev/null +++ b/lib/app/modules/selectISP/controllers/select_isp_controller.dart @@ -0,0 +1,252 @@ +// ignore_for_file: unnecessary_overrides, prefer_is_empty + +import 'dart:io'; +import 'package:internet_connection_checker/internet_connection_checker.dart'; +import 'package:IQ/app/modules/selectISP/views/select_isp_view.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:lottie/lottie.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/selectISP/models/isp_model.dart'; +import 'package:IQ/app/modules/service/api_service.dart'; +import 'package:IQ/main.dart'; +import 'package:IQ/app/routes/app_pages.dart'; +import 'dart:convert'; + +class SelectISPController extends GetxController with WidgetsBindingObserver { + late Future?> ispListVar; + List? listOfIsps = []; + List? serversList = []; + int selectIndex = 0; + String errorText = ''; + bool redraw = true; + + Widget futureBuilderWidget({Widget? widget}) => FutureBuilder( + future: ispListVar, + builder: ( + BuildContext context, + AsyncSnapshot?> snapshot, + ) { + if (snapshot.hasData) { + if (errorText != '') { + return Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + errorText == 'Connection Timed Out' + ? Icons.wifi_find_outlined + : Icons.wifi_off_outlined, + color: Colors.white, + size: 35, + ), + const SizedBox(width: 15), + TextWidget( + text: errorText, + color: Colors.white, + fontWeight: FontWeight.w400, + fontSize: 20, + ), + ], + ), + ); + } + listOfIsps = snapshot.data; + // listOfIsps = snapshot.data?.length == 0 ? saved : snapshot.data; + if (internetConnection) { + if ((saved?.isNotEmpty)!) { + var tmp = [...saved!]; + for (var i in tmp) { + if (i.custom == 0) { + saved?.remove(i); + } + } + for (var i in listOfIsps!) { + saved?.add(i); + } + serversList = saved; + storage.write('listOfIsps', serversList); + WidgetsBinding.instance.addPostFrameCallback((_) { + if (redraw) { + update(); + } + redraw = false; + }); + } else { + // saved = listOfIsps; + serversList = listOfIsps; + storage.write('listOfIsps', serversList); + WidgetsBinding.instance.addPostFrameCallback((_) { + if (redraw) { + update(); + } + redraw = false; + }); + } + } else { + serversList = saved; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (redraw) { + update(); + } + redraw = false; + }); + } + return widget!; + } else { + return Center( + child: Lottie.asset( + 'assets/animated_autologin.json', + repeat: true, + height: 100, + width: 100, + ), + ); + } + }, + ); + final InternetConnectionChecker _internetConnectionChecker = + InternetConnectionChecker(); + Future checkInternet() async { + bool result = await _internetConnectionChecker.hasConnection; + return result; + } + + bool internetConnection = false; + Future?> ispList() async { + await checkInternet().then((connection) { + internetConnection = connection; + return internetConnection; + }); + if (internetConnection) { + var value = await APIService.getUrl( + 'https://connect.snono-systems.com/index.php/api/isp', + ); + if (value.runtimeType == int) { + if (value == 0) { + errorText = 'No Internet Connection'; + } + if (value == -2) { + errorText = 'server unreachable'; + } + return []; + } + var fromJsonResponse = Isp.fromJson(jsonDecode(value.toString())); + listOfIsps = fromJsonResponse.data; + } else { + listOfIsps = saved; + } + + showNext = true; + update(); + return listOfIsps; + } + + initialValue() { + if ((saved?.isNotEmpty)!) { + initialItem = 0; + for (var i in saved!) { + if (i.custom == 1 || saved?.first.custom == 1) { + isCustomIsp = true; + } else { + isCustomIsp = false; + } + } + update(); + } + } + + removeISP() { + Get.defaultDialog( + title: 'Remove ISP', + titleStyle: buildTextStyle( + color: brandColor, + fontSize: 20, + fontWeight: FontWeight.w600, + ), + content: TextWidget( + text: 'Are you sure you want to remove ${selectedISP?.name} ?', + textAlign: TextAlign.center, + color: Colors.black, + fontSize: 20, + ), + confirm: TextButton( + onPressed: () { + serversList?.remove(serversList?[selectIndex]); + selectedISP = serversList?.first; + isCustomIsp = serversList?.first.custom != 1 ? false : true; + storage.write('listOfIsps', serversList); + update(); + Get.back(); + }, + child: TextWidget( + text: 'Yes', + color: brandColor, + fontSize: 20, + ), + ), + cancel: TextButton( + onPressed: () { + Get.back(); + }, + child: TextWidget( + text: 'No', + color: brandColor, + fontSize: 20, + ), + ), + ); + } + + onSelectedItemChanged(index) { + selectIndex = index; + isCustomIsp = serversList![index].custom != 1 ? false : true; + update(); + } + + onIspSelected() { + selectedISP = serversList?[selectIndex]; + storage.write('selectedISP', selectedISP); + url = 'https://${selectedISP?.serverAddress}/user/api/index.php/api'; + liveDataUrl = + 'http://${selectedISP?.serverAddress}/userlivetraffic/ucp/traffic?token='; + + storage.write('baseUrl', url); + storage.write('liveDataUrl', liveDataUrl); + + update(); + Get.offNamed(Routes.AUTOLOGIN); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + snackBarText = 'back_twice'.tr; + } + } + + @override + void onInit() { + // ispListVar = ispList(); + // snackBarText = 'back_twice'.tr; + // initialValue(); + // WidgetsBinding.instance.addObserver(this); + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} diff --git a/lib/app/modules/selectISP/models/isp_model.dart b/lib/app/modules/selectISP/models/isp_model.dart new file mode 100644 index 0000000..6fddd7d --- /dev/null +++ b/lib/app/modules/selectISP/models/isp_model.dart @@ -0,0 +1,53 @@ +class Isp { + int? status; + List? data; + + Isp({this.status, this.data}); + + Isp.fromJson(Map json) { + status = json['status']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data?.add(ISPsData.fromJson(v)); + }); + } + } + + Map toJson() { + final data = {}; + data['status'] = status; + data['data'] = this.data?.map((v) => v.toJson()).toList(); + return data; + } +} + +class ISPsData { + int? id; + String? name; + String? serverAddress; + int? custom; + + ISPsData({ + this.id, + this.name, + this.serverAddress, + this.custom + }); + + ISPsData.fromJson(Map json) { + id = json['id']; + name = json['name']; + serverAddress = json['server_address']; + custom = json['custom']; + } + + Map toJson() { + final data = {}; + data['id'] = id; + data['name'] = name; + data['server_address'] = serverAddress; + data['custom'] = custom; + return data; + } +} diff --git a/lib/app/modules/selectISP/views/select_isp_view.dart b/lib/app/modules/selectISP/views/select_isp_view.dart new file mode 100644 index 0000000..1754e59 --- /dev/null +++ b/lib/app/modules/selectISP/views/select_isp_view.dart @@ -0,0 +1,222 @@ +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; + +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/selectISP/models/isp_model.dart'; +import 'package:IQ/main.dart'; +import 'package:IQ/app/modules/selectISP/controllers/select_isp_controller.dart'; + +List? storedISPs = storage.read('listOfIsps'); +int? initialItem; +List? listOfIsps = []; +List? serversList = []; +List? saved = storedISPs != null + ? storedISPs?.map((e) => ISPsData.fromJson(e)).toList() + : []; +bool? isCustomIsp = false; +bool? showNext = false; +String? url; +String? liveDataUrl; +ISPsData? selectedISP; + +// ignore: must_be_immutable +class SelectISPView extends GetView { + const SelectISPView({Key? key}) : super(key: key); + // var selectedISPController = Get.find(); + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: brandColor, + appBar: AppBar( + backgroundColor: brandColor, + elevation: 0, + leading: Container(), + ), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: Stack( + alignment: Alignment.topCenter, + children: [ + SvgPicture.asset( + 'assets/2/icon.svg', + height: 80, + width: 80, + ), + SizedBox( + width: widthSize(context), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 190), + TextWidget( + color: const Color(0xffC4C4C4), + fontSize: 22, + text: "select_isp_title".tr, + ), + const SizedBox(height: 50), + GetBuilder( + init: SelectISPController(), + builder: (SelectISPController c) { + return c.futureBuilderWidget( + widget: Stack( + alignment: Alignment.center, + children: [ + Container( + height: 200, + width: Get.width, + margin: const EdgeInsets.symmetric( + horizontal: 20, + ), + child: ListWheelScrollView.useDelegate( + physics: const FixedExtentScrollPhysics(), + childDelegate: ListWheelChildBuilderDelegate( + builder: (context, index) { + return Center( + child: TextWidget( + text: c.serversList?[index].name ?? '', + color: Colors.white, + fontWeight: FontWeight.w400, + fontSize: 20, + ), + ); + }, + childCount: c.serversList?.length ?? 0, + ), + itemExtent: 45, + diameterRatio: 9, + controller: FixedExtentScrollController( + initialItem: initialItem ?? 0, + ), + useMagnifier: true, + magnification: 1.7, + clipBehavior: Clip.antiAliasWithSaveLayer, + onSelectedItemChanged: c.onSelectedItemChanged, + overAndUnderCenterOpacity: 0.7, + ), + ), + Column( + children: [ + Container( + margin: const EdgeInsets.symmetric( + horizontal: 120), + child: const Divider( + color: Colors.white, + thickness: 2, + ), + ), + const SizedBox(height: 30), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 120), + child: const Divider( + color: Colors.white, + thickness: 2, + ), + ), + ], + ), + ], + ), + ); + }, + ), + const Spacer(), + GetBuilder( + builder: (SelectISPController c) { + return !showNext! + ? Container() + : Container( + margin: const EdgeInsets.only(bottom: 30), + child: Align( + alignment: Alignment.bottomCenter, + child: Container( + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.white, + width: 1, + ), + ), + ), + child: TextButton( + onPressed: () => c.onIspSelected(), + child: TextWidget( + color: Colors.white, + fontSize: 26, + text: 'next_button'.tr, + fontWeight: FontWeight.normal, + ), + ), + ), + ), + ); + }, + ), + ], + ), + ), + ], + ), + ), + floatingActionButton: GetBuilder( + builder: (SelectISPController c) { + return !showNext! + ? Container() + : Container( + margin: const EdgeInsets.only( + right: 18, + left: 18, + bottom: 8, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GetBuilder( + builder: (SelectISPController c) { + return isCustomIsp! + ? Container( + margin: const EdgeInsets.only( + left: 18, + ), + child: FloatingActionButton( + heroTag: "btn1", + onPressed: c.removeISP, + backgroundColor: Colors.white, + child: SvgPicture.asset( + 'assets/remove.svg', + height: 30, + width: 30, + color: brandColor, + ), + ), + ) + : Container(); + }, + ), + FloatingActionButton( + heroTag: "btn2", + onPressed: () { + // Get.offNamed(Routes.ADD_ADDRESS); + }, + backgroundColor: Colors.white, + child: Icon( + Icons.add, + size: 50, + color: brandColor, + ), + ), + ], + ), + ); + }, + ), + ); + } +} diff --git a/lib/app/modules/service/api_service.dart b/lib/app/modules/service/api_service.dart new file mode 100644 index 0000000..d8e9aa6 --- /dev/null +++ b/lib/app/modules/service/api_service.dart @@ -0,0 +1,103 @@ +// ignore_for_file: unnecessary_overrides +import 'dart:async'; +import 'dart:io'; + +import 'package:http/http.dart' as http; +import 'package:logger/logger.dart'; + +import 'package:IQ/main.dart'; + +class APIService { + static Future getUrl(url) async { + try { + http.Request response; +// ignore: unrelated_type_equality_checks + response = http.Request('GET', Uri.parse(url)); + http.StreamedResponse request = await response.send(); + if (request.statusCode != 200) { + return request.statusCode; + } + String res = await request.stream.bytesToString(); + return res; + } catch (e) { + if (e is SocketException) { + return 0; + } else if (e is TimeoutException) { + return -2; + } + } + } + + static Future get(route, [bool auth = true]) async { + try { + var baseUrl = storage.read('baseUrl'); + var token = storage.read('token'); + // isExpired = JwtDecoder.isExpired(token!); + // if (isExpired) { + // storage.remove('token'); + // Get.offAllNamed(Routes.AUTOLOGIN); + // return -1; + // } + http.Request response; + response = http.Request('GET', Uri.parse('$baseUrl/$route')); + if (auth) response.headers.addAll({'Authorization': 'Bearer $token'}); + + http.StreamedResponse request = await response.send(); + Logger().e("token $token"); + if (request.statusCode != 200) { + token = null; + storage.remove('token'); + // Get.offAllNamed(Routes.SELECT_I_S_P); + return request.statusCode; + } + String res = await request.stream.bytesToString(); + Logger().e("request $res"); + return res; + } catch (e) { + if (e is SocketException) { + return 0; + } else if (e is TimeoutException) { + return -2; + } + } + } + + static Future post(route, String payload, [bool auth = true]) async { + try { + var baseUrl = storage.read('baseUrl'); + var token = storage.read('token'); + var request = http.Request( + 'POST', + Uri.parse('$baseUrl/$route'), + ); + request.bodyFields = {'payload': payload}; + // isExpired = JwtDecoder.isExpired(token!); + // if (isExpired) { + // storage.remove('token'); + // Get.offAllNamed(Routes.AUTOLOGIN); + // return -1; + // } + + if (auth) { + request.headers.addAll({ + 'Authorization': 'Bearer $token', + 'Accept': 'application/json', + }); + } + + http.StreamedResponse response = await request.send(); + if (response.statusCode != 200) { + return response.statusCode; + } + String res = await response.stream.bytesToString(); + + return res; + } catch (e) { + if (e is SocketException) { + return 0; + } else if (e is TimeoutException) { + return -2; + } + } + } +} diff --git a/lib/app/modules/single_ticket/bindings/single_ticket_binding.dart b/lib/app/modules/single_ticket/bindings/single_ticket_binding.dart new file mode 100644 index 0000000..1ce6694 --- /dev/null +++ b/lib/app/modules/single_ticket/bindings/single_ticket_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/single_ticket_controller.dart'; + +class SingleTicketBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SingleTicketController(), + ); + } +} diff --git a/lib/app/modules/single_ticket/controllers/single_ticket_controller.dart b/lib/app/modules/single_ticket/controllers/single_ticket_controller.dart new file mode 100644 index 0000000..80496fc --- /dev/null +++ b/lib/app/modules/single_ticket/controllers/single_ticket_controller.dart @@ -0,0 +1,133 @@ +// ignore_for_file: unnecessary_overrides + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/modules/home/models/single_ticket.dart'; +import 'package:IQ/app/modules/home/models/support_model.dart' + as support_ticket; +import 'package:IQ/app/modules/home/providers/add_reply_ticket.dart'; +import 'package:IQ/app/modules/home/providers/single_ticket_provider.dart'; + +class SingleTicketController extends GetxController + with WidgetsBindingObserver { + final formKey = GlobalKey(); + bool inputsEntered = false; + + // make scroll controller + final scrollController = ScrollController(); + bool fetchTicketsMessagesData = false; + // ignore: prefer_typing_uninitialized_variables + var fetchTicketsMessagesDataVar; + Future onRefresh() async { + fetchTicketsMessagesData = false; + inputsEntered = false; + singleTicket = null; + fetchTicketsMessagesDataVar = fetchLoadingSupportTicketsData(); + update(); + } + + final support_ticket.Data ticket = Get.arguments; + fetchLoadingSupportTicketsData() async { + await getUserSupportTicketsInforms(ticket.id); + if (getUserSupportTicketsLoads) { + fetchTicketsMessagesData = true; + messages = singleTicket?.data?.messages ?? []; + // ignore: prefer_is_empty + if (messages?.length != 0) { + WidgetsBinding.instance.addPostFrameCallback((_) { + scrollController.animateTo( + scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 1000), + curve: Curves.easeOut, + ); + }); + } + update(); + } else { + fetchTicketsMessagesData = false; + update(); + Get.snackbar('Error', 'Please try again later'); + } + } + + sendTicketReply() async { + String? username = ""; + if ((formKey.currentState?.validate())!) { + inputsEntered = true; + update(); + messages?.forEach((element) { + if (element.userDetails != null) { + username = element.userDetails?.username; + } + }); + await getUserSendReplyTicketInforms(ticket.id, ticketReply); + if (getUserSendReplyTicketInformsLoads) { + inputsEntered = false; + var now = DateTime.now(); + messages?.add( + Messages( + message: ticketReply, + createdAt: + "${now.year}-${now.month}-${now.day} ${now.hour}:${now.minute}:${now.second}", + userDetails: UserDetails(username: username), + ), + ); + formKey.currentState?.reset(); + update(); + scrollController.animateTo( + scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 300), + curve: Curves.easeOut, + ); + } else { + inputsEntered = false; + update(); + Get.snackbar('Error', 'Please try again later'); + } + } else { + inputsEntered = false; + update(); + } + } + + String? ticketReply; + onChangeTicketReply(String? ticketReplyInput) { + ticketReply = ticketReplyInput; + update(); + } + + List? messages = singleTicket?.data?.messages ?? []; + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + snackBarText = 'back_twice'.tr; + } + } + + @override + void onInit() { + fetchTicketsMessagesDataVar = fetchLoadingSupportTicketsData(); + WidgetsBinding.instance.addObserver(this); + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} diff --git a/lib/app/modules/single_ticket/views/single_ticket_view.dart b/lib/app/modules/single_ticket/views/single_ticket_view.dart new file mode 100644 index 0000000..d875533 --- /dev/null +++ b/lib/app/modules/single_ticket/views/single_ticket_view.dart @@ -0,0 +1,433 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/modules/home/models/support_model.dart' + as support_model; +import 'package:IQ/app/modules/single_ticket/controllers/single_ticket_controller.dart'; + +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; + +class SingleTicketView extends GetView { + SingleTicketView({Key? key}) : super(key: key); + final GlobalKey scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + var stackedContainer = Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox(height: MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Container( + margin: const EdgeInsets.only(top: 10), + child: Align( + alignment: Alignment.bottomCenter, + child: Column( + children: [ + SvgPicture.asset( + 'assets/support_icon.svg', + color: Colors.white, + height: 90, + width: 90, + ), + const SizedBox(height: 15), + TextWidget( + text: 'support'.tr, + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.w300, + textAlign: TextAlign.center, + ), + const SizedBox(height: 10), + ], + ), + ), + ) + ], + ), + ); + return Directionality( + textDirection: + defaultLocale == "en" ? TextDirection.rtl : TextDirection.ltr, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: GetBuilder( + init: SingleTicketController(), + builder: (SingleTicketController singleTicketController) { + return RefreshIndicator( + onRefresh: controller.onRefresh, + triggerMode: RefreshIndicatorTriggerMode.anywhere, + backgroundColor: Colors.white, + color: brandColor, + child: singleTicketController.fetchTicketsMessagesData + ? Stack( + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + height: 100, + margin: const EdgeInsets.only( + right: 20.0, + left: 20.0, + top: 25, + ), + child: FormBuilder( + key: controller.formKey, + child: FormBuilderTextField( + textDirection: textDirection, + autovalidateMode: + AutovalidateMode.onUserInteraction, + textAlign: defaultLocale == "en" + ? TextAlign.left + : TextAlign.right, + textAlignVertical: TextAlignVertical.top, + onChanged: controller.onChangeTicketReply, + name: 'ticket_message', + onEditingComplete: () { + FocusScope.of(context).unfocus(); + }, + validator: FormBuilderValidators.compose( + [ + FormBuilderValidators.required( + errorText: 'message_input_error'.tr, + ), + ], + ), + expands: true, + minLines: null, + maxLines: null, + style: buildTextStyle( + fontSize: 20, + color: Colors.black, + ), + keyboardType: TextInputType.multiline, + textInputAction: TextInputAction.newline, + decoration: InputDecoration( + hintTextDirection: defaultLocale == "en" + ? TextDirection.ltr + : TextDirection.rtl, + fillColor: Colors.white, + hintText: 'message'.tr, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(15), + borderSide: const BorderSide( + color: Colors.black, + ), + ), + filled: true, + hintStyle: buildTextStyle( + color: const Color.fromARGB( + 255, 184, 184, 184), + fontSize: 19, + ), + errorMaxLines: 2, + isDense: true, + errorStyle: buildTextStyle( + fontSize: 12, + color: const Color.fromARGB( + 255, 184, 184, 184), + ), + ), + ), + ), + ), + const SizedBox(height: 12), + Container( + width: widthSize(context), + height: 60, + margin: const EdgeInsets.symmetric( + horizontal: 20, vertical: 20), + child: TextButton( + onPressed: () { + FocusScope.of(context).unfocus(); + singleTicketController.sendTicketReply(); + }, + style: ButtonStyle( + shape: MaterialStateProperty.all( + const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(15), + ), + ), + ), + backgroundColor: MaterialStateProperty.all( + brandColor, + ), + ), + child: !singleTicketController.inputsEntered + ? TextWidget( + text: "send".tr, + fontSize: 18, + fontWeight: FontWeight.normal, + color: Colors.white, + ) + : const CircularProgressIndicator( + color: Colors.white, + ), + ), + ), + ], + ), + ), + Container( + margin: const EdgeInsets.only(top: 250), + padding: const EdgeInsets.only( + left: 20, + right: 20, + top: 18, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _getTicketStatus(singleTicketController.ticket), + TextWidget( + text: singleTicketController.ticket.subject, + fontSize: 22, + fontWeight: FontWeight.w500, + textAlign: TextAlign.right, + ), + ], + ), + ), + Container( + margin: const EdgeInsets.only( + top: 320, + bottom: 215, + ), + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + controller: singleTicketController.scrollController, + child: Column( + children: singleTicketController.messages?.map( + (message) { + if (message.managerDetails == null) { + return Container( + margin: const EdgeInsets.symmetric( + horizontal: 18, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ + TextWidget( + text: + "${message.userDetails?.username}", + fontSize: 20, + textAlign: TextAlign.right, + fontWeight: FontWeight.w500, + color: brandColor, + ), + const SizedBox(height: 2), + Container( + width: widthSize(context) * 0.8, + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), + color: const Color(0xffCCEAC7), + child: TextWidget( + text: "${message.message}", + fontSize: 18, + fontWeight: FontWeight.w500, + softWrap: true, + textAlign: TextAlign.end, + color: Colors.black, + ), + ), + const SizedBox(height: 3), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 60, + ), + alignment: defaultLocale == "en" + ? Alignment.centerRight + : Alignment.centerLeft, + child: TextWidget( + text: defaultLocale != "en" + ? "${message.createdAt?.split(" ")[0]} ${message.createdAt?.split(" ")[1]}" + : "${message.createdAt?.split(" ")[1]} ${message.createdAt?.split(" ")[0]}", + fontSize: 18, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + ), + const SizedBox(height: 22), + ], + ), + ); + } else { + return Container( + margin: const EdgeInsets.symmetric( + horizontal: 18, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + TextWidget( + text: + "${message.managerDetails?.username}", + fontSize: 20, + textAlign: TextAlign.right, + fontWeight: FontWeight.w500, + color: brandColor, + ), + const SizedBox(height: 2), + Container( + width: widthSize(context) * 0.8, + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 10, + ), + color: const Color(0xffC7DBEA), + child: TextWidget( + text: "${message.message}", + fontSize: 18, + fontWeight: FontWeight.w500, + softWrap: true, + textAlign: TextAlign.end, + color: Colors.black, + ), + ), + const SizedBox(height: 3), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 60, + ), + alignment: defaultLocale == "en" + ? Alignment.centerLeft + : Alignment.centerRight, + child: TextWidget( + text: defaultLocale != "en" + ? "${message.createdAt?.split(" ")[0]} ${message.createdAt?.split(" ")[1]}" + : "${message.createdAt?.split(" ")[1]} ${message.createdAt?.split(" ")[0]}", + fontSize: 18, + fontWeight: FontWeight.w400, + color: Colors.black, + ), + ), + const SizedBox(height: 22), + ], + ), + ); + } + }, + ).toList() as List, + ), + ), + ), + stackedContainer, + ], + ) + : Stack( + children: [ + Center( + child: CircularProgressIndicator( + color: brandColor, + ), + ), + stackedContainer, + ], + ), + ); + }, + ), + ), + ); + } + + Widget _getTicketStatus(support_model.Data e) { + String? statusString; + Color? statusColor; + if (e.closed == 0) { + statusString = "ticket_status_waiting".tr; + statusColor = const Color(0xffEB7923); + } else { + if (e.solved == 1) { + statusString = "ticket_status_solved".tr; + statusColor = brandColor; + } + if (e.solved == 0) { + statusString = "ticket_status_closed".tr; + statusColor = Colors.green; + } + } + return TextWidget( + text: statusString!, + fontSize: 20, + fontWeight: FontWeight.w700, + color: statusColor, + ); + } +} diff --git a/lib/app/modules/splash/splash.dart b/lib/app/modules/splash/splash.dart new file mode 100644 index 0000000..d73f1ac --- /dev/null +++ b/lib/app/modules/splash/splash.dart @@ -0,0 +1,34 @@ +import 'package:IQ/app/global/static_informs.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/routes/app_pages.dart'; + +class SplashScreen extends StatefulWidget { + const SplashScreen({super.key}); + + @override + _SplashScreenState createState() => _SplashScreenState(); +} + +class _SplashScreenState extends State { + @override + void initState() { + super.initState(); + Future.delayed(const Duration(seconds: 1), () { + Get.offAllNamed(Routes.AUTOLOGIN); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: brandColor, + body: Center( + child: SvgPicture.asset( + "assets/2/icon.svg", + ), + ), + ); + } +} diff --git a/lib/app/modules/support/bindings/support_binding.dart b/lib/app/modules/support/bindings/support_binding.dart new file mode 100644 index 0000000..2429c96 --- /dev/null +++ b/lib/app/modules/support/bindings/support_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/support_controller.dart'; + +class SupportBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => SupportController(), + ); + } +} diff --git a/lib/app/modules/support/controllers/support_controller.dart b/lib/app/modules/support/controllers/support_controller.dart new file mode 100644 index 0000000..cf801c0 --- /dev/null +++ b/lib/app/modules/support/controllers/support_controller.dart @@ -0,0 +1,68 @@ +// ignore_for_file: unnecessary_overrides + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/modules/home/models/support_model.dart'; +import 'package:IQ/app/modules/home/providers/support.dart'; + +class SupportController extends GetxController with WidgetsBindingObserver { + bool fetchSupportData = false; + // ignore: prefer_typing_uninitialized_variables + var fetchLoadingSupportTicketsDataVar; + + Future onRefresh() async { + fetchSupportData = false; + supportTickets = null; + fetchLoadingSupportTicketsDataVar = fetchLoadingSupportTicketsData(); + update(); + } + + fetchLoadingSupportTicketsData() async { + await getUserSupportInforms(); + if (getUserSupportInformsLoads) { + fetchSupportData = true; + listOfSupportTickets = supportTickets?.data ?? []; + update(); + } else { + fetchSupportData = false; + listOfSupportTickets = []; + update(); + Get.snackbar('Error', 'Please try again later'); + } + } + + List? listOfSupportTickets = supportTickets?.data ?? []; + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + if (state == AppLifecycleState.inactive || + state == AppLifecycleState.detached || + state == AppLifecycleState.paused) return; + if (state == AppLifecycleState.resumed) { + defaultLocale = Platform.localeName.split('_')[0]; + snackBarText = 'back_twice'.tr; + } + } + + @override + void onInit() { + fetchLoadingSupportTicketsDataVar = fetchLoadingSupportTicketsData(); + WidgetsBinding.instance.addObserver(this); + + super.onInit(); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + } +} diff --git a/lib/app/modules/support/views/support_view.dart b/lib/app/modules/support/views/support_view.dart new file mode 100644 index 0000000..8dc2c5a --- /dev/null +++ b/lib/app/modules/support/views/support_view.dart @@ -0,0 +1,318 @@ +import 'package:flutter/material.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/modules/home/models/support_model.dart'; +import 'package:IQ/app/routes/app_pages.dart'; + +import '../controllers/support_controller.dart'; + +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; + +class SupportView extends GetView { + SupportView({Key? key}) : super(key: key); + final GlobalKey scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + var stackedContainer = Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox(height: MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Container( + margin: const EdgeInsets.only(top: 10), + child: Align( + alignment: Alignment.bottomCenter, + child: Column( + children: [ + SvgPicture.asset( + 'assets/support_icon.svg', + color: Colors.white, + height: 90, + width: 90, + ), + const SizedBox(height: 15), + TextWidget( + text: 'support'.tr, + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.w300, + textAlign: TextAlign.center, + ), + const SizedBox(height: 10), + ], + ), + ), + ) + ], + ), + ); + return Directionality( + textDirection: + defaultLocale == "en" ? TextDirection.rtl : TextDirection.ltr, + child: Scaffold( + backgroundColor: backgroundColor, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + floatingActionButtonAnimator: FloatingActionButtonAnimator.scaling, + floatingActionButton: Container( + width: widthSize(context), + height: 60, + margin: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + child: TextButton( + onPressed: () { + Get.toNamed(Routes.NEW_TICKET); + }, + style: ButtonStyle( + shape: MaterialStateProperty.all( + const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(15), + ), + ), + ), + backgroundColor: MaterialStateProperty.all( + brandColor, + ), + ), + child: TextWidget( + text: "new_support_ticket".tr, + fontSize: 18, + fontWeight: FontWeight.normal, + color: Colors.white, + ), + ), + ), + drawerEdgeDragWidth: widthSize(context), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: GetBuilder( + init: SupportController(), + builder: (SupportController supportController) { + return RefreshIndicator( + onRefresh: controller.onRefresh, + triggerMode: RefreshIndicatorTriggerMode.anywhere, + backgroundColor: Colors.white, + color: brandColor, + child: supportController.fetchSupportData + ? Stack( + children: [ + Container( + margin: const EdgeInsets.only(top: 250), + child: (controller + .listOfSupportTickets?.isNotEmpty)! + ? SingleChildScrollView( + physics: + const AlwaysScrollableScrollPhysics(), + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: + controller.listOfSupportTickets?.map( + (e) { + return Container( + color: Colors.white, + margin: controller + .listOfSupportTickets + ?.last == + e + ? const EdgeInsets.only( + bottom: 80) + : null, + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 15, + right: 15, + ), + child: InkWell( + onTap: () { + Get.toNamed( + Routes.SINGLE_TICKET, + arguments: e, + ); + }, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Container( + margin: + const EdgeInsets.all( + 10), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + TextWidget( + text: e.createdAt + ?.split(' ')[0], + color: Colors.black, + fontSize: 22, + ), + TextWidget( + text: e.subject, + fontSize: 20, + color: const Color( + 0xff7A7A7A), + ), + ], + ), + ), + const SizedBox(height: 15), + Padding( + padding: const EdgeInsets + .symmetric( + horizontal: 10), + child: _getTicketStatus(e), + ), + const SizedBox(height: 4), + const Divider(), + ], + ), + ), + ); + }, + ).toList() as List, + ), + ) + : Center( + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + TextWidget( + text: 'empty_support'.tr, + color: Colors.grey, + fontSize: 24, + fontWeight: FontWeight.w500, + textAlign: TextAlign.center, + ), + const SizedBox(height: 15), + InkWell( + child: const Icon( + Icons.refresh, + color: Colors.grey, + size: 50, + ), + onTap: controller.onRefresh, + ), + ], + ), + ), + ), + stackedContainer, + ], + ) + : Stack( + children: [ + Center( + child: CircularProgressIndicator( + color: brandColor, + ), + ), + stackedContainer, + ], + ), + ); + }, + ), + ), + ), + ); + } + + Widget _getTicketStatus(Data e) { + String? statusString; + Color? statusColor; + if (e.closed == 0) { + statusString = "ticket_status_waiting".tr; + statusColor = const Color(0xffEB7923); + } else { + if (e.solved == 1) { + statusString = "ticket_status_solved".tr; + statusColor = brandColor; + } + if (e.solved == 0) { + statusString = "ticket_status_closed".tr; + statusColor = Colors.green; + } + } + return TextWidget( + text: statusString!, + fontSize: 20, + fontWeight: FontWeight.w700, + color: statusColor, + ); + } +} diff --git a/lib/app/modules/wifi_test/bindings/wifi_test_binding.dart b/lib/app/modules/wifi_test/bindings/wifi_test_binding.dart new file mode 100644 index 0000000..0b2da76 --- /dev/null +++ b/lib/app/modules/wifi_test/bindings/wifi_test_binding.dart @@ -0,0 +1,12 @@ +import 'package:get/get.dart'; + +import '../controllers/wifi_test_controller.dart'; + +class WifiTestBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => WifiTestController(), + ); + } +} diff --git a/lib/app/modules/wifi_test/controllers/wifi_test_controller.dart b/lib/app/modules/wifi_test/controllers/wifi_test_controller.dart new file mode 100644 index 0000000..e653357 --- /dev/null +++ b/lib/app/modules/wifi_test/controllers/wifi_test_controller.dart @@ -0,0 +1,101 @@ +// ignore_for_file: unnecessary_overrides + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class WifiTestController extends GetxController { + /// + final GlobalKey webViewKey = GlobalKey(); + var data = Get.arguments; + String url1 = ""; + + /// + late PullToRefreshController pullToRefreshController; + double progress1 = 0; + onProgressChanged(_, progress2) { + if (progress2 == 100) { + pullToRefreshController.endRefreshing(); + } + progress1 = progress2 / 100; + } + + onLoadStart(_, url2) { + url1 = url2.toString(); + update(); + } + + onLoadStop(_, url2) async { + pullToRefreshController.endRefreshing(); + url1 = url2.toString(); + update(); + } + + onLoadError(_, __, ___, ____) { + pullToRefreshController.endRefreshing(); + } + + /// + InAppWebViewController? webViewController; + onWebViewCreated(controller) { + webViewController = controller; + } + + onPressedBack() { + webViewController?.goBack(); + } + + onPressedForward() { + webViewController?.goForward(); + } + + onPressedReload() { + webViewController?.reload(); + } + + /// + Future shouldOverrideUrlLoading(_, navAc) async { + var uri = navAc.request.url!; + if (!["http", "https", "file", "chrome", "data", "javascript", "about"] + .contains(uri.scheme)) { + if (await canLaunchUrl(Uri.parse(url1))) { + // Launch the App + await launchUrl(Uri.parse(url1)); + // and cancel the request + return NavigationActionPolicy.CANCEL; + } + } + return NavigationActionPolicy.ALLOW; + } + + @override + void onInit() { + super.onInit(); + pullToRefreshController = PullToRefreshController( + options: PullToRefreshOptions(color: brandColor), + onRefresh: () async { + if (Platform.isAndroid) { + webViewController?.reload(); + } else if (Platform.isIOS) { + webViewController?.loadUrl( + urlRequest: URLRequest( + url: await webViewController?.getUrl(), + ), + ); + } + }, + ); + } + + @override + void onReady() { + super.onReady(); + } + + @override + void onClose() {} +} diff --git a/lib/app/modules/wifi_test/views/wifi_test_view.dart b/lib/app/modules/wifi_test/views/wifi_test_view.dart new file mode 100644 index 0000000..21ee3ee --- /dev/null +++ b/lib/app/modules/wifi_test/views/wifi_test_view.dart @@ -0,0 +1,207 @@ +import 'package:double_back_to_close_app/double_back_to_close_app.dart'; +import 'package:IQ/app/global/text_widget.dart'; +import 'package:IQ/app/modules/home/providers/user.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import 'package:get/get.dart'; +import 'package:IQ/app/global/global_snackbar.dart'; +import 'package:IQ/app/global/static_informs.dart'; +import 'package:IQ/app/modules/drawerSide/views/drawer_side_view.dart'; + +import '../controllers/wifi_test_controller.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; + +class WifiTestView extends GetView { + WifiTestView({Key? key}) : super(key: key); + final GlobalKey scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Directionality( + textDirection: + defaultLocale != "en" ? TextDirection.ltr : TextDirection.rtl, + child: Scaffold( + backgroundColor: Colors.white, + drawerScrimColor: Colors.black.withOpacity(0.7), + key: scaffoldKey, + endDrawer: const DrawerSideView(), + drawerEdgeDragWidth: widthSize(context), + body: DoubleBackToCloseApp( + snackBar: snackBar, + child: Stack( + children: [ + Container( + margin: const EdgeInsets.only(top: 250), + child: Stack( + children: [ + GetBuilder( + builder: (WifiTestController c) { + return InAppWebView( + /// + key: c.webViewKey, + initialUrlRequest: URLRequest( + url: Uri.parse("https://www.speedtest.net/"), + ), + initialOptions: InAppWebViewGroupOptions( + crossPlatform: InAppWebViewOptions( + useShouldOverrideUrlLoading: true, + mediaPlaybackRequiresUserGesture: false, + ), + android: AndroidInAppWebViewOptions( + useHybridComposition: true, + ), + ios: IOSInAppWebViewOptions( + allowsInlineMediaPlayback: true, + ), + ), + + /// + pullToRefreshController: c.pullToRefreshController, + onLoadStart: controller.onLoadStart, + onLoadStop: controller.onLoadStop, + onLoadError: controller.onLoadError, + + /// + onWebViewCreated: controller.onWebViewCreated, + onProgressChanged: controller.onProgressChanged, + + /// + androidOnPermissionRequest: (_, __, resources) async { + return PermissionRequestResponse( + resources: resources, + action: PermissionRequestResponseAction.GRANT, + ); + }, + onConsoleMessage: (controller, consoleMessage) { + debugPrint('consoleMessage = $consoleMessage'); + }, + + /// + shouldOverrideUrlLoading: + controller.shouldOverrideUrlLoading, + ); + }, + ), + GetBuilder( + builder: (WifiTestController co) { + return co.progress1 < 1.0 + ? LinearProgressIndicator(value: co.progress1) + : Container(); + }, + ), + ], + ), + ), + Container( + height: 250, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Stack( + children: [ + Container( + height: 230, + decoration: BoxDecoration( + color: brandColor, + image: const DecorationImage( + image: AssetImage('assets/background.png'), + fit: BoxFit.fill, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: MediaQuery.of(context).viewPadding.top), + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + margin: const EdgeInsets.only( + top: 5, + right: 15, + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/2/icon.svg", + height: 20, + width: 71.16, + ), + const SizedBox(width: 10), + Image.asset("assets/logo.png"), + ], + ), + ), + const SizedBox(width: 10), + Row( + children: [ + Text( + user?.data?.firstname ?? ' . . . ', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.normal, + ), + ), + IconButton( + onPressed: () { + scaffoldKey.currentState + ?.openEndDrawer(); + }, + icon: const Icon( + Icons.menu, + color: Colors.white, + size: 40, + ), + ), + ], + ), + ], + ), + ), + Container( + alignment: Alignment.center, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 30), + SvgPicture.asset( + 'assets/speedometer.svg', + height: 50, + width: 50, + color: Colors.white, + ), + const SizedBox(height: 20), + const TextWidget( + text: "SpeedTest", + fontSize: 28, + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/app/routes/app_pages.dart b/lib/app/routes/app_pages.dart new file mode 100644 index 0000000..323fbbe --- /dev/null +++ b/lib/app/routes/app_pages.dart @@ -0,0 +1,133 @@ +import 'package:IQ/app/modules/about/about_view.dart'; +import 'package:IQ/app/modules/about/bindings/about_binding.dart'; +import 'package:IQ/app/modules/splash/splash.dart'; +import 'package:get/get.dart'; +import 'package:IQ/app/modules/fillCard/bindings/fill_card_binding.dart'; +import 'package:IQ/app/modules/fillCard/views/fill_card_view.dart'; +import 'package:IQ/app/modules/wifi_test/bindings/wifi_test_binding.dart'; +import 'package:IQ/app/modules/wifi_test/views/wifi_test_view.dart'; + +import '../modules/LiveData/bindings/live_data_binding.dart'; +import '../modules/LiveData/views/live_data_view.dart'; +import '../modules/contact_us/bindings/contact_us_binding.dart'; +import '../modules/contact_us/views/contact_us_view.dart'; +import '../modules/autologin/bindings/autologin_binding.dart'; +import '../modules/autologin/views/autologin_view.dart'; +import '../modules/availablePackages/bindings/available_packages_binding.dart'; +import '../modules/availablePackages/views/available_packages_view.dart'; +import '../modules/dataUsage/bindings/data_usage_binding.dart'; +import '../modules/dataUsage/views/data_usage_view.dart'; +import '../modules/drawerSide/bindings/drawer_side_binding.dart'; +import '../modules/drawerSide/views/drawer_side_view.dart'; +import '../modules/home/bindings/home_binding.dart'; +import '../modules/home/views/home_view.dart'; +import '../modules/login/bindings/login_binding.dart'; +import '../modules/login/views/login_view.dart'; +import '../modules/new_ticket/bindings/new_ticket_binding.dart'; +import '../modules/new_ticket/views/new_ticket_view.dart'; +import '../modules/notificationsScreen/bindings/notifications_screen_binding.dart'; +import '../modules/notificationsScreen/views/notifications_screen_view.dart'; +import '../modules/selectISP/bindings/select_isp_binding.dart'; +import '../modules/selectISP/views/select_isp_view.dart'; +import '../modules/single_ticket/bindings/single_ticket_binding.dart'; +import '../modules/single_ticket/views/single_ticket_view.dart'; +import '../modules/support/bindings/support_binding.dart'; +import '../modules/support/views/support_view.dart'; + +// ignore_for_file: constant_identifier_names + +part 'app_routes.dart'; + +class AppPages { + AppPages._(); + + static const INITIAL = Routes.SELECT_I_S_P; + + static final routes = [ + GetPage( + name: _Paths.HOME, + page: () => HomeView(), + binding: HomeBinding(), + ), + GetPage( + name: _Paths.LOGIN, + page: () => LoginView(), + binding: LoginBinding(), + ), + GetPage( + name: _Paths.SELECT_I_S_P, + page: () => const SelectISPView(), + binding: SelectISPBinding(), + ), + GetPage( + name: _Paths.AUTOLOGIN, + page: () => const AutologinView(), + binding: AutologinBinding(), + ), + GetPage( + name: _Paths.DRAWER_SIDE, + page: () => const DrawerSideView(), + binding: DrawerSideBinding(), + ), + GetPage( + name: _Paths.DATA_USAGE, + page: () => const DataUsageView(), + binding: DataUsageBinding(), + ), + GetPage( + name: _Paths.AVAILABLE_PACKAGES, + page: () => AvailablePackagesView(), + binding: AvailablePackagesBinding(), + ), + GetPage( + name: _Paths.CONTACT_US, + page: () => ContactUsView(), + binding: ContactUsBinding(), + ), + GetPage( + name: _Paths.NOTIFICATIONS_SCREEN, + page: () => NotificationsScreenView(), + binding: NotificationsScreenBinding(), + ), + GetPage( + name: _Paths.LIVE_DATA, + page: () => const LiveDataView(), + binding: LiveDataBinding(), + ), + GetPage( + name: _Paths.SUPPORT, + page: () => SupportView(), + binding: SupportBinding(), + ), + GetPage( + name: _Paths.NEW_TICKET, + page: () => NewTicketView(), + binding: NewTicketBinding(), + ), + GetPage( + name: _Paths.SINGLE_TICKET, + page: () => SingleTicketView(), + binding: SingleTicketBinding(), + ), + GetPage( + name: _Paths.FILL_CARD, + page: () => FillCardView(), + binding: FillCardBinding(), + ), + GetPage( + name: _Paths.WIFI_TEST, + page: () => WifiTestView(), + binding: WifiTestBinding(), + ), + GetPage( + name: _Paths.ABOUT, + page: () => AboutView(), + binding: AboutBinding(), + ), + GetPage( + name: _Paths.SPLASH, + page: () => const SplashScreen(), + binding: AboutBinding(), + ), + ]; +} diff --git a/lib/app/routes/app_routes.dart b/lib/app/routes/app_routes.dart new file mode 100644 index 0000000..ab318dd --- /dev/null +++ b/lib/app/routes/app_routes.dart @@ -0,0 +1,45 @@ +// ignore_for_file: constant_identifier_names + +part of 'app_pages.dart'; +// DO NOT EDIT. This is code generated via package:get_cli/get_cli.dart +abstract class Routes { + Routes._(); + static const SPLASH = _Paths.SPLASH; + static const HOME = _Paths.HOME; + static const LOGIN = _Paths.LOGIN; + static const SELECT_I_S_P = _Paths.SELECT_I_S_P; + static const AUTOLOGIN = _Paths.AUTOLOGIN; + static const DRAWER_SIDE = _Paths.DRAWER_SIDE; + static const DATA_USAGE = _Paths.DATA_USAGE; + static const AVAILABLE_PACKAGES = _Paths.AVAILABLE_PACKAGES; + static const ABOUT = _Paths.ABOUT; + static const NOTIFICATIONS_SCREEN = _Paths.NOTIFICATIONS_SCREEN; + static const LIVE_DATA = _Paths.LIVE_DATA; + static const SUPPORT = _Paths.SUPPORT; + static const NEW_TICKET = _Paths.NEW_TICKET; + static const SINGLE_TICKET = _Paths.SINGLE_TICKET; + static const FILL_CARD = _Paths.FILL_CARD; + static const WIFI_TEST = _Paths.WIFI_TEST; + static const CONTACT_US = _Paths.CONTACT_US; +} + +abstract class _Paths { + _Paths._(); + static const SPLASH = '/splash'; + static const HOME = '/home'; + static const LOGIN = '/login'; + static const SELECT_I_S_P = '/select-i-s-p'; + static const AUTOLOGIN = '/autologin'; + static const DRAWER_SIDE = '/drawer-side'; + static const DATA_USAGE = '/data-usage'; + static const AVAILABLE_PACKAGES = '/available-packages'; + static const ABOUT = '/about'; + static const NOTIFICATIONS_SCREEN = '/notifications-screen'; + static const LIVE_DATA = '/live-data'; + static const SUPPORT = '/support'; + static const NEW_TICKET = '/new-ticket'; + static const SINGLE_TICKET = '/single-ticket'; + static const FILL_CARD = '/fill-card'; + static const WIFI_TEST = '/wifi-test'; + static const CONTACT_US = '/contact-us'; +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..57f1740 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,86 @@ +// import 'package:firebase_core/firebase_core.dart'; +// import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:get_storage/get_storage.dart'; + +import 'dart:io'; +import 'package:flutter/services.dart'; +import 'package:jwt_decoder/jwt_decoder.dart'; +import 'package:IQ/app/modules/selectISP/models/isp_model.dart'; +import 'package:IQ/app/modules/selectISP/views/select_isp_view.dart'; +import 'package:IQ/app.dart'; +import 'package:logger/logger.dart'; + +final storage = GetStorage(); +String? token = ''; +String? deviceId = ''; +bool isExpired = false; +String lat = ""; +String long = ""; +Future _getRequestPermission() async { + LocationPermission permission = await Geolocator.requestPermission(); + if (permission == LocationPermission.deniedForever) { + Geolocator.openAppSettings(); + return null; // Return null or handle this case differently. + } else if (permission == LocationPermission.denied) { + return null; // Return null or handle this case differently. + } else { + // If permission is granted, get the current position and return. + return await Geolocator.getCurrentPosition(); + } +} + +class MyHttpOverrides extends HttpOverrides { + @override + HttpClient createHttpClient(SecurityContext? context) { + return super.createHttpClient(context) + ..badCertificateCallback = ( + X509Certificate cert, + String host, + int port, + ) => + true; + } +} + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + // await Firebase.initializeApp(); + HttpOverrides.global = MyHttpOverrides(); + await GetStorage.init(); + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarIconBrightness: Brightness.light, + ), + ); + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + token = storage.read('token'); + selectedISP = storage.read('selectedISP') != null + ? ISPsData.fromJson(storage.read('selectedISP')) + : null; + if (token != null) { + isExpired = JwtDecoder.isExpired(token!); + if (isExpired == true) { + storage.remove('token'); + } + } + // final messaging = FirebaseMessaging.instance; + // await messaging.requestPermission( + // alert: true, + // badge: true, + // sound: true, + // ); + // deviceId = await messaging.getToken(); + Logger().e("deviceId = $deviceId"); + final currentPosition = await _getRequestPermission(); + if (currentPosition != null) { + lat = currentPosition.latitude.toString(); + long = currentPosition.longitude.toString(); + } + runApp(MyApp()); +} diff --git a/linux/.gitignore b/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 0000000..0322736 --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,116 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "sas4") +set(APPLICATION_ID "com.SnonoConnect") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/linux/flutter/CMakeLists.txt b/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..42992f2 --- /dev/null +++ b/linux/flutter/CMakeLists.txt @@ -0,0 +1,86 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..f6f23bf --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); +} diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..e0f0a47 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..f16b4c3 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_linux +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/linux/main.cc b/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/linux/my_application.cc b/linux/my_application.cc new file mode 100644 index 0000000..61e8a8e --- /dev/null +++ b/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "sas4"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "sas4"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/linux/my_application.h b/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/macos/.gitignore b/macos/.gitignore new file mode 100644 index 0000000..746adbb --- /dev/null +++ b/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000..4b81f9b --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000..5caa9d1 --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..5e1523a --- /dev/null +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,22 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import firebase_core +import firebase_messaging +import geolocator_apple +import path_provider_foundation +import sqflite +import url_launcher_macos + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) + FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) + GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) +} diff --git a/macos/Podfile b/macos/Podfile new file mode 100644 index 0000000..049abe2 --- /dev/null +++ b/macos/Podfile @@ -0,0 +1,40 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..cc5df34 --- /dev/null +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,572 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* snonoconnect.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "snonoconnect.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* snonoconnect.app */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* snonoconnect.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..86ca19d --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000..d53ef64 --- /dev/null +++ b/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a2ec33f --- /dev/null +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000..3c4935a Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000..ed4cc16 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000..483be61 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000..bcbf36d Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000..9c0a652 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000..e71a726 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000..8a31fe2 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..80e867a --- /dev/null +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..6eadf0a --- /dev/null +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = snonoconnect + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.snonoconnect + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2022 com.example. All rights reserved. diff --git a/macos/Runner/Configs/Debug.xcconfig b/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000..36b0fd9 --- /dev/null +++ b/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Release.xcconfig b/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000..dff4f49 --- /dev/null +++ b/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Warnings.xcconfig b/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000..42bcbf4 --- /dev/null +++ b/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000..dddb8a3 --- /dev/null +++ b/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist new file mode 100644 index 0000000..4789daa --- /dev/null +++ b/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000..2722837 --- /dev/null +++ b/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements new file mode 100644 index 0000000..852fa1a --- /dev/null +++ b/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..4c9b85a --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,919 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "5dce45a06d386358334eb1689108db6455d90ceb0d75848d5f4819283d4ee2b8" + url: "https://pub.dev" + source: hosted + version: "1.3.4" + archive: + dependency: transitive + description: + name: archive + sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + url: "https://pub.dev" + source: hosted + version: "3.3.7" + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + asn1lib: + dependency: transitive + description: + name: asn1lib + sha256: b74e3842a52c61f8819a1ec8444b4de5419b41a7465e69d4aa681445377398b0 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 + url: "https://pub.dev" + source: hosted + version: "3.2.3" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 + url: "https://pub.dev" + source: hosted + version: "1.0.2" + carousel_slider: + dependency: "direct main" + description: + name: carousel_slider + sha256: "9c695cc963bf1d04a47bd6021f68befce8970bcd61d24938e1fb0918cf5d9c42" + url: "https://pub.dev" + source: hosted + version: "4.2.1" + change_app_package_name: + dependency: "direct main" + description: + name: change_app_package_name + sha256: f9ebaf68a4b5a68c581492579bb68273c523ef325fbf9ce2f1b57fb136ad023b + url: "https://pub.dev" + source: hosted + version: "1.1.0" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7 + url: "https://pub.dev" + source: hosted + version: "0.4.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + crypto: + dependency: "direct main" + description: + name: crypto + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + csslib: + dependency: transitive + description: + name: csslib + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" + double_back_to_close_app: + dependency: "direct main" + description: + name: double_back_to_close_app + sha256: d19ce4e2f8d2cb9f35bdbc90eecd5c731cc0e6216f5e8f14e7d1e076dafb344a + url: "https://pub.dev" + source: hosted + version: "2.1.0" + encrypt: + dependency: "direct main" + description: + name: encrypt + sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" + url: "https://pub.dev" + source: hosted + version: "5.0.1" + equatable: + dependency: transitive + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "2e9324f719e90200dc7d3c4f5d2abc26052f9f2b995d3b6626c47a0dfe1c8192" + url: "https://pub.dev" + source: hosted + version: "2.15.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: b63e3be6c96ef5c33bdec1aab23c91eb00696f6452f0519401d640938c94cba2 + url: "https://pub.dev" + source: hosted + version: "4.8.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: "0fd5c4b228de29b55fac38aed0d9e42514b3d3bd47675de52bf7f8fccaf922fa" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + sha256: "8ac91d83a028eef050de770f1dc98421e215714d245f34de7b154d436676fbd0" + url: "https://pub.dev" + source: hosted + version: "14.6.5" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + sha256: b2995e3640efb646e9ebf0e2fa50dea84895f0746a31d7e3af0e5e009a533a1a + url: "https://pub.dev" + source: hosted + version: "4.5.4" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + sha256: "5d8446a28339124a2cb4f57a6ca454a3aca7d0c5c0cdfa5707afb192f7c830a7" + url: "https://pub.dev" + source: hosted + version: "3.5.4" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + sha256: "29da130cdef13f47e1798a66e99fd119e557c293b98be8ebaf6fed2cbc43bf29" + url: "https://pub.dev" + source: hosted + version: "0.50.6" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_blurhash: + dependency: transitive + description: + name: flutter_blurhash + sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + url: "https://pub.dev" + source: hosted + version: "3.3.1" + flutter_client_sse: + dependency: "direct main" + description: + name: flutter_client_sse + sha256: "3a234480f529240401dc063a205a36ddce71b36e37f373e54ea6dd380e31bbbb" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_form_builder: + dependency: "direct main" + description: + name: flutter_form_builder + sha256: e828c11156d75fc668da1d8e7ddc2311ea8368f023fd28a7c7c126c8b903c5d6 + url: "https://pub.dev" + source: hosted + version: "9.1.0" + flutter_inappwebview: + dependency: "direct main" + description: + name: flutter_inappwebview + sha256: f73505c792cf083d5566e1a94002311be497d984b5607f25be36d685cf6361cf + url: "https://pub.dev" + source: hosted + version: "5.7.2+3" + flutter_launcher_icons: + dependency: "direct main" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" + source: hosted + version: "1.0.4" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_native_splash: + dependency: "direct main" + description: + name: flutter_native_splash + sha256: ecff62b3b893f2f665de7e4ad3de89f738941fcfcaaba8ee601e749efafa4698 + url: "https://pub.dev" + source: hosted + version: "2.3.2" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "6ff9fa12892ae074092de2fa6a9938fb21dbabfdaa2ff57dc697ff912fc8d4b2" + url: "https://pub.dev" + source: hosted + version: "1.1.6" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + form_builder_validators: + dependency: "direct main" + description: + name: form_builder_validators + sha256: e04998b1597d76a51da7f009ed3b2f12d4173f13e146e8744fd2453e8595a2c9 + url: "https://pub.dev" + source: hosted + version: "9.0.0" + geolocator: + dependency: "direct main" + description: + name: geolocator + sha256: "5c23f3613f50586c0bbb2b8f970240ae66b3bd992088cf60dd5ee2e6f7dde3a8" + url: "https://pub.dev" + source: hosted + version: "9.0.2" + geolocator_android: + dependency: transitive + description: + name: geolocator_android + sha256: "835ff5b4888a2f8eba128996494faf9c5d422785322a81dc0565b99e0f6c379d" + url: "https://pub.dev" + source: hosted + version: "4.2.2" + geolocator_apple: + dependency: transitive + description: + name: geolocator_apple + sha256: "36527c555f4c425f7d8fa8c7c07d67b78e3ff7590d40448051959e1860c1cfb4" + url: "https://pub.dev" + source: hosted + version: "2.2.7" + geolocator_platform_interface: + dependency: transitive + description: + name: geolocator_platform_interface + sha256: af4d69231452f9620718588f41acc4cb58312368716bfff2e92e770b46ce6386 + url: "https://pub.dev" + source: hosted + version: "4.0.7" + geolocator_web: + dependency: transitive + description: + name: geolocator_web + sha256: f68a122da48fcfff68bbc9846bb0b74ef651afe84a1b1f6ec20939de4d6860e1 + url: "https://pub.dev" + source: hosted + version: "2.1.6" + geolocator_windows: + dependency: transitive + description: + name: geolocator_windows + sha256: "242a35938cbe81dd169c9c72fc53e8183c4447bfa998b5df56b6725796591951" + url: "https://pub.dev" + source: hosted + version: "0.1.2" + get: + dependency: "direct main" + description: + name: get + sha256: "2ba20a47c8f1f233bed775ba2dd0d3ac97b4cf32fc17731b3dfc672b06b0e92a" + url: "https://pub.dev" + source: hosted + version: "4.6.5" + get_storage: + dependency: "direct main" + description: + name: get_storage + sha256: "39db1fffe779d0c22b3a744376e86febe4ade43bf65e06eab5af707dc84185a2" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + html: + dependency: transitive + description: + name: html + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" + source: hosted + version: "0.15.4" + http: + dependency: "direct main" + description: + name: http + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" + source: hosted + version: "0.13.5" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf + url: "https://pub.dev" + source: hosted + version: "4.0.17" + internet_connection_checker: + dependency: "direct main" + description: + name: internet_connection_checker + sha256: "1c683e63e89c9ac66a40748b1b20889fd9804980da732bf2b58d6d5456c8e876" + url: "https://pub.dev" + source: hosted + version: "1.0.0+1" + intl: + dependency: "direct main" + description: + name: intl + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 + url: "https://pub.dev" + source: hosted + version: "0.18.0" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + jwt_decoder: + dependency: "direct main" + description: + name: jwt_decoder + sha256: "54774aebf83f2923b99e6416b4ea915d47af3bde56884eb622de85feabbc559f" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" + source: hosted + version: "1.0.1" + logger: + dependency: "direct main" + description: + name: logger + sha256: "7ad7215c15420a102ec687bb320a7312afd449bac63bfb1c60d9787c27b9767f" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + lottie: + dependency: "direct main" + description: + name: lottie + sha256: "893da7a0022ec2fcaa616f34529a081f617e86cc501105b856e5a3184c58c7c2" + url: "https://pub.dev" + source: hosted + version: "1.4.3" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + overlay_support: + dependency: "direct main" + description: + name: overlay_support + sha256: fc39389bfd94e6985e1e13b2a88a125fc4027608485d2d4e2847afe1b2bb339c + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + path_drawing: + dependency: transitive + description: + name: path_drawing + sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + url: "https://pub.dev" + source: hosted + version: "2.0.15" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" + url: "https://pub.dev" + source: hosted + version: "2.0.27" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" + url: "https://pub.dev" + source: hosted + version: "2.2.4" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 + url: "https://pub.dev" + source: hosted + version: "2.1.11" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + url: "https://pub.dev" + source: hosted + version: "2.0.6" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" + url: "https://pub.dev" + source: hosted + version: "2.1.7" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" + source: hosted + version: "5.4.0" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" + source: hosted + version: "3.7.3" + responsive_framework: + dependency: "direct main" + description: + name: responsive_framework + sha256: eacaec7792360711b063ff349794cfdcf567be5e3329f682fabcbe7d4975d263 + url: "https://pub.dev" + source: hosted + version: "0.1.7" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" + source: hosted + version: "0.27.7" + shimmer: + dependency: "direct main" + description: + name: shimmer + sha256: "1f1009b5845a1f88f1c5630212279540486f97409e9fc3f63883e71070d107bf" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + syncfusion_flutter_charts: + dependency: "direct main" + description: + name: syncfusion_flutter_charts + sha256: "0222ac9d8cb6c671f014effe9bd5c0aef35eadb16471355345ba87cc0ac007b3" + url: "https://pub.dev" + source: hosted + version: "20.4.54" + syncfusion_flutter_core: + dependency: transitive + description: + name: syncfusion_flutter_core + sha256: "3979f0b1c5a97422cadae52d476c21fa3e0fb671ef51de6cae1d646d8b99fe1f" + url: "https://pub.dev" + source: hosted + version: "20.4.54" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" + source: hosted + version: "0.5.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e" + url: "https://pub.dev" + source: hosted + version: "6.1.12" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "78cb6dea3e93148615109e58e42c35d1ffbf5ef66c44add673d0ab75f12ff3af" + url: "https://pub.dev" + source: hosted + version: "6.0.37" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea + url: "https://pub.dev" + source: hosted + version: "2.1.3" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4 + url: "https://pub.dev" + source: hosted + version: "2.0.18" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422" + url: "https://pub.dev" + source: hosted + version: "3.0.7" + uuid: + dependency: "direct main" + description: + name: uuid + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" + source: hosted + version: "3.0.7" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + win32: + dependency: transitive + description: + name: win32 + sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + url: "https://pub.dev" + source: hosted + version: "4.1.4" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff + url: "https://pub.dev" + source: hosted + version: "1.0.1" + xml: + dependency: transitive + description: + name: xml + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.0.3 <4.0.0" + flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..9ab7336 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,274 @@ +name: IQ +version: 1.0.0+1 +publish_to: none +description: A new Flutter project. +environment: + sdk: ">=3.0.3 <4.0.0" + +dependencies: + cached_network_image: ^3.2.3 + carousel_slider: ^4.2.1 + change_app_package_name: ^1.1.0 + crypto: ^3.0.1 + cupertino_icons: ^1.0.2 + double_back_to_close_app: ^2.1.0 + encrypt: ^5.0.1 + firebase_core: ^2.3.0 + firebase_messaging: ^14.1.2 + fl_chart: ^0.50.1 + flutter: + sdk: flutter + flutter_client_sse: ^1.0.0 + flutter_form_builder: ^9.1.0 + flutter_inappwebview: ^5.7.2 + flutter_launcher_icons: ^0.13.1 + flutter_native_splash: ^2.3.2 + flutter_svg: ^1.0.3 + form_builder_validators: ^9.0.0 + geolocator: ^9.0.2 + get: ^4.6.5 + get_storage: ^2.0.3 + http: ^0.13.4 + internet_connection_checker: ^1.0.0+1 + intl: ^0.18.0 + jwt_decoder: ^2.0.1 + logger: ^1.4.0 + lottie: ^1.2.2 + overlay_support: ^2.1.0 + responsive_framework: 0.1.7 + shimmer: ^2.0.0 + syncfusion_flutter_charts: ^20.2.46 + url_launcher: ^6.1.12 + uuid: ^3.0.6 +dev_dependencies: + change_app_package_name: ^1.1.0 + flutter_lints: ^1.0.0 + flutter_test: + sdk: flutter + +flutter: + generate: true + uses-material-design: true + fonts: + - family: DefaultFont + fonts: + - asset: fonts/ReadexPro/ReadexPro-Bold.ttf + weight: 700 + - asset: fonts/ReadexPro/ReadexPro-ExtraLight.ttf + weight: 200 + - asset: fonts/ReadexPro/ReadexPro-Light.ttf + weight: 300 + - asset: fonts/ReadexPro/ReadexPro-Medium.ttf + weight: 500 + - asset: fonts/ReadexPro/ReadexPro-Regular.ttf + weight: 400 + - asset: fonts/ReadexPro/ReadexPro-SemiBold.ttf + + - family: MarkaziText + fonts: + - asset: fonts/MarkaziText/MarkaziText-Bold.ttf + weight: 700 + - asset: fonts/MarkaziText/MarkaziText-Medium.ttf + weight: 500 + - asset: fonts/MarkaziText/MarkaziText-Regular.ttf + weight: 400 + - asset: fonts/MarkaziText/MarkaziText-SemiBold.ttf + weight: 600 + - family: Roboto + fonts: + - asset: fonts/Roboto/Roboto-BlackItalic.ttf + weight: 900 + - asset: fonts/Roboto/Roboto-Black.ttf + weight: 900 + - asset: fonts/Roboto/Roboto-BoldItalic.ttf + weight: 700 + - asset: fonts/Roboto/Roboto-Bold.ttf + weight: 700 + - asset: fonts/Roboto/Roboto-Medium.ttf + weight: 500 + - asset: fonts/Roboto/Roboto-Regular.ttf + weight: 400 + - asset: fonts/Roboto/Roboto-ThinItalic.ttf + weight: 100 + - asset: fonts/Roboto/Roboto-Thin.ttf + weight: 100 + - asset: fonts/Roboto/Roboto-Italic.ttf + weight: 400 + - asset: fonts/Roboto/Roboto-LightItalic.ttf + weight: 300 + - asset: fonts/Roboto/Roboto-Light.ttf + weight: 300 + - asset: fonts/Roboto/Roboto-MediumItalic.ttf + weight: 500 + - family: Inter + fonts: + - asset: fonts/Inter/Inter-Black.ttf + weight: 900 + - asset: fonts/Inter/Inter-Bold.ttf + weight: 700 + - asset: fonts/Inter/Inter-ExtraBold.ttf + weight: 800 + - asset: fonts/Inter/Inter-Regular.ttf + weight: 400 + - asset: fonts/Inter/Inter-SemiBold.ttf + weight: 600 + - asset: fonts/Inter/Inter-Thin.ttf + weight: 100 + - asset: fonts/Inter/Inter-ExtraLight.ttf + weight: 200 + - asset: fonts/Inter/Inter-Light.ttf + weight: 300 + - asset: fonts/Inter/Inter-Medium.ttf + weight: 500 + - family: ReadexPro + fonts: + - asset: fonts/ReadexPro/ReadexPro-Bold.ttf + weight: 700 + - asset: fonts/ReadexPro/ReadexPro-ExtraLight.ttf + weight: 200 + - asset: fonts/ReadexPro/ReadexPro-Light.ttf + weight: 300 + - asset: fonts/ReadexPro/ReadexPro-Medium.ttf + weight: 500 + - asset: fonts/ReadexPro/ReadexPro-Regular.ttf + weight: 400 + - asset: fonts/ReadexPro/ReadexPro-SemiBold.ttf + assets: + - assets/ + - assets/drawer icons/ + - assets/home_icons/ + - assets/1/ + - assets/2/ + - assets/app_icon/ + +flutter_icons: + android: "launcher_icon" + ios: true + remove_alpha_ios: true + image_path: "assets/app_icon/1.png" + adaptive_icon_background: "#7D7D7D" + +flutter_native_splash: + # This package generates native code to customize Flutter's default white native splash screen + # with background color and splash image. + # Customize the parameters below, and run the following command in the terminal: + # dart run flutter_native_splash:create + # To restore Flutter's default white splash screen, run the following command in the terminal: + # dart run flutter_native_splash:remove + # color or background_image is the only required parameter. Use color to set the background + # of your splash screen to a solid color. Use background_image to set the background of your + # splash screen to a png image. This is useful for gradients. The image will be stretch to the + # size of the app. Only one parameter can be used, color and background_image cannot both be set. + color: "#533191" + # background_image: "assets/2/icon.png" + # Optional parameters are listed below. To enable a parameter, uncomment the line by removing + # the leading # character. + # The image parameter allows you to specify an image used in the splash screen. It must be a + # png file and should be sized for 4x pixel density. + image: assets/2/icon.png + + # The branding property allows you to specify an image used as branding in the splash screen. + # It must be a png file. It is supported for Android, iOS and the Web. For Android 12, + # see the Android 12 section below. + # branding: assets/2/icon.png + # To position the branding image at the bottom of the screen you can use bottom, bottomRight, + # and bottomLeft. The default values is bottom if not specified or specified something else. + # branding_mode: center + # The color_dark, background_image_dark, image_dark, branding_dark are parameters that set the background + # and image when the device is in dark mode. If they are not specified, the app will use the + # parameters from above. If the image_dark parameter is specified, color_dark or + # background_image_dark must be specified. color_dark and background_image_dark cannot both be + # set. + #color_dark: "#042a49" + #background_image_dark: "assets/dark-background.png" + #image_dark: assets/splash-invert.png + #branding_dark: assets/dart_dark.png + # Android 12 handles the splash screen differently than previous versions. Please visit + # https://developer.android.com/guide/topics/ui/splash-screen + # Following are Android 12 specific parameter. + android_12: + # The image parameter sets the splash screen icon image. If this parameter is not specified, + # the app's launcher icon will be used instead. + # Please note that the splash screen will be clipped to a circle on the center of the screen. + # App icon with an icon background: This should be 960×960 pixels, and fit within a circle + # 640 pixels in diameter. + # App icon without an icon background: This should be 1152×1152 pixels, and fit within a circle + # 768 pixels in diameter. + image: assets/2/icon.png + + # Splash screen background color. + color: "#533191" + # App icon background color. + #icon_background_color: "#111111" + # The branding property allows you to specify an image used as branding in the splash screen. + # branding: assets/2/icon.png + # The image_dark, color_dark, icon_background_color_dark, and branding_dark set values that + # apply when the device is in dark mode. If they are not specified, the app will use the + # parameters from above. + #image_dark: assets/android12splash-invert.png + #color_dark: "#042a49" + #icon_background_color_dark: "#eeeeee" + + # The android, ios and web parameters can be used to disable generating a splash screen on a given + # platform. + android: true + ios: true + #web: false + # Platform specific images can be specified with the following parameters, which will override + # the respective parameter. You may specify all, selected, or none of these parameters: + #color_android: "#42a5f5" + #color_dark_android: "#042a49" + #color_ios: "#42a5f5" + #color_dark_ios: "#042a49" + #color_web: "#42a5f5" + #color_dark_web: "#042a49" + #image_android: assets/splash-android.png + #image_dark_android: assets/splash-invert-android.png + #image_ios: assets/splash-ios.png + #image_dark_ios: assets/splash-invert-ios.png + #image_web: assets/splash-web.gif + #image_dark_web: assets/splash-invert-web.gif + #background_image_android: "assets/background-android.png" + #background_image_dark_android: "assets/dark-background-android.png" + #background_image_ios: "assets/background-ios.png" + #background_image_dark_ios: "assets/dark-background-ios.png" + #background_image_web: "assets/background-web.png" + #background_image_dark_web: "assets/dark-background-web.png" + #branding_android: assets/brand-android.png + #branding_dark_android: assets/dart_dark-android.png + #branding_ios: assets/brand-ios.gif + #branding_dark_ios: assets/dart_dark-ios.gif + # The position of the splash image can be set with android_gravity, ios_content_mode, and + # web_image_mode parameters. All default to center. + # + # android_gravity can be one of the following Android Gravity (see + # https://developer.android.com/reference/android/view/Gravity): bottom, center, + # center_horizontal, center_vertical, clip_horizontal, clip_vertical, end, fill, fill_horizontal, + # fill_vertical, left, right, start, or top. + #android_gravity: center + # + # ios_content_mode can be one of the following iOS UIView.ContentMode (see + # https://developer.apple.com/documentation/uikit/uiview/contentmode): scaleToFill, + # scaleAspectFit, scaleAspectFill, center, top, bottom, left, right, topLeft, topRight, + # bottomLeft, or bottomRight. + #ios_content_mode: center + # + # web_image_mode can be one of the following modes: center, contain, stretch, and cover. + #web_image_mode: center + # The screen orientation can be set in Android with the android_screen_orientation parameter. + # Valid parameters can be found here: + # https://developer.android.com/guide/topics/manifest/activity-element#screen + #android_screen_orientation: sensorLandscape + # To hide the notification bar, use the fullscreen parameter. Has no effect in web since web + # has no notification bar. Defaults to false. + # NOTE: Unlike Android, iOS will not automatically show the notification bar when the app loads. + # To show the notification bar, add the following code to your Flutter app: + # WidgetsFlutterBinding.ensureInitialized(); + # SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.bottom, SystemUiOverlay.top], ); + fullscreen: true + # If you have changed the name(s) of your info.plist file(s), you can specify the filename(s) + # with the info_plist_files parameter. Remove only the # characters in the three lines below, + # do not remove any spaces: + #info_plist_files: + # - 'ios/Runner/Info-Debug.plist' + # - 'ios/Runner/Info-Release.plist' diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..e69de29 diff --git a/upload-keystore.jks b/upload-keystore.jks new file mode 100644 index 0000000..d17f67d Binary files /dev/null and b/upload-keystore.jks differ diff --git a/user.json b/user.json new file mode 100644 index 0000000..608de26 --- /dev/null +++ b/user.json @@ -0,0 +1,82 @@ +[ + { + "status": 200, + "data": { + "username": "96418310200", + "firstname": "حسنين نوفل محمد علي", + "lastname": "29A84A", + "name": "حسنين نوفل محمد علي 29A84A", + "email": null, + "phone": "07713227826", + "address": "712-25-8", + "company": null, + "registered_on": { + "date": "2022-02-03 11:30:04.000000", + "timezone_type": 3, + "timezone": "Asia/Baghdad" + }, + "id": 3572, + "static_ip": null, + "balance": 0, + "auto_renew": 0, + "profile_id": 3, + "contract_id": "RC42/13@712-25-8", + "loan_balance": 0 + }, + "permissions": [ + "prm_ucp_auto_login", + "prm_ucp_activate", + "prm_ucp_billing", + "prm_ucp_browse_packages", + "prm_ucp_change_info", + "prm_ucp_change_profile", + "prm_ucp_data_usage", + "prm_ucp_login", + "prm_ucp_sessions", + "prm_ucp_support", + "prm_ucp_extend", + "prm_ucp_auto_renew", + "prm_ucp_docs_show", + "prm_ucp_docs_upload" + ] + }, + { + "status": 200, + "data": { + "remaining_days": 26, + "remaining_traffic": "_", + "remaining_uptime": "_", + "balance": "0.00", + "unpaid_invoices": 0, + "loan": { + "rx_mb": null, + "tx_mb": null, + "rxtx_mb": null, + "days": null + } + } + }, + { + "status": 200, + "data": { + "profile_name": "Storm", + "description": null, + "expiration": "2022-05-10 12:00:00", + "profile_id": 3, + "status": true, + "price": 55000, + "subscription_status": { + "status": true, + "traffic": true, + "expiration": true, + "uptime": true + }, + "limits": { + "rx_bytes": null, + "tx_bytes": null, + "rxtx_bytes": null, + "uptime_seconds": null + } + } + } +] \ No newline at end of file diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/web/icons/Icon-512.png differ diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/web/icons/Icon-maskable-192.png differ diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/web/icons/Icon-maskable-512.png differ diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..4508116 --- /dev/null +++ b/web/index.html @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + sas4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..6a47b34 --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "sas4", + "short_name": "sas4", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/web/splash/img/dark-1x.png b/web/splash/img/dark-1x.png new file mode 100644 index 0000000..f7925a2 Binary files /dev/null and b/web/splash/img/dark-1x.png differ diff --git a/web/splash/img/dark-2x.png b/web/splash/img/dark-2x.png new file mode 100644 index 0000000..240e8b5 Binary files /dev/null and b/web/splash/img/dark-2x.png differ diff --git a/web/splash/img/dark-3x.png b/web/splash/img/dark-3x.png new file mode 100644 index 0000000..f806779 Binary files /dev/null and b/web/splash/img/dark-3x.png differ diff --git a/web/splash/img/dark-4x.png b/web/splash/img/dark-4x.png new file mode 100644 index 0000000..4ecf2c8 Binary files /dev/null and b/web/splash/img/dark-4x.png differ diff --git a/web/splash/img/light-1x.png b/web/splash/img/light-1x.png new file mode 100644 index 0000000..f7925a2 Binary files /dev/null and b/web/splash/img/light-1x.png differ diff --git a/web/splash/img/light-2x.png b/web/splash/img/light-2x.png new file mode 100644 index 0000000..240e8b5 Binary files /dev/null and b/web/splash/img/light-2x.png differ diff --git a/web/splash/img/light-3x.png b/web/splash/img/light-3x.png new file mode 100644 index 0000000..f806779 Binary files /dev/null and b/web/splash/img/light-3x.png differ diff --git a/web/splash/img/light-4x.png b/web/splash/img/light-4x.png new file mode 100644 index 0000000..4ecf2c8 Binary files /dev/null and b/web/splash/img/light-4x.png differ diff --git a/windows/.gitignore b/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt new file mode 100644 index 0000000..f7c5bf5 --- /dev/null +++ b/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.14) +project(sas4 LANGUAGES CXX) + +set(BINARY_NAME "sas4") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..245cf6d --- /dev/null +++ b/windows/flutter/CMakeLists.txt @@ -0,0 +1,102 @@ +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..16039c1 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,20 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + FirebaseCorePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); + GeolocatorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("GeolocatorWindows")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..e30096f --- /dev/null +++ b/windows/flutter/generated_plugins.cmake @@ -0,0 +1,26 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + firebase_core + geolocator_windows + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..de2d891 --- /dev/null +++ b/windows/runner/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc new file mode 100644 index 0000000..8fffd1b --- /dev/null +++ b/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "sas4" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "sas4" "\0" + VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "sas4.exe" "\0" + VALUE "ProductName", "sas4" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..b43b909 --- /dev/null +++ b/windows/runner/flutter_window.cpp @@ -0,0 +1,61 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h new file mode 100644 index 0000000..6da0652 --- /dev/null +++ b/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp new file mode 100644 index 0000000..76e5e35 --- /dev/null +++ b/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"sas4", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/windows/runner/resource.h b/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000..c04e20c Binary files /dev/null and b/windows/runner/resources/app_icon.ico differ diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..c977c4a --- /dev/null +++ b/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp new file mode 100644 index 0000000..d19bdbb --- /dev/null +++ b/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/windows/runner/utils.h b/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp new file mode 100644 index 0000000..c10f08d --- /dev/null +++ b/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h new file mode 100644 index 0000000..17ba431 --- /dev/null +++ b/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_