diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..9eefc1e3 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 3a83c2f0..bb67a9bf 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ doc/api/ .flutter-plugins .flutter-plugins-dependencies +/cogniopenapp/.idea +/cogniopenapp/android/.gradle diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..26d33521 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/caches/deviceStreaming.xml b/.idea/caches/deviceStreaming.xml new file mode 100644 index 00000000..5a2f8669 --- /dev/null +++ b/.idea/caches/deviceStreaming.xml @@ -0,0 +1,329 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..6e40516c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Dart & Flutter", + "request": "launch", + "type": "dart" + + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..7f84f482 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.sourceDirectory": "C:/Users/tosha/fall2024/clearassist/linux" +} \ No newline at end of file diff --git a/clearassist/.gitignore b/clearassist/.gitignore new file mode 100644 index 00000000..11fef8e8 --- /dev/null +++ b/clearassist/.gitignore @@ -0,0 +1,174 @@ +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +build/ +pubspec.lock +utils/test.dart +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +# dotenv environment variables file +*.env* + +# Avoid committing generated Javascript files: +*.dart.js +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your + # project includes source files written in JavaScript. +*.js_ +*.js.deps +*.js.map + +.flutter-plugins +.flutter-plugins-dependencies +.vs/ProjectSettings.json +.vs/slnx.sqlite +.vs/VSWorkspaceState.json +.vs/fall2023/v16/.suo +.vs/fall2023/v16/Browse.VC.db +Podfile +clearassistapp/*/Podfile +Dart_Packages.xml + +# FLUTTER MASTER .GITIGNORE FROM https://github.com/flutter/flutter/blob/master/.gitignore : + +# Miscellaneous +*.class +*.lock +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +clearassistapp/testApplicationDocumentsPath/tmp/* +clearassistapp/testApplicationDocumentsPath/files/*/* + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# Visual Studio Code related +.classpath +.project +.settings/ +.vscode/* + +# Flutter repo-specific +/bin/cache/ +/bin/internal/bootstrap.bat +/bin/internal/bootstrap.sh +/bin/mingit/ +/dev/benchmarks/mega_gallery/ +/dev/bots/.recipe_deps +/dev/bots/android_tools/ +/dev/devicelab/ABresults*.json +/dev/docs/doc/ +/dev/docs/api_docs.zip +/dev/docs/flutter.docs.zip +/dev/docs/lib/ +/dev/docs/pubspec.yaml +/dev/integration_tests/**/xcuserdata +/dev/integration_tests/**/Pods +/packages/flutter/coverage/ +version +analysis_benchmark.json + +# packages file containing multi-root paths +.packages.generated + +# Flutter/Dart/Pub related +**/doc/api/ +#.dart_tool/ +#.flutter-plugins +#.flutter-plugins-dependencies +**/generated_plugin_registrant.dart +#.packages +.pub-preload-cache/ +.pub-cache/ +.pub/ +#build/ +flutter_*.png +linked_*.ds +unlinked.ds +unlinked_spec.ds + +# Android related +**/android/**/gradle-wrapper.jar +.gradle/ +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java +**/android/key.properties +*.jks + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/.last_build_id +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/ephemeral +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# macOS +**/Flutter/ephemeral/ +**/Pods/ +**/macos/Flutter/GeneratedPluginRegistrant.swift +**/macos/Flutter/ephemeral +**/xcuserdata/ + +# Windows +**/windows/flutter/generated_plugin_registrant.cc +**/windows/flutter/generated_plugin_registrant.h +**/windows/flutter/generated_plugins.cmake + +# Linux +**/linux/flutter/generated_plugin_registrant.cc +**/linux/flutter/generated_plugin_registrant.h +**/linux/flutter/generated_plugins.cmake + +# Coverage +coverage/ + +# Symbols +app.*.symbols + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +!/dev/ci/**/Gemfile.lock +!.vscode/settings.json \ No newline at end of file diff --git a/clearassist/.metadata b/clearassist/.metadata new file mode 100644 index 00000000..620e877d --- /dev/null +++ b/clearassist/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + - platform: android + create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + - platform: ios + create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + - platform: linux + create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + - platform: macos + create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + - platform: web + create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + - platform: windows + create_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + base_revision: ff5b5b5fa6f35b717667719ddfdb1521d8bdd05a + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/clearassist/.vscode/settings.json b/clearassist/.vscode/settings.json new file mode 100644 index 00000000..c5f3f6b9 --- /dev/null +++ b/clearassist/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "interactive" +} \ No newline at end of file diff --git a/clearassist/LICENSE b/clearassist/LICENSE new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/clearassist/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/clearassist/README.md b/clearassist/README.md new file mode 100644 index 00000000..40e5df3f --- /dev/null +++ b/clearassist/README.md @@ -0,0 +1,64 @@ +# ClearAssist Overview + +The ClearAssist application for the UMGC Capstone - SWEN 670 Fall 2023 cohort submission. ClearAssist is an application designed to assist individuals suffering from cognitive impairment. The design for the application focuses on the following core principles: + +1. Make the application user friendly +2. Help users reacquaint themselves with the application when they need it +3. Develop the application to be as intuitive as possible + +The ClearAssist application utilizes video, audio, and photo captures to inventory every day conversations and each user's surroundings. With the integration of ChatGPT, AWS Rekognition, AWS Transcribe, and some custom search functionalities, users can find and remember anything they may have forgotten. + +## Setting Up Your Environment + +To setup your environment for running the application, review the Wikis locate in GitHub. + +1. The Wiki for setting up and configure flutter can be found here: https://github.com/umgc/fall2023/wiki/Flutter-Installation-SOP +2. The Wiki for how the ClearAssist development team manages source code can be found here: https://github.com/umgc/fall2023/wiki/Source-Control-and-Configuration-Management + +## Getting Started + +1. Change directories to the application folder `clearassistapp` +2. Run `flutter pub get` to install dependencies +3. Run `flutter emulators --launch ` to start the emulator device. For example, `flutter emulators --launch Pixel_5_API_34` + - Use `flutter emulators` to get a list of emulator ids. +4. Run `flutter run` to run the application in the emulated environment. + +# Using the .env file + +The .env file will store environmental (and other secret) variables used in the development and execution of the application functions. See the `temp-env` file with variables to fill in. +For example, the ChatGPT access token variable will be stored here to access the ChatGPT API (used in various audio transcription related features). Likewise, the AWS S3 and Rekognition accessKeys are also stored in this file. + +This .env file IS NOT to be checked into the source code repo. Before committing code, please ensure that your .env file is not being pushed into the branches; similarly, ensure that the .gitignore file include ` *.env` so that this .env file will never be uploaded to the repository. + +## Getting the OpenAI ChatGPT API Key + +The following outlines setting up a new key and adding it to the .env created with the instructions above. + +1. Go to https://openai.com and Login or Sign up for a new account. +2. Click on API +3. At top right, click on Personal and then View API Keys menu item. +4. Click "+ Create new secret key" button +5. Give the key a name, relating to ClearAssist or SWEN670 +6. The new secret key will appear in a text box with copy button next to it. +7. Copy the key and paste it into your .env file. +8. Save the key somewhere like OneNote where it will be safe, you cannot retrieve this key once you close this dialog. You can however make more. +9. Click done. + + +## Getting the AWS access key + +1. Go to https://aws.amazon.com/ and select "Sign In" to sign in or create a new "Free Tier" account +2. Once you are at the console home, navigate to your account and then "Security credentials" +3. Select "Users" and then "Create user" +4. Give the user a name. Select "next" to move to "Step 2: Set permissions" +5. Select "attach policies directly". Then select the "AmazonRekognitionFullAccess", "AmazonS3FullAccess", and "AmazonTranscribeFullAccess" permission policies +6. Select "Create user" in "Step 3: Review and create". + The new secret key will appear in a text box with copy button next to it. +7. Copy the accesskey and paste it into your .env file. +8. Copy the secretKey and paste it into your .env file. +9. Save the key somewhere like OneNote where it will be safe, you cannot retrieve this key once you close this dialog. You can however make more. +10. Click done. + +The Amazon Free tier ought to have enough space and video processing requests to complete development and testing. Just be aware of video fidelity and length when recording. +Requests are pretty cheap afterwards but the dollar amount can pile up if unaware. +Also beware to stop any "custom labels" created via Signficant Objects. The inferment hours for detecting custom labels from still frames can quickly rack up a bill as well. (services can be stopped from within the application, but also from the AWS Console - https://us-east-1.console.aws.amazon.com/rekognition/custom-labels#/projects) \ No newline at end of file diff --git a/clearassist/analysis_options.yaml b/clearassist/analysis_options.yaml new file mode 100644 index 00000000..0d290213 --- /dev/null +++ b/clearassist/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/clearassist/android/.gitignore b/clearassist/android/.gitignore new file mode 100644 index 00000000..6f568019 --- /dev/null +++ b/clearassist/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/clearassist/android/app/build.gradle b/clearassist/android/app/build.gradle new file mode 100644 index 00000000..f013169d --- /dev/null +++ b/clearassist/android/app/build.gradle @@ -0,0 +1,70 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace "comclearassist.clearassistapp" + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "comclearassist.clearassistapp" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion 21 + //minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + targetSdkVersion 29 + 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 {} diff --git a/clearassist/android/app/src/debug/AndroidManifest.xml b/clearassist/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..f15a9b4f --- /dev/null +++ b/clearassist/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/clearassist/android/app/src/main/AndroidManifest.xml b/clearassist/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..679435cd --- /dev/null +++ b/clearassist/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/clearassist/android/app/src/main/kotlin/comclearassist/clearassist/MainActivity.kt b/clearassist/android/app/src/main/kotlin/comclearassist/clearassist/MainActivity.kt new file mode 100644 index 00000000..319b726b --- /dev/null +++ b/clearassist/android/app/src/main/kotlin/comclearassist/clearassist/MainActivity.kt @@ -0,0 +1,70 @@ +package comclearassist.clearassistapp + +//import classes +import android.provider.ContactsContract +import android.telephony.SmsManager +import io.flutter.embedding.android.FlutterActivity +import io.flutter.plugin.common.MethodChannel +import io.flutter.embedding.engine.FlutterEngine + +class MainActivity : FlutterActivity() { + + private val CHANNEL = "smsChannel" + + override fun configureFlutterEngine(flutterEngine: FlutterEngine) { + super.configureFlutterEngine(flutterEngine) + + MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> + when (call.method) { + "sendSms" -> { + val phoneNumber = call.argument("phoneNumber") + val message = call.argument("message") + if (!phoneNumber.isNullOrEmpty() && !message.isNullOrEmpty()) { + sendSms(phoneNumber, message) + result.success("SMS Sent") + } else { + result.error("INVALID_INPUT", "Phone number or message is empty", null) + } + } + "getEmergencyContacts" -> { + val emergencyContacts = getEmergencyContacts() + result.success(emergencyContacts) + } + else -> result.notImplemented() + } + } + } + + private fun sendSms(phoneNumber: String, message: String) { + val smsManager = SmsManager.getDefault() + smsManager.sendTextMessage(phoneNumber, null, message, null, null) + } + + private fun getEmergencyContacts(): List { + val emergencyContacts = mutableListOf() + val projection = arrayOf( + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, + ContactsContract.CommonDataKinds.Phone.NUMBER + ) + + val cursor = contentResolver.query( + ContactsContract.CommonDataKinds.Phone.CONTENT_URI, + projection, + null, + null, + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC" + ) + + cursor?.use { + while (it.moveToNext()) { + val name = it.getString(it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)) ?: "" + val phoneNumber = it.getString(it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)) ?: "" + + if (name.contains("Emergency", ignoreCase = true)) { + emergencyContacts.add("$name: $phoneNumber") + } + } + } + return emergencyContacts + } +} diff --git a/clearassist/android/app/src/main/res/drawable-v21/launch_background.xml b/clearassist/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 00000000..f74085f3 --- /dev/null +++ b/clearassist/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/clearassist/android/app/src/main/res/drawable/launch_background.xml b/clearassist/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/clearassist/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/clearassist/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/clearassist/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..c5f90c2b Binary files /dev/null and b/clearassist/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/clearassist/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/clearassist/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..c7cdc046 Binary files /dev/null and b/clearassist/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/clearassist/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/clearassist/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..b274afa7 Binary files /dev/null and b/clearassist/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/clearassist/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/clearassist/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..2423ef1d Binary files /dev/null and b/clearassist/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/clearassist/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/clearassist/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..2102152f Binary files /dev/null and b/clearassist/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/clearassist/android/app/src/main/res/values-night/styles.xml b/clearassist/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 00000000..06952be7 --- /dev/null +++ b/clearassist/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/clearassist/android/app/src/main/res/values/styles.xml b/clearassist/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..cb1ef880 --- /dev/null +++ b/clearassist/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/clearassist/android/app/src/profile/AndroidManifest.xml b/clearassist/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..4073cdae --- /dev/null +++ b/clearassist/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/clearassist/android/build.gradle b/clearassist/android/build.gradle new file mode 100644 index 00000000..1f1f0324 --- /dev/null +++ b/clearassist/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.9.25' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/clearassist/android/gradle.properties b/clearassist/android/gradle.properties new file mode 100644 index 00000000..94adc3a3 --- /dev/null +++ b/clearassist/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/clearassist/android/gradle/wrapper/gradle-wrapper.properties b/clearassist/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..3c472b99 --- /dev/null +++ b/clearassist/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/clearassist/android/settings.gradle b/clearassist/android/settings.gradle new file mode 100644 index 00000000..55c4ca8b --- /dev/null +++ b/clearassist/android/settings.gradle @@ -0,0 +1,20 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() + + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") + + plugins { + id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false + } +} + +include ":app" + +apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/clearassist/assets/icons/app_icon.png b/clearassist/assets/icons/app_icon.png new file mode 100644 index 00000000..c7cdc046 Binary files /dev/null and b/clearassist/assets/icons/app_icon.png differ diff --git a/clearassist/assets/icons/ask_question.png b/clearassist/assets/icons/ask_question.png new file mode 100644 index 00000000..4fc043f5 Binary files /dev/null and b/clearassist/assets/icons/ask_question.png differ diff --git a/clearassist/assets/icons/camera_off.png b/clearassist/assets/icons/camera_off.png new file mode 100644 index 00000000..8c7e96e1 Binary files /dev/null and b/clearassist/assets/icons/camera_off.png differ diff --git a/clearassist/assets/icons/camera_on.png b/clearassist/assets/icons/camera_on.png new file mode 100644 index 00000000..d26a66d1 Binary files /dev/null and b/clearassist/assets/icons/camera_on.png differ diff --git a/clearassist/assets/icons/location_off.png b/clearassist/assets/icons/location_off.png new file mode 100644 index 00000000..f34082f4 Binary files /dev/null and b/clearassist/assets/icons/location_off.png differ diff --git a/clearassist/assets/icons/location_on.png b/clearassist/assets/icons/location_on.png new file mode 100644 index 00000000..7ece826d Binary files /dev/null and b/clearassist/assets/icons/location_on.png differ diff --git a/clearassist/assets/icons/mic_off.png b/clearassist/assets/icons/mic_off.png new file mode 100644 index 00000000..9b50766e Binary files /dev/null and b/clearassist/assets/icons/mic_off.png differ diff --git a/clearassist/assets/icons/mic_on.png b/clearassist/assets/icons/mic_on.png new file mode 100644 index 00000000..e619bc47 Binary files /dev/null and b/clearassist/assets/icons/mic_on.png differ diff --git a/clearassist/assets/icons/virtual_assistant.png b/clearassist/assets/icons/virtual_assistant.png new file mode 100644 index 00000000..d127d88c Binary files /dev/null and b/clearassist/assets/icons/virtual_assistant.png differ diff --git a/clearassist/assets/images/AudioExample.jpg b/clearassist/assets/images/AudioExample.jpg new file mode 100644 index 00000000..98c8b0b6 Binary files /dev/null and b/clearassist/assets/images/AudioExample.jpg differ diff --git a/clearassist/assets/images/GalleryExample.jpg b/clearassist/assets/images/GalleryExample.jpg new file mode 100644 index 00000000..d0d37808 Binary files /dev/null and b/clearassist/assets/images/GalleryExample.jpg differ diff --git a/clearassist/assets/images/Home1.jpg b/clearassist/assets/images/Home1.jpg new file mode 100644 index 00000000..542f4c72 Binary files /dev/null and b/clearassist/assets/images/Home1.jpg differ diff --git a/clearassist/assets/images/HometoAudio.jpg b/clearassist/assets/images/HometoAudio.jpg new file mode 100644 index 00000000..79b15dbd Binary files /dev/null and b/clearassist/assets/images/HometoAudio.jpg differ diff --git a/clearassist/assets/images/HometoGallery.jpg b/clearassist/assets/images/HometoGallery.jpg new file mode 100644 index 00000000..951e4ece Binary files /dev/null and b/clearassist/assets/images/HometoGallery.jpg differ diff --git a/clearassist/assets/images/HometoLocation.jpg b/clearassist/assets/images/HometoLocation.jpg new file mode 100644 index 00000000..f96cbc4f Binary files /dev/null and b/clearassist/assets/images/HometoLocation.jpg differ diff --git a/clearassist/assets/images/HometoObjectSearch.jpg b/clearassist/assets/images/HometoObjectSearch.jpg new file mode 100644 index 00000000..2d0942ff Binary files /dev/null and b/clearassist/assets/images/HometoObjectSearch.jpg differ diff --git a/clearassist/assets/images/HometoVA.jpg b/clearassist/assets/images/HometoVA.jpg new file mode 100644 index 00000000..86bcefde Binary files /dev/null and b/clearassist/assets/images/HometoVA.jpg differ diff --git a/clearassist/assets/images/SettingsScreen.jpg b/clearassist/assets/images/SettingsScreen.jpg new file mode 100644 index 00000000..1409d7cb Binary files /dev/null and b/clearassist/assets/images/SettingsScreen.jpg differ diff --git a/clearassist/assets/images/VAExample.jpg b/clearassist/assets/images/VAExample.jpg new file mode 100644 index 00000000..a74b8f83 Binary files /dev/null and b/clearassist/assets/images/VAExample.jpg differ diff --git a/clearassist/assets/images/background-OLD.jpg b/clearassist/assets/images/background-OLD.jpg new file mode 100644 index 00000000..8e883d21 Binary files /dev/null and b/clearassist/assets/images/background-OLD.jpg differ diff --git a/clearassist/assets/images/background.jpg b/clearassist/assets/images/background.jpg new file mode 100644 index 00000000..48b31149 Binary files /dev/null and b/clearassist/assets/images/background.jpg differ diff --git a/clearassist/assets/images/grey_background.jpg b/clearassist/assets/images/grey_background.jpg new file mode 100644 index 00000000..4c595a16 Binary files /dev/null and b/clearassist/assets/images/grey_background.jpg differ diff --git a/clearassist/assets/images/jokerFace.jpg b/clearassist/assets/images/jokerFace.jpg new file mode 100644 index 00000000..362f72f6 Binary files /dev/null and b/clearassist/assets/images/jokerFace.jpg differ diff --git a/clearassist/assets/images/license_agreement.png b/clearassist/assets/images/license_agreement.png new file mode 100644 index 00000000..089bc687 Binary files /dev/null and b/clearassist/assets/images/license_agreement.png differ diff --git a/clearassist/assets/images/pink_background.png b/clearassist/assets/images/pink_background.png new file mode 100644 index 00000000..ec2ca258 Binary files /dev/null and b/clearassist/assets/images/pink_background.png differ diff --git a/clearassist/assets/seed_data_files/bird.mp3 b/clearassist/assets/seed_data_files/bird.mp3 new file mode 100644 index 00000000..968f4308 Binary files /dev/null and b/clearassist/assets/seed_data_files/bird.mp3 differ diff --git a/clearassist/assets/seed_data_files/bird_transcript.txt b/clearassist/assets/seed_data_files/bird_transcript.txt new file mode 100644 index 00000000..a75d452f --- /dev/null +++ b/clearassist/assets/seed_data_files/bird_transcript.txt @@ -0,0 +1,15 @@ +Test bird transcript content. + +This transcript should be very long in order to ensure that it accurately reflects what a transcript may look like: + +Bird 1: Hey there, feathered friend! Did you catch that delicious worm this morning? + +Bird 2: Oh, absolutely! Are you talking about the one near the oak tree? It was a real treat! How about you? Find any tasty morsels today? + +Bird 1: I had a bit of trouble earlier, but I managed to nab a few tasty seeds by the garden. Those seeds can be tricky to crack open, but the effort was worth it. + +Bird 2: Haha, I can imagine! You always were the patient one, unlike me who prefers the quick and easy snacks. By the way, did you hear about the gathering at the birdbath later? Everyone's invited! + +Bird 1: Oh, I did! I wouldn't miss it for the world. It's always a blast to catch up with our fellow feathered friends and exchange stories about our adventures in the skies. I'll see you there, then? + +Bird 2: Absolutely! I'll be there with bells on, ready to share more tales of our avian escapades. Can't wait! \ No newline at end of file diff --git a/clearassist/assets/seed_data_files/cat.png b/clearassist/assets/seed_data_files/cat.png new file mode 100644 index 00000000..5391eff6 Binary files /dev/null and b/clearassist/assets/seed_data_files/cat.png differ diff --git a/clearassist/assets/seed_data_files/dog.mp4 b/clearassist/assets/seed_data_files/dog.mp4 new file mode 100644 index 00000000..60c1aa8e Binary files /dev/null and b/clearassist/assets/seed_data_files/dog.mp4 differ diff --git a/clearassist/assets/seed_data_files/dog.png b/clearassist/assets/seed_data_files/dog.png new file mode 100644 index 00000000..bb7ad630 Binary files /dev/null and b/clearassist/assets/seed_data_files/dog.png differ diff --git a/clearassist/azure-pipelines.yml b/clearassist/azure-pipelines.yml new file mode 100644 index 00000000..a3aab836 --- /dev/null +++ b/clearassist/azure-pipelines.yml @@ -0,0 +1,19 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +trigger: +- development + +pool: + vmImage: ubuntu-latest + +steps: +- script: echo Hello, world! + displayName: 'Run a one-line script' + +- script: | + echo Add other tasks to build, test, and deploy your project. + echo See https://aka.ms/yaml + displayName: 'Run a multi-line script' diff --git a/clearassist/depencencies-version.txt b/clearassist/depencencies-version.txt new file mode 100644 index 00000000..5af35e3a --- /dev/null +++ b/clearassist/depencencies-version.txt @@ -0,0 +1,645 @@ +Dart SDK 3.1.0 +Flutter SDK 3.13.1 +clearassistapp 1.0.0+1 +|-- assets_audio_player 3.1.1 +| |-- assets_audio_player_web 3.1.1 +| | |-- flutter... +| | '-- flutter_web_plugins... +| |-- rxdart 0.27.7 +| |-- flutter... +| |-- http... +| |-- path_provider... +| '-- uuid... +|-- audio_waveforms 1.0.4 +| '-- flutter... +|-- audioplayers 5.2.0 +| |-- audioplayers_android 4.0.2 +| | |-- audioplayers_platform_interface... +| | '-- flutter... +| |-- audioplayers_darwin 5.0.2 +| | |-- audioplayers_platform_interface... +| | '-- flutter... +| |-- audioplayers_linux 3.1.0 +| | |-- audioplayers_platform_interface... +| | '-- flutter... +| |-- audioplayers_platform_interface 6.1.0 +| | |-- flutter... +| | |-- meta... +| | '-- plugin_platform_interface... +| |-- audioplayers_web 4.1.0 +| | |-- audioplayers_platform_interface... +| | |-- flutter... +| | |-- flutter_web_plugins... +| | '-- js... +| |-- audioplayers_windows 3.1.0 +| | |-- audioplayers_platform_interface... +| | '-- flutter... +| |-- file 7.0.0 +| | |-- meta... +| | '-- path... +| |-- synchronized 3.1.0 +| |-- uuid 3.0.5 +| | '-- crypto... +| |-- flutter... +| |-- http... +| |-- meta... +| '-- path_provider... +|-- avatar_glow 2.0.2 +| '-- flutter... +|-- aws_client 0.4.1 +| |-- crypto 3.0.3 +| | '-- typed_data... +| |-- intl 0.18.1 +| | |-- clock... +| | |-- meta... +| | '-- path... +| |-- xml 6.3.0 +| | |-- petitparser 5.4.0 +| | | '-- meta... +| | |-- collection... +| | '-- meta... +| |-- collection... +| |-- http... +| |-- meta... +| '-- uuid... +|-- aws_kinesis_api 2.0.0 +| '-- shared_aws_api... +|-- aws_rekognition_api 2.0.0 +| '-- shared_aws_api 2.0.1 +| |-- collection... +| |-- crypto... +| |-- http... +| |-- intl... +| |-- meta... +| |-- uuid... +| '-- xml... +|-- aws_s3_api 2.0.0 +| '-- shared_aws_api... +|-- aws_sns_api 2.0.0 +| '-- shared_aws_api... +|-- aws_transcribe_api 2.0.0 +| '-- shared_aws_api... +|-- build_runner 2.4.6 +| |-- args 2.4.2 +| |-- build_config 1.1.1 +| | |-- checked_yaml 2.0.3 +| | | |-- json_annotation... +| | | |-- source_span... +| | | '-- yaml... +| | |-- json_annotation... +| | |-- path... +| | |-- pubspec_parse... +| | '-- yaml... +| |-- build_daemon 4.0.0 +| | |-- built_collection... +| | |-- built_value... +| | |-- http_multi_server... +| | |-- logging... +| | |-- path... +| | |-- pool... +| | |-- shelf... +| | |-- shelf_web_socket... +| | |-- stream_transform... +| | |-- watcher... +| | '-- web_socket_channel... +| |-- build_resolvers 2.4.1 +| | |-- analyzer... +| | |-- async... +| | |-- build... +| | |-- collection... +| | |-- convert... +| | |-- crypto... +| | |-- graphs... +| | |-- logging... +| | |-- package_config... +| | |-- path... +| | |-- pool... +| | |-- pub_semver... +| | |-- stream_transform... +| | '-- yaml... +| |-- build_runner_core 7.2.11 +| | |-- async... +| | |-- build... +| | |-- build_config... +| | |-- build_resolvers... +| | |-- collection... +| | |-- convert... +| | |-- crypto... +| | |-- glob... +| | |-- graphs... +| | |-- json_annotation... +| | |-- logging... +| | |-- meta... +| | |-- package_config... +| | |-- path... +| | |-- pool... +| | |-- timing... +| | |-- watcher... +| | '-- yaml... +| |-- frontend_server_client 3.2.0 +| | |-- async... +| | '-- path... +| |-- glob 2.1.2 +| | |-- async... +| | |-- collection... +| | |-- file... +| | |-- path... +| | '-- string_scanner... +| |-- graphs 2.3.1 +| | '-- collection... +| |-- http_multi_server 3.2.1 +| | '-- async... +| |-- io 1.0.4 +| | |-- meta... +| | |-- path... +| | '-- string_scanner... +| |-- logging 1.2.0 +| |-- mime 1.0.4 +| |-- package_config 2.1.0 +| | '-- path... +| |-- pool 1.5.1 +| | |-- async... +| | '-- stack_trace... +| |-- pub_semver 2.1.4 +| | |-- collection... +| | '-- meta... +| |-- pubspec_parse 1.2.3 +| | |-- checked_yaml... +| | |-- collection... +| | |-- json_annotation... +| | |-- pub_semver... +| | '-- yaml... +| |-- shelf 1.4.1 +| | |-- async... +| | |-- collection... +| | |-- http_parser... +| | |-- path... +| | |-- stack_trace... +| | '-- stream_channel... +| |-- shelf_web_socket 1.0.4 +| | |-- shelf... +| | |-- stream_channel... +| | '-- web_socket_channel... +| |-- stream_transform 2.1.0 +| |-- timing 1.0.1 +| | '-- json_annotation... +| |-- watcher 1.1.0 +| | |-- async... +| | '-- path... +| |-- web_socket_channel 2.4.0 +| | |-- async... +| | |-- crypto... +| | '-- stream_channel... +| |-- yaml 3.1.2 +| | |-- collection... +| | |-- source_span... +| | '-- string_scanner... +| |-- analyzer... +| |-- async... +| |-- build... +| |-- code_builder... +| |-- collection... +| |-- crypto... +| |-- dart_style... +| |-- js... +| |-- meta... +| |-- path... +| '-- stack_trace... +|-- camera 0.10.5+5 +| |-- camera_android 0.10.8+12 +| | |-- camera_platform_interface... +| | |-- flutter... +| | |-- flutter_plugin_android_lifecycle... +| | '-- stream_transform... +| |-- camera_avfoundation 0.9.13+6 +| | |-- camera_platform_interface... +| | |-- flutter... +| | '-- stream_transform... +| |-- camera_platform_interface 2.5.2 +| | |-- cross_file 0.3.3+6 +| | | |-- js... +| | | '-- meta... +| | |-- flutter... +| | |-- plugin_platform_interface... +| | '-- stream_transform... +| |-- camera_web 0.3.2+3 +| | |-- camera_platform_interface... +| | |-- flutter... +| | |-- flutter_web_plugins... +| | '-- stream_transform... +| |-- flutter_plugin_android_lifecycle 2.0.16 +| | '-- flutter... +| |-- flutter... +| '-- quiver... +|-- chat_gpt_flutter 1.0.13 +| |-- dio 4.0.6 +| | |-- http_parser... +| | '-- path... +| |-- json_annotation 4.8.1 +| | '-- meta... +| |-- json_serializable 6.7.1 +| | |-- source_helper 1.3.4 +| | | |-- analyzer... +| | | |-- collection... +| | | '-- source_gen... +| | |-- analyzer... +| | |-- async... +| | |-- build... +| | |-- build_config... +| | |-- collection... +| | |-- json_annotation... +| | |-- meta... +| | |-- path... +| | |-- pub_semver... +| | |-- pubspec_parse... +| | '-- source_gen... +| |-- pretty_dio_logger 1.2.0-beta-1 +| | '-- dio... +| |-- flutter... +| '-- http... +|-- cupertino_icons 1.0.6 +|-- dart_openai 3.0.0 +| |-- fetch_client 1.0.2 +| | |-- fetch_api 1.0.2 +| | | '-- js... +| | '-- http... +| |-- collection... +| |-- http... +| '-- meta... +|-- external_path 1.0.3 +| '-- flutter... +|-- flutter 0.0.0 +| |-- characters 1.3.0 +| |-- collection 1.17.2 +| |-- material_color_utilities 0.5.0 +| | '-- collection... +| |-- meta 1.9.1 +| |-- sky_engine 0.0.99 +| |-- vector_math 2.1.4 +| '-- web 0.1.4-beta +|-- flutter_dotenv 5.1.0 +| '-- flutter... +|-- flutter_lints 2.0.3 +| '-- lints 2.1.1 +|-- flutter_sound 9.2.13 +| |-- flutter_sound_platform_interface 9.2.13 +| | |-- flutter... +| | |-- logger... +| | |-- meta... +| | '-- plugin_platform_interface... +| |-- flutter_sound_web 9.2.13 +| | |-- flutter... +| | |-- flutter_sound_platform_interface... +| | |-- flutter_web_plugins... +| | |-- js... +| | |-- logger... +| | '-- meta... +| |-- logger 1.4.0 +| |-- provider 6.0.5 +| | |-- nested 1.0.0 +| | | '-- flutter... +| | |-- collection... +| | '-- flutter... +| |-- recase 4.1.0 +| |-- flutter... +| |-- path... +| |-- path_provider... +| |-- synchronized... +| '-- uuid... +|-- flutter_speed_dial 7.0.0 +| '-- flutter... +|-- flutter_test 0.0.0 +| |-- boolean_selector 2.1.1 +| | |-- source_span... +| | '-- string_scanner... +| |-- fake_async 1.3.1 +| | |-- clock... +| | '-- collection... +| |-- source_span 1.10.0 +| | |-- collection... +| | |-- path... +| | '-- term_glyph... +| |-- stack_trace 1.11.0 +| | '-- path... +| |-- stream_channel 2.1.1 +| | '-- async... +| |-- string_scanner 1.2.0 +| | '-- source_span... +| |-- term_glyph 1.2.1 +| |-- async... +| |-- characters... +| |-- clock... +| |-- collection... +| |-- flutter... +| |-- matcher... +| |-- material_color_utilities... +| |-- meta... +| |-- path... +| |-- test_api... +| |-- vector_math... +| '-- web... +|-- flutter_tts 3.8.3 +| |-- flutter... +| '-- flutter_web_plugins... +|-- gallery_saver 2.3.2 +| |-- flutter... +| |-- http... +| |-- path... +| '-- path_provider... +|-- geocoding 2.1.1 +| |-- geocoding_android 2.1.2 +| | |-- flutter... +| | '-- geocoding_platform_interface... +| |-- geocoding_ios 2.1.0 +| | |-- flutter... +| | '-- geocoding_platform_interface... +| |-- geocoding_platform_interface 2.0.1 +| | |-- flutter... +| | |-- meta... +| | '-- plugin_platform_interface... +| '-- flutter... +|-- geolocator 10.1.0 +| |-- geolocator_android 4.3.1 +| | |-- flutter... +| | |-- geolocator_platform_interface... +| | '-- uuid... +| |-- geolocator_apple 2.3.2 +| | |-- flutter... +| | '-- geolocator_platform_interface... +| |-- geolocator_platform_interface 4.1.1 +| | |-- flutter... +| | |-- meta... +| | |-- plugin_platform_interface... +| | '-- vector_math... +| |-- geolocator_web 2.2.0 +| | |-- flutter... +| | |-- flutter_web_plugins... +| | '-- geolocator_platform_interface... +| |-- geolocator_windows 0.2.1 +| | |-- flutter... +| | '-- geolocator_platform_interface... +| '-- flutter... +|-- http 0.13.6 +| |-- async 2.11.0 +| | |-- collection... +| | '-- meta... +| |-- http_parser 4.0.2 +| | |-- typed_data 1.3.2 +| | | '-- collection... +| | |-- collection... +| | |-- source_span... +| | '-- string_scanner... +| '-- meta... +|-- image_picker 1.0.4 +| |-- image_picker_android 0.8.8+2 +| | |-- flutter... +| | |-- flutter_plugin_android_lifecycle... +| | '-- image_picker_platform_interface... +| |-- image_picker_for_web 3.0.1 +| | |-- flutter... +| | |-- flutter_web_plugins... +| | |-- image_picker_platform_interface... +| | '-- mime... +| |-- image_picker_ios 0.8.8+2 +| | |-- flutter... +| | '-- image_picker_platform_interface... +| |-- image_picker_linux 0.2.1+1 +| | |-- file_selector_linux 0.9.2+1 +| | | |-- cross_file... +| | | |-- file_selector_platform_interface... +| | | '-- flutter... +| | |-- file_selector_platform_interface 2.6.1 +| | | |-- cross_file... +| | | |-- flutter... +| | | |-- http... +| | | '-- plugin_platform_interface... +| | |-- flutter... +| | '-- image_picker_platform_interface... +| |-- image_picker_macos 0.2.1+1 +| | |-- file_selector_macos 0.9.3+3 +| | | |-- cross_file... +| | | |-- file_selector_platform_interface... +| | | '-- flutter... +| | |-- file_selector_platform_interface... +| | |-- flutter... +| | '-- image_picker_platform_interface... +| |-- image_picker_platform_interface 2.9.1 +| | |-- cross_file... +| | |-- flutter... +| | |-- http... +| | '-- plugin_platform_interface... +| |-- image_picker_windows 0.2.1+1 +| | |-- file_selector_windows 0.9.3+1 +| | | |-- cross_file... +| | | |-- file_selector_platform_interface... +| | | '-- flutter... +| | |-- file_selector_platform_interface... +| | |-- flutter... +| | '-- image_picker_platform_interface... +| '-- flutter... +|-- local_auth 2.1.7 +| |-- local_auth_android 1.0.34 +| | |-- flutter... +| | |-- flutter_plugin_android_lifecycle... +| | |-- intl... +| | '-- local_auth_platform_interface... +| |-- local_auth_ios 1.1.4 +| | |-- flutter... +| | |-- intl... +| | '-- local_auth_platform_interface... +| |-- local_auth_platform_interface 1.0.8 +| | |-- flutter... +| | '-- plugin_platform_interface... +| |-- local_auth_windows 1.0.10 +| | |-- flutter... +| | '-- local_auth_platform_interface... +| '-- flutter... +|-- mockito 5.4.2 +| |-- analyzer 5.13.0 +| | |-- _fe_analyzer_shared 61.0.0 +| | | '-- meta... +| | |-- convert 3.1.1 +| | | '-- typed_data... +| | |-- collection... +| | |-- crypto... +| | |-- glob... +| | |-- meta... +| | |-- package_config... +| | |-- path... +| | |-- pub_semver... +| | |-- source_span... +| | |-- watcher... +| | '-- yaml... +| |-- build 2.4.1 +| | |-- analyzer... +| | |-- async... +| | |-- convert... +| | |-- crypto... +| | |-- glob... +| | |-- logging... +| | |-- meta... +| | |-- package_config... +| | '-- path... +| |-- code_builder 4.7.0 +| | |-- built_collection 5.1.1 +| | |-- built_value 8.6.3 +| | | |-- fixnum 1.1.0 +| | | |-- built_collection... +| | | |-- collection... +| | | '-- meta... +| | |-- collection... +| | |-- matcher... +| | '-- meta... +| |-- dart_style 2.3.2 +| | |-- analyzer... +| | |-- args... +| | |-- path... +| | |-- pub_semver... +| | '-- source_span... +| |-- source_gen 1.4.0 +| | |-- analyzer... +| | |-- async... +| | |-- build... +| | |-- dart_style... +| | |-- glob... +| | |-- path... +| | |-- source_span... +| | '-- yaml... +| |-- test_api 0.6.0 +| | |-- async... +| | |-- boolean_selector... +| | |-- collection... +| | |-- meta... +| | |-- source_span... +| | |-- stack_trace... +| | |-- stream_channel... +| | |-- string_scanner... +| | '-- term_glyph... +| |-- collection... +| |-- matcher... +| |-- meta... +| '-- path... +|-- mocktail 1.0.1 +| |-- collection... +| |-- matcher... +| '-- test_api... +|-- moment_dart 1.1.0 +|-- path 1.8.3 +|-- path_provider 2.1.1 +| |-- path_provider_android 2.2.0 +| | |-- flutter... +| | '-- path_provider_platform_interface... +| |-- path_provider_linux 2.2.1 +| | |-- ffi 2.1.0 +| | |-- xdg_directories 1.0.3 +| | | |-- meta... +| | | '-- path... +| | |-- flutter... +| | |-- path... +| | '-- path_provider_platform_interface... +| |-- path_provider_windows 2.2.1 +| | |-- win32 5.0.9 +| | | '-- ffi... +| | |-- ffi... +| | |-- flutter... +| | |-- path... +| | '-- path_provider_platform_interface... +| |-- flutter... +| |-- path_provider_foundation... +| '-- path_provider_platform_interface... +|-- path_provider_foundation 2.3.1 +| |-- flutter... +| '-- path_provider_platform_interface... +|-- path_provider_platform_interface 2.1.1 +| |-- platform 3.1.3 +| |-- flutter... +| '-- plugin_platform_interface... +|-- permission_handler 11.0.1 +| |-- permission_handler_android 11.1.0 +| | |-- flutter... +| | '-- permission_handler_platform_interface... +| |-- permission_handler_apple 9.1.4 +| | |-- flutter... +| | '-- permission_handler_platform_interface... +| |-- permission_handler_platform_interface 3.12.0 +| | |-- flutter... +| | |-- meta... +| | '-- plugin_platform_interface... +| |-- permission_handler_windows 0.1.3 +| | |-- flutter... +| | '-- permission_handler_platform_interface... +| |-- flutter... +| '-- meta... +|-- plugin_platform_interface 2.1.6 +| '-- meta... +|-- quiver 3.2.1 +| '-- matcher 0.12.16 +| |-- async... +| |-- meta... +| |-- stack_trace... +| |-- term_glyph... +| '-- test_api... +|-- speech_to_text 6.3.0 +| |-- clock 1.1.1 +| |-- flutter_web_plugins 0.0.0 +| | |-- characters... +| | |-- collection... +| | |-- flutter... +| | |-- material_color_utilities... +| | |-- meta... +| | |-- vector_math... +| | '-- web... +| |-- js 0.6.7 +| | '-- meta... +| |-- pedantic 1.11.1 +| |-- speech_to_text_macos 1.0.2 +| | |-- flutter... +| | |-- plugin_platform_interface... +| | '-- speech_to_text_platform_interface... +| |-- speech_to_text_platform_interface 2.1.0 +| | |-- flutter... +| | |-- meta... +| | '-- plugin_platform_interface... +| |-- flutter... +| |-- json_annotation... +| '-- meta... +|-- sqflite 2.3.0 +| |-- sqflite_common 2.5.0 +| | |-- meta... +| | |-- path... +| | '-- synchronized... +| |-- flutter... +| '-- path... +|-- sqflite_common_ffi 2.3.0+2 +| |-- sqlite3 2.1.0 +| | |-- collection... +| | |-- ffi... +| | |-- js... +| | |-- meta... +| | '-- path... +| |-- meta... +| |-- path... +| |-- sqflite_common... +| '-- synchronized... +|-- timeago 3.5.0 +| '-- intl... +|-- video_player 2.7.2 +| |-- html 0.15.4 +| | |-- csslib 1.0.0 +| | | '-- source_span... +| | '-- source_span... +| | |-- flutter... +| | '-- video_player_platform_interface... +| |-- video_player_avfoundation 2.5.0 +| | |-- flutter... +| | '-- video_player_platform_interface... +| |-- video_player_platform_interface 6.2.1 +| | |-- flutter... +| | '-- plugin_platform_interface... +| |-- video_player_web 2.1.1 +| | |-- flutter... +| | |-- flutter_web_plugins... +| | '-- video_player_platform_interface... +| '-- flutter... +'-- video_thumbnail 0.5.3 + '-- flutter.. \ No newline at end of file diff --git a/clearassist/devtools_options.yaml b/clearassist/devtools_options.yaml new file mode 100644 index 00000000..fa0b357c --- /dev/null +++ b/clearassist/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/clearassist/ios/.gitignore b/clearassist/ios/.gitignore new file mode 100644 index 00000000..7a7f9873 --- /dev/null +++ b/clearassist/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/clearassist/ios/Flutter/AppFrameworkInfo.plist b/clearassist/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..9625e105 --- /dev/null +++ b/clearassist/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/clearassist/ios/Flutter/Debug.xcconfig b/clearassist/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..ec97fc6f --- /dev/null +++ b/clearassist/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/clearassist/ios/Flutter/Release.xcconfig b/clearassist/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..c4855bfe --- /dev/null +++ b/clearassist/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/clearassist/ios/Runner.xcodeproj/project.pbxproj b/clearassist/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..7223c1c5 --- /dev/null +++ b/clearassist/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,722 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 80D2DB65DA544E3AEF5540D4 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF199DEC2F35E2FA1839AEB1 /* Pods_Runner.framework */; }; + 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 */; }; + CE16E49C0D6268FC3ABC1231 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B026773EF86950DAB569009B /* Pods_RunnerTests.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy 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 */ + 1052059969D1A7D0FB43110E /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 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 = ""; }; + 16ACBB7106EF11DB2E48948F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 2E8A93FEE95A453846A5E210 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 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 = ""; }; + B026773EF86950DAB569009B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BD04E2EE7BFBDF285206CA51 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + C6A7B915A0547D04E70F74B3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + EF199DEC2F35E2FA1839AEB1 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F5C401E8770FA6B925389757 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 051D93E82342E0CF348FD17C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CE16E49C0D6268FC3ABC1231 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 80D2DB65DA544E3AEF5540D4 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + A341B3CB2765822CA5C29771 /* Pods */, + 9A23D34F4A8C084CA8FD2D56 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + 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 = ""; + }; + 9A23D34F4A8C084CA8FD2D56 /* Frameworks */ = { + isa = PBXGroup; + children = ( + EF199DEC2F35E2FA1839AEB1 /* Pods_Runner.framework */, + B026773EF86950DAB569009B /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + A341B3CB2765822CA5C29771 /* Pods */ = { + isa = PBXGroup; + children = ( + 16ACBB7106EF11DB2E48948F /* Pods-Runner.debug.xcconfig */, + C6A7B915A0547D04E70F74B3 /* Pods-Runner.release.xcconfig */, + 2E8A93FEE95A453846A5E210 /* Pods-Runner.profile.xcconfig */, + BD04E2EE7BFBDF285206CA51 /* Pods-RunnerTests.debug.xcconfig */, + F5C401E8770FA6B925389757 /* Pods-RunnerTests.release.xcconfig */, + 1052059969D1A7D0FB43110E /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 0B1B934F7C4BB313C004C2A3 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + 051D93E82342E0CF348FD17C /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 7869F9B308BAC2AF8E8D64C5 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 03D9B2FF4BBF293E0354B021 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 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 */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 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 */ + 03D9B2FF4BBF293E0354B021 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 0B1B934F7C4BB313C004C2A3 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 7869F9B308BAC2AF8E8D64C5 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + 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-clearassist.clearassistapp"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BD04E2EE7BFBDF285206CA51 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com-clearassist.clearassistapp.RunnerTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F5C401E8770FA6B925389757 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com-clearassist.clearassistapp.RunnerTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1052059969D1A7D0FB43110E /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com-clearassist.clearassistapp.RunnerTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + 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-clearassist.clearassistapp"; + 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-clearassist.clearassistapp"; + 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 */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 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/clearassist/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/clearassist/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/clearassist/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/clearassist/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/clearassist/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/clearassist/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/clearassist/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/clearassist/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/clearassist/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/clearassist/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/clearassist/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..87131a09 --- /dev/null +++ b/clearassist/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/clearassist/ios/Runner.xcworkspace/contents.xcworkspacedata b/clearassist/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..21a3cc14 --- /dev/null +++ b/clearassist/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/clearassist/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/clearassist/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/clearassist/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/clearassist/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/clearassist/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/clearassist/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/clearassist/ios/Runner/AppDelegate.swift b/clearassist/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/clearassist/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/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/clearassist/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/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 00000000..dc9ada47 Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 00000000..7353c41e Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 00000000..797d452e Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 00000000..6ed2d933 Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 00000000..4cd7b009 Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 00000000..fe730945 Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 00000000..321773cd Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 00000000..797d452e Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 00000000..502f463a Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 00000000..0ec30343 Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 00000000..0ec30343 Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 00000000..e9f5fea2 Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 00000000..84ac32ae Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 00000000..8953cba0 Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 00000000..0467bf12 Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 00000000..0bedcf2f --- /dev/null +++ b/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/clearassist/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/clearassist/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/clearassist/ios/Runner/Base.lproj/LaunchScreen.storyboard b/clearassist/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/clearassist/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/clearassist/ios/Runner/Base.lproj/Main.storyboard b/clearassist/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/clearassist/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/clearassist/ios/Runner/Info.plist b/clearassist/ios/Runner/Info.plist new file mode 100644 index 00000000..a406ee2c --- /dev/null +++ b/clearassist/ios/Runner/Info.plist @@ -0,0 +1,55 @@ + + + + + NSFaceIDUsageDescription + We use FaceID for user authentication. + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ClearAssistapp + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + clearassistapp + 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 + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + NSLocationWhenInUseUsageDescription + This app needs access to location when open. + NSLocationAlwaysUsageDescription + This app needs access to location when in the background. + + diff --git a/clearassist/ios/Runner/Runner-Bridging-Header.h b/clearassist/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/clearassist/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/clearassist/ios/RunnerTests/RunnerTests.swift b/clearassist/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 00000000..86a7c3b1 --- /dev/null +++ b/clearassist/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/clearassist/lib/main.dart b/clearassist/lib/main.dart new file mode 100644 index 00000000..7b41e3db --- /dev/null +++ b/clearassist/lib/main.dart @@ -0,0 +1,67 @@ +import 'package:clearassistapp/src/camera_manager.dart'; +import 'package:clearassistapp/src/data_service.dart'; +import 'package:clearassistapp/src/s3_connection.dart'; +import 'package:clearassistapp/src/utils/directory_manager.dart'; +import 'package:clearassistapp/src/utils/logger.dart'; +import 'package:clearassistapp/src/utils/permission_manager.dart'; +import 'package:clearassistapp/ui/global_settings.dart'; +import 'package:clearassistapp/ui/home_screen.dart'; +import 'package:clearassistapp/ui/login_screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; + +void main() async { + initializeLogging(); + await dotenv.load(fileName: ".env"); + await DirectoryManager.instance.initializeDirectories(); + await DataService.instance.initializeData(); + await GlobalSettings.loadBackgroundPath(); + initializeData(); + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + title: 'ClearAssist', + theme: ThemeData( + primarySwatch: Colors.blue, + textTheme: Theme.of(context).textTheme.copyWith( + bodySmall: TextStyle(color: Colors.white), + bodyMedium: TextStyle(color: Colors.white), + bodyLarge: TextStyle(color: Colors.white), + displayLarge: TextStyle(color: Colors.white), + displayMedium: TextStyle(color: Colors.white), + displaySmall: TextStyle(color: Colors.white), + headlineLarge: TextStyle(color: Colors.white), + headlineMedium: TextStyle(color: Colors.white), + headlineSmall: + TextStyle(color: Colors.white, fontWeight: FontWeight.bold), + titleLarge: TextStyle(color: Colors.white), + titleMedium: TextStyle(color: Colors.white), + titleSmall: TextStyle(color: Colors.white), + labelLarge: TextStyle(color: Colors.white), + labelMedium: TextStyle(color: Colors.white), + labelSmall: TextStyle(color: Colors.white), + ), + ), + initialRoute: '/loginScreen', + routes: { + '/loginScreen': (context) => const LoginScreen(), + '/homeScreen': (context) => const HomeScreen(), + // Add more routes if necessary + }, + ); + } +} + +// Singleton initialization +void initializeData() async { + S3Bucket s3 = S3Bucket(); + CameraManager cm = CameraManager(); + await PermissionManager.requestInitialPermissions(); + await cm.initializeCamera(); +} diff --git a/clearassist/lib/src/address.dart b/clearassist/lib/src/address.dart new file mode 100644 index 00000000..a2b6aa83 --- /dev/null +++ b/clearassist/lib/src/address.dart @@ -0,0 +1,83 @@ +/* + Description + ----------- + This class provides the address of the phone running an app. + + 1. Obtain permission to access the device's Global Position System (GPS) receiver. + 2. Get the geospatial location from GPS. + 3. Use a web service to translate the coordinates to an address. + + Usage + ----- + 1. Add to AndroidManifest.xml files: + + + 2. Add to ios/Info.plist + NSLocationWhenInUseUsageDescription + This app needs access to location when open. + NSLocationAlwaysUsageDescription + This app needs access to location when in the background. + + 3. Add to pubspec.yaml + dependencies: + # A Flutter geocoding plugin which provides easy geocoding and reverse-geocoding features. + geocoding: ^2.1.1 + + # A Flutter geolocation plugin which provides easy access to platform specific location services. + geolocator: ^10.1.0 + + 4. Import file + import "address.dart"; + + 5. Make static function call + var physicalAddress = ""; + await Address.whereIAm().then((String address) { + physicalAddress = address; + }); + debugPrint(physicalAddress); + + Note + ---- + If run on an emulator, the return will always be "1650 Amphitheatre Pkwy, Mountain View, 94043, United States". +*/ + +import 'package:geocoding/geocoding.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:clearassistapp/src/utils/logger.dart'; + +class Address { + // The testing suite does not allow for mocking permissions, so we need to manually skip them if called during a test + // isTesting is off by default, and only enabled during testing calls + static Future whereIAm({bool isTesting = false}) async { + // Ensure GPS access + + if (!isTesting) { + LocationPermission locationPermission = + await Geolocator.checkPermission(); + + if (locationPermission == LocationPermission.denied || + locationPermission == LocationPermission.deniedForever) { + return ""; + } + } + + await Geolocator.requestPermission(); + + // Ask GPS to provide its current latitude and longitude coordinates + Position currentPosition = await Geolocator.getCurrentPosition( + desiredAccuracy: LocationAccuracy.best); + + // Ask Geocoder to match the coordinates to a geophysical address + try { + List currentPlacemarks = await placemarkFromCoordinates( + currentPosition.latitude, currentPosition.longitude); + Placemark currentPlace = currentPlacemarks[0]; + var address = + "${currentPlace.street}, ${currentPlace.locality}, ${currentPlace.administrativeArea}, ${currentPlace.postalCode}, ${currentPlace.isoCountryCode}"; + return address; + } catch (e) { + appLogger.severe(e); + return ""; + } + } +} diff --git a/clearassist/lib/src/aws_video_response.dart b/clearassist/lib/src/aws_video_response.dart new file mode 100644 index 00000000..84a45036 --- /dev/null +++ b/clearassist/lib/src/aws_video_response.dart @@ -0,0 +1,62 @@ +// Author: David Bright +// Date: 2023-10-10 +// Description: These classes are used to individually access the responses +// in the AWS Rekognition Object Label Response +// Last modified by: Zach Bowman +// Last modified on: 2023-11-02 + +import 'package:clearassistapp/src/utils/file_manager.dart'; +import 'package:flutter/material.dart'; + +class AWSVideoResponse { + String name; + double confidence; + int timestamp; + ResponseBoundingBox boundingBox; + String referenceVideoFilePath; + String address; + String parents; + + Image exampleImage = Image.network( + "https://cdn.pixabay.com/photo/2014/06/03/19/38/road-sign-361514_1280.png"); + + AWSVideoResponse.overloaded( + this.name, + this.confidence, + this.timestamp, + this.boundingBox, + this.referenceVideoFilePath, + this.address, + this.parents); + + //pull thumbnail image from the local file + Future getImage() async { + return await FileManager.getThumbnail( + FileManager.mostRecentVideoPath, timestamp); + } + + //reset thumbnail image with a new thumbnail from updated timestamp + void setImage(int timeStampNew) async { + exampleImage = await FileManager.getThumbnail( + FileManager.mostRecentVideoPath, timeStampNew); + } +} + +//Bounding Box coordinates - in double percentage (i.e., 0.1 for left means 10% of the pixel width from the left side for the initial box coordinate) +class ResponseBoundingBox { + double left; + double top; + double width; + double height; + + ResponseBoundingBox( + {required this.left, + required this.top, + required this.width, + required this.height}); + + @override + String toString() { + return 'ResponseBoundingBox{left: $left, top: $top, width: $width, height: $height}'; + } +} diff --git a/clearassist/lib/src/camera_manager.dart b/clearassist/lib/src/camera_manager.dart new file mode 100644 index 00000000..4d66613f --- /dev/null +++ b/clearassist/lib/src/camera_manager.dart @@ -0,0 +1,224 @@ +// Author: Ben Sutter +// Description: This class is used to control the video camera and associated auto record functionality. +// This class also enables for photo captures when prompted in the gallery screen. + +import 'dart:async'; +import 'dart:io'; + +import 'package:camera/camera.dart'; +import 'package:clearassistapp/src/data_service.dart'; +import 'package:clearassistapp/src/utils/directory_manager.dart'; +import 'package:clearassistapp/src/utils/file_manager.dart'; +import 'package:clearassistapp/src/utils/format_utils.dart'; +import 'package:clearassistapp/src/utils/logger.dart'; +import 'package:clearassistapp/src/utils/permission_manager.dart'; +import "package:flutter/material.dart"; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:image_picker/image_picker.dart'; + +/// Camera manager class to handle camera functionality. +class CameraManager { + CameraManager? cameraManager; + List _cameras = []; + late CameraController controller; + + static final CameraManager _instance = CameraManager._internal(); + + bool isAutoRecording = false; + bool uploadToRekognition = false; + bool isInitialized = false; + + int autoRecordingInterval = 60; + int cameraToUse = 1; + + late Image recentThumbnail; + CameraManager._internal(); + + factory CameraManager() { + return _instance; + } + + // Initalize the camera so it is ready for auto recording + Future initializeCamera() async { + parseEnviromentSettings(); + + // If permission is not granted then don't initialize + if (!await PermissionManager.cameraPermissionGranted()) { + isAutoRecording = false; + return; + } + + // Now, proceed with camera initialization + _cameras = await availableCameras(); + + // Make sure that there are available cameras if trying to use the front + // 0 equals rear, 1 = front + if (_cameras.length == 1) { + cameraToUse = 0; + } else if (_cameras.isEmpty) { + FormatUtils.logBigMessage("ERROR: NO CAMERAS DETECTED"); + return; + } + controller = CameraController(_cameras[cameraToUse], ResolutionPreset.high); + + await controller.initialize(); + + if (controller.value.isInitialized) { + isInitialized = true; + FormatUtils.logBigMessage("CAMERA HAS BEEN INITIALIZED"); + } + } + + // Parse environmental variables to determine enabld features + void parseEnviromentSettings() async { + await dotenv.load(fileName: ".env"); + cameraToUse = int.parse(dotenv.get('cameraToUse', fallback: "1")); + autoRecordingInterval = + int.parse(dotenv.get('autoRecordInterval', fallback: "60")); + isAutoRecording = + dotenv.get('autoRecordEnabled', fallback: "false") == "true"; + uploadToRekognition = + dotenv.get('autoUploadToRekognitionEnabled', fallback: "false") == + "true"; + String cameraUsed = (_cameras.length > 1) ? "front" : "rear"; + + if (isAutoRecording) { + FormatUtils.logBigMessage("AUTO VIDEO RECORDING IS ENABLED"); + } else { + FormatUtils.logBigMessage("AUTO VIDEO RECORDING IS DISABLED"); + } + + if (uploadToRekognition) { + FormatUtils.logBigMessage("AUTO REKOGNITION UPLOAD IS ENABLED"); + } else { + FormatUtils.logBigMessage("AUTO REKOGNITION UPLOAD IS DISABLED"); + } + + appLogger + .info("The camera that is being automatically used is the $cameraUsed"); + } + + // Starts the auto recording process + void startAutoRecording() async { + if (isAutoRecording) { + // Delay for camera initialization + Future.delayed(const Duration(milliseconds: 1500), () { + FormatUtils.logBigMessage("AUTO VIDEO RECORDING HAS STARTED"); + + startRecordingInBackground(); + }); + } + } + + // Stops any ongoing video recording + Future stopRecording() async { + try { + XFile? file = await controller.stopVideoRecording(); + + await saveMediaLocally(file); + } catch (e) { + appLogger.severe(e); + } + } + + Future manuallyStopRecording() async { + isAutoRecording = false; + await stopRecording(); + } + + Future manuallyStartRecording() async { + isAutoRecording = true; + startRecordingInBackground(); + } + + // Automatically starts looping in teh background until the user stops the video + void startRecordingInBackground() async { + if (!controller.value.isInitialized) { + appLogger.info('Error: Camera is not initialized.'); + appLogger.info('Auto recording has been canceled.'); + return; + } + + // Start recording in the background + + if (!isAutoRecording) { + return; + } + + controller.startVideoRecording(); + + // Record for 5 minutes (300 seconds) + await Future.delayed(Duration(seconds: autoRecordingInterval)); + + if (!isAutoRecording) { + return; + } + + await stopRecording(); + + await Future.delayed(const Duration(seconds: 2)); + // Start the next loop of the recording + startRecordingInBackground(); + } + + // Saves the media locally to app storage for use with other application aspects + Future saveMediaLocally(XFile mediaFile) async { + // Get the local directory + + // Define a file name for the saved media, you can use a timestamp or any unique name + const String fileExtension = 'mp4'; + + final String timestamp = DateTime.now().toString(); + final String sanitizedTimestamp = timestamp.replaceAll(' ', '_'); + final String fileName = + '$sanitizedTimestamp.$fileExtension'; // Use the determined file extension + + // Create a new file by copying the media file to the local directory + final File localFile = + File('${DirectoryManager.instance.videosDirectory.path}/$fileName'); + + // Copy the media to the local directory + await localFile.writeAsBytes(await mediaFile.readAsBytes()); + + // Check if the media file has been successfully saved + if (localFile.existsSync()) { + appLogger.info('Media saved locally: ${localFile.path}'); + FileManager.getMostRecentVideo(); + } else { + appLogger.severe('Failed to save media locally.'); + } + } + + // Takes a photo and saves it to the directory specified + Future capturePhoto(Directory destinationDirectory) async { + CameraManager manager = CameraManager(); + await manager.manuallyStopRecording(); + final String timestamp = DateTime.now().toString(); + final String sanitizedTimestamp = timestamp.replaceAll(' ', '_'); + final String fileName = + '$sanitizedTimestamp.jpg'; // Use the determined file extension + + final String fullPath = '${destinationDirectory.path}/$fileName'; + final ImagePicker picker = ImagePicker(); + await picker + .pickImage(source: ImageSource.camera) + .then((XFile? recordedimage) async { + if (recordedimage != null) { + // Copy the image to the specified location + File sourceFile = File(recordedimage.path); + File destinationFile = File(fullPath); + + try { + await sourceFile.copy(destinationFile.path); + // You can now use the 'destinationFile' for further operations if needed. + // Log the path of the saved image + appLogger.info('Image saved at: ${destinationFile.path}'); + await DataService.instance.addPhoto(photoFile: destinationFile); + } catch (e) { + appLogger.severe('Error while copying the image: $e'); + } + } + }); + manager.initializeCamera(); + } +} diff --git a/clearassist/lib/src/custom_label_response.dart b/clearassist/lib/src/custom_label_response.dart new file mode 100644 index 00000000..7a831c35 --- /dev/null +++ b/clearassist/lib/src/custom_label_response.dart @@ -0,0 +1,40 @@ +// Author: David Bright +// Date: 2023-10-25 +// Description: These classes are used to individually access the responses +// in the AWS Rekognition Custom Label Response +// Last modified by: Ben Sutter +// Last modified on: 2023-11-03 + +import 'package:flutter/material.dart'; + +//class to work with the Custom Label Response from AWS Rekognition. +class CustomLabelResponse { + String name; + double confidence; + ResponseBoundingBox? boundingBox; + Image exampleImage = + const Image(image: AssetImage("assets/test_images/eyeglass-green.jpg")); + + CustomLabelResponse(this.name, this.confidence); + + CustomLabelResponse.overloaded(this.name, this.confidence, this.boundingBox); +} + +//class for the bounding box information in the Response object. +class ResponseBoundingBox { + double left; + double top; + double width; + double height; + + ResponseBoundingBox( + {required this.left, + required this.top, + required this.width, + required this.height}); + + @override + String toString() { + return 'ResponseBoundingBox{left: $left, top: $top, width: $width, height: $height}'; + } +} diff --git a/clearassist/lib/src/data_service.dart b/clearassist/lib/src/data_service.dart new file mode 100644 index 00000000..77a909be --- /dev/null +++ b/clearassist/lib/src/data_service.dart @@ -0,0 +1,301 @@ +import 'dart:io'; + +import 'package:clearassistapp/src/database/controller/audio_controller.dart'; +import 'package:clearassistapp/src/database/controller/photo_controller.dart'; +import 'package:clearassistapp/src/database/model/audio.dart'; +import 'package:clearassistapp/src/database/model/media.dart'; +import 'package:clearassistapp/src/database/model/photo.dart'; +import 'package:clearassistapp/src/utils/format_utils.dart'; +import 'package:clearassistapp/src/database/repository/audio_repository.dart'; +import 'package:clearassistapp/src/database/repository/photo_repository.dart'; +import 'package:clearassistapp/src/utils/logger.dart'; + +class DataService { + DataService._internal(); + + static final DataService _instance = DataService._internal(); + static DataService get instance => _instance; + + late List mediaList = []; + bool hasBeenInitialized = false; + + Future initializeData() async { + await loadMedia(); + } + + // Used to show local database and objects + Future loadMedia() async { + final audios = await AudioRepository.instance.readAll(); + final photos = await PhotoRepository.instance.readAll(); + + mediaList = [...audios, ...photos]; + + if (!hasBeenInitialized) { + FormatUtils.logBigMessage("LOCAL DATABASE OBJECTS START"); + + if (audios.isNotEmpty) { + FormatUtils.logBigMessage("AUDIO OBJECTS START"); + for (var audio in audios) { + print('Audio #${audio.id}: ${audio.toJson()}'); + } + FormatUtils.logBigMessage("AUDIO OBJECTS END"); + } + + if (photos.isNotEmpty) { + FormatUtils.logBigMessage("PHOTO OBJECTS START"); + for (var photo in photos) { + print('Photo #${photo.id}: ${photo.toJson()}'); + } + FormatUtils.logBigMessage("PHOTO OBJECTS END"); + } + + FormatUtils.logBigMessage("LOCAL DATABASE OBJECTS END"); + hasBeenInitialized = true; + } + } + + Future unloadMedia() async { + mediaList.clear(); + } + + Future refreshMedia() async { + await unloadMedia(); + await loadMedia(); + } + + // |-------------------------------------------------------------------------| + // |--------------------------- AUDIO OPERATIONS ----------------------------| + // |-------------------------------------------------------------------------| + + // TODO, refactor seed data to just use addAudio(); + Future addSeedAudio({ + String? title, + String? description, + List? tags, + required File audioFile, + File? transcriptFile, + String? summary, + }) async { + try { + final audio = await AudioController.addSeedAudio( + title: title, + description: description, + tags: tags, + audioFile: audioFile, + transcriptFile: transcriptFile, + summary: summary, + ); + if (audio != null) { + await refreshMedia(); + } + return audio; + } catch (e) { + appLogger.severe('Data Service -- Error adding audio: $e'); + return null; + } + } + + Future addAudio({ + String? title, + String? description, + List? tags, + required File audioFile, + File? transcriptFile, + String? summary, + }) async { + try { + final audio = await AudioController.addAudio( + title: title, + description: description, + tags: tags, + audioFile: audioFile, + transcriptFile: transcriptFile, + summary: summary, + ); + if (audio != null) { + await refreshMedia(); + } + return audio; + } catch (e) { + appLogger.severe('Data Service -- Error adding audio: $e'); + return null; + } + } + + Future updateAudio({ + required int id, + String? title, + String? description, + List? tags, + bool? isFavorited, + File? transcriptFile, + String? summary, + }) async { + try { + final audio = await AudioController.updateAudio( + id: id, + title: title, + description: description, + isFavorited: isFavorited, + tags: tags, + transcriptFile: transcriptFile, + summary: summary, + ); + if (audio != null) { + await refreshMedia(); + } + return audio; + } catch (e) { + appLogger.severe('Data Service -- Error updating audio: $e'); + return null; + } + } + + Future removeAudio(int id) async { + try { + final audio = await AudioController.removeAudio(id); + if (audio != null) { + await refreshMedia(); + } + return audio; + } catch (e) { + appLogger.severe('Data Service -- Error removing audio: $e'); + return null; + } + } + + // |-------------------------------------------------------------------------| + // |--------------------------- PHOTO OPERATIONS ----------------------------| + // |-------------------------------------------------------------------------| + +// TODO, refactor seed data to just use addPhoto(); + Future addSeedPhoto({ + String? title, + String? description, + List? tags, + required File photoFile, + }) async { + try { + final photo = await PhotoController.addSeedPhoto( + title: title, + description: description, + tags: tags, + photoFile: photoFile, + ); + if (photo != null) { + await refreshMedia(); + } + return photo; + } catch (e) { + appLogger.severe('Data Service -- Error adding photo: $e'); + return null; + } + } + + Future addPhoto({ + String? title, + String? description, + List? tags, + required File photoFile, + }) async { + try { + final photo = await PhotoController.addPhoto( + title: title, + description: description, + tags: tags, + photoFile: photoFile, + ); + if (photo != null) { + await refreshMedia(); + } + return photo; + } catch (e) { + appLogger.severe('Data Service -- Error adding photo: $e'); + return null; + } + } + + Future updatePhoto({ + required int id, + String? title, + String? description, + bool? isFavorited, + List? tags, + }) async { + try { + final photo = await PhotoController.updatePhoto( + id: id, + title: title, + description: description, + isFavorited: isFavorited, + tags: tags, + ); + if (photo != null) { + await refreshMedia(); + } + return photo; + } catch (e) { + appLogger.severe('Data Service -- Error updating photo: $e'); + return null; + } + } + + Future removePhoto(int id) async { + try { + final photo = await PhotoController.removePhoto(id); + if (photo != null) { + await refreshMedia(); + } + return photo; + } catch (e) { + appLogger.severe('Data Service -- Error removing photo: $e'); + return null; + } + } + + // |-------------------------------------------------------------------------| + // |--------------------------- OTHER OPERATIONS ----------------------------| + // |-------------------------------------------------------------------------| + + Future updateMediaIsFavorited(Media media, bool isFavorited) async { + try { + Media? updatedMedia; + if (media is Audio) { + updatedMedia = await updateAudio( + id: media.id!, + isFavorited: isFavorited, + ); + } else if (media is Photo) { + updatedMedia = await updatePhoto( + id: media.id!, + isFavorited: isFavorited, + ); + } + return updatedMedia; + } catch (e) { + appLogger.severe('Data Service -- Error updating media isFavorited: $e'); + return null; + } + } + + Future updateMediaTags(Media media, List? tags) async { + try { + Media? updatedMedia; + if (media is Audio) { + updatedMedia = await updateAudio( + id: media.id!, + tags: tags, + ); + } else if (media is Photo) { + updatedMedia = await updatePhoto( + id: media.id!, + tags: tags, + ); + } + return updatedMedia; + } catch (e) { + appLogger.severe('Data Service -- Error updating media tags: $e'); + return null; + } + } +} diff --git a/clearassist/lib/src/database/app_database.dart b/clearassist/lib/src/database/app_database.dart new file mode 100644 index 00000000..a4fec435 --- /dev/null +++ b/clearassist/lib/src/database/app_database.dart @@ -0,0 +1,83 @@ +import 'package:clearassistapp/src/database/app_seed_data.dart'; +import 'package:clearassistapp/src/database/model/media.dart'; +import 'package:clearassistapp/src/database/repository/audio_repository.dart'; +import 'package:clearassistapp/src/database/repository/photo_repository.dart'; +import 'package:path/path.dart'; +import 'package:sqflite/sqflite.dart'; + +class AppDatabase { + static const tableLocations = 'locations'; + static final AppDatabase instance = AppDatabase._init(); + + static Database? _database; + + AppDatabase._init(); + + Future get database async { + if (_database != null) return _database!; + + _database = await _initDB('app.db'); + return _database!; + } + + Future _initDB(String filePath) async { + final dbPath = await getDatabasesPath(); + final path = join(dbPath, filePath); + + return await openDatabase(path, version: 1, onCreate: _createDB); + } + + Future _createDB(Database db, int version) async { + const idType = 'INTEGER PRIMARY KEY AUTOINCREMENT'; + const textType = 'TEXT NOT NULL'; + const boolType = 'BOOLEAN NOT NULL'; + const integerType = 'INTEGER NOT NULL'; + const textNullableType = 'TEXT'; + const floatType = 'FLOAT'; + + final mediaColumns = [ + '${MediaFields.id} $idType', + '${MediaFields.title} $textNullableType', + '${MediaFields.description} $textNullableType', + '${MediaFields.tags} $textNullableType', + '${MediaFields.timestamp} $integerType', + '${MediaFields.physicalAddress} $textNullableType', + '${MediaFields.storageSize} $integerType', + '${MediaFields.isFavorited} $boolType', + ]; + + await db.execute(''' + CREATE TABLE $tableAudios ( + ${mediaColumns.join(',\n')}, + ${AudioFields.audioFileName} $textType, + ${AudioFields.transcriptFileName} $textNullableType, + ${AudioFields.summary} $textNullableType + ) + '''); + + await db.execute(''' + CREATE TABLE $tablePhotos ( + ${mediaColumns.join(',\n')}, + ${PhotoFields.photoFileName} $textType + ) + '''); + + await db.execute(''' + CREATE TABLE $tableLocations ( + id $idType, + latitude $floatType, + longitude $floatType, + address $textNullableType, + timestamp $integerType + ) + '''); + + final appSeedData = AppSeedData(); + appSeedData.loadAppSeedData(); + } + + Future close() async { + final db = await instance.database; + db.close(); + } +} diff --git a/clearassist/lib/src/database/app_seed_data.dart b/clearassist/lib/src/database/app_seed_data.dart new file mode 100644 index 00000000..e813b4a3 --- /dev/null +++ b/clearassist/lib/src/database/app_seed_data.dart @@ -0,0 +1,62 @@ +import 'dart:io'; + +import 'package:clearassistapp/src/data_service.dart'; +import 'package:clearassistapp/src/utils/file_manager.dart'; +import 'package:clearassistapp/src/utils/logger.dart'; + +class AppSeedData { + void loadAppSeedData() async { + await loadSeedAudio(); + await loadSeedPhoto(); + await loadSeedVideo(); + } + + Future loadSeedAudio() async { + try { + File? audioFile = await FileManager.loadAssetFile( + 'assets/seed_data_files/bird.mp3', 'bird.mp3'); + File? transcriptFile = await FileManager.loadAssetFile( + 'assets/seed_data_files/bird_transcript.txt', 'bird_transcript.txt'); + List? tagsList = ['nature', 'bird']; + await DataService.instance.addSeedAudio( + title: 'Bird', + description: 'Audio of birds singing in the forest.', + tags: tagsList, + audioFile: audioFile, + transcriptFile: transcriptFile, + summary: 'This is a nature recording of birds singing.'); + FileManager.unloadAssetFile('bird.mp3'); + } catch (e) { + appLogger.severe('Error loading seed data photo: $e'); + } + } + + Future loadSeedPhoto() async { + try { + File? photoFile = await FileManager.loadAssetFile( + 'assets/seed_data_files/cat.png', 'cat.png'); + List? tagsList = ['pet', 'cat']; + await DataService.instance.addSeedPhoto( + title: 'Cat', + description: 'A photo of my pet cat, Kit Kat.', + tags: tagsList, + photoFile: photoFile, + ); + FileManager.unloadAssetFile('cat.png'); + } catch (e) { + appLogger.severe('Error loading seed data photo: $e'); + } + } + + Future loadSeedVideo() async { + try { + File? thumbnailFile = await FileManager.loadAssetFile( + 'assets/seed_data_files/dog.png', 'dog.png'); + List? tagsList = ['pet', 'dog']; + FileManager.unloadAssetFile('dog.mp4'); + FileManager.unloadAssetFile('dog.png'); + } catch (e) { + appLogger.severe('Error loading seed data video: $e'); + } + } +} diff --git a/clearassist/lib/src/database/controller/audio_controller.dart b/clearassist/lib/src/database/controller/audio_controller.dart new file mode 100644 index 00000000..40bb6d0c --- /dev/null +++ b/clearassist/lib/src/database/controller/audio_controller.dart @@ -0,0 +1,169 @@ +import 'dart:io'; + +import 'package:clearassistapp/src/address.dart'; +import 'package:clearassistapp/src/database/model/audio.dart'; +import 'package:clearassistapp/src/database/model/media_type.dart'; +import 'package:clearassistapp/src/database/repository/audio_repository.dart'; +import 'package:clearassistapp/src/utils/constants.dart'; +import 'package:clearassistapp/src/utils/directory_manager.dart'; +import 'package:clearassistapp/src/utils/file_manager.dart'; +import 'package:clearassistapp/src/utils/logger.dart'; + +class AudioController { + AudioController._(); + + static Future addSeedAudio({ + String? title, + String? description, + List? tags, + required File audioFile, + File? transcriptFile, + String? summary, + }) async { + try { + DateTime timestamp = DateTime.now(); + String physicalAddress = defaultAddress; + String audioFileExtension = + FileManager().getFileExtensionFromFile(audioFile); + String audioFileName = FileManager().generateFileName( + MediaType.audio.name, + timestamp, + audioFileExtension, + ); + int audioFileSize = FileManager.calculateFileSizeInBytes(audioFile); + String? transcriptFileName; + if (transcriptFile != null) { + String transcriptFileExtension = + FileManager().getFileExtensionFromFile(transcriptFile); + transcriptFileName = FileManager().generateFileName( + transcriptType, + timestamp, + transcriptFileExtension, + ); + await FileManager.addFileToFilesystem( + transcriptFile, + DirectoryManager.instance.transcriptsDirectory.path, + transcriptFileName, + ); + } + + Audio newAudio = Audio( + title: title, + description: description, + tags: tags, + timestamp: timestamp, + physicalAddress: physicalAddress, + audioFileName: audioFileName, + storageSize: audioFileSize, + isFavorited: false, + transcriptFileName: transcriptFileName, + summary: summary, + ); + + Audio createdAudio = await AudioRepository.instance.create(newAudio); + await FileManager.addFileToFilesystem( + audioFile, + DirectoryManager.instance.audiosDirectory.path, + audioFileName, + ); + return createdAudio; + } catch (e) { + appLogger.severe('Audio Controller -- Error adding audio: $e'); + return null; + } + } + + static Future addAudio({ + String? title, + String? description, + List? tags, + required File audioFile, + File? transcriptFile, + String? summary, + }) async { + try { + DateTime timestamp = DateTime.now(); + String physicalAddress = ""; + await Address.whereIAm().then((String address) { + physicalAddress = address; + }); + String audioFileName = FileManager.getFileName(audioFile.path); + int audioFileSize = FileManager.calculateFileSizeInBytes(audioFile); + String? transcriptFileName; + if (transcriptFile != null) { + transcriptFileName = FileManager.getFileName(transcriptFile.path); + } + + Audio newAudio = Audio( + title: title, + description: description, + tags: tags, + timestamp: timestamp, + physicalAddress: physicalAddress, + audioFileName: audioFileName, + storageSize: audioFileSize, + isFavorited: false, + transcriptFileName: transcriptFileName, + summary: summary, + ); + Audio createdAudio = await AudioRepository.instance.create(newAudio); + return createdAudio; + } catch (e) { + appLogger.severe('Audio Controller -- Error adding audio: $e'); + return null; + } + } + + static Future updateAudio({ + required int id, + String? title, + String? description, + bool? isFavorited, + List? tags, + File? transcriptFile, + String? summary, + }) async { + try { + final existingAudio = await AudioRepository.instance.read(id); + String? updatedTranscriptFileName; + if (transcriptFile != null) { + updatedTranscriptFileName = + FileManager.getFileName(transcriptFile.path); + } + + final updatedAudio = existingAudio.copy( + title: title ?? existingAudio.title, + description: description ?? existingAudio.description, + isFavorited: isFavorited ?? existingAudio.isFavorited, + tags: tags ?? existingAudio.tags, + transcriptFileName: updatedTranscriptFileName, + summary: summary ?? existingAudio.summary, + ); + + await AudioRepository.instance.update(updatedAudio); + return updatedAudio; + } catch (e) { + appLogger.severe('Audio Controller -- Error updating audio: $e'); + return null; + } + } + + static Future removeAudio(int id) async { + try { + final existingAudio = await AudioRepository.instance.read(id); + await AudioRepository.instance.delete(id); + final audioFilePath = + '${DirectoryManager.instance.audiosDirectory.path}/${existingAudio.audioFileName}'; + await FileManager.removeFileFromFilesystem(audioFilePath); + if (existingAudio.transcriptFileName != null) { + final transcriptFilePath = + '${DirectoryManager.instance.transcriptsDirectory.path}/${existingAudio.transcriptFileName}'; + await FileManager.removeFileFromFilesystem(transcriptFilePath); + } + return existingAudio; + } catch (e) { + appLogger.severe('Audio Controller -- Error removing audio: $e'); + return null; + } + } +} diff --git a/clearassist/lib/src/database/controller/contact_controller.dart b/clearassist/lib/src/database/controller/contact_controller.dart new file mode 100644 index 00000000..07fce2ef --- /dev/null +++ b/clearassist/lib/src/database/controller/contact_controller.dart @@ -0,0 +1,113 @@ +import 'dart:io'; + +import 'package:clearassistapp/src/database/model/contact.dart'; +import 'package:clearassistapp/src/database/repository/contact_repository.dart'; +import 'package:clearassistapp/src/utils/directory_manager.dart'; +import 'package:clearassistapp/src/utils/file_manager.dart'; +import 'package:clearassistapp/src/utils/logger.dart'; +import 'package:flutter_contacts/flutter_contacts.dart'; + +class ContactController { + ContactController._(); + + static Future addSeedContact({ + required Name displayName, + String? nickName, + Email? address, + required Phone number, + required File contactFile, + }) async { + try { + DateTime timestamp = DateTime.now(); + String contactFileExtension = + FileManager().getFileExtensionFromFile(contactFile); + String contactFileName = FileManager().generateFileName( + ContactFields.contactName, + timestamp, + contactFileExtension, + ); + int contactFileSize = FileManager.calculateFileSizeInBytes(contactFile); + ContactModel newContact = ContactModel( + name: Name(first: 'Jarrod', last: 'Brown'), + phoneNum: Phone('3183222237', isPrimary: true), + nickName: 'Caregiver Prime', + eMail: Email('jbrown843@student.umgc.edu'), + ); + ContactModel createdContact = + await ContactRepository.instance.create(newContact); + await FileManager.addFileToFilesystem( + contactFile, + DirectoryManager.instance.contactsDirectory.path, + contactFileName, + ); + return createdContact; + } catch (e) { + appLogger.severe('Contact Controller -- Error adding contact: $e'); + return null; + } + } + + static Future addContact({ + required Name newName, + String? newNickName, + required Phone newNum, + Email? newEmail, + required File contactFile, + }) async { + try { + String contactFileName = FileManager.getFileName(contactFile.path); + int contactFileSize = FileManager.calculateFileSizeInBytes(contactFile); + DateTime timestamp = + DateTime.parse(FileManager.getFileTimestamp(contactFile.path)); + ContactModel newContact = ContactModel( + nickName: newNickName ?? "", + name: newName, + phoneNum: newNum, + eMail: newEmail, + ); + ContactModel createdContact = + await ContactRepository.instance.create(newContact); + return createdContact; + } catch (e) { + appLogger.severe('Contact Controller -- Error adding contact: $e'); + return null; + } + } + + static Future updateContact({ + required int id, + Name? newName, + String? newNickName, + Email? newEmail, + Phone? newNumber, + }) async { + try { + final existingContact = await ContactRepository.instance.read(id); + final updatedContact = existingContact.copy( + potentialName: newName ?? existingContact.name, + potentialNickName: newNickName ?? existingContact.nickName, + potentialMail: newEmail ?? existingContact.eMail, + potentialPhone: newNumber ?? existingContact.phoneNum, + ); + await ContactRepository.instance.update(updatedContact); + return updatedContact; + } catch (e) { + appLogger.severe('Contact Controller -- Error updating contact: $e'); + return null; + } + } + + static Future removeContact(int id) async { + try { + final existingContact = await ContactRepository.instance.read(id); + await ContactRepository.instance.delete(id); + final contactFilePath = + '${DirectoryManager.instance.contactsDirectory.path}/${existingContact.name}'; + await FileManager.removeFileFromFilesystem(contactFilePath); + return existingContact; + } catch (e) { + appLogger.severe('Contact Controller -- Error removing contact: $e'); + return null; + } + } +} diff --git a/clearassist/lib/src/database/controller/photo_controller.dart b/clearassist/lib/src/database/controller/photo_controller.dart new file mode 100644 index 00000000..951e99fe --- /dev/null +++ b/clearassist/lib/src/database/controller/photo_controller.dart @@ -0,0 +1,124 @@ +import 'dart:io'; + +import 'package:clearassistapp/src/address.dart'; +import 'package:clearassistapp/src/database/model/media_type.dart'; +import 'package:clearassistapp/src/database/model/photo.dart'; +import 'package:clearassistapp/src/database/repository/photo_repository.dart'; +import 'package:clearassistapp/src/utils/constants.dart'; +import 'package:clearassistapp/src/utils/directory_manager.dart'; +import 'package:clearassistapp/src/utils/file_manager.dart'; +import 'package:clearassistapp/src/utils/logger.dart'; + +class PhotoController { + PhotoController._(); + + static Future addSeedPhoto({ + String? title, + String? description, + List? tags, + required File photoFile, + }) async { + try { + DateTime timestamp = DateTime.now(); + String physicalAddress = defaultAddress; + String photoFileExtension = + FileManager().getFileExtensionFromFile(photoFile); + String photoFileName = FileManager().generateFileName( + MediaType.photo.name, + timestamp, + photoFileExtension, + ); + int photoFileSize = FileManager.calculateFileSizeInBytes(photoFile); + Photo newPhoto = Photo( + title: title, + description: description, + tags: tags, + timestamp: timestamp, + physicalAddress: physicalAddress, + photoFileName: photoFileName, + storageSize: photoFileSize, + isFavorited: false, + ); + Photo createdPhoto = await PhotoRepository.instance.create(newPhoto); + await FileManager.addFileToFilesystem( + photoFile, + DirectoryManager.instance.photosDirectory.path, + photoFileName, + ); + return createdPhoto; + } catch (e) { + appLogger.severe('Photo Controller -- Error adding photo: $e'); + return null; + } + } + + static Future addPhoto({ + String? title, + String? description, + List? tags, + required File photoFile, + }) async { + try { + String photoFileName = FileManager.getFileName(photoFile.path); + int photoFileSize = FileManager.calculateFileSizeInBytes(photoFile); + DateTime timestamp = + DateTime.parse(FileManager.getFileTimestamp(photoFile.path)); + String physicalAddress = ''; + await Address.whereIAm().then((String address) { + physicalAddress = address; + }); + Photo newPhoto = Photo( + title: title ?? "", + description: description ?? "", + tags: tags ?? [], + timestamp: timestamp, + physicalAddress: physicalAddress, + photoFileName: photoFileName, + storageSize: photoFileSize, + isFavorited: false, + ); + Photo createdPhoto = await PhotoRepository.instance.create(newPhoto); + return createdPhoto; + } catch (e) { + appLogger.severe('Photo Controller -- Error adding photo: $e'); + return null; + } + } + + static Future updatePhoto({ + required int id, + String? title, + String? description, + bool? isFavorited, + List? tags, + }) async { + try { + final existingPhoto = await PhotoRepository.instance.read(id); + final updatedPhoto = existingPhoto.copy( + title: title ?? existingPhoto.title, + description: description ?? existingPhoto.description, + isFavorited: isFavorited ?? existingPhoto.isFavorited, + tags: tags ?? existingPhoto.tags, + ); + await PhotoRepository.instance.update(updatedPhoto); + return updatedPhoto; + } catch (e) { + appLogger.severe('Photo Controller -- Error updating photo: $e'); + return null; + } + } + + static Future removePhoto(int id) async { + try { + final existingPhoto = await PhotoRepository.instance.read(id); + await PhotoRepository.instance.delete(id); + final photoFilePath = + '${DirectoryManager.instance.photosDirectory.path}/${existingPhoto.photoFileName}'; + await FileManager.removeFileFromFilesystem(photoFilePath); + return existingPhoto; + } catch (e) { + appLogger.severe('Photo Controller -- Error removing photo: $e'); + return null; + } + } +} diff --git a/clearassist/lib/src/database/model/audio.dart b/clearassist/lib/src/database/model/audio.dart new file mode 100644 index 00000000..6c9efc32 --- /dev/null +++ b/clearassist/lib/src/database/model/audio.dart @@ -0,0 +1,108 @@ +import 'dart:io'; + +import 'package:clearassistapp/src/database/model/media.dart'; +import 'package:clearassistapp/src/database/model/media_type.dart'; +import 'package:clearassistapp/src/database/repository/audio_repository.dart'; +import 'package:clearassistapp/src/utils/directory_manager.dart'; +import 'package:clearassistapp/src/utils/file_manager.dart'; +import 'package:clearassistapp/src/utils/logger.dart'; + +class Audio extends Media { + final String audioFileName; + final String? transcriptFileName; + final String? summary; + + Audio({ + super.id, + String? title, + super.description, + super.tags, + required super.timestamp, + super.physicalAddress, + required super.storageSize, + required super.isFavorited, + required this.audioFileName, + this.transcriptFileName, + this.summary, + }) : super( + mediaType: MediaType.audio, + title: title ?? audioFileName, + ); + + @override + Audio copy({ + int? id, + String? title, + String? description, + List? tags, + DateTime? timestamp, + String? physicalAddress, + int? storageSize, + bool? isFavorited, + String? audioFileName, + String? transcriptFileName, + String? summary, + }) => + Audio( + id: id ?? this.id, + title: title ?? this.title, + description: description ?? this.description, + tags: tags ?? this.tags, + timestamp: timestamp ?? this.timestamp, + physicalAddress: physicalAddress ?? this.physicalAddress, + storageSize: storageSize ?? this.storageSize, + isFavorited: isFavorited ?? this.isFavorited, + audioFileName: audioFileName ?? this.audioFileName, + transcriptFileName: transcriptFileName ?? this.transcriptFileName, + summary: summary ?? this.summary, + ); + + @override + Map toJson() { + return { + ...super.toJson(), + AudioFields.audioFileName: audioFileName, + AudioFields.transcriptFileName: transcriptFileName, + AudioFields.summary: summary, + }; + } + + static Audio fromJson(Map json) { + try { + return Audio( + id: json[MediaFields.id] as int?, + title: json[MediaFields.title] as String?, + description: json[MediaFields.description] as String?, + tags: (json[MediaFields.tags] as String?)?.split(','), + timestamp: DateTime.fromMillisecondsSinceEpoch( + (json[MediaFields.timestamp] as int), + isUtc: true, + ), + physicalAddress: json[MediaFields.physicalAddress] as String?, + storageSize: json[MediaFields.storageSize] as int, + isFavorited: json[MediaFields.isFavorited] == 1, + audioFileName: json[AudioFields.audioFileName] as String, + transcriptFileName: json[AudioFields.transcriptFileName] as String?, + summary: json[AudioFields.summary] as String?, + ); + } catch (e) { + throw FormatException('Error parsing JSON: $e'); + } + } + + Future loadTranscriptFile() async { + try { + if (transcriptFileName == null) { + appLogger.severe('transcriptFileName is null'); + return null; + } + return FileManager.loadFile( + DirectoryManager.instance.transcriptsDirectory.path, + transcriptFileName!, + ); + } catch (e) { + appLogger.severe('Error loading transcript file: $e'); + return null; + } + } +} diff --git a/clearassist/lib/src/database/model/contact.dart b/clearassist/lib/src/database/model/contact.dart new file mode 100644 index 00000000..a8811c3e --- /dev/null +++ b/clearassist/lib/src/database/model/contact.dart @@ -0,0 +1,69 @@ +import 'package:logging/logging.dart'; +import 'package:flutter_contacts/flutter_contacts.dart'; +import 'dart:io'; + +var logger = Logger("Contact"); + +class ContactModel { + final Name name; + final Phone phoneNum; + final Email? eMail; + final String? nickName; + int? id; + File? contactFile; +// int photo?, +// int List? thumbnail, + // required Name name, + // required Phone phone, +// List notes, + // }) + + ContactModel( + {required this.name, + required this.phoneNum, + this.eMail, + this.nickName, + this.id, + this.contactFile}); + + Map toJson() { + return { + 'name': name, + 'phoneNum': phoneNum, + 'eMail': eMail, + 'nickName': nickName, + 'id': id, + 'file': contactFile + }; + } + + ContactModel copy({ + Name? potentialName, + Phone? potentialPhone, + Email? potentialMail, + String? potentialNickName, + int? potentialID, + }) => + ContactModel( + id: potentialID ?? id, + name: potentialName ?? name, + phoneNum: potentialPhone ?? phoneNum, + eMail: potentialMail ?? eMail, + nickName: potentialNickName ?? nickName, + ); + + static ContactModel fromJson(Map json) { + try { + return ContactModel( + id: json['id'] as int?, + phoneNum: json['phoneNum'] as Phone, + eMail: json['eMail'] as Email?, + nickName: json['nickName'] as String?, + name: json['name'] as Name, + contactFile: json['contact'] as File, + ); + } catch (e) { + throw FormatException('Error parsing JSON: $e'); + } + } +} diff --git a/clearassist/lib/src/database/model/location.dart b/clearassist/lib/src/database/model/location.dart new file mode 100644 index 00000000..0c1c1a79 --- /dev/null +++ b/clearassist/lib/src/database/model/location.dart @@ -0,0 +1,36 @@ +class LocationDataModel { + int? id; + final double? latitude; + final double? longitude; + final String? address; + final DateTime timestamp; + + LocationDataModel({ + this.id, + this.latitude, + this.longitude, + this.address, + required this.timestamp + }); + + Map toMap() { + return { + 'id': id, + 'latitude': latitude, + 'longitude': longitude, + 'address': address, + 'timestamp': timestamp.toIso8601String(), + }; + } + + // Convert a Map into a LocationDataModel + static LocationDataModel fromMap(Map map) { + return LocationDataModel( + id: map['id'], + latitude: map['latitude'], + longitude: map['longitude'], + address: map['address'], + timestamp: DateTime.parse(map['timestamp']), + ); + } +} diff --git a/clearassist/lib/src/database/model/media.dart b/clearassist/lib/src/database/model/media.dart new file mode 100644 index 00000000..f9800058 --- /dev/null +++ b/clearassist/lib/src/database/model/media.dart @@ -0,0 +1,73 @@ +import 'package:clearassistapp/src/database/model/media_type.dart'; + +abstract class MediaFields { + static final List values = [ + id, + title, + description, + tags, + timestamp, + physicalAddress, + storageSize, + isFavorited, + ]; + + static const String id = '_id'; + static const String title = 'title'; + static const String description = 'description'; + static const String tags = 'tags'; + static const String timestamp = 'timestamp'; + static const String physicalAddress = 'physicalAddress'; + static const String storageSize = 'storage_size'; + static const String isFavorited = 'is_favorited'; +} + +abstract class Media { + final int? id; + final MediaType mediaType; + final String title; + final String? description; + final List? tags; + final DateTime timestamp; + final String? physicalAddress; + final int storageSize; + bool isFavorited; + + Media({ + this.id, + required this.mediaType, + required this.title, + this.description, + this.tags, + required this.timestamp, + this.physicalAddress, + required this.storageSize, + required this.isFavorited, + }); + + Media copy({ + int? id, + String title, + String? description, + List? tags, + DateTime? timestamp, + String? physicalAddress, + int? storageSize, + bool? isFavorited, + }); + + Map toJson() => { + MediaFields.id: id, + MediaFields.title: title, + MediaFields.description: description, + MediaFields.tags: tags?.join(','), + MediaFields.timestamp: timestamp.toUtc().millisecondsSinceEpoch, + MediaFields.physicalAddress: physicalAddress, + MediaFields.storageSize: storageSize, + MediaFields.isFavorited: isFavorited ? 1 : 0, + }; + + static Media fromJson(Map json) { + throw UnimplementedError(); + } +} diff --git a/clearassist/lib/src/database/model/media_type.dart b/clearassist/lib/src/database/model/media_type.dart new file mode 100644 index 00000000..123fdec3 --- /dev/null +++ b/clearassist/lib/src/database/model/media_type.dart @@ -0,0 +1,5 @@ +enum MediaType { + audio, + photo, + video, +} diff --git a/clearassist/lib/src/database/model/photo.dart b/clearassist/lib/src/database/model/photo.dart new file mode 100644 index 00000000..2f162058 --- /dev/null +++ b/clearassist/lib/src/database/model/photo.dart @@ -0,0 +1,89 @@ +import 'package:clearassistapp/src/database/model/media.dart'; +import 'package:clearassistapp/src/database/model/media_type.dart'; +import 'package:clearassistapp/src/database/repository/photo_repository.dart'; +import 'package:clearassistapp/src/utils/directory_manager.dart'; +import 'package:clearassistapp/src/utils/file_manager.dart'; +import 'package:flutter/widgets.dart'; + +class Photo extends Media { + final String photoFileName; + + late Image? photo; + + Photo({ + super.id, + String? title, + super.description, + super.tags, + required super.timestamp, + super.physicalAddress, + required super.storageSize, + required super.isFavorited, + required this.photoFileName, + }) : super( + mediaType: MediaType.photo, + title: title ?? photoFileName, + ) { + _loadPhoto(); + } + + @override + Photo copy({ + int? id, + String? title, + String? description, + List? tags, + DateTime? timestamp, + String? physicalAddress, + int? storageSize, + bool? isFavorited, + String? photoFileName, + }) => + Photo( + id: id ?? this.id, + title: title ?? this.title, + description: description ?? this.description, + tags: tags ?? this.tags, + timestamp: timestamp ?? this.timestamp, + physicalAddress: physicalAddress ?? this.physicalAddress, + storageSize: storageSize ?? this.storageSize, + isFavorited: isFavorited ?? this.isFavorited, + photoFileName: photoFileName ?? this.photoFileName, + ); + + @override + Map toJson() { + return { + ...super.toJson(), + PhotoFields.photoFileName: photoFileName, + }; + } + + static Photo fromJson(Map json) { + try { + return Photo( + id: json[MediaFields.id] as int?, + title: json[MediaFields.title] as String?, + description: json[MediaFields.description] as String?, + tags: (json[MediaFields.tags] as String?)?.split(','), + timestamp: DateTime.fromMillisecondsSinceEpoch( + (json[MediaFields.timestamp] as int), + isUtc: true, + ), + physicalAddress: json[MediaFields.physicalAddress] as String, + storageSize: json[MediaFields.storageSize] as int, + isFavorited: json[MediaFields.isFavorited] == 1, + photoFileName: json[PhotoFields.photoFileName] as String, + ); + } catch (e) { + throw FormatException('Error parsing JSON for Photo: $e'); + } + } + + Future _loadPhoto() async { + photo = FileManager.loadImage( + DirectoryManager.instance.photosDirectory.path, + photoFileName, + ); + } +} diff --git a/clearassist/lib/src/database/repository/audio_repository.dart b/clearassist/lib/src/database/repository/audio_repository.dart new file mode 100644 index 00000000..b54e7014 --- /dev/null +++ b/clearassist/lib/src/database/repository/audio_repository.dart @@ -0,0 +1,79 @@ +import 'package:clearassistapp/src/database/app_database.dart'; +import 'package:clearassistapp/src/database/model/audio.dart'; +import 'package:clearassistapp/src/database/model/media.dart'; + +const String tableAudios = 'audios'; +const String transcriptType = 'transcript'; + +class AudioFields extends MediaFields { + static final List values = [ + ...MediaFields.values, + audioFileName, + transcriptFileName, + summary, + ]; + + static const String audioFileName = 'audio_file_name'; + static const String transcriptFileName = 'transcript_file_name'; + static const String summary = 'summary'; +} + +class AudioRepository { + static final AudioRepository instance = AudioRepository._init(); + + AudioRepository._init(); + + Future