diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa2fc39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,47 @@ +# 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 +.DS_Store diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..56bfc2c --- /dev/null +++ b/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: f4abaa0735eba4dfd8f33f73363911d63931fe03 + channel: stable + +project_type: app diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8752a9f --- /dev/null +++ b/LICENSE @@ -0,0 +1,17 @@ + Copyright 2023 Technische Universität Berlin + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this software except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +This product bundles the TRAPEZE Identity Kit, which is available under an +"MIT" license. For details, see assets/LICENSE. \ No newline at end of file diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..eeb81fa --- /dev/null +++ b/NOTICE @@ -0,0 +1,8 @@ +TRAPEZE-MOBILE +Copyright 2023 Technische Universität Berlin + +This product includes software developed at +Technische Universtität Berlin (https://tu.berlin/). + +The visual assets of the TRAPEZE Identity Kit +in assets/ic_launcher and assets/images were created by Tenforce. (https://www.tenforce.com/) diff --git a/README.md b/README.md new file mode 100644 index 0000000..3255ccc --- /dev/null +++ b/README.md @@ -0,0 +1,139 @@ +# TRAPEZE Mobile Application +Contributors: K. Pelz, P.Pathak, I.Lehrer, N.Shawarba, T.Eichinger, P.Raschke + +![Screenshots](https://github.com/trapeze-project/trapeze-mobile.git/blob/main/screenshots/put-all-screenshots-together.png?raw=true) + +This is the code repository for the TRAPEZE Mobile Application for Android phones. +The TRAPEZE Mobile Application is built on the basis of the [Flutter UI Framework](https://flutter.dev) developed by Google. +It provides a user interface for a mobile application that performs malware detection scans and, in case a malware was detected, provides further information on (1) how to resolve the security issue and (2) how to avoid the security issue it in the future. + +By default, the TRAPEZE Mobile Application makes use of the [Kaspersky Mobile Security SDK](https://www.kaspersky.com/mobile-security-sdk) by the Kaspersky Cyber-Security Company that implements malware detection scans. + +This ```trapeze-mobile``` repository DOES NOT contain any malware detection business logic. +The business logic for malware detection for use with the TRAPEZE Mobile Application is available in a separate repository called ```kaspersky_sdk``` available [here](https://github.com/trapeze-project/kaspersky_sdk). The ```kaspersky_sdk``` repository implements a [Flutter Plugin Package](https://docs.flutter.dev/packages-and-plugins/developing-packages#types). +Using malware detection scans provided by the Kaspersky Mobile Security SDK requires adding .aar files that contain their business logic to the ```kaspersky_sdk``` and also a *license key* from Kaspersky. + +A release version of the TRAPEZE Mobile Application can be downloaded [here](tbd). + +## 1. Clone the Code + +Clone the code respository for the TRAPEZE Mobile Application and the code repository for the Flutter package that holds the business logic for the malware detection scans. + +```sh +git clone https://github.com/trapeze-project/trapeze-mobile.git +git clone https://github.com/trapeze-project/kaspersky_sdk.git +``` + +The TRAPEZE Mobile Application assumes that both repositories are located in the same directory. + +```sh +./ + |-- /kaspersky_sdk --> code repository of the KMS-SDK Flutter Plugin Package + |-- /trapeze-mobile --> main code repository +``` + +If you wish to use another folder structure, you need to specify the path to the ```kaspersky_sdk``` repository in the ```pubspec.yaml``` file in the ```trapeze-mobile``` repository. + + +## 2. Install Dependencies + +### 2.1 Install Flutter and Dart command-line programs + +Download the latest stable release version of Flutter command-line program by following the official [installation steps](https://docs.flutter.dev/get-started/install). We verified the code to work for the following Flutter version: + +```sh +>> flutter --version +Flutter 3.0.0 • channel stable • https://github.com/flutter/flutter.git +Framework • revision ee4e09cce0 (7 days ago) • 2022-05-09 16:45:18 -0700 +Engine • revision d1b9a6938a +Tools • Dart 2.17.0 • DevTools 2.12.2 +``` + +> Note that the installation of the Flutter command-line program includes the installation of the Dart command-line program. + +### 2.2 Install an IDE + +
IDE Installation Details + +We present installations of two popular IDEs for the development of the TRAPEZE-mobile application. + +#### 2.2.1 Android Studio + +Download the Android Studio IDE following these [installation instructions](https://developer.android.com/studio?hl=de&gclid=CjwKCAjwj42UBhAAEiwACIhADk7rYnzdjIAXFR_vOgtWB1K62yQZFkn2xq1wzcm5KfY0p2PltBpJKhoCwn0QAvD_BwE&gclsrc=aw.ds). We have verified that the project builds correctly under the following release of Android Studio, Flutter, Dart, and Kotlin plugins: + +``` +Android Studio Chipmunk | 2021.2.1 +Build #AI-212.5712.43.2112.8512546, built on April 28, 2022 +Runtime version: 11.0.12+0-b1504.28-7817840 x86_64 +VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. +Non-Bundled Plugins: Dart (212.5744), org.jetbrains.kotlin (212-1.6.21-release-334-AS5457.46), io.flutter (67.1.2) +``` + +> Install Flutter, Dart, and Kotlin plugins by double tapping \[Shift\] and typing 'Plugin' into the search bar to navigate to the Plugin-manager. + +You may also need to configure the integrated Android SDK. You can install for instance the **Android SDK command-line Tools** and **Android SDK Build-Tools** via the SDK Manager. + +> Install Android SDK command-line tools and Build-tools by double tapping \[Shift\] and typing 'SDK Manager' into the search bar to navigate to the SDK Manager. + + +#### 2.2.2 Visual Studio Code + +Download the Visual Studio Code IDE following these [installation instructions](https://code.visualstudio.com/). We have verified that the project builds correctly under the following release of Android Studio, Flutter, Dart, and Kotlin plugins: + +``` +Visual Studio Code | Version: 1.67.1 +Commit: da15b6fd3ef856477bf6f4fb29ba1b7af717770d +Date: 2022-05-06T12:37:16.526Z +``` + +> Install Kotlin, Dart, and Flutter extensions by clicking on the Extensions icon in the left menu, or clicking on the Settings icon (gear) in the bottom left and then select 'Extensions'. + +
+ + +## 3. Run the App and Build an APK + +### 3.1 Run and build the TRAPEZE-mobile application + +> CAVEAT Running the TRAPEZE Mobile Application will only run if it is run on an *Android device* (currently no support for iOS and Web). + +> CAVEAT Malware detection scans will only work if the** *.aar files* from the Kaspersky Mobile Security SDK and a license key are added to the ```kaspersky_sdk``` repository as described in the README in the ```kaspersky_sdk``` repository. + +Run the TRAPEZE-mobile application by running the following commands + +1. [OPTIONAL] Clear dependencies +``` +flutter clean +``` + +2. Run the application +``` +flutter run -- +``` +where you can choose between 'debug' and 'release' modes. + +> Note that `flutter run` includes the execution of `flutter pub get` (install dependencies). + +### 3.2 Build an APK of the TRAPEZE-mobile application + +> CAVEAT Building .apk files of the TRAPEZE Mobile Application requires adding the Kaspersky Mobile Security SDK's .aar files and a license key to the ```kaspersky_sdk``` repository as described in the README in the ```kaspersky_sdk``` repository.* + +Build an APK (.apk) by running the following commands in the command-line at the root of the ```trapeze-mobile``` repository. + +1. [OPTIONAL] Clear dependencies +``` +flutter clean +``` + +2. Build APK +``` +flutter build apk -- +``` +where you can choose between 'debug' and 'release' modes. + +The compiled .apk files can be found here: `./build/app/outputs/flutter-apk/app-.apk`. + + +## Contact + +Please do not hesitate to direct your questions to tobias.eichinger (AT) tu-berlin.de and philip.raschke (AT) tu-berlin.de. diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..0a741cb --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,11 @@ +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 diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..603ef34 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,58 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 31 + 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 "de.tub.snet.flutternativetrapeze" + minSdkVersion 24 + targetSdkVersion 30 // = Android 11 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..a29e9e2 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/debug/gen/de/tub/snet/flutternativetrapeze/BuildConfig.java b/android/app/src/debug/gen/de/tub/snet/flutternativetrapeze/BuildConfig.java new file mode 100644 index 0000000..39f0bc9 --- /dev/null +++ b/android/app/src/debug/gen/de/tub/snet/flutternativetrapeze/BuildConfig.java @@ -0,0 +1,8 @@ +/*___Generated_by_IDEA___*/ + +package de.tub.snet.flutternativetrapeze; + +/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */ +public final class BuildConfig { + public final static boolean DEBUG = Boolean.parseBoolean(null); +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9736f2d --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/de/tub/snet/flutternativetrapeze/MainActivity.kt b/android/app/src/main/kotlin/de/tub/snet/flutternativetrapeze/MainActivity.kt new file mode 100644 index 0000000..0b44635 --- /dev/null +++ b/android/app/src/main/kotlin/de/tub/snet/flutternativetrapeze/MainActivity.kt @@ -0,0 +1,6 @@ +package de.tub.snet.flutternativetrapeze + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} 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..79bbe67 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/splash.png b/android/app/src/main/res/drawable-mdpi/splash.png new file mode 100644 index 0000000..c06978b 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-v21/background.png b/android/app/src/main/res/drawable-v21/background.png new file mode 100644 index 0000000..d9d4997 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/splash.png b/android/app/src/main/res/drawable-xhdpi/splash.png new file mode 100644 index 0000000..16683fe 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/splash.png b/android/app/src/main/res/drawable-xxhdpi/splash.png new file mode 100644 index 0000000..9b14128 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/splash.png b/android/app/src/main/res/drawable-xxxhdpi/splash.png new file mode 100644 index 0000000..5ba9998 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..d9d4997 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..f8b56cd Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..99f1371 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..697c95c Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..05501e0 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..a651674 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..449a9f9 --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values-v31/styles.xml b/android/app/src/main/res/values-v31/styles.xml new file mode 100644 index 0000000..f5fdb6b --- /dev/null +++ b/android/app/src/main/res/values-v31/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..15a797a --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..47672bf --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/android/app/src/profile/gen/com/example/flutternativetrapeze/BuildConfig.java b/android/app/src/profile/gen/com/example/flutternativetrapeze/BuildConfig.java new file mode 100644 index 0000000..7342df2 --- /dev/null +++ b/android/app/src/profile/gen/com/example/flutternativetrapeze/BuildConfig.java @@ -0,0 +1,8 @@ +/*___Generated_by_IDEA___*/ + +package com.example.flutternativetrapeze; + +/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */ +public final class BuildConfig { + public final static boolean DEBUG = Boolean.parseBoolean(null); +} \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..1881064 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + ext.kotlin_version = '1.6.21' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" + project.evaluationDependsOn(':app') +} + +task clean(type: 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..bc6a58a --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-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/DataBanks/actionInfo.json b/assets/DataBanks/actionInfo.json new file mode 100644 index 0000000..b5bffee --- /dev/null +++ b/assets/DataBanks/actionInfo.json @@ -0,0 +1,66 @@ +{ + "ThreatResolutionAction.antivirus": { + "priority": 2, + "description": "Install an Anti-Virus app, e.g. TotalAV Antivirus & VPN for Android devices (https://play.google.com/store/apps/details?id=com.totalav.android)." + }, + "ThreatResolutionAction.backupData": { + "priority": 2, + "description": "Make periodic backups of your files." + }, + "ThreatResolutionAction.vpn": { + "priority": 2, + "description": "Use a VPN program." + }, + "ThreatResolutionAction.thirdpartyDownload": { + "priority": 2, + "description": "Do not download software from unknown sources. Only download apps that are downloaded from the Play Store (Android) or AppStore (iOS)." + }, + "ThreatResolutionAction.securitySoftware": { + "priority": 2, + "description": "Install cyber security software such as e.g. Kaspersky Security & VPN for Android devices (https://play.google.com/store/apps/details?id=com.kms.free)." + }, + "ThreatResolutionAction.updatePermission": { + "priority": 2, + "description": "Update your app permissions. It is recommendable to deactivate all permissions from time to time and re-activate only those that are necessary." + }, + "ThreatResolutionAction.avoidUnsecureWifi": { + "priority": 2, + "description": "Connecting to open WiFi networks such as at a café or an airport, these networks may or may not be secured. The WiFi host and even other users may observe your online behavior.\nIt is recommendable to only use unsecured WiFi networks if it is either absolutely necessary or you trust both the WiFi host and all participants in the network ." + }, + "ThreatResolutionAction.updatePhoneVersion": { + "priority": 2, + "description": "Update your phone's operating system. A major component of software updates are security updates." + }, + "ThreatResolutionAction.randomPassword": { + "priority": 2, + "description": "Use randomized passwords. In particular, do not use passwords that contain parts of your name, birthdate, or simple sequences like 'abc' or '123'." + }, + "ThreatResolutionAction.avoidLinks": { + "priority": 2, + "description": "Avoid clicking on links or buttons to navigate. Make sure that you know and trust the source that provides you the link or button that you click." + }, + "ThreatResolutionAction.uninstallApps": { + "priority": 2, + "description": "Uninstall apps that you seldom use. In the settings of your phone, you can browse how often and how long you use an app." + }, + "ThreatResolutionAction.googlePlayProtect": { + "priority": 2, + "description": "Do not deactivate GooglePlayProtect on Android phones. GooglePlayProtect is a software that scans apps and identifies malicious behavior.\nIt is by default activated in the Play Store app on Android devices." + }, + "ThreatResolutionAction.savedPassword": { + "priority": 2, + "description": "savedPassword i really dont know what to do" + }, + "ThreatResolutionAction.factoryReset": { + "priority": 2, + "description": "Perform a factory reset on your device. Do not forget to backup your data before the factory reset, especially your photos and video files." + }, + "ThreatResolutionAction.clearStorage": { + "priority": 2, + "description": "Clear your storage periodically. This includes browser cookies and the device cache." + }, + "ThreatResolutionAction.unknown": { + "priority": 4, + "description": "Turn off WiFi and remove your SIM card. Then find help online and/or at a local phone store to resolve the unknown threat. Re-scan your device after you have performed a resolution action." + } +} diff --git a/assets/DataBanks/exampleFetchResult.json b/assets/DataBanks/exampleFetchResult.json new file mode 100644 index 0000000..bf0fad2 --- /dev/null +++ b/assets/DataBanks/exampleFetchResult.json @@ -0,0 +1,20 @@ +[ + { + "@context": { + "@vocab": "https:\/\/trapeze-project.eu\/ns\/threat-info#", + "@language": "en" + }, + "category": "Unknown", + "description": "Unknown malicious code. The code is typically too new or too rare to be properly categorized as Adware, Spyware, password extraction software, or remote admin software.", + "actions": [ + { + "priority": "4", + "description": "Turn off WiFi and remove your SIM card. Then find help online and\/or at a local phone store to resolve the unknown threat. Re-scan your device after you have performed a resolution action." + }, + { + "priority": "2", + "description": "Install an Anti-Virus app, e.g. TotalAV Antivirus & VPN for Android devices (https:\/\/play.google.com\/store\/apps\/details?id=com.totalav.android)." + } + ] + } +] \ No newline at end of file diff --git a/assets/DataBanks/threatResolutionActions.json b/assets/DataBanks/threatResolutionActions.json new file mode 100644 index 0000000..6177c34 --- /dev/null +++ b/assets/DataBanks/threatResolutionActions.json @@ -0,0 +1,54 @@ +{ + "VerdictCategory.Adware": [ + "ThreatResolutionAction.antivirus", + "ThreatResolutionActions.thirdpartyDownload", + "ThreatResolutionAction.uninstallApps", + "ThreatResolutionAction.googlePlayProtect" + ], + "VerdictCategory.DestructiveMalware": [ + "ThreatResolutionAction.thirdpartyDownload", + "ThreatResolutionAction.securitySoftware", + "ThreatResolutionAction.updatePermission", + "ThreatResolutionAction.antivirus", + "ThreatResolutionAction.avoidUnsecureWifi", + "ThreatResolutionAction.avoidLinks", + "ThreatResolutionAction.uninstallApps", + "ThreatResolutionAction.googlePlayProtect", + "ThreatResolutionAction.savedPassword", + "ThreatResolutionAction.factoryReset", + "ThreatResolutionAction.clearStorage" + ], + "VerdictCategory.Monitor": [ + "ThreatResolutionAction.thirdpartyDownload", + "ThreatResolutionAction.securitySoftware", + "ThreatResolutionAction.updatePermission", + "ThreatResolutionAction.antivirus", + "ThreatResolutionAction.avoidUnsecureWifi", + "ThreatResolutionAction.avoidLinks", + "ThreatResolutionAction.uninstallApps", + "ThreatResolutionAction.googlePlayProtect", + "ThreatResolutionAction.savedPassword", + "ThreatResolutionAction.factoryReset" + ], + "VerdictCategory.PswTool":[ + "ThreatResolutionAction.updatePermission", + "ThreatResolutionAction.antivirus", + "ThreatResolutionAction.securitySoftware", + "ThreatResolutionAction.updatePhoneVersion", + "ThreatResolutionAction.avoidLinks", + "ThreatResolutionAction.savedPassword", + "ThreatResolutionAction.randomPassword" + ], + "VerdictCategory.RemoteAdmin": [ + "ThreatResolutionAction.avoidUnsecureWifi", + "ThreatResolutionAction.randomPassword", + "ThreatResolutionAction.updatePermission", + "ThreatResolutionAction.uninstallApps", + "ThreatResolutionAction.avoidLinks", + "ThreatResolutionAction.factoryReset" + ], + "VerdictCategory.Unknown": [ + "ThreatResolutionAction.unknown", + "ThreatResolutionAction.antivirus" + ] +} diff --git a/assets/DataBanks/verdictCategoryInfo.json b/assets/DataBanks/verdictCategoryInfo.json new file mode 100644 index 0000000..5893f37 --- /dev/null +++ b/assets/DataBanks/verdictCategoryInfo.json @@ -0,0 +1,20 @@ +{ + "VerdictCategory.Adware": { + "description": "Adware (advertisement software) is software that shows advertisement to a user. Advertisement is typically shown to generate revenue and is therefore often part of a software's business model. Some adware track user behavior to show personalized advertisement. Advertisement is presented to the user in boxes, banners, videos, pop-ups ad or even entire screens.\nAdware sometimes installs itself without the knowledge of the user." + }, + "VerdictCategory.DestructiveMalware": { + "description": "Malware (malicious software) is software that is intentionally designed to cause harm to a user. This harm includes system disruption, unauthorized system access, and information leakage. Software that causes such harm unintentionally is deficient and not considered malware.\nSpyware, ransomware, viruses, worms, rootkits, wiper, and scareware are examples of malware." + }, + "VerdictCategory.Monitor": { + "description": "Spyware, spying software, is software that extracts user information without the knowledge of the user. Spyware violates user privacy and/or security if information is extracted without the knowledge of the user.\nWeb trackers are a common example of spyware." + }, + "VerdictCategory.PswTool": { + "description": "Password extraction software is software that extracts user passwords. Password extraction software violates user privacy and/or security if passwords are extracted without the knowledge of the user.\nKeystroke logging is a common example of password extraction software." + }, + "VerdictCategory.RemoteAdmin": { + "description": "Remote admin software is software that establishes administrator access from another device. The other device is typically located in physical distance to the accessed device.\nAdministrator access yields unlimited rights to install or un-install programs, read and write files, and alter the system configuration on the accessed device. Remote admin software violates user privacy and/or security if remote access is established without the knowledge of the user. " + }, + "VerdictCategory.Unknown": { + "description": "Unknown malicious code. The code is typically too new or too rare to be properly categorized as Adware, Spyware, password extraction software, or remote admin software." + } +} diff --git a/assets/database.db b/assets/database.db new file mode 100644 index 0000000..e69de29 diff --git a/assets/ic_launcher/android/ic_launcher-web.png b/assets/ic_launcher/android/ic_launcher-web.png new file mode 100644 index 0000000..10ac190 Binary files /dev/null and b/assets/ic_launcher/android/ic_launcher-web.png differ diff --git a/assets/ic_launcher/android/mipmap-anydpi-v26/ic_launcher.xml b/assets/ic_launcher/android/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/assets/ic_launcher/android/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/assets/ic_launcher/android/mipmap-anydpi-v26/ic_launcher_round.xml b/assets/ic_launcher/android/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/assets/ic_launcher/android/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/assets/ic_launcher/android/mipmap-hdpi/ic_launcher.png b/assets/ic_launcher/android/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..b87ec5a Binary files /dev/null and b/assets/ic_launcher/android/mipmap-hdpi/ic_launcher.png differ diff --git a/assets/ic_launcher/android/mipmap-hdpi/ic_launcher_foreground.png b/assets/ic_launcher/android/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..e56c4a5 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/assets/ic_launcher/android/mipmap-hdpi/ic_launcher_round.png b/assets/ic_launcher/android/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..085eba8 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-hdpi/ic_launcher_round.png differ diff --git a/assets/ic_launcher/android/mipmap-ldpi/ic_launcher.png b/assets/ic_launcher/android/mipmap-ldpi/ic_launcher.png new file mode 100644 index 0000000..bec91c2 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-ldpi/ic_launcher.png differ diff --git a/assets/ic_launcher/android/mipmap-mdpi/ic_launcher.png b/assets/ic_launcher/android/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..a30b511 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-mdpi/ic_launcher.png differ diff --git a/assets/ic_launcher/android/mipmap-mdpi/ic_launcher_foreground.png b/assets/ic_launcher/android/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..2069944 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/assets/ic_launcher/android/mipmap-mdpi/ic_launcher_round.png b/assets/ic_launcher/android/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..91bb661 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-mdpi/ic_launcher_round.png differ diff --git a/assets/ic_launcher/android/mipmap-xhdpi/ic_launcher.png b/assets/ic_launcher/android/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..16dc229 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-xhdpi/ic_launcher.png differ diff --git a/assets/ic_launcher/android/mipmap-xhdpi/ic_launcher_foreground.png b/assets/ic_launcher/android/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..9ac8dea Binary files /dev/null and b/assets/ic_launcher/android/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/assets/ic_launcher/android/mipmap-xhdpi/ic_launcher_round.png b/assets/ic_launcher/android/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..162afab Binary files /dev/null and b/assets/ic_launcher/android/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/assets/ic_launcher/android/mipmap-xxhdpi/ic_launcher.png b/assets/ic_launcher/android/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..28f012e Binary files /dev/null and b/assets/ic_launcher/android/mipmap-xxhdpi/ic_launcher.png differ diff --git a/assets/ic_launcher/android/mipmap-xxhdpi/ic_launcher_foreground.png b/assets/ic_launcher/android/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..615abe3 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/assets/ic_launcher/android/mipmap-xxhdpi/ic_launcher_round.png b/assets/ic_launcher/android/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..2e199f7 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/assets/ic_launcher/android/mipmap-xxxhdpi/ic_launcher.png b/assets/ic_launcher/android/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..bcf44b8 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/assets/ic_launcher/android/mipmap-xxxhdpi/ic_launcher_foreground.png b/assets/ic_launcher/android/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..4c6ed60 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/assets/ic_launcher/android/mipmap-xxxhdpi/ic_launcher_round.png b/assets/ic_launcher/android/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..05c34f0 Binary files /dev/null and b/assets/ic_launcher/android/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/assets/ic_launcher/android/playstore-icon.png b/assets/ic_launcher/android/playstore-icon.png new file mode 100644 index 0000000..7fc08ff Binary files /dev/null and b/assets/ic_launcher/android/playstore-icon.png differ diff --git a/assets/ic_launcher/android/values/ic_launcher_background.xml b/assets/ic_launcher/android/values/ic_launcher_background.xml new file mode 100644 index 0000000..1415682 --- /dev/null +++ b/assets/ic_launcher/android/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #ebd314 + \ No newline at end of file diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Contents.json b/assets/ic_launcher/ios/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..e83c3bf --- /dev/null +++ b/assets/ic_launcher/ios/AppIcon.appiconset/Contents.json @@ -0,0 +1,128 @@ +{ + "images":[ + { + "idiom":"iphone", + "size":"20x20", + "scale":"2x", + "filename":"Icon-App-20x20@2x.png" + }, + { + "idiom":"iphone", + "size":"20x20", + "scale":"3x", + "filename":"Icon-App-20x20@3x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"1x", + "filename":"Icon-App-29x29@1x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"2x", + "filename":"Icon-App-29x29@2x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"3x", + "filename":"Icon-App-29x29@3x.png" + }, + { + "idiom":"iphone", + "size":"40x40", + "scale":"2x", + "filename":"Icon-App-40x40@2x.png" + }, + { + "idiom":"iphone", + "size":"40x40", + "scale":"3x", + "filename":"Icon-App-40x40@3x.png" + }, + { + "idiom":"iphone", + "size":"60x60", + "scale":"2x", + "filename":"Icon-App-60x60@2x.png" + }, + { + "idiom":"iphone", + "size":"60x60", + "scale":"3x", + "filename":"Icon-App-60x60@3x.png" + }, + { + "idiom":"iphone", + "size":"76x76", + "scale":"2x", + "filename":"Icon-App-76x76@2x.png" + }, + { + "idiom":"ipad", + "size":"20x20", + "scale":"1x", + "filename":"Icon-App-20x20@1x.png" + }, + { + "idiom":"ipad", + "size":"20x20", + "scale":"2x", + "filename":"Icon-App-20x20@2x.png" + }, + { + "idiom":"ipad", + "size":"29x29", + "scale":"1x", + "filename":"Icon-App-29x29@1x.png" + }, + { + "idiom":"ipad", + "size":"29x29", + "scale":"2x", + "filename":"Icon-App-29x29@2x.png" + }, + { + "idiom":"ipad", + "size":"40x40", + "scale":"1x", + "filename":"Icon-App-40x40@1x.png" + }, + { + "idiom":"ipad", + "size":"40x40", + "scale":"2x", + "filename":"Icon-App-40x40@2x.png" + }, + { + "idiom":"ipad", + "size":"76x76", + "scale":"1x", + "filename":"Icon-App-76x76@1x.png" + }, + { + "idiom":"ipad", + "size":"76x76", + "scale":"2x", + "filename":"Icon-App-76x76@2x.png" + }, + { + "idiom":"ipad", + "size":"83.5x83.5", + "scale":"2x", + "filename":"Icon-App-83.5x83.5@2x.png" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "scale" : "1x", + "filename" : "ItunesArtwork@2x.png" + } + ], + "info":{ + "version":1, + "author":"easyappicon" + } +} diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-20x20@1x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..b634c21 Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-20x20@2x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..a4c5588 Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-20x20@3x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..0f27cf5 Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-29x29@1x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..0882439 Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-29x29@2x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..7c560b8 Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-29x29@3x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..1d91fa8 Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-40x40@1x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..a4c5588 Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-40x40@2x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..9460cb2 Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-40x40@3x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..2608edb Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-60x60@2x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..2608edb Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-60x60@3x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..c6c2d70 Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-76x76@1x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..80c41dd Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-76x76@2x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..82fbcde Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..5e5385c Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/assets/ic_launcher/ios/AppIcon.appiconset/ItunesArtwork@2x.png b/assets/ic_launcher/ios/AppIcon.appiconset/ItunesArtwork@2x.png new file mode 100644 index 0000000..74bb761 Binary files /dev/null and b/assets/ic_launcher/ios/AppIcon.appiconset/ItunesArtwork@2x.png differ diff --git a/assets/ic_launcher/ios/iTunesArtwork@1x.png b/assets/ic_launcher/ios/iTunesArtwork@1x.png new file mode 100644 index 0000000..7fc08ff Binary files /dev/null and b/assets/ic_launcher/ios/iTunesArtwork@1x.png differ diff --git a/assets/ic_launcher/ios/iTunesArtwork@2x.png b/assets/ic_launcher/ios/iTunesArtwork@2x.png new file mode 100644 index 0000000..74bb761 Binary files /dev/null and b/assets/ic_launcher/ios/iTunesArtwork@2x.png differ diff --git a/assets/ic_launcher/ios/iTunesArtwork@3x.png b/assets/ic_launcher/ios/iTunesArtwork@3x.png new file mode 100644 index 0000000..5b8ea36 Binary files /dev/null and b/assets/ic_launcher/ios/iTunesArtwork@3x.png differ diff --git a/assets/images/trapeze_banner_bw_rgb.png b/assets/images/trapeze_banner_bw_rgb.png new file mode 100644 index 0000000..bab2215 Binary files /dev/null and b/assets/images/trapeze_banner_bw_rgb.png differ diff --git a/assets/images/trapeze_banner_clear_background.png b/assets/images/trapeze_banner_clear_background.png new file mode 100644 index 0000000..f719db5 Binary files /dev/null and b/assets/images/trapeze_banner_clear_background.png differ diff --git a/assets/images/trapeze_banner_default_rgb.png b/assets/images/trapeze_banner_default_rgb.png new file mode 100644 index 0000000..315a2ee Binary files /dev/null and b/assets/images/trapeze_banner_default_rgb.png differ diff --git a/assets/images/trapeze_banner_invert_rgb.png b/assets/images/trapeze_banner_invert_rgb.png new file mode 100644 index 0000000..97ca8f2 Binary files /dev/null and b/assets/images/trapeze_banner_invert_rgb.png differ diff --git a/buildWLauncher.sh b/buildWLauncher.sh new file mode 100755 index 0000000..8fee3bb --- /dev/null +++ b/buildWLauncher.sh @@ -0,0 +1,3 @@ +#! /bin/sh +flutter pub pub run flutter_launcher_icons:main +flutter run \ No newline at end of file diff --git a/doc/api/__404error.html b/doc/api/__404error.html new file mode 100644 index 0000000..56c5cb5 --- /dev/null +++ b/doc/api/__404error.html @@ -0,0 +1,103 @@ + + + + + + + + + flutternativetrapeze - Dart API docs + + + + + + + + + + + + + + + + + +
+ +
+ + +
flutternativetrapeze
+ +
+ +
+ + +
+

404: Something's gone wrong :-(

+ +
+

You've tried to visit a page that doesn't exist. Luckily this site + has other pages.

+

If you were looking for something specific, try searching: +

+

+ +
+
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/categories.json b/doc/api/categories.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/doc/api/categories.json @@ -0,0 +1 @@ +[] diff --git a/doc/api/index.html b/doc/api/index.html new file mode 100644 index 0000000..70f13c3 --- /dev/null +++ b/doc/api/index.html @@ -0,0 +1,110 @@ + + + + + + + + + flutternativetrapeze - Dart API docs + + + + + + + + + + + + + + + + + +
+ +
+ + +
flutternativetrapeze
+ +
+ +
+ + +
+ +
+

FlutterNativeTrapeze

+
+ + +
+

Libraries

+
+
+ main + +
+
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/index.json b/doc/api/index.json new file mode 100644 index 0000000..309f4a0 --- /dev/null +++ b/doc/api/index.json @@ -0,0 +1 @@ +[{"name":"main","qualifiedName":"main","href":"main/main-library.html","type":"library","overriddenDepth":0,"packageName":"flutternativetrapeze"},{"name":"AbstractBloc","qualifiedName":"main.AbstractBloc","href":"main/AbstractBloc-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"AbstractBloc","qualifiedName":"main.AbstractBloc.AbstractBloc","href":"main/AbstractBloc/AbstractBloc.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"AbstractBloc","type":"class"}},{"name":"bloc","qualifiedName":"main.AbstractBloc.bloc","href":"main/AbstractBloc/bloc.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"AbstractBloc","type":"class"}},{"name":"dispose","qualifiedName":"main.AbstractBloc.dispose","href":"main/AbstractBloc/dispose.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"AbstractBloc","type":"class"}},{"name":"handler","qualifiedName":"main.AbstractBloc.handler","href":"main/AbstractBloc/handler.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"AbstractBloc","type":"class"}},{"name":"publisher","qualifiedName":"main.AbstractBloc.publisher","href":"main/AbstractBloc/publisher.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"AbstractBloc","type":"class"}},{"name":"App","qualifiedName":"main.App","href":"main/App-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"App","qualifiedName":"main.App.App","href":"main/App/App.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"App","type":"class"}},{"name":"build","qualifiedName":"main.App.build","href":"main/App/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"App","type":"class"}},{"name":"CardDisplay","qualifiedName":"main.CardDisplay","href":"main/CardDisplay-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"CardDisplay","qualifiedName":"main.CardDisplay.CardDisplay","href":"main/CardDisplay/CardDisplay.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"CardDisplay","type":"class"}},{"name":"build","qualifiedName":"main.CardDisplay.build","href":"main/CardDisplay/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"CardDisplay","type":"class"}},{"name":"child","qualifiedName":"main.CardDisplay.child","href":"main/CardDisplay/child.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"CardDisplay","type":"class"}},{"name":"elevation","qualifiedName":"main.CardDisplay.elevation","href":"main/CardDisplay/elevation.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"CardDisplay","type":"class"}},{"name":"padding","qualifiedName":"main.CardDisplay.padding","href":"main/CardDisplay/padding.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"CardDisplay","type":"class"}},{"name":"title","qualifiedName":"main.CardDisplay.title","href":"main/CardDisplay/title.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"CardDisplay","type":"class"}},{"name":"ConfigureResolutionRoute","qualifiedName":"main.ConfigureResolutionRoute","href":"main/ConfigureResolutionRoute-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ConfigureResolutionRoute","qualifiedName":"main.ConfigureResolutionRoute.ConfigureResolutionRoute","href":"main/ConfigureResolutionRoute/ConfigureResolutionRoute.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ConfigureResolutionRoute","type":"class"}},{"name":"build","qualifiedName":"main.ConfigureResolutionRoute.build","href":"main/ConfigureResolutionRoute/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ConfigureResolutionRoute","type":"class"}},{"name":"routeName","qualifiedName":"main.ConfigureResolutionRoute.routeName","href":"main/ConfigureResolutionRoute/routeName-constant.html","type":"constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ConfigureResolutionRoute","type":"class"}},{"name":"DefaultElevatedButton","qualifiedName":"main.DefaultElevatedButton","href":"main/DefaultElevatedButton-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"DefaultElevatedButton","qualifiedName":"main.DefaultElevatedButton.DefaultElevatedButton","href":"main/DefaultElevatedButton/DefaultElevatedButton.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"DefaultElevatedButton","type":"class"}},{"name":"build","qualifiedName":"main.DefaultElevatedButton.build","href":"main/DefaultElevatedButton/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"DefaultElevatedButton","type":"class"}},{"name":"height","qualifiedName":"main.DefaultElevatedButton.height","href":"main/DefaultElevatedButton/height.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"DefaultElevatedButton","type":"class"}},{"name":"name","qualifiedName":"main.DefaultElevatedButton.name","href":"main/DefaultElevatedButton/name.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"DefaultElevatedButton","type":"class"}},{"name":"onPressed","qualifiedName":"main.DefaultElevatedButton.onPressed","href":"main/DefaultElevatedButton/onPressed.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"DefaultElevatedButton","type":"class"}},{"name":"width","qualifiedName":"main.DefaultElevatedButton.width","href":"main/DefaultElevatedButton/width.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"DefaultElevatedButton","type":"class"}},{"name":"HomeRoute","qualifiedName":"main.HomeRoute","href":"main/HomeRoute-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"HomeRoute","qualifiedName":"main.HomeRoute.HomeRoute","href":"main/HomeRoute/HomeRoute.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"HomeRoute","type":"class"}},{"name":"build","qualifiedName":"main.HomeRoute.build","href":"main/HomeRoute/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"HomeRoute","type":"class"}},{"name":"routeName","qualifiedName":"main.HomeRoute.routeName","href":"main/HomeRoute/routeName-constant.html","type":"constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"HomeRoute","type":"class"}},{"name":"InfoType","qualifiedName":"main.InfoType","href":"main/InfoType-class.html","type":"enum","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"toString","qualifiedName":"main.InfoType.toString","href":"main/InfoType/toString.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"InfoType","type":"enum"}},{"name":"KnowledgeBaseRoute","qualifiedName":"main.KnowledgeBaseRoute","href":"main/KnowledgeBaseRoute-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"KnowledgeBaseRoute","qualifiedName":"main.KnowledgeBaseRoute.KnowledgeBaseRoute","href":"main/KnowledgeBaseRoute/KnowledgeBaseRoute.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"KnowledgeBaseRoute","type":"class"}},{"name":"build","qualifiedName":"main.KnowledgeBaseRoute.build","href":"main/KnowledgeBaseRoute/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"KnowledgeBaseRoute","type":"class"}},{"name":"routeName","qualifiedName":"main.KnowledgeBaseRoute.routeName","href":"main/KnowledgeBaseRoute/routeName-constant.html","type":"constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"KnowledgeBaseRoute","type":"class"}},{"name":"LoginRoute","qualifiedName":"main.LoginRoute","href":"main/LoginRoute-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"LoginRoute","qualifiedName":"main.LoginRoute.LoginRoute","href":"main/LoginRoute/LoginRoute.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"LoginRoute","type":"class"}},{"name":"createState","qualifiedName":"main.LoginRoute.createState","href":"main/LoginRoute/createState.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"LoginRoute","type":"class"}},{"name":"routeName","qualifiedName":"main.LoginRoute.routeName","href":"main/LoginRoute/routeName-constant.html","type":"constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"LoginRoute","type":"class"}},{"name":"ParseToString","qualifiedName":"main.ParseToString","href":"main/ParseToString.html","type":"extension","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"toShortString","qualifiedName":"main.ParseToString.toShortString","href":"main/ParseToString/toShortString.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ParseToString","type":"extension"}},{"name":"ResolveFilterBloc","qualifiedName":"main.ResolveFilterBloc","href":"main/ResolveFilterBloc-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"currentBloc","qualifiedName":"main.ResolveFilterBloc.currentBloc","href":"main/ResolveFilterBloc/currentBloc.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterBloc","type":"class"}},{"name":"handler","qualifiedName":"main.ResolveFilterBloc.handler","href":"main/ResolveFilterBloc/handler.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterBloc","type":"class"}},{"name":"setfromStatistics","qualifiedName":"main.ResolveFilterBloc.setfromStatistics","href":"main/ResolveFilterBloc/setfromStatistics.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterBloc","type":"class"}},{"name":"updateGroup","qualifiedName":"main.ResolveFilterBloc.updateGroup","href":"main/ResolveFilterBloc/updateGroup.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterBloc","type":"class"}},{"name":"updateSingle","qualifiedName":"main.ResolveFilterBloc.updateSingle","href":"main/ResolveFilterBloc/updateSingle.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterBloc","type":"class"}},{"name":"ResolveFilterHandler","qualifiedName":"main.ResolveFilterHandler","href":"main/ResolveFilterHandler-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ResolveFilterHandler","qualifiedName":"main.ResolveFilterHandler.ResolveFilterHandler","href":"main/ResolveFilterHandler/ResolveFilterHandler.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterHandler","type":"class"}},{"name":"switchGroup","qualifiedName":"main.ResolveFilterHandler.switchGroup","href":"main/ResolveFilterHandler/switchGroup.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterHandler","type":"class"}},{"name":"switchSingle","qualifiedName":"main.ResolveFilterHandler.switchSingle","href":"main/ResolveFilterHandler/switchSingle.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterHandler","type":"class"}},{"name":"ResolveFilterModel","qualifiedName":"main.ResolveFilterModel","href":"main/ResolveFilterModel-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ResolveFilterModel","qualifiedName":"main.ResolveFilterModel.ResolveFilterModel","href":"main/ResolveFilterModel/ResolveFilterModel.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterModel","type":"class"}},{"name":"filters","qualifiedName":"main.ResolveFilterModel.filters","href":"main/ResolveFilterModel/filters.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterModel","type":"class"}},{"name":"generateGroupedThreats","qualifiedName":"main.ResolveFilterModel.generateGroupedThreats","href":"main/ResolveFilterModel/generateGroupedThreats.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterModel","type":"class"}},{"name":"getFilterFromScanSatistic","qualifiedName":"main.ResolveFilterModel.getFilterFromScanSatistic","href":"main/ResolveFilterModel/getFilterFromScanSatistic.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterModel","type":"class"}},{"name":"isAnythingSelected","qualifiedName":"main.ResolveFilterModel.isAnythingSelected","href":"main/ResolveFilterModel/isAnythingSelected.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterModel","type":"class"}},{"name":"isGroupedChecked","qualifiedName":"main.ResolveFilterModel.isGroupedChecked","href":"main/ResolveFilterModel/isGroupedChecked.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterModel","type":"class"}},{"name":"lastScanned","qualifiedName":"main.ResolveFilterModel.lastScanned","href":"main/ResolveFilterModel/lastScanned.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterModel","type":"class"}},{"name":"numberOfToResolvedThreats","qualifiedName":"main.ResolveFilterModel.numberOfToResolvedThreats","href":"main/ResolveFilterModel/numberOfToResolvedThreats.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterModel","type":"class"}},{"name":"numberOfUnresolvedThreats","qualifiedName":"main.ResolveFilterModel.numberOfUnresolvedThreats","href":"main/ResolveFilterModel/numberOfUnresolvedThreats.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterModel","type":"class"}},{"name":"totalAmountOfThreats","qualifiedName":"main.ResolveFilterModel.totalAmountOfThreats","href":"main/ResolveFilterModel/totalAmountOfThreats.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveFilterModel","type":"class"}},{"name":"ResolveRoute","qualifiedName":"main.ResolveRoute","href":"main/ResolveRoute-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ResolveRoute","qualifiedName":"main.ResolveRoute.ResolveRoute","href":"main/ResolveRoute/ResolveRoute.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveRoute","type":"class"}},{"name":"createState","qualifiedName":"main.ResolveRoute.createState","href":"main/ResolveRoute/createState.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveRoute","type":"class"}},{"name":"routeName","qualifiedName":"main.ResolveRoute.routeName","href":"main/ResolveRoute/routeName-constant.html","type":"constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ResolveRoute","type":"class"}},{"name":"ScanInfo","qualifiedName":"main.ScanInfo","href":"main/ScanInfo-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ScanInfo","qualifiedName":"main.ScanInfo.ScanInfo","href":"main/ScanInfo/ScanInfo.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanInfo","type":"class"}},{"name":"build","qualifiedName":"main.ScanInfo.build","href":"main/ScanInfo/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanInfo","type":"class"}},{"name":"groupedThreat","qualifiedName":"main.ScanInfo.groupedThreat","href":"main/ScanInfo/groupedThreat.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanInfo","type":"class"}},{"name":"infoType","qualifiedName":"main.ScanInfo.infoType","href":"main/ScanInfo/infoType.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanInfo","type":"class"}},{"name":"ScanLogRoute","qualifiedName":"main.ScanLogRoute","href":"main/ScanLogRoute-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ScanLogRoute","qualifiedName":"main.ScanLogRoute.ScanLogRoute","href":"main/ScanLogRoute/ScanLogRoute.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanLogRoute","type":"class"}},{"name":"build","qualifiedName":"main.ScanLogRoute.build","href":"main/ScanLogRoute/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanLogRoute","type":"class"}},{"name":"routeName","qualifiedName":"main.ScanLogRoute.routeName","href":"main/ScanLogRoute/routeName-constant.html","type":"constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanLogRoute","type":"class"}},{"name":"ScanResolutionSwitch","qualifiedName":"main.ScanResolutionSwitch","href":"main/ScanResolutionSwitch-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ScanResolutionSwitch","qualifiedName":"main.ScanResolutionSwitch.ScanResolutionSwitch","href":"main/ScanResolutionSwitch/ScanResolutionSwitch.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanResolutionSwitch","type":"class"}},{"name":"build","qualifiedName":"main.ScanResolutionSwitch.build","href":"main/ScanResolutionSwitch/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanResolutionSwitch","type":"class"}},{"name":"groupedThreats","qualifiedName":"main.ScanResolutionSwitch.groupedThreats","href":"main/ScanResolutionSwitch/groupedThreats.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanResolutionSwitch","type":"class"}},{"name":"infoType","qualifiedName":"main.ScanResolutionSwitch.infoType","href":"main/ScanResolutionSwitch/infoType.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanResolutionSwitch","type":"class"}},{"name":"ScanRoute","qualifiedName":"main.ScanRoute","href":"main/ScanRoute-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ScanRoute","qualifiedName":"main.ScanRoute.ScanRoute","href":"main/ScanRoute/ScanRoute.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanRoute","type":"class"}},{"name":"createState","qualifiedName":"main.ScanRoute.createState","href":"main/ScanRoute/createState.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanRoute","type":"class"}},{"name":"routeName","qualifiedName":"main.ScanRoute.routeName","href":"main/ScanRoute/routeName-constant.html","type":"constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanRoute","type":"class"}},{"name":"ScanStatistics","qualifiedName":"main.ScanStatistics","href":"main/ScanStatistics-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ScanStatistics","qualifiedName":"main.ScanStatistics.ScanStatistics","href":"main/ScanStatistics/ScanStatistics.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatistics","type":"class"}},{"name":"build","qualifiedName":"main.ScanStatistics.build","href":"main/ScanStatistics/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatistics","type":"class"}},{"name":"ScanStatisticsBloc","qualifiedName":"main.ScanStatisticsBloc","href":"main/ScanStatisticsBloc-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"currentBloc","qualifiedName":"main.ScanStatisticsBloc.currentBloc","href":"main/ScanStatisticsBloc/currentBloc.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsBloc","type":"class"}},{"name":"handler","qualifiedName":"main.ScanStatisticsBloc.handler","href":"main/ScanStatisticsBloc/handler.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsBloc","type":"class"}},{"name":"resolve","qualifiedName":"main.ScanStatisticsBloc.resolve","href":"main/ScanStatisticsBloc/resolve.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsBloc","type":"class"}},{"name":"updateStatistics","qualifiedName":"main.ScanStatisticsBloc.updateStatistics","href":"main/ScanStatisticsBloc/updateStatistics.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsBloc","type":"class"}},{"name":"updateStatisticsfromModel","qualifiedName":"main.ScanStatisticsBloc.updateStatisticsfromModel","href":"main/ScanStatisticsBloc/updateStatisticsfromModel.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsBloc","type":"class"}},{"name":"ScanStatisticsHandler","qualifiedName":"main.ScanStatisticsHandler","href":"main/ScanStatisticsHandler-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ScanStatisticsHandler","qualifiedName":"main.ScanStatisticsHandler.ScanStatisticsHandler","href":"main/ScanStatisticsHandler/ScanStatisticsHandler.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsHandler","type":"class"}},{"name":"updateStatistics","qualifiedName":"main.ScanStatisticsHandler.updateStatistics","href":"main/ScanStatisticsHandler/updateStatistics.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsHandler","type":"class"}},{"name":"updateStatisticsfromModel","qualifiedName":"main.ScanStatisticsHandler.updateStatisticsfromModel","href":"main/ScanStatisticsHandler/updateStatisticsfromModel.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsHandler","type":"class"}},{"name":"updateStatisticsfromResolveModel","qualifiedName":"main.ScanStatisticsHandler.updateStatisticsfromResolveModel","href":"main/ScanStatisticsHandler/updateStatisticsfromResolveModel.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsHandler","type":"class"}},{"name":"ScanStatisticsModel","qualifiedName":"main.ScanStatisticsModel","href":"main/ScanStatisticsModel-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"ScanStatisticsModel","qualifiedName":"main.ScanStatisticsModel.ScanStatisticsModel","href":"main/ScanStatisticsModel/ScanStatisticsModel.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsModel","type":"class"}},{"name":"dummyScanStatisticsModelFactory","qualifiedName":"main.ScanStatisticsModel.dummyScanStatisticsModelFactory","href":"main/ScanStatisticsModel/dummyScanStatisticsModelFactory.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsModel","type":"class"}},{"name":"groupedThreats","qualifiedName":"main.ScanStatisticsModel.groupedThreats","href":"main/ScanStatisticsModel/groupedThreats.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsModel","type":"class"}},{"name":"identifiedThreats","qualifiedName":"main.ScanStatisticsModel.identifiedThreats","href":"main/ScanStatisticsModel/identifiedThreats.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsModel","type":"class"}},{"name":"lastScanned","qualifiedName":"main.ScanStatisticsModel.lastScanned","href":"main/ScanStatisticsModel/lastScanned.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsModel","type":"class"}},{"name":"names","qualifiedName":"main.ScanStatisticsModel.names","href":"main/ScanStatisticsModel/names-constant.html","type":"constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsModel","type":"class"}},{"name":"resolvedThreats","qualifiedName":"main.ScanStatisticsModel.resolvedThreats","href":"main/ScanStatisticsModel/resolvedThreats.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsModel","type":"class"}},{"name":"unresolvedThreats","qualifiedName":"main.ScanStatisticsModel.unresolvedThreats","href":"main/ScanStatisticsModel/unresolvedThreats.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"ScanStatisticsModel","type":"class"}},{"name":"SettingsRoute","qualifiedName":"main.SettingsRoute","href":"main/SettingsRoute-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"SettingsRoute","qualifiedName":"main.SettingsRoute.SettingsRoute","href":"main/SettingsRoute/SettingsRoute.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"SettingsRoute","type":"class"}},{"name":"createState","qualifiedName":"main.SettingsRoute.createState","href":"main/SettingsRoute/createState.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"SettingsRoute","type":"class"}},{"name":"routeName","qualifiedName":"main.SettingsRoute.routeName","href":"main/SettingsRoute/routeName-constant.html","type":"constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"SettingsRoute","type":"class"}},{"name":"UserBloc","qualifiedName":"main.UserBloc","href":"main/UserBloc-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"currentBloc","qualifiedName":"main.UserBloc.currentBloc","href":"main/UserBloc/currentBloc.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserBloc","type":"class"}},{"name":"handler","qualifiedName":"main.UserBloc.handler","href":"main/UserBloc/handler.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserBloc","type":"class"}},{"name":"login","qualifiedName":"main.UserBloc.login","href":"main/UserBloc/login.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserBloc","type":"class"}},{"name":"logout","qualifiedName":"main.UserBloc.logout","href":"main/UserBloc/logout.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserBloc","type":"class"}},{"name":"UserHandler","qualifiedName":"main.UserHandler","href":"main/UserHandler-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"UserHandler","qualifiedName":"main.UserHandler.UserHandler","href":"main/UserHandler/UserHandler.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserHandler","type":"class"}},{"name":"login","qualifiedName":"main.UserHandler.login","href":"main/UserHandler/login.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserHandler","type":"class"}},{"name":"logout","qualifiedName":"main.UserHandler.logout","href":"main/UserHandler/logout.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserHandler","type":"class"}},{"name":"UserModel","qualifiedName":"main.UserModel","href":"main/UserModel-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"UserModel","qualifiedName":"main.UserModel.UserModel","href":"main/UserModel/UserModel.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserModel","type":"class"}},{"name":"dummyUserModelFactory","qualifiedName":"main.UserModel.dummyUserModelFactory","href":"main/UserModel/dummyUserModelFactory.html","type":"method","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserModel","type":"class"}},{"name":"isLoggedIn","qualifiedName":"main.UserModel.isLoggedIn","href":"main/UserModel/isLoggedIn.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserModel","type":"class"}},{"name":"userName","qualifiedName":"main.UserModel.userName","href":"main/UserModel/userName.html","type":"property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserModel","type":"class"}},{"name":"UserRoute","qualifiedName":"main.UserRoute","href":"main/UserRoute-class.html","type":"class","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"UserRoute","qualifiedName":"main.UserRoute.UserRoute","href":"main/UserRoute/UserRoute.html","type":"constructor","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserRoute","type":"class"}},{"name":"build","qualifiedName":"main.UserRoute.build","href":"main/UserRoute/build.html","type":"method","overriddenDepth":1,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserRoute","type":"class"}},{"name":"routeName","qualifiedName":"main.UserRoute.routeName","href":"main/UserRoute/routeName-constant.html","type":"constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"UserRoute","type":"class"}},{"name":"knowledgeBaseDummy","qualifiedName":"main.knowledgeBaseDummy","href":"main/knowledgeBaseDummy-constant.html","type":"top-level constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"main","qualifiedName":"main.main","href":"main/main.html","type":"function","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"rnd","qualifiedName":"main.rnd","href":"main/rnd.html","type":"top-level property","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}},{"name":"seed","qualifiedName":"main.seed","href":"main/seed-constant.html","type":"top-level constant","overriddenDepth":0,"packageName":"flutternativetrapeze","enclosedBy":{"name":"main","type":"library"}}] diff --git a/doc/api/main/AbstractBloc-class.html b/doc/api/main/AbstractBloc-class.html new file mode 100644 index 0000000..054f5bd --- /dev/null +++ b/doc/api/main/AbstractBloc-class.html @@ -0,0 +1,337 @@ + + + + + + + + AbstractBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
AbstractBloc
+ +
+ +
+ + +
+
+

AbstractBloc<M, H> class + Null safety + +

+ + +
+

This AbstractBloc class implements the barebone structure of every Bloc.

+

We have Model generic M +We have a Handler generic H

+
+ + +
+
+ + + +
Implementers
+
+ + +
+
+ +
+

Constructors

+ +
+
+ AbstractBloc() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ bloc + → dynamic + +
+
+ Getter to get the current stream +
read-only
+ +
+ +
+ handler + → H + +
+
+ This handler field is used to modify the model M. +
@protected, final
+ +
+ +
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ publisher + BehaviorSubject<M> + +
+
+ This BehaviorSubject Object has the Stream Property we publish unto. +
@protected, final
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ dispose() + → void + + + +
+
+ + + +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/AbstractBloc/AbstractBloc.html b/doc/api/main/AbstractBloc/AbstractBloc.html new file mode 100644 index 0000000..68561f1 --- /dev/null +++ b/doc/api/main/AbstractBloc/AbstractBloc.html @@ -0,0 +1,134 @@ + + + + + + + + AbstractBloc constructor - AbstractBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
AbstractBloc
+ +
+ +
+ + +
+
+

AbstractBloc<M, H> constructor + Null safety +

+ +
+ AbstractBloc<M, H>() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/AbstractBloc/bloc.html b/doc/api/main/AbstractBloc/bloc.html new file mode 100644 index 0000000..9f10052 --- /dev/null +++ b/doc/api/main/AbstractBloc/bloc.html @@ -0,0 +1,149 @@ + + + + + + + + bloc property - AbstractBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
bloc
+ +
+ +
+ + +
+
+

bloc property + Null safety +

+ + + +
+ +
+ dynamic + bloc + + +
+ + +
+

Getter to get the current stream

+
+ + +
+

Implementation

+
get bloc => this.publisher.stream;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/AbstractBloc/dispose.html b/doc/api/main/AbstractBloc/dispose.html new file mode 100644 index 0000000..e153800 --- /dev/null +++ b/doc/api/main/AbstractBloc/dispose.html @@ -0,0 +1,145 @@ + + + + + + + + dispose method - AbstractBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
dispose
+ +
+ +
+ + +
+
+

dispose method + Null safety +

+ +
+ + +void +dispose() + + + +
+ + + + +
+

Implementation

+
void dispose() {
+  this.publisher.close();
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/AbstractBloc/handler.html b/doc/api/main/AbstractBloc/handler.html new file mode 100644 index 0000000..60d4008 --- /dev/null +++ b/doc/api/main/AbstractBloc/handler.html @@ -0,0 +1,145 @@ + + + + + + + + handler property - AbstractBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
handler
+ +
+ +
+ + +
+
+

handler property + Null safety +

+ +
+ H + handler +
@protected, final
+ +
+ +
+

This handler field is used to modify the model M.

+
+ + +
+

Implementation

+
@protected
+abstract final H handler;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/AbstractBloc/publisher.html b/doc/api/main/AbstractBloc/publisher.html new file mode 100644 index 0000000..dd9b4c1 --- /dev/null +++ b/doc/api/main/AbstractBloc/publisher.html @@ -0,0 +1,146 @@ + + + + + + + + publisher property - AbstractBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
publisher
+ +
+ +
+ + +
+
+

publisher property + Null safety +

+ +
+ BehaviorSubject<M> + publisher +
@protected, final
+ +
+ +
+

This BehaviorSubject Object has the Stream Property we publish unto.

+
+ + +
+

Implementation

+
@protected
+// ignore: close_sinks
+final BehaviorSubject<M> publisher = BehaviorSubject<M>();
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/App-class.html b/doc/api/main/App-class.html new file mode 100644 index 0000000..6f9b64e --- /dev/null +++ b/doc/api/main/App-class.html @@ -0,0 +1,414 @@ + + + + + + + + App class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
App
+ +
+ +
+ + +
+
+

App class + Null safety + +

+ + +
+

This App class is the main entry to the app.

+

Here are the routes and the themes.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ App() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This methoc configures the MaterialApp and the routes are set here. +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/App/App.html b/doc/api/main/App/App.html new file mode 100644 index 0000000..3738b54 --- /dev/null +++ b/doc/api/main/App/App.html @@ -0,0 +1,139 @@ + + + + + + + + App constructor - App class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
App
+ +
+ +
+ + +
+
+

App constructor + Null safety +

+ +
+ App() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/App/build.html b/doc/api/main/App/build.html new file mode 100644 index 0000000..10ab39c --- /dev/null +++ b/doc/api/main/App/build.html @@ -0,0 +1,182 @@ + + + + + + + + build method - App class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This methoc configures the MaterialApp and the routes are set here.

+
+ + + +
+

Implementation

+
@override
+Widget build(BuildContext context) {
+  return MaterialApp(
+    theme: ThemeData(
+        primarySwatch: App._primarySwatch,
+        fontFamily: 'Arial',
+        accentColor: App._secondarySwatch,
+        brightness: Brightness.light),
+    darkTheme: ThemeData(brightness: Brightness.dark),
+    themeMode: ThemeMode.light,
+    initialRoute: HomeRoute.routeName,
+    routes: <String, WidgetBuilder>{
+      HomeRoute.routeName: (BuildContext context) => HomeRoute(),
+      UserRoute.routeName: (BuildContext context) => UserRoute(),
+      ScanRoute.routeName: (BuildContext context) => ScanRoute(),
+      ScanLogRoute.routeName: (BuildContext context) => ScanLogRoute(),
+      ResolveRoute.routeName: (BuildContext context) => ResolveRoute(),
+      KnowledgeBaseRoute.routeName: (BuildContext context) =>
+          KnowledgeBaseRoute(),
+      SettingsRoute.routeName: (BuildContext context) => SettingsRoute(),
+      LoginRoute.routeName: (BuildContext context) => LoginRoute(),
+      ConfigureResolutionRoute.routeName: (BuildContext context) =>
+          ConfigureResolutionRoute(),
+    },
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/CardDisplay-class.html b/doc/api/main/CardDisplay-class.html new file mode 100644 index 0000000..087d77d --- /dev/null +++ b/doc/api/main/CardDisplay-class.html @@ -0,0 +1,462 @@ + + + + + + + + CardDisplay class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
CardDisplay
+ +
+ +
+ + +
+
+

CardDisplay class + Null safety + +

+ + +
+

This CardDisplay class is a ui component which can be used to display a card with a title and a body.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ CardDisplay({Key? key, Widget title = const Text(""), double elevation = 0, EdgeInsets padding = const EdgeInsets.all(0), Widget child = const Text("")}) +
+
+ +
const
+
+
+
+ +
+

Properties

+ +
+
+ child + Widget + +
+
+ Child that gets displayed on below a Divider and the title. +
final
+ +
+ +
+ elevation + double + +
+
+ Elevation which creates a dropshadow. +
final
+ +
+ +
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ padding + EdgeInsets + +
+
+ Padding of the card. +
final
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+ title + Widget + +
+
+ Title that gets displayed on top. +
final
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This build method creates a rounded card with the title a divider and the child. +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/CardDisplay/CardDisplay.html b/doc/api/main/CardDisplay/CardDisplay.html new file mode 100644 index 0000000..ce8bf83 --- /dev/null +++ b/doc/api/main/CardDisplay/CardDisplay.html @@ -0,0 +1,158 @@ + + + + + + + + CardDisplay constructor - CardDisplay class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
CardDisplay
+ +
+ +
+ + +
+
+

CardDisplay constructor + Null safety +

+ +
const + CardDisplay(
  1. {Key? key,
  2. +
  3. Widget title = const Text(""),
  4. +
  5. double elevation = 0,
  6. +
  7. EdgeInsets padding = const EdgeInsets.all(0),
  8. +
  9. Widget child = const Text("")}
  10. +
) +
+ + + + + +
+

Implementation

+
const CardDisplay(
+    {Key? key,
+    this.title = const Text(""),
+    this.elevation = 0,
+    this.padding = const EdgeInsets.all(0),
+    this.child = const Text("")})
+    : super(key: key);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/CardDisplay/build.html b/doc/api/main/CardDisplay/build.html new file mode 100644 index 0000000..359a365 --- /dev/null +++ b/doc/api/main/CardDisplay/build.html @@ -0,0 +1,182 @@ + + + + + + + + build method - CardDisplay class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This build method creates a rounded card with the title a divider and the child.

+
+ + + +
+

Implementation

+
@override
+Widget build(BuildContext context) {
+  return Card(
+    shape: RoundedRectangleBorder(
+        borderRadius: BorderRadius.all(Radius.circular(20))),
+    elevation: this.elevation,
+    child: Padding(
+      padding: this.padding,
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          this.title,
+          Divider(
+            thickness: 1,
+            indent: 60,
+          ),
+          this.child,
+        ],
+      ),
+    ),
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/CardDisplay/child.html b/doc/api/main/CardDisplay/child.html new file mode 100644 index 0000000..4f53270 --- /dev/null +++ b/doc/api/main/CardDisplay/child.html @@ -0,0 +1,153 @@ + + + + + + + + child property - CardDisplay class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
child
+ +
+ +
+ + +
+
+

child property + Null safety +

+ +
+ Widget + child +
final
+ +
+ +
+

Child that gets displayed on below a Divider and the title.

+
+ + +
+

Implementation

+
final Widget child;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/CardDisplay/elevation.html b/doc/api/main/CardDisplay/elevation.html new file mode 100644 index 0000000..ea7ea97 --- /dev/null +++ b/doc/api/main/CardDisplay/elevation.html @@ -0,0 +1,153 @@ + + + + + + + + elevation property - CardDisplay class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
elevation
+ +
+ +
+ + +
+
+

elevation property + Null safety +

+ +
+ double + elevation +
final
+ +
+ +
+

Elevation which creates a dropshadow.

+
+ + +
+

Implementation

+
final double elevation;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/CardDisplay/padding.html b/doc/api/main/CardDisplay/padding.html new file mode 100644 index 0000000..bce26bc --- /dev/null +++ b/doc/api/main/CardDisplay/padding.html @@ -0,0 +1,153 @@ + + + + + + + + padding property - CardDisplay class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
padding
+ +
+ +
+ + +
+
+

padding property + Null safety +

+ +
+ EdgeInsets + padding +
final
+ +
+ +
+

Padding of the card.

+
+ + +
+

Implementation

+
final EdgeInsets padding;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/CardDisplay/title.html b/doc/api/main/CardDisplay/title.html new file mode 100644 index 0000000..8004ff1 --- /dev/null +++ b/doc/api/main/CardDisplay/title.html @@ -0,0 +1,153 @@ + + + + + + + + title property - CardDisplay class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
title
+ +
+ +
+ + +
+
+

title property + Null safety +

+ +
+ Widget + title +
final
+ +
+ +
+

Title that gets displayed on top.

+
+ + +
+

Implementation

+
final Widget title;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ConfigureResolutionRoute-class.html b/doc/api/main/ConfigureResolutionRoute-class.html new file mode 100644 index 0000000..2426f89 --- /dev/null +++ b/doc/api/main/ConfigureResolutionRoute-class.html @@ -0,0 +1,437 @@ + + + + + + + + ConfigureResolutionRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ConfigureResolutionRoute
+ +
+ +
+ + +
+
+

ConfigureResolutionRoute class + Null safety + +

+ + +
+

This ConfigureResolutionRoute class represents the "Resolve - Configuration" page in the drawio sketch v4.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ ConfigureResolutionRoute({Key? key}) +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This build Method gets called to build the UI. This combines the +components into a Scaffold. +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + +
+

Constants

+ +
+
+ routeName + → const String + + +
+
+ This field is the routName under which this page is registered in the app. + + +
+ '/confres' +
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ConfigureResolutionRoute/ConfigureResolutionRoute.html b/doc/api/main/ConfigureResolutionRoute/ConfigureResolutionRoute.html new file mode 100644 index 0000000..38d58fc --- /dev/null +++ b/doc/api/main/ConfigureResolutionRoute/ConfigureResolutionRoute.html @@ -0,0 +1,146 @@ + + + + + + + + ConfigureResolutionRoute constructor - ConfigureResolutionRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ConfigureResolutionRoute
+ +
+ +
+ + +
+
+

ConfigureResolutionRoute constructor + Null safety +

+ +
+ ConfigureResolutionRoute(
  1. {Key? key}
  2. +
) +
+ + + + + +
+

Implementation

+
ConfigureResolutionRoute({Key? key}) : super(key: key);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ConfigureResolutionRoute/build.html b/doc/api/main/ConfigureResolutionRoute/build.html new file mode 100644 index 0000000..b943c30 --- /dev/null +++ b/doc/api/main/ConfigureResolutionRoute/build.html @@ -0,0 +1,187 @@ + + + + + + + + build method - ConfigureResolutionRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This build Method gets called to build the UI. This combines the +components into a Scaffold.

+
+ + + +
+

Implementation

+
@override
+Widget build(BuildContext context) {
+  return Scaffold(
+    appBar: AppBar(
+      title: Text("Configure Resolution",
+          style: TextStyle(fontWeight: FontWeight.bold)),
+    ),
+    body: StreamBuilder<Object>(
+      stream: ScanStatisticsBloc.currentBloc.bloc,
+      builder: (context, snapshot) {
+        if (snapshot.hasData) {
+          ScanStatisticsModel model = snapshot.data as ScanStatisticsModel;
+          return Column(
+            children: [
+              ..._buildSwitches(context, model),
+              Spacer(),
+              _buildResolveButton(context),
+              SizedBox(
+                height: 80,
+              ),
+            ],
+          );
+        }
+        return Text("Error");
+      },
+    ),
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ConfigureResolutionRoute/routeName-constant.html b/doc/api/main/ConfigureResolutionRoute/routeName-constant.html new file mode 100644 index 0000000..70d0c41 --- /dev/null +++ b/doc/api/main/ConfigureResolutionRoute/routeName-constant.html @@ -0,0 +1,151 @@ + + + + + + + + routeName constant - ConfigureResolutionRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
routeName
+ +
+ +
+ + +
+
+

routeName constant + Null safety +

+ +
+ String + const routeName + + +
+ +
+

This field is the routName under which this page is registered in the app.

+
+ + +
+

Implementation

+
static const String routeName = '/confres';
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/DefaultElevatedButton-class.html b/doc/api/main/DefaultElevatedButton-class.html new file mode 100644 index 0000000..63a92c3 --- /dev/null +++ b/doc/api/main/DefaultElevatedButton-class.html @@ -0,0 +1,462 @@ + + + + + + + + DefaultElevatedButton class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
DefaultElevatedButton
+ +
+ +
+ + +
+
+

DefaultElevatedButton class + Null safety + +

+ + +
+

This DefaultElevatedButton is a ElevatedButton with a fixed size, we use throughout the project.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ DefaultElevatedButton({Key? key, required VoidCallback? onPressed, String name = "", double height = 50, double width = 200}) +
+
+ +
const
+
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ height + double + +
+
+ +
final
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ name + String + +
+
+ Name of the Button as a String. +
final
+ +
+ +
+ onPressed + VoidCallback? + +
+
+ The CallBack Function which gets executed on every tap. +
final
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+ width + double + +
+
+ +
final
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This method builds a button with the size of the SizedBox. +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/DefaultElevatedButton/DefaultElevatedButton.html b/doc/api/main/DefaultElevatedButton/DefaultElevatedButton.html new file mode 100644 index 0000000..8291bf3 --- /dev/null +++ b/doc/api/main/DefaultElevatedButton/DefaultElevatedButton.html @@ -0,0 +1,158 @@ + + + + + + + + DefaultElevatedButton constructor - DefaultElevatedButton class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
DefaultElevatedButton
+ +
+ +
+ + +
+
+

DefaultElevatedButton constructor + Null safety +

+ +
const + DefaultElevatedButton(
  1. {Key? key,
  2. +
  3. required VoidCallback? onPressed,
  4. +
  5. String name = "",
  6. +
  7. double height = 50,
  8. +
  9. double width = 200}
  10. +
) +
+ + + + + +
+

Implementation

+
const DefaultElevatedButton({
+  Key? key,
+  required this.onPressed,
+  this.name = "",
+  this.height = 50,
+  this.width = 200,
+}) : super(key: key);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/DefaultElevatedButton/build.html b/doc/api/main/DefaultElevatedButton/build.html new file mode 100644 index 0000000..2fd0319 --- /dev/null +++ b/doc/api/main/DefaultElevatedButton/build.html @@ -0,0 +1,176 @@ + + + + + + + + build method - DefaultElevatedButton class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This method builds a button with the size of the SizedBox.

+
+ + + +
+

Implementation

+
@override
+Widget build(BuildContext context) {
+  return SizedBox(
+    width: width,
+    height: height,
+    child: ElevatedButton(
+      onPressed: this.onPressed,
+      child: Text(
+        this.name,
+        style: TextStyle(
+          fontSize: 20,
+        ),
+      ),
+    ),
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/DefaultElevatedButton/height.html b/doc/api/main/DefaultElevatedButton/height.html new file mode 100644 index 0000000..9e9e004 --- /dev/null +++ b/doc/api/main/DefaultElevatedButton/height.html @@ -0,0 +1,150 @@ + + + + + + + + height property - DefaultElevatedButton class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
height
+ +
+ +
+ + +
+
+

height property + Null safety +

+ +
+ double + height +
final
+ +
+ + + +
+

Implementation

+
final double height;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/DefaultElevatedButton/name.html b/doc/api/main/DefaultElevatedButton/name.html new file mode 100644 index 0000000..cd5da6d --- /dev/null +++ b/doc/api/main/DefaultElevatedButton/name.html @@ -0,0 +1,153 @@ + + + + + + + + name property - DefaultElevatedButton class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
name
+ +
+ +
+ + +
+
+

name property + Null safety +

+ +
+ String + name +
final
+ +
+ +
+

Name of the Button as a String.

+
+ + +
+

Implementation

+
final String name;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/DefaultElevatedButton/onPressed.html b/doc/api/main/DefaultElevatedButton/onPressed.html new file mode 100644 index 0000000..174ef03 --- /dev/null +++ b/doc/api/main/DefaultElevatedButton/onPressed.html @@ -0,0 +1,153 @@ + + + + + + + + onPressed property - DefaultElevatedButton class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
onPressed
+ +
+ +
+ + +
+
+

onPressed property + Null safety +

+ +
+ VoidCallback? + onPressed +
final
+ +
+ +
+

The CallBack Function which gets executed on every tap.

+
+ + +
+

Implementation

+
final VoidCallback? onPressed;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/DefaultElevatedButton/width.html b/doc/api/main/DefaultElevatedButton/width.html new file mode 100644 index 0000000..2378f7e --- /dev/null +++ b/doc/api/main/DefaultElevatedButton/width.html @@ -0,0 +1,150 @@ + + + + + + + + width property - DefaultElevatedButton class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
width
+ +
+ +
+ + +
+
+

width property + Null safety +

+ +
+ double + width +
final
+ +
+ + + +
+

Implementation

+
final double width;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/HomeRoute-class.html b/doc/api/main/HomeRoute-class.html new file mode 100644 index 0000000..218b6ae --- /dev/null +++ b/doc/api/main/HomeRoute-class.html @@ -0,0 +1,437 @@ + + + + + + + + HomeRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
HomeRoute
+ +
+ +
+ + +
+
+

HomeRoute class + Null safety + +

+ + +
+

This HomeRoute class represents the "Main(a-x), Main(b-x), Profile(a-y), Profile(b-y)" page in the drawio sketch v4.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ HomeRoute() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This build Method gets called to build the UI. This combines the +components into a Scaffold. +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + +
+

Constants

+ +
+
+ routeName + → const String + + +
+
+ This field is the routName under which this page is registered in the app. + + +
+ '/app' +
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/HomeRoute/HomeRoute.html b/doc/api/main/HomeRoute/HomeRoute.html new file mode 100644 index 0000000..0237f7d --- /dev/null +++ b/doc/api/main/HomeRoute/HomeRoute.html @@ -0,0 +1,141 @@ + + + + + + + + HomeRoute constructor - HomeRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
HomeRoute
+ +
+ +
+ + +
+
+

HomeRoute constructor + Null safety +

+ +
+ HomeRoute() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/HomeRoute/build.html b/doc/api/main/HomeRoute/build.html new file mode 100644 index 0000000..545f4be --- /dev/null +++ b/doc/api/main/HomeRoute/build.html @@ -0,0 +1,184 @@ + + + + + + + + build method - HomeRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This build Method gets called to build the UI. This combines the +components into a Scaffold.

+
+ + + +
+

Implementation

+
@override
+Widget build(BuildContext context) {
+  return Scaffold(
+    appBar: _buildAppBar(context),
+    body: Column(
+      children: [
+        SizedBox(height: 80),
+        ScanStatistics(),
+        Spacer(),
+        // Builds conditional Resolve button if unresolved threats are beyond 0.
+        _buildConditionalResolveButton(context),
+        // Builds Scan Button.
+        DefaultElevatedButton(
+          onPressed: () {
+            Navigator.pushNamed(context, ScanRoute.routeName);
+          },
+          name: "Scan my Device",
+        ),
+        SizedBox(
+          height: 80,
+        )
+      ],
+    ),
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/HomeRoute/routeName-constant.html b/doc/api/main/HomeRoute/routeName-constant.html new file mode 100644 index 0000000..2209a2e --- /dev/null +++ b/doc/api/main/HomeRoute/routeName-constant.html @@ -0,0 +1,151 @@ + + + + + + + + routeName constant - HomeRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
routeName
+ +
+ +
+ + +
+
+

routeName constant + Null safety +

+ +
+ String + const routeName + + +
+ +
+

This field is the routName under which this page is registered in the app.

+
+ + +
+

Implementation

+
static const String routeName = '/app';
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/InfoType-class.html b/doc/api/main/InfoType-class.html new file mode 100644 index 0000000..a26d460 --- /dev/null +++ b/doc/api/main/InfoType-class.html @@ -0,0 +1,360 @@ + + + + + + + + InfoType enum - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
InfoType
+ +
+ +
+ + +
+
+

InfoType enum + Null safety + +

+ + +
+

This is the InfoType enum which is the current set of threats

+
+ + +
+
+ + + + +
+
+ +
+

Constants

+ +
+
+ fakeapps + → const InfoType + + +
+
+ + + +
+ const InfoType(1) +
+
+ +
+ insecureWifi + → const InfoType + + +
+
+ + + +
+ const InfoType(3) +
+
+ +
+ keylogger + → const InfoType + + +
+
+ + + +
+ const InfoType(2) +
+
+ +
+ spyware + → const InfoType + + +
+
+ + + +
+ const InfoType(0) +
+
+ +
+ values + → const List<InfoType> + + +
+
+

A constant List of the values in this enum, in order of their declaration.

+ + +
+ const List<InfoType> +
+
+ +
+
+ + +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ index + int + +
+
+

The integer index of this enum.

+
final
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
override
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/InfoType/toString.html b/doc/api/main/InfoType/toString.html new file mode 100644 index 0000000..ff6df30 --- /dev/null +++ b/doc/api/main/InfoType/toString.html @@ -0,0 +1,150 @@ + + + + + + + + toString method - InfoType extension - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
toString
+ +
+ +
+ + +
+
+

toString method + Null safety +

+ +
+ + +String +toString() + +
override
+ +
+ +
+

A string representation of this object.

+

Some classes have a default textual representation, +often paired with a static parse function (like int.parse). +These classes will provide the textual representation as +their string represetion.

+

Other classes have no meaningful textual representation +that a program will care about. +Such classes will typically override toString to provide +useful information when inspecting the object, +mainly for debugging or logging.

+
+ + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/KnowledgeBaseRoute-class.html b/doc/api/main/KnowledgeBaseRoute-class.html new file mode 100644 index 0000000..70a9bfa --- /dev/null +++ b/doc/api/main/KnowledgeBaseRoute-class.html @@ -0,0 +1,439 @@ + + + + + + + + KnowledgeBaseRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
KnowledgeBaseRoute
+ +
+ +
+ + +
+
+

KnowledgeBaseRoute class + Null safety + +

+ + +
+

This KnowledgeBaseRoute class represents the "KnowledgeBase" page in the drawio sketch v4.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ KnowledgeBaseRoute({Key? key}) +
+
+ +
const
+
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This build Method gets called to build the UI. This combines the +components into a Scaffold. Espescially parses the knowledge base and puts all information from it +into a ListView. +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + +
+

Constants

+ +
+
+ routeName + → const String + + +
+
+ This field is the routName under which this page is registered in the app. + + +
+ "/knowledgeBase" +
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/KnowledgeBaseRoute/KnowledgeBaseRoute.html b/doc/api/main/KnowledgeBaseRoute/KnowledgeBaseRoute.html new file mode 100644 index 0000000..ebe27ae --- /dev/null +++ b/doc/api/main/KnowledgeBaseRoute/KnowledgeBaseRoute.html @@ -0,0 +1,146 @@ + + + + + + + + KnowledgeBaseRoute constructor - KnowledgeBaseRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
KnowledgeBaseRoute
+ +
+ +
+ + +
+
+

KnowledgeBaseRoute constructor + Null safety +

+ +
const + KnowledgeBaseRoute(
  1. {Key? key}
  2. +
) +
+ + + + + +
+

Implementation

+
const KnowledgeBaseRoute({Key? key}) : super(key: key);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/KnowledgeBaseRoute/build.html b/doc/api/main/KnowledgeBaseRoute/build.html new file mode 100644 index 0000000..c8ede3a --- /dev/null +++ b/doc/api/main/KnowledgeBaseRoute/build.html @@ -0,0 +1,184 @@ + + + + + + + + build method - KnowledgeBaseRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This build Method gets called to build the UI. This combines the +components into a Scaffold. Espescially parses the knowledge base and puts all information from it +into a ListView.

+
+ + + +
+

Implementation

+
@override
+Widget build(BuildContext context) {
+  final args = ModalRoute.of(context)!.settings.arguments as InfoType;
+  final entries = knowledgeBaseDummy[args]!.values.toList();
+  final keys = knowledgeBaseDummy[args]!.keys.toList();
+  return Scaffold(
+    appBar: _buildAppBar(context),
+    body: ListView.builder(
+        padding: EdgeInsets.only(left: 10, right: 10, top: 10),
+        itemCount: entries.length,
+        itemBuilder: (BuildContext context, int index) {
+          switch (keys[index]) {
+            case "name":
+              return _buildTitleCard(context, entries[index]);
+            default:
+              return _buildTextCard(
+                  context,
+                  keys[index].substring(0, 1).toUpperCase() +
+                      keys[index].substring(1, keys[index].length),
+                  entries[index]);
+          }
+        }),
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/KnowledgeBaseRoute/routeName-constant.html b/doc/api/main/KnowledgeBaseRoute/routeName-constant.html new file mode 100644 index 0000000..390694c --- /dev/null +++ b/doc/api/main/KnowledgeBaseRoute/routeName-constant.html @@ -0,0 +1,151 @@ + + + + + + + + routeName constant - KnowledgeBaseRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
routeName
+ +
+ +
+ + +
+
+

routeName constant + Null safety +

+ +
+ String + const routeName + + +
+ +
+

This field is the routName under which this page is registered in the app.

+
+ + +
+

Implementation

+
static const String routeName = "/knowledgeBase";
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/LoginRoute-class.html b/doc/api/main/LoginRoute-class.html new file mode 100644 index 0000000..242475f --- /dev/null +++ b/doc/api/main/LoginRoute-class.html @@ -0,0 +1,437 @@ + + + + + + + + LoginRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
LoginRoute
+ +
+ +
+ + +
+
+

LoginRoute class + Null safety + +

+ + +
+

This LoginRoute class is a StatefulWidget with the corresponding _LoginRouteState class for the UI and is "Profile(a)" page of the drawio sketch.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ LoginRoute({Key? key}) +
+
+ +
const
+
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ createElement() + StatefulElement + + + +
+
+ Creates a StatefulElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ createState() + → _LoginRouteState + + + +
+
+ Creates the mutable state for this widget at a given location in the tree. [...] +
override
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + +
+

Constants

+ +
+
+ routeName + → const String + + +
+
+ This field is the routName under which this page is registered in the app. + + +
+ '/' +
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/LoginRoute/LoginRoute.html b/doc/api/main/LoginRoute/LoginRoute.html new file mode 100644 index 0000000..4d73fca --- /dev/null +++ b/doc/api/main/LoginRoute/LoginRoute.html @@ -0,0 +1,146 @@ + + + + + + + + LoginRoute constructor - LoginRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
LoginRoute
+ +
+ +
+ + +
+
+

LoginRoute constructor + Null safety +

+ +
const + LoginRoute(
  1. {Key? key}
  2. +
) +
+ + + + + +
+

Implementation

+
const LoginRoute({Key? key}) : super(key: key);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/LoginRoute/createState.html b/doc/api/main/LoginRoute/createState.html new file mode 100644 index 0000000..52d2fbe --- /dev/null +++ b/doc/api/main/LoginRoute/createState.html @@ -0,0 +1,171 @@ + + + + + + + + createState method - LoginRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
createState
+ +
+ +
+ + +
+
+

createState method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +_LoginRouteState +createState() + +
override
+ +
+ +
+

Creates the mutable state for this widget at a given location in the tree.

+

Subclasses should override this method to return a newly created +instance of their associated State subclass:

+
@override
+_MyState createState() => _MyState();
+
+

The framework can call this method multiple times over the lifetime of +a StatefulWidget. For example, if the widget is inserted into the tree +in multiple locations, the framework will create a separate State object +for each location. Similarly, if the widget is removed from the tree and +later inserted into the tree again, the framework will call createState +again to create a fresh State object, simplifying the lifecycle of +State objects.

+
+ + + +
+

Implementation

+
@override
+_LoginRouteState createState() => _LoginRouteState();
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/LoginRoute/routeName-constant.html b/doc/api/main/LoginRoute/routeName-constant.html new file mode 100644 index 0000000..74bfd7b --- /dev/null +++ b/doc/api/main/LoginRoute/routeName-constant.html @@ -0,0 +1,151 @@ + + + + + + + + routeName constant - LoginRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
routeName
+ +
+ +
+ + +
+
+

routeName constant + Null safety +

+ +
+ String + const routeName + + +
+ +
+

This field is the routName under which this page is registered in the app.

+
+ + +
+

Implementation

+
static const String routeName = '/';
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ParseToString.html b/doc/api/main/ParseToString.html new file mode 100644 index 0000000..dce1191 --- /dev/null +++ b/doc/api/main/ParseToString.html @@ -0,0 +1,194 @@ + + + + + + + + ParseToString extension - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ParseToString
+ +
+ +
+ + +
+
+

ParseToString extension + Null safety + +

+ + + +
+
+
on
+
+ +
+
+
+ + +
+

Methods

+
+
+ toShortString() + String + + + +
+
+ Gives the InfoType a toString() method. + + +
+ +
+
+ + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ParseToString/toShortString.html b/doc/api/main/ParseToString/toShortString.html new file mode 100644 index 0000000..437a720 --- /dev/null +++ b/doc/api/main/ParseToString/toShortString.html @@ -0,0 +1,134 @@ + + + + + + + + toShortString method - ParseToString extension - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
toShortString
+ +
+ +
+ + +
+
+

toShortString method + Null safety +

+ +
+ + +String +toShortString() + + + +
+ +
+

Gives the InfoType a toString() method.

+
+ + + +
+

Implementation

+
String toShortString() {
+  return this.toString().split('.').last;
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc-class.html b/doc/api/main/ResolveFilterBloc-class.html new file mode 100644 index 0000000..7387886 --- /dev/null +++ b/doc/api/main/ResolveFilterBloc-class.html @@ -0,0 +1,386 @@ + + + + + + + + ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ResolveFilterBloc
+ +
+ +
+ + +
+
+

ResolveFilterBloc class + Null safety + +

+ + +
+

This ResolveFilterBloc class handles the state of the ResolveFilterModel.

+

There are mutation functions (setfromStatistics,updateSingle,updateGroup) to mutate the state of the current ResolveFilterModel.

+
ResolveFilterModel old;
+ResolveFilterBloc.currentBloc.updateSingle(InfoType.spyware,"MySpyware",old);
+
+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ + +
+

Properties

+ +
+
+ bloc + → dynamic + +
+
+ Getter to get the current stream +
read-only, inherited
+ +
+ +
+ handler + ResolveFilterHandler + +
+
+ Initializes the ResolveFilterHandler which performs all the state changes on the ResolveFilterModel. +
final
+ +
+ +
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ publisher + BehaviorSubject<ResolveFilterModel> + +
+
+ This BehaviorSubject Object has the Stream Property we publish unto. +
@protected, final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ dispose() + → void + + + +
+
+ +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ setfromStatistics(ScanStatisticsModel model) + → void + + + +
+
+ This Mutation adds a ResolveFilterModel to the stream based on the threats in the ScanStatisticsModel. + + +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ updateGroup(InfoType infoType, bool value, ResolveFilterModel model) + → void + + + +
+
+ This Mutaion updates a group threat filter value and pushes it to the publisher. + + +
+ +
+ updateSingle(InfoType infoType, String threat, ResolveFilterModel model) + → void + + + +
+
+ This Mutaion updates a group threat filter value and pushes it to the publisher. + + +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ +
+

Static Properties

+ +
+
+ currentBloc + ResolveFilterBloc + +
+
+ The current instance of the Singleton. +
final
+ +
+ +
+
+ + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc/ResolveFilterBloc.html b/doc/api/main/ResolveFilterBloc/ResolveFilterBloc.html new file mode 100644 index 0000000..daf69d3 --- /dev/null +++ b/doc/api/main/ResolveFilterBloc/ResolveFilterBloc.html @@ -0,0 +1,135 @@ + + + + + + + + ResolveFilterBloc constructor - ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ResolveFilterBloc
+ +
+ +
+ + +
+
+

ResolveFilterBloc constructor + Null safety +

+ +
+ ResolveFilterBloc() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc/bloc.html b/doc/api/main/ResolveFilterBloc/bloc.html new file mode 100644 index 0000000..b709fbf --- /dev/null +++ b/doc/api/main/ResolveFilterBloc/bloc.html @@ -0,0 +1,149 @@ + + + + + + + + bloc property - ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
bloc
+ +
+ +
+ + +
+
+

bloc property + Null safety +

+ + + +
+ +
+ dynamic + bloc +
inherited
+ +
+ + + + +
+

Implementation

+
get bloc => this.publisher.stream;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc/currentBloc.html b/doc/api/main/ResolveFilterBloc/currentBloc.html new file mode 100644 index 0000000..dbe9002 --- /dev/null +++ b/doc/api/main/ResolveFilterBloc/currentBloc.html @@ -0,0 +1,147 @@ + + + + + + + + currentBloc property - ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
currentBloc
+ +
+ +
+ + +
+
+

currentBloc property + Null safety +

+ +
+ ResolveFilterBloc + currentBloc +
final
+ +
+ +
+

The current instance of the Singleton.

+
+ + +
+

Implementation

+
static final ResolveFilterBloc currentBloc = ResolveFilterBloc._();
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc/dispose.html b/doc/api/main/ResolveFilterBloc/dispose.html new file mode 100644 index 0000000..e3776a0 --- /dev/null +++ b/doc/api/main/ResolveFilterBloc/dispose.html @@ -0,0 +1,148 @@ + + + + + + + + dispose method - ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
dispose
+ +
+ +
+ + +
+
+

dispose method + Null safety +

+ +
+ + +dynamic +dispose() + +
inherited
+ +
+ + + + +
+

Implementation

+
dispose() {
+  this.publisher.close();
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc/filter.html b/doc/api/main/ResolveFilterBloc/filter.html new file mode 100644 index 0000000..0dfae07 --- /dev/null +++ b/doc/api/main/ResolveFilterBloc/filter.html @@ -0,0 +1,147 @@ + + + + + + + + filter property - ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
filter
+ +
+ +
+ + +
+
+

filter property + Null safety +

+ + + +
+ +
+ dynamic + filter + + +
+ + + + +
+

Implementation

+
get filter => this._filterPublisher.stream;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc/handler.html b/doc/api/main/ResolveFilterBloc/handler.html new file mode 100644 index 0000000..2044754 --- /dev/null +++ b/doc/api/main/ResolveFilterBloc/handler.html @@ -0,0 +1,147 @@ + + + + + + + + handler property - ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
handler
+ +
+ +
+ + +
+
+

handler property + Null safety +

+ +
+ ResolveFilterHandler + handler +
final
+ +
+ +
+

Initializes the ResolveFilterHandler which performs all the state changes on the ResolveFilterModel.

+
+ + +
+

Implementation

+
final handler = ResolveFilterHandler();
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc/publisher.html b/doc/api/main/ResolveFilterBloc/publisher.html new file mode 100644 index 0000000..a55fe97 --- /dev/null +++ b/doc/api/main/ResolveFilterBloc/publisher.html @@ -0,0 +1,149 @@ + + + + + + + + publisher property - ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
publisher
+ +
+ +
+ + +
+
+

publisher property + Null safety +

+ +
+ BehaviorSubject<ResolveFilterModel> + publisher +
@protected, final, inherited
+ +
+ +
+

This ´BehaviorSubject´ Object has the Stream Property we publish unto

+
+ + +
+

Implementation

+
@protected
+// ignore: close_sinks
+final BehaviorSubject<T> publisher = BehaviorSubject<T>();
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc/setfromStatistics.html b/doc/api/main/ResolveFilterBloc/setfromStatistics.html new file mode 100644 index 0000000..20c13d7 --- /dev/null +++ b/doc/api/main/ResolveFilterBloc/setfromStatistics.html @@ -0,0 +1,152 @@ + + + + + + + + setfromStatistics method - ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
setfromStatistics
+ +
+ +
+ + +
+
+

setfromStatistics method + Null safety +

+ +
+ + +void +setfromStatistics(
  1. ScanStatisticsModel model
  2. +
) + + + +
+ +
+

This Mutation adds a ResolveFilterModel to the stream based on the threats in the ScanStatisticsModel.

+
+ + + +
+

Implementation

+
void setfromStatistics(ScanStatisticsModel model) {
+  this.publisher.add(ResolveFilterModel.getFilterFromScanSatistic(model));
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc/updateGroup.html b/doc/api/main/ResolveFilterBloc/updateGroup.html new file mode 100644 index 0000000..dfb2f8d --- /dev/null +++ b/doc/api/main/ResolveFilterBloc/updateGroup.html @@ -0,0 +1,154 @@ + + + + + + + + updateGroup method - ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
updateGroup
+ +
+ +
+ + +
+
+

updateGroup method + Null safety +

+ +
+ + +void +updateGroup(
  1. InfoType infoType,
  2. +
  3. bool value,
  4. +
  5. ResolveFilterModel model
  6. +
) + + + +
+ +
+

This Mutaion updates a group threat filter value and pushes it to the publisher.

+
+ + + +
+

Implementation

+
void updateGroup(InfoType infoType, bool value, ResolveFilterModel model) {
+  this.publisher.add(this.handler.switchGroup(infoType, value, model));
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterBloc/updateSingle.html b/doc/api/main/ResolveFilterBloc/updateSingle.html new file mode 100644 index 0000000..d5f235c --- /dev/null +++ b/doc/api/main/ResolveFilterBloc/updateSingle.html @@ -0,0 +1,155 @@ + + + + + + + + updateSingle method - ResolveFilterBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
updateSingle
+ +
+ +
+ + +
+
+

updateSingle method + Null safety +

+ +
+ + +void +updateSingle(
  1. InfoType infoType,
  2. +
  3. String threat,
  4. +
  5. ResolveFilterModel model
  6. +
) + + + +
+ +
+

This Mutaion updates a group threat filter value and pushes it to the publisher.

+
+ + + +
+

Implementation

+
void updateSingle(
+    InfoType infoType, String threat, ResolveFilterModel model) {
+  this.publisher.add(this.handler.switchSingle(infoType, threat, model));
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterHandler-class.html b/doc/api/main/ResolveFilterHandler-class.html new file mode 100644 index 0000000..2bc1e19 --- /dev/null +++ b/doc/api/main/ResolveFilterHandler-class.html @@ -0,0 +1,301 @@ + + + + + + + + ResolveFilterHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ResolveFilterHandler
+ +
+ +
+ + +
+
+

ResolveFilterHandler class + Null safety + +

+ + +
+

This ResolveFilterHandler class has the implementation for all the mutations in the ResolveFilterBloc.

+ +
+ + + +
+

Constructors

+ +
+
+ ResolveFilterHandler() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ switchGroup(InfoType infoType, bool value, ResolveFilterModel currentModel) + ResolveFilterModel + + + +
+
+ This is Method switches all the filter booleans of a given InfoType and returns a new and modified ResolveFilterModel. [...] + + +
+ +
+ switchSingle(InfoType infoType, String threat, ResolveFilterModel currentModel) + ResolveFilterModel + + + +
+
+ This is Method switches the filter boolean of a given InfoType and a given String threat and returns a new and modified ResolveFilterModel. + + +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterHandler/ResolveFilterHandler.html b/doc/api/main/ResolveFilterHandler/ResolveFilterHandler.html new file mode 100644 index 0000000..145e017 --- /dev/null +++ b/doc/api/main/ResolveFilterHandler/ResolveFilterHandler.html @@ -0,0 +1,132 @@ + + + + + + + + ResolveFilterHandler constructor - ResolveFilterHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ResolveFilterHandler
+ +
+ +
+ + +
+
+

ResolveFilterHandler constructor + Null safety +

+ +
+ ResolveFilterHandler() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterHandler/switchGroup.html b/doc/api/main/ResolveFilterHandler/switchGroup.html new file mode 100644 index 0000000..00a7aa8 --- /dev/null +++ b/doc/api/main/ResolveFilterHandler/switchGroup.html @@ -0,0 +1,169 @@ + + + + + + + + switchGroup method - ResolveFilterHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
switchGroup
+ +
+ +
+ + +
+
+

switchGroup method + Null safety +

+ +
+ + +ResolveFilterModel +switchGroup(
  1. InfoType infoType,
  2. +
  3. bool value,
  4. +
  5. ResolveFilterModel currentModel
  6. +
) + + + +
+ +
+

This is Method switches all the filter booleans of a given InfoType and returns a new and modified ResolveFilterModel.

+

Example: +{ +"InfoType.spyware":{ +"Test": false, +"Foo": true, +"bar": false +} +} +becomes if value = true +{ +"InfoType.spyware":{ +"Test": true, +"Foo": true, +"bar": true +} +}

+
+ + + +
+

Implementation

+
ResolveFilterModel switchGroup(
+    InfoType infoType, bool value, ResolveFilterModel currentModel) {
+  for (var keys in currentModel.filters[infoType]!.keys) {
+    currentModel.filters[infoType]![keys] = value;
+  }
+  return ResolveFilterModel(currentModel.filters, currentModel.lastScanned);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterHandler/switchSingle.html b/doc/api/main/ResolveFilterHandler/switchSingle.html new file mode 100644 index 0000000..1dc1fb7 --- /dev/null +++ b/doc/api/main/ResolveFilterHandler/switchSingle.html @@ -0,0 +1,152 @@ + + + + + + + + switchSingle method - ResolveFilterHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
switchSingle
+ +
+ +
+ + +
+
+

switchSingle method + Null safety +

+ +
+ + +ResolveFilterModel +switchSingle(
  1. InfoType infoType,
  2. +
  3. String threat,
  4. +
  5. ResolveFilterModel currentModel
  6. +
) + + + +
+ +
+

This is Method switches the filter boolean of a given InfoType and a given String threat and returns a new and modified ResolveFilterModel.

+
+ + + +
+

Implementation

+
ResolveFilterModel switchSingle(
+    InfoType infoType, String threat, ResolveFilterModel currentModel) {
+  currentModel.filters[infoType]![threat] =
+      !currentModel.filters[infoType]![threat]!;
+  return ResolveFilterModel(currentModel.filters, currentModel.lastScanned);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel-class.html b/doc/api/main/ResolveFilterModel-class.html new file mode 100644 index 0000000..93e7aff --- /dev/null +++ b/doc/api/main/ResolveFilterModel-class.html @@ -0,0 +1,398 @@ + + + + + + + + ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ResolveFilterModel
+ +
+ +
+ + +
+
+

ResolveFilterModel class + Null safety + +

+ + +
+

This ResolveFilterModel class is an entity that stores all relavant information about the ResolveFilter.

+
+ + + +
+

Constructors

+ +
+
+ ResolveFilterModel(Map<InfoType, Map<String, bool>> _filters, DateTime _lastScanned) +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ filters + Map<InfoType, Map<String, bool>> + +
+
+ +
read-only
+ +
+ +
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ lastScanned + DateTime + +
+
+ +
read-only
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ generateGroupedThreats() + Map<InfoType, List<String>> + + + +
+
+ This Method generates GroupedThreats which can then be used to update the ScanStatisticsModel. + + +
+ +
+ isAnythingSelected() + bool + + + +
+
+ This function checks if a single or more filters are true. + + +
+ +
+ isGroupedChecked(InfoType type) + bool + + + +
+
+ This functions checks if a specfic group is checked. + + +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ numberOfToResolvedThreats() + int + + + +
+
+ Returns the number of true values in the filter Map which corresponse to the amount of resolved threats and which is important to keep it in sync with the ScanStatisticsModel. + + +
+ +
+ numberOfUnresolvedThreats() + int + + + +
+
+ Returns the unresolved amounts of threats form the filter Map which is important to keep it in sync with the ScanStatisticsModel. + + +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ totalAmountOfThreats() + int + + + +
+
+ Returns the total amounts of threats form the filter Map which is important to keep it in sync with the ScanStatisticsModel. + + +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ + +
+

Static Methods

+
+
+ getFilterFromScanSatistic(ScanStatisticsModel model) + ResolveFilterModel + + + +
+
+ This is a static Factory Method which generates a ResolveFilterModel from a ScanStatisticsModel. + + +
+ +
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel/ResolveFilterModel.html b/doc/api/main/ResolveFilterModel/ResolveFilterModel.html new file mode 100644 index 0000000..7b84e65 --- /dev/null +++ b/doc/api/main/ResolveFilterModel/ResolveFilterModel.html @@ -0,0 +1,146 @@ + + + + + + + + ResolveFilterModel constructor - ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ResolveFilterModel
+ +
+ +
+ + +
+
+

ResolveFilterModel constructor + Null safety +

+ +
+ ResolveFilterModel(
  1. Map<InfoType, Map<String, bool>> _filters,
  2. +
  3. DateTime _lastScanned
  4. +
) +
+ + + + + +
+

Implementation

+
ResolveFilterModel(this._filters, this._lastScanned);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel/filters.html b/doc/api/main/ResolveFilterModel/filters.html new file mode 100644 index 0000000..f675ca1 --- /dev/null +++ b/doc/api/main/ResolveFilterModel/filters.html @@ -0,0 +1,152 @@ + + + + + + + + filters property - ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
filters
+ +
+ +
+ + +
+
+

filters property + Null safety +

+ + + +
+ +
+ Map<InfoType, Map<String, bool>> + filters + + +
+ + + + +
+

Implementation

+
Map<InfoType, Map<String, bool>> get filters => this._filters;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel/generateGroupedThreats.html b/doc/api/main/ResolveFilterModel/generateGroupedThreats.html new file mode 100644 index 0000000..f1d392a --- /dev/null +++ b/doc/api/main/ResolveFilterModel/generateGroupedThreats.html @@ -0,0 +1,168 @@ + + + + + + + + generateGroupedThreats method - ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
generateGroupedThreats
+ +
+ +
+ + +
+
+

generateGroupedThreats method + Null safety +

+ +
+ + +Map<InfoType, List<String>> +generateGroupedThreats() + + + +
+ +
+

This Method generates GroupedThreats which can then be used to update the ScanStatisticsModel.

+
+ + + +
+

Implementation

+
Map<InfoType, List<String>> generateGroupedThreats() {
+  Map<InfoType, List<String>> groupedThreats = Map();
+  for (InfoType type in InfoType.values) {
+    if (this._filters.containsKey(type)) {
+      List<String> threats = this
+          ._filters[type]!
+          .entries
+          .where((element) => !element.value)
+          .map((e) => e.key)
+          .toList();
+      groupedThreats[type] = threats;
+    } else {
+      groupedThreats[type] = [];
+    }
+  }
+  return groupedThreats;
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel/getFilterFromScanSatistic.html b/doc/api/main/ResolveFilterModel/getFilterFromScanSatistic.html new file mode 100644 index 0000000..5cdd152 --- /dev/null +++ b/doc/api/main/ResolveFilterModel/getFilterFromScanSatistic.html @@ -0,0 +1,168 @@ + + + + + + + + getFilterFromScanSatistic method - ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
getFilterFromScanSatistic
+ +
+ +
+ + +
+
+

getFilterFromScanSatistic method + Null safety +

+ +
+ + +ResolveFilterModel +getFilterFromScanSatistic(
  1. ScanStatisticsModel model
  2. +
) + + + +
+ +
+

This is a static Factory Method which generates a ResolveFilterModel from a ScanStatisticsModel.

+
+ + + +
+

Implementation

+
static ResolveFilterModel getFilterFromScanSatistic(
+    ScanStatisticsModel model) {
+  Map<InfoType, Map<String, bool>> filter = Map();
+  for (var entry in InfoType.values) {
+    Map<String, bool> values = Map();
+    var keys = model.groupedThreats[entry]!;
+    if (keys.length == 0) {
+      continue;
+    }
+    for (String threat in keys) {
+      values[threat] = true;
+    }
+    filter[entry] = values;
+  }
+  return ResolveFilterModel(filter, model.lastScanned);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel/isAnythingSelected.html b/doc/api/main/ResolveFilterModel/isAnythingSelected.html new file mode 100644 index 0000000..f5300d6 --- /dev/null +++ b/doc/api/main/ResolveFilterModel/isAnythingSelected.html @@ -0,0 +1,158 @@ + + + + + + + + isAnythingSelected method - ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
isAnythingSelected
+ +
+ +
+ + +
+
+

isAnythingSelected method + Null safety +

+ +
+ + +bool +isAnythingSelected() + + + +
+ +
+

This function checks if a single or more filters are true.

+
+ + + +
+

Implementation

+
bool isAnythingSelected() {
+  return this
+      ._filters
+      .values
+      .map((e) => e.values.reduce((value, element) => value || element))
+      .reduce((value, element) => value || element);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel/isGroupedChecked.html b/doc/api/main/ResolveFilterModel/isGroupedChecked.html new file mode 100644 index 0000000..ce31bbc --- /dev/null +++ b/doc/api/main/ResolveFilterModel/isGroupedChecked.html @@ -0,0 +1,158 @@ + + + + + + + + isGroupedChecked method - ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
isGroupedChecked
+ +
+ +
+ + +
+
+

isGroupedChecked method + Null safety +

+ +
+ + +bool +isGroupedChecked(
  1. InfoType type
  2. +
) + + + +
+ +
+

This functions checks if a specfic group is checked.

+
+ + + +
+

Implementation

+
bool isGroupedChecked(InfoType type) {
+  return this
+      ._filters[type]!
+      .values
+      .reduce((value, element) => value && element);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel/lastScanned.html b/doc/api/main/ResolveFilterModel/lastScanned.html new file mode 100644 index 0000000..2063715 --- /dev/null +++ b/doc/api/main/ResolveFilterModel/lastScanned.html @@ -0,0 +1,152 @@ + + + + + + + + lastScanned property - ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
lastScanned
+ +
+ +
+ + +
+
+

lastScanned property + Null safety +

+ + + +
+ +
+ DateTime + lastScanned + + +
+ + + + +
+

Implementation

+
DateTime get lastScanned => this._lastScanned;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel/numberOfToResolvedThreats.html b/doc/api/main/ResolveFilterModel/numberOfToResolvedThreats.html new file mode 100644 index 0000000..8ca3b35 --- /dev/null +++ b/doc/api/main/ResolveFilterModel/numberOfToResolvedThreats.html @@ -0,0 +1,158 @@ + + + + + + + + numberOfToResolvedThreats method - ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
numberOfToResolvedThreats
+ +
+ +
+ + +
+
+

numberOfToResolvedThreats method + Null safety +

+ +
+ + +int +numberOfToResolvedThreats() + + + +
+ +
+

Returns the number of true values in the filter Map which corresponse to the amount of resolved threats and which is important to keep it in sync with the ScanStatisticsModel.

+
+ + + +
+

Implementation

+
int numberOfToResolvedThreats() {
+  return this
+      ._filters
+      .values
+      .map((e) => e.values.where((element) => element).length)
+      .reduce((value, element) => value + element);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel/numberOfUnresolvedThreats.html b/doc/api/main/ResolveFilterModel/numberOfUnresolvedThreats.html new file mode 100644 index 0000000..2e79693 --- /dev/null +++ b/doc/api/main/ResolveFilterModel/numberOfUnresolvedThreats.html @@ -0,0 +1,158 @@ + + + + + + + + numberOfUnresolvedThreats method - ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
numberOfUnresolvedThreats
+ +
+ +
+ + +
+
+

numberOfUnresolvedThreats method + Null safety +

+ +
+ + +int +numberOfUnresolvedThreats() + + + +
+ +
+

Returns the unresolved amounts of threats form the filter Map which is important to keep it in sync with the ScanStatisticsModel.

+
+ + + +
+

Implementation

+
int numberOfUnresolvedThreats() {
+  return this
+      ._filters
+      .values
+      .map((e) => e.values.where((element) => !element).length)
+      .reduce((value, element) => value + element);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveFilterModel/totalAmountOfThreats.html b/doc/api/main/ResolveFilterModel/totalAmountOfThreats.html new file mode 100644 index 0000000..5a5066d --- /dev/null +++ b/doc/api/main/ResolveFilterModel/totalAmountOfThreats.html @@ -0,0 +1,158 @@ + + + + + + + + totalAmountOfThreats method - ResolveFilterModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
totalAmountOfThreats
+ +
+ +
+ + +
+
+

totalAmountOfThreats method + Null safety +

+ +
+ + +int +totalAmountOfThreats() + + + +
+ +
+

Returns the total amounts of threats form the filter Map which is important to keep it in sync with the ScanStatisticsModel.

+
+ + + +
+

Implementation

+
int totalAmountOfThreats() {
+  return this
+      ._filters
+      .values
+      .map((e) => e.values.length)
+      .reduce((value, element) => value + element);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveRoute-class.html b/doc/api/main/ResolveRoute-class.html new file mode 100644 index 0000000..ef6279f --- /dev/null +++ b/doc/api/main/ResolveRoute-class.html @@ -0,0 +1,436 @@ + + + + + + + + ResolveRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ResolveRoute
+ +
+ +
+ + +
+
+

ResolveRoute class + Null safety + +

+ + +
+

This ResolveRoute class is a StatefulWidget with the corresponding _ResolveRouteState class for the UI and is the "Resolution - Pending" page of the drawio sketch.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ ResolveRoute() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ createElement() + StatefulElement + + + +
+
+ Creates a StatefulElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ createState() + → _ResolveRouteState + + + +
+
+ Creates the mutable state for this widget at a given location in the tree. [...] +
override
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + +
+

Constants

+ +
+
+ routeName + → const String + + +
+
+ This field is the routName under which this page is registered in the app. + + +
+ '/resolve' +
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveRoute/ResolveRoute.html b/doc/api/main/ResolveRoute/ResolveRoute.html new file mode 100644 index 0000000..61dd5f0 --- /dev/null +++ b/doc/api/main/ResolveRoute/ResolveRoute.html @@ -0,0 +1,141 @@ + + + + + + + + ResolveRoute constructor - ResolveRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ResolveRoute
+ +
+ +
+ + +
+
+

ResolveRoute constructor + Null safety +

+ +
+ ResolveRoute() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveRoute/createState.html b/doc/api/main/ResolveRoute/createState.html new file mode 100644 index 0000000..049a6b6 --- /dev/null +++ b/doc/api/main/ResolveRoute/createState.html @@ -0,0 +1,171 @@ + + + + + + + + createState method - ResolveRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
createState
+ +
+ +
+ + +
+
+

createState method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +_ResolveRouteState +createState() + +
override
+ +
+ +
+

Creates the mutable state for this widget at a given location in the tree.

+

Subclasses should override this method to return a newly created +instance of their associated State subclass:

+
@override
+_MyState createState() => _MyState();
+
+

The framework can call this method multiple times over the lifetime of +a StatefulWidget. For example, if the widget is inserted into the tree +in multiple locations, the framework will create a separate State object +for each location. Similarly, if the widget is removed from the tree and +later inserted into the tree again, the framework will call createState +again to create a fresh State object, simplifying the lifecycle of +State objects.

+
+ + + +
+

Implementation

+
@override
+_ResolveRouteState createState() => _ResolveRouteState();
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ResolveRoute/routeName-constant.html b/doc/api/main/ResolveRoute/routeName-constant.html new file mode 100644 index 0000000..47db1b6 --- /dev/null +++ b/doc/api/main/ResolveRoute/routeName-constant.html @@ -0,0 +1,151 @@ + + + + + + + + routeName constant - ResolveRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
routeName
+ +
+ +
+ + +
+
+

routeName constant + Null safety +

+ +
+ String + const routeName + + +
+ +
+

This field is the routName under which this page is registered in the app.

+
+ + +
+

Implementation

+
static const String routeName = '/resolve';
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanInfo-class.html b/doc/api/main/ScanInfo-class.html new file mode 100644 index 0000000..a34084e --- /dev/null +++ b/doc/api/main/ScanInfo-class.html @@ -0,0 +1,438 @@ + + + + + + + + ScanInfo class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanInfo
+ +
+ +
+ + +
+
+

ScanInfo class + Null safety + +

+ + +
+

This ScanInfo class is used to display the threats shown in drawio sketch "Scan Log",

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ ScanInfo({Key? key, required InfoType infoType, required Map<InfoType, List<String>> groupedThreat}) +
+
+ +
const
+
+
+
+ +
+

Properties

+ +
+
+ groupedThreat + Map<InfoType, List<String>> + +
+
+ GroupedThreats of all, the build method lookes for the given InfoType. +
final
+ +
+ +
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ infoType + InfoType + +
+
+ InfoType which should get displayed +
final
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This method builds a Column with the title of the InfoType and the Threats in a Column below. [...] +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanInfo/ScanInfo.html b/doc/api/main/ScanInfo/ScanInfo.html new file mode 100644 index 0000000..9772983 --- /dev/null +++ b/doc/api/main/ScanInfo/ScanInfo.html @@ -0,0 +1,150 @@ + + + + + + + + ScanInfo constructor - ScanInfo class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanInfo
+ +
+ +
+ + +
+
+

ScanInfo constructor + Null safety +

+ +
const + ScanInfo(
  1. {Key? key,
  2. +
  3. required InfoType infoType,
  4. +
  5. required Map<InfoType, List<String>> groupedThreat}
  6. +
) +
+ + + + + +
+

Implementation

+
const ScanInfo(
+    {Key? key, required this.infoType, required this.groupedThreat})
+    : super(key: key);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanInfo/build.html b/doc/api/main/ScanInfo/build.html new file mode 100644 index 0000000..e4bc9d7 --- /dev/null +++ b/doc/api/main/ScanInfo/build.html @@ -0,0 +1,201 @@ + + + + + + + + build method - ScanInfo class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This method builds a Column with the title of the InfoType and the Threats in a Column below.

+

All threats are colored red and InfoTypes that don't occur are colored green

+
+ + + +
+

Implementation

+
@override
+Widget build(BuildContext context) {
+  return Column(
+    mainAxisAlignment: MainAxisAlignment.start,
+    crossAxisAlignment: CrossAxisAlignment.start,
+    children: [
+      Padding(
+        padding: EdgeInsets.only(top: 0),
+        child: Row(
+          children: [
+            Text(
+              knowledgeBaseDummy[infoType]!['name']!,
+              style: TextStyle(
+                  fontWeight: FontWeight.bold,
+                  // Checks if their are threats and adjust color accordingly
+                  color: this.groupedThreat[infoType]!.length > 0
+                      ? Colors.redAccent
+                      : Colors.greenAccent),
+            ),
+            Spacer(),
+            IconButton(
+                onPressed: () {
+                  Navigator.pushNamed(context, KnowledgeBaseRoute.routeName,
+                      arguments: infoType);
+                },
+                icon: Icon(Icons.info_outline)),
+          ],
+        ),
+      ),
+      // Adds all the threats this may need to be scrollabel if their are more threats identified this needs to change later
+      ...(this.groupedThreat[infoType]!.map(
+            (e) => Padding(
+              padding: EdgeInsets.only(left: 12),
+              child: Text(
+                "- " + e,
+                style: TextStyle(color: Colors.redAccent),
+              ),
+            ),
+          )),
+    ],
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanInfo/groupedThreat.html b/doc/api/main/ScanInfo/groupedThreat.html new file mode 100644 index 0000000..458db37 --- /dev/null +++ b/doc/api/main/ScanInfo/groupedThreat.html @@ -0,0 +1,151 @@ + + + + + + + + groupedThreat property - ScanInfo class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
groupedThreat
+ +
+ +
+ + +
+
+

groupedThreat property + Null safety +

+ +
+ Map<InfoType, List<String>> + groupedThreat +
final
+ +
+ +
+

GroupedThreats of all, the build method lookes for the given InfoType.

+
+ + +
+

Implementation

+
final Map<InfoType, List<String>> groupedThreat;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanInfo/infoType.html b/doc/api/main/ScanInfo/infoType.html new file mode 100644 index 0000000..8d579ab --- /dev/null +++ b/doc/api/main/ScanInfo/infoType.html @@ -0,0 +1,151 @@ + + + + + + + + infoType property - ScanInfo class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
infoType
+ +
+ +
+ + +
+
+

infoType property + Null safety +

+ +
+ InfoType + infoType +
final
+ +
+ +
+

InfoType which should get displayed

+
+ + +
+

Implementation

+
final InfoType infoType;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanLogRoute-class.html b/doc/api/main/ScanLogRoute-class.html new file mode 100644 index 0000000..72195ef --- /dev/null +++ b/doc/api/main/ScanLogRoute-class.html @@ -0,0 +1,437 @@ + + + + + + + + ScanLogRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanLogRoute
+ +
+ +
+ + +
+
+

ScanLogRoute class + Null safety + +

+ + +
+

This ScanLogRoute class represents the "Scan - Log" page in the drawio sketch v4.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ ScanLogRoute() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This build Method gets called to build the UI. This combines the +components into a Scaffold. +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + +
+

Constants

+ +
+
+ routeName + → const String + + +
+
+ This field is the routName under which this page is registered in the app. + + +
+ '/scanlog' +
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanLogRoute/ScanLogRoute.html b/doc/api/main/ScanLogRoute/ScanLogRoute.html new file mode 100644 index 0000000..202e5ed --- /dev/null +++ b/doc/api/main/ScanLogRoute/ScanLogRoute.html @@ -0,0 +1,141 @@ + + + + + + + + ScanLogRoute constructor - ScanLogRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanLogRoute
+ +
+ +
+ + +
+
+

ScanLogRoute constructor + Null safety +

+ +
+ ScanLogRoute() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanLogRoute/build.html b/doc/api/main/ScanLogRoute/build.html new file mode 100644 index 0000000..cf70a05 --- /dev/null +++ b/doc/api/main/ScanLogRoute/build.html @@ -0,0 +1,220 @@ + + + + + + + + build method - ScanLogRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This build Method gets called to build the UI. This combines the +components into a Scaffold.

+
+ + + +
+

Implementation

+
@override
+Widget build(BuildContext context) {
+  return Scaffold(
+    appBar: _buildAppBar(context),
+    body: Center(
+      child: Column(
+        children: [
+          StreamBuilder(
+            stream: ScanStatisticsBloc.currentBloc.bloc,
+            builder: (context, snapshot) {
+              if (snapshot.hasData && snapshot.data != null) {
+                ScanStatisticsModel model =
+                    (snapshot.data as ScanStatisticsModel);
+                return Column(
+                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
+                  crossAxisAlignment: CrossAxisAlignment.center,
+                  children: [
+                    SizedBox(height: 80),
+                    CardDisplay(
+                      padding: _padding,
+                      elevation: _elevation,
+                      title: Text(
+                        "Scan: " + model.lastScanned.toString().split(".")[0],
+                        style: _titleStyle,
+                      ),
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        mainAxisAlignment: MainAxisAlignment.start,
+                        children: [
+                          Text(
+                            "Threats:",
+                            style: TextStyle(
+                              fontWeight: FontWeight.bold,
+                            ),
+                          ),
+                          _buildThreatView(context, model)
+                        ],
+                      ),
+                    ),
+                    DefaultElevatedButton(
+                      onPressed: () {
+                        Navigator.pushNamed(
+                            context, ConfigureResolutionRoute.routeName);
+                      },
+                      name: "Resolve Threats",
+                    ),
+                    SizedBox(
+                      height: 80,
+                    ),
+                  ],
+                );
+              } else {
+                return Text("Error");
+              }
+            },
+          ),
+        ],
+      ),
+    ),
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanLogRoute/routeName-constant.html b/doc/api/main/ScanLogRoute/routeName-constant.html new file mode 100644 index 0000000..c618010 --- /dev/null +++ b/doc/api/main/ScanLogRoute/routeName-constant.html @@ -0,0 +1,151 @@ + + + + + + + + routeName constant - ScanLogRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
routeName
+ +
+ +
+ + +
+
+

routeName constant + Null safety +

+ +
+ String + const routeName + + +
+ +
+

This field is the routName under which this page is registered in the app.

+
+ + +
+

Implementation

+
static const String routeName = '/scanlog';
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanResolutionSwitch-class.html b/doc/api/main/ScanResolutionSwitch-class.html new file mode 100644 index 0000000..a33ac02 --- /dev/null +++ b/doc/api/main/ScanResolutionSwitch-class.html @@ -0,0 +1,435 @@ + + + + + + + + ScanResolutionSwitch class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanResolutionSwitch
+ +
+ +
+ + +
+
+

ScanResolutionSwitch class + Null safety + +

+ + + + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ ScanResolutionSwitch({Key? key, required InfoType infoType, required Map<InfoType, List<String>> groupedThreats}) +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ groupedThreats + Map<InfoType, List<String>> + +
+
+ Groupedthreats from a ScanStatisticsModel +
final
+ +
+ +
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ infoType + InfoType + +
+
+ InfoType that should be used to identify the Threats +
final
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This method builds a Switch parent for a InfoType and a subswitch for all the +threats belonging to that specific InfoType. +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanResolutionSwitch/ScanResolutionSwitch.html b/doc/api/main/ScanResolutionSwitch/ScanResolutionSwitch.html new file mode 100644 index 0000000..6529a57 --- /dev/null +++ b/doc/api/main/ScanResolutionSwitch/ScanResolutionSwitch.html @@ -0,0 +1,150 @@ + + + + + + + + ScanResolutionSwitch constructor - ScanResolutionSwitch class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanResolutionSwitch
+ +
+ +
+ + +
+
+

ScanResolutionSwitch constructor + Null safety +

+ +
+ ScanResolutionSwitch(
  1. {Key? key,
  2. +
  3. required InfoType infoType,
  4. +
  5. required Map<InfoType, List<String>> groupedThreats}
  6. +
) +
+ + + + + +
+

Implementation

+
ScanResolutionSwitch(
+    {Key? key, required this.infoType, required this.groupedThreats})
+    : super(key: key);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanResolutionSwitch/build.html b/doc/api/main/ScanResolutionSwitch/build.html new file mode 100644 index 0000000..6d12d07 --- /dev/null +++ b/doc/api/main/ScanResolutionSwitch/build.html @@ -0,0 +1,232 @@ + + + + + + + + build method - ScanResolutionSwitch class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This method builds a Switch parent for a InfoType and a subswitch for all the +threats belonging to that specific InfoType.

+
+ + + +
+

Implementation

+
@override
+Widget build(BuildContext context) {
+  return Column(
+    children: [
+      StreamBuilder<Object>(
+          stream: ResolveFilterBloc.currentBloc.bloc,
+          builder: (context, snapshot) {
+            try {
+              ResolveFilterModel model = snapshot.data as ResolveFilterModel;
+              return ExpansionTile(
+                /// Header with [InfoType] and in the expansion are the Threats belonging to that [InfoType]
+                leading: Checkbox(
+                  value: model.isGroupedChecked(infoType),
+                  onChanged: (e) {
+                    ResolveFilterBloc.currentBloc
+                        .updateGroup(infoType, e!, model);
+                  },
+                ),
+                title: Row(
+                  children: [
+                    Text(knowledgeBaseDummy[infoType]!['name']!),
+                    Spacer(),
+                    IconButton(
+                      icon: Icon(Icons.info_outline),
+                      onPressed: () {
+                        Navigator.of(context).pushNamed(
+                            KnowledgeBaseRoute.routeName,
+                            arguments: infoType);
+                      },
+                    ),
+                  ],
+                ),
+                children: [
+                  Divider(
+                    thickness: 1.2,
+                  ),
+                  ...groupedThreats[infoType]!.map(
+                    (threat) => ListTile(
+                      /// Builds the ListTile with corresponding to the infotype and the threat
+                      dense: true,
+                      leading: Checkbox(
+                        value: model.filters[infoType]![threat]!,
+                        onChanged: (e) {
+                          ResolveFilterBloc.currentBloc
+                              .updateSingle(infoType, threat, model);
+                        },
+                      ),
+                      title: Text(threat),
+                      subtitle: Padding(
+                        padding: const EdgeInsets.only(left: 12.0),
+                        child: Column(
+                          mainAxisAlignment: MainAxisAlignment.start,
+                          crossAxisAlignment: CrossAxisAlignment.start,
+
+                          /// Hard coded Actions
+                          children: [
+                            Text("recommended action"),
+                            Text("1. Move to quarantine"),
+                            Text("2. Force uninstall")
+                          ],
+                        ),
+                      ),
+                    ),
+                  ),
+                ],
+              );
+            } catch (e) {
+              return Text("Error");
+            }
+          }),
+    ],
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanResolutionSwitch/createState.html b/doc/api/main/ScanResolutionSwitch/createState.html new file mode 100644 index 0000000..c99ec34 --- /dev/null +++ b/doc/api/main/ScanResolutionSwitch/createState.html @@ -0,0 +1,171 @@ + + + + + + + + createState method - ScanResolutionSwitch class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
createState
+ +
+ +
+ + +
+
+

createState method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +_ScanResolutionSwitchState +createState() + +
override
+ +
+ +
+

Creates the mutable state for this widget at a given location in the tree.

+

Subclasses should override this method to return a newly created +instance of their associated State subclass:

+
@override
+_MyState createState() => _MyState();
+
+

The framework can call this method multiple times over the lifetime of +a StatefulWidget. For example, if the widget is inserted into the tree +in multiple locations, the framework will create a separate State object +for each location. Similarly, if the widget is removed from the tree and +later inserted into the tree again, the framework will call createState +again to create a fresh State object, simplifying the lifecycle of +State objects.

+
+ + + +
+

Implementation

+
@override
+_ScanResolutionSwitchState createState() => _ScanResolutionSwitchState();
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanResolutionSwitch/groupedThreats.html b/doc/api/main/ScanResolutionSwitch/groupedThreats.html new file mode 100644 index 0000000..6ac102b --- /dev/null +++ b/doc/api/main/ScanResolutionSwitch/groupedThreats.html @@ -0,0 +1,151 @@ + + + + + + + + groupedThreats property - ScanResolutionSwitch class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
groupedThreats
+ +
+ +
+ + +
+
+

groupedThreats property + Null safety +

+ +
+ Map<InfoType, List<String>> + groupedThreats +
final
+ +
+ +
+

Groupedthreats from a ScanStatisticsModel

+
+ + +
+

Implementation

+
final Map<InfoType, List<String>> groupedThreats;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanResolutionSwitch/infoType.html b/doc/api/main/ScanResolutionSwitch/infoType.html new file mode 100644 index 0000000..cb0dd57 --- /dev/null +++ b/doc/api/main/ScanResolutionSwitch/infoType.html @@ -0,0 +1,151 @@ + + + + + + + + infoType property - ScanResolutionSwitch class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
infoType
+ +
+ +
+ + +
+
+

infoType property + Null safety +

+ +
+ InfoType + infoType +
final
+ +
+ +
+

InfoType that should be used to identify the Threats

+
+ + +
+

Implementation

+
final InfoType infoType;
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanRoute-class.html b/doc/api/main/ScanRoute-class.html new file mode 100644 index 0000000..3e8ffdd --- /dev/null +++ b/doc/api/main/ScanRoute-class.html @@ -0,0 +1,436 @@ + + + + + + + + ScanRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanRoute
+ +
+ +
+ + +
+
+

ScanRoute class + Null safety + +

+ + +
+

This ScanRoute class is a StatefulWidget with the corresponding _ScanRouteState class for the UI and is the "Scan - Pending" page in the drawio sketch.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ ScanRoute() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ createElement() + StatefulElement + + + +
+
+ Creates a StatefulElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ createState() + → _ScanRouteState + + + +
+
+ Creates the mutable state for this widget at a given location in the tree. [...] +
override
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + +
+

Constants

+ +
+
+ routeName + → const String + + +
+
+ This field is the routName under which this page is registered in the app. + + +
+ '/scan' +
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanRoute/ScanRoute.html b/doc/api/main/ScanRoute/ScanRoute.html new file mode 100644 index 0000000..33a3e97 --- /dev/null +++ b/doc/api/main/ScanRoute/ScanRoute.html @@ -0,0 +1,141 @@ + + + + + + + + ScanRoute constructor - ScanRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanRoute
+ +
+ +
+ + +
+
+

ScanRoute constructor + Null safety +

+ +
+ ScanRoute() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanRoute/createState.html b/doc/api/main/ScanRoute/createState.html new file mode 100644 index 0000000..75e68cc --- /dev/null +++ b/doc/api/main/ScanRoute/createState.html @@ -0,0 +1,171 @@ + + + + + + + + createState method - ScanRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
createState
+ +
+ +
+ + +
+
+

createState method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +_ScanRouteState +createState() + +
override
+ +
+ +
+

Creates the mutable state for this widget at a given location in the tree.

+

Subclasses should override this method to return a newly created +instance of their associated State subclass:

+
@override
+_MyState createState() => _MyState();
+
+

The framework can call this method multiple times over the lifetime of +a StatefulWidget. For example, if the widget is inserted into the tree +in multiple locations, the framework will create a separate State object +for each location. Similarly, if the widget is removed from the tree and +later inserted into the tree again, the framework will call createState +again to create a fresh State object, simplifying the lifecycle of +State objects.

+
+ + + +
+

Implementation

+
@override
+_ScanRouteState createState() => _ScanRouteState();
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanRoute/routeName-constant.html b/doc/api/main/ScanRoute/routeName-constant.html new file mode 100644 index 0000000..630f38b --- /dev/null +++ b/doc/api/main/ScanRoute/routeName-constant.html @@ -0,0 +1,151 @@ + + + + + + + + routeName constant - ScanRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
routeName
+ +
+ +
+ + +
+
+

routeName constant + Null safety +

+ +
+ String + const routeName + + +
+ +
+

This field is the routName under which this page is registered in the app.

+
+ + +
+

Implementation

+
static const String routeName = '/scan';
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatistics-class.html b/doc/api/main/ScanStatistics-class.html new file mode 100644 index 0000000..c1fb7eb --- /dev/null +++ b/doc/api/main/ScanStatistics-class.html @@ -0,0 +1,413 @@ + + + + + + + + ScanStatistics class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanStatistics
+ +
+ +
+ + +
+
+

ScanStatistics class + Null safety + +

+ + +
+

This ScanStatistics class displays the data from the ScanStatisticsModel as shwon in drawio sketch "Main(a-x,b-x), Profile(a-y,b-y)".

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ ScanStatistics() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This method reads the ScanStatisticsModel from the ScanStatisticsBloc and displays its value into a card. +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatistics/ScanStatistics.html b/doc/api/main/ScanStatistics/ScanStatistics.html new file mode 100644 index 0000000..c27e820 --- /dev/null +++ b/doc/api/main/ScanStatistics/ScanStatistics.html @@ -0,0 +1,139 @@ + + + + + + + + ScanStatistics constructor - ScanStatistics class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanStatistics
+ +
+ +
+ + +
+
+

ScanStatistics constructor + Null safety +

+ +
+ ScanStatistics() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatistics/build.html b/doc/api/main/ScanStatistics/build.html new file mode 100644 index 0000000..d654b2d --- /dev/null +++ b/doc/api/main/ScanStatistics/build.html @@ -0,0 +1,218 @@ + + + + + + + + build method - ScanStatistics class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This method reads the ScanStatisticsModel from the ScanStatisticsBloc and displays its value into a card.

+
+ + + +
+

Implementation

+
@override
+Widget build(BuildContext context) {
+  return Column(
+    children: [
+      StreamBuilder(
+        stream: ScanStatisticsBloc.currentBloc.bloc,
+        builder: (context, snapshot) {
+          if (snapshot.hasData) {
+            ScanStatisticsModel model =
+                (snapshot.data as ScanStatisticsModel);
+            return Column(
+              children: [
+                CardDisplay(
+                  elevation: _elevation,
+                  padding: _padding,
+                  title: Text(
+                    "Last Scan: " +
+                        model.lastScanned.toString().split(".")[0],
+                    style: _titleStyle,
+                  ),
+                  child: Column(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    mainAxisAlignment: MainAxisAlignment.start,
+                    children: [
+                      Text(
+                        "Threats identified: " +
+                            model.identifiedThreats.toString(),
+                        style: TextStyle(
+                          fontWeight: FontWeight.bold,
+                          fontSize: _threatTextSize,
+                        ),
+                      ),
+                      Text(
+                        "Threats resolved: " +
+                            model.resolvedThreats.toString(),
+                        style: TextStyle(
+                          fontWeight: FontWeight.bold,
+                          fontSize: _threatTextSize,
+                          color: _threatResolved,
+                        ),
+                      ),
+                      Text(
+                        "Threats unresolved: " +
+                            model.unresolvedThreats.toString(),
+                        style: TextStyle(
+                          fontWeight: FontWeight.bold,
+                          fontSize: _threatTextSize,
+                          color: _threatUnresolved,
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+              ],
+            );
+          }
+          return Center(child: Text("You haven't scanned your device..."));
+        },
+      ),
+    ],
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc-class.html b/doc/api/main/ScanStatisticsBloc-class.html new file mode 100644 index 0000000..808aad4 --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc-class.html @@ -0,0 +1,385 @@ + + + + + + + + ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanStatisticsBloc
+ +
+ +
+ + +
+
+

ScanStatisticsBloc class + Null safety + +

+ + +
+

This ScanStatisticsBloc class handles the state of the ScanStatisticsModel.

+

There are mutation functions (updateStatistics,resolve,updateStatisticsfromModel) to mutate the state of the current ScanStatisticsModel.

+
ScanStatisticsBloc.currentBloc.updateStatistics(10,8,2,DateTime.now(),Map());
+
+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ + +
+

Properties

+ +
+
+ bloc + → dynamic + +
+
+ Getter to get the current stream +
read-only, inherited
+ +
+ +
+ handler + ScanStatisticsHandler + +
+
+ Initializes the ScanStatisticsHandler which performs all the state changes on the ScanStatisticsModel. +
final
+ +
+ +
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ publisher + BehaviorSubject<ScanStatisticsModel> + +
+
+ This BehaviorSubject Object has the Stream Property we publish unto. +
@protected, final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ dispose() + → void + + + +
+
+ +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ resolve(ResolveFilterModel resolveModel) + → void + + + +
+
+ Resolves only threats which are specified in the ResolveFilterModel and notifies the ResolveFilterBloc after. + + +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ updateStatistics(int identifiedThreats, int resolvedThreats, int unresolvedThreats, DateTime lastScanned, Map<InfoType, List<String>> groupedThreats) + → void + + + +
+
+ Updates the the ScanStatisticsModel by specific values which are given as paramters and publishes it to the stream. + + +
+ +
+ updateStatisticsfromModel(ScanStatisticsModel model) + → void + + + +
+
+ Sets ScanStatisticsModel to a deepcopy of the new ScanStatisticsModel. + + +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ +
+

Static Properties

+ +
+
+ currentBloc + ScanStatisticsBloc + +
+
+ The current instance of the Singleton. +
final
+ +
+ +
+
+ + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc/ScanStatisticsBloc.html b/doc/api/main/ScanStatisticsBloc/ScanStatisticsBloc.html new file mode 100644 index 0000000..473cb76 --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc/ScanStatisticsBloc.html @@ -0,0 +1,135 @@ + + + + + + + + ScanStatisticsBloc constructor - ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanStatisticsBloc
+ +
+ +
+ + +
+
+

ScanStatisticsBloc constructor + Null safety +

+ +
+ ScanStatisticsBloc() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc/bloc.html b/doc/api/main/ScanStatisticsBloc/bloc.html new file mode 100644 index 0000000..fc98473 --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc/bloc.html @@ -0,0 +1,149 @@ + + + + + + + + bloc property - ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
bloc
+ +
+ +
+ + +
+
+

bloc property + Null safety +

+ + + +
+ +
+ dynamic + bloc +
inherited
+ +
+ + + + +
+

Implementation

+
get bloc => this.publisher.stream;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc/currentBloc.html b/doc/api/main/ScanStatisticsBloc/currentBloc.html new file mode 100644 index 0000000..46cf946 --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc/currentBloc.html @@ -0,0 +1,147 @@ + + + + + + + + currentBloc property - ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
currentBloc
+ +
+ +
+ + +
+
+

currentBloc property + Null safety +

+ +
+ ScanStatisticsBloc + currentBloc +
final
+ +
+ +
+

The current instance of the Singleton.

+
+ + +
+

Implementation

+
static final ScanStatisticsBloc currentBloc = ScanStatisticsBloc._();
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc/dispose.html b/doc/api/main/ScanStatisticsBloc/dispose.html new file mode 100644 index 0000000..36f8d09 --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc/dispose.html @@ -0,0 +1,148 @@ + + + + + + + + dispose method - ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
dispose
+ +
+ +
+ + +
+
+

dispose method + Null safety +

+ +
+ + +dynamic +dispose() + +
inherited
+ +
+ + + + +
+

Implementation

+
dispose() {
+  this.publisher.close();
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc/handler.html b/doc/api/main/ScanStatisticsBloc/handler.html new file mode 100644 index 0000000..c998ea0 --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc/handler.html @@ -0,0 +1,147 @@ + + + + + + + + handler property - ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
handler
+ +
+ +
+ + +
+
+

handler property + Null safety +

+ +
+ ScanStatisticsHandler + handler +
final
+ +
+ +
+

Initializes the ScanStatisticsHandler which performs all the state changes on the ScanStatisticsModel.

+
+ + +
+

Implementation

+
final handler = ScanStatisticsHandler();
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc/publisher.html b/doc/api/main/ScanStatisticsBloc/publisher.html new file mode 100644 index 0000000..d567056 --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc/publisher.html @@ -0,0 +1,149 @@ + + + + + + + + publisher property - ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
publisher
+ +
+ +
+ + +
+
+

publisher property + Null safety +

+ +
+ BehaviorSubject<ScanStatisticsModel> + publisher +
@protected, final, inherited
+ +
+ +
+

This ´BehaviorSubject´ Object has the Stream Property we publish unto

+
+ + +
+

Implementation

+
@protected
+// ignore: close_sinks
+final BehaviorSubject<T> publisher = BehaviorSubject<T>();
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc/resolve.html b/doc/api/main/ScanStatisticsBloc/resolve.html new file mode 100644 index 0000000..3e495f6 --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc/resolve.html @@ -0,0 +1,155 @@ + + + + + + + + resolve method - ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
resolve
+ +
+ +
+ + +
+
+

resolve method + Null safety +

+ +
+ + +void +resolve(
  1. ResolveFilterModel resolveModel
  2. +
) + + + +
+ +
+

Resolves only threats which are specified in the ResolveFilterModel and notifies the ResolveFilterBloc after.

+
+ + + +
+

Implementation

+
void resolve(ResolveFilterModel resolveModel) {
+  ScanStatisticsModel newModel =
+      this.handler.updateStatisticsfromResolveModel(resolveModel);
+  ResolveFilterBloc.currentBloc.setfromStatistics(newModel);
+  this.publisher.add(newModel);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc/statistics.html b/doc/api/main/ScanStatisticsBloc/statistics.html new file mode 100644 index 0000000..0bf75fa --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc/statistics.html @@ -0,0 +1,150 @@ + + + + + + + + statistics property - ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
statistics
+ +
+ +
+ + +
+
+

statistics property + Null safety +

+ + + +
+ +
+ dynamic + statistics + + +
+ + +
+

Listener

+
+ + +
+

Implementation

+
get statistics => this._statisticPublisher.stream;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc/updateStatistics.html b/doc/api/main/ScanStatisticsBloc/updateStatistics.html new file mode 100644 index 0000000..1a45448 --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc/updateStatistics.html @@ -0,0 +1,168 @@ + + + + + + + + updateStatistics method - ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
updateStatistics
+ +
+ +
+ + +
+
+

updateStatistics method + Null safety +

+ +
+ + +void +updateStatistics(
  1. int identifiedThreats,
  2. +
  3. int resolvedThreats,
  4. +
  5. int unresolvedThreats,
  6. +
  7. DateTime lastScanned,
  8. +
  9. Map<InfoType, List<String>> groupedThreats
  10. +
) + + + +
+ +
+

Updates the the ScanStatisticsModel by specific values which are given as paramters and publishes it to the stream.

+
+ + + +
+

Implementation

+
void updateStatistics(
+    int identifiedThreats,
+    int resolvedThreats,
+    int unresolvedThreats,
+    DateTime lastScanned,
+    Map<InfoType, List<String>> groupedThreats) {
+  ScanStatisticsModel newStat = this.handler.updateStatistics(
+      identifiedThreats,
+      resolvedThreats,
+      unresolvedThreats,
+      lastScanned,
+      groupedThreats);
+  ResolveFilterBloc.currentBloc.setfromStatistics(newStat);
+  this.publisher.add(newStat);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsBloc/updateStatisticsfromModel.html b/doc/api/main/ScanStatisticsBloc/updateStatisticsfromModel.html new file mode 100644 index 0000000..e9c28e4 --- /dev/null +++ b/doc/api/main/ScanStatisticsBloc/updateStatisticsfromModel.html @@ -0,0 +1,154 @@ + + + + + + + + updateStatisticsfromModel method - ScanStatisticsBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
updateStatisticsfromModel
+ +
+ +
+ + +
+
+

updateStatisticsfromModel method + Null safety +

+ +
+ + +void +updateStatisticsfromModel(
  1. ScanStatisticsModel model
  2. +
) + + + +
+ +
+

Sets ScanStatisticsModel to a deepcopy of the new ScanStatisticsModel.

+
+ + + +
+

Implementation

+
void updateStatisticsfromModel(ScanStatisticsModel model) {
+  ScanStatisticsModel newStat = this.handler.updateStatisticsfromModel(model);
+  ResolveFilterBloc.currentBloc.setfromStatistics(newStat);
+  this.publisher.add(newStat);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsHandler-class.html b/doc/api/main/ScanStatisticsHandler-class.html new file mode 100644 index 0000000..1e94193 --- /dev/null +++ b/doc/api/main/ScanStatisticsHandler-class.html @@ -0,0 +1,315 @@ + + + + + + + + ScanStatisticsHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanStatisticsHandler
+ +
+ +
+ + +
+
+

ScanStatisticsHandler class + Null safety + +

+ + +
+

This ScanStatisticsHandler class has the implementation for all the mutations in the ScanStatisticsBloc.

+ +
+ + + +
+

Constructors

+ +
+
+ ScanStatisticsHandler() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ updateStatistics(int identifiedThreats, int resolvedThreats, int unresolvedThreats, DateTime lastScanned, Map<InfoType, List<String>> groupedThreats) + ScanStatisticsModel + + + +
+
+ This method just creates a new ScanStatisticsModel from the given parameters. + + +
+ +
+ updateStatisticsfromModel(ScanStatisticsModel model) + ScanStatisticsModel + + + +
+
+ This method just creates a deepcopy of a ScanStatisticsModel and returns it. + + +
+ +
+ updateStatisticsfromResolveModel(ResolveFilterModel resolveModel) + ScanStatisticsModel + + + +
+
+ This method creates a ScanStatisticsModel from a ResolveFilterModel and calculates the parameters with functions provided by the ResolveFilterModel. + + +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsHandler/ScanStatisticsHandler.html b/doc/api/main/ScanStatisticsHandler/ScanStatisticsHandler.html new file mode 100644 index 0000000..ff0b5cc --- /dev/null +++ b/doc/api/main/ScanStatisticsHandler/ScanStatisticsHandler.html @@ -0,0 +1,133 @@ + + + + + + + + ScanStatisticsHandler constructor - ScanStatisticsHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanStatisticsHandler
+ +
+ +
+ + +
+
+

ScanStatisticsHandler constructor + Null safety +

+ +
+ ScanStatisticsHandler() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsHandler/updateStatistics.html b/doc/api/main/ScanStatisticsHandler/updateStatistics.html new file mode 100644 index 0000000..81b61b2 --- /dev/null +++ b/doc/api/main/ScanStatisticsHandler/updateStatistics.html @@ -0,0 +1,158 @@ + + + + + + + + updateStatistics method - ScanStatisticsHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
updateStatistics
+ +
+ +
+ + +
+
+

updateStatistics method + Null safety +

+ +
+ + +ScanStatisticsModel +updateStatistics(
  1. int identifiedThreats,
  2. +
  3. int resolvedThreats,
  4. +
  5. int unresolvedThreats,
  6. +
  7. DateTime lastScanned,
  8. +
  9. Map<InfoType, List<String>> groupedThreats
  10. +
) + + + +
+ +
+

This method just creates a new ScanStatisticsModel from the given parameters.

+
+ + + +
+

Implementation

+
ScanStatisticsModel updateStatistics(
+    int identifiedThreats,
+    int resolvedThreats,
+    int unresolvedThreats,
+    DateTime lastScanned,
+    Map<InfoType, List<String>> groupedThreats) {
+  return ScanStatisticsModel(identifiedThreats, resolvedThreats,
+      unresolvedThreats, lastScanned, groupedThreats);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsHandler/updateStatisticsfromModel.html b/doc/api/main/ScanStatisticsHandler/updateStatisticsfromModel.html new file mode 100644 index 0000000..e021390 --- /dev/null +++ b/doc/api/main/ScanStatisticsHandler/updateStatisticsfromModel.html @@ -0,0 +1,149 @@ + + + + + + + + updateStatisticsfromModel method - ScanStatisticsHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
updateStatisticsfromModel
+ +
+ +
+ + +
+
+

updateStatisticsfromModel method + Null safety +

+ +
+ + +ScanStatisticsModel +updateStatisticsfromModel(
  1. ScanStatisticsModel model
  2. +
) + + + +
+ +
+

This method just creates a deepcopy of a ScanStatisticsModel and returns it.

+
+ + + +
+

Implementation

+
ScanStatisticsModel updateStatisticsfromModel(ScanStatisticsModel model) {
+  return ScanStatisticsModel(model.identifiedThreats, model.resolvedThreats,
+      model.unresolvedThreats, model.lastScanned, model.groupedThreats);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsHandler/updateStatisticsfromResolveModel.html b/doc/api/main/ScanStatisticsHandler/updateStatisticsfromResolveModel.html new file mode 100644 index 0000000..100f4f2 --- /dev/null +++ b/doc/api/main/ScanStatisticsHandler/updateStatisticsfromResolveModel.html @@ -0,0 +1,154 @@ + + + + + + + + updateStatisticsfromResolveModel method - ScanStatisticsHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
updateStatisticsfromResolveModel
+ +
+ +
+ + +
+
+

updateStatisticsfromResolveModel method + Null safety +

+ +
+ + +ScanStatisticsModel +updateStatisticsfromResolveModel(
  1. ResolveFilterModel resolveModel
  2. +
) + + + +
+ +
+

This method creates a ScanStatisticsModel from a ResolveFilterModel and calculates the parameters with functions provided by the ResolveFilterModel.

+
+ + + +
+

Implementation

+
ScanStatisticsModel updateStatisticsfromResolveModel(
+    ResolveFilterModel resolveModel) {
+  return ScanStatisticsModel(
+      resolveModel.totalAmountOfThreats(),
+      resolveModel.numberOfToResolvedThreats(),
+      resolveModel.numberOfUnresolvedThreats(),
+      resolveModel.lastScanned,
+      resolveModel.generateGroupedThreats());
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsModel-class.html b/doc/api/main/ScanStatisticsModel-class.html new file mode 100644 index 0000000..f99e88c --- /dev/null +++ b/doc/api/main/ScanStatisticsModel-class.html @@ -0,0 +1,373 @@ + + + + + + + + ScanStatisticsModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanStatisticsModel
+ +
+ +
+ + +
+
+

ScanStatisticsModel class + Null safety + +

+ + +
+

This ScanStatisticsModel class represents a scanlog with all the information that a supposed scan could deliver.

+
+ + + +
+

Constructors

+ +
+
+ ScanStatisticsModel(int _identifiedThreats, int _resolvedThreats, int _unresolvedThreats, DateTime _lastScanned, Map<InfoType, List<String>> _groupedThreats) +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ groupedThreats + Map<InfoType, List<String>> + +
+
+ +
read-only
+ +
+ +
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ identifiedThreats + int + +
+
+ +
read-only
+ +
+ +
+ lastScanned + DateTime + +
+
+ +
read-only
+ +
+ +
+ resolvedThreats + int + +
+
+ +
read-only
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+ unresolvedThreats + int + +
+
+ +
read-only
+ +
+ +
+
+ +
+

Methods

+
+
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ + +
+

Static Methods

+
+
+ dummyScanStatisticsModelFactory() + ScanStatisticsModel + + + +
+
+ Dummy Factory Method which returns ScanStatisticsModel with a random threat amount and random threat names. + + +
+ +
+
+ +
+

Constants

+ +
+
+ names + → const List<String> + + +
+
+ Just nessacry for the random name generation + + +
+ ["MyTest", "Fictional", "Malicious", "Generals", "HelloWorld", "Infectious", "Mono", "Dou", "Foo", "Bar&q… +
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsModel/ScanStatisticsModel.html b/doc/api/main/ScanStatisticsModel/ScanStatisticsModel.html new file mode 100644 index 0000000..7f994e4 --- /dev/null +++ b/doc/api/main/ScanStatisticsModel/ScanStatisticsModel.html @@ -0,0 +1,149 @@ + + + + + + + + ScanStatisticsModel constructor - ScanStatisticsModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
ScanStatisticsModel
+ +
+ +
+ + +
+
+

ScanStatisticsModel constructor + Null safety +

+ +
+ ScanStatisticsModel(
  1. int _identifiedThreats,
  2. +
  3. int _resolvedThreats,
  4. +
  5. int _unresolvedThreats,
  6. +
  7. DateTime _lastScanned,
  8. +
  9. Map<InfoType, List<String>> _groupedThreats
  10. +
) +
+ + + + + +
+

Implementation

+
ScanStatisticsModel(this._identifiedThreats, this._resolvedThreats,
+    this._unresolvedThreats, this._lastScanned, this._groupedThreats);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsModel/dummyScanStatisticsModelFactory.html b/doc/api/main/ScanStatisticsModel/dummyScanStatisticsModelFactory.html new file mode 100644 index 0000000..d25138f --- /dev/null +++ b/doc/api/main/ScanStatisticsModel/dummyScanStatisticsModelFactory.html @@ -0,0 +1,160 @@ + + + + + + + + dummyScanStatisticsModelFactory method - ScanStatisticsModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
dummyScanStatisticsModelFactory
+ +
+ +
+ + +
+
+

dummyScanStatisticsModelFactory method + Null safety +

+ +
+ + +ScanStatisticsModel +dummyScanStatisticsModelFactory() + + + +
+ +
+

Dummy Factory Method which returns ScanStatisticsModel with a random threat amount and random threat names.

+
+ + + +
+

Implementation

+
static ScanStatisticsModel dummyScanStatisticsModelFactory() {
+  Map<InfoType, List<String>> dummyGroupedThreats = _dummyGroupedThreats();
+  int identifiedThreats = dummyGroupedThreats.values
+      .map((value) => value.length)
+      .reduce((value, element) => value + element);
+  int unresolvedThreats = identifiedThreats;
+  int resolvedThreats = 0;
+  return ScanStatisticsModel(identifiedThreats, resolvedThreats,
+      unresolvedThreats, DateTime.now(), dummyGroupedThreats);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsModel/groupedThreats.html b/doc/api/main/ScanStatisticsModel/groupedThreats.html new file mode 100644 index 0000000..07448df --- /dev/null +++ b/doc/api/main/ScanStatisticsModel/groupedThreats.html @@ -0,0 +1,151 @@ + + + + + + + + groupedThreats property - ScanStatisticsModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
groupedThreats
+ +
+ +
+ + +
+
+

groupedThreats property + Null safety +

+ + + +
+ +
+ Map<InfoType, List<String>> + groupedThreats + + +
+ + + + +
+

Implementation

+
Map<InfoType, List<String>> get groupedThreats => _groupedThreats;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsModel/identifiedThreats.html b/doc/api/main/ScanStatisticsModel/identifiedThreats.html new file mode 100644 index 0000000..5e85714 --- /dev/null +++ b/doc/api/main/ScanStatisticsModel/identifiedThreats.html @@ -0,0 +1,151 @@ + + + + + + + + identifiedThreats property - ScanStatisticsModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
identifiedThreats
+ +
+ +
+ + +
+
+

identifiedThreats property + Null safety +

+ + + +
+ +
+ int + identifiedThreats + + +
+ + + + +
+

Implementation

+
int get identifiedThreats => _identifiedThreats;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsModel/lastScanned.html b/doc/api/main/ScanStatisticsModel/lastScanned.html new file mode 100644 index 0000000..fb5b138 --- /dev/null +++ b/doc/api/main/ScanStatisticsModel/lastScanned.html @@ -0,0 +1,151 @@ + + + + + + + + lastScanned property - ScanStatisticsModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
lastScanned
+ +
+ +
+ + +
+
+

lastScanned property + Null safety +

+ + + +
+ +
+ DateTime + lastScanned + + +
+ + + + +
+

Implementation

+
DateTime get lastScanned => _lastScanned;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsModel/names-constant.html b/doc/api/main/ScanStatisticsModel/names-constant.html new file mode 100644 index 0000000..bfaf86d --- /dev/null +++ b/doc/api/main/ScanStatisticsModel/names-constant.html @@ -0,0 +1,160 @@ + + + + + + + + names constant - ScanStatisticsModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
names
+ +
+ +
+ + +
+
+

names constant + Null safety +

+ +
+ List<String> + const names + + +
+ +
+

Just nessacry for the random name generation

+
+ + +
+

Implementation

+
static const List<String> names = [
+  "MyTest",
+  "Fictional",
+  "Malicious",
+  "Generals",
+  "HelloWorld",
+  "Infectious",
+  "Mono",
+  "Dou",
+  "Foo",
+  "Bar"
+];
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsModel/resolvedThreats.html b/doc/api/main/ScanStatisticsModel/resolvedThreats.html new file mode 100644 index 0000000..5924018 --- /dev/null +++ b/doc/api/main/ScanStatisticsModel/resolvedThreats.html @@ -0,0 +1,151 @@ + + + + + + + + resolvedThreats property - ScanStatisticsModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
resolvedThreats
+ +
+ +
+ + +
+
+

resolvedThreats property + Null safety +

+ + + +
+ +
+ int + resolvedThreats + + +
+ + + + +
+

Implementation

+
int get resolvedThreats => _resolvedThreats;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/ScanStatisticsModel/unresolvedThreats.html b/doc/api/main/ScanStatisticsModel/unresolvedThreats.html new file mode 100644 index 0000000..2e609be --- /dev/null +++ b/doc/api/main/ScanStatisticsModel/unresolvedThreats.html @@ -0,0 +1,151 @@ + + + + + + + + unresolvedThreats property - ScanStatisticsModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
unresolvedThreats
+ +
+ +
+ + +
+
+

unresolvedThreats property + Null safety +

+ + + +
+ +
+ int + unresolvedThreats + + +
+ + + + +
+

Implementation

+
int get unresolvedThreats => _unresolvedThreats;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/SettingsRoute-class.html b/doc/api/main/SettingsRoute-class.html new file mode 100644 index 0000000..8c810a3 --- /dev/null +++ b/doc/api/main/SettingsRoute-class.html @@ -0,0 +1,436 @@ + + + + + + + + SettingsRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
SettingsRoute
+ +
+ +
+ + +
+
+

SettingsRoute class + Null safety + +

+ + +
+

This SettingsRoute class is a StatefulWidget with the corresponding _SettingsRoute class for the UI and is "Scan - Settings" page of the drawio sketch.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ SettingsRoute({Key? key}) +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ createElement() + StatefulElement + + + +
+
+ Creates a StatefulElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ createState() + → _SettingsRoute + + + +
+
+ Creates the mutable state for this widget at a given location in the tree. [...] +
override
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + +
+

Constants

+ +
+
+ routeName + → const String + + +
+
+ This field is the routName under which this page is registered in the app. + + +
+ "/settings" +
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/SettingsRoute/SettingsRoute.html b/doc/api/main/SettingsRoute/SettingsRoute.html new file mode 100644 index 0000000..ac85e93 --- /dev/null +++ b/doc/api/main/SettingsRoute/SettingsRoute.html @@ -0,0 +1,146 @@ + + + + + + + + SettingsRoute constructor - SettingsRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
SettingsRoute
+ +
+ +
+ + +
+
+

SettingsRoute constructor + Null safety +

+ +
+ SettingsRoute(
  1. {Key? key}
  2. +
) +
+ + + + + +
+

Implementation

+
SettingsRoute({Key? key}) : super(key: key);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/SettingsRoute/createState.html b/doc/api/main/SettingsRoute/createState.html new file mode 100644 index 0000000..6da5e2b --- /dev/null +++ b/doc/api/main/SettingsRoute/createState.html @@ -0,0 +1,171 @@ + + + + + + + + createState method - SettingsRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
createState
+ +
+ +
+ + +
+
+

createState method + Null safety +

+ +
+ +
+
    +
  1. @override
  2. +
+
+ +_SettingsRoute +createState() + +
override
+ +
+ +
+

Creates the mutable state for this widget at a given location in the tree.

+

Subclasses should override this method to return a newly created +instance of their associated State subclass:

+
@override
+_MyState createState() => _MyState();
+
+

The framework can call this method multiple times over the lifetime of +a StatefulWidget. For example, if the widget is inserted into the tree +in multiple locations, the framework will create a separate State object +for each location. Similarly, if the widget is removed from the tree and +later inserted into the tree again, the framework will call createState +again to create a fresh State object, simplifying the lifecycle of +State objects.

+
+ + + +
+

Implementation

+
@override
+_SettingsRoute createState() => _SettingsRoute();
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/SettingsRoute/routeName-constant.html b/doc/api/main/SettingsRoute/routeName-constant.html new file mode 100644 index 0000000..bb88c4b --- /dev/null +++ b/doc/api/main/SettingsRoute/routeName-constant.html @@ -0,0 +1,151 @@ + + + + + + + + routeName constant - SettingsRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
routeName
+ +
+ +
+ + +
+
+

routeName constant + Null safety +

+ +
+ String + const routeName + + +
+ +
+

This field is the routName under which this page is registered in the app.

+
+ + +
+

Implementation

+
static const String routeName = "/settings";
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserBloc-class.html b/doc/api/main/UserBloc-class.html new file mode 100644 index 0000000..4cbc4b8 --- /dev/null +++ b/doc/api/main/UserBloc-class.html @@ -0,0 +1,371 @@ + + + + + + + + UserBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
UserBloc
+ +
+ +
+ + +
+
+

UserBloc class + Null safety + +

+ + +
+

This UserBloc class handles the state of the UserModel.

+

There are mutation functions (login,logout) to mutate the state of the current UserModel.

+
UserBloc.currentBloc.login("TestUser");
+
+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ + +
+

Properties

+ +
+
+ bloc + → dynamic + +
+
+ Getter to get the current stream +
read-only, inherited
+ +
+ +
+ handler + UserHandler + +
+
+ Initializes the UserHandler which performs all the state changes on the UserModel. +
final
+ +
+ +
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ publisher + BehaviorSubject<UserModel> + +
+
+ This BehaviorSubject Object has the Stream Property we publish unto. +
@protected, final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ dispose() + → void + + + +
+
+ +
inherited
+ +
+ +
+ login(String username) + → void + + + +
+
+ Authenticates a new user by username (Dummy Implemetation no login is being performed). [...] + + +
+ +
+ logout() + → void + + + +
+
+ Logs the current user out and replaces the UserModel with a empty one. [...] + + +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ +
+

Static Properties

+ +
+
+ currentBloc + UserBloc + +
+
+ The current instance of the Singleton. +
final
+ +
+ +
+
+ + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserBloc/UserBloc.html b/doc/api/main/UserBloc/UserBloc.html new file mode 100644 index 0000000..cb998d1 --- /dev/null +++ b/doc/api/main/UserBloc/UserBloc.html @@ -0,0 +1,141 @@ + + + + + + + + UserBloc constructor - UserBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
UserBloc
+ +
+ +
+ + +
+
+

UserBloc constructor + Null safety +

+ +
+ UserBloc() +
+ + + + + +
+

Implementation

+
UserBloc() {
+  // To get a default user on app launch
+  this._userPublisher.add(UserModel.dummyUserModelFactory());
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserBloc/bloc.html b/doc/api/main/UserBloc/bloc.html new file mode 100644 index 0000000..0213e9b --- /dev/null +++ b/doc/api/main/UserBloc/bloc.html @@ -0,0 +1,148 @@ + + + + + + + + bloc property - UserBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
bloc
+ +
+ +
+ + +
+
+

bloc property + Null safety +

+ + + +
+ +
+ dynamic + bloc +
inherited
+ +
+ + + + +
+

Implementation

+
get bloc => this.publisher.stream;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserBloc/currentBloc.html b/doc/api/main/UserBloc/currentBloc.html new file mode 100644 index 0000000..96054b4 --- /dev/null +++ b/doc/api/main/UserBloc/currentBloc.html @@ -0,0 +1,146 @@ + + + + + + + + currentBloc property - UserBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
currentBloc
+ +
+ +
+ + +
+
+

currentBloc property + Null safety +

+ +
+ UserBloc + currentBloc +
final
+ +
+ +
+

The current instance of the Singleton.

+
+ + +
+

Implementation

+
static final UserBloc currentBloc = UserBloc._();
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserBloc/dispose.html b/doc/api/main/UserBloc/dispose.html new file mode 100644 index 0000000..0c3901d --- /dev/null +++ b/doc/api/main/UserBloc/dispose.html @@ -0,0 +1,147 @@ + + + + + + + + dispose method - UserBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
dispose
+ +
+ +
+ + +
+
+

dispose method + Null safety +

+ +
+ + +dynamic +dispose() + +
inherited
+ +
+ + + + +
+

Implementation

+
dispose() {
+  this.publisher.close();
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserBloc/handler.html b/doc/api/main/UserBloc/handler.html new file mode 100644 index 0000000..65c570e --- /dev/null +++ b/doc/api/main/UserBloc/handler.html @@ -0,0 +1,146 @@ + + + + + + + + handler property - UserBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
handler
+ +
+ +
+ + +
+
+

handler property + Null safety +

+ +
+ UserHandler + handler +
final
+ +
+ +
+

Initializes the UserHandler which performs all the state changes on the UserModel.

+
+ + +
+

Implementation

+
final handler = UserHandler();
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserBloc/login.html b/doc/api/main/UserBloc/login.html new file mode 100644 index 0000000..a7a616b --- /dev/null +++ b/doc/api/main/UserBloc/login.html @@ -0,0 +1,153 @@ + + + + + + + + login method - UserBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
login
+ +
+ +
+ + +
+
+

login method + Null safety +

+ +
+ + +void +login(
  1. String username
  2. +
) + + + +
+ +
+

Authenticates a new user by username (Dummy Implemetation no login is being performed).

+

Creates a new UserModel and adds it to the publisher.

+
+ + + +
+

Implementation

+
void login(String username) {
+  UserModel newUser = this.handler.login(username);
+  this.publisher.add(newUser);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserBloc/logout.html b/doc/api/main/UserBloc/logout.html new file mode 100644 index 0000000..f525443 --- /dev/null +++ b/doc/api/main/UserBloc/logout.html @@ -0,0 +1,152 @@ + + + + + + + + logout method - UserBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
logout
+ +
+ +
+ + +
+
+

logout method + Null safety +

+ +
+ + +void +logout() + + + +
+ +
+

Logs the current user out and replaces the UserModel with a empty one.

+

Creates a new empty UserModel and adds it to the publisher.

+
+ + + +
+

Implementation

+
void logout() {
+  UserModel newUser = this.handler.logout();
+  this.publisher.add(newUser);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserBloc/publisher.html b/doc/api/main/UserBloc/publisher.html new file mode 100644 index 0000000..580b55c --- /dev/null +++ b/doc/api/main/UserBloc/publisher.html @@ -0,0 +1,148 @@ + + + + + + + + publisher property - UserBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
publisher
+ +
+ +
+ + +
+
+

publisher property + Null safety +

+ +
+ BehaviorSubject<UserModel> + publisher +
@protected, final, inherited
+ +
+ +
+

This ´BehaviorSubject´ Object has the Stream Property we publish unto

+
+ + +
+

Implementation

+
@protected
+// ignore: close_sinks
+final BehaviorSubject<T> publisher = BehaviorSubject<T>();
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserBloc/user.html b/doc/api/main/UserBloc/user.html new file mode 100644 index 0000000..45d7ccc --- /dev/null +++ b/doc/api/main/UserBloc/user.html @@ -0,0 +1,149 @@ + + + + + + + + user property - UserBloc class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
user
+ +
+ +
+ + +
+
+

user property + Null safety +

+ + + +
+ +
+ dynamic + user + + +
+ + +
+

Listeners

+
+ + +
+

Implementation

+
get user => this._userPublisher.stream;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserHandler-class.html b/doc/api/main/UserHandler-class.html new file mode 100644 index 0000000..181ba9f --- /dev/null +++ b/doc/api/main/UserHandler-class.html @@ -0,0 +1,301 @@ + + + + + + + + UserHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
UserHandler
+ +
+ +
+ + +
+
+

UserHandler class + Null safety + +

+ + +
+

This UserHandler class has the implementation for all the mutations in the UserBloc.

+ +
+ + + +
+

Constructors

+ +
+
+ UserHandler() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ login(String username) + UserModel + + + +
+
+ This method returns a new UserModel with a given username. + + +
+ +
+ logout() + UserModel + + + +
+
+ This method returns a new UserModel with a empty username (which simulates the logout). + + +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserHandler/UserHandler.html b/doc/api/main/UserHandler/UserHandler.html new file mode 100644 index 0000000..e3d605d --- /dev/null +++ b/doc/api/main/UserHandler/UserHandler.html @@ -0,0 +1,132 @@ + + + + + + + + UserHandler constructor - UserHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
UserHandler
+ +
+ +
+ + +
+
+

UserHandler constructor + Null safety +

+ +
+ UserHandler() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserHandler/login.html b/doc/api/main/UserHandler/login.html new file mode 100644 index 0000000..b420740 --- /dev/null +++ b/doc/api/main/UserHandler/login.html @@ -0,0 +1,147 @@ + + + + + + + + login method - UserHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
login
+ +
+ +
+ + +
+
+

login method + Null safety +

+ +
+ + +UserModel +login(
  1. String username
  2. +
) + + + +
+ +
+

This method returns a new UserModel with a given username.

+
+ + + +
+

Implementation

+
UserModel login(String username) {
+  return UserModel(username);
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserHandler/logout.html b/doc/api/main/UserHandler/logout.html new file mode 100644 index 0000000..41f4607 --- /dev/null +++ b/doc/api/main/UserHandler/logout.html @@ -0,0 +1,146 @@ + + + + + + + + logout method - UserHandler class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
logout
+ +
+ +
+ + +
+
+

logout method + Null safety +

+ +
+ + +UserModel +logout() + + + +
+ +
+

This method returns a new UserModel with a empty username (which simulates the logout).

+
+ + + +
+

Implementation

+
UserModel logout() {
+  return UserModel("");
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserModel-class.html b/doc/api/main/UserModel-class.html new file mode 100644 index 0000000..d4b9efb --- /dev/null +++ b/doc/api/main/UserModel-class.html @@ -0,0 +1,315 @@ + + + + + + + + UserModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
UserModel
+ +
+ +
+ + +
+
+

UserModel class + Null safety + +

+ + +
+

This UserModel class represents the current logged in user.

+
+ + + +
+

Constructors

+ +
+
+ UserModel(String _userName) +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
read-only, inherited
+ +
+ +
+ isLoggedIn + bool + +
+
+ Check weather a user is logged in, but in this cases only looks for a username unequal to "". +
read-only
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+ userName + String + +
+
+ +
read-only
+ +
+ +
+
+ +
+

Methods

+
+
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toString() + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
inherited
+ +
+ +
+
+ + +
+

Static Methods

+
+
+ dummyUserModelFactory() + UserModel + + + +
+
+ This dummy user factory method generates a user with an empty username. +This is considered not logged in. + + +
+ +
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserModel/UserModel.html b/doc/api/main/UserModel/UserModel.html new file mode 100644 index 0000000..b7d88d0 --- /dev/null +++ b/doc/api/main/UserModel/UserModel.html @@ -0,0 +1,139 @@ + + + + + + + + UserModel constructor - UserModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
UserModel
+ +
+ +
+ + +
+
+

UserModel constructor + Null safety +

+ +
+ UserModel(
  1. String _userName
  2. +
) +
+ + + + + +
+

Implementation

+
UserModel(this._userName);
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserModel/dummyUserModelFactory.html b/doc/api/main/UserModel/dummyUserModelFactory.html new file mode 100644 index 0000000..9b03d40 --- /dev/null +++ b/doc/api/main/UserModel/dummyUserModelFactory.html @@ -0,0 +1,149 @@ + + + + + + + + dummyUserModelFactory method - UserModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
dummyUserModelFactory
+ +
+ +
+ + +
+
+

dummyUserModelFactory method + Null safety +

+ +
+ + +UserModel +dummyUserModelFactory() + + + +
+ +
+

This dummy user factory method generates a user with an empty username. +This is considered not logged in.

+
+ + + +
+

Implementation

+
static UserModel dummyUserModelFactory() {
+  return UserModel("");
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserModel/isLoggedIn.html b/doc/api/main/UserModel/isLoggedIn.html new file mode 100644 index 0000000..d56e4cd --- /dev/null +++ b/doc/api/main/UserModel/isLoggedIn.html @@ -0,0 +1,149 @@ + + + + + + + + isLoggedIn property - UserModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
isLoggedIn
+ +
+ +
+ + +
+
+

isLoggedIn property + Null safety +

+ + + +
+ +
+ bool + isLoggedIn + + +
+ + +
+

Check weather a user is logged in, but in this cases only looks for a username unequal to "".

+
+ + +
+

Implementation

+
bool get isLoggedIn => this._userName.length > 0;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserModel/userName.html b/doc/api/main/UserModel/userName.html new file mode 100644 index 0000000..bfedef3 --- /dev/null +++ b/doc/api/main/UserModel/userName.html @@ -0,0 +1,146 @@ + + + + + + + + userName property - UserModel class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
userName
+ +
+ +
+ + +
+
+

userName property + Null safety +

+ + + +
+ +
+ String + userName + + +
+ + + + +
+

Implementation

+
String get userName => this._userName;
+
+ +
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserRoute-class.html b/doc/api/main/UserRoute-class.html new file mode 100644 index 0000000..299bdb8 --- /dev/null +++ b/doc/api/main/UserRoute-class.html @@ -0,0 +1,437 @@ + + + + + + + + UserRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
UserRoute
+ +
+ +
+ + +
+
+

UserRoute class + Null safety + +

+ + +
+

This UserRoute class represents the "Profile(b)" page in the drawio sketch v4.

+
+ + +
+
+
Inheritance
+
+ + + + + +
+
+ +
+

Constructors

+ +
+
+ UserRoute() +
+
+ +
+
+
+ +
+

Properties

+ +
+
+ hashCode + int + +
+
+ The hash code for this object. [...] +
@nonVirtual, read-only, inherited
+ +
+ +
+ key + Key? + +
+
+ Controls how one widget replaces another widget in the tree. [...] +
final, inherited
+ +
+ +
+ runtimeType + Type + +
+
+ A representation of the runtime type of the object. +
read-only, inherited
+ +
+ +
+
+ +
+

Methods

+
+
+ build(BuildContext context) + Widget + + + +
+
+ This build Method gets called to build the UI. This combines the +components into a Scaffold. +
override
+ +
+ +
+ createElement() + StatelessElement + + + +
+
+ Creates a StatelessElement to manage this widget's location in the tree. [...] +
inherited
+ +
+ +
+ debugDescribeChildren() + List<DiagnosticsNode> + + + +
+
+ Returns a list of DiagnosticsNode objects describing this node's +children. [...] +
@protected, inherited
+ +
+ +
+ debugFillProperties(DiagnosticPropertiesBuilder properties) + → void + + + +
+
+ Add additional properties associated with the node. [...] +
inherited
+ +
+ +
+ noSuchMethod(Invocation invocation) + → dynamic + + + +
+
+ Invoked when a non-existent method or property is accessed. [...] +
inherited
+ +
+ +
+ toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) + DiagnosticsNode + + + +
+
+ Returns a debug representation of the object that is used by debugging +tools and by DiagnosticsNode.toStringDeep. [...] +
inherited
+ +
+ +
+ toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) + String + + + +
+
+ A string representation of this object. [...] +
inherited
+ +
+ +
+ toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a string representation of this node and its descendants. [...] +
inherited
+ +
+ +
+ toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) + String + + + +
+
+ Returns a one-line detailed description of the object. [...] +
inherited
+ +
+ +
+ toStringShort() + String + + + +
+
+ A short, textual description of this widget. +
inherited
+ +
+ +
+
+ +
+

Operators

+
+
+ operator ==(Object other) + bool + + + +
+
+ The equality operator. [...] +
@nonVirtual, inherited
+ +
+ +
+
+ + + +
+

Constants

+ +
+
+ routeName + → const String + + +
+
+ This field is the routName under which this page is registered in the app. + + +
+ '/user' +
+
+ +
+
+ +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserRoute/UserRoute.html b/doc/api/main/UserRoute/UserRoute.html new file mode 100644 index 0000000..519ef70 --- /dev/null +++ b/doc/api/main/UserRoute/UserRoute.html @@ -0,0 +1,141 @@ + + + + + + + + UserRoute constructor - UserRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
UserRoute
+ +
+ +
+ + +
+
+

UserRoute constructor + Null safety +

+ +
+ UserRoute() +
+ + + + + + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserRoute/build.html b/doc/api/main/UserRoute/build.html new file mode 100644 index 0000000..64d5e83 --- /dev/null +++ b/doc/api/main/UserRoute/build.html @@ -0,0 +1,188 @@ + + + + + + + + build method - UserRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
build
+ +
+ +
+ + +
+
+

build method + Null safety +

+ +
+ + +Widget +build(
  1. BuildContext context
  2. +
) + +
override
+ +
+ +
+

This build Method gets called to build the UI. This combines the +components into a Scaffold.

+
+ + + +
+

Implementation

+
Widget build(BuildContext context) {
+  return Scaffold(
+    appBar: _buildAppBar(context),
+    body: Column(
+      children: [
+        SizedBox(
+          height: 60,
+        ),
+        _buildUserCard(context),
+        Spacer(),
+        DefaultElevatedButton(
+          width: 215,
+          onPressed: () {
+            UserBloc.currentBloc.logout();
+            Navigator.of(context).popAndPushNamed(HomeRoute.routeName);
+          },
+          name: "Logout",
+        ),
+        SizedBox(
+          height: 4,
+        ),
+        DefaultElevatedButton(
+          onPressed: () {},
+          width: 215,
+          height: 50,
+          name: "Privacy Dashboard",
+        ),
+        SizedBox(
+          height: 80,
+        )
+      ],
+    ),
+  );
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/UserRoute/routeName-constant.html b/doc/api/main/UserRoute/routeName-constant.html new file mode 100644 index 0000000..1eca6b7 --- /dev/null +++ b/doc/api/main/UserRoute/routeName-constant.html @@ -0,0 +1,151 @@ + + + + + + + + routeName constant - UserRoute class - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
routeName
+ +
+ +
+ + +
+
+

routeName constant + Null safety +

+ +
+ String + const routeName + + +
+ +
+

This field is the routName under which this page is registered in the app.

+
+ + +
+

Implementation

+
static const String routeName = '/user';
+
+
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/filterBloc.html b/doc/api/main/filterBloc.html new file mode 100644 index 0000000..31cd214 --- /dev/null +++ b/doc/api/main/filterBloc.html @@ -0,0 +1,161 @@ + + + + + + + + filterBloc property - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
filterBloc
+ +
+ +
+ + +
+
+

filterBloc top-level property + Null safety + +

+ +
+ ResolveFilterBloc + filterBloc +
final
+ +
+ + + +
+

Implementation

+
final filterBloc = ResolveFilterBloc();
+
+ + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/knowledgeBaseDummy-constant.html b/doc/api/main/knowledgeBaseDummy-constant.html new file mode 100644 index 0000000..7b5909b --- /dev/null +++ b/doc/api/main/knowledgeBaseDummy-constant.html @@ -0,0 +1,195 @@ + + + + + + + + knowledgeBaseDummy constant - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
knowledgeBaseDummy
+ +
+ +
+ + +
+
+

knowledgeBaseDummy top-level constant + Null safety + +

+ +
+ Map<InfoType, Map<String, String>> + const knowledgeBaseDummy + + +
+ +
+

Current dummy representation of the Knowledgebase.

+
+ + +
+

Implementation

+
const Map<InfoType, Map<String, String>> knowledgeBaseDummy = {
+  // taken from https://whatis.techtarget.com/definition/mobile-spyware
+  InfoType.spyware: {
+    "name": "Spyware",
+    "description":
+        "Mobile spyware is a classification of software programs that monitors and records information about an end user's actions without the end user's knowledge or permission. If the end user is aware that monitoring software has been installed, the software is not considered to be spyware. Like desktop spyware, mobile spyware is often installed unwittingly by the end user when he or she sideloads a third-party software app, visits or is redirected to a malicious website or leaves the computing device physically unattended. Once a mobile device is infected with spyware, the spy can eavesdrop on conversations held on (or near) a compromised smartphone or access data that is stored on or transmitted by the device. Bluetooth also offers a largely unsecured interface that can be exploited by those in close proximity, through techniques like Bluesnarfing. Smartphone accelerometers have been used in keyboard vibration attacks to detect what is typed on a computer with surprising accuracy when the phone was sitting on the desk near the keyboard. Controversially, governments have used mobile spyware to access the data of citizens, notably with the Smurf suite of spyware tools brought to public attention by Edward Snowden.",
+    "actions":
+        "Antivirus software that includes antispyware protection should be used to find and remove spyware. Although mobile security software exists, many users are lax about installing it. For one thing, phone security solutions use up system resources thereby slowing down other software and consuming power. Furthermore, because the effectiveness of app-based security has often been questioned, users may feel that installing security apps is pointless. To prevent spyware, users should only download software from trusted sources, read all disclosures when installing software, avoid clicking on pop-up ads and stay current with updates for operating system (OS) and application software.",
+  },
+  // taken from https://www.trendmicro.com/vinfo/us/security/definition/fake-apps
+  InfoType.fakeapps: {
+    "name": "Fake Apps",
+    "description":
+        "These are apps in mobile devices that trick users into downloading them by using legitimate companies or popular references. They may also pose as quirky and attractive apps, providing interesting services like live wallpapers or real-time spying tools. Once installed on a mobile device, fake apps can perform a variety of malicious routines. They can persistently push ads, track and report location and other sensitive information, or subscribe users to premium services without consent. These can all lead to loss of data and privacy and waste of device resources. To a cybercriminal, generating interest of the online public is easy by baiting users with apps that generate buzz in the mobile device-using world. Even from official sites, risks still abound in these app-distribution platforms, enough to prey on a trusting user.",
+    "actions":
+        "In today’s ever-evolving technology-driven society, it is easy to fall into the traps left by cybercriminals. A mobile device user has an average of 41 downloaded apps. With the demand still growing for more ways to expand one’s mobile device use, it is expected that more and more ways will be sought by cybercriminals to take advantage on this clamor for newer, more advanced apps. The biggest armor a smart mobile user can wear is to stay well-informed of the many ways a cybercriminal could take advantage of mobile device’s vulnerability. These simple steps are key in keeping your app-world safe from threats: Think before you download. Choose apps that will be useful to you. Be mindful of the download sites you go to for your apps. It is always best to go to official app stores for security. Always check for app details prior to your download. Reading on every tiny detail can aid you to weed out the fake or malicious apps. Never click on links with promises that are too good to be true. Read everything and carefully analyze permissions asked by apps you download. Always be in the know of security features installed on your mobile devices. Invest and install an effective mobile security app.",
+  },
+  // taken from https://www.kaspersky.com/resource-center/definitions/keylogger
+  InfoType.keylogger: {
+    "name": "Keylogger",
+    "description":
+        "Keystroke logging is an act of tracking and recording every keystroke entry made on a computer, often without the permission or knowledge of the user. A “keystroke” is just any interaction you make with a button on your keyboard. Keystrokes are how you “speak” to your computers. Each keystroke transmits a signal that tells your computer programs what you want them to do. Keylogger tools can either be hardware or software meant to automate the process of keystroke logging. These tools record the data sent by every keystroke into a text file to be retrieved at a later time. Some tools can record everything on your copy-cut-paste clipboard, calls, GPS data, and even microphone or camera footage. Keyloggers are a surveillance tool with legitimate uses for personal or professional IT monitoring. Some of these uses enter an ethically questionable grey area. However, other keylogger uses are explicitly criminal. Regardless of the use, keyloggers are often used without the user’s fully aware consent and keyloggers are used under the assumption that users should behave as normal.",
+    "actions":
+        "Always read your terms of service or any contracts before accepting. You should know what you’re agreeing to before you sign up. Researching user feedback on software you plan to install might provide some helpful guidance as well. Install internet security software on all your devices. Malicious keyloggers generally make their way to devices in software form. If you have a security software suite like Kaspersky Anti-Virus, you’ll have an active shield to guard against infections. Make sure your security programs are updated on the latest threats. Your security needs to have every known keylogger definition to detect them properly. Many modern products automatically update to protect against keylogger malware and other threats. Don’t leave your mobile and computer devices unsupervised. If a criminal can steal your device or even get their hands on it for a moment, that may be all they need. Hold on to your devices to help prevent keyloggers from being implanted. Keep all other device software updated. Your operating system, software products and Web browsers should all be up to date with the latest security patches. When an update is offered, be sure to download and install it as soon as possible. Do not use unfamiliar USB drives or external hard drives. Many criminals leave these devices in public places to entice you to take them and use them. Once plugged into your computer or mobile device, they can infiltrate and begin logging."
+  },
+  // taken from https://us.norton.com/internetsecurity-wifi-the-dos-and-donts-of-using-public-wi-fi.html
+  InfoType.insecureWifi: {
+    "name": "Insecure Wifi",
+    "description":
+        "Public Wi-Fi is available just about everywhere, from the local coffee shop to the hotels and airports you visit while traveling. Wi-Fi has made our lives a little easier, but it also poses security risks to the personal information available on our laptops and smartphones. Here is a helpful list of dos and don’ts you should follow if you plan to use public Wi-Fi. Public Wi-Fi is available just about everywhere, from the local coffee shop to the hotels and airports you visit while traveling. Wi-Fi has made our lives a little easier, but it also poses security risks to the personal information available on our laptops and smartphones. Here is a helpful list of dos and don’ts you should follow if you plan to use public Wi-Fi.",
+    "actions":
+        "Do connect to secured public networks whenever possible. In the event that you’re unable to connect to a secured network, using an unsecured network would be permissible if the connection requires some sort of login or registration. Don't access personal bank accounts, or sensitive personal data, on unsecured public networks. Even secured networks can be risky. Use your best judgment if you must access these accounts on public Wi-Fi. Don't leave your laptop, tablet, or smartphone unattended in a public place. Even if you’re working on a secure Wi-Fi network, that won’t stop someone from taking your property or sneaking a peek at your device. Don't shop online when using public Wi-Fi. Sure, shopping doesn’t seem like it involves sensitive data, but making purchases online requires personal information that could include bank account and retailer login credentials. Shopping isn’t something you want to do on an unsecured Wi-Fi network. Do turn off automatic connectivity. Most smartphones, laptops, and tablets have automatic connectivity settings, which allow you to seamlessly connect from one hotspot to the next. This is a convenient feature, but it can also connect your devices to networks you ordinarily would not use. Keep these settings turned off, especially when you’re traveling to unfamiliar places. Do monitor your Bluetooth connectivity. Bluetooth in the home is an amazing feature on many smart devices. However, leaving Bluetooth on while in public places can pose a huge risk to your cybersecurity. Bluetooth connectivity allows various devices to communicate with each other, and a hacker can look for open Bluetooth signals to gain access to your devices. Keep this function on your phone and other devices locked down when you leave your home, office, or similar secured area. Do think about using a virtual private network (VPN) solution to ensure your privacy and anonymity are protected when you use public Wi-Fi. VPN services, like the new Norton Secure VPN, can encrypt all the data that you send and receive while using a public Wi-Fi hotspot, securing your information from other users of the same connection."
+  },
+};
+
+ + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/main-library.html b/doc/api/main/main-library.html new file mode 100644 index 0000000..ef100ff --- /dev/null +++ b/doc/api/main/main-library.html @@ -0,0 +1,466 @@ + + + + + + + + main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
main
+ +
+ +
+ + +
+
+

main library + Null safety + +

+ + + + +
+

Classes

+ +
+
+ AbstractBloc<M, H> + +
+
+ This AbstractBloc class implements the barebone structure of every Bloc. [...] +
+ +
+ App + +
+
+ This App class is the main entry to the app. [...] +
+ +
+ CardDisplay + +
+
+ This CardDisplay class is a ui component which can be used to display a card with a title and a body. +
+ +
+ ConfigureResolutionRoute + +
+
+ This ConfigureResolutionRoute class represents the "Resolve - Configuration" page in the drawio sketch v4. +
+ +
+ DefaultElevatedButton + +
+
+ This DefaultElevatedButton is a ElevatedButton with a fixed size, we use throughout the project. +
+ +
+ HomeRoute + +
+
+ This HomeRoute class represents the "Main(a-x), Main(b-x), Profile(a-y), Profile(b-y)" page in the drawio sketch v4. +
+ +
+ KnowledgeBaseRoute + +
+
+ This KnowledgeBaseRoute class represents the "KnowledgeBase" page in the drawio sketch v4. +
+ +
+ LoginRoute + +
+
+ This LoginRoute class is a StatefulWidget with the corresponding _LoginRouteState class for the UI and is "Profile(a)" page of the drawio sketch. +
+ +
+ ResolveFilterBloc + +
+
+ This ResolveFilterBloc class handles the state of the ResolveFilterModel. [...] +
+ +
+ ResolveFilterHandler + +
+
+ This ResolveFilterHandler class has the implementation for all the mutations in the ResolveFilterBloc. [...] +
+ +
+ ResolveFilterModel + +
+
+ This ResolveFilterModel class is an entity that stores all relavant information about the ResolveFilter. +
+ +
+ ResolveRoute + +
+
+ This ResolveRoute class is a StatefulWidget with the corresponding _ResolveRouteState class for the UI and is the "Resolution - Pending" page of the drawio sketch. +
+ +
+ ScanInfo + +
+
+ This ScanInfo class is used to display the threats shown in drawio sketch "Scan Log", +
+ +
+ ScanLogRoute + +
+
+ This ScanLogRoute class represents the "Scan - Log" page in the drawio sketch v4. +
+ +
+ ScanResolutionSwitch + +
+
+ +
+ +
+ ScanRoute + +
+
+ This ScanRoute class is a StatefulWidget with the corresponding _ScanRouteState class for the UI and is the "Scan - Pending" page in the drawio sketch. +
+ +
+ ScanStatistics + +
+
+ This ScanStatistics class displays the data from the ScanStatisticsModel as shwon in drawio sketch "Main(a-x,b-x), Profile(a-y,b-y)". +
+ +
+ ScanStatisticsBloc + +
+
+ This ScanStatisticsBloc class handles the state of the ScanStatisticsModel. [...] +
+ +
+ ScanStatisticsHandler + +
+
+ This ScanStatisticsHandler class has the implementation for all the mutations in the ScanStatisticsBloc. [...] +
+ +
+ ScanStatisticsModel + +
+
+ This ScanStatisticsModel class represents a scanlog with all the information that a supposed scan could deliver. +
+ +
+ SettingsRoute + +
+
+ This SettingsRoute class is a StatefulWidget with the corresponding _SettingsRoute class for the UI and is "Scan - Settings" page of the drawio sketch. +
+ +
+ UserBloc + +
+
+ This UserBloc class handles the state of the UserModel. [...] +
+ +
+ UserHandler + +
+
+ This UserHandler class has the implementation for all the mutations in the UserBloc. [...] +
+ +
+ UserModel + +
+
+ This UserModel class represents the current logged in user. +
+ +
+ UserRoute + +
+
+ This UserRoute class represents the "Profile(b)" page in the drawio sketch v4. +
+ +
+
+ + +
+

Extensions

+ +
+
+ ParseToString + +
+
+ +
+ + +
+
+ +
+

Constants

+ +
+
+ knowledgeBaseDummy + → const Map<InfoType, Map<String, String>> + + +
+
+ Current dummy representation of the Knowledgebase. + + +
+ {InfoType.spyware : {"name" : "Spyware", "description" : "Mobile spyware is a classification of software programs that monitors and records information about an end … +
+
+ +
+ seed + → const int + + +
+
+ Demo Seed + + +
+ 14023 +
+
+ +
+
+ +
+

Properties

+ +
+
+ rnd + Random + +
+
+ Demo Random Number Generator +
read / write
+ +
+ +
+
+ +
+

Functions

+ +
+
+ main() + → void + + + +
+
+ + + +
+ +
+
+ +
+

Enums

+ +
+
+ InfoType + +
+
+ This is the InfoType enum which is the current set of threats +
+ +
+
+ + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/main.html b/doc/api/main/main.html new file mode 100644 index 0000000..7f7fc22 --- /dev/null +++ b/doc/api/main/main.html @@ -0,0 +1,162 @@ + + + + + + + + main function - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
main
+ +
+ +
+ + +
+
+

main function + Null safety + +

+ +
+ + +void +main() + +
+ + + + +
+

Implementation

+
void main() {
+  runApp(App());
+}
+
+ + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/rnd.html b/doc/api/main/rnd.html new file mode 100644 index 0000000..550fe45 --- /dev/null +++ b/doc/api/main/rnd.html @@ -0,0 +1,162 @@ + + + + + + + + rnd property - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
rnd
+ +
+ +
+ + +
+
+

rnd top-level property + Null safety + +

+ +
+ Random + rnd +
read / write
+ +
+ +
+

Demo Random Number Generator

+
+ + +
+

Implementation

+
Random rnd = new Random(seed);
+
+ + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/seed-constant.html b/doc/api/main/seed-constant.html new file mode 100644 index 0000000..36ac24c --- /dev/null +++ b/doc/api/main/seed-constant.html @@ -0,0 +1,162 @@ + + + + + + + + seed constant - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
seed
+ +
+ +
+ + +
+
+

seed top-level constant + Null safety + +

+ +
+ int + const seed + + +
+ +
+

Demo Seed

+
+ + +
+

Implementation

+
const int seed = 14023;
+
+ + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/statBloc.html b/doc/api/main/statBloc.html new file mode 100644 index 0000000..93aebbc --- /dev/null +++ b/doc/api/main/statBloc.html @@ -0,0 +1,161 @@ + + + + + + + + statBloc property - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
statBloc
+ +
+ +
+ + +
+
+

statBloc top-level property + Null safety + +

+ +
+ ScanStatisticsBloc + statBloc +
final
+ +
+ + + +
+

Implementation

+
final statBloc = ScanStatisticsBloc();
+
+ + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/main/userBloc.html b/doc/api/main/userBloc.html new file mode 100644 index 0000000..6362e5c --- /dev/null +++ b/doc/api/main/userBloc.html @@ -0,0 +1,161 @@ + + + + + + + + userBloc property - main library - Dart API + + + + + + + + + + + + + + + + + +
+ +
+ + +
userBloc
+ +
+ +
+ + +
+
+

userBloc top-level property + Null safety + +

+ +
+ UserBloc + userBloc +
final
+ +
+ + + +
+

Implementation

+
final userBloc = UserBloc();
+
+ + + +
+ + + + + +
+ +
+ + flutternativetrapeze + 1.0.0+1 + + + +
+ + + + + + + + + + + + diff --git a/doc/api/static-assets/favicon.png b/doc/api/static-assets/favicon.png new file mode 100644 index 0000000..43d2ffa Binary files /dev/null and b/doc/api/static-assets/favicon.png differ diff --git a/doc/api/static-assets/github.css b/doc/api/static-assets/github.css new file mode 100644 index 0000000..791932b --- /dev/null +++ b/doc/api/static-assets/github.css @@ -0,0 +1,99 @@ +/* + +github.com style (c) Vasily Polovnyov + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #333; + background: #f8f8f8; +} + +.hljs-comment, +.hljs-quote { + color: #998; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-subst { + color: #333; + font-weight: bold; +} + +.hljs-number, +.hljs-literal, +.hljs-variable, +.hljs-template-variable, +.hljs-tag .hljs-attr { + color: #008080; +} + +.hljs-string, +.hljs-doctag { + color: #d14; +} + +.hljs-title, +.hljs-section, +.hljs-selector-id { + color: #900; + font-weight: bold; +} + +.hljs-subst { + font-weight: normal; +} + +.hljs-type, +.hljs-class .hljs-title { + color: #458; + font-weight: bold; +} + +.hljs-tag, +.hljs-name, +.hljs-attribute { + color: #000080; + font-weight: normal; +} + +.hljs-regexp, +.hljs-link { + color: #009926; +} + +.hljs-symbol, +.hljs-bullet { + color: #990073; +} + +.hljs-built_in, +.hljs-builtin-name { + color: #0086b3; +} + +.hljs-meta { + color: #999; + font-weight: bold; +} + +.hljs-deletion { + background: #fdd; +} + +.hljs-addition { + background: #dfd; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/doc/api/static-assets/highlight.pack.js b/doc/api/static-assets/highlight.pack.js new file mode 100644 index 0000000..dabdd3c --- /dev/null +++ b/doc/api/static-assets/highlight.pack.js @@ -0,0 +1,775 @@ +/*! + Highlight.js v11.0.1 (git: 1cf31f015d) + (c) 2006-2021 Ivan Sagalaev and other contributors + License: BSD-3-Clause + */ +var hljs=function(){"use strict";var e={exports:{}};function t(e){ +return e instanceof Map?e.clear=e.delete=e.set=()=>{ +throw Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{ +throw Error("set is read-only") +}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach((n=>{var i=e[n] +;"object"!=typeof i||Object.isFrozen(i)||t(i)})),e} +e.exports=t,e.exports.default=t;var n=e.exports;class i{constructor(e){ +void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} +ignoreMatch(){this.isMatchIgnored=!0}}function r(e){ +return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") +}function s(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] +;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const o=e=>!!e.kind +;class a{constructor(e,t){ +this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ +this.buffer+=r(e)}openNode(e){if(!o(e))return;let t=e.kind +;t=e.sublanguage?"language-"+t:((e,{prefix:t})=>{if(e.includes(".")){ +const n=e.split(".") +;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") +}return`${t}${e}`})(t,{prefix:this.classPrefix}),this.span(t)}closeNode(e){ +o(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ +this.buffer+=``}}class l{constructor(){this.rootNode={ +children:[]},this.stack=[this.rootNode]}get top(){ +return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ +this.top.children.push(e)}openNode(e){const t={kind:e,children:[]} +;this.add(t),this.stack.push(t)}closeNode(){ +if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ +for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} +walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ +return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), +t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ +"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ +l._collapse(e)})))}}class c extends l{constructor(e){super(),this.options=e} +addKeyword(e,t){""!==e&&(this.openNode(t),this.addText(e),this.closeNode())} +addText(e){""!==e&&this.add(e)}addSublanguage(e,t){const n=e.root +;n.kind=t,n.sublanguage=!0,this.add(n)}toHTML(){ +return new a(this,this.options).value()}finalize(){return!0}}function g(e){ +return e?"string"==typeof e?e:e.source:null}function d(...e){ +return e.map((e=>g(e))).join("")}function u(...e){return"("+((e=>{ +const t=e[e.length-1] +;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} +})(e).capture?"":"?:")+e.map((e=>g(e))).join("|")+")"}function h(e){ +return RegExp(e.toString()+"|").exec("").length-1} +const f=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ +;function p(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n +;let i=g(e),r="";for(;i.length>0;){const e=f.exec(i);if(!e){r+=i;break} +r+=i.substring(0,e.index), +i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?r+="\\"+(Number(e[1])+t):(r+=e[0], +"("===e[0]&&n++)}return r})).map((e=>`(${e})`)).join(t)} +const b="[a-zA-Z]\\w*",m="[a-zA-Z_]\\w*",E="\\b\\d+(\\.\\d+)?",x="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",y="\\b(0b[01]+)",w={ +begin:"\\\\[\\s\\S]",relevance:0},_={scope:"string",begin:"'",end:"'", +illegal:"\\n",contains:[w]},v={scope:"string",begin:'"',end:'"',illegal:"\\n", +contains:[w]},O=(e,t,n={})=>{const i=s({scope:"comment",begin:e,end:t, +contains:[]},n);i.contains.push({scope:"doctag", +begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", +end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) +;const r=u("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) +;return i.contains.push({begin:d(/[ ]+/,"(",r,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),i +},k=O("//","$"),N=O("/\\*","\\*/"),S=O("#","$");var M=Object.freeze({ +__proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:b,UNDERSCORE_IDENT_RE:m, +NUMBER_RE:E,C_NUMBER_RE:x,BINARY_NUMBER_RE:y, +RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", +SHEBANG:(e={})=>{const t=/^#![ ]*\// +;return e.binary&&(e.begin=d(t,/.*\b/,e.binary,/\b.*/)),s({scope:"meta",begin:t, +end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, +BACKSLASH_ESCAPE:w,APOS_STRING_MODE:_,QUOTE_STRING_MODE:v,PHRASAL_WORDS_MODE:{ +begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +},COMMENT:O,C_LINE_COMMENT_MODE:k,C_BLOCK_COMMENT_MODE:N,HASH_COMMENT_MODE:S, +NUMBER_MODE:{scope:"number",begin:E,relevance:0},C_NUMBER_MODE:{scope:"number", +begin:x,relevance:0},BINARY_NUMBER_MODE:{scope:"number",begin:y,relevance:0}, +REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{scope:"regexp",begin:/\//, +end:/\/[gimuy]*/,illegal:/\n/,contains:[w,{begin:/\[/,end:/\]/,relevance:0, +contains:[w]}]}]},TITLE_MODE:{scope:"title",begin:b,relevance:0}, +UNDERSCORE_TITLE_MODE:{scope:"title",begin:m,relevance:0},METHOD_GUARD:{ +begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{ +"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ +t.data._beginMatch!==e[1]&&t.ignoreMatch()}})});function R(e,t){ +"."===e.input[e.index-1]&&t.ignoreMatch()}function j(e,t){ +void 0!==e.className&&(e.scope=e.className,delete e.className)}function A(e,t){ +t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", +e.__beforeBegin=R,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, +void 0===e.relevance&&(e.relevance=0))}function I(e,t){ +Array.isArray(e.illegal)&&(e.illegal=u(...e.illegal))}function B(e,t){ +if(e.match){ +if(e.begin||e.end)throw Error("begin & end are not supported with match") +;e.begin=e.match,delete e.match}}function T(e,t){ +void 0===e.relevance&&(e.relevance=1)}const L=(e,t)=>{if(!e.beforeMatch)return +;if(e.starts)throw Error("beforeMatch cannot be used with starts") +;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] +})),e.keywords=n.keywords, +e.begin=d(n.beforeMatch,d("(?=",n.begin,")")),e.starts={relevance:0, +contains:[Object.assign(n,{endsParent:!0})]},e.relevance=0,delete n.beforeMatch +},D=["of","and","for","in","not","or","if","then","parent","list","value"] +;function P(e,t,n="keyword"){const i=Object.create(null) +;return"string"==typeof e?r(n,e.split(" ")):Array.isArray(e)?r(n,e):Object.keys(e).forEach((n=>{ +Object.assign(i,P(e[n],t,n))})),i;function r(e,n){ +t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") +;i[n[0]]=[e,C(n[0],n[1])]}))}}function C(e,t){ +return t?Number(t):(e=>D.includes(e.toLowerCase()))(e)?0:1}const H={},$=e=>{ +console.error(e)},U=(e,...t)=>{console.log("WARN: "+e,...t)},z=(e,t)=>{ +H[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),H[`${e}/${t}`]=!0) +},K=Error();function W(e,t,{key:n}){let i=0;const r=e[n],s={},o={} +;for(let e=1;e<=t.length;e++)o[e+i]=r[e],s[e+i]=!0,i+=h(t[e-1]) +;e[n]=o,e[n]._emit=s,e[n]._multi=!0}function X(e){(e=>{ +e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, +delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ +_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope +}),(e=>{if(Array.isArray(e.begin)){ +if(e.skip||e.excludeBegin||e.returnBegin)throw $("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), +K +;if("object"!=typeof e.beginScope||null===e.beginScope)throw $("beginScope must be object"), +K;W(e,e.begin,{key:"beginScope"}),e.begin=p(e.begin,{joinWith:""})}})(e),(e=>{ +if(Array.isArray(e.end)){ +if(e.skip||e.excludeEnd||e.returnEnd)throw $("skip, excludeEnd, returnEnd not compatible with endScope: {}"), +K +;if("object"!=typeof e.endScope||null===e.endScope)throw $("endScope must be object"), +K;W(e,e.end,{key:"endScope"}),e.end=p(e.end,{joinWith:""})}})(e)}function G(e){ +function t(t,n){return RegExp(g(t),"m"+(e.case_insensitive?"i":"")+(n?"g":""))} +class n{constructor(){ +this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} +addRule(e,t){ +t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), +this.matchAt+=h(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) +;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(p(e,{joinWith:"|" +}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex +;const t=this.matcherRe.exec(e);if(!t)return null +;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] +;return t.splice(0,n),Object.assign(t,i)}}class i{constructor(){ +this.rules=[],this.multiRegexes=[], +this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ +if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n +;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), +t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ +return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ +this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ +const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex +;let n=t.exec(e) +;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ +const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} +return n&&(this.regexIndex+=n.position+1, +this.regexIndex===this.count&&this.considerAll()),n}} +if(e.compilerExtensions||(e.compilerExtensions=[]), +e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") +;return e.classNameAliases=s(e.classNameAliases||{}),function n(r,o){const a=r +;if(r.isCompiled)return a +;[j,B,X,L].forEach((e=>e(r,o))),e.compilerExtensions.forEach((e=>e(r,o))), +r.__beforeBegin=null,[A,I,T].forEach((e=>e(r,o))),r.isCompiled=!0;let l=null +;return"object"==typeof r.keywords&&r.keywords.$pattern&&(r.keywords=Object.assign({},r.keywords), +l=r.keywords.$pattern, +delete r.keywords.$pattern),l=l||/\w+/,r.keywords&&(r.keywords=P(r.keywords,e.case_insensitive)), +a.keywordPatternRe=t(l,!0), +o&&(r.begin||(r.begin=/\B|\b/),a.beginRe=t(r.begin),r.end||r.endsWithParent||(r.end=/\B|\b/), +r.end&&(a.endRe=t(r.end)), +a.terminatorEnd=g(r.end)||"",r.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(r.end?"|":"")+o.terminatorEnd)), +r.illegal&&(a.illegalRe=t(r.illegal)), +r.contains||(r.contains=[]),r.contains=[].concat(...r.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>s(e,{ +variants:null},t)))),e.cachedVariants?e.cachedVariants:Z(e)?s(e,{ +starts:e.starts?s(e.starts):null +}):Object.isFrozen(e)?s(e):e))("self"===e?r:e)))),r.contains.forEach((e=>{n(e,a) +})),r.starts&&n(r.starts,o),a.matcher=(e=>{const t=new i +;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" +}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" +}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function Z(e){ +return!!e&&(e.endsWithParent||Z(e.starts))}const F=r,V=s,q=Symbol("nomatch") +;var J=(e=>{const t=Object.create(null),r=Object.create(null),s=[];let o=!0 +;const a="Could not find the language '{}', did you forget to load/include a language module?",l={ +disableAutodetect:!0,name:"Plain text",contains:[]};let g={ +ignoreUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, +languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", +cssSelector:"pre code",languages:null,__emitter:c};function d(e){ +return g.noHighlightRe.test(e)}function u(e,t,n,i){let r="",s="" +;"object"==typeof t?(r=e, +n=t.ignoreIllegals,s=t.language,i=void 0):(z("10.7.0","highlight(lang, code, ...args) has been deprecated."), +z("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), +s=e,r=t),void 0===n&&(n=!0);const o={code:r,language:s};w("before:highlight",o) +;const a=o.result?o.result:h(o.language,o.code,n,i) +;return a.code=o.code,w("after:highlight",a),a}function h(e,n,r,s){ +const l=Object.create(null);function c(){if(!k.keywords)return void S.addText(M) +;let e=0;k.keywordPatternRe.lastIndex=0;let t=k.keywordPatternRe.exec(M),n="" +;for(;t;){n+=M.substring(e,t.index) +;const r=_.case_insensitive?t[0].toLowerCase():t[0],s=(i=r,k.keywords[i]);if(s){ +const[e,i]=s +;if(S.addText(n),n="",l[r]=(l[r]||0)+1,l[r]<=7&&(R+=i),e.startsWith("_"))n+=t[0];else{ +const n=_.classNameAliases[e]||e;S.addKeyword(t[0],n)}}else n+=t[0] +;e=k.keywordPatternRe.lastIndex,t=k.keywordPatternRe.exec(M)}var i +;n+=M.substr(e),S.addText(n)}function d(){null!=k.subLanguage?(()=>{ +if(""===M)return;let e=null;if("string"==typeof k.subLanguage){ +if(!t[k.subLanguage])return void S.addText(M) +;e=h(k.subLanguage,M,!0,N[k.subLanguage]),N[k.subLanguage]=e._top +}else e=f(M,k.subLanguage.length?k.subLanguage:null) +;k.relevance>0&&(R+=e.relevance),S.addSublanguage(e._emitter,e.language) +})():c(),M=""}function u(e,t){let n=1;for(;void 0!==t[n];){if(!e._emit[n]){n++ +;continue}const i=_.classNameAliases[e[n]]||e[n],r=t[n] +;i?S.addKeyword(r,i):(M=r,c(),M=""),n++}}function p(e,t){ +return e.scope&&"string"==typeof e.scope&&S.openNode(_.classNameAliases[e.scope]||e.scope), +e.beginScope&&(e.beginScope._wrap?(S.addKeyword(M,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), +M=""):e.beginScope._multi&&(u(e.beginScope,t),M="")),k=Object.create(e,{parent:{ +value:k}}),k}function b(e,t,n){let r=((e,t)=>{const n=e&&e.exec(t) +;return n&&0===n.index})(e.endRe,n);if(r){if(e["on:end"]){const n=new i(e) +;e["on:end"](t,n),n.isMatchIgnored&&(r=!1)}if(r){ +for(;e.endsParent&&e.parent;)e=e.parent;return e}} +if(e.endsWithParent)return b(e.parent,t,n)}function m(e){ +return 0===k.matcher.regexIndex?(M+=e[0],1):(I=!0,0)}function x(e){ +const t=e[0],i=n.substr(e.index),r=b(k,e,i);if(!r)return q;const s=k +;k.endScope&&k.endScope._wrap?(d(), +S.addKeyword(t,k.endScope._wrap)):k.endScope&&k.endScope._multi?(d(), +u(k.endScope,e)):s.skip?M+=t:(s.returnEnd||s.excludeEnd||(M+=t), +d(),s.excludeEnd&&(M=t));do{ +k.scope&&!k.isMultiClass&&S.closeNode(),k.skip||k.subLanguage||(R+=k.relevance), +k=k.parent}while(k!==r.parent) +;return r.starts&&p(r.starts,e),s.returnEnd?0:t.length}let y={};function w(t,s){ +const a=s&&s[0];if(M+=t,null==a)return d(),0 +;if("begin"===y.type&&"end"===s.type&&y.index===s.index&&""===a){ +if(M+=n.slice(s.index,s.index+1),!o){const t=Error(`0 width match regex (${e})`) +;throw t.languageName=e,t.badRule=y.rule,t}return 1} +if(y=s,"begin"===s.type)return(e=>{ +const t=e[0],n=e.rule,r=new i(n),s=[n.__beforeBegin,n["on:begin"]] +;for(const n of s)if(n&&(n(e,r),r.isMatchIgnored))return m(t) +;return n.skip?M+=t:(n.excludeBegin&&(M+=t), +d(),n.returnBegin||n.excludeBegin||(M=t)),p(n,e),n.returnBegin?0:t.length})(s) +;if("illegal"===s.type&&!r){ +const e=Error('Illegal lexeme "'+a+'" for mode "'+(k.scope||"")+'"') +;throw e.mode=k,e}if("end"===s.type){const e=x(s);if(e!==q)return e} +if("illegal"===s.type&&""===a)return 1 +;if(A>1e5&&A>3*s.index)throw Error("potential infinite loop, way more iterations than matches") +;return M+=a,a.length}const _=E(e) +;if(!_)throw $(a.replace("{}",e)),Error('Unknown language: "'+e+'"') +;const v=G(_);let O="",k=s||v;const N={},S=new g.__emitter(g);(()=>{const e=[] +;for(let t=k;t!==_;t=t.parent)t.scope&&e.unshift(t.scope) +;e.forEach((e=>S.openNode(e)))})();let M="",R=0,j=0,A=0,I=!1;try{ +for(k.matcher.considerAll();;){ +A++,I?I=!1:k.matcher.considerAll(),k.matcher.lastIndex=j +;const e=k.matcher.exec(n);if(!e)break;const t=w(n.substring(j,e.index),e) +;j=e.index+t}return w(n.substr(j)),S.closeAllNodes(),S.finalize(),O=S.toHTML(),{ +language:e,value:O,relevance:R,illegal:!1,_emitter:S,_top:k}}catch(t){ +if(t.message&&t.message.includes("Illegal"))return{language:e,value:F(n), +illegal:!0,relevance:0,_illegalBy:{message:t.message,index:j, +context:n.slice(j-100,j+100),mode:t.mode,resultSoFar:O},_emitter:S};if(o)return{ +language:e,value:F(n),illegal:!1,relevance:0,errorRaised:t,_emitter:S,_top:k} +;throw t}}function f(e,n){n=n||g.languages||Object.keys(t);const i=(e=>{ +const t={value:F(e),illegal:!1,relevance:0,_top:l,_emitter:new g.__emitter(g)} +;return t._emitter.addText(e),t})(e),r=n.filter(E).filter(y).map((t=>h(t,e,!1))) +;r.unshift(i);const s=r.sort(((e,t)=>{ +if(e.relevance!==t.relevance)return t.relevance-e.relevance +;if(e.language&&t.language){if(E(e.language).supersetOf===t.language)return 1 +;if(E(t.language).supersetOf===e.language)return-1}return 0})),[o,a]=s,c=o +;return c.secondBest=a,c}function p(e){let t=null;const n=(e=>{ +let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" +;const n=g.languageDetectRe.exec(t);if(n){const t=E(n[1]) +;return t||(U(a.replace("{}",n[1])), +U("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} +return t.split(/\s+/).find((e=>d(e)||E(e)))})(e);if(d(n))return +;w("before:highlightElement",{el:e,language:n +}),!g.ignoreUnescapedHTML&&e.children.length>0&&(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), +console.warn("https://github.com/highlightjs/highlight.js/issues/2886"), +console.warn(e)),t=e;const i=t.textContent,s=n?u(i,{language:n,ignoreIllegals:!0 +}):f(i);e.innerHTML=s.value,((e,t,n)=>{const i=t&&r[t]||n +;e.classList.add("hljs"),e.classList.add("language-"+i) +})(e,n,s.language),e.result={language:s.language,re:s.relevance, +relevance:s.relevance},s.secondBest&&(e.secondBest={ +language:s.secondBest.language,relevance:s.secondBest.relevance +}),w("after:highlightElement",{el:e,result:s,text:i})}let b=!1;function m(){ +"loading"!==document.readyState?document.querySelectorAll(g.cssSelector).forEach(p):b=!0 +}function E(e){return e=(e||"").toLowerCase(),t[e]||t[r[e]]} +function x(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ +r[e.toLowerCase()]=t}))}function y(e){const t=E(e) +;return t&&!t.disableAutodetect}function w(e,t){const n=e;s.forEach((e=>{ +e[n]&&e[n](t)}))} +"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ +b&&m()}),!1),Object.assign(e,{highlight:u,highlightAuto:f,highlightAll:m, +highlightElement:p, +highlightBlock:e=>(z("10.7.0","highlightBlock will be removed entirely in v12.0"), +z("10.7.0","Please use highlightElement now."),p(e)),configure:e=>{g=V(g,e)}, +initHighlighting:()=>{ +m(),z("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, +initHighlightingOnLoad:()=>{ +m(),z("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") +},registerLanguage:(n,i)=>{let r=null;try{r=i(e)}catch(e){ +if($("Language definition for '{}' could not be registered.".replace("{}",n)), +!o)throw e;$(e),r=l} +r.name||(r.name=n),t[n]=r,r.rawDefinition=i.bind(null,e),r.aliases&&x(r.aliases,{ +languageName:n})},unregisterLanguage:e=>{delete t[e] +;for(const t of Object.keys(r))r[t]===e&&delete r[t]}, +listLanguages:()=>Object.keys(t),getLanguage:E,registerAliases:x, +autoDetection:y,inherit:V,addPlugin:e=>{(e=>{ +e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ +e["before:highlightBlock"](Object.assign({block:t.el},t)) +}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ +e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),s.push(e)} +}),e.debugMode=()=>{o=!1},e.safeMode=()=>{o=!0},e.versionString="11.0.1" +;for(const e in M)"object"==typeof M[e]&&n(M[e]);return Object.assign(e,M),e +})({}),Y=Object.freeze({__proto__:null});const Q=J +;for(const e of Object.keys(Y)){const t=e.replace("grmr_","") +;Q.registerLanguage(t,Y[e])}return Q}() +;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);hljs.registerLanguage("xml",(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function n(e){return a("(?=",e,")")} +function a(...n){return n.map((n=>e(n))).join("")}function s(...n){ +return"("+((e=>{const n=e[e.length-1] +;return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{} +})(n).capture?"":"?:")+n.map((n=>e(n))).join("|")+")"}return e=>{ +const t=a(/[A-Z_]/,a("(?:",/[A-Z0-9_.-]*:/,")?"),/[A-Z0-9_.-]*/),i={ +className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},c={begin:/\s/, +contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] +},r=e.inherit(c,{begin:/\(/,end:/\)/}),l=e.inherit(e.APOS_STRING_MODE,{ +className:"string"}),g=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),m={ +endsWithParent:!0,illegal:/`]+/}]}]}]};return{ +name:"HTML, XML", +aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], +case_insensitive:!0,contains:[{className:"meta",begin://, +relevance:10,contains:[c,g,l,r,{begin:/\[/,end:/\]/,contains:[{className:"meta", +begin://,contains:[c,r,g,l]}]}]},e.COMMENT(//,{ +relevance:10}),{begin://,relevance:10},i,{ +className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"style"},contains:[m],starts:{ +end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"script"},contains:[m],starts:{ +end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ +className:"tag",begin:/<>|<\/>/},{className:"tag", +begin:a(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name", +begin:t,relevance:0,starts:m}]},{className:"tag",begin:a(/<\//,n(a(t,/>/))), +contains:[{className:"name",begin:t,relevance:0},{begin:/>/,relevance:0, +endsParent:!0}]}]}}})());hljs.registerLanguage("markdown",(()=>{"use strict";function n(...n){ +return n.map((n=>{return(e=n)?"string"==typeof e?e:e.source:null;var e +})).join("")}return e=>{const a={begin:/<\/?[A-Za-z_]/,end:">", +subLanguage:"xml",relevance:0},i={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0 +},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, +relevance:2},{begin:n(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), +relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ +begin:/\[.+?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{ +className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, +returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", +excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", +end:"\\]",excludeBegin:!0,excludeEnd:!0}]},s={className:"strong",contains:[], +variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},c={ +className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{ +begin:/_(?!_)/,end:/_/,relevance:0}]};s.contains.push(c),c.contains.push(s) +;let t=[a,i] +;return s.contains=s.contains.concat(t),c.contains=c.contains.concat(t), +t=t.concat(s,c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ +className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:t},{ +begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", +contains:t}]}]},a,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", +end:"\\s+",excludeEnd:!0},s,c,{className:"quote",begin:"^>\\s+",contains:t, +end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ +begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ +begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", +contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ +begin:"^[-\\*]{3,}",end:"$"},i,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ +className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ +className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})());hljs.registerLanguage("css",(()=>{"use strict" +;const e=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","p","q","quote","samp","section","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],t=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"],i=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"],o=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"],r=["align-content","align-items","align-self","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","auto","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","clip-path","color","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","cursor","direction","display","empty-cells","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-variant","font-variant-ligatures","font-variation-settings","font-weight","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inherit","initial","justify-content","left","letter-spacing","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","mask","max-height","max-width","min-height","min-width","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","perspective","perspective-origin","pointer-events","position","quotes","resize","right","src","tab-size","table-layout","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-indent","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","white-space","widows","width","word-break","word-spacing","word-wrap","z-index"].reverse() +;return n=>{const a=(e=>({IMPORTANT:{scope:"meta",begin:"!important"},HEXCOLOR:{ +scope:"number",begin:"#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})"}, +ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", +contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{ +scope:"number", +begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", +relevance:0}}))(n),l=[n.APOS_STRING_MODE,n.QUOTE_STRING_MODE];return{name:"CSS", +case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"}, +classNameAliases:{keyframePosition:"selector-tag"}, +contains:[n.C_BLOCK_COMMENT_MODE,{begin:/-(webkit|moz|ms|o)-(?=[a-z])/ +},a.CSS_NUMBER_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0 +},{className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0 +},a.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{ +begin:":("+i.join("|")+")"},{begin:"::("+o.join("|")+")"}]},{ +className:"attribute",begin:"\\b("+r.join("|")+")\\b"},{begin:":",end:"[;}]", +contains:[a.HEXCOLOR,a.IMPORTANT,a.CSS_NUMBER_MODE,...l,{ +begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri" +},contains:[{className:"string",begin:/[^)]/,endsWithParent:!0,excludeEnd:!0}] +},{className:"built_in",begin:/[\w-]+(?=\()/}]},{ +begin:(s=/@/,((...e)=>e.map((e=>(e=>e?"string"==typeof e?e:e.source:null)(e))).join(""))("(?=",s,")")), +end:"[{;]",relevance:0,illegal:/:/,contains:[{className:"keyword", +begin:/@-?\w[\w]*(-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0, +relevance:0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only", +attribute:t.join(" ")},contains:[{begin:/[a-z-]+(?=:)/,className:"attribute" +},...l,a.CSS_NUMBER_MODE]}]},{className:"selector-tag", +begin:"\\b("+e.join("|")+")\\b"}]};var s}})());hljs.registerLanguage("plaintext",(()=>{"use strict";return t=>({ +name:"Plain text",aliases:["text","txt"],disableAutodetect:!0})})());hljs.registerLanguage("bash",(()=>{"use strict";function e(...e){ +return e.map((e=>{return(s=e)?"string"==typeof s?s:s.source:null;var s +})).join("")}return s=>{const n={},t={begin:/\$\{/,end:/\}/,contains:["self",{ +begin:/:-/,contains:[n]}]};Object.assign(n,{className:"variable",variants:[{ +begin:e(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},t]});const a={ +className:"subst",begin:/\$\(/,end:/\)/,contains:[s.BACKSLASH_ESCAPE]},i={ +begin:/<<-?\s*(?=\w+)/,starts:{contains:[s.END_SAME_AS_BEGIN({begin:/(\w+)/, +end:/(\w+)/,className:"string"})]}},c={className:"string",begin:/"/,end:/"/, +contains:[s.BACKSLASH_ESCAPE,n,a]};a.contains.push(c);const o={begin:/\$\(\(/, +end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},s.NUMBER_MODE,n] +},r=s.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 +}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, +contains:[s.inherit(s.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ +name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z._-]+\b/, +keyword:["if","then","else","elif","fi","for","while","in","do","done","case","esac","function"], +literal:["true","false"], +built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp" +},contains:[r,s.SHEBANG(),l,o,s.HASH_COMMENT_MODE,i,c,{className:"",begin:/\\"/ +},{className:"string",begin:/'/,end:/'/},n]}}})());hljs.registerLanguage("kotlin",(()=>{"use strict" +;var e="\\.([0-9](_*[0-9])*)",n="[0-9a-fA-F](_*[0-9a-fA-F])*",a={ +className:"number",variants:[{ +begin:`(\\b([0-9](_*[0-9])*)((${e})|\\.)?|(${e}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:`\\b([0-9](_*[0-9])*)((${e})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{ +begin:`(${e})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{ +begin:`\\b0[xX]((${n})\\.?|(${n})?\\.(${n}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${n})[lL]?\\b`},{ +begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], +relevance:0};return e=>{const n={ +keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual", +built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing", +literal:"true false null"},i={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@" +},s={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},t={ +className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},r={className:"string", +variants:[{begin:'"""',end:'"""(?=[^"])',contains:[t,s]},{begin:"'",end:"'", +illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/, +contains:[e.BACKSLASH_ESCAPE,t,s]}]};s.contains.push(r);const l={ +className:"meta", +begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?" +},c={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/, +end:/\)/,contains:[e.inherit(r,{className:"string"})]}] +},o=a,b=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),E={ +variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/, +contains:[]}]},d=E;return d.variants[1].contains=[E],E.variants[1].contains=[d], +{name:"Kotlin",aliases:["kt","kts"],keywords:n, +contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag", +begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,b,{className:"keyword", +begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol", +begin:/@\w+/}]}},i,l,c,{className:"function",beginKeywords:"fun",end:"[(]|$", +returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{ +begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, +contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://, +keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/, +endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/, +endsWithParent:!0,contains:[E,e.C_LINE_COMMENT_MODE,b],relevance:0 +},e.C_LINE_COMMENT_MODE,b,l,c,r,e.C_NUMBER_MODE]},b]},{className:"class", +beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0, +illegal:"extends implements",contains:[{ +beginKeywords:"public protected internal private constructor" +},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0, +excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/, +excludeBegin:!0,returnEnd:!0},l,c]},r,{className:"meta",begin:"^#!/usr/bin/env", +end:"$",illegal:"\n"},o]}}})());hljs.registerLanguage("diff",(()=>{"use strict";function e(...e){ +return"("+((e=>{const n=e[e.length-1] +;return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{} +})(e).capture?"":"?:")+e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null +;var n})).join("|")+")"}return n=>({name:"Diff",aliases:["patch"],contains:[{ +className:"meta",relevance:10, +match:e(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/) +},{className:"comment",variants:[{ +begin:e(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/), +end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{ +className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/, +end:/$/}]})})());hljs.registerLanguage("shell",(()=>{"use strict";return s=>({ +name:"Shell Session",aliases:["console","shellsession"],contains:[{ +className:"meta",begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{ +end:/[^\\](?=\s*$)/,subLanguage:"bash"}}]})})());hljs.registerLanguage("json",(()=>{"use strict";return e=>({name:"JSON", +contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01 +},{match:/[{}[\],:]/,className:"punctuation",relevance:0},e.QUOTE_STRING_MODE,{ +beginKeywords:"true false null" +},e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:"\\S"}) +})());hljs.registerLanguage("java",(()=>{"use strict" +;var e="\\.([0-9](_*[0-9])*)",a="[0-9a-fA-F](_*[0-9a-fA-F])*",n={ +className:"number",variants:[{ +begin:`(\\b([0-9](_*[0-9])*)((${e})|\\.)?|(${e}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:`\\b([0-9](_*[0-9])*)((${e})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{ +begin:`(${e})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{ +begin:`\\b0[xX]((${a})\\.?|(${a})?\\.(${a}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${a})[lL]?\\b`},{ +begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], +relevance:0};function s(e,a,n){return-1===n?"":e.replace(a,(t=>s(e,a,n-1)))} +return e=>{ +const a="[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*",t=a+s("(?:<"+a+"~~~(?:\\s*,\\s*"+a+"~~~)*>)?",/~~~/g,2),i={ +keyword:["synchronized","abstract","private","var","static","if","const ","for","while","strictfp","finally","protected","import","native","final","void","enum","else","break","transient","catch","instanceof","volatile","case","assert","package","default","public","try","switch","continue","throws","protected","public","private","module","requires","exports","do"], +literal:["false","true","null"], +type:["char","boolean","long","float","int","byte","short","double"], +built_in:["super","this"]},r={className:"meta",begin:"@"+a,contains:[{ +begin:/\(/,end:/\)/,contains:["self"]}]},l={className:"params",begin:/\(/, +end:/\)/,keywords:i,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE],endsParent:!0} +;return{name:"Java",aliases:["jsp"],keywords:i,illegal:/<\/|#/, +contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/, +relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{ +begin:/import java\.[a-z]+\./,keywords:"import",relevance:2 +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{ +match:[/\b(?:class|interface|enum|extends|implements|new)/,/\s+/,a],className:{ +1:"keyword",3:"title.class"}},{begin:[a,/\s+/,a,/\s+/,/=/],className:{1:"type", +3:"variable",5:"operator"}},{begin:[/record/,/\s+/,a],className:{1:"keyword", +3:"title.class"},contains:[l,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ +beginKeywords:"new throw return else",relevance:0},{ +begin:["(?:"+t+"\\s+)",e.UNDERSCORE_IDENT_RE,/\s*(?=\()/],className:{ +2:"title.function"},keywords:i,contains:[{className:"params",begin:/\(/, +end:/\)/,keywords:i,relevance:0, +contains:[r,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,n,e.C_BLOCK_COMMENT_MODE] +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},n,r]}}})());hljs.registerLanguage("objectivec",(()=>{"use strict";return e=>{ +const n=/[a-zA-Z@][a-zA-Z0-9_]*/,_={$pattern:n, +keyword:["@interface","@class","@protocol","@implementation"]};return{ +name:"Objective-C",aliases:["mm","objc","obj-c","obj-c++","objective-c++"], +keywords:{$pattern:n, +keyword:["int","float","while","char","export","sizeof","typedef","const","struct","for","union","unsigned","long","volatile","static","bool","mutable","if","do","return","goto","void","enum","else","break","extern","asm","case","short","default","double","register","explicit","signed","typename","this","switch","continue","wchar_t","inline","readonly","assign","readwrite","self","@synchronized","id","typeof","nonatomic","super","unichar","IBOutlet","IBAction","strong","weak","copy","in","out","inout","bycopy","byref","oneway","__strong","__weak","__block","__autoreleasing","@private","@protected","@public","@try","@property","@end","@throw","@catch","@finally","@autoreleasepool","@synthesize","@dynamic","@selector","@optional","@required","@encode","@package","@import","@defs","@compatibility_alias","__bridge","__bridge_transfer","__bridge_retained","__bridge_retain","__covariant","__contravariant","__kindof","_Nonnull","_Nullable","_Null_unspecified","__FUNCTION__","__PRETTY_FUNCTION__","__attribute__","getter","setter","retain","unsafe_unretained","nonnull","nullable","null_unspecified","null_resettable","class","instancetype","NS_DESIGNATED_INITIALIZER","NS_UNAVAILABLE","NS_REQUIRES_SUPER","NS_RETURNS_INNER_POINTER","NS_INLINE","NS_AVAILABLE","NS_DEPRECATED","NS_ENUM","NS_OPTIONS","NS_SWIFT_UNAVAILABLE","NS_ASSUME_NONNULL_BEGIN","NS_ASSUME_NONNULL_END","NS_REFINED_FOR_SWIFT","NS_SWIFT_NAME","NS_SWIFT_NOTHROW","NS_DURING","NS_HANDLER","NS_ENDHANDLER","NS_VALUERETURN","NS_VOIDRETURN"], +literal:["false","true","FALSE","TRUE","nil","YES","NO","NULL"], +built_in:["BOOL","dispatch_once_t","dispatch_queue_t","dispatch_sync","dispatch_async","dispatch_once"] +},illegal:"/,end:/$/,illegal:"\\n" +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"class", +begin:"("+_.keyword.join("|")+")\\b",end:/(\{|$)/,excludeEnd:!0,keywords:_, +contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"\\."+e.UNDERSCORE_IDENT_RE, +relevance:0}]}}})());hljs.registerLanguage("dart",(()=>{"use strict";return e=>{const n={ +className:"subst",variants:[{begin:"\\$[A-Za-z0-9_]+"}]},a={className:"subst", +variants:[{begin:/\$\{/,end:/\}/}],keywords:"true false null this is new super" +},t={className:"string",variants:[{begin:"r'''",end:"'''"},{begin:'r"""', +end:'"""'},{begin:"r'",end:"'",illegal:"\\n"},{begin:'r"',end:'"',illegal:"\\n" +},{begin:"'''",end:"'''",contains:[e.BACKSLASH_ESCAPE,n,a]},{begin:'"""', +end:'"""',contains:[e.BACKSLASH_ESCAPE,n,a]},{begin:"'",end:"'",illegal:"\\n", +contains:[e.BACKSLASH_ESCAPE,n,a]},{begin:'"',end:'"',illegal:"\\n", +contains:[e.BACKSLASH_ESCAPE,n,a]}]};a.contains=[e.C_NUMBER_MODE,t] +;const i=["Comparable","DateTime","Duration","Function","Iterable","Iterator","List","Map","Match","Object","Pattern","RegExp","Set","Stopwatch","String","StringBuffer","StringSink","Symbol","Type","Uri","bool","double","int","num","Element","ElementList"],r=i.map((e=>e+"?")) +;return{name:"Dart",keywords:{ +keyword:["abstract","as","assert","async","await","break","case","catch","class","const","continue","covariant","default","deferred","do","dynamic","else","enum","export","extends","extension","external","factory","false","final","finally","for","Function","get","hide","if","implements","import","in","inferface","is","late","library","mixin","new","null","on","operator","part","required","rethrow","return","set","show","static","super","switch","sync","this","throw","true","try","typedef","var","void","while","with","yield"], +built_in:i.concat(r).concat(["Never","Null","dynamic","print","document","querySelector","querySelectorAll","window"]), +$pattern:/[A-Za-z][A-Za-z0-9_]*\??/}, +contains:[t,e.COMMENT(/\/\*\*(?!\/)/,/\*\//,{subLanguage:"markdown",relevance:0 +}),e.COMMENT(/\/{3,} ?/,/$/,{contains:[{subLanguage:"markdown",begin:".", +end:"$",relevance:0}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{ +className:"class",beginKeywords:"class interface",end:/\{/,excludeEnd:!0, +contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE] +},e.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"},{begin:"=>"}]}}})());hljs.registerLanguage("ruby",(()=>{"use strict";function e(e){ +return n("(?=",e,")")}function n(...e){return e.map((e=>{ +return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return a=>{ +const i="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",s={ +keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor __FILE__", +built_in:"proc lambda",literal:"true false nil"},r={className:"doctag", +begin:"@[A-Za-z]+"},b={begin:"#<",end:">"},c=[a.COMMENT("#","$",{contains:[r] +}),a.COMMENT("^=begin","^=end",{contains:[r],relevance:10 +}),a.COMMENT("^__END__","\\n$")],t={className:"subst",begin:/#\{/,end:/\}/, +keywords:s},g={className:"string",contains:[a.BACKSLASH_ESCAPE,t],variants:[{ +begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/, +end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{ +begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/, +end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{ +begin:/\B\?(\\\d{1,3})/},{begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{ +begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{ +begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{ +begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{ +begin:n(/<<[-~]?'?/,e(/(\w+)(?=\W)[^\n]*\n(?:[^\n]*\n)*?\s*\1\b/)), +contains:[a.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/, +contains:[a.BACKSLASH_ESCAPE,t]})]}]},d="[0-9](_?[0-9])*",l={className:"number", +relevance:0,variants:[{ +begin:`\\b([1-9](_?[0-9])*|0)(\\.(${d}))?([eE][+-]?(${d})|r)?i?\\b`},{ +begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b" +},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{ +begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{ +begin:"\\b0(_?[0-7])+r?i?\\b"}]},o={className:"params",begin:"\\(",end:"\\)", +endsParent:!0,keywords:s},_=[g,{className:"class",beginKeywords:"class module", +end:"$|;",illegal:/=/,contains:[a.inherit(a.TITLE_MODE,{ +begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|!)?"}),{begin:"<\\s*",contains:[{ +begin:"("+a.IDENT_RE+"::)?"+a.IDENT_RE,relevance:0}]}].concat(c)},{ +className:"function",begin:n(/def\s+/,e(i+"\\s*(\\(|;|$)")),relevance:0, +keywords:"def",end:"$|;",contains:[a.inherit(a.TITLE_MODE,{begin:i +}),o].concat(c)},{begin:a.IDENT_RE+"::"},{className:"symbol", +begin:a.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol", +begin:":(?!\\s)",contains:[g,{begin:i}],relevance:0},l,{className:"variable", +begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{ +className:"params",begin:/\|/,end:/\|/,relevance:0,keywords:s},{ +begin:"("+a.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{ +className:"regexp",contains:[a.BACKSLASH_ESCAPE,t],illegal:/\n/,variants:[{ +begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(", +end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}] +}].concat(b,c),relevance:0}].concat(b,c);t.contains=_,o.contains=_;const E=[{ +begin:/^\s*=>/,starts:{end:"$",contains:_}},{className:"meta", +begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])", +starts:{end:"$",contains:_}}];return c.unshift(b),{name:"Ruby", +aliases:["rb","gemspec","podspec","thor","irb"],keywords:s,illegal:/\/\*/, +contains:[a.SHEBANG({binary:"ruby"})].concat(E).concat(c).concat(_)}}})());hljs.registerLanguage("yaml",(()=>{"use strict";return e=>{ +const n="true false yes no null",a="[\\w#;/?:@&=+$,.~*'()[\\]]+",s={ +className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/ +},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable", +variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(s,{ +variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={ +end:",",endsWithParent:!0,excludeEnd:!0,keywords:n,relevance:0},t={begin:/\{/, +end:/\}/,contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]", +contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",variants:[{ +begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{ +begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$", +relevance:10},{className:"string", +begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{ +begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0, +relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type", +begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a +},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta", +begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)", +relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{ +className:"number", +begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b" +},{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},t,g,s],c=[...b] +;return c.pop(),c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0, +aliases:["yml"],contains:b}}})());hljs.registerLanguage("javascript",(()=>{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer","BigInt64Array","BigUint64Array","BigInt"],s=["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],i=["arguments","this","super","console","window","document","localStorage","module","global"],c=[].concat(r,t,s) +;function o(e){return l("(?=",e,")")}function l(...e){return e.map((e=>{ +return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return b=>{ +const g=e,d={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/, +isTrulyOpeningTag:(e,n)=>{const a=e[0].length+e.index,t=e.input[a] +;"<"!==t?">"===t&&(((e,{after:n})=>{const a="",B={ +match:[/const|var|let/,/\s+/,g,/\s*/,/=\s*/,o(C)],className:{1:"keyword", +3:"title.function"},contains:[w]};return{name:"Javascript", +aliases:["js","jsx","mjs","cjs"],keywords:u,exports:{PARAMS_CONTAINS:S}, +illegal:/#(?![$_A-z])/,contains:[b.SHEBANG({label:"shebang",binary:"node", +relevance:5}),{label:"use_strict",className:"meta",relevance:10, +begin:/^\s*['"]use (strict|asm)['"]/ +},b.APOS_STRING_MODE,b.QUOTE_STRING_MODE,N,f,A,v,y,O,{className:"attr", +begin:g+o(":"),relevance:0},B,{ +begin:"("+b.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", +keywords:"return throw case",relevance:0,contains:[v,b.REGEXP_MODE,{ +className:"function",begin:C,returnBegin:!0,end:"\\s*=>",contains:[{ +className:"params",variants:[{begin:b.UNDERSCORE_IDENT_RE,relevance:0},{ +className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0, +excludeEnd:!0,keywords:u,contains:S}]}]},{begin:/,/,relevance:0},{match:/\s+/, +relevance:0},{variants:[{begin:"<>",end:""},{begin:d.begin, +"on:begin":d.isTrulyOpeningTag,end:d.end}],subLanguage:"xml",contains:[{ +begin:d.begin,end:d.end,skip:!0,contains:["self"]}]}]},I,{ +beginKeywords:"while if switch catch for"},{ +begin:"\\b(?!function)"+b.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,label:"func.def",contains:[w,b.inherit(b.TITLE_MODE,{begin:g, +className:"title.function"})]},{match:/\.\.\./,relevance:0},M,{match:"\\$"+g, +relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, +contains:[w]},T,{relevance:0,match:/\b[A-Z][A-Z_]+\b/, +className:"variable.constant"},R,k,{match:/\$[(.]/}]}}})());hljs.registerLanguage("c",(()=>{"use strict";function e(e){ +return((...e)=>e.map((e=>(e=>e?"string"==typeof e?e:e.source:null)(e))).join(""))("(?:",e,")?") +}return n=>{const t=n.COMMENT("//","$",{contains:[{begin:/\\\n/}] +}),s="[a-zA-Z_]\\w*::",r="(decltype\\(auto\\)|"+e(s)+"[a-zA-Z_]\\w*"+e("<[^<>]+>")+")",a={ +className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{ +match:/\batomic_[a-z]{3,6}\b/}]},i={className:"string",variants:[{ +begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[n.BACKSLASH_ESCAPE]},{ +begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", +end:"'",illegal:"."},n.END_SAME_AS_BEGIN({ +begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},l={ +className:"number",variants:[{begin:"\\b(0b[01']+)"},{ +begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" +},{ +begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" +}],relevance:0},c={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ +keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" +},contains:[{begin:/\\\n/,relevance:0},n.inherit(i,{className:"string"}),{ +className:"string",begin:/<.*?>/},t,n.C_BLOCK_COMMENT_MODE]},o={ +className:"title",begin:e(s)+n.IDENT_RE,relevance:0 +},d=e(s)+n.IDENT_RE+"\\s*\\(",u={ +keyword:["asm","auto","break","case","const","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","static","struct","switch","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"], +type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal128","complex","bool","imaginary"], +literal:"true false NULL", +built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr" +},g=[c,a,t,n.C_BLOCK_COMMENT_MODE,l,i],m={variants:[{begin:/=/,end:/;/},{ +begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}], +keywords:u,contains:g.concat([{begin:/\(/,end:/\)/,keywords:u, +contains:g.concat(["self"]),relevance:0}]),relevance:0},_={ +begin:"("+r+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0, +keywords:u,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:"decltype\\(auto\\)", +keywords:u,relevance:0},{begin:d,returnBegin:!0,contains:[n.inherit(o,{ +className:"title.function"})],relevance:0},{relevance:0,match:/,/},{ +className:"params",begin:/\(/,end:/\)/,keywords:u,relevance:0, +contains:[t,n.C_BLOCK_COMMENT_MODE,i,l,a,{begin:/\(/,end:/\)/,keywords:u, +relevance:0,contains:["self",t,n.C_BLOCK_COMMENT_MODE,i,l,a]}] +},a,t,n.C_BLOCK_COMMENT_MODE,c]};return{name:"C",aliases:["h"],keywords:u, +disableAutodetect:!0,illegal:"=]/,contains:[{ +beginKeywords:"final class struct"},n.TITLE_MODE]}]),exports:{preprocessor:c, +strings:i,keywords:u}}}})());hljs.registerLanguage("swift",(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function a(e){return t("(?=",e,")")} +function t(...a){return a.map((a=>e(a))).join("")}function n(...a){ +return"("+((e=>{const a=e[e.length-1] +;return"object"==typeof a&&a.constructor===Object?(e.splice(e.length-1,1),a):{} +})(a).capture?"":"?:")+a.map((a=>e(a))).join("|")+")"} +const i=e=>t(/\b/,e,/\w$/.test(e)?/\b/:/\B/),s=["Protocol","Type"].map(i),u=["init","self"].map(i),c=["Any","Self"],r=["actor","associatedtype","async","await",/as\?/,/as!/,"as","break","case","catch","class","continue","convenience","default","defer","deinit","didSet","do","dynamic","else","enum","extension","fallthrough",/fileprivate\(set\)/,"fileprivate","final","for","func","get","guard","if","import","indirect","infix",/init\?/,/init!/,"inout",/internal\(set\)/,"internal","in","is","lazy","let","mutating","nonmutating",/open\(set\)/,"open","operator","optional","override","postfix","precedencegroup","prefix",/private\(set\)/,"private","protocol",/public\(set\)/,"public","repeat","required","rethrows","return","set","some","static","struct","subscript","super","switch","throws","throw",/try\?/,/try!/,"try","typealias",/unowned\(safe\)/,/unowned\(unsafe\)/,"unowned","var","weak","where","while","willSet"],o=["false","nil","true"],l=["assignment","associativity","higherThan","left","lowerThan","none","right"],m=["#colorLiteral","#column","#dsohandle","#else","#elseif","#endif","#error","#file","#fileID","#fileLiteral","#filePath","#function","#if","#imageLiteral","#keyPath","#line","#selector","#sourceLocation","#warn_unqualified_access","#warning"],p=["abs","all","any","assert","assertionFailure","debugPrint","dump","fatalError","getVaList","isKnownUniquelyReferenced","max","min","numericCast","pointwiseMax","pointwiseMin","precondition","preconditionFailure","print","readLine","repeatElement","sequence","stride","swap","swift_unboxFromSwiftValueWithType","transcode","type","unsafeBitCast","unsafeDowncast","withExtendedLifetime","withUnsafeMutablePointer","withUnsafePointer","withVaList","withoutActuallyEscaping","zip"],F=n(/[/=\-+!*%<>&|^~?]/,/[\u00A1-\u00A7]/,/[\u00A9\u00AB]/,/[\u00AC\u00AE]/,/[\u00B0\u00B1]/,/[\u00B6\u00BB\u00BF\u00D7\u00F7]/,/[\u2016-\u2017]/,/[\u2020-\u2027]/,/[\u2030-\u203E]/,/[\u2041-\u2053]/,/[\u2055-\u205E]/,/[\u2190-\u23FF]/,/[\u2500-\u2775]/,/[\u2794-\u2BFF]/,/[\u2E00-\u2E7F]/,/[\u3001-\u3003]/,/[\u3008-\u3020]/,/[\u3030]/),d=n(F,/[\u0300-\u036F]/,/[\u1DC0-\u1DFF]/,/[\u20D0-\u20FF]/,/[\uFE00-\uFE0F]/,/[\uFE20-\uFE2F]/),b=t(F,d,"*"),h=n(/[a-zA-Z_]/,/[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,/[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,/[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,/[\u1E00-\u1FFF]/,/[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,/[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,/[\u2C00-\u2DFF\u2E80-\u2FFF]/,/[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,/[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,/[\uFE47-\uFEFE\uFF00-\uFFFD]/),f=n(h,/\d/,/[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/),w=t(h,f,"*"),y=t(/[A-Z]/,f,"*"),g=["autoclosure",t(/convention\(/,n("swift","block","c"),/\)/),"discardableResult","dynamicCallable","dynamicMemberLookup","escaping","frozen","GKInspectable","IBAction","IBDesignable","IBInspectable","IBOutlet","IBSegueAction","inlinable","main","nonobjc","NSApplicationMain","NSCopying","NSManaged",t(/objc\(/,w,/\)/),"objc","objcMembers","propertyWrapper","requires_stored_property_inits","resultBuilder","testable","UIApplicationMain","unknown","usableFromInline"],E=["iOS","iOSApplicationExtension","macOS","macOSApplicationExtension","macCatalyst","macCatalystApplicationExtension","watchOS","watchOSApplicationExtension","tvOS","tvOSApplicationExtension","swift"] +;return e=>{const F={match:/\s+/,relevance:0},h=e.COMMENT("/\\*","\\*/",{ +contains:["self"]}),v=[e.C_LINE_COMMENT_MODE,h],A={match:[/\./,n(...s,...u)], +className:{2:"keyword"}},N={match:t(/\./,n(...r)),relevance:0 +},C=r.filter((e=>"string"==typeof e)).concat(["_|0"]),D={variants:[{ +className:"keyword", +match:n(...r.filter((e=>"string"!=typeof e)).concat(c).map(i),...u)}]},k={ +$pattern:n(/\b\w+/,/#\w+/),keyword:C.concat(m),literal:o},B=[A,N,D],_=[{ +match:t(/\./,n(...p)),relevance:0},{className:"built_in", +match:t(/\b/,n(...p),/(?=\()/)}],S={match:/->/,relevance:0},M=[S,{ +className:"operator",relevance:0,variants:[{match:b},{match:`\\.(\\.|${d})+`}] +}],x="([0-9a-fA-F]_*)+",I={className:"number",relevance:0,variants:[{ +match:"\\b(([0-9]_*)+)(\\.(([0-9]_*)+))?([eE][+-]?(([0-9]_*)+))?\\b"},{ +match:`\\b0x(${x})(\\.(${x}))?([pP][+-]?(([0-9]_*)+))?\\b`},{ +match:/\b0o([0-7]_*)+\b/},{match:/\b0b([01]_*)+\b/}]},L=(e="")=>({ +className:"subst",variants:[{match:t(/\\/,e,/[0\\tnr"']/)},{ +match:t(/\\/,e,/u\{[0-9a-fA-F]{1,8}\}/)}]}),O=(e="")=>({className:"subst", +match:t(/\\/,e,/[\t ]*(?:[\r\n]|\r\n)/)}),T=(e="")=>({className:"subst", +label:"interpol",begin:t(/\\/,e,/\(/),end:/\)/}),$=(e="")=>({begin:t(e,/"""/), +end:t(/"""/,e),contains:[L(e),O(e),T(e)]}),j=(e="")=>({begin:t(e,/"/), +end:t(/"/,e),contains:[L(e),T(e)]}),P={className:"string", +variants:[$(),$("#"),$("##"),$("###"),j(),j("#"),j("##"),j("###")]},K={ +match:t(/`/,w,/`/)},z=[K,{className:"variable",match:/\$\d+/},{ +className:"variable",match:`\\$${f}+`}],q=[{match:/(@|#)available/, +className:"keyword",starts:{contains:[{begin:/\(/,end:/\)/,keywords:E, +contains:[...M,I,P]}]}},{className:"keyword",match:t(/@/,n(...g))},{ +className:"meta",match:t(/@/,w)}],U={match:a(/\b[A-Z]/),relevance:0,contains:[{ +className:"type", +match:t(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/,f,"+") +},{className:"type",match:y,relevance:0},{match:/[?!]+/,relevance:0},{ +match:/\.\.\./,relevance:0},{match:t(/\s+&\s+/,a(y)),relevance:0}]},Z={ +begin://,keywords:k,contains:[...v,...B,...q,S,U]};U.contains.push(Z) +;const V={begin:/\(/,end:/\)/,relevance:0,keywords:k,contains:["self",{ +match:t(w,/\s*:/),keywords:"_|0",relevance:0 +},...v,...B,..._,...M,I,P,...z,...q,U]},W={begin://,contains:[...v,U] +},G={begin:/\(/,end:/\)/,keywords:k,contains:[{ +begin:n(a(t(w,/\s*:/)),a(t(w,/\s+/,w,/\s*:/))),end:/:/,relevance:0,contains:[{ +className:"keyword",match:/\b_\b/},{className:"params",match:w}] +},...v,...B,...M,I,P,...q,U,V],endsParent:!0,illegal:/["']/},R={ +match:[/func/,/\s+/,n(K.match,w,b)],className:{1:"keyword",3:"title.function"}, +contains:[W,G,F],illegal:[/\[/,/%/]},X={ +match:[/\b(?:subscript|init[?!]?)/,/\s*(?=[<(])/],className:{1:"keyword"}, +contains:[W,G,F],illegal:/\[|%/},H={match:[/operator/,/\s+/,b],className:{ +1:"keyword",3:"title"}},J={begin:[/precedencegroup/,/\s+/,y],className:{ +1:"keyword",3:"title"},contains:[U],keywords:[...l,...o],end:/}/} +;for(const e of P.variants){const a=e.contains.find((e=>"interpol"===e.label)) +;a.keywords=k;const t=[...B,..._,...M,I,P,...z];a.contains=[...t,{begin:/\(/, +end:/\)/,contains:["self",...t]}]}return{name:"Swift",keywords:k, +contains:[...v,R,X,{beginKeywords:"struct protocol class extension enum actor", +end:"\\{",excludeEnd:!0,keywords:k,contains:[e.inherit(e.TITLE_MODE,{ +className:"title.class",begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/}),...B] +},H,J,{beginKeywords:"import",end:/$/,contains:[...v],relevance:0 +},...B,..._,...M,I,P,...z,...q,U,V]}}})()); \ No newline at end of file diff --git a/doc/api/static-assets/play_button.svg b/doc/api/static-assets/play_button.svg new file mode 100644 index 0000000..c39a2f4 --- /dev/null +++ b/doc/api/static-assets/play_button.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/doc/api/static-assets/readme.md b/doc/api/static-assets/readme.md new file mode 100644 index 0000000..357c11c --- /dev/null +++ b/doc/api/static-assets/readme.md @@ -0,0 +1,22 @@ +# highlight.js + +Generated from https://highlightjs.org/download/ on 2021-07-13 + +**Included languages:** + +* bash +* c +* css +* dart +* diff +* html, xml +* java +* javascript +* json +* kotlin +* markdown +* objective-c +* plaintext +* shell +* swift +* yaml diff --git a/doc/api/static-assets/script.js b/doc/api/static-assets/script.js new file mode 100644 index 0000000..e88f030 --- /dev/null +++ b/doc/api/static-assets/script.js @@ -0,0 +1,501 @@ +/* + * + * Update script.js versions in all lib/templates when modifying this file! + * + */ +function initSideNav() { + const leftNavToggle = document.getElementById('sidenav-left-toggle'); + const leftDrawer = document.querySelector('.sidebar-offcanvas-left'); + const overlay = document.getElementById('overlay-under-drawer'); + + function toggleBoth() { + if (leftDrawer) { + leftDrawer.classList.toggle('active'); + } + + if (overlay) { + overlay.classList.toggle('active'); + } + } + + if (overlay) { + overlay.addEventListener('click', toggleBoth); + } + + if (leftNavToggle) { + leftNavToggle.addEventListener('click', toggleBoth); + } +} + +function saveLeftScroll() { + const leftSidebar = document.getElementById('dartdoc-sidebar-left'); + sessionStorage.setItem('dartdoc-sidebar-left-scrollt' + window.location.pathname, leftSidebar.scrollTop.toString()); + sessionStorage.setItem('dartdoc-sidebar-left-scrolll' + window.location.pathname, leftSidebar.scrollLeft.toString()); +} + +function saveMainContentScroll() { + const mainContent = document.getElementById('dartdoc-main-content'); + sessionStorage.setItem('dartdoc-main-content-scrollt' + window.location.pathname, mainContent.scrollTop.toString()); + sessionStorage.setItem('dartdoc-main-content-scrolll' + window.location.pathname, mainContent.scrollLeft.toString()); +} + +function saveRightScroll() { + const rightSidebar = document.getElementById('dartdoc-sidebar-right'); + sessionStorage.setItem('dartdoc-sidebar-right-scrollt' + window.location.pathname, rightSidebar.scrollTop.toString()); + sessionStorage.setItem('dartdoc-sidebar-right-scrolll' + window.location.pathname, rightSidebar.scrollLeft.toString()); +} + +function restoreScrolls() { + const leftSidebar = document.getElementById('dartdoc-sidebar-left'); + const mainContent = document.getElementById('dartdoc-main-content'); + const rightSidebar = document.getElementById('dartdoc-sidebar-right'); + + try { + const leftSidebarX = sessionStorage.getItem('dartdoc-sidebar-left-scrolll' + window.location.pathname); + const leftSidebarY = sessionStorage.getItem('dartdoc-sidebar-left-scrollt' + window.location.pathname); + + const mainContentX = sessionStorage.getItem('dartdoc-main-content-scrolll' + window.location.pathname); + const mainContentY = sessionStorage.getItem('dartdoc-main-content-scrollt' + window.location.pathname); + + const rightSidebarX = sessionStorage.getItem('dartdoc-sidebar-right-scrolll' + window.location.pathname); + const rightSidebarY = sessionStorage.getItem('dartdoc-sidebar-right-scrollt' + window.location.pathname); + + leftSidebar.scrollTo(parseFloat(leftSidebarX), parseFloat(leftSidebarY)); + mainContent.scrollTo(parseFloat(mainContentX), parseFloat(mainContentY)); + rightSidebar.scrollTo(parseFloat(rightSidebarX), parseFloat(rightSidebarY)); + } finally { + // Set visibility to visible after scroll to prevent the brief appearance of the + // panel in the wrong position. + leftSidebar.style.visibility = 'visible'; + mainContent.style.visibility = 'visible'; + rightSidebar.style.visibility = 'visible'; + } +} + +function initScrollSave() { + const leftSidebar = document.getElementById('dartdoc-sidebar-left'); + const mainContent = document.getElementById('dartdoc-main-content'); + const rightSidebar = document.getElementById('dartdoc-sidebar-right'); + + leftSidebar.addEventListener("scroll", saveLeftScroll, true); + mainContent.addEventListener("scroll", saveMainContentScroll, true); + rightSidebar.addEventListener("scroll", saveRightScroll, true); +} + +const weights = { + 'library' : 2, + 'class' : 2, + 'mixin' : 3, + 'extension' : 3, + 'typedef' : 3, + 'method' : 4, + 'accessor' : 4, + 'operator' : 4, + 'constant' : 4, + 'property' : 4, + 'constructor' : 4 +}; + +function findMatches(index, query) { + if (query === '') { + return []; + } + + const allMatches = []; + + index.forEach(element => { + function score(value) { + value -= element.overriddenDepth * 10; + const weightFactor = weights[element.type] || 4; + allMatches.push({element: element, score: (value / weightFactor) >> 0}); + } + + const name = element.name; + const qualifiedName = element.qualifiedName; + const lowerName = name.toLowerCase(); + const lowerQualifiedName = qualifiedName.toLowerCase(); + const lowerQuery = query.toLowerCase(); + + if (name === query || qualifiedName === query || name === `dart:${query}`) { + score(2000); + } else if (lowerName === `dart:${lowerQuery}`) { + score(1800); + } else if (lowerName === lowerQuery || lowerQualifiedName === lowerQuery) { + score(1700); + } else if (query.length > 1) { + if (name.startsWith(query) || qualifiedName.startsWith(query)) { + score(750); + } else if (lowerName.startsWith(lowerQuery) || lowerQualifiedName.startsWith(lowerQuery)) { + score(650); + } else if (name.includes(query) || qualifiedName.includes(query)) { + score(500); + } else if (lowerName.includes(lowerQuery) || lowerQualifiedName.includes(query)) { + score(400); + } + } + }); + + allMatches.sort((a, b) => { + const x = b.score - a.score; + if (x === 0) { + return a.element.name.length - b.element.name.length; + } + return x; + }); + + const justElements = []; + + for (let i = 0; i < allMatches.length; i++) { + justElements.push(allMatches[i].element); + } + + return justElements; +} + +let baseHref = ''; + +const minLength = 1; +const suggestionLimit = 10; + +function initializeSearch(input, index) { + input.disabled = false; + input.setAttribute('placeholder', 'Search API Docs'); + + // Handle grabbing focus when the users types / outside of the input + document.addEventListener('keypress', (event) => { + if (event.code === 'Slash' && !(document.activeElement instanceof HTMLInputElement)) { + event.preventDefault(); + input.focus(); + } + }); + + // Prepare elements + + const parentForm = input.parentNode; + const wrapper = document.createElement('div'); + wrapper.classList.add('tt-wrapper'); + + parentForm.replaceChild(wrapper, input); + + const inputHint = document.createElement('input'); + inputHint.setAttribute('type', 'text'); + inputHint.setAttribute('autocomplete', 'off'); + inputHint.setAttribute('readonly', 'true'); + inputHint.setAttribute('spellcheck', 'false'); + inputHint.setAttribute('tabindex', '-1'); + inputHint.classList.add('typeahead', 'tt-hint'); + + wrapper.appendChild(inputHint); + + input.setAttribute('autocomplete', 'off'); + input.setAttribute('spellcheck', 'false'); + input.classList.add('tt-input'); + + wrapper.appendChild(input); + + const listBox = document.createElement('div'); + listBox.setAttribute('role', 'listbox'); + listBox.setAttribute('aria-expanded', 'false'); + listBox.style.display = 'none'; + listBox.classList.add('tt-menu'); + + const presentation = document.createElement('div'); + presentation.classList.add('tt-elements'); + + listBox.appendChild(presentation); + + wrapper.appendChild(listBox); + + // Set up various search functionality + + function highlight(text, query) { + query = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return text.replace(new RegExp(query, 'gi'), (matched) => { + return `${matched}`; + }); + } + + function createSuggestion(query, match) { + const suggestion = document.createElement('div'); + suggestion.setAttribute('data-href', match.href); + suggestion.classList.add('tt-suggestion'); + + const suggestionTitle = document.createElement('span'); + suggestionTitle.classList.add('tt-suggestion-title'); + suggestionTitle.innerHTML = highlight(`${match.name} ${match.type.toLowerCase()}`, query); + + suggestion.appendChild(suggestionTitle); + + if (match.enclosedBy) { + const fromLib = document.createElement('div'); + fromLib.classList.add('search-from-lib'); + fromLib.innerHTML = `from ${highlight(match.enclosedBy.name, query)}`; + + suggestion.appendChild(fromLib); + } + + suggestion.addEventListener('mousedown', event => { + event.preventDefault(); + }); + + suggestion.addEventListener('click', event => { + if (match.href) { + window.location = baseHref + match.href; + event.preventDefault(); + } + }); + + return suggestion; + } + + let storedValue = null; + let actualValue = ''; + let hint = null; + + let suggestionElements = []; + let suggestionsInfo = []; + let selectedElement = null; + + function setHint(value) { + hint = value; + inputHint.value = value || ''; + } + + function updateSuggestions(query, suggestions) { + suggestionsInfo = []; + suggestionElements = []; + presentation.textContent = ''; + + if (suggestions.length < minLength) { + setHint(null) + hideSuggestions(); + return; + } + + for (let i = 0; i < suggestions.length; i++) { + const element = createSuggestion(query, suggestions[i]); + suggestionElements.push(element); + presentation.appendChild(element); + } + + suggestionsInfo = suggestions; + + setHint(query + suggestions[0].name.slice(query.length)); + selectedElement = null; + + showSuggestions(); + } + + function handle(newValue, forceUpdate) { + if (actualValue === newValue && !forceUpdate) { + return; + } + + if (newValue === null || newValue.length === 0) { + updateSuggestions('', []); + return; + } + + const suggestions = findMatches(index, newValue).slice(0, suggestionLimit); + actualValue = newValue; + + updateSuggestions(newValue, suggestions); + } + + function showSuggestions() { + if (presentation.hasChildNodes()) { + listBox.style.display = 'block'; + listBox.setAttribute('aria-expanded', 'true'); + } + } + + function hideSuggestions() { + listBox.style.display = 'none'; + listBox.setAttribute('aria-expanded', 'false'); + } + + // Hook up events + + input.addEventListener('focus', () => { + handle(input.value, true); + }); + + input.addEventListener('blur', () => { + selectedElement = null; + if (storedValue !== null) { + input.value = storedValue; + storedValue = null; + } + hideSuggestions(); + setHint(null); + }); + + input.addEventListener('input', event => { + handle(event.target.value); + }); + + input.addEventListener('keydown', event => { + if (suggestionElements.length === 0) { + return; + } + + if (event.code === 'Enter') { + const selectingElement = selectedElement || 0; + const href = suggestionElements[selectingElement].dataset.href; + if (href) { + window.location = baseHref + href; + } + return; + } + + if (event.code === 'Tab') { + if (selectedElement === null) { + // The user wants to fill the field with the hint + if (hint !== null) { + input.value = hint; + handle(hint); + event.preventDefault(); + } + } else { + // The user wants to fill the input field with their currently selected suggestion + handle(suggestionsInfo[selectedElement].name); + storedValue = null; + selectedElement = null; + event.preventDefault(); + } + return; + } + + const lastIndex = suggestionElements.length - 1; + const previousSelectedElement = selectedElement; + + if (event.code === 'ArrowUp') { + if (selectedElement === null) { + selectedElement = lastIndex; + } else if (selectedElement === 0) { + selectedElement = null; + } else { + selectedElement--; + } + } else if (event.code === 'ArrowDown') { + if (selectedElement === null) { + selectedElement = 0; + } else if (selectedElement === lastIndex) { + selectedElement = null; + } else { + selectedElement++; + } + } else { + if (storedValue !== null) { + storedValue = null; + handle(input.value); + } + return; + } + + if (previousSelectedElement !== null) { + suggestionElements[previousSelectedElement].classList.remove('tt-cursor'); + } + + if (selectedElement !== null) { + const selected = suggestionElements[selectedElement]; + selected.classList.add('tt-cursor'); + + // Guarantee the selected element is visible + if (selectedElement === 0) { + listBox.scrollTop = 0; + } else if (selectedElement === lastIndex) { + listBox.scrollTop = listBox.scrollHeight; + } else { + const offsetTop = selected.offsetTop; + const parentOffsetHeight = listBox.offsetHeight; + if (offsetTop < parentOffsetHeight || parentOffsetHeight < (offsetTop + selected.offsetHeight)) { + selected.scrollIntoView({behavior: 'auto', block: 'nearest'}); + } + } + + if (storedValue === null) { + // Store the actual input value to display their currently selected item + storedValue = input.value; + } + input.value = suggestionsInfo[selectedElement].name; + setHint(''); + } else if (storedValue !== null && previousSelectedElement !== null) { + // They are moving back to the input field, so return the stored value + input.value = storedValue; + setHint(storedValue + suggestionsInfo[0].name.slice(storedValue.length)); + storedValue = null; + } + + event.preventDefault(); + }); +} + +document.addEventListener('DOMContentLoaded', () => { + // Place this first so that unexpected exceptions in other JavaScript do not block page visibility. + restoreScrolls(); + hljs.highlightAll(); + initSideNav(); + initScrollSave(); + + const searchBox = document.getElementById('search-box'); + const searchBody = document.getElementById('search-body'); + const searchSidebar = document.getElementById('search-sidebar'); + + if (document.body.getAttribute('data-using-base-href') === 'false') { + // If dartdoc did not add a base-href tag, we will need to add the relative + // path ourselves. + baseHref = document.body.getAttribute('data-base-href'); + } + + function disableSearch() { + console.log('Could not activate search functionality.'); + if (searchBox) { + searchBox.placeholder = 'Failed to initialize search'; + } + + if (searchBody) { + searchBody.placeholder = 'Failed to initialize search'; + } + + if (searchSidebar) { + searchSidebar.placeholder = 'Failed to initialize search'; + } + } + + if ('fetch' in window) { + fetch(baseHref + 'index.json', {method: 'GET'}) + .then(response => response.json()) + .then(index => { + // Handle if the user specified a `search` parameter in the URL + if ('URLSearchParams' in window) { + const search = new URLSearchParams(window.location.search).get('search'); + if (search) { + const matches = findMatches(search); + if (matches.length !== 0) { + window.location = baseHref + matches[0].href; + return; + } + } + } + + // Initialize all three search fields + if (searchBox) { + initializeSearch(searchBox, index); + } + + if (searchBody) { + initializeSearch(searchBody, index); + } + + if (searchSidebar) { + initializeSearch(searchSidebar, index); + } + }) + .catch(() => { + disableSearch(); + }); + } else { + disableSearch(); + } +}); diff --git a/doc/api/static-assets/styles.css b/doc/api/static-assets/styles.css new file mode 100644 index 0000000..7ea04df --- /dev/null +++ b/doc/api/static-assets/styles.css @@ -0,0 +1,1022 @@ +/* + * + * Update styles.css versions in all lib/templates when modifying this file! + * + */ + +/* Palette generated by Material Palette - materialpalette.com/blue/cyan */ + +.dark-primary-color { background: #1976D2; } +.default-primary-color { background: #2196F3; } +.light-primary-color { background: #BBDEFB; } +.text-primary-color { color: #FFFFFF; } +.accent-color { background: #00BCD4; } +.primary-text-color { color: #212121; } +.secondary-text-color { color: #727272; } +.divider-color { border-color: #B6B6B6; } + +/* for layout */ +html, +body { + margin: 0; + padding: 0; + height: 100%; + width: 100%; + overflow: hidden; + box-sizing: border-box; +} + +*, *:before, *:after { + box-sizing: inherit; +} + +body { + display: flex; + flex-direction: column; + -webkit-overflow-scrolling: touch; +} + +header { + flex: 0 0 50px; + display: flex; + flex-direction: row; + align-items: center; + padding-left: 30px; +} + +header ol { + list-style: none; + margin: 0; + padding: 0; +} + +header ol li { + display: inline; +} + +header form { + display: flex; + flex: 1; + justify-content: flex-end; + padding-right: 30px; +} + +header#header-search-sidebar { + height: 50px; + margin-bottom: 25px; +} + +footer { + flex: 0 0 16px; + text-align: center; + padding: 16px 20px; +} + +main { + flex: 1; + display: flex; + flex-direction: row; + padding: 20px; + min-height: 0; +} + +.sidebar-offcanvas-left { + flex: 0 1 230px; + order: 1; + overflow-y: scroll; + padding: 20px 0 15px 30px; + margin: 5px 20px 0 0; + visibility: hidden; /* shown by Javascript after scroll position restore */ +} + +::-webkit-scrollbar-button{ display: none; height: 13px; border-radius: 0px; background-color: #AAA; } +::-webkit-scrollbar-button:hover{ background-color: #AAA; } +::-webkit-scrollbar-thumb{ background-color: #CCC; } +::-webkit-scrollbar-thumb:hover{ background-color: #CCC; } +::-webkit-scrollbar{ width: 4px; } + +.main-content::-webkit-scrollbar{ width: 8px; } + +.main-content { + flex: 1; + order: 2; + overflow-y: scroll; + padding: 10px 20px 0 20px; + visibility: hidden; /* shown by Javascript after scroll position restore */ +} + +.sidebar-offcanvas-right { + flex: 0 1 12em; + order: 3; + overflow-y: scroll; + padding: 20px 15px 15px 15px; + margin-top: 5px; + margin-right: 20px; + visibility: hidden; /* shown by Javascript after scroll position restore */ +} +/* end for layout */ + +body { + -webkit-text-size-adjust: 100%; + overflow-x: hidden; + font-family: Roboto, sans-serif; + font-size: 16px; + line-height: 1.42857143; + color: #111111; + background-color: #fff; +} + +/* some of this is to reset bootstrap */ +nav.navbar { + background-color: inherit; + min-height: 50px; + border: 0; +} + +@media (max-width: 768px) { + .hidden-xs { + display: none !important; + } +} + +@media (min-width: 769px) { + .hidden-l { + display: none !important; + } +} + +nav.navbar .row { + padding-top: 8px; +} + +nav .container { + white-space: nowrap; +} + +header { + background-color: #eeeeee; + box-shadow: 0 3px 5px rgba(0,0,0,0.1); +} + +header.header-fixed nav.navbar-fixed-top { + box-shadow: 0 3px 5px rgba(0,0,0,0.1); +} + +header.container-fluid { + padding: 0; +} + +header .masthead { + padding-top: 64px; +} + +header .contents { + padding: 0; +} + +@media screen and (max-width:768px) { + header .contents { + padding-left: 15px; + padding-right: 15px; + } +} + +a { + text-decoration: none; +} + +.body { + margin-top: 90px; +} + +section { + margin-bottom: 36px; +} + +dl { + margin: 0; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: Roboto, sans-serif; + font-weight: 400; + margin-top: 1.5em; + color: #111111; +} + +h1.title { + overflow: hidden; + text-overflow: ellipsis; +} + +h1 { + font-size: 37px; + margin-top: 0; + margin-bottom: 0.67em; +} + +h2 { + font-size: 28px; +} + +h5 { + font-size: 16px; +} + +.subtitle { + font-size: 17px; + min-height: 1.4em; +} + +.title-description .subtitle { + white-space: nowrap; + overflow-x: hidden; + text-overflow: ellipsis; +} + +p { + margin-bottom: 1em; + margin-top: 0; +} + +a { + color: #0175C2; +} + +a:hover { + color: #13B9FD; +} + +pre.prettyprint { + font-family: 'Roboto Mono', Menlo, monospace; + color: black; + border-radius: 0; + font-size: 15px; + word-wrap: normal; + line-height: 1.4; + border: 0; + margin: 16px 0 16px 0; + padding: 8px; +} + +pre code { + white-space: pre; + word-wrap: initial; + font-size: 100% +} + +.fixed { + white-space: pre; +} + +pre { + border: 1px solid #ddd; + background-color: #eee; + font-size: 14px; +} + +code { + font-family: 'Roboto Mono', Menlo, monospace; + /* overriding bootstrap */ + color: inherit; + padding: 0.2em 0.4em; + font-size: 85%; + background-color: rgba(27,31,35,0.05); + border-radius: 3px; +} + +@media(max-width: 768px) { + nav .container { + width: 100% + } + + h1 { + font-size: 24px; + } + + pre { + margin: 16px 0; + } +} + +@media (min-width: 768px) { + ul.subnav li { + font-size: 17px; + } +} + +header h1 { + font-weight: 400; + margin-bottom: 16px; +} + +header a, +header p, +header li { + color: #111111; +} + +header a:hover { + color: #0175C2; +} + +header h1 .kind { + color: #555; +} + +dt { + font-weight: normal; +} + +dd { + color: #212121; + margin-bottom: 1em; + margin-left: 0; +} + +dd.callable, dd.constant, dd.property { + margin-bottom: 24px; +} + +dd p { + overflow-x: hidden; + text-overflow: ellipsis; + margin-bottom: 0; +} + +/* Enum values do not have their own pages; their full docs are presented on the + * enum class's page. */ +dt.constant + dd p { + margin-bottom: 1em; +} + +/* indents wrapped lines */ +section.summary dt { + margin-left: 24px; + text-indent: -24px; +} + +.dl-horizontal dd { + margin-left: initial; +} + +dl.dl-horizontal dt { + font-style: normal; + text-align: left; + color: #727272; + margin-right: 20px; + width: initial; +} + +dt .name { + font-weight: 500; +} + +dl dt.callable .name { + float: none; + width: auto; +} + +.parameter { + white-space: nowrap; +} + +.type-parameter { + white-space: nowrap; +} + +.multi-line-signature .type-parameter .parameter { + margin-left: 0px; + display: unset; +} + +.parameter-list { + display: table-cell; + margin-left: 10px; + list-style-type: none; +} + +.signature { + color: #727272; +} + +.signature a { + /* 50% mix of default-primary-color and primary-text-color. */ + color: #4674a2; +} + +.optional { + font-style: italic; +} + +.undocumented { + font-style: italic; +} + +.is-const { + font-style: italic; +} + +.deprecated { + text-decoration: line-through; +} + +.category.linked { + font-weight: bold; + opacity: 1; +} + +/* Colors for category based on categoryOrder in dartdoc_options.config. */ +.category.cp-0 { + background-color: #54b7c4 +} + +.category.cp-1 { + background-color: #54c47f +} + +.category.cp-2 { + background-color: #c4c254 +} + +.category.cp-3 { + background-color: #c49f54 +} + +.category.cp-4 { + background-color: #c45465 +} + +.category.cp-5 { + background-color: #c454c4 +} + +.category a { + color: white; +} + +.category { + padding: 2px 4px; + font-size: 12px; + border-radius: 4px; + background-color: #999; + text-transform: uppercase; + color: white; + opacity: .5; +} + +h1 .category { + vertical-align: middle; +} + +.feature { + display: inline-block; + background: white; + border: 1px solid #0175c2; + border-radius: 20px; + color: #0175c2; + + font-size: 12px; + padding: 1px 6px; + margin: 0 8px 0 0; +} + +a.feature:hover { + border-color: #13B9FD; +} + +h1 .feature { + vertical-align: middle; +} + +.source-link { + padding: 18px 4px; + vertical-align: middle; +} + +.source-link .material-icons { + font-size: 18px; +} + +@media (max-width: 768px) { + .source-link { + padding: 7px 2px; + font-size: 10px; + } +} + +#external-links { + float: right; +} + +.btn-group { + position: relative; + display: inline-flex; + vertical-align: middle; +} + +p.firstline { + font-weight: bold; +} + +footer { + color: #fff; + background-color: #111111; + width: 100%; +} + +footer p { + margin: 0; +} + +footer .no-break { + white-space: nowrap; +} + +footer .container, +footer .container-fluid { + padding-left: 0; + padding-right: 0; +} + +footer a, footer a:hover { + color: #fff; +} + +.markdown.desc { + max-width: 700px; +} + +.markdown h1 { + font-size: 24px; + margin-bottom: 8px; +} + +.markdown h2 { + font-size: 20px; + margin-top: 24px; + margin-bottom: 8px; +} + +.markdown h3 { + font-size: 18px; + margin-bottom: 8px; +} + +.markdown h4 { + font-size: 16px; + margin-bottom: 0; +} + +.markdown li p { + margin: 0; +} + +.gt-separated { + list-style: none; + padding: 0; + margin: 0; +} + +.gt-separated li { + display: inline-block; +} + +.gt-separated li:before { + background-image: url("data:image/svg+xml;utf8,"); + background-position: center; + content: "\00a0"; + margin: 0 6px 0 4px; + padding: 0 3px 0 0; +} + +.gt-separated.dark li:before { + background-image: url("data:image/svg+xml;utf8,"); +} + +.gt-separated li:first-child:before { + background-image: none; + content: ""; + margin: 0; + padding: 0; +} + +/* The slug line under a declaration for things like "const", "read-only", etc. */ +.features { + font-style: italic; + color: #727272; +} + +.multi-line-signature { + font-size: 17px; + color: #727272; +} + +.multi-line-signature .parameter { + margin-left: 24px; + display: block; +} + +.breadcrumbs { + padding: 0; + margin: 8px 0 8px 0; + white-space: nowrap; + line-height: 1; +} + +@media screen and (min-width: 768px) { + nav ol.breadcrumbs { + float: left; + } +} + +@media screen and (max-width: 768px) { + .breadcrumbs { + margin: 0 0 24px 0; + overflow-x: hidden; + } +} + +.self-crumb { + color: #555; +} + +.self-name { + color: #555; + display: none; +} + +.annotation-list { + list-style: none; + padding: 0; + display: inline; +} + +.comma-separated { + list-style: none; + padding: 0; + display: inline; +} + +.comma-separated li { + display: inline; +} + +.comma-separated li:after { + content: ", "; +} + +.comma-separated li:last-child:after { + content: ""; +} + +.end-with-period li:last-child:after { + content: "."; +} + +.container > section:first-child { + border: 0; +} + +.constructor-modifier { + font-style: italic; +} + +section.multi-line-signature div.parameters { + margin-left: 24px; +} + +/* subnav styles */ + +ul.subnav { + overflow: auto; + white-space: nowrap; + padding-left: 0; + min-height: 25px; +} + +ul.subnav::-webkit-scrollbar { + display: none; +} + +ul.subnav li { + display: inline-block; + text-transform: uppercase; +} + +ul.subnav li a { + color: #111; +} + +ul.subnav li { + margin-right: 24px; +} + +ul.subnav li:last-of-type { + margin-right: 0; +} + +@media(max-width: 768px) { + ul.subnav li { + margin-right: 16px; + } +} + +/* sidebar styles */ + +.sidebar ol { + list-style: none; + line-height: 22px; + margin-top: 0; + margin-bottom: 0; + padding: 0 0 15px 0; +} + +.sidebar h5 a, +.sidebar h5 a:hover { + color: #727272; +} + +.sidebar h5, +.sidebar ol li { + text-overflow: ellipsis; + overflow: hidden; + padding: 3px 0 3px 3px; +} + +.sidebar h5 { + color: #727272; + font-size: 18px; + margin: 0 0 22px 0; + padding-top: 0; +} + +.sidebar ol li.section-title { + font-size: 18px; + font-weight: normal; + text-transform: uppercase; + padding-top: 25px; +} + +.sidebar ol li.section-subtitle a { + color: inherit; +} + +.sidebar ol li.section-subtitle { + font-weight: 400; + text-transform: uppercase; +} + +.sidebar ol li.section-subitem { + margin-left: 12px; +} + +.sidebar ol li:first-child { + padding-top: 3px; + margin-top: 0; +} + +button { + padding: 0; +} + +#sidenav-left-toggle { + display: none; + vertical-align: text-bottom; + padding: 0; +} + +/* left-nav disappears, and can transition in from the left */ +@media screen and (max-width:768px) { + #sidenav-left-toggle { + display: inline; + background: no-repeat url("data:image/svg+xml;utf8,"); + background-position: center; + width: 24px; + height: 24px; + border: none; + margin-right: 24px; + } + + #overlay-under-drawer.active { + opacity: 0.4; + height: 100%; + z-index: 1999; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: black; + display: block; + } + + .sidebar-offcanvas-left { + left: -100%; + position: fixed; + -webkit-transition:all .25s ease-out; + -o-transition:all .25s ease-out; + transition:all .25s ease-out; + z-index: 2000; + top: 0; + width: 280px; /* works all the way down to an iphone 4 */ + height: 90%; + background-color: white; + overflow-y: scroll; /* TODO: how to hide scroll bars? */ + padding: 10px; + margin: 10px 10px; + box-shadow: 5px 5px 5px 5px #444444; + visibility: hidden; /* shown by Javascript after scroll position restore */ + } + + ol#sidebar-nav { + font-size: 18px; + white-space: pre-line; + } + + .sidebar-offcanvas-left.active { + left: 0; /* this animates our drawer into the page */ + } + + .self-name { + display: inline-block; + } +} + +.sidebar-offcanvas-left h5 { + margin-bottom: 10px; +} + +.sidebar-offcanvas-left h5:last-of-type { + border: 0; + margin-bottom: 25px; +} + +/* the right nav disappears out of view when the window shrinks */ +@media screen and (max-width: 992px) { + .sidebar-offcanvas-right { + display: none; + } +} + +#overlay-under-drawer { + display: none; +} + +/* find-as-you-type search box */ + +/* override bootstrap defaults */ +.form-control { + border-radius: 0; + border: 0; +} + +@media screen and (max-width: 768px) { + form.search { + display: none; + } +} + +.typeahead, +.tt-query, +.tt-hint { + width: 200px; + height: 20px; + padding: 2px 7px 1px 7px; + line-height: 20px; + outline: none; +} + +.typeahead { + background-color: #fff; + border-radius: 2px; +} + +.tt-wrapper { + position: relative; + display: inline-block; +} + +.tt-input { + position: relative; + vertical-align: top; + background-color: transparent; +} + +.tt-query { + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.tt-hint { + position: absolute; + top: 0; + left: 0; + box-shadow: none; + background: none 0 0 / auto repeat scroll padding-box border-box rgb(255, 255, 255); + border-color: transparent; + color: #999; + border-width: 0; +} + +.navbar-right .tt-menu { + right:0; + left: inherit !important; + width: 422px; + max-height: 250px; + overflow-y: scroll; +} + +.tt-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 100; + font-size: 14px; + margin: 0; + padding: 8px 0; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); + -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); + box-shadow: 0 5px 10px rgba(0,0,0,.2); +} + +.tt-suggestion { + padding: 3px 20px; + color: #212121; +} + +.tt-suggestion:hover { + cursor: pointer; + color: #fff; + background-color: #0097cf; +} + +.tt-suggestion:hover .search-from-lib { + color: #ddd; +} + +.tt-suggestion.tt-cursor { + color: #fff; + background-color: #0097cf; +} + +.tt-suggestion.tt-cursor .search-from-lib { + color: #ddd; +} + +.tt-suggestion p { + margin: 0; +} + +.search-from-lib { + font-style: italic; + color: gray; +} + +.search-body { + border: 1px solid #7f7f7f; + max-width: 400px; + box-shadow: 3px 3px 5px rgba(0,0,0,0.1); +} + +section#setter { + border-top: 1px solid #ddd; + padding-top: 36px; +} + +li.inherited a { + opacity: 0.65; + font-style: italic; +} + +#instance-methods dt.inherited .name, +#instance-properties dt.inherited .name, +#operators dt.inherited .name { + font-weight: 300; + font-style: italic; +} + +#instance-methods dt.inherited .signature, +#instance-properties dt.inherited .signature, +#operators dt.inherited .signature { + font-weight: 300; +} + +@media print { + .subnav, .sidebar { + display:none; + } + + a[href]:after { + content:"" !important; + } +} diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..151026b --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,33 @@ +*.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..8d4492f --- /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 + 9.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..1e8c3c9 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.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..86f9bde --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,22 @@ +PODS: + - Flutter (1.0.0) + - path_provider (0.0.1): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - path_provider (from `.symlinks/plugins/path_provider/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + path_provider: + :path: ".symlinks/plugins/path_provider/ios" + +SPEC CHECKSUMS: + Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c + path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c + +PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c + +COCOAPODS: 1.10.1 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e2a0431 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,471 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + 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 */; }; +/* 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 = ""; }; + 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 = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 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 */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + 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 = 1020; + 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; + 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 */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + 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"; + }; +/* 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 = 9.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; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flutternativetrapeze; + 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 = 9.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 = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + 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; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flutternativetrapeze; + 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; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flutternativetrapeze; + 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 */ + }; + 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/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..a28140c --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + 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/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + 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..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..9c3ffc1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..3d4c840 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..3c27068 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..5d4efea Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..3199d6b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..a9e3c2f Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..e614799 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..3c27068 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..3161048 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..cad0cc8 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..cad0cc8 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..29a0b6d Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..06ec67b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..875d769 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..23608eb Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ 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..d9d4997 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..c06978b 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..16683fe 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..9b14128 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..852917d --- /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..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..5fbe3b4 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + flutternativetrapeze + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + 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/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..81e6052 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import './src/app.dart'; + +// This is for the doc generation +// - INTERFACES +export './src/interfaces/abstract_bloc.dart'; + +// - UTILITIES +export './src/utilities/device_scan/device_scan_statistics/device_scan_statistics_bloc.dart'; +export './src/utilities/device_scan/device_scan_statistics/device_scan_statistics_handler.dart'; +export './src/utilities/device_scan/device_scan_statistics/device_scan_statistics_model.dart'; +export './src/utilities/user_management/user_bloc.dart'; +export './src/utilities/user_management/user_handler.dart'; +export './src/utilities/user_management/user_model.dart'; + +// - SCREENS +export './src/screens/home/home_screen.dart'; +export './src/screens/device_scan/device_scan_screen.dart'; +export './src/screens/device_scan/device_scan_log_screen.dart'; +export './src/screens/knowledgebase/knowledgebase_screen.dart'; + +export './src/screens/user_management/login_screen.dart'; +export './src/screens/user_management/profile_screen.dart'; + +// - WIDGETS +export './src/widgets/base_widgets/base_card_widget.dart'; +export './src/widgets/base_widgets/base_elevated_button_widget.dart'; +export './src/widgets/device_scan_summary/device_scan_summary_widget.dart'; +export './src/widgets/device_scan/device_scan_progress_widget.dart'; + +// - APP +export './src/app.dart'; + +void main() { + runApp(App()); +} diff --git a/lib/src/app.dart b/lib/src/app.dart new file mode 100644 index 0000000..f882c25 --- /dev/null +++ b/lib/src/app.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; + +import 'package:flutternativetrapeze/src/config/theme.dart'; + +import 'package:flutternativetrapeze/src/screens/home/home_screen.dart'; +import 'package:flutternativetrapeze/src/screens/device_scan/device_scan_screen.dart'; +import 'package:flutternativetrapeze/src/screens/device_scan/device_scan_log_screen.dart'; +import 'package:flutternativetrapeze/src/screens/knowledgebase/knowledgebase_screen.dart'; +import 'package:flutternativetrapeze/src/screens/user_management/login_screen.dart'; +import 'package:flutternativetrapeze/src/screens/user_management/profile_screen.dart'; + +import 'package:connectivity_wrapper/connectivity_wrapper.dart'; + +/// This [App] class is the main entry to the app. +/// +/// Here are the routes and the themes. +class App extends StatelessWidget { + /// Primary swatch; official TRAPEZE yellow + static const MaterialColor _primarySwatch = AppColors.PRIMARY_SWATCH; + + /// Fitting secondary swatch; TODO: Add inverted TRAPEZE color palette + static const MaterialColor _secondarySwatch = AppColors.SECONDARY_SWATCH; + + /// This method configures the [MaterialApp] and the routes are set here. + @override + Widget build(BuildContext context) { + return ConnectivityAppWrapper( + app: MaterialApp( + theme: ThemeData( + fontFamily: 'Arial', + brightness: Brightness.light, + colorScheme: + ColorScheme.fromSwatch(primarySwatch: App._primarySwatch) + .copyWith(secondary: App._secondarySwatch)), + darkTheme: ThemeData(brightness: Brightness.dark), + themeMode: ThemeMode.light, + + // internet connection checker with dialog + builder: (buildContext, widget) { + return ConnectivityWidgetWrapper( + child: widget!, + disableInteraction: true, + height: 70, + message: + 'Please connect to the internet. \nwe need to fetch various informations about virsues and actions against them from the internet.', + ); + }, + + initialRoute: HomeScreen.routeName, + routes: { + HomeScreen.routeName: (BuildContext context) => HomeScreen(), // home + LoginScreen.routeName: (BuildContext context) => + LoginScreen(), // user_management + ProfileScreen.routeName: (BuildContext context) => + ProfileScreen(), // user_management + DeviceScanScreen.routeName: (BuildContext context) => + DeviceScanScreen(), // device_scan + DeviceScanLogScreen.routeName: (BuildContext context) => + DeviceScanLogScreen(), // device_scan + // DeviceScanConfigurationScreen.routeName: (BuildContext context) => DeviceScanConfigurationScreen(), // device_scan + + KnowledgebaseScreen.routeName: (BuildContext context) => + KnowledgebaseScreen(), // threat_resolution + }, + ), + ); + } +} diff --git a/lib/src/config/constants.dart b/lib/src/config/constants.dart new file mode 100644 index 0000000..69e692b --- /dev/null +++ b/lib/src/config/constants.dart @@ -0,0 +1 @@ +const String LOG_FILE_NAME = "device_scan_log.json"; diff --git a/lib/src/config/paths.dart b/lib/src/config/paths.dart new file mode 100644 index 0000000..eaaf33b --- /dev/null +++ b/lib/src/config/paths.dart @@ -0,0 +1 @@ +const String PATH_TO_TRAPEZE_BANNER = "assets/images/trapeze_banner_clear_background.png"; diff --git a/lib/src/config/theme.dart b/lib/src/config/theme.dart new file mode 100644 index 0000000..1d7b599 --- /dev/null +++ b/lib/src/config/theme.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class AppColors { + static const TRAPEZE_YELLOW_RGBO_HEX = 0xFFEED216; + static const TRAPEZE_YELLOW = Color(TRAPEZE_YELLOW_RGBO_HEX); + + /// (yellow (RGB) = 0xEED216) = (228,210,22); opacity (O) = 0xFF) + /// https://maketintsandshades.com/#EED216 + static const PRIMARY_SWATCH = MaterialColor(TRAPEZE_YELLOW_RGBO_HEX, { + 50: const Color(0xFFD6BD14), // 10% + 100: const Color(0xFFBEA812),// 20% + 200: const Color(0xFFA7930F),// 30% + 300: const Color(0xFF8F7E0D),// 40% + 400: const Color(0xFF77690B),// 50% + 500: const Color(0xFF5F5409),// 60% + 600: const Color(0xFF473F07),// 70% + 700: const Color(0xFF302A04),// 80% + 800: const Color(0xFF181502),// 90% + 900: const Color(0xFF000000), // 100% + }); + + static const SECONDARY_SWATCH = MaterialColor(0xFFe89309, { + 50: const Color(0xFFF0D72D), // 10% + 100: const Color(0xFFF1DB45),// 20% + 200: const Color(0xFFF3E05C),// 30% + 300: const Color(0xFFF5E473),// 40% + 400: const Color(0xFFF7E98B),// 50% + 500: const Color(0xFFF8EDA2),// 60% + 600: const Color(0xFFFAF2B9),// 70% + 700: const Color(0xFFFCF6D0),// 80% + 800: const Color(0xFFFDFBE8),// 90% + 900: const Color(0xFFFFFFFF), // 100% + }); + +} \ No newline at end of file diff --git a/lib/src/interfaces/abstract_bloc.dart b/lib/src/interfaces/abstract_bloc.dart new file mode 100644 index 0000000..f7ef109 --- /dev/null +++ b/lib/src/interfaces/abstract_bloc.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; +import 'package:rxdart/rxdart.dart'; + +/// This [AbstractBloc] class implements the barebone structure of every Bloc. +/// +/// We have Model generic [M] +/// We have a Handler generic [H] +abstract class AbstractBloc { + /// This [BehaviorSubject] Object has the Stream Property we publish unto. + @protected + // ignore: close_sinks + final BehaviorSubject publisher = BehaviorSubject(); + + /// This handler field is used to modify the model [M]. + @protected + abstract final H handler; + + void dispose() { + this.publisher.close(); + } + + /// Getter to get the current stream + get bloc => this.publisher.stream; +} diff --git a/lib/src/screens/device_scan/device_scan_log_screen.dart b/lib/src/screens/device_scan/device_scan_log_screen.dart new file mode 100644 index 0000000..e21afc1 --- /dev/null +++ b/lib/src/screens/device_scan/device_scan_log_screen.dart @@ -0,0 +1,168 @@ +import 'package:flutter/material.dart'; +import 'package:flutternativetrapeze/src/screens/knowledgebase/knowledgebase_screen.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_bloc.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_model.dart'; +import 'package:flutternativetrapeze/src/widgets/base_widgets/base_card_widget.dart'; +import 'package:flutternativetrapeze/src/widgets/base_widgets/base_elevated_button_widget.dart'; +import 'package:flutternativetrapeze/src/widgets/device_scan_summary/device_scan_summary_widget.dart'; +import 'package:kaspersky_sdk/kaspersky_sdk.dart'; + +/// This [DeviceScanLogScreen] class represents the "Scan - Log" screen in "./release-info/v1.0.0-dummy/navigation/TRAPEZE-mobile[v1.0.0-dummy]_navigation.pdf". +class DeviceScanLogScreen extends StatelessWidget { + /// This field is the routeName under which this page is registered in the app. + static const String routeName = '/device_scan_log'; + + /// This method builds the [AppBar] for the [Scaffold] and sets the title to the "Scan Log". + AppBar _buildAppBar(BuildContext context) { + return AppBar( + title: Text("Scan Log", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25)), + ); + } + + /// This method builds the Threats based on the [DeviceScanStatisticsModel] and puts them into a [Column]. + Widget _buildThreatView( + BuildContext context, DeviceScanStatisticsModel model) { + return Padding( + padding: EdgeInsets.only(left: 8, top: 6, bottom: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ...model.verdictCategoryToThreatInfosMap.keys.map((e) => + DeviceScanSummaryWidget( + verdictCategory: e, + groupedThreat: model.verdictCategoryToThreatInfosMap)) + ], + ), + ); + } + + Widget _buildWhatToDoButton( + BuildContext context, List verdictCategories) { + return Center( + child: BaseElevatedButtonWidget( + onPressed: () { + Navigator.pushNamed( + context, + KnowledgebaseScreen.routeName, + arguments: { + 'verdictCategories': verdictCategories, + 'showThreatInfo': false, + 'showAllRecommendedActions': true + }, + ); + }, + name: "What can I do?", + ), + ); + } + + /// This build Method gets called to build the UI. This combines the + /// components into a [Scaffold]. + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: _buildAppBar(context), + body: Center( + child: StreamBuilder( + stream: DeviceScanStatisticsBloc.currentBloc.bloc, + builder: (context, snapshot) { + if (snapshot.hasData && snapshot.data != null) { + DeviceScanStatisticsModel model = + (snapshot.data as DeviceScanStatisticsModel); + if (model.identifiedThreats > 0) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: 20, + ), + Expanded( + child: Scrollbar( + thumbVisibility: true, + thickness: 5, + radius: Radius.circular(20), + child: ListView( + scrollDirection: Axis.vertical, + padding: + EdgeInsets.only(left: 10, right: 10, top: 10), + children: [ + BaseCardWidget( + padding: _padding, + elevation: _elevation, + title: Text( + "Scan: " + + model.lastScanned.toString().split(".")[0], + style: _titleStyle, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Threats:", style: _listTitleTextStyle), + _buildThreatView(context, + model) // render the detected threats into the BaseCardWidget; this includes the small info icon to the right of every detected threat + ], + ), + ), + ], + ), + ), + ), + SizedBox( + height: 25, + ), + _buildWhatToDoButton(context, + model.verdictCategoryToThreatInfosMap.keys.toList()), + SizedBox( + height: 40, + ) + ], + ); + } else { + return Column( + children: [ + SizedBox( + height: 30, + ), + Container( + margin: const EdgeInsets.symmetric(horizontal: 10.0), + child: Text( + 'No security threats have been identified.', + style: const TextStyle( + fontSize: 30.0, + ), + ), + ), + ], + ); + } + } else { + return Text("Error"); + } + }, + ), + ), + ); + } + + /// Tweak for the Title of the [BaseCardWidget] + final TextStyle _titleStyle = TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20, + ); + + final TextStyle _listTitleTextStyle = TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black, + fontSize: 18, + ); + + /// Tweak for the elevation of the [BaseCardWidget] + final double _elevation = 6; + + /// Tweak for the padding of the threats + final EdgeInsets _padding = EdgeInsets.all(5); +} diff --git a/lib/src/screens/device_scan/device_scan_screen.dart b/lib/src/screens/device_scan/device_scan_screen.dart new file mode 100644 index 0000000..3779e34 --- /dev/null +++ b/lib/src/screens/device_scan/device_scan_screen.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutternativetrapeze/main.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_controller/device_scan_progress_bloc.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_statistics_history/device_scan_statistics_history_bloc.dart'; +import 'package:flutternativetrapeze/src/widgets/device_scan/device_scan_progress_widget.dart'; + +/// This [DeviceScanScreen] class is a [StatefulWidget] with the corresponding [_ScanRouteState] class for the UI and represents the "Scan - Pending" screen in +/// "./release-info/v0.1.0/navigation/TRAPEZE-mobile[v0.1.0]_navigation.pdf". +class DeviceScanScreen extends StatelessWidget { + /// This field is the routeName under which this page is registered in the app. + static const String routeName = '/device_scan'; + + const DeviceScanScreen({Key? key}) : super(key: key); + + /// This build Method gets called to build the UI. This combines the + /// components into a [Scaffold]. + @override + Widget build(BuildContext context) { + return Scaffold( + body: Padding( + padding: EdgeInsets.all(20), + child: Padding( + padding: EdgeInsets.only(top: 80, bottom: 50), + child: BlocConsumer( + bloc: DeviceScanProgressBloc(), + listener: (context, state) { + if (state is AbortScanState) { + Navigator.pop(context); + } else if (state is FinishScanState) { + DeviceScanStatisticsHistoryBloc.currentBloc.refreshScanHistory(); + DeviceScanStatisticsBloc.currentBloc.updateStatisticsFromDirectory(state.dir.path); + Navigator.popAndPushNamed(context, DeviceScanLogScreen.routeName); + } + }, + buildWhen: (previous, current) { + if (previous.runtimeType != current.runtimeType) return true; + if (previous is UpdateScanState && current is UpdateScanState) { + return previous.progress != current.progress || + previous.currentTask != current.currentTask; + } + return true; + }, + builder: (context, state) { + double progress = 0; + String currentTask = ''; + if (state is StartScanState) { + currentTask = 'Start Scan'; + } else if (state is UpdateScanState) { + progress = state.progress; + currentTask = state.currentTask; + } else if (state is FinishScanState) { + progress = 1; + currentTask = 'Finished Scan'; + } + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Scanning Device...", + style: Theme.of(context).textTheme.headline5, + ), + Spacer(), + Container( + alignment: Alignment.center, + child: DeviceScanProgressWidget( + progress: progress, + currentTask: currentTask, + )), + Spacer(), + BaseElevatedButtonWidget( + onPressed: () { + BlocProvider.of(context, listen: false) + .add(AbortScanEvent()); + }, + name: "Abort", + ), + ], + ); + }, + ), + ), + ), + ); + } +} diff --git a/lib/src/screens/home/home_screen.dart b/lib/src/screens/home/home_screen.dart new file mode 100644 index 0000000..6141d0b --- /dev/null +++ b/lib/src/screens/home/home_screen.dart @@ -0,0 +1,221 @@ +import 'package:flutter/material.dart'; +import 'package:flutternativetrapeze/main.dart'; +import 'package:flutternativetrapeze/src/config/paths.dart' as Paths; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_statistics_history/device_scan_statistics_history_bloc.dart'; +import 'package:flutternativetrapeze/src/widgets/device_scan_info/device_scan_info_widget.dart'; + +/// This [HomeScreen] class represents the "Home (a-x)", "Home (b-x)", "Profile (a-y)", "Profile (b-y)" screens +/// in "./release-info/v1.0.0-dummy/navigation/TRAPEZE-mobile[v1.0.0-dummy]_navigation.pdf". +class HomeScreen extends StatelessWidget { + /// This field is the routeName under which this page is registered in the app. + static const String routeName = '/'; + + const HomeScreen({Key? key}) : super(key: key); + + /// This method builds the [AppBar] for the [Scaffold] and sets the title to the Trapeze logo. + AppBar _buildAppBar(BuildContext context) { + return AppBar( + title: Image.asset(Paths.PATH_TO_TRAPEZE_BANNER, fit: BoxFit.cover), + // This code shows the name of the logged in user when logged in. Was replaced with the Trapeze Logo. + // title: StreamBuilder( + // stream: userBloc.user, + // builder: (context, snapshot) { + // if (snapshot.hasData) { + // UserModel model = snapshot.data as UserModel; + // return Text(model.userName); + // } else { + // return Text("No logged in user found"); + // } + // }, + // ), + leading: StreamBuilder( + stream: UserBloc.currentBloc.bloc, + builder: (context, snapshot) { + if (snapshot.hasData) { + UserModel model = snapshot.data as UserModel; + return model.isLoggedIn + ? IconButton( + icon: const Icon(Icons.account_circle), + iconSize: _toolbarIconSize, + onPressed: () { + Navigator.pushNamed(context, ProfileScreen.routeName); + }, + ) + : Container(); + } else { + return Text("No logged in user found"); + } + }), + actions: [ + // IconButton( + // icon: const Icon(Icons.settings), + // iconSize: _toolbarIconSize, + // onPressed: () { + // Navigator.pushNamed(context, SettingsRoute.routeName); + // }, + // ), + ], + ); + } + + String _pascalCaseToLowerCaseSentence(String str) { + String nameInSentenceCase = + str.replaceAll(RegExp(r'(?( + value: model.filter, + items: >[ + ...Filter.values.map( + (e) { + return DropdownMenuItem( + child: Text(_pascalCaseToLowerCaseSentence(e.name)), + value: e, + ); + }, + ) + ], + onChanged: (Filter? filter) => DeviceScanStatisticsHistoryBloc + .currentBloc + .updateScanFilter(filter!), + ), + ], + ); + } + } + return Container(); + }, + ); + } + + /// This build Method gets called to build the UI. This combines the + /// components into a [Scaffold]. + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: _buildAppBar(context), + body: Column( + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5.0), + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.grey, + offset: Offset(0.0, 1.0), //(x,y) + blurRadius: 6.0, + ), + ], + ), + child: Row( + children: [ + SizedBox(width: 20), + _buildFilterDropMenu(context), + Spacer(), + ], + ), + ), + + StreamBuilder( + stream: DeviceScanStatisticsHistoryBloc.currentBloc.bloc, + builder: (context, snapshot) { + if (snapshot.hasData) { + DeviceScanStatisticsHistoryModel model = + snapshot.data as DeviceScanStatisticsHistoryModel; + if (model.scans.length != 0) { + return Expanded( + child: Scrollbar( + thumbVisibility: true, + thickness: 5, + radius: Radius.circular(20), + child: ListView.builder( + padding: EdgeInsets.only(top: 10, left: 10, right: 10), + scrollDirection: Axis.vertical, + itemCount: model.scans.length, // model.scans.length + itemBuilder: (context, index) { + return DeviceScanInfoWidget( + deviceScan: model.scans[index], + ); + }, + ), + ), + ); + } + } + return Expanded( + child: Container( + margin: const EdgeInsets.only(top: 10, left: 10.0, right: 10.0), + child: Text( + "You have not scanned your device yet", + style: const TextStyle( + fontSize: 30.0, + ), + ), + )); + }, + ), + + SizedBox( + height: 10, + ), + + // Builds Scan Button. + BaseElevatedButtonWidget( + onPressed: () { + // Navigator.pushNamed(context, DeviceScanScreen.routeName); + showDialog( + context: context, + builder: (_) => AlertDialog( + title: Text("Privacy Policy"), + content: Text( + "The TRAPEZE mobile app is about to scan your device. Do you want to scan your device for malware now?"), + actions: [ + TextButton( + child: const Text("Cancel"), + onPressed: () { + Navigator.pop(context); + }, + ), + TextButton( + child: const Text("Send and Scan"), + onPressed: () { + Navigator.pop(context); + Navigator.pushNamed( + context, DeviceScanScreen.routeName); + }, + ) + ], + ), + barrierDismissible: false); + }, + name: "Scan my Device", + ), + SizedBox( + height: 23, + ), + // copyright + const Text('Trapeze Mobile \u00a92021'), + SizedBox( + height: 13, + ), + ], + ), + ); + } + + /// Tweaking value for ToolbarIconSize + final double _toolbarIconSize = 30.0; +} diff --git a/lib/src/screens/knowledgebase/knowledgebase_screen.dart b/lib/src/screens/knowledgebase/knowledgebase_screen.dart new file mode 100644 index 0000000..39eccd3 --- /dev/null +++ b/lib/src/screens/knowledgebase/knowledgebase_screen.dart @@ -0,0 +1,257 @@ +import 'package:flutter/material.dart' hide Actions; +import 'package:flutternativetrapeze/src/utilities/knowledgebase/action_info.dart'; +import 'package:flutternativetrapeze/src/utilities/knowledgebase/mapping_service.dart'; +import 'package:readmore/readmore.dart'; +import 'package:flutternativetrapeze/src/utilities/knowledgebase/threat_resolution_actions.dart'; +import 'package:kaspersky_sdk/kaspersky_sdk.dart' show VerdictCategory; + +/// This [KnowledgebaseScreen] class represents the "KnowledgeBase" page in the drawio sketch v4. +class KnowledgebaseScreen extends StatelessWidget { + /// This field is the routName under which this page is registered in the app. + static const String routeName = "/knowledgebase"; + + /// This method returns a [AppBar] with "Knowledgebase" as title. + AppBar _buildAppBar(BuildContext context) { + return AppBar( + title: Text( + "Knowledgebase", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25), + ), + ); + } + + /// This method returns a [Widget] with the knowledegbase-threat-type. + Widget _buildTitleCardThreatInfo(BuildContext context, String verdictName) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(20))), + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Text( + "Threat-Type: " + verdictName, + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 20, + ), + ), + ), + elevation: 4); + } + + /// This method creates the readmore cards with the description or the actions text from the knowledge base. + /// + /// title ["Description","Actions"] and text is the corresponding text. + Widget _buildTextCardThreatInfo( + BuildContext context, ThreatResolutionsActions threatResolutionsActions) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(20))), + elevation: 4, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Description', + style: TextStyle( + fontWeight: FontWeight.w400, + fontSize: 20, + color: Colors.deepPurple, + ), + ), + Divider( + thickness: 1.2, + ), + SizedBox( + height: 10, + ), + ReadMoreText( + threatResolutionsActions.verdictCategoryInfo.description, + trimLines: 8, + trimMode: TrimMode.Line, + trimCollapsedText: 'Show more', + trimExpandedText: ' show less', + delimiter: " ", + style: TextStyle(color: Colors.black, fontSize: 18), + ), + SizedBox( + height: 15, + ), + Text( + 'Recommended Actions', + style: TextStyle( + fontWeight: FontWeight.w400, + fontSize: 20, + color: Colors.deepPurple, + ), + ), + Divider( + thickness: 1.2, + ), + SizedBox( + height: 10, + ), + // return actionInfoList.asMap().entries.map((entry) => Text('${entry.key + 1}- ' + entry.value.description)).toList(); + + ...(threatResolutionsActions.actionsInfos.asMap().entries.map( + (entry) => Padding( + padding: EdgeInsets.only(left: 12), + child: Text( + '${entry.key + 1}- ' + entry.value.description + '\n', + style: TextStyle(color: Colors.black, fontSize: 18), + ), + ), + )), + ], + ), + ), + ); + } + + Widget _buildThreatInfoComponent( + BuildContext context, ThreatResolutionsActions threatResolutionsActions) { + return Scrollbar( + thumbVisibility: true, + thickness: 5, + radius: Radius.circular(20), + child: ListView( + scrollDirection: Axis.vertical, + padding: EdgeInsets.only(left: 10, right: 10, top: 10), + children: [ + _buildTitleCardThreatInfo( + context, threatResolutionsActions.verdictCategoryInfo.name), + _buildTextCardThreatInfo(context, threatResolutionsActions), + ], + ), + ); + } + + Widget _buildTitleCardRecommendedActions(BuildContext context) { + return Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(20))), + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Text( + "Recommended Actions", + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 20, + ), + ), + ), + elevation: 4); + } + + Widget _buildTextCardRecommendedActions(BuildContext context, + List threatResolutionsActions) { + List recommendedActions = (threatResolutionsActions + .map((e) => e.actionsInfos) + .expand((i) => i) + .toList()); + // sort actions + recommendedActions.sort((a, b) => a.priority.compareTo(b.priority)); + List recommendedActionsDescriptions = recommendedActions + .map((e) => e.description) + .toList() + .toSet() + .toList(); // .toSet().toList() deleted duplicates + + return Card( + elevation: 4, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(20))), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 15, + ), + Text( + 'Summary', + style: TextStyle( + fontWeight: FontWeight.w400, + fontSize: 20, + color: Colors.deepPurple, + ), + ), + Divider( + thickness: 1.2, + ), + SizedBox( + height: 10, + ), + ...recommendedActionsDescriptions.asMap().entries.map( + (entry) => Padding( + padding: EdgeInsets.only(left: 12), + child: Text( + '${entry.key + 1}- ' + entry.value + '\n', + style: TextStyle(color: Colors.black, fontSize: 18), + ), + ), + ) + ], + ), + ), + ); + } + + Widget _buildRecommendedActionsComponent(BuildContext context, + List threatResolutionsActions) { + return Scrollbar( + thumbVisibility: true, + thickness: 5, + radius: Radius.circular(20), + child: ListView( + scrollDirection: Axis.vertical, + padding: EdgeInsets.only(left: 10, right: 10, top: 10), + children: [ + _buildTitleCardRecommendedActions(context), + _buildTextCardRecommendedActions(context, threatResolutionsActions) + ], + ), + ); + } + + /// This build Method gets called to build the UI. This combines the + /// components into a [Scaffold]. Espescially parses the knowledge base and puts all information from it + /// into a [ListView]. + @override + Widget build(BuildContext context) { + final routes = + ModalRoute.of(context)!.settings.arguments as Map; + final verdictCategories = + routes['verdictCategories'] as List; + + final showThreatInfo = routes['showThreatInfo'] as bool; + final showAllRecommendedActions = + routes['showAllRecommendedActions'] as bool; + print(verdictCategories); + return Scaffold( + appBar: _buildAppBar(context), + body: FutureBuilder>( + future: MappingService.knowledgeBaseThreatResolutionsActions( + verdictCategories: verdictCategories), + builder: (context, + AsyncSnapshot> snapshot) { + if (snapshot.hasData) { + if (showThreatInfo) { + return _buildThreatInfoComponent(context, snapshot.data!.first); + } else if (showAllRecommendedActions) { + return _buildRecommendedActionsComponent( + context, snapshot.data!); + } else { + return Text("Knowledgebase screen is unavailable"); + } + } else { + return Text("Knowledgebase screen is unavailable"); + } + }), + ); + } +} diff --git a/lib/src/screens/user_management/login_screen.dart b/lib/src/screens/user_management/login_screen.dart new file mode 100644 index 0000000..5bde5d4 --- /dev/null +++ b/lib/src/screens/user_management/login_screen.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; +import 'package:flutternativetrapeze/src/utilities/user_management/user_bloc.dart'; +import 'package:flutternativetrapeze/src/screens/home/home_screen.dart'; + +/// This [LoginScreen] class is a [StatefulWidget] with the corresponding [_LoginRouteState] class for the UI and represents the "Profile(a)" screen +/// in "./release-info/v1.0.0-dummy/navigation/TRAPEZE-mobile[v1.0.0-dummy]_navigation.pdf". +class LoginScreen extends StatefulWidget { + /// This field is the routeName under which this page is registered in the app. + static const String routeName = '/login'; + + const LoginScreen({Key? key}) : super(key: key); + + @override + _LoginRouteState createState() => _LoginRouteState(); +} + +/// This [_LoginRouteState] class stores the state of the [username] and [password] and implements the [build] method. +class _LoginRouteState extends State { + /// State username variable (needs to be redone just for demo purpose). + String username = ""; + + /// State username variable (needs to be redone just for demo purpose). + String password = ""; + + /// This method returns a [AppBar] with "Login" as title. + AppBar _buildAppBar(BuildContext context) { + return AppBar( + title: Text( + "Login", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ); + } + + /// This method returns a InputField with a given label and a provided onChangeMethod. + Widget _buildInputField(BuildContext context, String labelText, + String hintText, ValueChanged? onChanged) { + return Padding( + padding: EdgeInsets.all(10), + child: TextField( + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: labelText, + hintText: hintText), + onChanged: onChanged, + ), + ); + } + + /// This method returns a [TextButton] which handels the forgott password behaviour. + Widget _buildForgotPasswordButton(BuildContext context) { + return TextButton( + onPressed: () { + //TODO FORGOT PASSWORD SCREEN GOES HERE + }, + child: Text( + 'Forgot Password', + style: TextStyle(color: Theme.of(context).primaryColor, fontSize: 15), + ), + ); + } + + /// This method returns a [Container]-button which handels the login behaviour. + Widget _buildLoginButton(BuildContext context) { + return Container( + height: 50, + width: 250, + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.circular(20)), + child: TextButton( + onPressed: () { + if (this.username.length > 0 && this.password.length > 0) { + UserBloc.currentBloc.login(this.username); + Navigator.pushNamed(context, HomeScreen.routeName); + } + }, + child: Text( + 'Login', + style: TextStyle(color: Colors.black, fontSize: 25), + ), + ), + ); + } + + /// This build Method gets called to build the UI. This combines the + /// components into a [Scaffold]. + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: _buildAppBar(context), + body: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + _buildInputField( + context, + 'Username', + 'Enter valid username', + (String value) { + setState(() { + this.username = value; + }); + }, + ), + _buildInputField( + context, + 'Password', + 'Enter your secure password', + (String value) { + setState(() { + this.password = value; + }); + }, + ), + _buildForgotPasswordButton(context), + _buildLoginButton(context) + ], + ), + ); + } +} diff --git a/lib/src/screens/user_management/profile_screen.dart b/lib/src/screens/user_management/profile_screen.dart new file mode 100644 index 0000000..5ed324e --- /dev/null +++ b/lib/src/screens/user_management/profile_screen.dart @@ -0,0 +1,91 @@ +import 'package:flutter/material.dart'; +import 'package:flutternativetrapeze/src/utilities/user_management/user_bloc.dart'; +import 'package:flutternativetrapeze/src/utilities/user_management/user_model.dart'; +import 'package:flutternativetrapeze/src/screens/home/home_screen.dart'; +import 'package:flutternativetrapeze/src/widgets/base_widgets/base_card_widget.dart'; +import 'package:flutternativetrapeze/src/widgets/base_widgets/base_elevated_button_widget.dart'; + +/// This [ProfileScreen] class represents the "Profile(b)" screen in "./release-info/v1.0.0-dummy/navigation/TRAPEZE-mobile[v1.0.0-dummy]_navigation.pdf". +class ProfileScreen extends StatelessWidget { + /// This field is the routeName under which this page is registered in the app. + static const String routeName = '/profile'; + + const ProfileScreen ({Key? key}) : super(key: key); + + /// This method builds the [AppBar] for the [Scaffold] and sets the title to the "Scan Log". + AppBar _buildAppBar(BuildContext context) { + return AppBar( + title: Text("User", style: TextStyle(fontWeight: FontWeight.bold)), + ); + } + + /// This method builds the user card displaying the the username of the logged in user. + StreamBuilder _buildUserCard(BuildContext context) { + return StreamBuilder( + stream: UserBloc.currentBloc.bloc, + builder: (context, snapshot) { + if (snapshot.hasData) { + UserModel model = snapshot.data as UserModel; + return BaseCardWidget( + elevation: _elevation, + padding: _padding, + title: Text("Logged in as:", style: _textStyle), + child: Text( + model.userName, + ), + ); + } else { + return Text("No user logged in..."); + } + }); + } + + /// This build Method gets called to build the UI. This combines the + /// components into a [Scaffold]. + Widget build(BuildContext context) { + return Scaffold( + appBar: _buildAppBar(context), + body: Column( + children: [ + SizedBox( + height: 60, + ), + _buildUserCard(context), + Spacer(), + BaseElevatedButtonWidget( + width: 215, + onPressed: () { + UserBloc.currentBloc.logout(); + Navigator.of(context).popAndPushNamed(HomeScreen.routeName); + }, + name: "Logout", + ), + SizedBox( + height: 4, + ), + BaseElevatedButtonWidget( + onPressed: () {}, + width: 215, + height: 50, + name: "Privacy Dashboard", + ), + SizedBox( + height: 80, + ) + ], + ), + ); + } + + /// Tweak for the elevation of the [BaseCardWidget]. + final double _elevation = 6; + + /// Tweak for the Title of the [BaseCardWidget]. + static final TextStyle _textStyle = TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20, + ); + + /// Tweak for the padding of the UserInfo. + static final EdgeInsets _padding = EdgeInsets.all(15); +} diff --git a/lib/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart b/lib/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart new file mode 100644 index 0000000..dae14f4 --- /dev/null +++ b/lib/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart @@ -0,0 +1,131 @@ +import 'dart:io'; + +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_controller/device_scan_progress_bloc.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/kaspersky_sdk/easy_scanner_controller.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_log_controller/device_scan_log_controller.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/kaspersky_sdk/interface/sdk_component_controller.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/kaspersky_sdk/sdk_initialization_controller.dart'; + +class DeviceScanController { + /// This controller class handles device scans as triggered for instance by pushing the "Scan my Device" Button on the + /// "Home(x)", "Home(y)", and "Home(z)" screens in "./release-info/v0.1.0/navigation/TRAPEZE-mobile[v0.1.0]_navigation.pdf". + /// Scans represent a list of <_tasks>, where every task is associated with an index <_taskIndex> (first task -> 0; second task -> 1; ..) + /// This controller class provides the following functionality: + /// + /// (I.) Set the tasks to perform in a device scan + /// (II.) Control device scans + /// (II.a) Start a device scan + /// (II.b) Report the progress of the device scan + /// (II.c) Run the next task of a device scan, unless the device scan is (i) aborted or (ii) finished. + /// (II.d) Finish the device scan + /// (II.e) Abort the device scan (non-error; e.g. user-triggered) + /// (II.f) Abort the device scan (error) + /// (III.) Retrieve a list of task results + /// EXAMPLE: for the _tasks list [SdkInitializationController(this), EasyScannerController(this)] + /// results could be the list [true, EasyResult[filesCount=11600, filesScanned=11267, objectsScanned=10798, objectsSkipped=601, malwareCount=1, riskwareCount=0, isRooted=false]] + /// true -> SDK Initialization was successful + /// EasyResult[...] -> EasyScanner scanned successfully + /// (*): The progress of a device scan is defined as the number of finished tasks <_taskIndex> divided by the total number of tasks <_tasks.length>. + final DeviceScanProgressBloc bloc; + late List _tasks; + int _taskIndex = 0; + bool _isAborted = false; + + // (I.) Set tasks to perform in a device scan + DeviceScanController(this.bloc) { + _tasks = [ + SdkInitializationController(this), + EasyScannerController(this), + ]; + } + + // (II.) Control device scans + + // (II.a) Start a device scan + void startScan() async { + print( + './lib/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart: (II.a) START DEVICE SCAN: ${_tasks.length} tasks scheduled.'); + // Reset <_isAborted> to default value: false + _isAborted = false; // default + + // if SDK is initialized + if (_tasks[_taskIndex].getResult()) { + print('(II.a) SDK already initialized, skipping SDK initialization.'); + // skip SDK initialization by setting + _taskIndex = 0; + } else { + // start the device scan with SDK Initialization by setting + _taskIndex = -1; + } + // Start the device scan + runNextTask(); + } + + // (II.b) Report the progress(*) of the device scan and the description of the current task + void reportProgressOnCurrentTask( + double taskProgress, String description) async { + var scanProgress = + _taskIndex / _tasks.length + taskProgress / _tasks.length; + print( + './lib/src/utilities/device_scan/device_scan_controller/device_scan_controller/device_scan_controller.dart: (II.b) REPORT DEVICE SCAN PROGRESS (${scanProgress * 100} %/ 100%) on current task "$description"'); + // Add device scan progress and the description to (ScanProgressBloc) bloc + // NOTE that the device scan progress is split into the sum of (i) fully finished tasks and (ii) partially finished tasks + bloc.add(UpdateScanEvent(scanProgress, description)); + } + + // (II.c) Run the next task of a device scan, unless the device scan is (i) aborted or (ii) finished. + void runNextTask() async { + // (i) Check if Scan aborted + if (_isAborted) return; + // (ii) Check if Scan finished (last task finished) + if (_taskIndex + 1 == _tasks.length) { + finishScan(); + return; + } + + print( + './lib/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart: (II.c) RUN NEXT DEVICE SCAN TASK'); + // Increment _taskIndex + _taskIndex = _taskIndex + 1; + // Run next task + _tasks[_taskIndex].run(); + } + + // (II.d) Finish the device scan: Reset task counter <_taskIndex> and persist result log + void finishScan() async { + print( + './lib/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart: (II.d) FINISH DEVICE SCAN'); + _taskIndex = 0; + List results = getResults(); + File file = await DeviceScanLogController.logger.writeLog(results); + // Add error string to (ScanProgressBloc) bloc + bloc.add(FinishScanEvent(file.parent)); + } + + // (II.e) Abort the device scan (non-error; e.g. user-triggered) + void abortScan() async { + print( + './lib/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart: (II.e) ABORT DEVICE SCAN (user-triggered)'); + // Reset <_taskIndex> and <_isAborted> to default values + _taskIndex = 0; + _isAborted = true; + } + + /// (II.f) Abort the device scan (error) + void errorScan(String reason) async { + print( + './lib/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart: (II.f) ABORT DEVICE SCAN (error)'); + + /// Reset <_taskIndex> and <_isAborted> to default values + _isAborted = true; + _taskIndex = 0; + + /// Add error string to (ScanProgressBloc) bloc + bloc.add(ErrorScanEvent(reason)); + } + + /// (III.) Retrieve a list of task results + List getResults() { + return _tasks.map((t) => t.getResult()).toList(); + } +} diff --git a/lib/src/utilities/device_scan/device_scan_controller/device_scan_progress_bloc.dart b/lib/src/utilities/device_scan/device_scan_controller/device_scan_progress_bloc.dart new file mode 100644 index 0000000..6f4e177 --- /dev/null +++ b/lib/src/utilities/device_scan/device_scan_controller/device_scan_progress_bloc.dart @@ -0,0 +1,118 @@ +import 'dart:io'; + +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart'; +import 'package:permission_handler/permission_handler.dart'; + +/// This file holds (I.) Scan Progress Events; (II.) Scan Progress States; (III.) Scan Progress Bloc +// ---------------------------------------------------------------------------- +/// (I.) Scan Progress Events +/// * 1. Start Scan +/// * 2. Finish Scan +/// * 3. Abort Scan +/// * 4. Error Scan +/// * 5. Update Scan + +/// Abstract Scan Progress Event Class +abstract class ScanProgressEvent {} + +/// * I.1. Start Scan +class StartScanEvent extends ScanProgressEvent {} + +/// * I.2. Finish Scan +class FinishScanEvent extends ScanProgressEvent { + final Directory dir; + + FinishScanEvent(this.dir); +} + +/// * I.3. Abort Scan +class AbortScanEvent extends ScanProgressEvent {} + +/// * I.4. Error Scan +class ErrorScanEvent extends ScanProgressEvent { + final String reason; + + ErrorScanEvent(this.reason); +} + +/// * I.5. Update Scan +class UpdateScanEvent extends ScanProgressEvent { + final double progress; + final String currentTask; + + UpdateScanEvent(this.progress, this.currentTask); +} + +// ---------------------------------------------------------------------------- +/// (II.) Scan Progress States +/// * 1. Start State +/// * 2. Finish State +/// * 3. Abort State +/// * 4. Error State +/// * 5. Update State + +/// Abstract Scan Progress State Class +abstract class ScanProgressState {} + +/// * II.1 Start State +class StartScanState extends ScanProgressState {} + +/// * II.2 Finish State +class FinishScanState extends ScanProgressState { + final Directory dir; + + FinishScanState(this.dir); +} + +/// * II.3 Abort State +class AbortScanState extends ScanProgressState {} + +/// * II.4 Error State +class ErrorScanState extends ScanProgressState { + final String reason; + + ErrorScanState(this.reason); +} + +/// * II.5 Update State +class UpdateScanState extends ScanProgressState { + final double progress; + final String currentTask; + + UpdateScanState(this.progress, this.currentTask); +} + +// ---------------------------------------------------------------------------- +/// (III.) Scan Progress Bloc +/// The Scan Progress Bloc sets states based on events +class DeviceScanProgressBloc extends Bloc { + late DeviceScanController _controller; + // Set initial state + DeviceScanProgressBloc() : super(StartScanState()) { + _controller = DeviceScanController(this); + on((event, emit) async { + if (event is StartScanEvent) { + PermissionStatus status = await Permission.storage.request(); + if (status == PermissionStatus.denied || + status == PermissionStatus.permanentlyDenied) { + emit(ErrorScanState('Missing File Access Permission')); + return; + } + _controller = DeviceScanController(this); + _controller.startScan(); + emit(StartScanState()); + } else if (event is FinishScanEvent) { + emit(FinishScanState(event.dir)); + } else if (event is AbortScanEvent) { + _controller.abortScan(); + emit(AbortScanState()); + } else if (event is ErrorScanEvent) { + emit(ErrorScanState(event.reason)); + } else if (event is UpdateScanEvent) { + emit(UpdateScanState(event.progress, event.currentTask)); + } + }); + add(StartScanEvent()); + } +} diff --git a/lib/src/utilities/device_scan/device_scan_log_controller/device_scan_log_controller.dart b/lib/src/utilities/device_scan/device_scan_log_controller/device_scan_log_controller.dart new file mode 100644 index 0000000..4699151 --- /dev/null +++ b/lib/src/utilities/device_scan/device_scan_log_controller/device_scan_log_controller.dart @@ -0,0 +1,130 @@ +import 'dart:convert'; +import 'dart:core'; +import 'dart:io'; + +import 'package:path_provider/path_provider.dart'; +import 'package:flutternativetrapeze/src/config/constants.dart' as Constants; + +class DeviceScanLogController { + /// This controller class handles logging the results of device scans (see './lib/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart'). + /// Device scan results are converted into a string in JSON-format (see the Example below). + /// + /// Log files are stored as *.json files in the following directory structure: + /// logRootDir + /// | + /// |_ logDir1 + /// | | + /// | |_ logFile1.json + /// | + /// |_ logDir2 + /// | | + /// | |_ logFile2.json + /// | + /// ... + /// + /// Methods: + /// (I.) Write a log file + /// (II.) Read a log file + /// + /// Example + /// * log file path: + /// '/data/user/0/com.example.flutternativetrapeze/app_flutter/1653915014704/device_scan_log.json'. + /// * log file: + /// { + /// "bool":true, + /// "EasyResult": + /// { + /// "filesCount":11501, + /// "filesScanned":11168, + /// "malwareList": + /// [ + /// { + /// "categories":["Unknown"], + /// "fileFullPath":"/data/app/~~T6s6bq18HbqZzkNJCH5pjw==/com.amtso.mobiletestfile-x8ssZCq_cnJRIhwVrw94PQ==/base.apk", + /// "objectName":"/data/app/~~T6s6bq18HbqZzkNJCH5pjw==/com.amtso.mobiletestfile-x8ssZCq_cnJRIhwVrw94PQ==/base.apk", + /// "packageName":"com.amtso.mobiletestfile", + /// "severityLevel":"High", + /// "virusName":"AMTSO-test-file", + /// "isApplication":true, + /// "isCloudCheckFailed":false, + /// "isDeviceAdminThreat":false + /// } + /// ], + /// "objectsScanned":10676, + /// "objectsSkipped":601, + /// "riskwareList":[], + /// "isRooted":false + /// } + /// } + DeviceScanLogController._privateConstructor(); + static final String _logFileName = Constants.LOG_FILE_NAME; + static final DeviceScanLogController _logger = + DeviceScanLogController._privateConstructor(); + + static DeviceScanLogController get logger => _logger; + + /// Get path to the on-device directory <_logRootDir> that holds (a) app-specific and (b) user-generated data. + /// Returns: + Future get _logRootDir async { + final Directory logRootDirectory = await getApplicationDocumentsDirectory(); + return logRootDirectory.path; + } + + /// Create a log directory in the log root directory <_logRootDir> to persist a log file in (format: './<_logRootDir>/$logDirectoryName'). + /// NOTE the s are chosen as the current time stamp. + /// Returns: + Future _createLogDirectory(String logDirectoryName) async { + final String logRootDir = await _logRootDir; + final Directory logDir = await Directory('$logRootDir/$logDirectoryName/') + .create(recursive: true); + print( + "./lib/src/utilities/persistence/log_controller.dart: CREATE LOG DIRECTORY: '$logDir'."); + return logDir; + } + + /// Create a log file 'device_scan_log.json' in a log directory <$logDir> + Future _createLogFile(Directory logDir) { + File file = File( + '${logDir.path}${logDir.path.endsWith('/') ? '' : '/'}$_logFileName'); + print( + "./lib/src/utilities/log_controller.dart: CREATE LOG FILE: '${logDir.path}${logDir.path.endsWith('/') ? '' : '/'}$_logFileName'."); + return file.create(); + } + + /// (I.) Write a log file for a list of <$deviceScanResults>. + Future writeLog(List deviceScanResults) async { + // Fetch the current date time (format: UNIX timestamp) + DateTime now = DateTime.now(); + // Initialize an empty key-value map + Map deviceScanResultsMap = {}; + + // Convert the list of <$deviceScanResults> into a stringified JSON + for (dynamic res in deviceScanResults) { + deviceScanResultsMap[res.runtimeType.toString()] = res; + } + String deviceScanResultsJsonString = jsonEncode(deviceScanResultsMap); + + // Create the log directory + Directory logDir = + await _createLogDirectory(now.millisecondsSinceEpoch.toString()); + // Create the log file + File file = await _createLogFile(logDir); + // Write <$deviceScanResultsJSON> into log file + return await file.writeAsString(deviceScanResultsJsonString); + } + + /// (II.) Read a log file identified by a UNIX timestamp. + Future readLog(DateTime time) async { + try { + String lp = await _logRootDir; + File readFile = File( + '$lp${lp.endsWith('/') ? '' : '/'}${time.millisecondsSinceEpoch}/$_logFileName'); + String log = await readFile.readAsString(); + return jsonDecode(log); + } catch (e) { + return "We are very sorry, we could not find any scan."; //TODO TEXT? 1/0? int.parse(log) + } + // write into a log/ file but not on the phone "creating the log" + // solution controller -> save the map threat:solution, add the solution to the log --> to save it. + } +} diff --git a/lib/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_bloc.dart b/lib/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_bloc.dart new file mode 100644 index 0000000..38188d1 --- /dev/null +++ b/lib/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_bloc.dart @@ -0,0 +1,101 @@ +import 'dart:io'; + +import 'package:flutternativetrapeze/src/interfaces/abstract_bloc.dart'; +import 'package:kaspersky_sdk/kaspersky_sdk.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_model.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_handler.dart'; +import 'package:path_provider/path_provider.dart'; + +/// This [DeviceScanStatisticsBloc] class handles the state of the [DeviceScanStatisticsModel]. +/// +/// There are mutation functions ([updateStatistics],[resolve],[updateStatisticsfromModel]) to muta state of the current [DeviceScanStatisticsModel]. +///```dart +/// DeviceScanStatisticsBloc.currentBloc.updateStatistics(10,8,2,DateTime.now(),Map()); +/// ``` +class DeviceScanStatisticsBloc extends AbstractBloc { + /// The current instance of the Singleton. + static final DeviceScanStatisticsBloc currentBloc = + DeviceScanStatisticsBloc._(); + + /// Initializes the [DeviceScanStatisticsHandler] which performs all the state changes on the [DeviceScanStatisticsModel]. + final handler = DeviceScanStatisticsHandler(); + + /// Private Constructor for this BloC to make it a Singleton. + DeviceScanStatisticsBloc._() { + loadMostRecentScanIfExist(); + } + + void updateStatisticsFromDirectory(String dirPath) { + DeviceScanStatisticsModel newModel = + handler.updateStatisticsFromDirectory(dirPath); + + this.publisher.add(newModel); + } + + /// Updates the the [DeviceScanStatisticsModel] by specific values which are given as paramters and publishes it to the stream. + void updateStatistics( + int identifiedThreats, + int resolvedThreats, + int unresolvedThreats, + DateTime lastScanned, + Map> verdictCategoryMappedThreatInfo) + //Map> groupedThreats, + //EasyResult easyResult) + { + DeviceScanStatisticsModel newStat = this.handler.updateStatistics( + identifiedThreats, + resolvedThreats, + unresolvedThreats, + lastScanned, + verdictCategoryMappedThreatInfo + //groupedThreats, + //easyResult, + ); + + this.publisher.add(newStat); + } + + /// Sets [DeviceScanStatisticsModel] to a deepcopy of the new [DeviceScanStatisticsModel]. + void updateStatisticsfromModel(DeviceScanStatisticsModel model) { + DeviceScanStatisticsModel newStat = + this.handler.updateStatisticsfromModel(model); + this.publisher.add(newStat); + } + + Future getMostRecentScanDirectoryPath() async { + int mostRecentScanDateInMillisecondsSinceEpoch = 0; + final Directory logRootDirectory = await getApplicationDocumentsDirectory(); + + List entities = + Directory('${logRootDirectory.path}/').listSync(); + final Iterable directories = entities.whereType(); + + directories.where((element) { + // getting directories that include scans + return int.tryParse(element.path.split('/').last) != null; + }).forEach((element) { + //finding the date of the latest Scan + int? scanDateInMillisecondsSinceEpoch = + int.tryParse(element.path.split('/').last); + if (scanDateInMillisecondsSinceEpoch! > + mostRecentScanDateInMillisecondsSinceEpoch) { + mostRecentScanDateInMillisecondsSinceEpoch = + scanDateInMillisecondsSinceEpoch; + } + }); + + if (mostRecentScanDateInMillisecondsSinceEpoch != 0) { + return '${logRootDirectory.path}/$mostRecentScanDateInMillisecondsSinceEpoch'; + } + return null; + } + + Future loadMostRecentScanIfExist() async { + String? mostRecentScanDirectoryPath = + await getMostRecentScanDirectoryPath(); + if (mostRecentScanDirectoryPath != null) { + updateStatisticsFromDirectory(mostRecentScanDirectoryPath); + } + } +} diff --git a/lib/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_handler.dart b/lib/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_handler.dart new file mode 100644 index 0000000..69f6444 --- /dev/null +++ b/lib/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_handler.dart @@ -0,0 +1,81 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:kaspersky_sdk/kaspersky_sdk.dart'; + +import 'package:flutternativetrapeze/main.dart'; +import 'package:flutternativetrapeze/src/config/constants.dart' as Constants; +import 'package:flutternativetrapeze/src/utilities/knowledgebase/mapping_service.dart'; + +/// This [DeviceScanStatisticsHandler] class has the implementation for all the mutations in the [DeviceScanStatisticsBloc]. +/// +/// - with the follwing mutations [updateStatistics], [updateStatisticsfromModel], [updateStatisticsfromResolveModel] +class DeviceScanStatisticsHandler { + static final String _logFileName = Constants.LOG_FILE_NAME; + + DeviceScanStatisticsModel updateStatisticsFromDirectory(String dirPath) { + DateTime timestamp = + DateTime.fromMillisecondsSinceEpoch(int.parse(dirPath.split('/').last)); + File resultsFile = + File('$dirPath${dirPath.endsWith('/') ? '' : '/'}$_logFileName'); + String json = resultsFile.readAsStringSync(); + dynamic decodedJson = jsonDecode(json); + EasyResult easyResult = EasyResult.fromJson(decodedJson['EasyResult']); + Map> map = + MappingService.getVerdictCategoryToThreatInfosMap(easyResult); + + int numOfIdentifiedThreats = + easyResult.malwareList.length + easyResult.riskwareList.length; + int numOfResolvedThreats = 0; + int numOfUnresolvedThreats = + easyResult.malwareList.length + easyResult.riskwareList.length; + + // if some of the threats are resolved then read from ModifiedEasyResult + // EasyResult contains the original scan + // ModifiedEasyResult contains all unresolved threats + // ModifiedEasyResult is created after ThreadResolution process + if (decodedJson['ModifiedEasyResult'] != null) { + EasyResult modifiedEasyResult = + EasyResult.fromJson(decodedJson['ModifiedEasyResult']); + map = + MappingService.getVerdictCategoryToThreatInfosMap(modifiedEasyResult); + + numOfUnresolvedThreats = modifiedEasyResult.malwareList.length + + modifiedEasyResult.riskwareList.length; + + numOfResolvedThreats = numOfIdentifiedThreats - numOfResolvedThreats; + } + + return DeviceScanStatisticsModel(numOfIdentifiedThreats, + numOfResolvedThreats, numOfUnresolvedThreats, timestamp, map); + } + + /// This method just creates a new [DeviceScanStatisticsModel] from the given parameters. + DeviceScanStatisticsModel updateStatistics( + int identifiedThreats, + int resolvedThreats, + int unresolvedThreats, + DateTime lastScanned, + Map> verdictCategoryMappedThreatInfo, + ) { + return DeviceScanStatisticsModel( + identifiedThreats, + resolvedThreats, + unresolvedThreats, + lastScanned, + verdictCategoryMappedThreatInfo, + ); + } + + /// This method just creates a deepcopy of a [DeviceScanStatisticsModel] and returns it. + DeviceScanStatisticsModel updateStatisticsfromModel( + DeviceScanStatisticsModel model) { + return DeviceScanStatisticsModel( + model.identifiedThreats, + model.resolvedThreats, + model.unresolvedThreats, + model.lastScanned, + model.verdictCategoryToThreatInfosMap, + ); + } +} diff --git a/lib/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_model.dart b/lib/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_model.dart new file mode 100644 index 0000000..2cbfca4 --- /dev/null +++ b/lib/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_model.dart @@ -0,0 +1,32 @@ +import 'dart:core'; + +import 'package:kaspersky_sdk/kaspersky_sdk.dart'; + +/// This [DeviceScanStatisticsModel] class represents a scanlog with all the information that a supposed scan could deliver. +class DeviceScanStatisticsModel { + /// Result of Easy Scanner + // final EasyResult easyResult; + + /// Amount of Identified Threats equals the sum of the reslovedThreats and the unresolvedThreat + final int identifiedThreats; + + /// Amount of already resolved Threats + final int resolvedThreats; + + /// Amount of open Threats + final int unresolvedThreats; + + /// [DateTime] of the last Scan. + final DateTime lastScanned; + + /// GroupedThreats is a Map of Threats corresponing to a ThreatType + final Map> verdictCategoryToThreatInfosMap; + + DeviceScanStatisticsModel( + this.identifiedThreats, + this.resolvedThreats, + this.unresolvedThreats, + this.lastScanned, + this.verdictCategoryToThreatInfosMap, + ); +} diff --git a/lib/src/utilities/device_scan/device_scan_statistics_history/device_scan_statistics_history_bloc.dart b/lib/src/utilities/device_scan/device_scan_statistics_history/device_scan_statistics_history_bloc.dart new file mode 100644 index 0000000..240f567 --- /dev/null +++ b/lib/src/utilities/device_scan/device_scan_statistics_history/device_scan_statistics_history_bloc.dart @@ -0,0 +1,130 @@ +import 'package:flutternativetrapeze/src/interfaces/abstract_bloc.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_bloc.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_statistics/device_scan_statistics_model.dart'; +import 'dart:io'; +import 'package:path_provider/path_provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +enum Filter { Latest, LatestThree, All } + +class DeviceScanStatisticsHistoryModel { + final List scans; + final Filter filter; + + DeviceScanStatisticsHistoryModel(this.scans, this.filter); +} + +class DeviceScanStatisticsHistoryHandler { + Future> getAllScansDirectories() async { + final Directory logRootDirectory = await getApplicationDocumentsDirectory(); + + List entities = Directory('${logRootDirectory.path}/').listSync(); + final Iterable directories = entities.whereType(); + + List scansDate = directories.where((element) { + // getting directories that include scans + return int.tryParse(element.path.split('/').last) != null; + }).map((element) { + //finding the date of the latest Scan + return int.tryParse(element.path.split('/').last)!; + }).toList(); + scansDate.sort(); + List scansDateSortedDec = scansDate.reversed.toList(); + + List scansPaths = scansDateSortedDec.map((e) { + return '${logRootDirectory.path}/$e'; + }).toList(); + return scansPaths; + } + + Future getScans() async { + List filteredDeviceScans = []; + List scansDirectories = await getAllScansDirectories(); + Filter filter = await loadFilterFromSharedPrefernces(); + + switch (filter) { + case Filter.Latest: + // do something + if (scansDirectories.length >= 1) { + scansDirectories.sublist(0, 1).forEach((element) { + filteredDeviceScans.add(DeviceScanStatisticsBloc.currentBloc.handler + .updateStatisticsFromDirectory(scansDirectories[0])); + }); + } + break; + case Filter.LatestThree: + if (scansDirectories.length >= 3) { + scansDirectories.sublist(0, 3).forEach((element) { + filteredDeviceScans.add(DeviceScanStatisticsBloc.currentBloc.handler + .updateStatisticsFromDirectory(element)); + }); + } else { + continue addAllScans; + } + break; + addAllScans: + case Filter.All: + // do something else + scansDirectories.forEach((element) { + filteredDeviceScans.add( + DeviceScanStatisticsBloc.currentBloc.handler.updateStatisticsFromDirectory(element)); + }); + break; + } + + return DeviceScanStatisticsHistoryModel(filteredDeviceScans, filter); + } + + Future updateScanFilter(Filter filter) async { + await saveFilterInSharedPrefernces(filter); + return getScans(); + } + + Future loadFilterFromSharedPrefernces() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.getString('filter'); + switch (prefs.getString('filter')) { + case 'Latest': + return Filter.Latest; + case 'LatestThree': + return Filter.LatestThree; + case 'All': + return Filter.All; + default: + return Filter.All; + } + } + + Future saveFilterInSharedPrefernces(Filter filter) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setString('filter', filter.name); + } +} + +class DeviceScanStatisticsHistoryBloc + extends AbstractBloc { + /// The current instance of the Singleton. + static final DeviceScanStatisticsHistoryBloc currentBloc = DeviceScanStatisticsHistoryBloc._(); + + final handler = DeviceScanStatisticsHistoryHandler(); + + /// Private Constructor for this BloC to make it a Singleton. + DeviceScanStatisticsHistoryBloc._() { + // call init + loadScanHistory(); + } + + Future updateScanFilter(Filter filter) async { + DeviceScanStatisticsHistoryModel newState = await this.handler.updateScanFilter(filter); + this.publisher.add(newState); + } + + Future loadScanHistory() async { + DeviceScanStatisticsHistoryModel newState = await this.handler.getScans(); + this.publisher.add(newState); + } + + Future refreshScanHistory() async { + await loadScanHistory(); + } +} diff --git a/lib/src/utilities/device_scan/kaspersky_sdk/easy_scanner_controller.dart b/lib/src/utilities/device_scan/kaspersky_sdk/easy_scanner_controller.dart new file mode 100644 index 0000000..88387a6 --- /dev/null +++ b/lib/src/utilities/device_scan/kaspersky_sdk/easy_scanner_controller.dart @@ -0,0 +1,96 @@ +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_log_controller/device_scan_log_controller.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/kaspersky_sdk/interface/sdk_component_controller.dart'; +import 'package:kaspersky_sdk/kaspersky_sdk.dart'; +import 'dart:developer'; + +class EasyScannerController extends SdkComponentController { + /// This component controller class handles device scans as per the EasyScanner component of the Kaspersky Mobile Security SDK (KMS-SDK), simply referred to as 'Easy Scanner' (see (*)). + /// REMARK: Make sure that the app has permissions to READ-access all files on the device. + /// See for instance the 'READ-access' permissions in './android/app/src/main/AndroidManifest.xml'. + final DeviceScanController controller; + EasyResult? _result; + + EasyScannerController(this.controller); + + @override + String get name => 'Easy Scanner'; // (*) + + @override + void run() async { + print( + './lib/src/utilities/device_scan/kaspersky_sdk/easy_scanner_controller.dart: START DEVICE SCAN TASK: Easy Scanner'); + EasyScanner().scan(EasyMode.Full, _MyEasyListener(controller, this)); + double taskProgress = 0; + controller.reportProgressOnCurrentTask(taskProgress, 'Easy Scanner'); + } + + @override + getResult() { + return _result; + } +} + +// ---------------------------------------------------------------------------- + +class _MyEasyListener extends EasyListener { + final DeviceScanController controller; + final EasyScannerController _scanController; + late DeviceScanLogController logController; + + _MyEasyListener(this.controller, this._scanController) { + this.logController = DeviceScanLogController.logger; + } + + @override + void onFilesCountCalculated(int fileCount) async { + print('[EasyScanner] counted $fileCount files'); + controller.reportProgressOnCurrentTask( + 0.2, 'Found $fileCount files to scan'); + } + + @override + void onFinished(EasyResult result) async { + print('[EasyScanner] finished $result'); + _scanController._result = result; + controller.reportProgressOnCurrentTask(1, 'Running Easy Scanner DONE'); + controller.runNextTask(); + log("DEBUG - RESULTS: ${result.toString()}"); // log for controlling + } + + @override + void onMalwareDetected(EasyObject object, ThreatInfo threat) async { + print('[EasyScanner] malware detected $object $threat'); + // TODO: implement onMalwareDetected + } + + @override + void onObjectBegin(EasyObject object) async { + // print('[EasyScanner] begin object $object'); + // TODO: implement onObjectBegin + } + + @override + void onObjectEnd(EasyObject object, EasyStatus status) async { + // print('[EasyScanner] end object $object $status'); + // TODO: implement onObjectEnd + } + + @override + void onRiskwareDetected(EasyObject object, ThreatInfo threat) async { + print('[EasyScanner] riskware detected $object $threat'); + // TODO: implement onRiskwareDetected + } + + @override + void onRooted() async { + print('[EasyScanner] rooted'); + // TODO: implement onRooted + } + + @override + void onError(String message) { + print('[Easy Scanner] error: $message'); + // TODO: implement onError + } +} diff --git a/lib/src/utilities/device_scan/kaspersky_sdk/interface/sdk_component_controller.dart b/lib/src/utilities/device_scan/kaspersky_sdk/interface/sdk_component_controller.dart new file mode 100644 index 0000000..e7fa178 --- /dev/null +++ b/lib/src/utilities/device_scan/kaspersky_sdk/interface/sdk_component_controller.dart @@ -0,0 +1,10 @@ +abstract class SdkComponentController { + /// Abstract class for making available components of the Kaspersky Mobile Security SDK (KMS-SDK). + /// Every component controller has a: + /// * name; to identify the component controller + /// * method; e.g. run a device scan (see for instance './lib/src/utilities/device_scan/kaspersky_sdk/easy_scanner_controller.dart') + /// * method; to retrieve tha results derived by the method + String get name; + void run(); + dynamic getResult(); +} diff --git a/lib/src/utilities/device_scan/kaspersky_sdk/sdk_initialization_controller.dart b/lib/src/utilities/device_scan/kaspersky_sdk/sdk_initialization_controller.dart new file mode 100644 index 0000000..5c0c628 --- /dev/null +++ b/lib/src/utilities/device_scan/kaspersky_sdk/sdk_initialization_controller.dart @@ -0,0 +1,59 @@ +import 'package:flutternativetrapeze/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart'; +import 'package:flutternativetrapeze/src/utilities/device_scan/kaspersky_sdk/interface/sdk_component_controller.dart'; +import 'package:kaspersky_sdk/kaspersky_sdk.dart'; + +class SdkInitializationController extends SdkComponentController { + /// This component controller class handles the initialization of the Kaspersky Mobile Security SDK (KMS-SDK), simply referred to as 'SDK Initialization' (see (*)). + /// Once the KMS--SDK is initialized, its security components such as EasyScanner (see for instance "./lib/src/utilities/device_scan/kaspersky_sdk/easy_scanner_controller.dart") + /// can be used. + /// + /// Sdk Initialization is the initial task of a device scan (see for instance "./lib/src/utilities/device_scan/device_scan_controller/device_scan_controller.dart"). + /// As a device scan task, it is associated with a taskProgress in the interval [0,1] (corresponding to 0% and 100% completion respectively). + /// + final DeviceScanController controller; + static bool success = false; + + SdkInitializationController(this.controller); + + @override + String get name => 'SDK Initialization'; // (*) + + @override + void run() async { + print( + './lib/src/utilities/device_scan/kaspersky_sdk/sdk_initialization_controller.dart: START DEVICE SCAN TASK: SDK Initialization'); + KavSdk.init(_MyKavSdkListener(controller, this)); + double taskProgress = 0; + controller.reportProgressOnCurrentTask(taskProgress, 'SDK Initialization'); + } + + @override + getResult() { + return success; + } + + setResult(result) { + success = result; + } +} + +// ---------------------------------------------------------------------------- + +class _MyKavSdkListener extends KavSdkInitListener { + final DeviceScanController controller; + final SdkInitializationController initController; + + _MyKavSdkListener(this.controller, this.initController); + + @override + void onInitializationFailed(String result) { + controller.errorScan('SDK Initialization (FAILURE): $result'); + } + + @override + void onSdkInitialized() { + initController.setResult(true); + controller.reportProgressOnCurrentTask(1, 'SDK Initialization (SUCCESS)'); + controller.runNextTask(); + } +} diff --git a/lib/src/utilities/knowledgebase/action_info.dart b/lib/src/utilities/knowledgebase/action_info.dart new file mode 100644 index 0000000..2aa8302 --- /dev/null +++ b/lib/src/utilities/knowledgebase/action_info.dart @@ -0,0 +1,6 @@ +class ActionInfo { + String description = ''; + int priority = 1; + + ActionInfo({required this.description, required this.priority}); +} diff --git a/lib/src/utilities/knowledgebase/mapping_service.dart b/lib/src/utilities/knowledgebase/mapping_service.dart new file mode 100644 index 0000000..5e93888 --- /dev/null +++ b/lib/src/utilities/knowledgebase/mapping_service.dart @@ -0,0 +1,154 @@ +import 'dart:core'; +import 'package:flutternativetrapeze/src/utilities/knowledgebase/threat_resolution_actions.dart'; +import 'package:kaspersky_sdk/kaspersky_sdk.dart' + show EasyResult, ThreatInfo, VerdictCategory; + +enum ThreatResolutionAction { + antivirus, + backupData, + vpn, + thirdpartyDownload, + securitySoftware, + updatePermission, + avoidUnsecureWifi, + updatePhoneVersion, + randomPassword, + avoidLinks, + uninstallApps, + googlePlayProtect, + savedPassword, + factoryReset, + clearStorage, + unknown, +} + +class MappingService { + /// The [MappingService] class handles mapping information on threats identifies by the Kaspersky Mobile Security SDK (e.g. instances of [EasyResult]) + /// into an output format that the app will display in the "Device Scan Log Screen" (see for instance: './release-info/v0.1.0/TRAPEZE-mobile[v0.1.0]_navigation.pdf'). + /// The output format is a VerdictCategoryToThreatInfosMap (Map>). Here, a verdict category + /// is one of a fixed list of threat categories (this is defined by the Kaspersky Mobile Security SDK (see for instance: file:///Users/snet/Documents/H2020%20Projekte/2021/TRAPEZE/work%20packages/work%20package%204/TUB/mobile-app/Kaspersky%20SDK/android/5.13.0.136/KL_Mobile_SDK_Android_5.13.0.136_Release_Trapeze_(EuroComission)/manuals/Kaspersky%20Mobile%20Security%20SDK/javadoc/com/kavsdk/antivirus/VerdictCategory.html)) + /// VerdictCategories: + /// ################## + /// * Adware + /// * DestructiveMalware + /// * Monitor + /// * PswTool + /// * RemoteAdmin + /// * Unknown + /// + /// Every malware/riskware threat identified by the Kaspersky Mobile Security SDK is associated to a file, we will call this the threat file. + /// Every threat file is associated to a ThreatInfo that contains information on the specific threat file such as the path to the file and a + /// list of VerdictCategories associated. + /// + /// EXAMPLE: + /// ######### + /// Consider for example that an EasyResult contains information on a single malicious file we call "ThreatFile1". + /// "ThreatFile1" is associated to the VerdictCategories 'Adware' and 'DestructiveMalware'. + /// The UI in the "Device Scan Log Screen" would display this information in the following fashion: + /// + /// UI: + /// + /// Threats: + /// Adware + /// -> ThreatFile1 + /// DestructiveMalware + /// -> ThreatFile1 + /// + /// Data: + /// + /// Threats: + /// VerdictCategory1: + /// -> ThreatFiles that have VerdictCategory1 + /// VerdictCategory2: + /// -> ThreatFiles that have VerdictCategory2 + /// + /// The UI thus requires a Map. This Map is produced by the method (I.) in the below. + /// + /// This class provides the following functionality: + /// (I.) Map information from an [EasyResult] into a VerdictCatgegoryToThreatInfosMap + /// + /// private methods + /// (_II.) Convert an [EasyResult] instance into a Map> + /// (_III.) Reverse a Map> into a Map> + + // (I.) Convert an [EasyResult] instance into a VertictCategoryToThreatInfosMap + static Map> + getVerdictCategoryToThreatInfosMap(EasyResult easyResult) { + // (_II.) Convert an [EasyResult] instance into a Map> + Map> threatInfoToVerdictCategoriesMap = + getThreatInfoToVerdictCategoriesMap(easyResult); + // (_III.) Reverse a Map> into a Map> + return _reverseMap(threatInfoToVerdictCategoriesMap); + } + + // (_II.) Convert an [EasyResult] instance into a Map> + static Map> + getThreatInfoToVerdictCategoriesMap(EasyResult easyResult) { + // This function takes an EasyResult object and extracts a map of ThreatInfo to List. + // See the kaspersky_sdk package for details. Roughly, every ThreatInfo describes a category of a security threat such as "virus" + // and a verdict category denotes + // input: + // * EasyResult easyResult: + // output: + // * Map<> result: + + // initialize resultMap + Map> resultMap = new Map(); + // concatenate the lists of detected malware and riskware to a list of threatInfos + List threatInfos = + easyResult.malwareList.followedBy(easyResult.riskwareList).toList(); + // for every threatInfo in threatInfos + for (ThreatInfo threatInfo in threatInfos) { + List verdictCategoriesForThreatInfo; + // select its corresponding verdictCategories + if (threatInfo.categories.isEmpty) { + verdictCategoriesForThreatInfo = []; + } else { + verdictCategoriesForThreatInfo = threatInfo.categories; + } + // and append (threatInfo: unique verdictCategoriesForThreatInfo) to the resultMap + if (verdictCategoriesForThreatInfo.isNotEmpty) { + resultMap[threatInfo] = + verdictCategoriesForThreatInfo.toSet().toList(); //.toList(); + } + } + return resultMap; + } + + // (_III.) Reverse a Map> into a Map> + static Map> _reverseMap( + Map> map) { + // Example: + // * input : {a: [1, 2], b: [2, 3]} (map) + // * output: {1:[a], 2:[a,b], 3: [b]} (reversedMap) + + // select unique values of the input map + var mapValues = map.values.expand((i) => i).toSet(); + // construct the reversedMap (see Example) + Map> reversedMap = new Map.fromIterable( + mapValues, + key: (mapValue) => mapValue, + value: (mapValue) => map.keys + .where((i) => map[i]?.contains(mapValue) ?? false) + .toList()); + + return reversedMap; + } + + static Future> + knowledgeBaseThreatResolutionsActions( + {required List verdictCategories}) async { + return await Future.wait(verdictCategories.map((verdictCategory) async => + await ThreatResolutionsActions.create(verdictCategory))); + } + + // static Future knowledgeBaseActionInfo( + // ThreatResolutionAction threatResolutionAction) async { + // return await ActionInfo.create(threatResolutionAction); + // } + + // static Future knowledgeBaseVerdictCategoryInfo( + // {required VerdictCategory verdictCategory}) async { + // return await VerdictCategoryInfo.create(verdictCategory); + // } +} diff --git a/lib/src/utilities/knowledgebase/threat_resolution_actions.dart b/lib/src/utilities/knowledgebase/threat_resolution_actions.dart new file mode 100644 index 0000000..113c337 --- /dev/null +++ b/lib/src/utilities/knowledgebase/threat_resolution_actions.dart @@ -0,0 +1,86 @@ +import 'dart:convert'; +import 'package:flutternativetrapeze/src/utilities/knowledgebase/action_info.dart'; +import 'package:flutternativetrapeze/src/utilities/knowledgebase/verdict_category_info.dart'; +import 'package:kaspersky_sdk/kaspersky_sdk.dart'; +import 'package:deep_pick/deep_pick.dart'; +import 'package:http/http.dart'; + +/// This class provides the name and the description of each [VerdictCategory], which is used as a mapping in [KnowledgebaseScreen] + +class ThreatResolutionsActions { + VerdictCategoryInfo verdictCategoryInfo; + + // these actions are sorted + List actionsInfos = []; + + ThreatResolutionsActions._( + {required this.verdictCategoryInfo, required this.actionsInfos}) { + actionsInfos.sort((a, b) => a.priority.compareTo(b.priority)); + } + + static Future create( + VerdictCategory verdictCategory) async { + /* + The knowledge-base is a php-server that features an API. (see: https://github.com/trapeze-project/knowledge-base) + The knowledge-based features an API that responds to a URL with a query like this: + SEND: + .../kb.php?action=threat&category[]=Adware&category[]=Unknown + + RETURN: + [ + { + "category": "Adware", + "description": "Adware (advertisement software) is softwa[...]", + "actions": [ + { + "priority": 2, + "description": "Install an Anti-Virus app, e.g. TotalAV[...]" + }, + { + "priority": 2, + "description":"Do not download software from unknown[...]"}, + }, + [...] + } + ] + + The important part is the action=threat part that tells the API that we are querying knowledge on security threats. + To provider further details on what security threats we are interested in, we specify "category[]=Adware" to query + knowledge on Adware, and additionally (&) "category[]=Unknown", to query knowledge on an Unknown securty threat. + + The information that is queried from the knowledgebase is currently (March 2023) hardcoded. + + + */ + // var url = Uri.http( + // 'localhost:9999', '/kb.php', {'action': 'threat', 'category[]': verdictCategory.name}); + + // for debugging: local endpoint: 'http://localhost:9999/kb.php?action=threat&category[]=${verdictCategory.name}'); + /* The endpoint is https://trapeze.imp.bg.ac.rs/knowledgebase and, as stated in the GitHub repository, + a simple user interface for querying the knowledge base is available by using ‘?action=debug’ as the + query and opening the URL in a browser (https://trapeze.imp.bg.ac.rs/knowledgebase/kb.php?action=debug). + */ + + var url = Uri.parse( + 'https://trapeze.imp.bg.ac.rs/knowledgebase/kb.php?action=threat&category[]=${verdictCategory.name}'); + + Response response = await get(url); + + List data = json.decode(response.body) as List; + + String description = pick(data, 0, 'description').asStringOrThrow(); + + VerdictCategoryInfo verdictCategoryInfo = VerdictCategoryInfo( + verdictCategory: verdictCategory, description: description); + + List actionsInfo = + pick(data, 0, 'actions').asListOrEmpty((pick) { + return ActionInfo( + description: pick('description').required().asString(), + priority: pick('priority').required().asIntOrThrow()); + }); + + return ThreatResolutionsActions._( + verdictCategoryInfo: verdictCategoryInfo, actionsInfos: actionsInfo); + } +} diff --git a/lib/src/utilities/knowledgebase/verdict_category_info.dart b/lib/src/utilities/knowledgebase/verdict_category_info.dart new file mode 100644 index 0000000..fdfc030 --- /dev/null +++ b/lib/src/utilities/knowledgebase/verdict_category_info.dart @@ -0,0 +1,18 @@ +import 'package:kaspersky_sdk/kaspersky_sdk.dart'; + +/// This class provides the name and the description of each [VerdictCategory], which is used as a mapping in [KnowledgebaseScreen] + +class VerdictCategoryInfo { + VerdictCategory verdictCategory = VerdictCategory.Unknown; + String description = ''; + + String get name { + String nameInPascalCase = verdictCategory.name; + String nameInSentenceCase = + nameInPascalCase.replaceAll(RegExp(r'(? { + /// Initializes the [UserHandler] which performs all the state changes on the [UserModel]. + final handler = UserHandler(); + + /// The current instance of the Singleton. + static final UserBloc currentBloc = UserBloc._(); + + /// The private [UserBloc] constructor initializes the bloc Singleton with a dummy empty user model. + UserBloc._() { + /// To get a default user on app launch + this.publisher.add(UserModel.dummyUserModelFactory()); + } + + /// Authenticates a new user by username (Dummy Implemetation no login is being performed). + /// + /// Creates a new [UserModel] and adds it to the [publisher]. + void login(String username) { + UserModel newUser = this.handler.login(username); + this.publisher.add(newUser); + } + + /// Logs the current user out and replaces the [UserModel] with a empty one. + /// + /// Creates a new empty [UserModel] and adds it to the [publisher]. + void logout() { + UserModel newUser = this.handler.logout(); + this.publisher.add(newUser); + } +} diff --git a/lib/src/utilities/user_management/user_handler.dart b/lib/src/utilities/user_management/user_handler.dart new file mode 100644 index 0000000..f68db56 --- /dev/null +++ b/lib/src/utilities/user_management/user_handler.dart @@ -0,0 +1,16 @@ +import 'package:flutternativetrapeze/src/utilities/user_management/user_model.dart'; + +/// This [UserHandler] class has the implementation for all the mutations in the [UserBloc]. +/// +/// - with the follwing mutations [login],[logout] +class UserHandler { + /// This method returns a new [UserModel] with a given username. + UserModel login(String username) { + return UserModel(username); + } + + /// This method returns a new [UserModel] with a empty username (which simulates the logout). + UserModel logout() { + return UserModel(""); + } +} diff --git a/lib/src/utilities/user_management/user_model.dart b/lib/src/utilities/user_management/user_model.dart new file mode 100644 index 0000000..a21a0f0 --- /dev/null +++ b/lib/src/utilities/user_management/user_model.dart @@ -0,0 +1,18 @@ +/// This [UserModel] class represents the current logged in user. +class UserModel { + // Currently only a username is rquired to be considered logged In + final String _userName; + + UserModel(this._userName); + + String get userName => this._userName; + + /// Check weather a user is logged in, but in this cases only looks for a username unequal to "". + bool get isLoggedIn => this._userName.length > 0; + + /// This dummy user factory method generates a user with an empty username. + /// This is considered not logged in. + static UserModel dummyUserModelFactory() { + return UserModel(""); + } +} diff --git a/lib/src/widgets/base_widgets/base_card_widget.dart b/lib/src/widgets/base_widgets/base_card_widget.dart new file mode 100644 index 0000000..7a76734 --- /dev/null +++ b/lib/src/widgets/base_widgets/base_card_widget.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; + +/// Rounded card widget. +/// ________________ +/// | title | +/// | _______________| +/// | child | +/// |________________| +class BaseCardWidget extends StatelessWidget { + /// Title that gets displayed on top. + final Widget title; + + /// Child that gets displayed on below a [Divider] and the title. + final Widget child; + + /// Elevation which creates a dropshadow. + final double elevation; + + /// Padding of the card. + final EdgeInsets padding; + + const BaseCardWidget( + {Key? key, + this.title = const Text(""), + this.elevation = 0, + this.padding = const EdgeInsets.all(0), + this.child = const Text("")}) + : super(key: key); + + /// Build method + @override + Widget build(BuildContext context) { + return Card( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(20))), + elevation: this.elevation, + child: Padding( + padding: this.padding, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + this.title, + Divider( + thickness: 1, + indent: 60, + ), + this.child, + ], + ), + ), + ); + } +} diff --git a/lib/src/widgets/base_widgets/base_elevated_button_widget.dart b/lib/src/widgets/base_widgets/base_elevated_button_widget.dart new file mode 100644 index 0000000..048d742 --- /dev/null +++ b/lib/src/widgets/base_widgets/base_elevated_button_widget.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:flutternativetrapeze/src/config/theme.dart'; + +/// This [BaseElevatedButtonWidget] is a ElevatedButton with a fixed size, we use throughout the project. +/// _______________________ +/// |SizedBox_______________| +/// ||ElevatedButton || +/// || ________________ || +/// || | | || +/// || | Text | || +/// || |________________| || +/// ||_____________________|| +/// +class BaseElevatedButtonWidget extends StatelessWidget { + /// The CallBack Function which gets executed on every tap. + final VoidCallback? onPressed; + + /// Name of the Button as a [String]. + final String name; + final double width; + final double height; + const BaseElevatedButtonWidget({ + Key? key, + required this.onPressed, + this.name = "", + this.height = 50, + this.width = 200, + }) : super(key: key); + + /// This method builds a button with the size of the [SizedBox]. + @override + Widget build(BuildContext context) { + return SizedBox( + width: width, + height: height, + child: ElevatedButton( + onPressed: this.onPressed, + style: ElevatedButton.styleFrom( + backgroundColor: AppColors.TRAPEZE_YELLOW, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(25), + ), + ), + child: Text( + this.name, + style: TextStyle( + fontSize: 20, + ), + ), + ), + ); + } +} diff --git a/lib/src/widgets/device_scan/device_scan_progress_widget.dart b/lib/src/widgets/device_scan/device_scan_progress_widget.dart new file mode 100644 index 0000000..9ef0a83 --- /dev/null +++ b/lib/src/widgets/device_scan/device_scan_progress_widget.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; + +/// This [DeviceScanProgressWidget] class displays a donut which is used as an indicator for the scanprogress in [DeviceScanScreen] and [ThreatResolutionScreen]. +/// See for instance the "Scan-Pending" screen in "./release-info/v0.1.0/navigation/TRAPEZE-mobile[v0.1.0]_navigation.pdf". +/// +/// ______________________________________________ +/// |Stack_________________________________________| +/// ||CircularProgressIndicator || +/// || ______._______ || +/// || / TextA: \ || +/// || | progressString | || +/// || \ ______._______/ || +/// ||____________________________________________|| +/// | Text B: currentTask | +/// |______________________________________________| +/// +/// +class DeviceScanProgressWidget extends StatelessWidget { + /// Progress value form 0 to 100 as [double]. + final double progress; + + final String currentTask; + + DeviceScanProgressWidget({this.progress = 0, this.currentTask = '...'}); + + /// This method builds a [SizedBox] with the [_radius] as width and height and places the Circle inside. + @override + Widget build(BuildContext context) { + return Column( + children: [ + Stack(alignment: Alignment.center, children: [ + SizedBox( + width: _radius, + height: _radius, + child: CircularProgressIndicator( + value: progress, + strokeWidth: _strokeWidth, + ), + ), + Text( //Text A + progressString, + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold, fontSize: _fontSize), + ), + ]), + Text( // Text B + currentTask, + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold, fontSize: _fontSize), + ), + ], + ); + } + + /// This getter turns the progress into a procent [String]. + String get progressString => ((this.progress * 100).toInt()).toString() + "%"; + + /// Tweak for the StrokeWidth + final double _strokeWidth = 12.0; + + /// Tweak for the Radius + final double _radius = 200.0; + + /// Tweak for the Fontsize of the procent [String]. + final double _fontSize = 40.0; +} diff --git a/lib/src/widgets/device_scan_info/device_scan_info_widget.dart b/lib/src/widgets/device_scan_info/device_scan_info_widget.dart new file mode 100644 index 0000000..f0f1eed --- /dev/null +++ b/lib/src/widgets/device_scan_info/device_scan_info_widget.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; +import 'package:flutternativetrapeze/main.dart'; + +/// Rounded card widget. +/// ________________ +/// | title | +/// | _______________| +/// | child | +/// |________________| +class DeviceScanInfoWidget extends StatelessWidget { + final double elevation = 6; + + final EdgeInsets padding = const EdgeInsets.all(10); + + final TextStyle titleStyle = const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20, + ); + + /// Tweaks the ThreatTextSize of the [BaseCardWidget] + final double _threatTextSize = 16; + + /// Tweaks the color of the resoved threats of the [BaseCardWidget] + + final DeviceScanStatisticsModel deviceScan; + + const DeviceScanInfoWidget({Key? key, required this.deviceScan}) + : super(key: key); + + Widget _buildConditionalShowDetailsTextButton(BuildContext context) { + return Center( + child: TextButton( + onPressed: () { + DeviceScanStatisticsBloc.currentBloc + .updateStatisticsfromModel(deviceScan); + // Navigator.pushNamed(context, ThreatResolutionConfigurationScreen.routeName); + Navigator.pushNamed(context, DeviceScanLogScreen.routeName); + }, + child: const Text( + 'show scan log', + style: TextStyle( + decoration: TextDecoration.underline, + color: Colors.blue, + ), + ), + ), + ); + } + + /// Build method + @override + Widget build(BuildContext context) { + return BaseCardWidget( + elevation: elevation, + padding: padding, + title: Text( + "Scan: " + deviceScan.lastScanned.toString().split(".")[0], + style: titleStyle, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Threats identified: " + deviceScan.identifiedThreats.toString(), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: _threatTextSize, + color: deviceScan.identifiedThreats == 0 + ? Colors.black + : Colors.green, + ), + ), + _buildConditionalShowDetailsTextButton(context), + ], + ), + ); + } +} diff --git a/lib/src/widgets/device_scan_summary/device_scan_summary_widget.dart b/lib/src/widgets/device_scan_summary/device_scan_summary_widget.dart new file mode 100644 index 0000000..67882bb --- /dev/null +++ b/lib/src/widgets/device_scan_summary/device_scan_summary_widget.dart @@ -0,0 +1,89 @@ +import 'package:flutter/material.dart'; +import 'package:flutternativetrapeze/src/screens/knowledgebase/knowledgebase_screen.dart'; +import 'package:kaspersky_sdk/kaspersky_sdk.dart'; + +/// This [DeviceScanSummaryWidget] class is used to display a scan log. +/// See for instance the "Scan - Log (b)" screen and there the card underneath the header showing three unknown threats +/// in "./release-info/v0.1.0/navigation/TRAPEZE-mobile[v0.1.0]_navigation.pdf". +/// +/// ____________________________________________________________________________ +/// |Row_________________________________________________________________________| +/// | Text A: knowledgeBaseThreat[verdictCategory]!['name'] | Spacer | IconButton (i) | +/// |____________________________________________________________________________| +/// |Map_________________________________________________________________________| +/// || Text B: "-> " + groupedThreat[verdictCategory].virusName || +/// ||__________________________________________________________________________|| +/// +/// +class DeviceScanSummaryWidget extends StatelessWidget { + /// [VerdictCategory] which should get displayed + final VerdictCategory verdictCategory; + + /// GroupedThreats of all, the build method looks for the given [VerdictCategory]. + final Map> groupedThreat; + const DeviceScanSummaryWidget( + {Key? key, required this.verdictCategory, required this.groupedThreat}) + : super(key: key); + + /// This method builds a [Column] with the title of the [VerdictCategory] and the Threats in a [Column] below. + /// + /// All threats are colored red and [VerdictCategory]s that don't occur are colored green + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(top: 0), + child: Row( + children: [ + Text( + // Text A + // get verdictCategory name in sentence case + verdictCategory.name + .replaceAll(RegExp(r'(? 0 + ? Colors.blueGrey + : Colors.greenAccent), + ), + Spacer(), + IconButton( + onPressed: () { + Navigator.pushNamed( + context, + KnowledgebaseScreen.routeName, + arguments: { + 'verdictCategories': [verdictCategory], + 'showThreatInfo': true, + 'showAllRecommendedActions': false + }, + ); + }, + icon: Icon(Icons.info_outline)), + ], + ), + ), + // Adds all the threats this may need to be scrollable if there are more threats identified this needs to change later + ...(this.groupedThreat[verdictCategory]!.map( + (e) => Padding( + padding: EdgeInsets.only(left: 12), + child: Text( + // Text B + "-> " + e.virusName, + style: TextStyle( + color: Colors.redAccent, + fontSize: 16, + fontStyle: FontStyle.italic), + ), + ), + )), + ], + ); + } +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..35ae6b7 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,768 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "47.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "4.7.0" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.1" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.9.0" + blinking_text: + dependency: "direct main" + description: + name: blinking_text + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + bloc: + dependency: transitive + description: + name: bloc + url: "https://pub.dartlang.org" + source: hosted + version: "7.2.1" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.16.0" + connectivity_plus: + dependency: transitive + description: + name: connectivity_plus + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.9" + connectivity_plus_linux: + dependency: transitive + description: + name: connectivity_plus_linux + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + connectivity_plus_macos: + dependency: transitive + description: + name: connectivity_plus_macos + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.6" + connectivity_plus_platform_interface: + dependency: transitive + description: + name: connectivity_plus_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.3" + connectivity_plus_web: + dependency: transitive + description: + name: connectivity_plus_web + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.5" + connectivity_plus_windows: + dependency: transitive + description: + name: connectivity_plus_windows + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.2" + connectivity_wrapper: + dependency: "direct main" + description: + name: connectivity_wrapper + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" + coverage: + dependency: transitive + description: + name: coverage + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.2" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.2" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + dbus: + dependency: transitive + description: + name: dbus + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.8" + deep_pick: + dependency: "direct main" + description: + name: deep_pick + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.0" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.4" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + url: "https://pub.dartlang.org" + source: hosted + version: "7.3.3" + flutter_launcher_icons: + dependency: "direct main" + description: + name: flutter_launcher_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.3" + flutter_native_splash: + dependency: "direct main" + description: + name: flutter_native_splash + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.10+1" + 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" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + html: + dependency: transitive + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.15.0" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.5" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.4" + json_annotation: + dependency: transitive + description: + name: json_annotation + url: "https://pub.dartlang.org" + source: hosted + version: "4.7.0" + kaspersky_sdk: + dependency: "direct main" + description: + path: "../kaspersky_sdk" + relative: true + source: path + version: "0.0.1" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.12" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.5" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + nm: + dependency: transitive + description: + name: nm + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + path: + dependency: "direct main" + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.2" + path_provider: + dependency: "direct main" + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.20" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.7" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + url: "https://pub.dartlang.org" + source: hosted + version: "8.3.0" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "3.7.1" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.1" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" + provider: + dependency: transitive + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.3" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + readmore: + dependency: "direct main" + description: + name: readmore + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + rxdart: + dependency: "direct main" + description: + name: rxdart + url: "https://pub.dartlang.org" + source: hosted + version: "0.27.5" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.15" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.14" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + shelf_static: + dependency: transitive + description: + name: shelf_static + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + source_maps: + dependency: transitive + description: + name: source_maps + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.10" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.0" + sqflite: + dependency: "direct main" + description: + name: sqflite + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.2+4" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3+3" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0+2" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + test: + dependency: "direct dev" + description: + name: test + url: "https://pub.dartlang.org" + source: hosted + version: "1.21.4" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.12" + test_core: + dependency: transitive + description: + name: test_core + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.16" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + universal_io: + dependency: transitive + description: + name: universal_io + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + vm_service: + dependency: transitive + description: + name: vm_service + url: "https://pub.dartlang.org" + source: hosted + version: "8.3.0" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0+2" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" +sdks: + dart: ">=2.18.0 <3.0.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..f4fdafa --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,120 @@ +name: flutternativetrapeze +description: A Flutter application that has been created in the frame of the EU-funded TRAPEZE project (https://trapeze-project.eu/) grant agreement identifier 883464. + +# The following line prevents the package from being accidentally published to +# pub.dev using `pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.17.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + sqflite: ^1.2.0 + path: + + path_provider: ^2.0.7 + shared_preferences: + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + rxdart: ^0.27.1 + readmore: ^2.1.0 + # settings_ui: ^1.0.0 + flutter_launcher_icons: ^0.9.2 + # add '../kaspersky_sdk/' as Flutter plugin package + kaspersky_sdk: + path: ../kaspersky_sdk + + flutter_bloc: ^7.3.3 + permission_handler: ^8.3.0 + blinking_text: ^1.0.1+2 + flutter_native_splash: ^2.2.10+1 + deep_pick: ^0.10.0 + http: ^0.13.5 + connectivity_wrapper: ^1.1.0 + +flutter_native_splash: + color: "#FFFF00" + image: assets/images/trapeze_banner_clear_background.png + android: true + ios: true + web: true + android_gravity: center + ios_content_mode: center + web_image_mode: center + android12: true + +dev_dependencies: + flutter_test: + sdk: flutter + test: ^1.17.12 + +# the paths need to be changed when building application. It then the whole path needs to be copied +flutter_icons: + android: true + ios: true + image_path_ios: "assets/ic_launcher/ios/iTunesArtwork@1x.png" + image_path_android: "assets/ic_launcher/android/ic_launcher-web.png" + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + assets: + - assets/images/trapeze_banner_clear_background.png + - assets/database.db + - assets/DataBanks/verdictCategoryInfo.json + - assets/DataBanks/actionInfo.json + - assets/DataBanks/threatResolutionActions.json + - assets/DataBanks/exampleFetchResult.json + # - assets/images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages + diff --git a/screenshots/DeviceScanLogScreen.jpg b/screenshots/DeviceScanLogScreen.jpg new file mode 100644 index 0000000..c428946 Binary files /dev/null and b/screenshots/DeviceScanLogScreen.jpg differ diff --git a/screenshots/HomeScreen.jpg b/screenshots/HomeScreen.jpg new file mode 100644 index 0000000..5fcc677 Binary files /dev/null and b/screenshots/HomeScreen.jpg differ diff --git a/screenshots/KnowledgebaseScreen-Recommended-Actions.jpg b/screenshots/KnowledgebaseScreen-Recommended-Actions.jpg new file mode 100644 index 0000000..8329fd8 Binary files /dev/null and b/screenshots/KnowledgebaseScreen-Recommended-Actions.jpg differ diff --git a/screenshots/KnowledgebaseScreen-Threat-Type.jpg b/screenshots/KnowledgebaseScreen-Threat-Type.jpg new file mode 100644 index 0000000..6f4c7ce Binary files /dev/null and b/screenshots/KnowledgebaseScreen-Threat-Type.jpg differ diff --git a/screenshots/put-all-screenshots-together.drawio b/screenshots/put-all-screenshots-together.drawio new file mode 100644 index 0000000..5a4321a --- /dev/null +++ b/screenshots/put-all-screenshots-together.drawio @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/screenshots/put-all-screenshots-together.png b/screenshots/put-all-screenshots-together.png new file mode 100644 index 0000000..d4d0eab Binary files /dev/null and b/screenshots/put-all-screenshots-together.png differ diff --git a/test/mapping_test.dart b/test/mapping_test.dart new file mode 100644 index 0000000..5e3d030 --- /dev/null +++ b/test/mapping_test.dart @@ -0,0 +1,288 @@ +import 'package:test/test.dart'; +import 'package:flutternativetrapeze/src/utilities/knowledgebase/mapping_service.dart'; +import 'package:kaspersky_sdk/kaspersky_sdk.dart'; + +void main() { + group('map easy result to info types', () { + test('Mapping multiple categories', () { + ThreatInfo threatInfo = ThreatInfo( + [VerdictCategory.Adware, VerdictCategory.Monitor], + 'fileFullPath', + 'objectName', + 'packageName', + SeverityLevel.Medium, + 'virusName', + false, + false, + false, + ); + EasyResult easyResult = EasyResult( + 10, + 11, + [threatInfo], + 20, + 21, + [], + true, + ); + Map> map = + MappingService.mapEasyResultToInfoTypes(easyResult); + List infoTypes = map[threatInfo]!; + expect(infoTypes.length, 1); + expect(infoTypes.contains(InfoType.spyware), true); + }); + test('Mapping one categories', () { + ThreatInfo threatInfo = ThreatInfo( + [VerdictCategory.Adware], + 'fileFullPath', + 'objectName', + 'packageName', + SeverityLevel.Medium, + 'virusName', + false, + false, + false, + ); + EasyResult easyResult = EasyResult( + 10, + 11, + [threatInfo], + 20, + 21, + [], + true, + ); + Map> map = + MappingService.mapEasyResultToInfoTypes(easyResult); + List infoTypes = map[threatInfo]!; + expect(infoTypes.length, 1); + expect(infoTypes.contains(InfoType.spyware), true); + }); + + test('Empty verdical category list', () { + ThreatInfo threatInfo = ThreatInfo([], 'fileFullPath', 'objectName', + 'packageName', SeverityLevel.Low, 'virusName', false, false, false); + EasyResult easyResult = EasyResult( + 10, + 10, + [threatInfo], + 9, + 0, + [], + false, + ); + Map> map = + MappingService.mapEasyResultToInfoTypes(easyResult); + List infoTypes = map[threatInfo]!; + expect(infoTypes.isEmpty, true); + }); + + test('Mapping does not contain duplicates - duplicate category', () { + ThreatInfo threatInfo = ThreatInfo( + [VerdictCategory.PswTool, VerdictCategory.PswTool], + 'fileFullPath', + 'objectName', + 'packageName', + SeverityLevel.Low, + 'virusName', + false, + false, + false); + EasyResult easyResult = EasyResult( + 10, + 10, + [threatInfo], + 9, + 0, + [], + false, + ); + Map> map = + MappingService.mapEasyResultToInfoTypes(easyResult); + List infoTypes = map[threatInfo]!; + expect(infoTypes.length, 2); + expect(infoTypes.contains(InfoType.keylogger), true); + expect(infoTypes.contains(InfoType.spyware), true); + }); + test('one threat info without category, one with category', () { + ThreatInfo withoutVerdict = ThreatInfo([], 'fileFullPath', 'objectName', + 'packageName', SeverityLevel.Low, 'virusName', false, false, false); + ThreatInfo withVerdict = ThreatInfo( + [VerdictCategory.DestructiveMalware], + 'fileFullPath', + 'objectName', + 'packageName', + SeverityLevel.Low, + 'virusName', + false, + false, + false); + EasyResult easyResult = + EasyResult(10, 10, [withoutVerdict, withVerdict], 9, 0, [], false); + Map> map = + MappingService.mapEasyResultToInfoTypes(easyResult); + List? emptyInfoTypes = map[withoutVerdict]; + expect(emptyInfoTypes != null, true, + reason: + 'list of into types for threat info without verdict category is null'); + expect(emptyInfoTypes!.isEmpty, true, + reason: + 'list of into types for threat info without verdict category has elements'); + List? nonEmptyInfoTypes = map[withVerdict]; + expect(nonEmptyInfoTypes != null, true, + reason: + 'list of into types for threat info with verdict category is null'); + expect(nonEmptyInfoTypes!.isNotEmpty, true, + reason: + 'list of into types for threat info with verdict category has no elements'); + }); + }); + group('reverse dictionary tests', () { + test('empty map', () { + Map> map = + MappingService.reverseDictionary({}); + expect(map.isEmpty, true, reason: 'empty map must result in empty map'); + }); + test('empty list', () { + ThreatInfo threatInfo = ThreatInfo( + [VerdictCategory.Adware], + 'fileFullPath', + 'objectName', + 'packageName', + SeverityLevel.Medium, + 'virusName', + false, + false, + false); + Map> threatInfoMap = { + threatInfo: [], + }; + Map> map = + MappingService.reverseDictionary(threatInfoMap); + expect(map.length, 0); + }); + test('empty list and non-empty list', () { + ThreatInfo threatInfo = ThreatInfo( + [VerdictCategory.Adware], + 'fileFullPath', + 'objectName', + 'packageName', + SeverityLevel.Medium, + 'virusName', + false, + false, + false); + ThreatInfo threatInfo2 = ThreatInfo( + [VerdictCategory.DestructiveMalware], + 'fileFullPath', + 'objectName', + 'packageName', + SeverityLevel.Medium, + 'virusName', + false, + false, + false); + Map> threatInfoMap = { + threatInfo: [], + threatInfo2: [InfoType.malware] + }; + Map> map = + MappingService.reverseDictionary(threatInfoMap); + expect(map.length, 1); + List? threats = map[InfoType.malware]; + expect(threats == null, false); + expect(threats!.length, 1); + expect(threats[0], threatInfo2); + }); + test('simple map', () { + ThreatInfo threatInfo = ThreatInfo( + [VerdictCategory.Adware], + 'fileFullPath', + 'objectName', + 'packageName', + SeverityLevel.Medium, + 'virusName', + false, + false, + false); + Map> threatInfoMap = { + threatInfo: [InfoType.spyware], + }; + Map> map = + MappingService.reverseDictionary(threatInfoMap); + expect(map.length, 1); + List? threats = map[InfoType.spyware]; + expect(threats == null, false); + expect(threats!.length, 1); + expect(threats[0], threatInfo); + }); + test('map with duplicates', () { + ThreatInfo threatInfo = ThreatInfo( + [VerdictCategory.Adware], + 'fileFullPath', + 'objectName', + 'packageName', + SeverityLevel.Medium, + 'virusName', + false, + false, + false); + ThreatInfo threatInfo2 = ThreatInfo( + [VerdictCategory.DestructiveMalware], + 'fileFullPath', + 'objectName', + 'packageName', + SeverityLevel.Medium, + 'virusName', + false, + false, + false); + Map> threatInfoMap = { + threatInfo: [InfoType.spyware], + threatInfo2: [InfoType.spyware, InfoType.malware], + }; + Map> map = + MappingService.reverseDictionary(threatInfoMap); + expect(map.length, 2); + List? threats = map[InfoType.spyware]; + expect(threats == null, false); + expect(threats!.length, 2); + expect(threats.contains(threatInfo), true); + expect(threats.contains(threatInfo2), true); + List? threats2 = map[InfoType.malware]; + expect(threats2 == null, false); + expect(threats2!.length, 1); + expect(threats2[0], threatInfo2); + }); + }); + group('map info types to solutions and actions', () { + test('empty info types', () { + List infoTypes = []; + List actions = MappingService.mapInfoTypesToActions(infoTypes); + expect(actions.isEmpty, true); + }); + test('single info type', () { + List infoTypes = [InfoType.fakeapps]; + List actions = MappingService.mapInfoTypesToActions(infoTypes); + expect(actions.isNotEmpty, true); + }); + test('duplicate info type', () { + List infoTypes = [InfoType.fakeapps, InfoType.fakeapps]; + List actions = MappingService.mapInfoTypesToActions(infoTypes); + expect(actions.length == actions.toSet().length, true); + }); + test('two info type with same solution', () { + List infoTypes = [InfoType.fakeapps, InfoType.rootedphone]; + List actions = MappingService.mapInfoTypesToActions(infoTypes); + expect(actions.length == actions.toSet().length, true); + }); + test('each info type has at least one solution', () { + for (InfoType infoType in InfoType.values) { + List actions = + MappingService.mapInfoTypesToActions([infoType]); + expect(actions.isNotEmpty, true, + reason: '$verdictCategory has no solutions / actions'); + } + }); + }); +} diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..8a174ab --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:flutternativetrapeze/src/app.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(App()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} 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/index.html b/web/index.html new file mode 100644 index 0000000..574b143 --- /dev/null +++ b/web/index.html @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + flutternativetrapeze + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..91d6b59 --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "flutternativetrapeze", + "short_name": "flutternativetrapeze", + "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" + } + ] +} diff --git a/web/splash/img/dark-1x.png b/web/splash/img/dark-1x.png new file mode 100644 index 0000000..c06978b 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..16683fe 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..9b14128 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..5ba9998 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..c06978b 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..16683fe 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..9b14128 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..5ba9998 Binary files /dev/null and b/web/splash/img/light-4x.png differ diff --git a/web/splash/splash.js b/web/splash/splash.js new file mode 100644 index 0000000..3b6ed11 --- /dev/null +++ b/web/splash/splash.js @@ -0,0 +1,5 @@ +function removeSplashFromWeb() { + document.getElementById("splash")?.remove(); + document.getElementById("splash-branding")?.remove(); + document.body.style.background = "transparent"; +} diff --git a/web/splash/style.css b/web/splash/style.css new file mode 100644 index 0000000..318989f --- /dev/null +++ b/web/splash/style.css @@ -0,0 +1,63 @@ +body { + margin:0; + height:100%; + background: #FFFF00; + + background-size: 100% 100%; +} + +.center { + margin: 0; + position: absolute; + top: 50%; + left: 50%; + -ms-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.contain { + display:block; + width:100%; height:100%; + object-fit: contain; +} + +.stretch { + display:block; + width:100%; height:100%; +} + +.cover { + display:block; + width:100%; height:100%; + object-fit: cover; +} + +.bottom { + position: absolute; + bottom: 0; + left: 50%; + -ms-transform: translate(-50%, 0); + transform: translate(-50%, 0); +} + +.bottomLeft { + position: absolute; + bottom: 0; + left: 0; +} + +.bottomRight { + position: absolute; + bottom: 0; + right: 0; +} + +@media (prefers-color-scheme: dark) { + body { + margin:0; + height:100%; + background: #FFFF00; + + background-size: 100% 100%; + } +}