[
  {
    "path": ".gitignore",
    "content": "# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.buildlog/\n.history\n.svn/\n\n# IntelliJ related\n*.iml\n*.ipr\n*.iws\n.idea/\n\n# The .vscode folder contains launch configuration and tasks you configure in\n# VS Code which you may wish to be included in version control, so this line\n# is commented out by default.\n#.vscode/\n\n# Flutter/Dart/Pub related\n**/doc/api/\n**/ios/Flutter/.last_build_id\n.dart_tool/\n.flutter-plugins\n.flutter-plugins-dependencies\n.packages\n.pub-cache/\n.pub/\n/build/\n\n# Web related\nlib/generated_plugin_registrant.dart\n\n# Symbolication related\napp.*.symbols\n\n# Obfuscation related\napp.*.map.json\n\n# Exceptions to above rules.\n!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages\n"
  },
  {
    "path": ".metadata",
    "content": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrades etc.\n#\n# This file should be version controlled and should not be manually edited.\n\nversion:\n  revision: bbfbf1770cca2da7c82e887e4e4af910034800b6\n  channel: stable\n\nproject_type: app\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Diganta Kalita\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\"><a href=\"https://github.com/realdiganta/hitup-messenger\"><img src=\"https://user-images.githubusercontent.com/47485188/101604747-5a6a8d00-3a27-11eb-9c00-8124df47589e.png\" alt=\"Logo\" height=\"140\", width=\"140\"/></a></p>\n<h1 align=\"center\">HitUp Messenger</h1>\n<p align=\"center\">A Fully Functioning Chat Messenger (like Whatsapp) built using Flutter.</p>\n\n<p align=\"center\">\n\t<a href=\"https://github.com/realdiganta/hitup-messenger\"><img src=\"https://img.shields.io/badge/apk%20size-18%20MB-blueviolet\"/></a> <a href=\"https://github.com/realdiganta/hitup-messenger\"><img src=\"https://img.shields.io/badge/version-1.2.6%2B7-blue\"/></a> <a href=\"https://github.com/realdiganta/hitup-messenger\"><img src=\"https://img.shields.io/badge/license-MIT-orange\"/></a> \n</p><br/><br/>\n\n\n<img src=\"https://user-images.githubusercontent.com/47485188/101521998-9c0a2200-39ac-11eb-964a-79d51b4f89c1.png\" alt=\"Screenshot\" height=\"500\" width=\"270\"/> <img src=\"https://user-images.githubusercontent.com/47485188/101522157-dd023680-39ac-11eb-8851-be5b351d3186.png\" alt=\"Screenshot\" height=\"500\" width=\"270\"/> <img src=\"https://user-images.githubusercontent.com/47485188/101532693-e98d8b80-39ba-11eb-804f-78ccad3f1f31.png\" alt=\"Screenshot\" height=\"500\" width=\"270\"/> \n\n\n## About the project\n- Flutter for building the Android & IOS App.\n- Firestore database for storing user data.\n- Firebase Storage for storing images.\n- [MQTT](https://www.hivemq.com/mqtt-essentials/) as messaging protocol hosted in AWS EC2.\n- SQLite for storing contacts & chats in Local Database.\n- [OneSignal](https://onesignal.com/) for Push Notifications.\n\n## Features\n\n### Super Fast Messaging using MQTT Protocol (MQTT is used by Facebook Messenger)\n\nArchitecture:\n> When you send a message from the app, the message first goes to the MQTT server. Then the MQTT server sends the message directly to the device of the client who is supposed to receive it. When received, the client stores the message in the local sqlite database first then shows it to the chat screen. (Firestore is in no way used to store or send text messages. Firestore is used only to store user & contacts data). To learn more about MQTT please [refer here](https://www.hivemq.com/mqtt-essentials/).\n<br>\n\n### Phone Number Authentication Sign-in\nAuthentication is done using Firebase.\n<br>\n\n<img src=\"https://user-images.githubusercontent.com/47485188/101533784-476ea300-39bc-11eb-99b7-4fe09cf2c29a.png\" alt=\"Screenshot\" height=\"500\" width=\"270\"/> <img src=\"https://user-images.githubusercontent.com/47485188/101533474-e0e98500-39bb-11eb-8e67-b50827a8a1e0.png\" alt=\"Screenshot\" height=\"500\" width=\"270\"/>\n\n\n### Sending Images\nSend & Receive Images (Snapchat style UI).\nThe images are not stored in Gallery. Instead they are stored in the local sqlite database in bytes format. \n<br><br>\n<img src=\"https://user-images.githubusercontent.com/47485188/101521696-2f8f2300-39ac-11eb-9f42-5afd2ad0e36a.gif\" alt=\"Screenshot\" height=\"500\" width=\"270\"/>\n\n### Super Fast Loading of Messages (Using SQLite as Local DB to store messages)\n\nEven when the client is offline, he/she can view the messages on opening the chat screen, because the messages are loaded directly from the local sqlite db. And that is the only place where the messages are stored. The MQTT server doesn't store old messages. The MQTT Server only stores the last message sent and then replaces it when a new message is sent.\n\n### Sending texts to Phone Contacts\nOn the Contacts Screen, you will get a list of all your phone contacts who are also using the messenger and can chat with them. (Just like sending messages to your contacts in Whatsapp)<br>\n\n<img src=\"https://user-images.githubusercontent.com/47485188/101533031-5dc82f00-39bb-11eb-8f53-035e3f01112d.png\" alt=\"Screenshot\" height=\"500\" width=\"270\"/>\n<br>\n\n### Adding contacts using username. Sending & Receiving Friend Requests\nYou can also send friend request to someone using their username. On sending friend request, the other user will get a push notification & and a friend request. If he/she accepts the request then you will get an notification & will be able to chat with the user. (Same as the feature in Snapchat) <br><br>\n<img src=\"https://user-images.githubusercontent.com/47485188/101530774-5ce1ce00-39b8-11eb-88b5-8d6ae66e049e.png\" alt=\"Screenshot\" height=\"500\" width=\"280\"/>\n\n### Block Contact<br>\n<img src=\"https://user-images.githubusercontent.com/47485188/101531982-ea71ed80-39b9-11eb-8d8f-190be70c7131.png\" alt=\"Screenshot\" height=\"500\" width=\"280\"/>\n\n\n### Realtime Push Notifications \nUsing OneSignal. User will get realtime push notifications (even when the app is closed) when \n- He/She receives a new message\n- He/She receives a friend request\n- Someone accepts their friend request\n<br>\n\n<img src=\"https://user-images.githubusercontent.com/47485188/101627059-cce96600-3a43-11eb-83b1-12ab08d20a35.gif\" alt=\"Notification\" height=\"500\" width=\"270\"/>\n\n<br><br>\n\n### Change Profile Photo\n\n### Image Compression Before Sending\n\n### Emoji Support\n\n### Neumorphic UI\n\n### Invite Friends Feature\n\n\n<br>\n\n## Other Important Information\n\n## Installation & Setup (Optional)\n1. Firebase\n> To change the firestore database, just replace the google-services.json in android/app to your own google-services.json file from your firebase account.\n2. MQTT Server\n> To transfer messages I am using an MQTT server which I have setup in a EC2 instance on AWS. For details on how to setup your own MQTT server please refer here : [Setup MQTT Server on AWS EC2](http://blog.yatis.io/install-secure-robust-mosquitto-mqtt-broker-aws-ubuntu/). Then change the serverAddress parameter in lib/functions/MQTTFunction.dart file, (connect() function) to the public address of your EC2 instance.\n <br>\n\n3. OneSignal\n> First create an account in [OneSignal](https://onesignal.com/). Then replace the app_id parameter in lib/functions/UserDataFunction.dart sendNotification() function with your own OneSignal app_id.\n\n## Motivation & Contribution\nI want to build this messenger into the biggest open source messenger on the web with all functionalities from the top Messengers like Whatsapp, Telegram, Signal, Snapchat, etc. There a lot of features still to be added like end-to-end encryption, audio messages, audio/video calling, stories, etc. So, we are open to pull requests. Please contribute in any way you can, adding new features, finding or fixing bugs, adding to the documenation, better code commenting, etc. \n\n## Contributing\nIf you want to contribute to this project other than by coding, please contact me here digantakalita.ai@gmail.com\n\n## License\n[MIT License](https://github.com/realdiganta/hitup-messenger/blob/master/LICENSE)\n\n## Supporters\n[![Stargazers repo roster for @realdiganta/hitup-messenger](https://reporoster.com/stars/realdiganta/hitup-messenger)](https://github.com/realdiganta/hitup-messenger/stargazers)\n[![Forkers repo roster for @realdiganta/hitup-messenger](https://reporoster.com/forks/realdiganta/hitup-messenger)](https://github.com/realdiganta/hitup-messenger/network/members)\n"
  },
  {
    "path": "android/.gitignore",
    "content": "gradle-wrapper.jar\n/.gradle\n/captures/\n/gradlew\n/gradlew.bat\n/local.properties\nGeneratedPluginRegistrant.java\n\n# Remember to never publicly share your keystore.\n# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app\nkey.properties\n"
  },
  {
    "path": "android/app/build.gradle",
    "content": "buildscript {\n    repositories {\n        // ...\n        maven { url 'https://plugins.gradle.org/m2/' } // Gradle Plugin Portal\n    }\n    dependencies {\n        // OneSignal-Gradle-Plugin\n        classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.6, 0.99.99]'\n    }\n}\napply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin'\n\ndef localProperties = new Properties()\ndef localPropertiesFile = rootProject.file('local.properties')\nif (localPropertiesFile.exists()) {\n    localPropertiesFile.withReader('UTF-8') { reader ->\n        localProperties.load(reader)\n    }\n}\n\ndef flutterRoot = localProperties.getProperty('flutter.sdk')\nif (flutterRoot == null) {\n    throw new GradleException(\"Flutter SDK not found. Define location with flutter.sdk in the local.properties file.\")\n}\n\ndef flutterVersionCode = localProperties.getProperty('flutter.versionCode')\nif (flutterVersionCode == null) {\n    flutterVersionCode = '1'\n}\n\ndef flutterVersionName = localProperties.getProperty('flutter.versionName')\nif (flutterVersionName == null) {\n    flutterVersionName = '1.0'\n}\n\napply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply from: \"$flutterRoot/packages/flutter_tools/gradle/flutter.gradle\"\napply plugin: 'com.google.gms.google-services'\n\ndef keystoreProperties = new Properties()\ndef keystorePropertiesFile = rootProject.file('key.properties')\nif (keystorePropertiesFile.exists()) {\n    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))\n}\n\nandroid {\n    compileSdkVersion 28\n\n    sourceSets {\n        main.java.srcDirs += 'src/main/kotlin'\n    }\n\n    lintOptions {\n        disable 'InvalidPackage'\n    }\n\n    defaultConfig {\n        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).\n        applicationId \"com.digantakalita.coocoo\"\n        minSdkVersion 21\n        targetSdkVersion 29\n        versionCode flutterVersionCode.toInteger()\n        versionName flutterVersionName\n    }\n\n\n    buildTypes {\n        release {\n            // TODO: Add your own signing config for the release build.\n            // Signing with the debug keys for now, so `flutter run --release` works.\n        }\n    }\n}\n\nflutter {\n    source '../..'\n}\n\ndependencies {\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n    implementation 'com.google.firebase:firebase-analytics:17.2.2'\n}\n"
  },
  {
    "path": "android/app/google-services.json",
    "content": "{\n  \"project_info\": {\n    \"project_number\": \"754179280048\",\n    \"firebase_url\": \"https://coocoo-private-fc1e0.firebaseio.com\",\n    \"project_id\": \"coocoo-private-fc1e0\",\n    \"storage_bucket\": \"coocoo-private-fc1e0.appspot.com\"\n  },\n  \"client\": [\n    {\n      \"client_info\": {\n        \"mobilesdk_app_id\": \"1:754179280048:android:05aeea871ac3c2980aff75\",\n        \"android_client_info\": {\n          \"package_name\": \"com.digantakalita.coocoo\"\n        }\n      },\n      \"oauth_client\": [\n        {\n          \"client_id\": \"754179280048-it11k86jo0o6paa7j49h5822chkn3bfb.apps.googleusercontent.com\",\n          \"client_type\": 3\n        }\n      ],\n      \"api_key\": [\n        {\n          \"current_key\": \"AIzaSyCBIAEZd1QRl6aclVIvJ1Hwp53HRGz_cL0\"\n        }\n      ],\n      \"services\": {\n        \"appinvite_service\": {\n          \"other_platform_oauth_client\": [\n            {\n              \"client_id\": \"754179280048-it11k86jo0o6paa7j49h5822chkn3bfb.apps.googleusercontent.com\",\n              \"client_type\": 3\n            }\n          ]\n        }\n      }\n    },\n    {\n      \"client_info\": {\n        \"mobilesdk_app_id\": \"1:754179280048:android:9879c8ab91f94f440aff75\",\n        \"android_client_info\": {\n          \"package_name\": \"com.digantakalita.coocooprivate\"\n        }\n      },\n      \"oauth_client\": [\n        {\n          \"client_id\": \"754179280048-7b457bisjiacvm9q5jtfc6v7qveldthc.apps.googleusercontent.com\",\n          \"client_type\": 1,\n          \"android_info\": {\n            \"package_name\": \"com.digantakalita.coocooprivate\",\n            \"certificate_hash\": \"95d0565459f5ab2a868748443dbeddb9f31ab585\"\n          }\n        },\n        {\n          \"client_id\": \"754179280048-it11k86jo0o6paa7j49h5822chkn3bfb.apps.googleusercontent.com\",\n          \"client_type\": 3\n        }\n      ],\n      \"api_key\": [\n        {\n          \"current_key\": \"AIzaSyCBIAEZd1QRl6aclVIvJ1Hwp53HRGz_cL0\"\n        }\n      ],\n      \"services\": {\n        \"appinvite_service\": {\n          \"other_platform_oauth_client\": [\n            {\n              \"client_id\": \"754179280048-it11k86jo0o6paa7j49h5822chkn3bfb.apps.googleusercontent.com\",\n              \"client_type\": 3\n            }\n          ]\n        }\n      }\n    }\n  ],\n  \"configuration_version\": \"1\"\n}"
  },
  {
    "path": "android/app/src/debug/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.digantakalita.coocoo\">\n    <!-- Flutter needs it to communicate with the running application\n         to allow setting breakpoints, to provide hot reload, etc.\n    -->\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n</manifest>\n"
  },
  {
    "path": "android/app/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.digantakalita.coocoo\">\n    <!-- io.flutter.app.FlutterApplication is an android.app.Application that\n         calls FlutterMain.startInitialization(this); in its onCreate method.\n         In most cases you can leave this as-is, but you if you want to provide\n         additional functionality it is fine to subclass or reimplement\n         FlutterApplication and put your custom class here. -->\n    <uses-permission android:name=\"android.permission.READ_CONTACTS\" />\n    <uses-permission android:name=\"android.permission.WRITE_CONTACTS\" />\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n    <application\n        android:name=\"io.flutter.app.FlutterApplication\"\n        android:label=\"HitUp\"\n        android:icon=\"@mipmap/ic_launcher\">\n        <activity\n            android:name=\".MainActivity\"\n            android:launchMode=\"singleTop\"\n            android:theme=\"@style/LaunchTheme\"\n            android:configChanges=\"orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode\"\n            android:hardwareAccelerated=\"true\"\n            android:windowSoftInputMode=\"adjustResize\">\n            <!-- Specifies an Android theme to apply to this Activity as soon as\n                 the Android process has started. This theme is visible to the user\n                 while the Flutter UI initializes. After that, this theme continues\n                 to determine the Window background behind the Flutter UI. -->\n            <meta-data\n              android:name=\"io.flutter.embedding.android.NormalTheme\"\n              android:resource=\"@style/NormalTheme\"\n              />\n            <!-- Displays an Android View that continues showing the launch screen\n                 Drawable until Flutter paints its first frame, then this splash\n                 screen fades out. A splash screen is useful to avoid any visual\n                 gap between the end of Android's launch screen and the painting of\n                 Flutter's first frame. -->\n            <meta-data\n              android:name=\"io.flutter.embedding.android.SplashScreenDrawable\"\n              android:resource=\"@drawable/launch_background\"\n              />\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n        <!-- Don't delete the meta-data below.\n             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->\n        <meta-data\n            android:name=\"flutterEmbedding\"\n            android:value=\"2\" />\n    </application>\n</manifest>\n"
  },
  {
    "path": "android/app/src/main/kotlin/com/digantakalita/coocoo/MainActivity.kt",
    "content": "package com.digantakalita.coocoo\n\nimport io.flutter.embedding.android.FlutterActivity\n\nclass MainActivity: FlutterActivity() {\n}\n"
  },
  {
    "path": "android/app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector\n    android:height=\"108dp\"\n    android:width=\"108dp\"\n    android:viewportHeight=\"108\"\n    android:viewportWidth=\"108\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"#3DDC84\"\n          android:pathData=\"M0,0h108v108h-108z\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M9,0L9,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,0L19,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M29,0L29,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M39,0L39,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M49,0L49,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M59,0L59,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M69,0L69,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M79,0L79,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M89,0L89,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M99,0L99,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,9L108,9\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,19L108,19\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,29L108,29\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,39L108,39\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,49L108,49\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,59L108,59\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,69L108,69\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,79L108,79\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,89L108,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,99L108,99\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,29L89,29\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,39L89,39\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,49L89,49\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,59L89,59\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,69L89,69\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,79L89,79\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M29,19L29,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M39,19L39,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M49,19L49,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M59,19L59,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M69,19L69,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M79,19L79,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n</vector>\n"
  },
  {
    "path": "android/app/src/main/res/drawable/launch_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@android:color/white\" />\n\n    <!-- You can insert your own image assets here -->\n    <!-- <item>\n        <bitmap\n            android:gravity=\"center\"\n            android:src=\"@mipmap/launch_image\" />\n    </item> -->\n</layer-list>\n"
  },
  {
    "path": "android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\"/>\n    <foreground android:drawable=\"@mipmap/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\"/>\n    <foreground android:drawable=\"@mipmap/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "android/app/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is starting -->\n    <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Black.NoTitleBar\">\n        <!-- Show a splash screen on the activity. Automatically removed when\n             Flutter draws its first frame -->\n        <item name=\"android:windowBackground\">@drawable/launch_background</item>\n    </style>\n    <!-- Theme applied to the Android Window as soon as the process has started.\n         This theme determines the color of the Android Window while your\n         Flutter UI initializes, as well as behind your Flutter UI while its\n         running.\n         \n         This Theme is only used starting with V2 of Flutter's Android embedding. -->\n    <style name=\"NormalTheme\" parent=\"@android:style/Theme.Black.NoTitleBar\">\n        <item name=\"android:windowBackground\">@android:color/white</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "android/app/src/profile/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.digantakalita.coocoo\">\n    <!-- Flutter needs it to communicate with the running application\n         to allow setting breakpoints, to provide hot reload, etc.\n    -->\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n</manifest>\n"
  },
  {
    "path": "android/build.gradle",
    "content": "buildscript {\n    ext.kotlin_version = '1.3.50'\n    repositories {\n        google()\n        jcenter()\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.5.0'\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n        classpath 'com.google.gms:google-services:4.3.3'\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n    }\n}\n\nrootProject.buildDir = '../build'\nsubprojects {\n    project.buildDir = \"${rootProject.buildDir}/${project.name}\"\n}\nsubprojects {\n    project.evaluationDependsOn(':app')\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "android/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Fri Jun 23 08:50:38 CEST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-5.6.2-all.zip\n"
  },
  {
    "path": "android/gradle.properties",
    "content": "org.gradle.jvmargs=-Xmx1536M\nandroid.enableR8=true\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n"
  },
  {
    "path": "android/settings.gradle",
    "content": "include ':app'\n\ndef localPropertiesFile = new File(rootProject.projectDir, \"local.properties\")\ndef properties = new Properties()\n\nassert localPropertiesFile.exists()\nlocalPropertiesFile.withReader(\"UTF-8\") { reader -> properties.load(reader) }\n\ndef flutterSdkPath = properties.getProperty(\"flutter.sdk\")\nassert flutterSdkPath != null, \"flutter.sdk not set in local.properties\"\napply from: \"$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle\"\n"
  },
  {
    "path": "ios/.gitignore",
    "content": "*.mode1v3\n*.mode2v3\n*.moved-aside\n*.pbxuser\n*.perspectivev3\n**/*sync/\n.sconsign.dblite\n.tags*\n**/.vagrant/\n**/DerivedData/\nIcon?\n**/Pods/\n**/.symlinks/\nprofile\nxcuserdata\n**/.generated/\nFlutter/App.framework\nFlutter/Flutter.framework\nFlutter/Flutter.podspec\nFlutter/Generated.xcconfig\nFlutter/app.flx\nFlutter/app.zip\nFlutter/flutter_assets/\nFlutter/flutter_export_environment.sh\nServiceDefinitions.json\nRunner/GeneratedPluginRegistrant.*\n\n# Exceptions to above rules.\n!default.mode1v3\n!default.mode2v3\n!default.pbxuser\n!default.perspectivev3\n"
  },
  {
    "path": "ios/Flutter/AppFrameworkInfo.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n  <key>CFBundleDevelopmentRegion</key>\n  <string>$(DEVELOPMENT_LANGUAGE)</string>\n  <key>CFBundleExecutable</key>\n  <string>App</string>\n  <key>CFBundleIdentifier</key>\n  <string>io.flutter.flutter.app</string>\n  <key>CFBundleInfoDictionaryVersion</key>\n  <string>6.0</string>\n  <key>CFBundleName</key>\n  <string>App</string>\n  <key>CFBundlePackageType</key>\n  <string>FMWK</string>\n  <key>CFBundleShortVersionString</key>\n  <string>1.0</string>\n  <key>CFBundleSignature</key>\n  <string>????</string>\n  <key>CFBundleVersion</key>\n  <string>1.0</string>\n  <key>MinimumOSVersion</key>\n  <string>8.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Flutter/Debug.xcconfig",
    "content": "#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "ios/Flutter/Release.xcconfig",
    "content": "#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "ios/Runner/AppDelegate.swift",
    "content": "import UIKit\nimport Flutter\n\n@UIApplicationMain\n@objc class AppDelegate: FlutterAppDelegate {\n  override func application(\n    _ application: UIApplication,\n    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n  ) -> Bool {\n    GeneratedPluginRegistrant.register(with: self)\n    return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n  }\n}\n"
  },
  {
    "path": "ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-40x40@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-40x40@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-60x60@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-60x60@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-20x20@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-29x29@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-29x29@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-40x40@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-40x40@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-76x76@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-76x76@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"83.5x83.5\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-83.5x83.5@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"1024x1024\",\n      \"idiom\" : \"ios-marketing\",\n      \"filename\" : \"Icon-App-1024x1024@1x.png\",\n      \"scale\" : \"1x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}\n"
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}\n"
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md",
    "content": "# Launch Screen Assets\n\nYou can customize the launch screen with your own desired assets by replacing the image files in this directory.\n\nYou 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."
  },
  {
    "path": "ios/Runner/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"12121\" systemVersion=\"16G29\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" colorMatched=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"12089\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Ydg-fD-yQy\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xbc-2k-c8Z\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <imageView opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" image=\"LaunchImage\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YRO-k0-Ey4\">\n                            </imageView>\n                        </subviews>\n                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"centerX\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"centerX\" id=\"1a2-6s-vTC\"/>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"centerY\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"centerY\" id=\"4X2-HB-R7a\"/>\n                        </constraints>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <image name=\"LaunchImage\" width=\"168\" height=\"185\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "ios/Runner/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"10117\" systemVersion=\"15F34\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" initialViewController=\"BYZ-38-t0r\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"10085\"/>\n    </dependencies>\n    <scenes>\n        <!--Flutter View Controller-->\n        <scene sceneID=\"tne-QT-ifu\">\n            <objects>\n                <viewController id=\"BYZ-38-t0r\" customClass=\"FlutterViewController\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"y3c-jy-aDJ\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"wfy-db-euE\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "ios/Runner/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>coocoo</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(FLUTTER_BUILD_NAME)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(FLUTTER_BUILD_NUMBER)</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UIViewControllerBasedStatusBarAppearance</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner/Runner-Bridging-Header.h",
    "content": "#import \"GeneratedPluginRegistrant.h\"\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };\n\t\t3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };\n\t\t74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };\n\t\t97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };\n\t\t97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };\n\t\t97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t9705A1C41CF9048500538489 /* Embed Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tname = \"Embed Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = \"<group>\"; };\n\t\t1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = \"<group>\"; };\n\t\t3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = \"<group>\"; };\n\t\t74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"Runner-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\t74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = \"<group>\"; };\n\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = \"<group>\"; };\n\t\t9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = \"<group>\"; };\n\t\t97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t97C146EB1CF9000F007C117D /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t9740EEB11CF90186004384FC /* Flutter */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,\n\t\t\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */,\n\t\t\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */,\n\t\t\t\t9740EEB31CF90195004384FC /* Generated.xcconfig */,\n\t\t\t);\n\t\t\tname = Flutter;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146E51CF9000F007C117D = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9740EEB11CF90186004384FC /* Flutter */,\n\t\t\t\t97C146F01CF9000F007C117D /* Runner */,\n\t\t\t\t97C146EF1CF9000F007C117D /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146EF1CF9000F007C117D /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146EE1CF9000F007C117D /* Runner.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146F01CF9000F007C117D /* Runner */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146FA1CF9000F007C117D /* Main.storyboard */,\n\t\t\t\t97C146FD1CF9000F007C117D /* Assets.xcassets */,\n\t\t\t\t97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,\n\t\t\t\t97C147021CF9000F007C117D /* Info.plist */,\n\t\t\t\t1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,\n\t\t\t\t1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,\n\t\t\t\t74858FAE1ED2DC5600515810 /* AppDelegate.swift */,\n\t\t\t\t74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,\n\t\t\t);\n\t\t\tpath = Runner;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t97C146ED1CF9000F007C117D /* Runner */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget \"Runner\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t9740EEB61CF901F6004384FC /* Run Script */,\n\t\t\t\t97C146EA1CF9000F007C117D /* Sources */,\n\t\t\t\t97C146EB1CF9000F007C117D /* Frameworks */,\n\t\t\t\t97C146EC1CF9000F007C117D /* Resources */,\n\t\t\t\t9705A1C41CF9048500538489 /* Embed Frameworks */,\n\t\t\t\t3B06AD1E1E4923F5004D2608 /* Thin Binary */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = Runner;\n\t\t\tproductName = Runner;\n\t\t\tproductReference = 97C146EE1CF9000F007C117D /* Runner.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t97C146E61CF9000F007C117D /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 1020;\n\t\t\t\tORGANIZATIONNAME = \"\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t97C146ED1CF9000F007C117D = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3.1;\n\t\t\t\t\t\tLastSwiftMigration = 1100;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject \"Runner\" */;\n\t\t\tcompatibilityVersion = \"Xcode 9.3\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 97C146E51CF9000F007C117D;\n\t\t\tproductRefGroup = 97C146EF1CF9000F007C117D /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t97C146ED1CF9000F007C117D /* Runner */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t97C146EC1CF9000F007C117D /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,\n\t\t\t\t97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,\n\t\t\t\t97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Thin Binary\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"/bin/sh \\\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\\\" embed_and_thin\";\n\t\t};\n\t\t9740EEB61CF901F6004384FC /* Run Script */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Run Script\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"/bin/sh \\\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\\\" build\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t97C146EA1CF9000F007C117D /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,\n\t\t\t\t1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\t97C146FA1CF9000F007C117D /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146FB1CF9000F007C117D /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t97C147001CF9000F007C117D /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t249021D3217E4FDB00AE95B9 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSUPPORTED_PLATFORMS = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t249021D4217E4FDB00AE95B9 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.digantakalita.coocoo;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t97C147031CF9000F007C117D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t97C147041CF9000F007C117D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSUPPORTED_PLATFORMS = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Owholemodule\";\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t97C147061CF9000F007C117D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.digantakalita.coocoo;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t97C147071CF9000F007C117D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.digantakalita.coocoo;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t97C146E91CF9000F007C117D /* Build configuration list for PBXProject \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t97C147031CF9000F007C117D /* Debug */,\n\t\t\t\t97C147041CF9000F007C117D /* Release */,\n\t\t\t\t249021D3217E4FDB00AE95B9 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t97C147061CF9000F007C117D /* Debug */,\n\t\t\t\t97C147071CF9000F007C117D /* Release */,\n\t\t\t\t249021D4217E4FDB00AE95B9 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 97C146E61CF9000F007C117D /* Project object */;\n}\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>PreviewsEnabled</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1020\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n               BuildableName = \"Runner.app\"\n               BlueprintName = \"Runner\"\n               ReferencedContainer = \"container:Runner.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Profile\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "ios/Runner.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>PreviewsEnabled</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "lib/blocs/AddFriends/add_friends_bloc.dart",
    "content": "import 'dart:async';\nimport 'dart:convert';\n\nimport 'package:bloc/bloc.dart';\nimport 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/config/Paths.dart';\nimport 'package:coocoo/functions/AddFriendsFunction.dart';\nimport 'package:coocoo/functions/BaseFunctions.dart';\nimport 'package:coocoo/functions/ChatFunction.dart';\nimport 'package:coocoo/functions/UserDataFunction.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:coocoo/widgets/GradientSnackBar.dart';\nimport 'package:equatable/equatable.dart';\nimport 'package:flutter/material.dart';\n\npart 'add_friends_event.dart';\npart 'add_friends_state.dart';\n\nclass AddFriendsBloc extends Bloc<AddFriendsEvent, AddFriendsState> {\n  AddFriendsBloc() : super(AddFriendsInitial());\n\n  Firestore _firestore = Firestore.instance;\n  AddFriendsFunction addFriendsFunction = AddFriendsFunction();\n  ChatFunction chatFunction = ChatFunction();\n  UserDataFunction userDataFunction = UserDataFunction();\n  String myName = SharedObjects.prefs.getString(Constants.fullName);\n\n  @override\n  Stream<AddFriendsState> mapEventToState(\n    AddFriendsEvent event,\n  ) async* {\n    if (event is SearchHitUpIdEvent) {\n      yield* mapSearchHitUpIdEventToState(event);\n    }\n    if (event is AddButtonClickEvent) {\n      yield* mapAddButtonClickEventToState(event);\n    }\n    if (event is AcceptFriendRequestEvent) {\n      yield* mapAcceptFriendRequestEventToState(event);\n    }\n    if (event is DeclineFriendRequestEvent) {\n      yield* mapDeclineFriendRequestEventToState(event);\n    }\n  }\n\n  Stream<AddFriendsState> mapDeclineFriendRequestEventToState(\n      DeclineFriendRequestEvent event) async* {\n    yield DecliningFriendRequestState();\n    await addFriendsFunction\n        .removeFromFriendRequestsCollection(event.phoneNumber);\n    addFriendsFunction.removeFromSentRequestsCollection(event.phoneNumber);\n    yield FriendRequestDeclinedState();\n  }\n\n  Stream<AddFriendsState> mapAcceptFriendRequestEventToState(\n      AcceptFriendRequestEvent event) async* {\n    yield AcceptingFriendRequestState();\n    String chatId = await addFriendsFunction.addToLocalDBAndSubscribe(\n        event.context, event.phoneNumber);\n    chatFunction.sendMessageToServer(\n        event.context, 'Hi, I have accepted your friend request', chatId);\n\n    await addFriendsFunction\n        .removeFromFriendRequestsCollection(event.phoneNumber);\n    yield FriendRequestAcceptedState();\n    userDataFunction.sendNotification(toUid:event.phoneNumber, title: \"New Notification\", content: \"$myName has accepted your friend request\");\n    GradientSnackBar.showMessage(event.context, \"Friend Request Accepted\", 1);\n    addFriendsFunction.removeFromSentRequestsCollection(event.phoneNumber);\n  }\n\n  Stream<AddFriendsState> mapAddButtonClickEventToState(\n      AddButtonClickEvent event) async* {\n    yield SendingFriendRequestState();\n    await addFriendsFunction.addToLocalDBAndSubscribe(\n        event.context, event.friend.phoneNumber);\n    await addFriendsFunction\n        .addToSentRequestsCollection(event.friend.phoneNumber);\n    yield FriendRequestSentState(event.friend);\n    userDataFunction.sendNotification(toUid:event.friend.phoneNumber, title: \"New Notification\", content: \"$myName has sent you a friend request\");\n    addFriendsFunction.addToFriendRequestsCollection(event.friend.phoneNumber);\n  }\n\n  Stream<AddFriendsState> mapSearchHitUpIdEventToState(\n      SearchHitUpIdEvent event) async* {\n    yield SearchingHitUpIdState();\n\n    final HitUpIdLocation hitUpIdLocation =\n        await addFriendsFunction.checkHitUpId(event.hitUpId);\n\n    // if hitUpId does not exists in local db, friend requests & sent requests\n    if (hitUpIdLocation == HitUpIdLocation.Nowhere) {\n      QuerySnapshot snapshot = await _firestore\n          .collection(Paths.usersPath)\n          .where(\"username\", isEqualTo: event.hitUpId)\n          .limit(1)\n          .getDocuments();\n\n      if (snapshot.documents.length > 0) {\n        DocumentSnapshot doc = snapshot.documents[0];\n        yield HitUpIdExistsState(MyContact.fromFireStore(doc));\n      } else {\n        yield HitUpIdNotExistsState(event.hitUpId);\n      }\n    } else {\n      yield HitUpIdAlreadyThere(event.hitUpId, hitUpIdLocation);\n    }\n  }\n}\n"
  },
  {
    "path": "lib/blocs/AddFriends/add_friends_event.dart",
    "content": "part of 'add_friends_bloc.dart';\n\nabstract class AddFriendsEvent extends Equatable {\n  const AddFriendsEvent();\n}\n\nclass SearchHitUpIdEvent extends AddFriendsEvent {\n  final String hitUpId;\n\n  SearchHitUpIdEvent(this.hitUpId);\n\n  @override\n  List<Object> get props => [hitUpId];\n}\n\nclass AddButtonClickEvent extends AddFriendsEvent {\n  final MyContact friend;\n  final BuildContext context;\n\n  AddButtonClickEvent(this.context, this.friend);\n\n  @override\n  List<Object> get props => [context, friend];\n}\n\nclass AcceptFriendRequestEvent extends AddFriendsEvent {\n  final String phoneNumber;\n  final BuildContext context;\n\n  AcceptFriendRequestEvent(this.phoneNumber, this.context);\n\n  @override\n  List<Object> get props => [phoneNumber, context];\n}\n\nclass DeclineFriendRequestEvent extends AddFriendsEvent{\n  final String phoneNumber;\n  DeclineFriendRequestEvent(this.phoneNumber);\n\n  @override\n  List<Object> get props => [phoneNumber];\n}\n"
  },
  {
    "path": "lib/blocs/AddFriends/add_friends_state.dart",
    "content": "part of 'add_friends_bloc.dart';\n\nabstract class AddFriendsState extends Equatable {\n  const AddFriendsState();\n}\n\nclass AddFriendsInitial extends AddFriendsState {\n  @override\n  List<Object> get props => [];\n}\n\nclass SearchingHitUpIdState extends AddFriendsState {\n  @override\n  List<Object> get props => [];\n}\n\nclass HitUpIdExistsState extends AddFriendsState {\n  final MyContact friend;\n\n  HitUpIdExistsState(this.friend);\n\n  @override\n  List<Object> get props => [friend];\n}\n\nclass HitUpIdNotExistsState extends AddFriendsState {\n  final String hitupId;\n\n  HitUpIdNotExistsState(this.hitupId);\n  @override\n  List<Object> get props => [hitupId];\n}\n\nclass HitUpIdAlreadyThere extends AddFriendsState {\n  final String hitUpId;\n  final HitUpIdLocation hitUpIdLocation;\n\n  HitUpIdAlreadyThere(this.hitUpId, this.hitUpIdLocation);\n\n  @override\n  List<Object> get props => [hitUpId, hitUpIdLocation];\n}\n\nclass SendingFriendRequestState extends AddFriendsState {\n  @override\n  List<Object> get props => [];\n}\n\nclass FriendRequestSentState extends AddFriendsState {\n  final MyContact friend;\n\n  FriendRequestSentState(this.friend);\n\n  @override\n  List<Object> get props => [friend];\n}\n\nclass AcceptingFriendRequestState extends AddFriendsState {\n  @override\n  List<Object> get props => [];\n}\n\nclass FriendRequestAcceptedState extends AddFriendsState {\n  @override\n  List<Object> get props => [];\n}\n\nclass DecliningFriendRequestState extends AddFriendsState{\n  @override\n  List<Object> get props => [];\n}\n\nclass FriendRequestDeclinedState extends AddFriendsState{\n  @override\n  List<Object> get props => [];\n}\n"
  },
  {
    "path": "lib/blocs/chats/chat_bloc.dart",
    "content": "import 'dart:async';\nimport 'dart:io';\n\nimport 'package:bloc/bloc.dart';\nimport 'package:coocoo/functions/ChatFunction.dart';\nimport 'package:coocoo/managers/db_manager.dart';\nimport 'package:coocoo/models/ChatMessage.dart';\nimport 'package:equatable/equatable.dart';\nimport 'package:flutter/material.dart';\n\npart 'chat_event.dart';\npart 'chat_state.dart';\n\nclass ChatBloc extends Bloc<ChatEvent, ChatState> {\n  ChatBloc() : super(ChatInitial());\n\n  ChatFunction chatFunction = ChatFunction();\n\n  @override\n  Stream<ChatState> mapEventToState(\n    ChatEvent event,\n  ) async* {\n    if (event is SendMessageEvent) {\n      chatFunction.sendMessageToServer(event.context, event.msg, event.chatId);\n    }\n    if (event is SendImageEvent) {\n      chatFunction.sendImageToServer(\n          event.context, event.imageFile, event.chatId);\n    }\n    if (event is ReceivedMessageEvent) {\n      List<ChatMessage> allMessages =\n          await chatFunction.getAllMsgsFromMessagesTable(event.chatId);\n      yield (ReceivedMessageState(allMessages));\n    }\n    if (event is LoadInitialMessagesEvent) {\n      List<ChatMessage> lastChatMsgs =\n          await chatFunction.getAllMsgsFromMessagesTable(event.chatId);\n      yield (InitialMessagesLoadedState(lastChatMsgs));\n    }\n    if (event is BlockUserEvent) {\n      chatFunction.blockUser(event.context, event.chatId);\n      yield (BlockedUserState());\n      DBManager.db.isBlocked(event.chatId);\n    }\n    if (event is UnblockUserEvent) {\n      chatFunction.unBlockUser(event.context, event.chatId);\n      yield (UnblockedUserState());\n    }\n  }\n}\n"
  },
  {
    "path": "lib/blocs/chats/chat_event.dart",
    "content": "part of 'chat_bloc.dart';\n\nabstract class ChatEvent extends Equatable {\n  const ChatEvent();\n}\n\nclass SendMessageEvent extends ChatEvent {\n  final BuildContext context;\n  final String msg;\n  final String chatId;\n\n  SendMessageEvent(this.context, this.msg, this.chatId);\n\n  @override\n  List<Object> get props => [msg, chatId];\n}\n\nclass SendImageEvent extends ChatEvent {\n  final BuildContext context;\n  final File imageFile;\n  final String chatId;\n\n  SendImageEvent(this.context, this.imageFile, this.chatId);\n\n  @override\n  List<Object> get props => [imageFile, chatId];\n}\n\nclass ReceivedMessageEvent extends ChatEvent {\n  final String chatId;\n\n  ReceivedMessageEvent(this.chatId);\n\n  @override\n  List<Object> get props => [chatId];\n}\n\nclass LoadInitialMessagesEvent extends ChatEvent {\n  final String chatId;\n\n  LoadInitialMessagesEvent(this.chatId);\n\n  @override\n  List<Object> get props => [chatId];\n}\n\nclass BlockUserEvent extends ChatEvent{\n  final BuildContext context;\n  final String chatId;\n  BlockUserEvent(this.context, this.chatId);\n\n  @override\n  List<Object> get props => [context, chatId];\n}\n\nclass UnblockUserEvent extends ChatEvent{\n  final BuildContext context;\n  final String chatId;\n  UnblockUserEvent(this.context, this.chatId);\n\n  @override\n  List<Object> get props => [context, chatId];\n}\n"
  },
  {
    "path": "lib/blocs/chats/chat_state.dart",
    "content": "part of 'chat_bloc.dart';\n\nabstract class ChatState extends Equatable {\n  final List<ChatMessage> chatMessages;\n\n  const ChatState(this.chatMessages);\n}\n\nclass ChatInitial extends ChatState {\n  ChatInitial() : super([]);\n  @override\n  List<Object> get props => [];\n}\n\nclass ReceivedMessageState extends ChatState {\n  final List<ChatMessage> chatMessages;\n\n  ReceivedMessageState(this.chatMessages) : super(chatMessages);\n\n  @override\n  List<Object> get props => [chatMessages];\n}\n\nclass InitialMessagesLoadedState extends ChatState {\n  final List<ChatMessage> chatMessages;\n\n  InitialMessagesLoadedState(this.chatMessages) : super(chatMessages);\n\n  @override\n  List<Object> get props => [chatMessages];\n}\n\nclass BlockedUserState extends ChatState {\n  BlockedUserState() : super([]);\n  @override\n  List<Object> get props => [];\n}\n\nclass UnblockedUserState extends ChatState {\n  UnblockedUserState() : super([]);\n\n  @override\n  List<Object> get props => [];\n}\n"
  },
  {
    "path": "lib/blocs/contacts/contacts_bloc.dart",
    "content": "import 'dart:async';\n\nimport 'package:bloc/bloc.dart';\nimport 'package:coocoo/functions/UserDataFunction.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:equatable/equatable.dart';\n\npart 'contacts_event.dart';\npart 'contacts_state.dart';\n\nclass ContactsBloc extends Bloc<ContactsEvent, ContactsState> {\n  ContactsBloc() : super(InitialContactsState());\n\n  UserDataFunction userDataFunction = UserDataFunction();\n\n  @override\n  Stream<ContactsState> mapEventToState(\n    ContactsEvent event,\n  ) async* {\n    if (event is FetchContactsEvent) {\n      try {\n        yield FetchingContactsState();\n        List<MyContact> contacts = await userDataFunction.getContactsFromDB();\n        add(ReceivedContactsEvent(contacts));\n      } on Exception catch (e) {\n        print(e);\n      }\n    }\n    if (event is ReceivedContactsEvent) {\n      yield FetchedContactsState(event.contacts);\n    }\n  }\n}\n"
  },
  {
    "path": "lib/blocs/contacts/contacts_event.dart",
    "content": "part of 'contacts_bloc.dart';\n\nabstract class ContactsEvent extends Equatable {\n  const ContactsEvent();\n}\n\nclass FetchContactsEvent extends ContactsEvent {\n  @override\n  String toString() => 'FetchContactsEvent';\n\n  @override\n  List<Object> get props => [];\n}\n\nclass ReceivedContactsEvent extends ContactsEvent {\n  final List<MyContact> contacts;\n\n  ReceivedContactsEvent(this.contacts);\n\n  @override\n  String toString() => \"ReceivedContactsEvent\";\n\n  @override\n  List<Object> get props => [contacts];\n}\n"
  },
  {
    "path": "lib/blocs/contacts/contacts_state.dart",
    "content": "part of 'contacts_bloc.dart';\n\nabstract class ContactsState extends Equatable {\n  const ContactsState();\n}\n\nclass InitialContactsState extends ContactsState {\n  @override\n  String toString() => \"InitialContactsState\";\n\n  @override\n  List<Object> get props => [];\n}\n\nclass FetchingContactsState extends ContactsState {\n  @override\n  String toString() => \"FetchingContactsState\";\n\n  @override\n  List<Object> get props => [];\n}\n\nclass FetchedContactsState extends ContactsState {\n  final List<MyContact> contacts;\n\n  FetchedContactsState(this.contacts);\n\n  @override\n  String toString() => \"FetchedContactsState\";\n\n  @override\n  List<Object> get props => [contacts];\n}\n\nclass ErrorState extends ContactsState {\n  // TODO: Implement errors\n\n  @override\n  List<Object> get props => [];\n}\n"
  },
  {
    "path": "lib/blocs/home/home_bloc.dart",
    "content": "import 'dart:async';\n\nimport 'package:bloc/bloc.dart';\nimport 'package:coocoo/functions/MQTTFunction.dart';\nimport 'package:coocoo/managers/db_manager.dart';\nimport 'package:coocoo/models/Conversation.dart';\nimport 'package:equatable/equatable.dart';\nimport 'package:flutter/cupertino.dart';\n\npart 'home_event.dart';\npart 'home_state.dart';\n\nclass HomeBloc extends Bloc<HomeEvent, HomeState> {\n  HomeBloc() : super(HomeInitial());\n\n  MQTTFunction mqttFunction = MQTTFunction();\n\n  @override\n  Stream<HomeState> mapEventToState(\n    HomeEvent event,\n  ) async* {\n    if (event is ConnectToServerEvent) {\n      try {\n        await mqttFunction.connect(event.context);\n      } catch (e) {\n        print(\"Couln't Connect to Server. Most Probably Internet is Off\");\n      }\n      add(FetchHomeChatsEvent());\n    }\n    if (event is DisconnectEvent) {\n      mqttFunction.disconnect();\n    }\n    if (event is FetchHomeChatsEvent) {\n      yield* mapFetchHomeChatsEventToState();\n    }\n  }\n\n  Stream<HomeState> mapFetchHomeChatsEventToState() async* {\n    List<Conversation> conversations = [];\n    //TODO: Implement\n    List<Map<dynamic, dynamic>> dbData =\n        await DBManager.db.getAlConversationsFromChatTable();\n\n    dbData.forEach((dbMap) {\n      conversations.add(Conversation.fromMap(dbMap));\n    });\n\n    conversations.sort((b, a) => a.time.compareTo(b.time));\n\n    yield (FetchedHomeChatsState(conversations));\n  }\n}\n"
  },
  {
    "path": "lib/blocs/home/home_event.dart",
    "content": "part of 'home_bloc.dart';\n\nabstract class HomeEvent extends Equatable {\n  const HomeEvent();\n}\n\nclass FetchHomeChatsEvent extends HomeEvent {\n  @override\n  List<Object> get props => [];\n}\n\nclass ConnectToServerEvent extends HomeEvent {\n  final BuildContext context;\n\n  ConnectToServerEvent(this.context);\n\n  @override\n  List<Object> get props => [context];\n}\n\nclass DisconnectEvent extends HomeEvent {\n  @override\n  List<Object> get props => [];\n}\n"
  },
  {
    "path": "lib/blocs/home/home_state.dart",
    "content": "part of 'home_bloc.dart';\n\nabstract class HomeState extends Equatable {\n  final List<Conversation> conversations;\n  const HomeState(this.conversations);\n}\n\nclass HomeInitial extends HomeState {\n  HomeInitial() : super([]);\n\n  @override\n  List<Object> get props => [];\n}\n\nclass FetchedHomeChatsState extends HomeState {\n  final List<Conversation> conversations;\n  FetchedHomeChatsState(this.conversations) : super(conversations);\n\n  @override\n  List<Object> get props => [conversations];\n}\n"
  },
  {
    "path": "lib/blocs/timer/timer_bloc.dart",
    "content": "import 'dart:async';\n\nimport 'package:bloc/bloc.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:equatable/equatable.dart';\n\npart 'timer_event.dart';\npart 'timer_state.dart';\n\nclass TimerBloc extends Bloc<TimerEvent, TimerState> {\n  TimerBloc() : super(TimerStoppedState());\n\n  Stream<int> timerStream;\n  StreamSubscription<int> timerSubscription;\n\n  @override\n  Stream<TimerState> mapEventToState(\n    TimerEvent event,\n  ) async* {\n    if (event is StartTimerEvent) {\n      timerStream = stopWatchStream();\n      timerSubscription?.cancel();\n      timerSubscription = timerStream.listen((int newTick) {\n        add(TimerTickedEvent(newTick));\n      });\n    }\n    if (event is TimerTickedEvent) {\n      yield (TimerRunInProgressState(event.newTick));\n    }\n    if (event is StopTimerEvent) {\n      timerSubscription?.cancel();\n      timerStream = null;\n      yield (TimerStoppedState());\n    }\n  }\n\n  Stream<int> stopWatchStream() {\n    StreamController<int> streamController;\n    Timer timer;\n    Duration timerInterval = Duration(seconds: 1);\n    int counter = Constants.resendOtpTime;\n\n    void stopTimer() {\n      if (timer != null) {\n        timer.cancel();\n        timer = null;\n        counter = Constants.resendOtpTime;\n        streamController.close();\n      }\n    }\n\n    void tick(_) {\n      counter--;\n      streamController.add(counter);\n      if (counter < 1) {\n        add(StopTimerEvent());\n      }\n    }\n\n    void startTimer() {\n      timer = Timer.periodic(timerInterval, tick);\n    }\n\n    streamController = StreamController<int>(\n      onListen: startTimer,\n      onCancel: stopTimer,\n      onResume: startTimer,\n      onPause: stopTimer,\n    );\n\n    return streamController.stream;\n  }\n}\n"
  },
  {
    "path": "lib/blocs/timer/timer_event.dart",
    "content": "part of 'timer_bloc.dart';\n\nabstract class TimerEvent extends Equatable {\n  const TimerEvent();\n}\n\nclass StartTimerEvent extends TimerEvent {\n  @override\n  List<Object> get props => [];\n}\n\nclass TimerTickedEvent extends TimerEvent {\n  final int newTick;\n\n  TimerTickedEvent(this.newTick);\n\n  @override\n  List<Object> get props => [newTick];\n}\n\nclass StopTimerEvent extends TimerEvent {\n  @override\n  List<Object> get props => [];\n}\n"
  },
  {
    "path": "lib/blocs/timer/timer_state.dart",
    "content": "part of 'timer_bloc.dart';\n\nabstract class TimerState extends Equatable {\n  const TimerState();\n}\n\nclass TimerInitial extends TimerState {\n  @override\n  List<Object> get props => [];\n}\n\nclass TimerRunInProgressState extends TimerState {\n  final int newTick;\n\n  TimerRunInProgressState(this.newTick);\n\n  @override\n  List<Object> get props => [newTick];\n}\n\nclass TimerStoppedState extends TimerState {\n  @override\n  List<Object> get props => [];\n}\n"
  },
  {
    "path": "lib/config/Constants.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass Constants {\n  static final Color stuffColor = Colors.blueAccent[400];\n  static final Color textStuffColor = Colors.blueGrey[700];\n  static final int resendOtpTime = 35;\n\n  static const firstRun = \"firstRun\";\n  static const sessionUid = \"phoneNumber\";\n  static const sessionUsername = 'sessionUsername';\n  static const fullName = 'fullName';\n  static const sessionName = 'sessionName';\n  static const sessionProfilePictureUrl = 'sessionProfilePictureUrl';\n  static const sessionCountryCode = 'sessionCountryCode';\n\n  static const configDarkMode = 'configDarkMode';\n  static String downloadsDirPath;\n  static String cacheDirPath;\n\n  static const profilePicChangeMsg = \"profile_pic_change\";\n}\n"
  },
  {
    "path": "lib/config/Paths.dart",
    "content": "class Paths {\n  /*\n  Firebase paths\n   */\n  static const String profilePicturePath = 'profile_pictures';\n  static const String imageAttachmentsPath = 'images';\n  static const String videoAttachmentsPath = 'videos';\n  static const String fileAttachmentsPath = 'files';\n  static const String usersPath = '/users';\n  static const String contactsPath = 'contacts';\n  static const String usernameUidMapPath = '/username_uid_map';\n  static const String chatsPath = '/chats';\n  static const String chat_messages = '/chat_messages';\n  static const String messagesPath = 'messages';\n  static const String friendRequestsPath = 'friend requests';\n  static const String sentRequestsPath = 'sent requests';\n\n  static const String MESSAGES_COLLECTION = \"messages\";\n  static const String USERS_COLLECTION = \"users\";\n  static const String CALL_COLLECTION = \"call\";\n\n  static const String TIMESTAMP_FIELD = \"timestamp\";\n  static const String EMAIL_FIELD = \"email\";\n\n  static const String MESSAGE_TYPE_IMAGE = \"image\";\n}\n"
  },
  {
    "path": "lib/constants.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/painting.dart';\nimport 'package:flutter_neumorphic/flutter_neumorphic.dart';\n\nconst kMobileTextFieldDecoration = InputDecoration(\n  hintText: 'Enter Mobile Number',\n  contentPadding: EdgeInsets.symmetric(vertical: 1.5),\n  enabledBorder: OutlineInputBorder(\n    borderSide: BorderSide(\n      color: Color(0xFF6A1B9A),\n      width: 2.0,\n    ),\n  ),\n  focusedBorder: OutlineInputBorder(\n    borderSide: BorderSide(\n      color: Color(0xFF6A1B9A),\n      width: 2.0,\n    ),\n  ),\n  focusedErrorBorder: OutlineInputBorder(\n    borderSide: BorderSide(\n      color: Color(0xFF6A1B9A),\n      width: 2.0,\n    ),\n  ),\n);\n\nconst kChatsGroupsTextStyle = TextStyle(\n  fontSize: 17.0,\n  fontWeight: FontWeight.w600,\n);\n\nconst kCircleNeumorphicStyle = NeumorphicStyle(\n  shadowDarkColor: Colors.black,\n  shadowLightColor: Colors.white,\n  boxShape: NeumorphicBoxShape.circle(),\n  depth: 7,\n  intensity: 0.7,\n  surfaceIntensity: 0.6,\n  shape: NeumorphicShape.convex,\n);\n\nconst kChatCircleNeumorphicStyle = NeumorphicStyle(\n  shadowDarkColor: Colors.black,\n  shadowLightColor: Colors.white,\n  boxShape: NeumorphicBoxShape.circle(),\n  depth: 5,\n  intensity: 0.65,\n  surfaceIntensity: 0.6,\n);\n\nconst kRequestTitleStyle = TextStyle(\n  fontWeight: FontWeight.w700,\n  fontSize: 23.0,\n);\n\nconst double perfectWidth = 411.4; // 683.4;\n\nconst kHitUpIdTextFieldDecoration = InputDecoration(\n  contentPadding: EdgeInsets.symmetric(vertical: 0.0, horizontal: 15.0),\n  hintText: 'Search Username',\n  fillColor: Colors.white,\n  filled: true,\n  border: OutlineInputBorder(\n    borderRadius: const BorderRadius.all(\n      Radius.circular(40.0),\n    ),\n  ),\n  focusedBorder: OutlineInputBorder(\n    borderRadius: const BorderRadius.all(\n      Radius.circular(40.0),\n    ),\n  ),\n);\n"
  },
  {
    "path": "lib/functions/AddFriendsFunction.dart",
    "content": "import 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/config/Paths.dart';\nimport 'package:coocoo/functions/BaseFunctions.dart';\nimport 'package:coocoo/functions/ChatFunction.dart';\nimport 'package:coocoo/managers/db_manager.dart';\nimport 'package:coocoo/managers/mqtt_manager.dart';\nimport 'package:coocoo/stateProviders/mqtt_state.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:flutter/cupertino.dart';\nimport 'package:provider/provider.dart';\n\nclass AddFriendsFunction extends BaseAddFriendsFunction {\n  Firestore _firestore = Firestore.instance;\n  ChatFunction chatFunction = ChatFunction();\n  String uid = SharedObjects.prefs.getString(Constants.sessionUid);\n\n  @override\n  void dispose() {}\n\n  @override\n  Future<void> addToFriendRequestsCollection(String phoneNumber) async {\n    // add to friend requests collection of the other user\n    CollectionReference usersRef = _firestore.collection(Paths.usersPath);\n\n    // first get my data\n    DocumentSnapshot snapshot = await usersRef.document(uid).get();\n\n    usersRef\n        .document(phoneNumber)\n        .collection(Paths.friendRequestsPath)\n        .document(uid)\n        .setData({\n      'username': snapshot.data['username'],\n      'photoUrl': snapshot.data['photoUrl'],\n      'name': snapshot.data['name'],\n      'phoneNumber': snapshot.data['phoneNumber'],\n    });\n  }\n\n  @override\n  Future<String> addToLocalDBAndSubscribe(\n      BuildContext context, String phoneNumber) async {\n    DocumentSnapshot docSnapshot = await _firestore\n        .collection(Paths.usersPath)\n        .document(phoneNumber)\n        .get();\n\n    String chatId = await chatFunction.createChatIdForContact(phoneNumber);\n\n    // create a row for this user, i.e add the contact to my local db\n    String photoUrl = docSnapshot.data[\"photoUrl\"];\n    String username = docSnapshot.data[\"username\"];\n    String name = docSnapshot.data[\"name\"];\n    await DBManager.db.createRow(phoneNumber, chatId, name, username, photoUrl,\n        0); // 0 because here this is not a phone contact\n\n    // Subscribe to the chatId\n    MQTTManager manager = context.read<MQTTState>().manager;\n    print(\"SUBSCRIBING TO TOPIC : $chatId\");\n    manager.subscribeTopic(chatId);\n\n    return chatId;\n  }\n\n  @override\n  Future<void> addToSentRequestsCollection(String phoneNumber) async {\n    // add to my sent requests collection\n    CollectionReference usersRef = _firestore.collection(Paths.usersPath);\n\n    // first get the data for the phoneNumber\n    DocumentSnapshot snapshot = await usersRef.document(phoneNumber).get();\n\n    usersRef\n        .document(uid)\n        .collection(Paths.sentRequestsPath)\n        .document(phoneNumber)\n        .setData({\n      'username': snapshot.data['username'],\n      'photoUrl': snapshot.data['photoUrl'],\n      'name': snapshot.data['name'],\n      'phoneNumber': snapshot.data['phoneNumber'],\n    });\n  }\n\n  @override\n  Future<HitUpIdLocation> checkHitUpId(String hitUpId) async {\n    bool ans;\n    // check if hitUpId exists in local db\n    ans = await DBManager.db.checkIfUsernameExistsInDb(hitUpId);\n\n    if (ans) {\n      return HitUpIdLocation.InLocalDb;\n    } else {\n      // check if hitUpId exists in Firebase Friend Requests collection\n      String uid = SharedObjects.prefs.getString(Constants.sessionUid);\n      QuerySnapshot snapshot = await _firestore\n          .collection(Paths.usersPath)\n          .document(uid)\n          .collection(Paths.friendRequestsPath)\n          .where('username', isEqualTo: hitUpId)\n          .limit(1)\n          .getDocuments();\n\n      if (snapshot.documents.length > 0) {\n        return HitUpIdLocation.InFriendRequests;\n      } else {\n        // check if hitUpId exists in Firebase Sent Requests Collection\n        snapshot = await _firestore\n            .collection(Paths.usersPath)\n            .document(uid)\n            .collection(Paths.sentRequestsPath)\n            .where('username', isEqualTo: hitUpId)\n            .limit(1)\n            .getDocuments();\n\n        if (snapshot.documents.length > 0) {\n          return HitUpIdLocation.InSentRequests;\n        } else {\n          return HitUpIdLocation.Nowhere;\n        }\n      }\n    }\n  }\n\n  @override\n  Future<void> removeFromFriendRequestsCollection(String phoneNumber) async {\n    // remove from my friend requests collection\n    CollectionReference usersRef = _firestore.collection(Paths.usersPath);\n\n    await usersRef\n        .document(uid)\n        .collection(Paths.friendRequestsPath)\n        .document(phoneNumber)\n        .delete();\n  }\n\n  @override\n  void removeFromSentRequestsCollection(String phoneNumber) {\n    // remove from the other user's sent requests collection\n    CollectionReference usersRef = _firestore.collection(Paths.usersPath);\n\n    usersRef\n        .document(phoneNumber)\n        .collection(Paths.sentRequestsPath)\n        .document(uid)\n        .delete();\n  }\n}\n"
  },
  {
    "path": "lib/functions/BaseFunctions.dart",
    "content": "import 'dart:io';\n\nimport 'package:coocoo/models/ChatMessage.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/models/NonContact.dart';\nimport 'package:flutter/cupertino.dart';\nimport 'package:permission_handler/permission_handler.dart';\n\nenum HitUpIdLocation {\n  InLocalDb,\n  InFriendRequests,\n  InSentRequests,\n  Nowhere,\n}\n\nabstract class BaseFunction {\n  void dispose();\n}\n\nabstract class BaseUserDataFunction extends BaseFunction {\n  Future<List<MyContact>> getContactsFromDB();\n  Future<void> loadPhoneContactsV2(BuildContext context);\n  Future<List<NonContact>> loadNonContactsV2();\n  Future<PermissionStatus> askContactPermissions();\n  void onShare(BuildContext context);\n  void sendNotification({String toUid, String title, String content});\n  Future<void> verifyPhoneNumber(\n      BuildContext context, String phoneNum, Function verificationFailed);\n}\n\nabstract class BaseChatFunction extends BaseFunction {\n  Future<void> createChatIdForContact(String contactPhoneNumber);\n  void sendMessageToServer(BuildContext context, String msg, String chatId);\n  void sendImageToServer(BuildContext context, File imageFile, String chatId);\n  void sendServiceMsgToServer(BuildContext context, String msg, String chatId);\n  Future<List<ChatMessage>> getAllMsgsFromMessagesTable(String chatId);\n  void blockUser(BuildContext context, String chatId);\n  void unBlockUser(BuildContext context, String chatId);\n}\n\nabstract class BaseMQTTFunction extends BaseFunction {\n  Future<void> connect(BuildContext context);\n  void disconnect();\n}\n\nabstract class BaseUIFunction extends BaseFunction {\n  double cleanValue(double screenWidth, double value);\n}\n\nabstract class BaseAddFriendsFunction extends BaseFunction {\n  Future<String> addToLocalDBAndSubscribe(\n      BuildContext context, String phoneNumber);\n  Future<void> addToFriendRequestsCollection(String phoneNumber);\n  Future<void> addToSentRequestsCollection(String phoneNumber);\n  Future<HitUpIdLocation> checkHitUpId(String hitUpId);\n  Future<void> removeFromFriendRequestsCollection(String phoneNumber);\n  void removeFromSentRequestsCollection(String phoneNumber);\n}\n"
  },
  {
    "path": "lib/functions/ChatFunction.dart",
    "content": "import 'dart:convert';\nimport 'dart:io';\nimport 'dart:math';\n\nimport 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/config/Paths.dart';\nimport 'package:coocoo/functions/BaseFunctions.dart';\nimport 'package:coocoo/managers/db_manager.dart';\nimport 'package:coocoo/managers/mqtt_manager.dart';\nimport 'package:coocoo/models/ChatMessage.dart';\nimport 'package:coocoo/stateProviders/mqtt_state.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter_image_compress/flutter_image_compress.dart';\nimport 'package:path_provider/path_provider.dart';\nimport 'package:provider/provider.dart';\n\nclass ChatFunction extends BaseChatFunction {\n  Firestore _firestore = Firestore.instance;\n  MQTTManager _manager;\n  String myUid = SharedObjects.prefs.getString(Constants.sessionUid);\n\n  @override\n  Future<String> createChatIdForContact(String contactPhoneNumber) async {\n    String chatId;\n    String uId = SharedObjects.prefs.getString(Constants.sessionUid);\n    CollectionReference usersCollection =\n        _firestore.collection(Paths.usersPath);\n    DocumentReference userRef = usersCollection.document(uId);\n    DocumentReference contactRef = usersCollection.document(contactPhoneNumber);\n    DocumentSnapshot userSnapshot = await userRef.get();\n\n    // if chatId doesn't exists for that contact then create new ChatId and update it\n    // for both the user and the contact\n    // else use the chatId which already exists\n    if (userSnapshot.data['chats'] == null ||\n        userSnapshot.data['chats'][contactPhoneNumber] == null) {\n      chatId = createChatId();\n      await userRef.setData({\n        'chats': {contactPhoneNumber: chatId}\n      }, merge: true);\n      await contactRef.setData({\n        'chats': {uId: chatId}\n      }, merge: true);\n    } else {\n      chatId = userSnapshot.data['chats'][contactPhoneNumber];\n    }\n\n    return chatId;\n  }\n\n  String createChatId() {\n    final Random _random = Random.secure();\n    final int idLength = 16; // length of the chatId\n\n    var values = List<int>.generate(idLength, (i) => _random.nextInt(256));\n\n    return base64Url.encode(values);\n  }\n\n  @override\n  void dispose() {}\n\n  @override\n  void sendMessageToServer(BuildContext context, String msg, String chatId) {\n    if (_manager == null) {\n      _manager = context.read<MQTTState>().manager;\n    }\n    print(\"calling send message to server\");\n    Map msgMap = {\"msg\": \"$msg\", \"type\": \"text\", \"uid\": \"$myUid\"};\n    String msgToSend = json.encode(msgMap);\n    _manager.publish(msgToSend, chatId);\n  }\n\n  @override\n  Future<List<ChatMessage>> getAllMsgsFromMessagesTable(String chatId) async {\n    return await DBManager.db.readAllMessagesfromMessagesTable(chatId);\n  }\n\n  // 2. compress file and get file.\n  Future<File> testCompressAndGetFile(File file) async {\n    Directory tempDir = await getTemporaryDirectory();\n    String tempPath = tempDir.path;\n    var result = await FlutterImageCompress.compressAndGetFile(\n      file.absolute.path,\n      tempPath + \"/temp.jpg\",\n      minHeight: 400,\n      minWidth: 400,\n      quality: 80,\n    );\n    return result;\n  }\n\n  @override\n  void sendImageToServer(\n      BuildContext context, File imageFile, String chatId) async {\n    if (_manager == null) {\n      _manager = context.read<MQTTState>().manager;\n    }\n\n    // compress the image & make it smaller in size\n    File newFile = await testCompressAndGetFile(imageFile);\n\n    // change the image to bytes format\n    String base64Image = base64Encode(newFile.readAsBytesSync());\n    String msgToSend =\n        '{\"msg\" : \"$base64Image\", \"type\" : \"image\", \"uid\" : \"$myUid\"}';\n\n    while (!_manager.getConnectionStatus()) {\n      print(\"NOT CONNECTED BEFORE PUBLISHING\");\n      await Future.delayed(Duration(seconds: 1));\n    }\n\n    print(\"CONNECTED BEFORE PUBLISHING\");\n    _manager.publish(msgToSend, chatId);\n  }\n\n  @override\n  void sendServiceMsgToServer(BuildContext context, String msg, String chatId) {\n    if (_manager == null) {\n      _manager = context.read<MQTTState>().manager;\n    }\n    _manager.publish(msg, chatId);\n  }\n\n  @override\n  void blockUser(BuildContext context, String chatId) {\n    if (_manager == null) {\n      _manager = context.read<MQTTState>().manager;\n    }\n    DBManager.db.updateBlockStatus(0, chatId);\n    _manager.unSubscribeTopic(chatId);\n  }\n\n  @override\n  void unBlockUser(BuildContext context, String chatId) {\n    if (_manager == null) {\n      _manager = context.read<MQTTState>().manager;\n    }\n    DBManager.db.updateBlockStatus(1, chatId);\n    _manager.subscribeTopic(chatId);\n  }\n}\n"
  },
  {
    "path": "lib/functions/MQTTFunction.dart",
    "content": "import 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/functions/BaseFunctions.dart';\nimport 'package:coocoo/managers/mqtt_manager.dart';\nimport 'package:coocoo/stateProviders/mqtt_state.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:flutter/src/widgets/framework.dart';\nimport 'package:provider/provider.dart';\n\nclass MQTTFunction extends BaseMQTTFunction {\n  MQTTManager _manager;\n  String loggedInUser;\n\n  @override\n  Future<void> connect(BuildContext context) async {\n    loggedInUser = SharedObjects.prefs.getString(Constants.sessionUid);\n    _manager = context.read<MQTTState>().manager;\n\n    final String password = \"S8x${loggedInUser.substring(1, 6)}S,.@\";\n\n    if (_manager == null) {\n      _manager = MQTTManager(\n        serverAddress: \"13.127.199.45\",\n        clientName: loggedInUser,\n        context: context,\n      );\n\n      _manager.initializeMQTTClient();\n\n      // also set the mqtt_manager to the provider\n      context.read<MQTTState>().setNewManager(_manager);\n      print(_manager);\n    }\n\n    print(\"Connecting to server\");\n    await _manager.connect(loggedInUser, password);\n  }\n\n  @override\n  void dispose() {}\n\n  @override\n  void disconnect() {\n    if (_manager != null) {\n      _manager.disconnect();\n    }\n  }\n}\n"
  },
  {
    "path": "lib/functions/UserDataFunction.dart",
    "content": "import 'dart:convert';\n\nimport 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:contacts_service/contacts_service.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/config/Paths.dart';\nimport 'package:coocoo/functions/BaseFunctions.dart';\nimport 'package:coocoo/functions/ChatFunction.dart';\nimport 'package:coocoo/managers/db_manager.dart';\nimport 'package:coocoo/managers/mqtt_manager.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/models/NonContact.dart';\nimport 'package:coocoo/stateProviders/mqtt_state.dart';\nimport 'package:coocoo/stateProviders/number_state.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:firebase_auth/firebase_auth.dart';\nimport 'package:flutter/material.dart';\nimport 'package:http/http.dart' as http;\nimport 'package:permission_handler/permission_handler.dart';\nimport 'package:provider/provider.dart';\nimport 'package:share/share.dart';\n\nclass UserDataFunction extends BaseUserDataFunction {\n  Firestore _firestore = Firestore.instance;\n  ChatFunction chatFunction = ChatFunction();\n\n  @override\n  void dispose() {}\n\n  @override\n  Future<List<NonContact>> loadNonContactsV2() async {\n    List<NonContact> _nonContacts = [];\n    Iterable<Contact> _contacts =\n        await ContactsService.getContacts(withThumbnails: false);\n    String countryCode =\n        SharedObjects.prefs.getString(Constants.sessionCountryCode);\n\n    await Future.forEach(_contacts, (_contact) async {\n      String tempNum = cleanNumber(_contact, countryCode);\n\n      if (tempNum != null) {\n        bool contactExists =\n            await DBManager.db.checkIfContactExistsInDb(tempNum);\n\n        // if contact does not exist in local db then add it to the nonContacts list\n        if (!contactExists) {\n          print(tempNum);\n          _nonContacts.add(NonContact(tempNum, name: _contact.displayName));\n        }\n      }\n    });\n\n    return _nonContacts;\n  }\n\n  @override\n  Future<void> loadPhoneContactsV2(BuildContext context) async {\n    Iterable<Contact> _contacts =\n        await ContactsService.getContacts(withThumbnails: false);\n    String countryCode =\n        SharedObjects.prefs.getString(Constants.sessionCountryCode);\n\n    try {\n      await Future.forEach(_contacts, (_contact) async {\n        String tempNum = cleanNumber(_contact, countryCode);\n        String contactName = _contact.displayName;\n\n        if (tempNum != null) {\n          bool contactExists =\n              await DBManager.db.checkIfContactExistsInDb(tempNum);\n\n          if (!contactExists) {\n            await addInstalledUserToDBANDSubscribe(\n                context, tempNum, contactName);\n          } else if (contactExists) {\n            // however if contact exists in local db but does not exist in primary firestore\n            // users database because he deleted his account then remove him from local db\n            removeUninstalledUserFromDB(context, tempNum);\n          }\n        }\n      });\n    } catch (e, s) {\n      print(s);\n    }\n  }\n\n  void removeUninstalledUserFromDB(BuildContext context, String tempNum) async {\n    final contactRef = _firestore.collection(Paths.usersPath).document(tempNum);\n\n    contactRef.get().then((docSnapshot) async {\n      if (!docSnapshot.exists) {\n        // delete the contact from local Database\n        await DBManager.db.deleteContact(tempNum);\n      }\n    });\n  }\n\n  Future<void> addInstalledUserToDBANDSubscribe(\n      BuildContext context, String tempNum, String contactName) async {\n    final contactRef = _firestore.collection(Paths.usersPath).document(tempNum);\n\n    contactRef.get().then((docSnapshot) async {\n      // if the user has installed the app then add him as a contact to my db\n      // else do nothing\n      if (docSnapshot.exists) {\n        print(\"USER $tempNum EXISTS IN DB\");\n        String chatId = await chatFunction.createChatIdForContact(tempNum);\n\n        // create a row for this user, i.e add the contact to my local db\n        String photoUrl = docSnapshot.data[\"photoUrl\"];\n        String username = docSnapshot.data[\"username\"];\n        await DBManager.db.createRow(\n            docSnapshot.documentID,\n            chatId,\n            contactName,\n            username,\n            photoUrl,\n            1); // true because here this is a phone contact\n\n        // Subscribe to the chatId\n        MQTTManager manager = context.read<MQTTState>().manager;\n        print(\"SUBSCRIBING TO TOPIC : $chatId\");\n        manager.subscribeTopic(chatId);\n      }\n    }).catchError((e) {\n      print(\"e\");\n    });\n  }\n\n  dynamic cleanNumber(Contact dirtyNumber, String countryCode) {\n    // when we clean a number, we first remove all the white spaces and hyphens and then\n    // if the number does not has a country code,i.e, if its length is less than 11\n    // then we add the user's country code.\n    try {\n      String num = dirtyNumber.phones.first.value;\n      String num2 = num.replaceAll(RegExp(r\"\\D+\"), '');\n      if (num2.length < 11) {\n        return \"$countryCode$num2\";\n      } else {\n        return num2;\n      }\n    } catch (e) {\n      return null;\n    }\n  }\n\n  @override\n  Future<PermissionStatus> askContactPermissions() async {\n    PermissionStatus permissionStatus = await _getContactPermission();\n    return permissionStatus;\n  }\n\n  Future<PermissionStatus> _getContactPermission() async {\n    PermissionStatus permission = await Permission.contacts.status;\n    if (permission != PermissionStatus.granted &&\n        permission != PermissionStatus.restricted) {\n      Map<Permission, PermissionStatus> permissionStatus = await [\n        Permission.contacts,\n      ].request();\n      return permissionStatus[Permission.contacts] ??\n          PermissionStatus.undetermined;\n    } else {\n      return permission;\n    }\n  }\n\n  @override\n  Future<List<MyContact>> getContactsFromDB() async {\n    List<MyContact> contacts = [];\n\n    List<Map<dynamic, dynamic>> dbData = await DBManager.db.getAllContacts();\n\n    dbData.forEach((map) {\n      contacts.add(MyContact.fromMap(map));\n    });\n\n    return contacts;\n  }\n\n  @override\n  void onShare(BuildContext context) async {\n    // A builder is used to retrieve the context immediately\n    // surrounding the RaisedButton.\n    //\n    // The context's `findRenderObject` returns the first\n    // RenderObject in its descendent tree when it's not\n    // a RenderObjectWidget. The RaisedButton's RenderObject\n    // has its position and size after it's built.\n    final RenderBox box = context.findRenderObject();\n    await Share.share(\n        \"https://play.google.com/store/apps/details?id=com.digantakalita.coocoo\",\n        subject: \"Lets have our private chats on\"\n            \"this New Cool Messenger HitUp from now on. Its way safer than the others.\",\n        sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);\n  }\n\n  @override\n  void sendNotification({String toUid, String title, String content}) async {\n    final String app_id = \"98194ba4-9b9a-416b-ab0c-74b851af4f1a\";\n    var body = jsonEncode({\n      \"include_external_user_ids\": [toUid],\n      \"app_id\": app_id,\n      \"contents\": {\"en\": content},\n      \"headings\": {\"en\": title},\n      \"collapse_id\": \"123\",\n      \"android_channel_id\": \"0940813c-e319-4ff3-8d52-a202bf767b3a\"\n    });\n    http.Response response = await http.post(\n        'https://onesignal.com/api/v1/notifications',\n        body: body,\n        headers: {\n          \"content-type\": \"application/json\",\n          \"Authorization\":\n              \"Basic ZGY5MWZjZjctYmQ0My00ZDhjLTliYmItNzE0ZjlmOWVkYjYz\"\n        });\n    if (response.statusCode == 200) {\n      print(\"NOTIFICATION SENT SUCCESSFULLY\");\n    } else {\n      print('Notification Error | Error Code: ${response.statusCode}');\n    }\n  }\n\n  @override\n  Future<void> verifyPhoneNumber(BuildContext context, String phoneNum,\n      Function verificationFailed) async {\n    final FirebaseAuth _auth = FirebaseAuth.instance;\n    await _auth.verifyPhoneNumber(\n      phoneNumber: phoneNum,\n      timeout: Duration(seconds: 30),\n      verificationCompleted: null,\n      verificationFailed: verificationFailed,\n      codeSent: (String verificationId, [int forceResendingToken]) async {\n        context.read<NumberState>().setOTP(verificationId);\n      },\n      codeAutoRetrievalTimeout: null,\n    );\n  }\n}\n"
  },
  {
    "path": "lib/main.dart",
    "content": "import 'package:coocoo/blocs/AddFriends/add_friends_bloc.dart';\nimport 'package:coocoo/blocs/chats/chat_bloc.dart';\nimport 'package:coocoo/blocs/contacts/contacts_bloc.dart';\nimport 'package:coocoo/blocs/timer/timer_bloc.dart';\nimport 'package:coocoo/screens/home_screen.dart';\nimport 'package:coocoo/splashscreen.dart';\nimport 'package:coocoo/stateProviders/number_state.dart';\nimport 'package:coocoo/stateProviders/profilePicUrlState.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_bloc/flutter_bloc.dart';\nimport 'package:provider/provider.dart';\n\nimport 'blocs/home/home_bloc.dart';\nimport 'stateProviders/mqtt_state.dart';\n\nvoid main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  SharedObjects.prefs = await CachedSharedPreferences.getInstance();\n  runApp(MultiBlocProvider(\n    providers: [\n      BlocProvider<ContactsBloc>(\n        create: (context) => ContactsBloc(),\n      ),\n      BlocProvider<ChatBloc>(\n        create: (context) => ChatBloc(),\n      ),\n      BlocProvider<HomeBloc>(\n        create: (context) => HomeBloc(),\n      ),\n      BlocProvider<AddFriendsBloc>(\n        create: (context) => AddFriendsBloc(),\n      ),\n      BlocProvider<TimerBloc>(\n        create: (context) => TimerBloc(),\n      )\n    ],\n    child: MyApp(),\n  ));\n}\n\nclass MyApp extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return MultiProvider(\n      providers: [\n        ChangeNotifierProvider<MQTTState>(create: (context) => MQTTState()),\n        ChangeNotifierProvider<NumberState>(\n          create: (context) => NumberState(),\n        ),\n        ChangeNotifierProvider<ProfilePicUrlState>(\n            create: (context) => ProfilePicUrlState()),\n      ],\n      child: MaterialApp(\n        debugShowCheckedModeBanner: false,\n        title: 'HitUp Messenger',\n        routes: {\n          '/homeScreen': (context) => HomeScreen(),\n        },\n        theme: ThemeData(\n          primaryColor: Colors.white,\n          primarySwatch: Colors.blueGrey,\n          visualDensity: VisualDensity.adaptivePlatformDensity,\n        ),\n        home: SplashScreen(),\n      ),\n    );\n  }\n}\n\n//Feature Ideas\n\n//TODO: Mood of a user\n//TODO: Online Offline...but only to the people whom I wanna show if I am online\n//TODO: whether the user is active or not, i.e if she is inside your chat window or is she chatting with someone else\n"
  },
  {
    "path": "lib/managers/db_manager.dart",
    "content": "import 'package:coocoo/models/ChatMessage.dart';\nimport 'package:path/path.dart';\nimport 'package:sqflite/sqflite.dart';\n\nclass DBManager {\n  DBManager._();\n\n  static final DBManager db = DBManager._();\n\n  Database _database;\n\n  // final String contactsTable = \"Contacts\";\n  final String messagesTable = \"Messages\";\n  final String chatsTable = \"Chats\";\n\n  final String phoneNumberColumn = \"phoneNumber\";\n  final String chatIdColumn = \"chatId\";\n  final String nameColumn = 'name';\n  final String usernameColumn = 'username';\n  final String msgColumn = \"msg\";\n  final String timeColumn = \"time\";\n  final String photoUrlColumn = \"photoUrl\";\n  final String msgTypeColumn = 'msgType';\n  final String isContactColumn = 'isContact';\n  final String blockStatusColumn = 'blockStat'; // 0 => Blocked, 1 => Unblocked\n  final String msgStatusColumn = \"msgStatus\"; // 0=> Received, 1=> Sent\n\n  Future<Database> get database async {\n    if (_database != null) {\n      return _database;\n    }\n    _database = await initDB();\n    return _database;\n  }\n\n  initDB() async {\n    String dbPath = await getDatabasesPath();\n    return await openDatabase(\n      join(dbPath, \"chat_database.db\"),\n      version: 1,\n      // onCreate is called only if there was no prior database in the specified path\n      onCreate: (Database db, int version) async {\n        // we need 3 tables\n        // 1. for storing users data\n        // await db.execute(\n        //     \"CREATE TABLE $contactsTable ($phoneNumberColumn TEXT PRIMARY KEY, $chatIdColumn TEXT, \"\n        //     \"$nameColumn TEXT, $usernameColumn TEXT,\"\n        //     \"$photoUrlColumn TEXT, $isContactColumn INTEGER, $blockStatusColumn INTEGER)\");\n\n        // 2. for storing the messages for the chat screen\n        await db.execute(\"CREATE TABLE $messagesTable (\"\n            \"$chatIdColumn TEXT, $msgColumn TEXT, $msgTypeColumn TEXT, \"\n            \"$timeColumn INTEGER, $msgStatusColumn INTEGER)\");\n\n        // 3. for storing the last message to show in the home screen in the chat cards\n        await db.execute(\n            \"CREATE TABLE $chatsTable ($phoneNumberColumn TEXT PRIMARY KEY, $nameColumn TEXT,\"\n            \"$chatIdColumn TEXT, $usernameColumn TEXT, $photoUrlColumn TEXT, $isContactColumn INTEGER, $blockStatusColumn INTEGER,\"\n            \" $msgColumn TEXT, $msgTypeColumn TEXT, \"\n            \"$timeColumn INTEGER)\");\n      },\n    );\n  }\n\n  Future<void> updateMessageToChatTable(\n      String chatId, String newMsg, String msgType, int currTime) async {\n    final Database db = await database;\n\n    int numOfUpdates = await db.rawUpdate(\n        \"UPDATE $chatsTable SET $msgColumn = ?, $timeColumn = ?, $msgTypeColumn = ? WHERE $chatIdColumn = ?\",\n        [newMsg, currTime, msgType, chatId]);\n\n    print(\"$numOfUpdates rows were changed in Chats Table\");\n  }\n\n  Future<void> addNewMessageToMessagesTable(String chatId, String newMsg,\n      String msgType, int currTime, int msgStatus) async {\n    final Database db = await database;\n\n    await db.insert(\n      messagesTable,\n      {\n        chatIdColumn: chatId,\n        msgColumn: newMsg,\n        msgTypeColumn: msgType,\n        timeColumn: currTime,\n        msgStatusColumn: msgStatus,\n      },\n      conflictAlgorithm: ConflictAlgorithm.ignore,\n    );\n  }\n\n  Future<ChatMessage> readMessageFromChatTable(String chatId) async {\n    final Database db = await database;\n\n    List<Map<String, dynamic>> res = await db.query(chatsTable,\n        columns: [\n          msgColumn,\n          msgTypeColumn,\n          timeColumn,\n          chatIdColumn,\n          msgStatusColumn\n        ],\n        where: \"$chatIdColumn = ?\",\n        whereArgs: [chatId]);\n\n    ChatMessage chatMessage = ChatMessage.fromMap(res[0]);\n\n    print(\"Most recent message read From Db :::::::: $chatMessage\");\n    return chatMessage;\n  }\n\n  Future<List<ChatMessage>> readAllMessagesfromMessagesTable(\n      String chatId) async {\n    final Database db = await database;\n\n    var res = await db\n        .query(messagesTable, where: \"$chatIdColumn = ?\", whereArgs: [chatId]);\n\n    return res.map((e) => ChatMessage.fromMap(e)).toList();\n  }\n\n// get all conversations from chat table to show in the home page\n  Future<List<Map<dynamic, dynamic>>> getAlConversationsFromChatTable() async {\n    final Database db = await database;\n\n    var res = await db.query(chatsTable, where: \"$msgColumn IS NOT NULL\");\n    List<Map> output = List<Map>.from(res);\n\n    return output;\n  }\n\n  Future<void> updateProfilePicInChatsTable(\n      String photoUrl, String chatId) async {\n    final Database db = await database;\n\n    await db.rawUpdate(\n      \"UPDATE $chatsTable SET $photoUrlColumn = ? WHERE $chatIdColumn = ?\",\n      [photoUrl, chatId],\n    );\n  }\n\n  Future<List<Map<dynamic, dynamic>>> getAllContacts() async {\n    final Database db = await database;\n\n    var res = await db.query(\n      chatsTable,\n      columns: [\n        phoneNumberColumn,\n        nameColumn,\n        usernameColumn,\n        photoUrlColumn,\n        chatIdColumn\n      ],\n      where: \"$isContactColumn = ?\",\n      whereArgs: [1],\n    );\n    List<Map> output = List<Map>.from(res);\n\n    return output;\n  }\n\n  Future<void> createRow(String phoneNum, String chatId, String contactName,\n      String username, String photoUrl, int isContact) async {\n    final Database db = await database;\n\n    await db.insert(\n      chatsTable,\n      {\n        phoneNumberColumn: phoneNum,\n        chatIdColumn: chatId,\n        nameColumn: contactName,\n        usernameColumn: username,\n        photoUrlColumn: photoUrl,\n        isContactColumn: isContact,\n        blockStatusColumn: 1, // At first it will be unblocked ofcourse\n        msgColumn: null,\n        msgTypeColumn: null,\n        timeColumn: null,\n      },\n      conflictAlgorithm: ConflictAlgorithm.ignore,\n    );\n  }\n\n  Future<void> deleteContact(String phoneNum) async {\n    final Database db = await database;\n\n    await db.delete(chatsTable,\n        where: \"$phoneNumberColumn = ?\", whereArgs: [phoneNum]);\n  }\n\n  Future<bool> checkIfContactExistsInDb(String phoneNumber) async {\n    final Database db = await database;\n\n    var result = await db.rawQuery(\n      \"SELECT COUNT(1) FROM $chatsTable WHERE $phoneNumberColumn = ? LIMIT 1\",\n      [phoneNumber],\n    );\n    return result[0][\"COUNT(1)\"] == 1 ? true : false;\n  }\n\n  Future<bool> checkIfUsernameExistsInDb(String username) async {\n    final Database db = await database;\n    var result = await db.rawQuery(\n      \"SELECT COUNT(1) FROM $chatsTable WHERE $usernameColumn = ? LIMIT 1\",\n      [username],\n    );\n    return result[0][\"COUNT(1)\"] == 1 ? true : false;\n  }\n\n  Future<void> deleteTable() async {\n    final Database db = await database;\n\n    await db.delete(chatsTable, where: '1');\n  }\n\n// check if contact is blocked or unblocked\n  Future<bool> isBlocked(String chatId) async {\n    final Database db = await database;\n\n    var res = await db.query(chatsTable,\n        columns: [blockStatusColumn],\n        where: '$chatIdColumn = ?',\n        whereArgs: [chatId]);\n\n    return (res[0][\"blockStat\"] == 1 ? false : true);\n  }\n\n  Future<void> updateBlockStatus(int newStatus, String chatId) async {\n    final Database db = await database;\n\n    await db.rawUpdate(\n      \"UPDATE $chatsTable SET $blockStatusColumn = ? WHERE $chatIdColumn = ?\",\n      [newStatus, chatId],\n    );\n  }\n\n  Future<void> updateName(String newName, String chatId) async {\n    final Database db = await database;\n\n    await db.rawUpdate(\n      \"UPDATE $chatsTable SET $nameColumn = ? WHERE $chatIdColumn = ?\",\n      [newName, chatId],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/managers/mqtt_manager.dart",
    "content": "import 'dart:convert';\n\nimport 'package:coocoo/blocs/chats/chat_bloc.dart';\nimport 'package:coocoo/blocs/home/home_bloc.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/stateProviders/mqtt_state.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter_bloc/flutter_bloc.dart';\nimport 'package:mqtt_client/mqtt_client.dart';\nimport 'package:mqtt_client/mqtt_server_client.dart';\nimport 'package:provider/provider.dart';\n\nimport 'db_manager.dart';\n\nclass MQTTManager {\n  MQTTManager({\n    @required this.serverAddress,\n    @required this.clientName,\n    @required this.context,\n  });\n\n  final String serverAddress;\n  final String clientName;\n  final BuildContext context;\n  MqttServerClient _client;\n\n  ChatBloc chatBloc;\n  HomeBloc homeBloc;\n\n  void initializeMQTTClient() {\n    _client = MqttServerClient(serverAddress, clientName);\n    _client.port = 1883;\n    _client.keepAlivePeriod = 43200;\n    _client.logging(on: false);\n    _client.onDisconnected = onDisconnected;\n    _client.onConnected = onConnect;\n\n    // auto reconnecting when client is disconnected to server\n    _client.autoReconnect = true;\n\n    final connMess = MqttConnectMessage()\n        .withClientIdentifier(clientName)\n        .keepAliveFor(\n            43200) // Must agree with the keep alive set above or not set\n        .withWillTopic(\n            'willtopic') // If you set this you must set a will message\n        .withWillMessage('My Will message')\n        .withWillRetain()\n        .withWillQos(MqttQos.atLeastOnce);\n\n    _client.connectionMessage = connMess;\n  }\n\n  void disconnect() {\n    _client.disconnect();\n  }\n\n  bool getConnectionStatus() {\n    if (_client.connectionStatus.state == MqttConnectionState.connected) {\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  Future<void> connect(String username, String password) async {\n    try {\n      await _client.connect(username, password);\n    } on Exception catch (e) {\n      print('EXAMPLE::client exception - $e');\n      _client.disconnect();\n    }\n  }\n\n  void subscribeTopic(String topic) {\n    _client.subscribe(topic, MqttQos.atLeastOnce);\n\n    /// The client has a change notifier object(see the Observable class) which we then listen to to get\n    /// notifications of published updates to each subscribed topic.\n  }\n\n  void unSubscribeTopic(String topic) {\n    _client.unsubscribe(topic);\n  }\n\n  Stream<List<MqttReceivedMessage<MqttMessage>>> get messageStream =>\n      _client.updates;\n\n  void publish(String myMessage, String topic) {\n    final builder = MqttClientPayloadBuilder();\n    builder.addString(myMessage);\n    _client.publishMessage(topic, MqttQos.atLeastOnce, builder.payload,\n        retain: true);\n  }\n\n  void onDisconnected() {\n    print('Client Disconnect');\n  }\n\n  void onConnect() {\n    chatBloc = BlocProvider.of<ChatBloc>(context);\n    homeBloc = BlocProvider.of<HomeBloc>(context);\n    _client.updates.listen((List<MqttReceivedMessage<MqttMessage>> c) async {\n      final MqttPublishMessage recMess = c[0].payload;\n      final String chatId = c[0].topic;\n      final msg =\n          MqttPublishPayload.bytesToStringAsString(recMess.payload.message);\n\n      print(\"THIS IS THE MESSAGE BEFORE DECODING\");\n      print(msg);\n      Map parsedMsg = json.decode(msg);\n      final int currTime = DateTime.now().millisecondsSinceEpoch;\n      String myUid = SharedObjects.prefs.getString(Constants.sessionUid);\n\n      if (parsedMsg[\"type\"] == \"service\") {\n        // mqtt message if any of my contacts changed his/her profile picture\n        if (parsedMsg[\"msg\"] == Constants.profilePicChangeMsg) {\n          if (parsedMsg[\"uid\"] != myUid) {\n            print(\"Profile Pic Changed For $chatId\");\n            await DBManager.db.updateProfilePicInChatsTable(\n                parsedMsg[\"profilePicUrl\"], chatId);\n            homeBloc.add(FetchHomeChatsEvent());\n          }\n        }\n      } else {\n// save message to local db\n        print(parsedMsg[\"uid\"]);\n        print(myUid);\n        if (parsedMsg[\"uid\"] == myUid) {\n          // if uid of message is same as mine then that means\n          // I sent the message, so save it to db as sent message\n          print(\"seetting messages to local db 1\");\n          await DBManager.db.addNewMessageToMessagesTable(\n              chatId,\n              parsedMsg[\"msg\"],\n              parsedMsg[\"type\"],\n              currTime,\n              1); // 1 bcox message is sent\n\n        } else {\n          print(\"seetting messages to local db 0\");\n          // save the message to local db as received message\n          await DBManager.db.addNewMessageToMessagesTable(\n              chatId,\n              parsedMsg[\"msg\"],\n              parsedMsg[\"type\"],\n              currTime,\n              0); // 0 bcox message is received\n        }\n\n        DBManager.db.updateMessageToChatTable(\n          chatId,\n          parsedMsg[\"msg\"],\n          parsedMsg[\"type\"],\n          currTime,\n        );\n\n        //also notify the bloc that a new message is received so that it\n        // may read the last message from the local db\n        chatBloc.add(ReceivedMessageEvent(chatId));\n\n        // fetching the chatcards for the homePage\n        homeBloc.add(FetchHomeChatsEvent());\n      }\n    });\n  }\n}\n"
  },
  {
    "path": "lib/models/ChatMessage.dart",
    "content": "class ChatMessage {\n  final String msg;\n  final int time;\n  final String msgType;\n  // final int msgStatus;\n  final String chatId;\n  final bool isSelf;\n\n  ChatMessage({this.msg, this.time, this.msgType, this.chatId, this.isSelf});\n\n  factory ChatMessage.fromMap(Map map) {\n    return ChatMessage(\n      msg: map[\"msg\"],\n      time: map[\"time\"],\n      msgType: map[\"msgType\"],\n      chatId: map[\"chatId\"],\n      isSelf: map[\"msgStatus\"] == 1 ? true : false,\n    );\n  }\n\n  @override\n  String toString() => \"msg : $msg, time : $time, \"\n      \"msgType : $msgType, chatId : $chatId, isSelf: $isSelf\";\n}\n"
  },
  {
    "path": "lib/models/Conversation.dart",
    "content": "class Conversation {\n  final String phoneNumber;\n  final String lastMessage;\n  final String msgType;\n  final int time;\n  final String photoUrl;\n  final String chatId;\n  final String name;\n  final String username;\n\n  Conversation({\n    this.phoneNumber,\n    this.lastMessage,\n    this.msgType,\n    this.time,\n    this.photoUrl,\n    this.chatId,\n    this.name,\n    this.username,\n  });\n\n  factory Conversation.fromMap(Map map) {\n    // here map is the map from the sqflite database\n    return Conversation(\n      phoneNumber: map[\"phoneNumber\"],\n      lastMessage: map[\"msg\"],\n      msgType: map[\"msgType\"],\n      time: map[\"time\"],\n      photoUrl: map[\"photoUrl\"],\n      chatId: map[\"chatId\"],\n      name: map['name'],\n      username: map['username'],\n    );\n  }\n\n  @override\n  String toString() => \"phoneNumber : $phoneNumber,\"\n      \"lastMessage : $lastMessage, msgType : $msgType, time : $time, photoUrl : $photoUrl, \"\n      \"chatId : $chatId\";\n}\n"
  },
  {
    "path": "lib/models/MyContact.dart",
    "content": "import 'package:cloud_firestore/cloud_firestore.dart';\n\nclass MyContact {\n  final String phoneNumber;\n  final String name;\n  final String username;\n  final String photoUrl;\n  final String chatId;\n  final int ind;\n\n  MyContact(\n      {this.phoneNumber,\n      this.name,\n      this.username,\n      this.photoUrl,\n      this.chatId,\n      this.ind});\n\n  factory MyContact.fromFireStore(DocumentSnapshot snapshot) {\n    var data = snapshot.data;\n\n    return MyContact(\n        phoneNumber: data['phoneNumber'] ?? snapshot.documentID,\n        name: data['name'],\n        photoUrl: data['photoUrl'],\n        username: data['username'],\n        chatId: data['chatId']);\n  }\n\n  factory MyContact.fromMap(Map data) {\n    return MyContact(\n        phoneNumber: data['phoneNumber'],\n        name: data['name'],\n        photoUrl: data['photoUrl'],\n        username: data['username'],\n        chatId: data['chatId']);\n  }\n\n  @override\n  String toString() {\n    return \"index : ${this.ind}, phoneNumber : ${this.phoneNumber}, \"\n        \"name : ${this.name} photoUrl : ${this.photoUrl}, \"\n        \"chatId : ${this.chatId}, username : ${this.username}\";\n  }\n}\n"
  },
  {
    "path": "lib/models/NonContact.dart",
    "content": "import 'package:equatable/equatable.dart';\n\nclass NonContact extends Equatable {\n  final String name;\n  final String phoneNumber;\n\n  NonContact(this.phoneNumber, {this.name});\n\n  @override\n  List<Object> get props => [phoneNumber];\n}\n"
  },
  {
    "path": "lib/models/User.dart",
    "content": "import 'package:cloud_firestore/cloud_firestore.dart';\n\nclass User {\n  String documentId;\n  String phoneNumber;\n  String username;\n  String photoUrl;\n\n  User({this.documentId, this.phoneNumber, this.username, this.photoUrl});\n\n  factory User.fromFirestore(DocumentSnapshot doc) {\n    Map data = doc.data;\n    return User(\n        documentId: doc.documentID,\n        phoneNumber: data['phoneNumber'],\n        username: data['username'],\n        photoUrl: data['photoUrl']);\n  }\n  factory User.fromMap(Map data) {\n    return User(\n        documentId: data['uid'],\n        phoneNumber: data['phoneNumber'],\n        username: data['username'],\n        photoUrl: data['photoUrl']);\n  }\n  @override\n  String toString() {\n    return '{ documentId: $documentId, phoneNumb: $phoneNumber, username: $username, photoUrl: $photoUrl }';\n  }\n}\n"
  },
  {
    "path": "lib/screens/ContactsHelpPage.dart",
    "content": "import 'package:coocoo/constants.dart';\nimport 'package:flutter/material.dart';\n\nclass ContactsHelpPage extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    final double screenWidth = MediaQuery.of(context).size.width;\n    return Scaffold(\n      appBar: AppBar(\n        title: Text('Contacts Help'),\n      ),\n      body: Container(\n        padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0),\n        child: Column(\n          crossAxisAlignment: CrossAxisAlignment.start,\n          children: <Widget>[\n            Text(\n              \"    If some of your friends don't appear in\\n    the contacts\"\n              \" list, we recommend\\n    the following steps:\",\n              style: TextStyle(\n                fontSize: (screenWidth / perfectWidth) * 18.0,\n                fontWeight: FontWeight.w400,\n              ),\n            ),\n            SizedBox(height: 8.0),\n            Text(\n              \"1. Click on the Refresh Button on the\\n \"\n              \"   Top right hand side of the page and \"\n              \"\\n    check for the contact again.\",\n              style: TextStyle(\n                fontSize: (screenWidth / perfectWidth) * 18.0,\n                fontWeight: FontWeight.w400,\n              ),\n            ),\n            SizedBox(height: 8.0),\n            Text(\n              \"2. Make sure that your friend is using\\n     HitUp Messenger\",\n              style: TextStyle(\n                fontSize: (screenWidth / perfectWidth) * 18.0,\n                fontWeight: FontWeight.w400,\n              ),\n            ),\n            SizedBox(height: 8.0),\n            Text(\n              \"3. Make sure that your friend's phone number\\n     is in your \"\n              \"address book\",\n              style: TextStyle(\n                fontSize: (screenWidth / perfectWidth) * 18.0,\n                fontWeight: FontWeight.w400,\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/screens/account_screen.dart",
    "content": "import 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/screens/profile_screen.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/config/Paths.dart';\nimport 'package:coocoo/managers/db_manager.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:coocoo/widgets/DangerCard.dart';\nimport 'package:coocoo/widgets/SettingsTile.dart';\nimport 'package:firebase_auth/firebase_auth.dart';\nimport 'package:flutter/material.dart';\n\nimport '../splashscreen.dart';\n\nclass AccountScreen extends StatefulWidget {\n  @override\n  _AccountScreenState createState() => _AccountScreenState();\n}\n\nclass _AccountScreenState extends State<AccountScreen> {\n  final Firestore _firestore = Firestore.instance;\n  FirebaseAuth _auth = FirebaseAuth.instance;\n  bool loading = false;\n\n  Future<bool> _showDialogBox() async {\n    return (await showDialog(\n          context: context,\n          builder: (context) => AlertDialog(\n            title: Text('Are you sure?'),\n            content: Text('You want to delete your HitUp account?'),\n            actions: <Widget>[\n              FlatButton(\n                onPressed: () => Navigator.of(context).pop(false),\n                child: Text('No'),\n              ),\n              FlatButton(\n                onPressed: () async {\n                  setState(() {\n                    loading = true;\n                  });\n                  String userPhone =\n                      SharedObjects.prefs.getString(Constants.sessionUid);\n\n                  try {\n                    _firestore\n                        .collection(Paths.usersPath)\n                        .document(userPhone)\n                        .delete();\n                  } catch (e) {\n                    print(e);\n                  }\n                  DBManager.db.deleteTable();\n                  await SharedObjects.prefs.clearAll();\n                  Navigator.push(context,\n                      MaterialPageRoute(builder: (context) => SplashScreen()));\n                  setState(() {\n                    loading = false;\n                  });\n                },\n                child: Text('Yes Delete'),\n              ),\n            ],\n          ),\n        )) ??\n        false;\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text('Account'),\n      ),\n      body: !loading\n          ? Padding(\n              padding: const EdgeInsets.symmetric(vertical: 8.0),\n              child: Column(\n                mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                children: [\n                  SettingsTile(\n                    icon: Icons.account_circle,\n                    title: 'My Account',\n                    onPress: () {\n                      Navigator.push(\n                          context,\n                          MaterialPageRoute(\n                              builder: (context) => ProfileScreen()));\n                    },\n                  ),\n                  DangerCard(Colors.red, 'Delete Account', () {\n                    _showDialogBox();\n                  }),\n                ],\n              ),\n            )\n          : Center(child: CircularProgressIndicator()),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/screens/addFriends_screen.dart",
    "content": "import 'dart:ui';\n\nimport 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/blocs/AddFriends/add_friends_bloc.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/config/Paths.dart';\nimport 'package:coocoo/constants.dart';\nimport 'package:coocoo/functions/BaseFunctions.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:coocoo/widgets/AddFriendCard.dart';\nimport 'package:coocoo/widgets/FriendRequestCard.dart';\nimport 'package:coocoo/widgets/NoRequestsCard.dart';\nimport 'package:coocoo/widgets/SentRequestCard.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/painting.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_bloc/flutter_bloc.dart';\nimport 'package:flutter_neumorphic/flutter_neumorphic.dart';\n\nenum RequestsType { FriendRequests, SentRequests }\n\nclass AddFriendsScreen extends StatefulWidget {\n  @override\n  _AddFriendsScreenState createState() => _AddFriendsScreenState();\n}\n\nclass _AddFriendsScreenState extends State<AddFriendsScreen> {\n  final TextEditingController hitupIdController = TextEditingController();\n  Firestore _firestore = Firestore.instance;\n  String uid = SharedObjects.prefs.getString(Constants.sessionUid);\n  AddFriendsBloc addFriendsBloc;\n  final _formKey = GlobalKey<FormState>();\n\n  Widget _buildRequestsStreamBuilder(\n      double algo, RequestsType requestsType, BuildContext contex) {\n    return StreamBuilder<QuerySnapshot>(\n      stream: _firestore\n          .collection(Paths.usersPath)\n          .document(uid)\n          .collection(requestsType == RequestsType.SentRequests\n              ? Paths.sentRequestsPath\n              : Paths.friendRequestsPath)\n          .snapshots(),\n      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {\n        Widget toShow;\n        if (snapshot.hasError) {\n          toShow = HitUpIdTextWidget(\n              algo: algo, text: 'Sorry! Not able to retrieve Data');\n        } else {\n          switch (snapshot.connectionState) {\n            case ConnectionState.none:\n              toShow = HitUpIdTextWidget(\n                  algo: algo, text: 'Sorry! Not able to retrieve Data');\n              break;\n            case ConnectionState.waiting:\n              toShow = Padding(\n                padding: const EdgeInsets.only(top: 8.0),\n                child: Center(\n                  child: SizedBox(\n                    child: CircularProgressIndicator(),\n                    height: 60,\n                    width: 60,\n                  ),\n                ),\n              );\n              break;\n            case ConnectionState.active:\n            case ConnectionState.done:\n              if (snapshot.data.documents.isEmpty) {\n                toShow = NoRequestsCard(\n                    algo: algo,\n                    text: requestsType == RequestsType.SentRequests\n                        ? 'You h'\n                            'ave not sent any Friend Requests'\n                        : 'You have No '\n                            'Friend Requests');\n              } else {\n                toShow = Column(\n                  children: snapshot.data.documents\n                      .map((e) => requestsType == RequestsType.SentRequests\n                          ? SentRequestCard(MyContact.fromFireStore(e))\n                          : FriendRequestCard(MyContact.fromFireStore(e),\n                              addFriendsBloc, contex))\n                      .toList(),\n                );\n              }\n              break;\n          }\n        }\n        return toShow;\n      },\n    );\n  }\n\n  @override\n  void initState() {\n    addFriendsBloc = BlocProvider.of<AddFriendsBloc>(context);\n    super.initState();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    double width = MediaQuery.of(context).size.width;\n    double algo = width / perfectWidth;\n    return Form(\n      key: _formKey,\n      child: Padding(\n        padding: EdgeInsets.only(top: 12.0, right: 10.0, left: 10.0),\n        child: ListView(\n          children: [\n            Row(\n              children: [\n                GestureDetector(\n                  child: Icon(\n                    Icons.arrow_back,\n                    color: Colors.black,\n                  ),\n                  onTap: () {\n                    Navigator.pop(context);\n                  },\n                ),\n                SizedBox(width: 5.0),\n                Expanded(\n                    child: TextFormField(\n                  inputFormatters: [\n                    FilteringTextInputFormatter.deny(\n                        RegExp(r'\\s+')) // no spaces allowed\n                  ],\n                  validator: (value) {\n                    if (value.isEmpty) {\n                      return \"Please enter a valid username\";\n                    }\n                    return null;\n                  },\n                  controller: hitupIdController,\n                  style: TextStyle(\n                    fontSize: algo * 18.0,\n                  ),\n                  autocorrect: false,\n                  cursorColor: Colors.blueGrey,\n                  decoration: kHitUpIdTextFieldDecoration,\n                )),\n                SizedBox(width: algo * 10.0),\n                GestureDetector(\n                  onTap: () {\n                    if (_formKey.currentState.validate()) {\n                      addFriendsBloc\n                          .add(SearchHitUpIdEvent(hitupIdController.text));\n                    }\n                    hitupIdController.clear();\n                  },\n                  child: Text(\n                    'Search',\n                    style: TextStyle(\n                      letterSpacing: 0.5,\n                      fontSize: algo * 21.0,\n                      fontWeight: FontWeight.bold,\n                    ),\n                  ),\n                ),\n              ],\n            ),\n            Padding(\n              padding: const EdgeInsets.symmetric(vertical: 8.0),\n              child: BlocBuilder<AddFriendsBloc, AddFriendsState>(\n                builder: (context, state) {\n                  if (state is SearchingHitUpIdState) {\n                    return SearchingCard(algo: algo);\n                  }\n                  if (state is HitUpIdAlreadyThere) {\n                    if (state.hitUpIdLocation == HitUpIdLocation.InLocalDb) {\n                      return HitUpIdTextWidget(\n                          algo: algo,\n                          text:\n                              '@${state.hitUpId} already exists in your contacts!');\n                    } else if (state.hitUpIdLocation ==\n                        HitUpIdLocation.InFriendRequests) {\n                      return HitUpIdTextWidget(\n                          algo: algo,\n                          text:\n                              'You have already received a friend request from @${state.hitUpId}. Please'\n                              ' check your Friend Requests List');\n                    } else if (state.hitUpIdLocation ==\n                        HitUpIdLocation.InSentRequests) {\n                      return HitUpIdTextWidget(\n                          algo: algo,\n                          text:\n                              'You have already sent a friend request to @${state.hitUpId}');\n                    }\n                  }\n                  if (state is SendingFriendRequestState) {\n                    return SearchingCard(algo: algo);\n                  }\n                  if (state is FriendRequestSentState) {\n                    return SentRequestCard(state.friend);\n                  }\n                  if (state is HitUpIdExistsState) {\n                    // return Text(state.friend.name);\n                    return AddFriendCard(state.friend, () async {\n                      // print(state.friend.phoneNumber);\n                      addFriendsBloc\n                          .add(AddButtonClickEvent(context, state.friend));\n                    });\n                  }\n                  if (state is HitUpIdNotExistsState) {\n                    return HitUpIdTextWidget(\n                      algo: algo,\n                      text: 'HitUp Id @${state.hitupId} not found!',\n                    );\n                  }\n                  return SizedBox(height: 10.0);\n                },\n              ),\n            ),\n            Column(\n              crossAxisAlignment: CrossAxisAlignment.start,\n              children: [\n                Text(\n                  'Friend Requests',\n                  style: kRequestTitleStyle,\n                ),\n                SizedBox(height: 6.0),\n                BlocBuilder<AddFriendsBloc, AddFriendsState>(\n                  builder: (context, state) {\n                    if (state is AcceptingFriendRequestState ||\n                        state is DecliningFriendRequestState) {\n                      return SearchingCard(algo: algo);\n                    }\n                    return _buildRequestsStreamBuilder(\n                        algo, RequestsType.FriendRequests, context);\n                  },\n                ),\n              ],\n            ),\n            SizedBox(height: 30.0),\n            Column(\n              crossAxisAlignment: CrossAxisAlignment.start,\n              children: [\n                Text(\n                  'Your Sent Requests',\n                  style: kRequestTitleStyle,\n                ),\n                SizedBox(height: 6.0),\n                _buildRequestsStreamBuilder(\n                  algo,\n                  RequestsType.SentRequests,\n                  context,\n                ),\n              ],\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    hitupIdController.dispose();\n    // addFriendsBloc.close();\n  }\n}\n\nclass SearchingCard extends StatelessWidget {\n  const SearchingCard({\n    Key key,\n    @required this.algo,\n  }) : super(key: key);\n\n  final double algo;\n\n  @override\n  Widget build(BuildContext context) {\n    return Card(\n      elevation: 5.0,\n      child: Container(\n        padding: EdgeInsets.symmetric(vertical: 3.0),\n        height: algo * 50.0,\n        child: Center(\n          child: CircularProgressIndicator(),\n        ),\n      ),\n    );\n  }\n}\n\nclass HitUpIdTextWidget extends StatelessWidget {\n  final double algo;\n  final String text;\n\n  HitUpIdTextWidget({\n    @required this.algo,\n    @required this.text,\n  });\n\n  @override\n  Widget build(BuildContext context) {\n    return Card(\n      elevation: 5.0,\n      child: Padding(\n        padding: const EdgeInsets.symmetric(vertical: 6.0, horizontal: 8.0),\n        child: Center(\n          child: Text(text,\n              textAlign: TextAlign.center,\n              style: TextStyle(\n                fontSize: algo * 20.0,\n                color: Constants.textStuffColor,\n              )),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/screens/chat_screen.dart",
    "content": "import 'dart:async';\nimport 'dart:io';\n\nimport 'package:cached_network_image/cached_network_image.dart';\nimport 'package:coocoo/screens/friend_profile_screen.dart';\nimport 'package:coocoo/blocs/chats/chat_bloc.dart';\nimport 'package:coocoo/constants.dart';\nimport 'package:coocoo/functions/UserDataFunction.dart';\nimport 'package:coocoo/models/ChatMessage.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/stateProviders/profilePicUrlState.dart';\nimport 'package:coocoo/widgets/ChatItemWidget.dart';\nimport 'package:coocoo/widgets/GradientSnackBar.dart';\nimport 'package:coocoo/widgets/ImageFullScreenWidget.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_bloc/flutter_bloc.dart';\nimport 'package:flutter_emoji/flutter_emoji.dart' as emj;\nimport 'package:flutter_neumorphic/flutter_neumorphic.dart';\nimport 'package:image_picker/image_picker.dart';\nimport 'package:provider/provider.dart';\n\nclass ChatScreen extends StatefulWidget {\n  final MyContact toContact;\n  ChatScreen(this.toContact);\n  @override\n  _ChatScreenState createState() => _ChatScreenState();\n}\n\nclass _ChatScreenState extends State<ChatScreen> {\n  var parser = emj.EmojiParser();\n  TextEditingController chatTextController = TextEditingController();\n  ChatBloc chatBloc;\n  UserDataFunction userDataFunction = UserDataFunction();\n  List<ChatMessage> allMessages = [];\n  ScrollController _scrollController;\n  final picker = ImagePicker();\n\n  Widget _buildSendButton(double algo) {\n    return Expanded(\n      child: InkWell(\n        onTap: () {\n          String tempChatId = widget.toContact.chatId;\n          String msgToSend = parser.unemojify(chatTextController.text);\n\n          chatBloc.add(SendMessageEvent(context, msgToSend, tempChatId));\n          userDataFunction.sendNotification(\n            toUid: widget.toContact.phoneNumber,\n            title: \"${widget.toContact.name}\",\n            content: msgToSend,\n          );\n          chatTextController.clear();\n        },\n        child: Neumorphic(\n          style: kCircleNeumorphicStyle,\n          child: CircleAvatar(\n            backgroundColor: Colors.white,\n            radius: algo * 33.0,\n            child: Neumorphic(\n              style: NeumorphicStyle(\n                shadowDarkColor: Colors.blueGrey,\n                boxShape: NeumorphicBoxShape.circle(),\n                depth: 4,\n                intensity: 0.7,\n                surfaceIntensity: 0.6,\n              ),\n              child: CircleAvatar(\n                radius: algo * 23.0,\n                backgroundColor: Colors.white,\n                child:\n                    Icon(Icons.send, color: Colors.blueGrey, size: algo * 26.0),\n              ),\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n\n  Widget _buildTypeMessageTextField() {\n    return Expanded(\n      flex: 5,\n      child: Row(\n        children: [\n          Expanded(\n            child: Neumorphic(\n              margin: EdgeInsets.only(left: 6, right: 5, top: 2, bottom: 4),\n              style: NeumorphicStyle(\n                depth: -15,\n                boxShape: NeumorphicBoxShape.stadium(),\n                shadowDarkColorEmboss: Colors.black,\n                shadowLightColor: Colors.white,\n                intensity: 0.6,\n              ),\n              padding: EdgeInsets.symmetric(vertical: 14, horizontal: 18),\n              child: TextField(\n                onTap: () {\n                  // scroll to the bottom of the list when keyboard appears\n                  Timer(\n                      Duration(milliseconds: 200),\n                      () => _scrollController.animateTo(\n                          _scrollController.position.maxScrollExtent,\n                          duration: Duration(milliseconds: 500),\n                          curve: Curves.easeIn));\n                },\n                focusNode: FocusNode(),\n                cursorColor: Colors.blueGrey,\n                controller: chatTextController,\n                style: TextStyle(\n                  fontSize: 21.0,\n                ),\n                decoration:\n                    InputDecoration.collapsed(hintText: \"Type a message\"),\n              ),\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n\n  Widget _buildContactProfilePicture(double algo) {\n    return GestureDetector(\n      onTap: () {\n        Navigator.push(\n            context,\n            MaterialPageRoute(\n                builder: (context) => ImageFullScreen(\n                    url: widget.toContact.photoUrl,\n                    tag: 'dash${widget.toContact.ind}')));\n      },\n      child: Hero(\n        tag: 'dash${widget.toContact.ind}',\n        child: Neumorphic(\n          style: kCircleNeumorphicStyle,\n          child: CircleAvatar(\n            radius: algo * 23.5,\n            backgroundImage:\n                CachedNetworkImageProvider(widget.toContact.photoUrl),\n          ),\n        ),\n      ),\n    );\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    chatBloc = BlocProvider.of<ChatBloc>(context);\n    chatBloc.add(LoadInitialMessagesEvent(widget.toContact.chatId));\n    _scrollController = ScrollController();\n  }\n\n  @override\n  void dispose() {\n    chatTextController.dispose();\n    _scrollController.dispose();\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    final double screenWidth = MediaQuery.of(context).size.width;\n    final double algo = screenWidth / perfectWidth;\n    return Scaffold(\n      backgroundColor: Colors.grey[200],\n      appBar: AppBar(\n        titleSpacing: 0.0,\n        automaticallyImplyLeading: false,\n        leading: GestureDetector(\n          onTap: () {\n            Navigator.pop(context);\n          },\n          child: Icon(\n            Icons.arrow_back,\n            color: Colors.blueGrey[700],\n          ),\n        ),\n        backgroundColor: Colors.white,\n        title: Row(\n          mainAxisAlignment: MainAxisAlignment.start,\n          children: [\n            _buildContactProfilePicture(algo),\n            SizedBox(width: algo * 13.0),\n            GestureDetector(\n              onTap: () {\n                Navigator.push(\n                    context,\n                    MaterialPageRoute(\n                        builder: (context) =>\n                            FriendProfileScreen(widget.toContact)));\n              },\n              child: Text(\n                widget.toContact.name,\n                style: TextStyle(\n                  color: Colors.blueGrey[700],\n                  fontSize: algo * 20.0,\n                  fontWeight: FontWeight.w600,\n                ),\n              ),\n            ),\n          ],\n        ),\n        actions: <Widget>[\n          GestureDetector(\n            onTap: () {\n              pickImage();\n            },\n            child: Icon(\n              Icons.attach_file,\n              color: Colors.blueGrey[700],\n              size: 30.0,\n            ),\n          ),\n          SizedBox(width: 5.0),\n          GestureDetector(\n            onTap: () {\n              Navigator.push(\n                  context,\n                  MaterialPageRoute(\n                      builder: (context) =>\n                          FriendProfileScreen(widget.toContact)));\n            },\n            child: Icon(\n              Icons.more_vert_sharp,\n              size: 30.0,\n            ),\n          ),\n          SizedBox(width: algo * 15.0),\n        ],\n      ),\n      body: Container(\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.spaceBetween,\n          children: [\n            Flexible(\n              child: BlocListener<ChatBloc, ChatState>(\n                listener: (context, state) {\n                  if (state is ReceivedMessageState) {\n                    if (state.chatMessages[0].chatId ==\n                        widget.toContact.chatId) {\n                      setState(() {\n                        allMessages = state.chatMessages;\n                      });\n                    }\n                  }\n                  if (state is InitialMessagesLoadedState) {\n                    setState(() {\n                      allMessages = state.chatMessages;\n                    });\n                  }\n\n                  // jump to the bottom of the screen when a new message arrives\n                  // also using a timer because we need to jump to the bottom\n                  // only after the new message is updated in the listview\n                  Timer(\n                      Duration(milliseconds: 600),\n                      () => _scrollController.animateTo(\n                          _scrollController.position.maxScrollExtent,\n                          duration: Duration(milliseconds: 200),\n                          curve: Curves.easeIn));\n                },\n                child: Padding(\n                  padding: EdgeInsets.symmetric(vertical: algo * 8.0),\n                  child: ListView.builder(\n                      controller: _scrollController,\n                      itemCount: allMessages.length,\n                      itemBuilder: (context, index) {\n                        return ChatItemWidget(allMessages[index]);\n                      }),\n                ),\n              ),\n            ),\n            Row(\n              children: [\n                _buildTypeMessageTextField(),\n                _buildSendButton(algo),\n              ],\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n\n  Future pickImage() async {\n    final pickedFile = await picker.getImage(source: ImageSource.gallery);\n    if (pickedFile != null) {\n      File tempFile = File(pickedFile.path);\n      chatBloc.add(SendImageEvent(context, tempFile, widget.toContact.chatId));\n      GradientSnackBar.showMessage(\n          context, \"Sending Your Beautiful Image...\", 2);\n      userDataFunction.sendNotification(\n        toUid: widget.toContact.phoneNumber,\n        title: \"You have New Messages\",\n        content: \"Click To View\",\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "lib/screens/contacts_screen.dart",
    "content": "import 'package:animated_bottom_navigation_bar/animated_bottom_navigation_bar.dart';\nimport 'package:coocoo/screens/ContactsHelpPage.dart';\nimport 'package:coocoo/screens/addFriends_screen.dart';\nimport 'package:coocoo/blocs/contacts/contacts_bloc.dart';\nimport 'package:coocoo/functions/UserDataFunction.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/widgets/ContactRowWidget.dart';\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_bloc/flutter_bloc.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\n\nimport '../constants.dart';\n\nclass ContactListPage extends StatefulWidget {\n  @override\n  State<StatefulWidget> createState() => _ContactListPageState();\n\n  const ContactListPage();\n}\n\nclass _ContactListPageState extends State<ContactListPage>\n    with SingleTickerProviderStateMixin {\n  ContactsBloc contactsBloc;\n  final TextEditingController usernameController = TextEditingController();\n  List<MyContact> contacts = [];\n  UserDataFunction userDataFunction;\n  bool refreshing = false;\n  Color stuffColor = Colors.blueGrey[700];\n  bool showSearchBar = false;\n  int _selectedIndex = 0;\n\n  AnimationController _animationController;\n  Animation<double> animation;\n  CurvedAnimation curve;\n\n  final iconList = <IconData>[\n    FontAwesomeIcons.addressBook,\n    // Icons.contacts,\n    // FontAwesomeIcons.solidAddressBook,\n    FontAwesomeIcons.userFriends,\n  ];\n\n  @override\n  void dispose() {\n    usernameController.dispose();\n    _animationController.dispose();\n    // contactsBloc.close();\n    super.dispose();\n  }\n\n  @override\n  void initState() {\n    userDataFunction = UserDataFunction();\n    contactsBloc = BlocProvider.of<ContactsBloc>(context);\n    contactsBloc.add(FetchContactsEvent());\n    super.initState();\n\n    final systemTheme = SystemUiOverlayStyle.light.copyWith(\n      systemNavigationBarColor: Colors.black,\n      systemNavigationBarIconBrightness: Brightness.light,\n    );\n    SystemChrome.setSystemUIOverlayStyle(systemTheme);\n\n    _animationController = AnimationController(\n      duration: Duration(seconds: 1),\n      vsync: this,\n    );\n    curve = CurvedAnimation(\n      parent: _animationController,\n      curve: Interval(\n        0.5,\n        1.0,\n        curve: Curves.fastOutSlowIn,\n      ),\n    );\n    animation = Tween<double>(\n      begin: 0,\n      end: 1,\n    ).animate(curve);\n\n    Future.delayed(\n      Duration(seconds: 1),\n      () => _animationController.forward(),\n    );\n  }\n\n  Widget _buildRefreshButton() {\n    return InkWell(\n      child: Icon(\n        Icons.refresh,\n        color: stuffColor,\n      ),\n      onTap: () async {\n        setState(() {\n          refreshing = true;\n        });\n        await userDataFunction.loadPhoneContactsV2(context);\n        await Future.delayed(Duration(seconds: 8));\n        contactsBloc.add(FetchContactsEvent());\n        setState(() {\n          refreshing = false;\n        });\n      },\n    );\n  }\n\n  Widget _buildRefreshing() {\n    return Container(\n      width: 20.0,\n      padding: EdgeInsets.symmetric(vertical: 18.0),\n      child: CircularProgressIndicator(\n        strokeWidth: 2.5,\n        backgroundColor: Colors.white,\n      ),\n    );\n  }\n\n  Widget _buildNormalAppBar(double screenWidth) {\n    return AppBar(\n      automaticallyImplyLeading: false,\n      leading: IconButton(\n        icon: Icon(\n          Icons.arrow_back,\n          color: stuffColor,\n        ),\n        onPressed: () {\n          Navigator.pop(context);\n        },\n      ),\n      backgroundColor: Colors.white,\n      title: Text(\n        'Select Contact',\n        style: TextStyle(\n            fontSize: (screenWidth / perfectWidth) * 22.0, color: stuffColor),\n      ),\n      actions: <Widget>[\n        refreshing ? _buildRefreshing() : _buildRefreshButton(),\n        SizedBox(width: 25.0),\n      ],\n    );\n  }\n\n  void _onItemTapped(int ind) {\n    setState(() {\n      _selectedIndex = ind;\n    });\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    final double screenWidth = MediaQuery.of(context).size.width;\n    return SafeArea(\n      child: Scaffold(\n        backgroundColor: Colors.grey[200],\n        appBar: _selectedIndex == 0 ? _buildNormalAppBar(screenWidth) : null,\n        floatingActionButton: FloatingActionButton(\n          elevation: 8,\n          backgroundColor: Colors.white,\n          child: Icon(\n            Icons.favorite,\n            size: 40.0,\n            color: Colors.black,\n          ),\n          onPressed: () {\n            _animationController.reset();\n            _animationController.forward();\n          },\n        ),\n        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,\n        bottomNavigationBar: AnimatedBottomNavigationBar(\n          elevation: 30.0,\n          activeColor: Colors.black,\n          splashColor: Colors.blueAccent,\n          backgroundColor: Colors.white,\n          icons: iconList,\n          iconSize: 30.0,\n          activeIndex: _selectedIndex,\n          inactiveColor: Colors.grey,\n          notchAndCornersAnimation: animation,\n          splashSpeedInMilliseconds: 300,\n          notchSmoothness: NotchSmoothness.softEdge,\n          gapLocation: GapLocation.center,\n          leftCornerRadius: 20,\n          rightCornerRadius: 20,\n          onTap: _onItemTapped,\n        ),\n        body: _selectedIndex == 0\n            ? BlocBuilder<ContactsBloc, ContactsState>(\n                builder: (context, state) {\n                if (state is FetchingContactsState) {\n                  print(\"Fetching Contacts\");\n                  return SizedBox(\n                    height: (MediaQuery.of(context).size.height),\n                    child: Center(child: CircularProgressIndicator()),\n                  );\n                }\n                if (state is FetchedContactsState) {\n                  contacts = state.contacts;\n                }\n                return ListView(\n                  children: <Widget>[\n                    Column(\n                      children: List.generate(\n                          contacts.length,\n                          (index) => ContactRowWidget(\n                                contact: contacts[index],\n                              )),\n                    ),\n                    Divider(thickness: 1.5),\n                    SizedBox(height: (screenWidth / perfectWidth) * 20.0),\n                    ListTile(\n                      leading: Icon(\n                        Icons.share,\n                        color: Colors.black,\n                      ),\n                      title: Text(\n                        'Invite Friends',\n                        style: TextStyle(\n                          fontSize: (screenWidth / perfectWidth) * 20.0,\n                          fontWeight: FontWeight.w400,\n                        ),\n                      ),\n                      onTap: () => userDataFunction.onShare(context),\n                    ),\n                    ListTile(\n                      leading: Icon(\n                        Icons.help,\n                        color: Colors.black,\n                      ),\n                      title: Text(\n                        'Contacts Help',\n                        style: TextStyle(\n                          fontSize: (screenWidth / perfectWidth) * 20.0,\n                          fontWeight: FontWeight.w400,\n                        ),\n                      ),\n                      onTap: () {\n                        Navigator.push(\n                            context,\n                            MaterialPageRoute(\n                                builder: (context) => ContactsHelpPage()));\n                      },\n                    ),\n                  ],\n                );\n              })\n            : AddFriendsScreen(),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/screens/enter_name_screen.dart",
    "content": "import 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/screens/update_profile.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/config/Paths.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:coocoo/widgets/NameTextField.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/painting.dart';\n\nclass EnterName extends StatefulWidget {\n  @override\n  _EnterNameState createState() => _EnterNameState();\n}\n\nclass _EnterNameState extends State<EnterName> {\n  final TextEditingController firstNameController = TextEditingController();\n  final TextEditingController lastNameController = TextEditingController();\n  final _formKey = GlobalKey<FormState>();\n  Firestore firestore = Firestore.instance;\n  bool isLoading = false;\n\n  Future<void> saveFullName(String firstname, String lastname) async {\n    String uid = SharedObjects.prefs.getString(Constants.sessionUid);\n    String fullName = '$firstname $lastname';\n\n    DocumentReference ref = firestore.collection(Paths.usersPath).document(\n        uid); //reference of the user's document node in database/users. This node is created using uid\n    var data = {'name': fullName};\n    await ref.setData(data, merge: true); // set the photourl, age and username\n    await SharedObjects.prefs.setString(Constants.fullName, fullName);\n  }\n\n  Widget buildLoadingScreen() {\n    return Center(\n      child: CircularProgressIndicator(),\n    );\n  }\n\n  Widget buildEnterNameScreen() {\n    return Padding(\n      padding: const EdgeInsets.symmetric(horizontal: 35.0, vertical: 40.0),\n      child: Form(\n        key: _formKey,\n        child: ListView(\n          children: [\n            Center(\n              child: Text(\"What's your name?\",\n                  style: TextStyle(\n                    fontSize: 25.0,\n                    fontWeight: FontWeight.w600,\n                  )),\n            ),\n            SizedBox(height: 8.0),\n            Column(\n              children: [\n                NameTextField(\n                  hintText: 'FIRST NAME',\n                  controller: firstNameController,\n                ),\n                NameTextField(\n                  hintText: 'LAST NAME',\n                  controller: lastNameController,\n                ),\n                SizedBox(height: 10.0),\n                Text(\"This name will appear when someone searches for you \"\n                    \"on HitUp\")\n              ],\n            ),\n            SizedBox(height: 40.0),\n            RaisedButton(\n              padding: EdgeInsets.symmetric(vertical: 8.0),\n              onPressed: () async {\n                if (_formKey.currentState.validate()) {\n                  setState(() {\n                    isLoading = true;\n                  });\n                  await saveFullName(\n                      firstNameController.text, lastNameController.text);\n                  Navigator.push(context,\n                      MaterialPageRoute(builder: (context) => UpdateProfile()));\n                  isLoading = false;\n                }\n              },\n              elevation: 10.0,\n              color: Colors.blueAccent[400],\n              child: Text(\n                \"NEXT\",\n                style: TextStyle(\n                    color: Colors.white, fontSize: 25.0, letterSpacing: 1.0),\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      body: isLoading ? buildLoadingScreen() : buildEnterNameScreen(),\n    );\n  }\n\n  @override\n  void dispose() {\n    firstNameController.dispose();\n    lastNameController.dispose();\n    super.dispose();\n  }\n}\n"
  },
  {
    "path": "lib/screens/friend_profile_screen.dart",
    "content": "import 'package:cached_network_image/cached_network_image.dart';\nimport 'package:coocoo/blocs/chats/chat_bloc.dart';\nimport 'package:coocoo/blocs/home/home_bloc.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/constants.dart';\nimport 'package:coocoo/managers/db_manager.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/widgets/DangerCard.dart';\nimport 'package:coocoo/widgets/ImageFullScreenWidget.dart';\nimport 'package:coocoo/widgets/ListTileProfile.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_bloc/flutter_bloc.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\n\nclass FriendProfileScreen extends StatefulWidget {\n  final MyContact friend;\n  FriendProfileScreen(this.friend);\n\n  @override\n  _FriendProfileScreenState createState() => _FriendProfileScreenState();\n}\n\nclass _FriendProfileScreenState extends State<FriendProfileScreen> {\n  ChatBloc chatBloc;\n  bool isBlocked = false;\n  TextEditingController changeNameController = TextEditingController();\n  final _formKey = GlobalKey<FormState>();\n  HomeBloc homeBloc;\n\n  Future<bool> _showPrompt(BuildContext context) async {\n    return (await showDialog(\n          context: context,\n          builder: (context) => AlertDialog(\n            title:\n                Text('Are you sure you want to block ${widget.friend.name}?'),\n            content:\n                Text(\"You won't be able to send or receive any messages from\"\n                    \" ${widget.friend.name}.\"),\n            actions: <Widget>[\n              FlatButton(\n                onPressed: () => Navigator.of(context).pop(false),\n                child: Text(\n                  'NO',\n                  style: TextStyle(\n                    fontWeight: FontWeight.bold,\n                  ),\n                ),\n              ),\n              FlatButton(\n                onPressed: () {\n                  chatBloc.add(BlockUserEvent(context, widget.friend.chatId));\n                  Navigator.of(context).pop(false);\n                },\n                child: Text(\n                  'YES',\n                  style: TextStyle(\n                    fontWeight: FontWeight.bold,\n                  ),\n                ),\n              ),\n            ],\n          ),\n        )) ??\n        false;\n  }\n\n  void updateIsBlocked() async {\n    bool temp = await DBManager.db.isBlocked(widget.friend.chatId);\n    setState(() {\n      isBlocked = temp;\n      print(isBlocked);\n    });\n  }\n\n  @override\n  void initState() {\n    chatBloc = BlocProvider.of<ChatBloc>(context);\n    updateIsBlocked();\n    super.initState();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    double screenWidth = MediaQuery.of(context).size.width;\n    double algo = screenWidth / perfectWidth;\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(\"Profile\"),\n      ),\n      body: Container(\n        width: double.infinity,\n        padding: EdgeInsets.symmetric(\n            vertical: algo * 10.0, horizontal: algo * 15.0),\n        child: Column(\n          crossAxisAlignment: CrossAxisAlignment.center,\n          children: [\n            GestureDetector(\n              onTap: () {\n                Navigator.push(\n                    context,\n                    MaterialPageRoute(\n                        builder: (context) =>\n                            ImageFullScreen(url: widget.friend.photoUrl)));\n              },\n              child: CircleAvatar(\n                radius: algo * 120.0,\n                backgroundColor: Colors.white,\n                backgroundImage:\n                    CachedNetworkImageProvider(widget.friend.photoUrl),\n              ),\n            ),\n            Spacer(\n              flex: 2,\n            ),\n            ListTileProfile(\n              iconData: FontAwesomeIcons.book,\n              title: 'Full Name',\n              subTitle: widget.friend.name,\n              trailingWidget: GestureDetector(\n                onTap: () {\n                  showModalBottomSheet(\n                    context: context,\n                    isScrollControlled: true,\n                    shape: RoundedRectangleBorder(\n                        borderRadius:\n                            BorderRadius.vertical(top: Radius.circular(20.0))),\n                    builder: (BuildContext context) {\n                      return Form(\n                        key: _formKey,\n                        child: Container(\n                          padding: EdgeInsets.only(\n                              bottom: MediaQuery.of(context).viewInsets.bottom,\n                              top: 10.0,\n                              left: 15.0,\n                              right: 15.0),\n                          child: Column(\n                            mainAxisSize: MainAxisSize.min,\n                            children: [\n                              Text(\n                                'Edit Name',\n                                style: TextStyle(\n                                  fontSize: 20.0,\n                                  fontWeight: FontWeight.w500,\n                                ),\n                              ),\n                              SizedBox(height: algo * 12.0),\n                              TextFormField(\n                                validator: (value) {\n                                  if (value.trim().isEmpty) {\n                                    return \"Please enter a valid Name\";\n                                  }\n                                  return null;\n                                },\n                                controller: changeNameController,\n                                style: TextStyle(\n                                  fontSize: algo * 18.0,\n                                ),\n                                autocorrect: false,\n                                cursorColor: Colors.blueGrey,\n                                decoration:\n                                    kHitUpIdTextFieldDecoration.copyWith(\n                                  hintText: 'New Name',\n                                ),\n                              ),\n                              SizedBox(height: algo * 8.0),\n                              FlatButton(\n                                onPressed: () async {\n                                  if (_formKey.currentState.validate()) {\n                                    Navigator.popUntil(\n                                        context, (route) => route.isFirst);\n                                    await DBManager.db.updateName(\n                                        changeNameController.text,\n                                        widget.friend.chatId);\n                                    homeBloc =\n                                        BlocProvider.of<HomeBloc>(context);\n                                    homeBloc.add(FetchHomeChatsEvent());\n                                  }\n                                },\n                                color: Constants.stuffColor,\n                                child: Text(\n                                  'DONE',\n                                  style: TextStyle(\n                                    color: Colors.white,\n                                    fontSize: algo * 22.0,\n                                    letterSpacing: 0.5,\n                                  ),\n                                ),\n                              ),\n                            ],\n                          ),\n                        ),\n                      );\n                    },\n                  );\n                },\n                child: Icon(\n                  Icons.edit,\n                  color: Constants.stuffColor,\n                ),\n              ),\n            ),\n            ListTileProfile(\n              iconData: FontAwesomeIcons.solidUser,\n              title: \"Username\",\n              subTitle: widget.friend.username,\n            ),\n            Spacer(\n              flex: 5,\n            ),\n            BlocListener<ChatBloc, ChatState>(\n              listener: (context, state) {\n                if (state is BlockedUserState) {\n                  setState(() {\n                    isBlocked = true;\n                  });\n                } else {\n                  setState(() {\n                    isBlocked = false;\n                  });\n                }\n              },\n              child: isBlocked\n                  ? DangerCard(Colors.green, 'UnBlock', () async {\n                      chatBloc\n                          .add(UnblockUserEvent(context, widget.friend.chatId));\n                    })\n                  : DangerCard(Colors.red, 'Block', () async {\n                      _showPrompt(context);\n                    }),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/screens/help_screen.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\n\nclass HelpScreen extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(\"Help\"),\n      ),\n      body: Container(\n        padding: const EdgeInsets.symmetric(vertical: 15.0, horizontal: 8.0),\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.spaceBetween,\n          children: [\n            Text(\n              \"For help with any issues, bugs or feature requests please write a review \"\n              \"on Google Play Store or directly contact us \"\n              \"at: \",\n              textAlign: TextAlign.center,\n              style: TextStyle(\n                fontSize: 20.0,\n                fontWeight: FontWeight.w400,\n              ),\n            ),\n            Column(\n              children: [\n                ContactMeCard(\n                  iconData: FontAwesomeIcons.envelope,\n                  title: 'digantakalita.ai@gmail.com',\n                ),\n                ContactMeCard(\n                  iconData: FontAwesomeIcons.instagram,\n                  title: '@digantakalita_real',\n                ),\n                ContactMeCard(\n                  iconData: FontAwesomeIcons.twitter,\n                  title: '@realdiganta',\n                ),\n                ContactMeCard(\n                  iconData: FontAwesomeIcons.whatsapp,\n                  title: '+91 1111111111',\n                ),\n                SizedBox(height: 10.0),\n                Text(\n                  \"If your messages are not being sent, just check your \"\n                  \"internet connection or restart the app,\"\n                  \" and it will start working fine af\",\n                  textAlign: TextAlign.center,\n                  style: TextStyle(\n                    fontSize: 17.0,\n                  ),\n                )\n              ],\n            ),\n            SizedBox(height: 20.0),\n            Text(\n              \"We typically reply within 4 hours\",\n              style: TextStyle(\n                fontSize: 18.0,\n                color: Colors.teal,\n                fontWeight: FontWeight.bold,\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n\nclass ContactMeCard extends StatelessWidget {\n  final IconData iconData;\n  final String title;\n\n  ContactMeCard({this.iconData, this.title});\n\n  @override\n  Widget build(BuildContext context) {\n    return Card(\n      elevation: 5.0,\n      child: ListTile(\n        leading: FaIcon(\n          iconData,\n          color: Colors.pinkAccent,\n        ),\n        title: Text(\n          title,\n          style: TextStyle(\n            fontWeight: FontWeight.w600,\n            fontSize: 19.0,\n            letterSpacing: 0.8,\n          ),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/screens/home_screen.dart",
    "content": "import 'dart:async';\n\nimport 'package:cached_network_image/cached_network_image.dart';\nimport 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/screens/contacts_screen.dart';\nimport 'package:coocoo/screens/profile_screen.dart';\nimport 'package:coocoo/screens/settings_screen.dart';\nimport 'package:coocoo/blocs/home/home_bloc.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/config/Paths.dart';\nimport 'package:coocoo/constants.dart';\nimport 'package:coocoo/models/Conversation.dart';\nimport 'package:coocoo/stateProviders/profilePicUrlState.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:coocoo/widgets/ChatCard.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_bloc/flutter_bloc.dart';\nimport 'package:flutter_neumorphic/flutter_neumorphic.dart';\nimport 'package:onesignal_flutter/onesignal_flutter.dart';\nimport 'package:provider/provider.dart';\n\nclass HomeScreen extends StatefulWidget {\n  @override\n  _HomeScreenState createState() => _HomeScreenState();\n}\n\nclass _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {\n  HomeBloc homeBloc;\n\n  List<Conversation> conversations;\n\n  void setUserNameAndNameIfNull() {\n    Firestore _firestore = Firestore.instance;\n    String uid = SharedObjects.prefs.getString(Constants.sessionUid);\n    String username = SharedObjects.prefs.getString(Constants.sessionUsername);\n    String fullName = SharedObjects.prefs.getString(Constants.fullName);\n\n    if (username == null || fullName == null) {\n      _firestore.collection(Paths.usersPath).document(uid).get().then((doc) {\n        SharedObjects.prefs\n            .setString(Constants.sessionUsername, doc.data[\"username\"]);\n        SharedObjects.prefs.setString(Constants.fullName, doc.data[\"name\"]);\n        SharedObjects.prefs.setString(\n            Constants.sessionProfilePictureUrl, doc.data[\"photoUrl\"]);\n      });\n    }\n  }\n\n  Future<bool> _onWillPop() async {\n    return (await showDialog(\n          context: context,\n          builder: (context) => AlertDialog(\n            title: Text('Are you sure?'),\n            content: Text('Do you want to exit the App'),\n            actions: <Widget>[\n              FlatButton(\n                onPressed: () => Navigator.of(context).pop(false),\n                child: Text('No'),\n              ),\n              FlatButton(\n                onPressed: () =>\n                    SystemChannels.platform.invokeMethod('SystemNavigator.pop'),\n                child: Text('Yes'),\n              ),\n            ],\n          ),\n        )) ??\n        false;\n  }\n\n  void initOneSignal() async {\n    await OneSignal.shared.init(\"98194ba4-9b9a-416b-ab0c-74b851af4f1a\",\n        iOSSettings: {\n          OSiOSSettings.autoPrompt: false,\n          OSiOSSettings.inAppLaunchUrl: false\n        });\n    await OneSignal.shared\n        .setInFocusDisplayType(OSNotificationDisplayType.notification);\n\n    final String myUid = SharedObjects.prefs.getString(Constants.sessionUid);\n    await OneSignal.shared.setExternalUserId(myUid);\n\n    OneSignal.shared.addTrigger('update', '1');\n  }\n\n  @override\n  void initState() {\n    WidgetsBinding.instance.addObserver(this);\n    initOneSignal();\n    homeBloc = BlocProvider.of<HomeBloc>(context);\n    super.initState();\n\n    // connecting to the mqtt server in the home page\n    homeBloc.add(ConnectToServerEvent(context));\n    setUserNameAndNameIfNull();\n    print(\"Home Screen Opened\");\n  }\n\n  @override\n  void didChangeAppLifecycleState(AppLifecycleState state) {\n    super.didChangeAppLifecycleState(state);\n    if (state == AppLifecycleState.paused) {\n      homeBloc.add(DisconnectEvent());\n    }\n    if (state == AppLifecycleState.resumed) {\n      homeBloc.add(ConnectToServerEvent(context));\n    }\n  }\n\n  @override\n  void dispose() {\n    WidgetsBinding.instance.removeObserver(this);\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    final double screenWidth = MediaQuery.of(context).size.width;\n    return WillPopScope(\n      onWillPop: _onWillPop,\n      child: Scaffold(\n        backgroundColor: Colors.grey[200],\n        floatingActionButton: FloatingActionButton(\n          onPressed: () {\n            Navigator.push(context,\n                MaterialPageRoute(builder: (context) => ContactListPage()));\n          },\n          backgroundColor: Colors.blueGrey[600],\n          elevation: 15.0,\n          child: Icon(\n            Icons.message,\n          ),\n        ),\n        body: SafeArea(\n          child: Container(\n            padding: EdgeInsets.only(top: 15.0, left: 15.0, right: 15.0),\n            child: Column(\n              children: <Widget>[\n                Row(\n                  children: [\n                    Text(\n                      'Chats',\n                      style: TextStyle(\n                        color: Colors.blueGrey[700],\n                        fontSize: (screenWidth / perfectWidth) * 30.0,\n                        fontWeight: FontWeight.w600,\n                      ),\n                    ),\n                    Spacer(\n                      flex: 10,\n                    ),\n                    GestureDetector(\n                      onTap: () {\n                        Navigator.push(\n                            context,\n                            MaterialPageRoute(\n                                builder: (context) => ProfileScreen()));\n                      },\n                      child: Padding(\n                        padding: EdgeInsets.symmetric(\n                            vertical: 3.0, horizontal: 15.0),\n                        child: Hero(\n                          tag: 'myProfile',\n                          child: Neumorphic(\n                            style: kCircleNeumorphicStyle,\n                            child: CircleAvatar(\n                              backgroundColor: Colors.white,\n                              radius: (screenWidth / perfectWidth) * 33.0,\n                              backgroundImage: CachedNetworkImageProvider(\n                                  context\n                                      .watch<ProfilePicUrlState>()\n                                      .profilePicUrl),\n                            ),\n                          ),\n                        ),\n                      ),\n                    ),\n                    GestureDetector(\n                      onTap: () {\n                        Navigator.push(\n                            context,\n                            MaterialPageRoute(\n                                builder: (context) => SettingsScreen()));\n                      },\n                      child: Icon(\n                        Icons.more_vert,\n                        size: (screenWidth / perfectWidth) * 30.0,\n                      ),\n                    ),\n                  ],\n                ),\n                SizedBox(height: 10.0),\n                Expanded(\n                    flex: 3,\n                    child: BlocBuilder<HomeBloc, HomeState>(\n                      builder: (context, state) {\n                        conversations = state.conversations;\n                        if (conversations.length > 0 &&\n                            conversations.isNotEmpty) {\n                          return ListView.builder(\n                              itemCount: conversations.length,\n                              itemBuilder: (context, index) {\n                                return ChatCard(conversations[index], index);\n                              });\n                        } else {\n                          return Center(child: Text(\"You have No Messages\"));\n                        }\n                      },\n                    ))\n              ],\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/screens/login_screen.dart",
    "content": "import 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/screens/otp_screen.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/functions/UserDataFunction.dart';\nimport 'package:coocoo/stateProviders/number_state.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:country_pickers/country.dart';\nimport 'package:country_pickers/country_pickers.dart';\nimport 'package:firebase_auth/firebase_auth.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:provider/provider.dart';\n\nclass Login extends StatefulWidget {\n  @override\n  _LoginState createState() => _LoginState();\n}\n\nclass _LoginState extends State<Login> {\n  final _formKey = GlobalKey<FormState>();\n  Firestore _firestore = Firestore.instance;\n  TextEditingController mobileNumberController = TextEditingController();\n  final FirebaseAuth _auth = FirebaseAuth.instance;\n  UserDataFunction userDataFunction = UserDataFunction();\n\n  String countryCode = '91';\n\n  // TODO: Handle the exception nicely here instead of just printing out the error\n  final PhoneVerificationFailed _verificationFailed =\n      (AuthException authException) {\n    print(authException.message);\n  };\n\n  Future<bool> _showContinueDialog() async {\n    return (await showDialog(\n          context: context,\n          builder: (context) => AlertDialog(\n            title: Text(\n                'We will be verifying the phone number: +$countryCode ${mobileNumberController.text}'),\n            content: Text('Is this OK, or would you like to edit the number?'),\n            actions: <Widget>[\n              FlatButton(\n                onPressed: () => Navigator.of(context).pop(false),\n                child: Text('EDIT'),\n              ),\n              FlatButton(\n                onPressed: () async {\n                  context.read<NumberState>().setPhoneNumber(\n                      \"$countryCode${mobileNumberController.text}\");\n                  await SharedObjects.prefs\n                      .setString(Constants.sessionCountryCode, countryCode);\n                  await userDataFunction.verifyPhoneNumber(\n                      context,\n                      '+$countryCode' + mobileNumberController.text.toString(),\n                      _verificationFailed);\n                  Navigator.push(context,\n                      MaterialPageRoute(builder: (context) => OTPScreen()));\n                },\n                child: Text('OK'),\n              ),\n            ],\n          ),\n        )) ??\n        false;\n  }\n\n  Widget _buildDropdownItem(Country country) => Container(\n        child: Row(\n          children: <Widget>[\n            CountryPickerUtils.getDefaultFlagImage(country),\n            SizedBox(\n              width: 8.0,\n            ),\n            Text(\"+${country.phoneCode} ${country.isoCode}\"),\n          ],\n        ),\n      );\n\n  @override\n  void dispose() {\n    mobileNumberController.dispose();\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      body: ChangeNotifierProvider<NumberState>(\n        create: (context) => NumberState(),\n        child: Form(\n          key: _formKey,\n          child: SafeArea(\n            child: Padding(\n              padding: EdgeInsets.symmetric(vertical: 35.0, horizontal: 22.0),\n              child: ListView(\n                children: <Widget>[\n                  Column(\n                    mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                    children: <Widget>[\n                      Column(\n                        children: <Widget>[\n                          Text(\n                            'Verify your phone number',\n                            style: TextStyle(\n                              color: Constants.textStuffColor,\n                              fontSize: 22.0,\n                              fontWeight: FontWeight.w600,\n                            ),\n                          ),\n                          SizedBox(height: 30.0),\n                          Text(\n                            'HitUp Messenger will send and SMS message (carrier charges may apply) to verify'\n                            ' your phone number. Enter your phone number.',\n                            style: TextStyle(\n                              fontSize: 16.0,\n                              fontWeight: FontWeight.w400,\n                            ),\n                            textAlign: TextAlign.center,\n                          ),\n                          SizedBox(height: 20.0),\n                          CountryPickerDropdown(\n                            initialValue: 'IN',\n                            itemBuilder: _buildDropdownItem,\n//                                itemFilter:  ['AR', 'DE', 'GB', 'CN'].contains(c.isoCode),\n                            sortComparator: (Country a, Country b) =>\n                                a.isoCode.compareTo(b.isoCode),\n                            onValuePicked: (Country country) {\n                              setState(() {\n                                countryCode = country.phoneCode;\n                              });\n                            },\n                          ),\n                          Padding(\n                            padding: EdgeInsets.symmetric(horizontal: 50.0),\n                            child: TextFormField(\n                              controller: mobileNumberController,\n                              maxLengthEnforced: true,\n                              maxLength: 10,\n                              cursorColor: Constants.stuffColor,\n                              style: TextStyle(fontSize: 20.0),\n                              keyboardType: TextInputType.number,\n                              textAlign: TextAlign.center,\n                              decoration: InputDecoration(\n                                hintText: 'Phone Number',\n                              ),\n                              inputFormatters: [\n                                FilteringTextInputFormatter.deny(\n                                    RegExp(r'\\s+')) // no spaces allowed\n                              ],\n                              validator: (value) {\n                                if (value.length != 10) {\n                                  return 'Please enter 10 digits';\n                                }\n                                return null;\n                              },\n                            ),\n                          ),\n                        ],\n                      ),\n                      RaisedButton(\n                        padding: EdgeInsets.symmetric(\n                            vertical: 8.0, horizontal: 30.0),\n                        color: Constants.stuffColor,\n                        child: Text(\n                          'NEXT',\n                          style: TextStyle(\n                            color: Colors.white,\n                            fontSize: 18.0,\n                            letterSpacing: 1.0,\n                          ),\n                        ),\n                        onPressed: () async {\n                          if (_formKey.currentState.validate()) {\n                            await _showContinueDialog();\n                          }\n                        },\n                      ),\n                    ],\n                  ),\n                ],\n              ),\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/screens/otp_screen.dart",
    "content": "import 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/screens/enter_name_screen.dart';\nimport 'package:coocoo/blocs/timer/timer_bloc.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/functions/MQTTFunction.dart';\nimport 'package:coocoo/functions/UserDataFunction.dart';\nimport 'package:coocoo/screens/home_screen.dart';\nimport 'package:coocoo/stateProviders/number_state.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:firebase_auth/firebase_auth.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_bloc/flutter_bloc.dart';\nimport 'package:permission_handler/permission_handler.dart';\nimport 'package:provider/provider.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\nclass OTPScreen extends StatefulWidget {\n  @override\n  _OTPScreenState createState() => _OTPScreenState();\n}\n\nclass _OTPScreenState extends State<OTPScreen> {\n  final _formKey = GlobalKey<FormState>();\n  TextEditingController otpController = TextEditingController();\n  FirebaseAuth _auth = FirebaseAuth.instance;\n  Firestore _firestore = Firestore.instance;\n  SharedPreferences loginData;\n\n  bool isVerifying = false;\n  UserDataFunction userDataFunction;\n  MQTTFunction mqttFunction;\n  bool showSpinner = false;\n  TimerBloc timerBLoc;\n  String minutesStr = '00';\n  String secondsStr = Constants.resendOtpTime.toString();\n\n  bool resendOtpSwitch = false;\n\n  // TODO: Handle the exception nicely here instead of just printing out the error\n  final PhoneVerificationFailed _verificationFailed =\n      (AuthException authException) {\n    print(authException.message);\n  };\n\n  Future<bool> _showWrongOTPDialog() async {\n    return (await showDialog(\n          context: context,\n          builder: (context) => AlertDialog(\n            title: Text('The code you entered was not correct'),\n            content: Text('Please enter the correct code!'),\n            actions: <Widget>[\n              FlatButton(\n                onPressed: () => Navigator.of(context).pop(false),\n                child: Text('TRY AGAIN'),\n              ),\n            ],\n          ),\n        )) ??\n        false;\n  }\n\n  Future<void> _signInWithPhoneNumber(String smsCode) async {\n    AuthCredential _authCredential = PhoneAuthProvider.getCredential(\n        verificationId: context.read<NumberState>().otp, smsCode: smsCode);\n\n    await _auth.signInWithCredential(_authCredential).catchError((error) {\n      _showWrongOTPDialog();\n      print(error);\n    }).then((AuthResult _authResult) async {\n      if (_authResult != null) {\n        setState(() {\n          isVerifying = true;\n        });\n        FirebaseUser currUser = _authResult.user;\n        print(currUser.phoneNumber);\n        String myPhoneNumber = currUser.phoneNumber.substring(1);\n        DocumentReference ref = _firestore.collection('users').document(\n            myPhoneNumber); //reference of the user's document node in database/users. This node is created using uid\n\n        await SharedObjects.prefs.setBool('login', false);\n        await SharedObjects.prefs\n            .setString(Constants.sessionUid, myPhoneNumber);\n\n        ref.get().then((doc) async {\n          if (doc.exists) {\n            String profilePhotoUrl = doc.data['photoUrl'];\n            String username = doc.data['username'];\n            SharedObjects.prefs\n                .setString(Constants.sessionProfilePictureUrl, profilePhotoUrl);\n            SharedObjects.prefs.setString(Constants.sessionUsername, username);\n\n            PermissionStatus currPermission =\n                await userDataFunction.askContactPermissions();\n\n            if (currPermission == PermissionStatus.granted) {\n              await userDataFunction.loadPhoneContactsV2(context);\n              isVerifying = false;\n              Navigator.push(context,\n                  MaterialPageRoute(builder: (context) => HomeScreen()));\n            } else {\n              setState(() {\n                isVerifying = false;\n              });\n            }\n          } else {\n            var data = {\n              //add details\n              'phoneNumber': myPhoneNumber,\n            };\n            ref.setData(data, merge: true);\n            isVerifying = false;\n            Navigator.push(\n                context, MaterialPageRoute(builder: (context) => EnterName()));\n          }\n        });\n      }\n    });\n  }\n\n  Widget _buildOTPScreen() {\n    return ChangeNotifierProvider<NumberState>(\n      create: (context) => NumberState(),\n      child: Form(\n        key: _formKey,\n        child: SafeArea(\n          child: Padding(\n            padding: EdgeInsets.symmetric(vertical: 35.0, horizontal: 25.0),\n            child: ListView(\n              children: <Widget>[\n                Column(\n                  mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                  children: <Widget>[\n                    Column(\n                      children: <Widget>[\n                        Text(\n                          'Verify +${context.watch<NumberState>().phoneNumber}',\n                          style: TextStyle(\n                            color: Constants.textStuffColor,\n                            fontSize: 22.0,\n                            fontWeight: FontWeight.w600,\n                          ),\n                        ),\n                        SizedBox(height: 30.0),\n                        Text(\n                          \"Please enter the 6-digit code sent to +${context.watch<NumberState>().phoneNumber}\",\n                          style: TextStyle(\n                            fontSize: 16.0,\n                            fontWeight: FontWeight.w400,\n                          ),\n                          textAlign: TextAlign.center,\n                        ),\n                        SizedBox(height: 20.0),\n                        Padding(\n                          padding: EdgeInsets.symmetric(horizontal: 50.0),\n                          child: TextFormField(\n                            controller: otpController,\n                            maxLengthEnforced: true,\n                            maxLength: 6,\n                            cursorColor: Constants.stuffColor,\n                            style: TextStyle(fontSize: 18.0),\n                            keyboardType: TextInputType.number,\n                            textAlign: TextAlign.center,\n                            decoration: InputDecoration(\n                              hintText: 'Enter 6-digit code',\n                            ),\n                          ),\n                        ),\n                      ],\n                    ),\n                    RaisedButton(\n                      padding:\n                          EdgeInsets.symmetric(vertical: 8.0, horizontal: 30.0),\n                      color: Constants.stuffColor,\n                      child: Text(\n                        'VERIFY',\n                        style: TextStyle(\n                          color: Colors.white,\n                          fontSize: 18.0,\n                          letterSpacing: 1.0,\n                        ),\n                      ),\n                      onPressed: () async {\n                        setState(() {\n                          showSpinner = true;\n                        });\n                        await _signInWithPhoneNumber(\n                            otpController.text.toString());\n                        setState(() {\n                          showSpinner = false;\n                        });\n                      },\n                    ),\n                    SizedBox(height: 15.0),\n                    Card(\n                      elevation: 5.0,\n                      child: ListTile(\n                          onTap: resendOtpSwitch\n                              ? () {\n                                  timerBLoc.add(StartTimerEvent());\n                                  setState(() {\n                                    resendOtpSwitch = false;\n                                  });\n                                  String phoneNum =\n                                      context.read<NumberState>().phoneNumber;\n                                  userDataFunction.verifyPhoneNumber(context,\n                                      '+$phoneNum', _verificationFailed);\n                                }\n                              : () {},\n                          leading: Icon(Icons.message,\n                              color:\n                                  resendOtpSwitch ? Colors.black : Colors.grey),\n                          title: Text(\n                            'Resend OTP',\n                            style: TextStyle(\n                              color:\n                                  resendOtpSwitch ? Colors.black : Colors.grey,\n                            ),\n                          ),\n                          trailing: BlocListener<TimerBloc, TimerState>(\n                            listener: (context, state) {\n                              if (state is TimerRunInProgressState) {\n                                setState(() {\n                                  secondsStr = (state.newTick % 60)\n                                      .floor()\n                                      .toString()\n                                      .padLeft(2, '0');\n                                });\n                              }\n\n                              if (state is TimerStoppedState) {\n                                setState(() {\n                                  resendOtpSwitch = true;\n                                });\n                              }\n                            },\n                            child: Text(\n                              '$minutesStr:$secondsStr',\n                            ),\n                          )),\n                    ),\n                  ],\n                ),\n              ],\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n\n  Widget _loadingScreen() {\n    return Center(\n      child: CircularProgressIndicator(),\n    );\n  }\n\n  @override\n  void initState() {\n    userDataFunction = UserDataFunction();\n    timerBLoc = BlocProvider.of<TimerBloc>(context);\n    timerBLoc.add(StartTimerEvent());\n    super.initState();\n  }\n\n  @override\n  void dispose() {\n    otpController.dispose();\n    timerBLoc.close();\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      body: isVerifying || showSpinner ? _loadingScreen() : _buildOTPScreen(),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/screens/profile_screen.dart",
    "content": "import 'dart:io';\n\nimport 'package:cached_network_image/cached_network_image.dart';\nimport 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/config/Paths.dart';\nimport 'package:coocoo/constants.dart';\nimport 'package:coocoo/functions/ChatFunction.dart';\nimport 'package:coocoo/stateProviders/profilePicUrlState.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:coocoo/widgets/ListTileProfile.dart';\nimport 'package:firebase_storage/firebase_storage.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_image_compress/flutter_image_compress.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\nimport 'package:image_picker/image_picker.dart';\nimport 'package:path/path.dart';\nimport 'package:path_provider/path_provider.dart';\nimport 'package:provider/provider.dart';\n\nclass ProfileScreen extends StatefulWidget {\n  @override\n  _ProfileScreenState createState() => _ProfileScreenState();\n}\n\nclass _ProfileScreenState extends State<ProfileScreen> {\n  final picker = ImagePicker();\n  File profileImageFile;\n  ImageProvider profileImage;\n  FirebaseStorage firebaseStorage = FirebaseStorage.instance;\n  Firestore fireStoreDb = Firestore.instance;\n  bool uploadingDp = false;\n  ChatFunction chatFunction;\n\n  @override\n  Widget build(BuildContext context) {\n    profileImage = CachedNetworkImageProvider(\n        context.watch<ProfilePicUrlState>().profilePicUrl);\n    double screenWidth = MediaQuery.of(context).size.width;\n    double algo = screenWidth / perfectWidth;\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(\"Profile\"),\n      ),\n      body: Container(\n        width: double.infinity,\n        padding: EdgeInsets.symmetric(\n            vertical: algo * 10.0, horizontal: algo * 15.0),\n        child: Column(\n          crossAxisAlignment: CrossAxisAlignment.center,\n          children: [\n            Stack(\n              children: [\n                Opacity(\n                  opacity: uploadingDp ? 0.5 : 1.0,\n                  child: Hero(\n                    tag: 'myProfile',\n                    child: CircleAvatar(\n                      radius: algo * 120.0,\n                      backgroundColor: Colors.white,\n                      backgroundImage: profileImage,\n                    ),\n                  ),\n                ),\n                Positioned.fill(\n                  child: Align(\n                    alignment: Alignment.center,\n                    child: uploadingDp\n                        ? CircularProgressIndicator(\n                            backgroundColor: Colors.white,\n                          )\n                        : Container(),\n                  ),\n                ),\n                Positioned(\n                  bottom: algo * 5.0,\n                  right: algo * 10.0,\n                  child: GestureDetector(\n                    onTap: () {\n                      pickImage(context);\n                    },\n                    child: CircleAvatar(\n                      backgroundColor: Colors.grey[200],\n                      radius: algo * 30.0,\n                      child: Icon(\n                        Icons.camera_alt,\n                        color: Colors.blueGrey,\n                        size: algo * 33.0,\n                      ),\n                    ),\n                  ),\n                )\n              ],\n            ),\n            Spacer(\n              flex: 2,\n            ),\n            ListTileProfile(\n              iconData: FontAwesomeIcons.solidUser,\n              title: 'Username',\n              subTitle:\n                  SharedObjects.prefs.getString(Constants.sessionUsername) ??\n                      \"\",\n            ),\n            ListTileProfile(\n              iconData: FontAwesomeIcons.book,\n              title: 'Full Name',\n              subTitle: SharedObjects.prefs.getString(Constants.fullName),\n            ),\n            ListTileProfile(\n              iconData: Icons.phone,\n              title: 'Phone Number',\n              subTitle: SharedObjects.prefs.getString(Constants.sessionUid),\n            ),\n            Spacer(\n              flex: 9,\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n\n  Future pickImage(BuildContext context) async {\n    final pickedFile = await picker.getImage(source: ImageSource.gallery);\n    if (pickedFile != null) {\n      profileImageFile = File(pickedFile.path);\n      setState(() {\n        uploadingDp = true;\n      });\n      String profileImageUrl =\n          await uploadFile(profileImageFile, Paths.profilePicturePath);\n      await saveProfilePicture(profileImageUrl, context);\n      setState(() {\n        uploadingDp = false;\n        profileImage = FileImage(profileImageFile);\n      });\n    }\n  }\n\n  Future<void> saveProfilePicture(\n      String profileImageUrl, BuildContext context) async {\n    String uid = SharedObjects.prefs.getString(Constants.sessionUid);\n\n    DocumentReference ref = fireStoreDb.collection(Paths.usersPath).document(\n        uid); //reference of the user's document node in database/users. This node is created using uid\n    var data = {\n      'photoUrl': profileImageUrl,\n    };\n    await ref.setData(data, merge: true); // set the photourl, age and username\n    await SharedObjects.prefs\n        .setString(Constants.sessionProfilePictureUrl, profileImageUrl);\n    context.read<ProfilePicUrlState>().setProfilePicUrl(profileImageUrl);\n\n    // notify my contacts devices that I have changed my DP\n    chatFunction = ChatFunction();\n    ref.get().then((snapshot) {\n      var chatIds = snapshot.data[\"chats\"];\n      String msgToSend =\n          '{\"msg\" : \"${Constants.profilePicChangeMsg}\", \"profilePicUrl\" : \"$profileImageUrl\",'\n          '\"uid\" : \"$uid\", \"type\" : \"service\"}';\n      chatIds.values.forEach((chatId) {\n        chatFunction.sendServiceMsgToServer(context, msgToSend, chatId);\n      });\n    });\n  }\n\n  // 2. compress file and get file.\n  Future<File> testCompressAndGetFile(File file, String username) async {\n    Directory tempDir = await getTemporaryDirectory();\n    String tempPath = tempDir.path;\n    var result = await FlutterImageCompress.compressAndGetFile(\n      file.absolute.path,\n      tempPath + \"/$username.jpg\",\n      minHeight: 500,\n      minWidth: 500,\n      quality: 80,\n    );\n    return result;\n  }\n\n  Future<String> uploadFile(File file, String path) async {\n    String username = SharedObjects.prefs.getString(Constants.sessionUsername);\n    file = await testCompressAndGetFile(file, username);\n\n    String fileName = basename(file.path);\n    final milliSecs = DateTime.now().millisecondsSinceEpoch;\n    StorageReference reference = firebaseStorage.ref().child(\n        '$path/$milliSecs\\_$fileName'); // get a reference to the path of the image directory\n    String uploadPath = await reference.getPath();\n    print('uploading to $uploadPath');\n    StorageUploadTask uploadTask =\n        reference.putFile(file); // put the file in the path\n    StorageTaskSnapshot result =\n        await uploadTask.onComplete; // wait for the upload to complete\n    String url = await result.ref\n        .getDownloadURL(); //retrieve the download link and return it\n    return url;\n  }\n}\n"
  },
  {
    "path": "lib/screens/settings_screen.dart",
    "content": "import 'package:coocoo/screens/account_screen.dart';\nimport 'package:coocoo/screens/help_screen.dart';\nimport 'package:coocoo/functions/UserDataFunction.dart';\nimport 'package:coocoo/widgets/SettingsTile.dart';\nimport 'package:flutter/material.dart';\n\nclass SettingsScreen extends StatelessWidget {\n  final UserDataFunction userDataFunction = UserDataFunction();\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text('Settings'),\n      ),\n      body: Column(\n        children: [\n          SettingsTile(\n            icon: Icons.settings,\n            title: 'Account',\n            onPress: () {\n              Navigator.push(context,\n                  MaterialPageRoute(builder: (context) => AccountScreen()));\n            },\n          ),\n          SettingsTile(\n            icon: Icons.help_outline,\n            title: 'Help',\n            onPress: () {\n              Navigator.push(context,\n                  MaterialPageRoute(builder: (context) => HelpScreen()));\n            },\n          ),\n          SettingsTile(\n            icon: Icons.supervisor_account,\n            title: 'Invite a Friend',\n            onPress: () => userDataFunction.onShare(context),\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/screens/update_profile.dart",
    "content": "import 'dart:io';\n\nimport 'package:cloud_firestore/cloud_firestore.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/config/Paths.dart';\nimport 'package:coocoo/functions/MQTTFunction.dart';\nimport 'package:coocoo/functions/UserDataFunction.dart';\nimport 'package:coocoo/screens/home_screen.dart';\nimport 'package:coocoo/stateProviders/profilePicUrlState.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:firebase_storage/firebase_storage.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:flutter_image_compress/flutter_image_compress.dart';\nimport 'package:image_picker/image_picker.dart';\nimport 'package:path/path.dart';\nimport 'package:path_provider/path_provider.dart';\nimport 'package:permission_handler/permission_handler.dart';\nimport 'package:provider/provider.dart';\n\nenum PageState { initial, updating }\n\nclass UpdateProfile extends StatefulWidget {\n  @override\n  _UpdateProfileState createState() => _UpdateProfileState();\n}\n\nclass _UpdateProfileState extends State<UpdateProfile> {\n  PageState profilePageState = PageState.initial;\n  UserDataFunction userDataFunction;\n  MQTTFunction mqttFunction;\n  final _formKey = GlobalKey<FormState>();\n\n  File profileImageFile;\n  ImageProvider profileImage = AssetImage('images/user.png');\n  final TextEditingController usernameController = TextEditingController();\n  FirebaseStorage firebaseStorage = FirebaseStorage.instance;\n  Firestore fireStoreDb = Firestore.instance;\n  final picker = ImagePicker();\n  String NoDpUrl =\n      \"https://firebasestorage.googleapis.com/v0/b/coocoo-private-fc1e0.appspot.com/o/user.png?alt=media&token=0572ebb8-630d-4468-b5e1-91fd4cc9e049\";\n\n  @override\n  void dispose() {\n    usernameController.dispose();\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      body: Form(\n        key: _formKey,\n        child: buildUpdateProfilePage(context),\n      ),\n    );\n  }\n\n  Widget buildUpdateProfilePage(BuildContext context) {\n    if (profilePageState == PageState.initial) {\n      return SafeArea(\n        child: Padding(\n          padding: EdgeInsets.symmetric(vertical: 35.0, horizontal: 15.0),\n          child: ListView(\n            children: <Widget>[\n              Column(\n                mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                children: <Widget>[\n                  Column(\n                    children: <Widget>[\n                      Text(\n                        'Profile Info',\n                        style: TextStyle(\n                          color: Constants.textStuffColor,\n                          fontSize: 22.0,\n                          fontWeight: FontWeight.w600,\n                        ),\n                      ),\n                      SizedBox(height: 30.0),\n                      Text(\n                        \"Please provide an username and a profile photo\",\n                        style: TextStyle(\n                          fontSize: 16.0,\n                          fontWeight: FontWeight.w400,\n                        ),\n                        textAlign: TextAlign.center,\n                      ),\n                      SizedBox(height: 20.0),\n                      Padding(\n                        padding: EdgeInsets.symmetric(horizontal: 10.0),\n                        child: Row(\n                          children: <Widget>[\n                            GestureDetector(\n                              onTap: pickImage,\n                              child: CircleAvatar(\n                                backgroundImage: profileImage,\n                                radius: 35,\n                              ),\n                            ),\n                            SizedBox(width: 10.0),\n                            Expanded(\n                              child: TextFormField(\n                                inputFormatters: [\n                                  FilteringTextInputFormatter.deny(\n                                      RegExp(r'\\s+')) // no spaces allowed\n                                ],\n                                validator: (value) {\n                                  if (value.isEmpty) {\n                                    return 'Please enter a valid username';\n                                  }\n                                  return null;\n                                },\n                                controller: usernameController,\n                                maxLengthEnforced: true,\n                                maxLength: 26,\n                                cursorColor: Constants.stuffColor,\n                                style: TextStyle(fontSize: 18.0),\n                                keyboardType: TextInputType.text,\n                                decoration: InputDecoration(\n                                  hintText: 'username',\n                                ),\n                              ),\n                            ),\n                          ],\n                        ),\n                      ),\n                    ],\n                  ),\n                  RaisedButton(\n                    padding:\n                        EdgeInsets.symmetric(vertical: 8.0, horizontal: 30.0),\n                    color: Constants.stuffColor,\n                    child: Text(\n                      'NEXT',\n                      style: TextStyle(\n                        color: Colors.white,\n                        fontSize: 18.0,\n                        letterSpacing: 1.0,\n                      ),\n                    ),\n                    onPressed: () async {\n                      if (_formKey.currentState.validate()) {\n                        setState(() {\n                          profilePageState = PageState.updating;\n                        });\n                        // set profile image\n                        if (profileImageFile != null) {\n                          String profilePictureUrl = await uploadFile(\n                              profileImageFile,\n                              Paths.profilePicturePath,\n                              usernameController.text);\n                          await saveProfileDetails(profilePictureUrl,\n                              usernameController.text, context);\n                        } else {\n                          await saveProfileDetails(\n                              NoDpUrl, usernameController.text, context);\n                        }\n\n                        // get contacts permission and load the phone contacts\n                        userDataFunction = UserDataFunction();\n                        PermissionStatus currPermission =\n                            await userDataFunction.askContactPermissions();\n                        if (currPermission == PermissionStatus.granted) {\n                          await userDataFunction.loadPhoneContactsV2(context);\n                          Navigator.push(\n                              context,\n                              MaterialPageRoute(\n                                  builder: (context) => HomeScreen()));\n                        } else {\n                          setState(() {\n                            profilePageState = PageState.initial;\n                          });\n                        }\n                      }\n                    },\n                  ),\n                ],\n              ),\n            ],\n          ),\n        ),\n      );\n    } else if (profilePageState == PageState.updating) {\n      return Center(\n        child: CircularProgressIndicator(),\n      );\n    }\n    return Center(\n      child: CircularProgressIndicator(),\n    );\n  }\n\n  Future<void> saveProfileDetails(\n      String profileImageUrl, String username, BuildContext context) async {\n    String uid = SharedObjects.prefs.getString(Constants.sessionUid);\n    print('Session UID of PROFILE : $uid');\n\n    DocumentReference ref = fireStoreDb.collection(Paths.usersPath).document(\n        uid); //reference of the user's document node in database/users. This node is created using uid\n    var data = {\n      'photoUrl': profileImageUrl,\n      'username': username,\n    };\n    await ref.setData(data, merge: true); // set the photourl, age and username\n    await SharedObjects.prefs.setString(Constants.sessionUsername, username);\n    await SharedObjects.prefs\n        .setString(Constants.sessionProfilePictureUrl, profileImageUrl);\n    context.read<ProfilePicUrlState>().setProfilePicUrl(profileImageUrl);\n  }\n\n  // 2. compress file and get file.\n  Future<File> testCompressAndGetFile(File file, String username) async {\n    Directory tempDir = await getTemporaryDirectory();\n    String tempPath = tempDir.path;\n    var result = await FlutterImageCompress.compressAndGetFile(\n      file.absolute.path,\n      tempPath + \"/$username.jpg\",\n      minHeight: 500,\n      minWidth: 500,\n      quality: 80,\n    );\n    return result;\n  }\n\n  Future<String> uploadFile(File file, String path, String username) async {\n    file = await testCompressAndGetFile(file, username);\n\n    String fileName = basename(file.path);\n    final milliSecs = DateTime.now().millisecondsSinceEpoch;\n    StorageReference reference = firebaseStorage.ref().child(\n        '$path/$milliSecs\\_$fileName'); // get a reference to the path of the image directory\n    String uploadPath = await reference.getPath();\n    print('uploading to $uploadPath');\n    StorageUploadTask uploadTask =\n        reference.putFile(file); // put the file in the path\n    StorageTaskSnapshot result =\n        await uploadTask.onComplete; // wait for the upload to complete\n    String url = await result.ref\n        .getDownloadURL(); //retrieve the download link and return it\n    return url;\n  }\n\n  Future pickImage() async {\n    final pickedFile = await picker.getImage(source: ImageSource.gallery);\n    print('Picked file path is : ' + pickedFile.path);\n    profileImageFile = File(pickedFile.path);\n    setState(() {\n      profileImage = FileImage(profileImageFile);\n    });\n  }\n}\n"
  },
  {
    "path": "lib/splashscreen.dart",
    "content": "import 'package:coocoo/screens/login_screen.dart';\nimport 'package:coocoo/functions/MQTTFunction.dart';\nimport 'package:coocoo/functions/UserDataFunction.dart';\nimport 'package:coocoo/screens/home_screen.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/rendering.dart';\nimport 'package:permission_handler/permission_handler.dart';\n\nclass SplashScreen extends StatefulWidget {\n  @override\n  _SplashScreenState createState() => _SplashScreenState();\n}\n\nclass _SplashScreenState extends State<SplashScreen> {\n  bool newUser;\n  UserDataFunction userDataFunction;\n  MQTTFunction mqttFunction;\n  String loggedInUser;\n\n  void checkIfAlreadyLogin(BuildContext context) async {\n    newUser = (SharedObjects.prefs.getBool('login') ?? true);\n    print(newUser);\n    if (newUser == false) {\n      userDataFunction = UserDataFunction();\n      PermissionStatus currPermission =\n          await userDataFunction.askContactPermissions();\n      if (currPermission == PermissionStatus.granted) {\n        // load Contacts here itself\n        await userDataFunction.loadPhoneContactsV2(context);\n        // wait a little time for loading\n        await Future.delayed(Duration(seconds: 2));\n        Navigator.pushReplacement(\n            context, MaterialPageRoute(builder: (context) => HomeScreen()));\n      } else {\n        Navigator.push(\n            context, MaterialPageRoute(builder: (context) => Login()));\n      }\n    } else {\n      Navigator.push(context, MaterialPageRoute(builder: (context) => Login()));\n    }\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    WidgetsBinding.instance\n        .addPostFrameCallback((_) => checkIfAlreadyLogin(context));\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return SafeArea(\n      child: Scaffold(\n        body: Container(\n          child: Center(\n            child: Padding(\n              padding: EdgeInsets.symmetric(vertical: 22.0),\n              child: Container(\n                padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0),\n                width: 140.0,\n                height: 140.0,\n                decoration: BoxDecoration(\n                  boxShadow: [\n                    BoxShadow(\n                      color: Colors.blueGrey,\n                      offset: Offset(2.5, 3.5), //(x,y)\n                      blurRadius: 2.5,\n                    ),\n                  ],\n                  color: Colors.blueGrey[100],\n                  borderRadius: BorderRadius.only(\n                    topRight: Radius.circular(40.0),\n                    bottomLeft: Radius.circular(40.0),\n                  ),\n                ),\n                child: Center(\n                    child: Icon(\n                  Icons.favorite,\n                  size: 80.0,\n                )),\n              ),\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/stateProviders/mqtt_state.dart",
    "content": "import 'package:coocoo/managers/mqtt_manager.dart';\nimport 'package:flutter/material.dart';\n\nclass MQTTState with ChangeNotifier {\n  MQTTManager _manager;\n  Map<String, String> _lastSenderMap = {};\n  Map<String, String> _lastMsgMap = {};\n\n  MQTTManager get manager => _manager;\n\n  String getLastSender(String chatId) {\n    return _lastSenderMap[chatId];\n  }\n\n  String getLastMsg(String chatId) {\n    return _lastMsgMap[chatId];\n  }\n\n  void setLastSender(String chatId, String newSender) {\n    _lastSenderMap[chatId] = newSender;\n  }\n\n  void setLastMsg(String chatId, String newMsg) {\n    _lastMsgMap[chatId] = newMsg;\n  }\n\n  void setNewManager(MQTTManager newManager) {\n    if (_manager == null) {\n      _manager = newManager;\n    }\n    notifyListeners();\n  }\n}\n"
  },
  {
    "path": "lib/stateProviders/number_state.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass NumberState with ChangeNotifier {\n  String _otp;\n  String _phoneNumber;\n  String _username;\n\n  String get otp => _otp;\n  String get phoneNumber => _phoneNumber;\n  String get username => _username;\n\n  void setOTP(String newValue) {\n    _otp = newValue;\n    notifyListeners();\n  }\n\n  void setPhoneNumber(String newphoneNumber) {\n    _phoneNumber = newphoneNumber;\n    notifyListeners();\n  }\n}\n"
  },
  {
    "path": "lib/stateProviders/profilePicUrlState.dart",
    "content": "import 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/utils/SharedObjects.dart';\nimport 'package:flutter/material.dart';\n\nString NoDpUrl =\n    \"https://firebasestorage.googleapis.com/v0/b/coocoo-private-fc1e0.appspot.com/o/user.png?alt=media&token=0572ebb8-630d-4468-b5e1-91fd4cc9e049\";\n\nclass ProfilePicUrlState with ChangeNotifier {\n  String _profilePicUrl =\n      SharedObjects.prefs.getString(Constants.sessionProfilePictureUrl) ??\n          NoDpUrl;\n\n  String get profilePicUrl => _profilePicUrl;\n\n  void setProfilePicUrl(String newUrl) {\n    _profilePicUrl = newUrl;\n    notifyListeners();\n  }\n}\n"
  },
  {
    "path": "lib/utils/Exceptions.dart",
    "content": "abstract class CooCooException implements Exception {\n  String errorMessage();\n}\n\nclass UserNotFoundException extends CooCooException {\n  @override\n  String errorMessage() => 'No user found for provided uid/username';\n}\n\nclass UsernameMappingUndefinedException extends CooCooException {\n  @override\n  String errorMessage() => 'User not found';\n}\n\nclass ContactAlreadyExistsException extends CooCooException {\n  @override\n  String errorMessage() => 'MyContact already exists!';\n}\n"
  },
  {
    "path": "lib/utils/SharedObjects.dart",
    "content": "import 'package:coocoo/config/Constants.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\nclass SharedObjects {\n  static CachedSharedPreferences prefs;\n}\n\nclass CachedSharedPreferences {\n  static SharedPreferences sharedPreferences;\n  static CachedSharedPreferences instance;\n  static final cachedKeyList = {\n    Constants.firstRun,\n    Constants.sessionUid,\n    Constants.sessionUsername,\n    Constants.fullName,\n    Constants.sessionName,\n    Constants.sessionProfilePictureUrl,\n    Constants.configDarkMode,\n    Constants.sessionCountryCode\n  };\n  static final sessionKeyList = {\n    Constants.sessionName,\n    Constants.fullName,\n    Constants.sessionUid,\n    Constants.sessionUsername,\n    Constants.sessionProfilePictureUrl,\n    Constants.sessionCountryCode,\n  };\n\n  static Map<String, dynamic> map = Map();\n\n  static Future<CachedSharedPreferences> getInstance() async {\n    sharedPreferences = await SharedPreferences.getInstance();\n    if (sharedPreferences.getBool(Constants.firstRun) == null ||\n        sharedPreferences.get(Constants.firstRun)) {\n      // if first run, then set these values\n      await sharedPreferences.setBool(Constants.configDarkMode, false);\n      await sharedPreferences.setBool(Constants.firstRun, false);\n    }\n    for (String key in cachedKeyList) {\n      map[key] = sharedPreferences.get(key);\n    }\n    if (instance == null) instance = CachedSharedPreferences();\n    return instance;\n  }\n\n  String getString(String key) {\n    if (cachedKeyList.contains(key)) {\n      return map[key];\n    }\n    return sharedPreferences.getString(key);\n  }\n\n  bool getBool(String key) {\n    if (cachedKeyList.contains(key)) {\n      return map[key];\n    }\n    return sharedPreferences.getBool(key);\n  }\n\n  Future<bool> setString(String key, String value) async {\n    bool result = await sharedPreferences.setString(key, value);\n    if (result) map[key] = value;\n    return result;\n  }\n\n  Future<bool> setBool(String key, bool value) async {\n    bool result = await sharedPreferences.setBool(key, value);\n    if (result) map[key] = value;\n    return result;\n  }\n\n  Future<void> clearAll() async {\n    await sharedPreferences.clear();\n    map = Map();\n  }\n\n  Future<void> clearSession() async {\n    await sharedPreferences.remove(Constants.sessionProfilePictureUrl);\n    await sharedPreferences.remove(Constants.sessionUsername);\n    await sharedPreferences.remove(Constants.fullName);\n    await sharedPreferences.remove(Constants.sessionUid);\n    await sharedPreferences.remove(Constants.sessionName);\n    await sharedPreferences.remove(Constants.sessionCountryCode);\n    map.removeWhere((k, v) => (sessionKeyList.contains(k)));\n  }\n}\n"
  },
  {
    "path": "lib/widgets/AddFriendCard.dart",
    "content": "import 'package:cached_network_image/cached_network_image.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/constants.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/widgets/ImageFullScreenWidget.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_emoji/flutter_emoji.dart';\nimport 'package:flutter_neumorphic/flutter_neumorphic.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\n\nclass AddFriendCard extends StatelessWidget {\n  final MyContact friend;\n  final Function addFunc;\n  final parser = EmojiParser();\n\n  AddFriendCard(this.friend, this.addFunc);\n\n  @override\n  Widget build(BuildContext context) {\n    final double screenWidth = MediaQuery.of(context).size.width;\n    double algo = screenWidth / perfectWidth;\n    return Card(\n      elevation: 10.0,\n      child: ListTile(\n        leading: GestureDetector(\n          onTap: () {\n            Navigator.push(\n                context,\n                MaterialPageRoute(\n                    builder: (context) =>\n                        ImageFullScreen(url: friend.photoUrl)));\n          },\n          child: CircleAvatar(\n            backgroundColor: Colors.white,\n            radius: (screenWidth / perfectWidth) * 28.0,\n            backgroundImage: CachedNetworkImageProvider(friend.photoUrl),\n          ),\n        ),\n        title: Text(\n          parser.emojify(friend.name),\n          style: TextStyle(\n            fontWeight: FontWeight.bold,\n            fontSize: (screenWidth / perfectWidth) * 17.0,\n          ),\n        ),\n        subtitle: Text(\n          '@${friend.username}',\n          style: TextStyle(\n            fontSize: (screenWidth / perfectWidth) * 14.0,\n          ),\n        ),\n        trailing: GestureDetector(\n          onTap: addFunc,\n          child: Card(\n              elevation: 5.0,\n              color: Colors.grey[200],\n              child: Padding(\n                padding: EdgeInsets.symmetric(\n                    horizontal: algo * 15.0, vertical: algo * 3.0),\n                child: Row(\n                  mainAxisSize: MainAxisSize.min,\n                  children: [\n                    FaIcon(\n                      FontAwesomeIcons.userPlus,\n                      size: algo * 20.0,\n                      color: Constants.textStuffColor,\n                    ),\n                    SizedBox(\n                      width: algo * 5.0,\n                    ),\n                    Text(\n                      'Add',\n                      style: TextStyle(\n                        fontWeight: FontWeight.w500,\n                        color: Constants.textStuffColor,\n                        fontSize: 18.0,\n                      ),\n                    )\n                  ],\n                ),\n              )),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/widgets/ChatCard.dart",
    "content": "import 'package:cached_network_image/cached_network_image.dart';\nimport 'package:coocoo/constants.dart';\nimport 'package:coocoo/models/Conversation.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/screens/chat_screen.dart';\nimport 'package:coocoo/widgets/ImageFullScreenWidget.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/rendering.dart';\nimport 'package:flutter_emoji/flutter_emoji.dart';\nimport 'package:flutter_neumorphic/flutter_neumorphic.dart';\nimport 'package:intl/intl.dart';\n\nclass ChatCard extends StatelessWidget {\n  final Conversation conversation;\n  final int ind;\n  final parser = EmojiParser();\n\n  ChatCard(this.conversation, this.ind);\n\n  Widget buildMessage(String msgType, TextStyle chatTextStyle) {\n    if (msgType == 'text') {\n      return Text(\n        parser.emojify(conversation.lastMessage),\n        style: chatTextStyle,\n      );\n    } else {\n      return Align(\n        alignment: Alignment.centerLeft,\n        child: Icon(\n          Icons.image,\n          color: Colors.blueAccent,\n          size: 30.0,\n        ),\n      );\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    double screenWidth = MediaQuery.of(context).size.width;\n    final TextStyle kChatTextStyle =\n        Theme.of(context).textTheme.bodyText2.copyWith(\n              fontWeight: FontWeight.w400,\n              fontSize: (screenWidth / perfectWidth) * 15.0,\n            );\n    final TextStyle kTimeTextStyle =\n        Theme.of(context).textTheme.bodyText2.copyWith(\n              fontWeight: FontWeight.w300,\n              fontSize: (screenWidth / perfectWidth) * 13.0,\n            );\n    final TextStyle kTitleTextStyle =\n        Theme.of(context).textTheme.headline6.copyWith(\n              color: Colors.black,\n              fontWeight: FontWeight.bold,\n              fontSize: (screenWidth / perfectWidth) * 20.0,\n            );\n    final currTime = DateFormat()\n        .add_MMMd()\n        .add_jm()\n        .format(DateTime.fromMillisecondsSinceEpoch(conversation.time));\n\n    return Padding(\n      padding: const EdgeInsets.only(bottom: 12.0),\n      child: Neumorphic(\n        style: NeumorphicStyle(\n          shadowDarkColor: Colors.blueGrey,\n          lightSource: LightSource.topRight,\n          color: Colors.white,\n          depth: 4,\n          intensity: 0.8,\n        ),\n        child: ListTile(\n          contentPadding: EdgeInsets.symmetric(vertical: 3.0, horizontal: 8.0),\n          onTap: () {\n            Navigator.push(\n                context,\n                MaterialPageRoute(\n                    builder: (context) => ChatScreen(MyContact(\n                          phoneNumber: conversation.phoneNumber,\n                          name: conversation.name,\n                          photoUrl: conversation.photoUrl,\n                          chatId: conversation.chatId,\n                          username: conversation.username,\n                          ind: ind,\n                        ))));\n          },\n          leading: GestureDetector(\n            onTap: () {\n              Navigator.push(\n                  context,\n                  MaterialPageRoute(\n                      builder: (context) => ImageFullScreen(\n                          url: conversation.photoUrl, tag: \"dash$ind\")));\n            },\n            child: Hero(\n              tag: \"dash$ind\",\n              child: Neumorphic(\n                style: kChatCircleNeumorphicStyle,\n                child: CircleAvatar(\n                  backgroundColor: Colors.white,\n                  radius: (screenWidth / perfectWidth) * 28.0,\n                  backgroundImage:\n                      CachedNetworkImageProvider(conversation.photoUrl),\n                ),\n              ),\n            ),\n          ),\n          title: Text(\n            parser.emojify(conversation.name),\n            style: kTitleTextStyle,\n          ),\n          subtitle: buildMessage(conversation.msgType, kChatTextStyle),\n          trailing: Text(\n            currTime,\n            style: kTimeTextStyle,\n          ),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/widgets/ChatItemWidget.dart",
    "content": "import 'dart:convert';\n\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/models/ChatMessage.dart';\nimport 'package:coocoo/widgets/ImageFullScreenWidget.dart';\nimport 'package:flutter/material.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\nimport 'package:intl/intl.dart';\nimport 'package:flutter_emoji/flutter_emoji.dart' as emj;\n\nclass ChatItemWidget extends StatelessWidget {\n  final ChatMessage message;\n  final parser = emj.EmojiParser();\n\n  ChatItemWidget(this.message);\n\n  final Color selfMessageColor = Colors.white;\n  final Color otherMessageColor = Colors.black;\n\n  final Color selfMessageBackgroundColor = Constants.textStuffColor;\n  final Color otherMessageBackgroundColor = Colors.white;\n\n  @override\n  Widget build(BuildContext context) {\n    return Container(\n      child: Column(\n        children: [\n          buildMessageContainer(\n              message.isSelf, message.msg, context, message.msgType),\n          buildTimeStamp(context, message.isSelf, message.time.toString())\n        ],\n      ),\n    );\n  }\n\n  Widget buildMessageBody(\n      String msgBody, String msgType, bool isSelf, BuildContext context) {\n    if (msgType == 'text' || msgType == null) {\n      return Text(\n        parser.emojify(\"${msgBody ?? ''}\"),\n        style: TextStyle(\n          color: isSelf ? selfMessageColor : otherMessageColor,\n          fontSize: 15.0,\n        ),\n      );\n    } else {\n      // it is an image\n      try {\n        return GestureDetector(\n          onTap: () {\n            Navigator.push(\n                context,\n                MaterialPageRoute(\n                    builder: (context) => ImageFullScreen(\n                          memoryImage: msgBody,\n                        )));\n          },\n          child: Container(\n            width: 95.0,\n            height: 25.0,\n            child: Row(\n              mainAxisAlignment: MainAxisAlignment.center,\n              children: [\n                FaIcon(\n                  FontAwesomeIcons.play,\n                  color: isSelf ? Colors.white : Colors.black,\n                  size: 22.0,\n                ),\n                SizedBox(width: 8.0),\n                Text(\n                  \"Photo\",\n                  style: TextStyle(\n                    color: isSelf ? Colors.white : Colors.black,\n                    fontSize: 19.0,\n                    letterSpacing: 1.0,\n                    fontWeight: FontWeight.w500,\n                  ),\n                ),\n              ],\n            ),\n          ),\n        );\n      } catch (e) {\n        return Container();\n      }\n    }\n  }\n\n  Row buildMessageContainer(\n      bool isSelf, String msgBody, BuildContext context, String msgType) {\n    double lrEdgeInsets = 15.0;\n    double tbEdgeInsets = 10.0;\n\n    return Row(\n      children: <Widget>[\n        Container(\n          child: buildMessageBody(msgBody, msgType, isSelf, context),\n          padding: EdgeInsets.fromLTRB(\n              lrEdgeInsets, tbEdgeInsets, lrEdgeInsets, tbEdgeInsets),\n          constraints: BoxConstraints(maxWidth: 300.0),\n          decoration: BoxDecoration(\n              color: isSelf\n                  ? selfMessageBackgroundColor\n                  : otherMessageBackgroundColor,\n              borderRadius: BorderRadius.only(\n                bottomLeft: Radius.circular(8.0),\n                bottomRight: Radius.circular(8.0),\n                topLeft: isSelf ? Radius.circular(8.0) : Radius.zero,\n                topRight: isSelf ? Radius.zero : Radius.circular(8.0),\n              ),\n              border: Border.all(color: Colors.grey)),\n          margin:\n              EdgeInsets.only(right: isSelf ? 5.0 : 0, left: isSelf ? 0 : 5.0),\n        )\n      ],\n      mainAxisAlignment: isSelf\n          ? MainAxisAlignment.end\n          : MainAxisAlignment.start, // aligns the chatitem to right end\n    );\n  }\n\n  Row buildTimeStamp(BuildContext context, bool isSelf, String timeStamp) {\n    final currTime = DateFormat()\n        .add_y()\n        .add_MMMd()\n        .add_jm()\n        .format(DateTime.fromMillisecondsSinceEpoch(int.parse(timeStamp)));\n    return Row(\n        mainAxisAlignment:\n            isSelf ? MainAxisAlignment.end : MainAxisAlignment.start,\n        children: <Widget>[\n          Container(\n            child: Text(\n              currTime,\n              style: Theme.of(context).textTheme.caption,\n            ),\n            margin: EdgeInsets.only(\n                left: isSelf ? 5.0 : 4.0,\n                right: isSelf ? 4.0 : 5.0,\n                top: 3.0,\n                bottom: 6.0),\n          )\n        ]);\n  }\n}\n"
  },
  {
    "path": "lib/widgets/ContactCard.dart",
    "content": "import 'package:cached_network_image/cached_network_image.dart';\nimport 'package:coocoo/constants.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_emoji/flutter_emoji.dart';\nimport 'package:flutter_neumorphic/flutter_neumorphic.dart';\n\nclass ContactCard extends StatelessWidget {\n  final String name;\n  final String status;\n  final String profilePic;\n  final parser = EmojiParser();\n\n  ContactCard({\n    @required this.name,\n    @required this.profilePic,\n    this.status,\n  });\n\n  @override\n  Widget build(BuildContext context) {\n    final double screenWidth = MediaQuery.of(context).size.width;\n    return ListTile(\n      leading: CircleAvatar(\n        backgroundColor: Colors.white,\n        radius: (screenWidth / perfectWidth) * 18.0,\n        backgroundImage: CachedNetworkImageProvider(profilePic),\n      ),\n      title: Text(\n        parser.emojify(name),\n        style: TextStyle(\n          fontWeight: FontWeight.bold,\n          fontSize: (screenWidth / perfectWidth) * 17.0,\n        ),\n      ),\n      subtitle: Text(\n        status,\n        style: TextStyle(\n          fontSize: (screenWidth / perfectWidth) * 14.0,\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/widgets/ContactRowWidget.dart",
    "content": "import 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/screens/chat_screen.dart';\nimport 'package:coocoo/widgets/ContactCard.dart';\nimport 'package:flutter/material.dart';\n\n// ignore: must_be_immutable\nclass ContactRowWidget extends StatelessWidget {\n  ContactRowWidget({\n    Key key,\n    @required this.contact,\n  }) : super(key: key);\n  final MyContact contact;\n\n  @override\n  Widget build(BuildContext context) {\n    return InkWell(\n        onTap: () {\n          Navigator.push(\n              context,\n              MaterialPageRoute(\n                builder: (context) => ChatScreen(contact),\n              ));\n        },\n        child: ContactCard(\n          name: contact.name,\n          profilePic: contact.photoUrl,\n          status: '@${contact.username ?? contact.phoneNumber}',\n        ));\n  }\n}\n"
  },
  {
    "path": "lib/widgets/DangerCard.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\n\nclass DangerCard extends StatelessWidget {\n  final String title;\n  final Function func;\n  final Color color;\n\n  DangerCard(this.color, this.title, this.func);\n\n  @override\n  Widget build(BuildContext context) {\n    return Card(\n      elevation: 5.0,\n      child: ListTile(\n        title: Text(\n          title,\n          style: TextStyle(\n            fontWeight: FontWeight.w600,\n            color: color,\n            fontSize: 15.0,\n          ),\n        ),\n        leading: FaIcon(FontAwesomeIcons.skullCrossbones, color: color),\n        onTap: func,\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/widgets/FriendRequestCard.dart",
    "content": "import 'package:cached_network_image/cached_network_image.dart';\nimport 'package:coocoo/blocs/AddFriends/add_friends_bloc.dart';\nimport 'package:coocoo/constants.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/widgets/ImageFullScreenWidget.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_emoji/flutter_emoji.dart';\nimport 'package:flutter_neumorphic/flutter_neumorphic.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\n\nclass FriendRequestCard extends StatelessWidget {\n  final MyContact friend;\n  final parser = EmojiParser();\n  final AddFriendsBloc addFriendsBloc;\n  final BuildContext contex;\n\n  FriendRequestCard(this.friend, this.addFriendsBloc, this.contex);\n\n  Future<bool> _showPrompt(BuildContext context) async {\n    return (await showDialog(\n          context: context,\n          builder: (context) => AlertDialog(\n            title: Text('Please Confirm'),\n            content: Text(\n                'Do you want to decline friend request from ${friend.name} ?'),\n            actions: <Widget>[\n              FlatButton(\n                onPressed: () => Navigator.of(context).pop(false),\n                child: Text(\n                  'NO',\n                  style: TextStyle(\n                    fontWeight: FontWeight.bold,\n                  ),\n                ),\n              ),\n              FlatButton(\n                onPressed: () {\n                  addFriendsBloc\n                      .add(DeclineFriendRequestEvent(friend.phoneNumber));\n                  Navigator.of(context).pop(false);\n                },\n                child: Text(\n                  'YES',\n                  style: TextStyle(\n                    fontWeight: FontWeight.bold,\n                  ),\n                ),\n              ),\n            ],\n          ),\n        )) ??\n        false;\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    final double screenWidth = MediaQuery.of(context).size.width;\n    return Card(\n      elevation: 5.0,\n      child: ListTile(\n        leading: GestureDetector(\n          onTap: () {\n            Navigator.push(\n                context,\n                MaterialPageRoute(\n                    builder: (context) =>\n                        ImageFullScreen(url: friend.photoUrl)));\n          },\n          child: CircleAvatar(\n            backgroundColor: Colors.white,\n            radius: (screenWidth / perfectWidth) * 28.0,\n            backgroundImage: CachedNetworkImageProvider(friend.photoUrl),\n          ),\n        ),\n        title: Text(\n          parser.emojify(friend.name),\n          style: TextStyle(\n            fontWeight: FontWeight.bold,\n            fontSize: (screenWidth / perfectWidth) * 17.0,\n          ),\n        ),\n        subtitle: Text(\n          '@${friend.username}',\n          style: TextStyle(\n            fontSize: (screenWidth / perfectWidth) * 14.0,\n          ),\n        ),\n        trailing: Row(\n          mainAxisSize: MainAxisSize.min,\n          children: [\n            GestureDetector(\n              onTap: () {\n                addFriendsBloc\n                    .add(AcceptFriendRequestEvent(friend.phoneNumber, contex));\n              },\n              child: Neumorphic(\n                style: kCircleNeumorphicStyle.copyWith(\n                  depth: 5.0,\n                ),\n                child: CircleAvatar(\n                  backgroundColor: Colors.green[500],\n                  child: FaIcon(\n                    FontAwesomeIcons.check,\n                    color: Colors.white,\n                  ),\n                ),\n              ),\n            ),\n            SizedBox(width: (screenWidth / perfectWidth) * 20.0),\n            GestureDetector(\n              onTap: () async {\n                await _showPrompt(context);\n              },\n              child: Neumorphic(\n                style: kCircleNeumorphicStyle.copyWith(\n                  depth: 5.0,\n                ),\n                child: CircleAvatar(\n                  backgroundColor: Colors.red,\n                  child: FaIcon(\n                    FontAwesomeIcons.times,\n                    color: Colors.white,\n                  ),\n                ),\n              ),\n            )\n          ],\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/widgets/GradientSnackBar.dart",
    "content": "import 'package:flushbar/flushbar.dart';\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\n\nclass GradientSnackBar {\n  static void showMessage(\n      BuildContext context, String message, int secondsDuration) {\n    Flushbar(\n      message: message,\n      duration: Duration(seconds: secondsDuration),\n      backgroundGradient: LinearGradient(\n          begin: Alignment.bottomLeft,\n          end: Alignment.bottomRight,\n          colors: [Colors.green, Colors.blueAccent]),\n      backgroundColor: Colors.red,\n      boxShadows: [\n        BoxShadow(\n          color: Colors.blue[800],\n          offset: Offset(0.0, 2.0),\n          blurRadius: 3.0,\n        )\n      ],\n    )..show(context);\n  }\n\n  static void showError(BuildContext context, String error) {\n    Flushbar(\n      message: error,\n      duration: Duration(milliseconds: 1500),\n      backgroundGradient: LinearGradient(\n          begin: Alignment.center,\n          end: Alignment.bottomRight,\n          colors: [\n            Colors.red[700],\n            Colors.blueGrey,\n          ]),\n      backgroundColor: Colors.red,\n      boxShadows: [\n        BoxShadow(\n          color: Colors.blue[800],\n          offset: Offset(0.0, 2.0),\n          blurRadius: 3.0,\n        )\n      ],\n    )..show(context);\n  }\n}\n"
  },
  {
    "path": "lib/widgets/ImageFullScreenWidget.dart",
    "content": "import 'dart:convert';\n\nimport 'package:cached_network_image/cached_network_image.dart';\nimport 'package:flutter/material.dart';\n\nclass ImageFullScreen extends StatelessWidget {\n  final String url;\n  final String tag;\n  final String memoryImage;\n  ImageFullScreen({this.url, this.tag, this.memoryImage});\n\n  Widget _buildImage() {\n    if (memoryImage != null) {\n      return Image(\n        image: MemoryImage(base64Decode(memoryImage)),\n      );\n    } else {\n      return tag != null\n          ? Hero(tag: tag, child: CachedNetworkImage(imageUrl: url))\n          : CachedNetworkImage(\n              imageUrl: url,\n            );\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Stack(\n      children: [\n        Positioned(\n          left: 12.0,\n          top: 10.0,\n          child: GestureDetector(\n            onTap: () {\n              Navigator.of(context).pop();\n            },\n            child: Icon(\n              Icons.arrow_back,\n              color: Colors.white,\n              size: 40.0,\n            ),\n          ),\n        ),\n        Align(\n          alignment: Alignment.center,\n          child: Container(\n            color: Colors.black,\n            child: _buildImage(),\n          ),\n        ),\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/widgets/ListTileProfile.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass ListTileProfile extends StatelessWidget {\n  final IconData iconData;\n  final String title;\n  final String subTitle;\n  final Widget trailingWidget;\n\n  ListTileProfile(\n      {this.iconData, this.title, this.subTitle, this.trailingWidget});\n\n  @override\n  Widget build(BuildContext context) {\n    return Card(\n      elevation: 10.0,\n      child: ListTile(\n        leading: Icon(\n          iconData,\n          color: Colors.blueGrey,\n        ),\n        title: Text(\n          title,\n          style: TextStyle(\n            fontSize: 14.0,\n            color: Colors.grey[600],\n          ),\n        ),\n        subtitle: Text(\n          subTitle,\n          style: TextStyle(\n            fontSize: 20.0,\n            color: Colors.black,\n          ),\n        ),\n        trailing: trailingWidget,\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/widgets/NameTextField.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\n\nclass NameTextField extends StatelessWidget {\n  final String hintText;\n  final TextEditingController controller;\n\n  NameTextField({this.hintText, this.controller});\n\n  @override\n  Widget build(BuildContext context) {\n    return Padding(\n      padding: const EdgeInsets.symmetric(vertical: 8.0),\n      child: TextFormField(\n        inputFormatters: [\n          FilteringTextInputFormatter.deny(RegExp(r'\\s+')) // no spaces allowed\n        ],\n        validator: (value) {\n          if (value.trim().isEmpty) {\n            return 'Please enter a valid $hintText';\n          }\n          return null;\n        },\n        controller: controller,\n        style: TextStyle(\n          fontSize: 18.0,\n        ),\n        decoration: InputDecoration(\n          hintText: hintText,\n          contentPadding: EdgeInsets.only(bottom: -15.0),\n          focusedBorder: UnderlineInputBorder(\n            borderSide: BorderSide(\n              color: Colors.black,\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/widgets/NoRequestsCard.dart",
    "content": "import 'package:coocoo/config/Constants.dart';\nimport 'package:flutter/material.dart';\n\nclass NoRequestsCard extends StatelessWidget {\n  final double algo;\n  final String text;\n\n  NoRequestsCard({\n    @required this.algo,\n    @required this.text,\n  });\n\n  @override\n  Widget build(BuildContext context) {\n    return Card(\n      elevation: 5.0,\n      child: Padding(\n        padding: const EdgeInsets.symmetric(vertical: 25.0, horizontal: 8.0),\n        child: Center(\n          child: Text(text,\n              textAlign: TextAlign.center,\n              style: TextStyle(\n                fontSize: algo * 20.0,\n                color: Constants.textStuffColor,\n              )),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/widgets/NonContactCard.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:share/share.dart';\n\nclass NonContactCard extends StatelessWidget {\n  final String name;\n\n  NonContactCard(\n    this.name,\n  );\n\n  @override\n  Widget build(BuildContext context) {\n    return ListTile(\n      leading: CircleAvatar(\n        backgroundColor: Colors.white,\n        radius: 18.0,\n        backgroundImage: AssetImage('images/user.png'),\n      ),\n      title: Text(\n        name,\n        style: TextStyle(\n          fontWeight: FontWeight.bold,\n          fontSize: 15.0,\n        ),\n      ),\n      trailing: FlatButton(\n        child: Text(\n          'Invite',\n          style: TextStyle(\n            color: Colors.white,\n          ),\n        ),\n        color: Colors.green,\n        onPressed: () => _onShare(context),\n      ),\n    );\n  }\n\n  _onShare(BuildContext context) async {\n    // A builder is used to retrieve the context immediately\n    // surrounding the RaisedButton.\n    //\n    // The context's `findRenderObject` returns the first\n    // RenderObject in its descendent tree when it's not\n    // a RenderObjectWidget. The RaisedButton's RenderObject\n    // has its position and size after it's built.\n    final RenderBox box = context.findRenderObject();\n    await Share.share(\n        \"https://play.google.com/store/apps/details?id=com.digantakalita.coocoo\",\n        subject: \"Lets have our private chats on\"\n            \"this New Cool Messenger HitUp from now on. Its way safer than the others.\",\n        sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);\n  }\n}\n"
  },
  {
    "path": "lib/widgets/SentRequestCard.dart",
    "content": "import 'package:cached_network_image/cached_network_image.dart';\nimport 'package:coocoo/config/Constants.dart';\nimport 'package:coocoo/constants.dart';\nimport 'package:coocoo/models/MyContact.dart';\nimport 'package:coocoo/widgets/ImageFullScreenWidget.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_emoji/flutter_emoji.dart';\nimport 'package:flutter_neumorphic/flutter_neumorphic.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\n\nclass SentRequestCard extends StatelessWidget {\n  final MyContact friend;\n  final parser = EmojiParser();\n\n  SentRequestCard(this.friend);\n\n  Future<bool> _showContinueDialog(BuildContext context) async {\n    return (await showDialog(\n          context: context,\n          builder: (context) => AlertDialog(\n            title: Text('Friend Request Pending'),\n            content: Text(\n                '${friend.name} has not accepted your friend request yet.'),\n            actions: <Widget>[\n              FlatButton(\n                onPressed: () => Navigator.of(context).pop(false),\n                child: Text(\n                  'OK',\n                  style: TextStyle(\n                    fontWeight: FontWeight.bold,\n                  ),\n                ),\n              ),\n            ],\n          ),\n        )) ??\n        false;\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    final double screenWidth = MediaQuery.of(context).size.width;\n    double algo = screenWidth / perfectWidth;\n    return Card(\n      elevation: 1.0,\n      child: ListTile(\n        onTap: () async {\n          await _showContinueDialog(context);\n        },\n        leading: GestureDetector(\n          onTap: () {\n            Navigator.push(\n                context,\n                MaterialPageRoute(\n                    builder: (context) =>\n                        ImageFullScreen(url: friend.photoUrl)));\n          },\n          child: CircleAvatar(\n            backgroundColor: Colors.white,\n            radius: (screenWidth / perfectWidth) * 28.0,\n            backgroundImage: CachedNetworkImageProvider(friend.photoUrl),\n          ),\n        ),\n        title: Text(\n          parser.emojify(friend.name),\n          style: TextStyle(\n            fontWeight: FontWeight.bold,\n            fontSize: (screenWidth / perfectWidth) * 17.0,\n          ),\n        ),\n        subtitle: Text(\n          '@${friend.username}',\n          style: TextStyle(\n            fontSize: (screenWidth / perfectWidth) * 14.0,\n          ),\n        ),\n        trailing: Card(\n            elevation: 2.0,\n            color: Colors.grey[200],\n            child: Padding(\n              padding: EdgeInsets.symmetric(\n                  horizontal: algo * 15.0, vertical: algo * 3.0),\n              child: Row(\n                mainAxisSize: MainAxisSize.min,\n                children: [\n                  Stack(\n                    clipBehavior: Clip.none,\n                    children: [\n                      Positioned(\n                        right: algo * 17.0,\n                        top: algo * 4.0,\n                        child: FaIcon(\n                          FontAwesomeIcons.check,\n                          size: algo * 10.0,\n                          color: Constants.textStuffColor,\n                        ),\n                      ),\n                      FaIcon(\n                        FontAwesomeIcons.solidUser,\n                        size: algo * 20.0,\n                        color: Constants.textStuffColor,\n                      ),\n                    ],\n                  ),\n                  SizedBox(\n                    width: algo * 5.0,\n                  ),\n                  Text(\n                    'Sent',\n                    style: TextStyle(\n                      fontWeight: FontWeight.w500,\n                      color: Constants.textStuffColor,\n                      fontSize: 18.0,\n                    ),\n                  )\n                ],\n              ),\n            )),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/widgets/SettingsTile.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass SettingsTile extends StatelessWidget {\n  final IconData icon;\n  final String title;\n  final Function onPress;\n\n  SettingsTile({@required this.icon, @required this.title, this.onPress});\n\n  @override\n  Widget build(BuildContext context) {\n    return Card(\n      elevation: 5.0,\n      child: ListTile(\n        title: Text(\n          title,\n          style: TextStyle(\n            fontWeight: FontWeight.w500,\n          ),\n        ),\n        leading: Icon(icon, color: Colors.blueGrey),\n        onTap: onPress,\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "pubspec.yaml",
    "content": "name: coocoo\ndescription: A Private Chat Messenger\n\n# The following line prevents the package from being accidentally published to\n# pub.dev using `pub publish`. This is preferred for private packages.\npublish_to: 'none' # Remove this line if you wish to publish to pub.dev\n\n# The following defines the version and build number for your application.\n# A version number is three numbers separated by dots, like 1.2.43\n# followed by an optional build number separated by a +.\n# Both the version and the builder number may be overridden in flutter\n# build by specifying --build-name and --build-number, respectively.\n# In Android, build-name is used as versionName while build-number used as versionCode.\n# Read more about Android versioning at https://developer.android.com/studio/publish/versioning\n# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.\n# Read more about iOS versioning at\n# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html\nversion: 1.2.6+7\n\nenvironment:\n  sdk: \">=2.7.0 <3.0.0\"\n\ndependencies:\n  flutter:\n    sdk: flutter\n\n\n  # The following adds the Cupertino Icons font to your application.\n  # Use with the CupertinoIcons class for iOS style icons.\n  cupertino_icons: ^0.1.3\n  provider: ^4.1.2\n  firebase_auth: ^0.16.1\n  cloud_firestore: ^0.13.7\n  mqtt_client: ^7.1.0\n  contacts_service: ^0.4.6\n  permission_handler: ^5.0.1\n  image_picker: ^0.6.7+4\n  firebase_storage: ^3.0.6\n  shared_preferences: ^0.5.3+4\n  flutter_bloc: ^6.1.0\n  equatable: ^1.2.5\n  cached_network_image: ^2.2.0+1\n  sqflite: ^1.3.1\n  path: ^1.7.0\n  intl: ^0.16.1\n  flutter_neumorphic: ^3.0.1\n  country_pickers: ^1.3.0\n  font_awesome_flutter: ^8.8.1\n  onesignal_flutter: ^2.6.1\n  flutter_image_compress: ^0.7.0\n  path_provider: ^1.6.14\n  flushbar: ^1.10.4\n  share: ^0.6.5\n  flutter_emoji: ^2.2.1+1\n  animated_bottom_navigation_bar: ^0.1.2+2\n\ndev_dependencies:\n  flutter_test:\n    sdk: flutter\n\n# For information on the generic Dart part of this file, see the\n# following page: https://dart.dev/tools/pub/pubspec\n\n# The following section is specific to Flutter.\nflutter:\n\n  # The following line ensures that the Material Icons font is\n  # included with your application, so that you can use the icons in\n  # the material Icons class.\n  uses-material-design: true\n\n  # To add assets to your application, add an assets section, like this:\n  assets:\n    - images/\n  #   - images/a_dot_ham.jpeg\n\n  # An image asset can refer to one or more resolution-specific \"variants\", see\n  # https://flutter.dev/assets-and-images/#resolution-aware.\n\n  # For details regarding adding assets from package dependencies, see\n  # https://flutter.dev/assets-and-images/#from-packages\n\n  # To add custom fonts to your application, add a fonts section here,\n  # in this \"flutter\" section. Each entry in this list should have a\n  # \"family\" key with the font family name, and a \"fonts\" key with a\n  # list giving the asset and other descriptors for the font. For\n  # example:\n#  fonts:\n#    - family: NotoColorEmoji\n#      fonts:\n#        - asset: fonts/\n  #       - asset: fonts/Schyler-Italic.ttf\n  #         style: italic\n  #   - family: Trajan Pro\n  #     fonts:\n  #       - asset: fonts/TrajanPro.ttf\n  #       - asset: fonts/TrajanPro_Bold.ttf\n  #         weight: 700\n  #\n  # For details regarding fonts from package dependencies,\n  # see https://flutter.dev/custom-fonts/#from-packages\n"
  },
  {
    "path": "test/widget_test.dart",
    "content": "// This is a basic Flutter widget test.\n//\n// To perform an interaction with a widget in your test, use the WidgetTester\n// utility that Flutter provides. For example, you can send tap and scroll\n// gestures. You can also use WidgetTester to find child widgets in the widget\n// tree, read text, and verify that the values of widget properties are correct.\n\nimport 'package:flutter/material.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\nimport 'package:coocoo/main.dart';\n\nvoid main() {\n  testWidgets('Counter increments smoke test', (WidgetTester tester) async {\n    // Build our app and trigger a frame.\n    await tester.pumpWidget(MyApp());\n\n    // Verify that our counter starts at 0.\n    expect(find.text('0'), findsOneWidget);\n    expect(find.text('1'), findsNothing);\n\n    // Tap the '+' icon and trigger a frame.\n    await tester.tap(find.byIcon(Icons.add));\n    await tester.pump();\n\n    // Verify that our counter has incremented.\n    expect(find.text('0'), findsNothing);\n    expect(find.text('1'), findsOneWidget);\n  });\n}\n"
  }
]