[
  {
    "path": ".firebaserc",
    "content": "{\n  \"projects\": {\n    \"default\": \"letschat-31c80\"\n  }\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "# Files for the ART/Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\nout/\n\n# Gradle files\n.gradle/\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Log Files\n*.log\n\n# Android Studio Navigation editor temp files\n.navigation/\n\n# Android Studio captures folder\ncaptures/\n\n# Intellij\n*.iml\n.idea/workspace.xml\n.idea/tasks.xml\n.idea/gradle.xml\n.idea/dictionaries\n.idea/libraries\n\n# Keystore files\n*.jks\n\n# External native build folder generated in Android Studio 2.2 and later\n.externalNativeBuild\n\n\n# Freeline\nfreeline.py\nfreeline/\nfreeline_project_description.json\n"
  },
  {
    "path": ".idea/assetWizardSettings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"WizardSettings\">\n    <option name=\"children\">\n      <map>\n        <entry key=\"imageWizard\">\n          <value>\n            <PersistentState>\n              <option name=\"children\">\n                <map>\n                  <entry key=\"imageAssetPanel\">\n                    <value>\n                      <PersistentState>\n                        <option name=\"children\">\n                          <map>\n                            <entry key=\"actionbar\">\n                              <value>\n                                <PersistentState>\n                                  <option name=\"children\">\n                                    <map>\n                                      <entry key=\"clipArt\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                                <entry key=\"imagePath\" value=\"/tmp/ic_android_black_24dp.xml\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"text\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"textAsset\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                    </map>\n                                  </option>\n                                </PersistentState>\n                              </value>\n                            </entry>\n                            <entry key=\"launcher\">\n                              <value>\n                                <PersistentState>\n                                  <option name=\"children\">\n                                    <map>\n                                      <entry key=\"foregroundClipArt\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"imagePath\" value=\"/tmp/ic_android_black_24dp.xml\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"foregroundImage\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                                <entry key=\"imagePath\" value=\"$USER_HOME$/Downloads/send.png\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"foregroundText\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"foregroundTextAsset\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                    </map>\n                                  </option>\n                                  <option name=\"values\">\n                                    <map>\n                                      <entry key=\"backgroundAssetType\" value=\"COLOR\" />\n                                    </map>\n                                  </option>\n                                </PersistentState>\n                              </value>\n                            </entry>\n                            <entry key=\"launcherLegacy\">\n                              <value>\n                                <PersistentState>\n                                  <option name=\"children\">\n                                    <map>\n                                      <entry key=\"clipArt\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                                <entry key=\"imagePath\" value=\"/tmp/ic_android_black_24dp.xml\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"text\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"textAsset\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                    </map>\n                                  </option>\n                                </PersistentState>\n                              </value>\n                            </entry>\n                            <entry key=\"notification\">\n                              <value>\n                                <PersistentState>\n                                  <option name=\"children\">\n                                    <map>\n                                      <entry key=\"clipArt\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                                <entry key=\"imagePath\" value=\"/tmp/ic_android_black_24dp.xml\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"image\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                                <entry key=\"imagePath\" value=\"$USER_HOME$/Downloads/send.png\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"text\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"textAsset\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                    </map>\n                                  </option>\n                                  <option name=\"values\">\n                                    <map>\n                                      <entry key=\"assetType\" value=\"IMAGE\" />\n                                      <entry key=\"imageAsset\" value=\"$USER_HOME$/Downloads/send.png\" />\n                                    </map>\n                                  </option>\n                                </PersistentState>\n                              </value>\n                            </entry>\n                            <entry key=\"tvBanner\">\n                              <value>\n                                <PersistentState>\n                                  <option name=\"children\">\n                                    <map>\n                                      <entry key=\"foregroundText\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                    </map>\n                                  </option>\n                                </PersistentState>\n                              </value>\n                            </entry>\n                            <entry key=\"tvChannel\">\n                              <value>\n                                <PersistentState>\n                                  <option name=\"children\">\n                                    <map>\n                                      <entry key=\"foregroundClipArt\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"imagePath\" value=\"/tmp/ic_android_black_24dp.xml\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"foregroundImage\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"foregroundText\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                      <entry key=\"foregroundTextAsset\">\n                                        <value>\n                                          <PersistentState>\n                                            <option name=\"values\">\n                                              <map>\n                                                <entry key=\"color\" value=\"000000\" />\n                                              </map>\n                                            </option>\n                                          </PersistentState>\n                                        </value>\n                                      </entry>\n                                    </map>\n                                  </option>\n                                </PersistentState>\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                        <option name=\"values\">\n                          <map>\n                            <entry key=\"outputIconType\" value=\"NOTIFICATION\" />\n                          </map>\n                        </option>\n                      </PersistentState>\n                    </value>\n                  </entry>\n                </map>\n              </option>\n            </PersistentState>\n          </value>\n        </entry>\n        <entry key=\"vectorWizard\">\n          <value>\n            <PersistentState>\n              <option name=\"children\">\n                <map>\n                  <entry key=\"vectorAssetStep\">\n                    <value>\n                      <PersistentState>\n                        <option name=\"children\">\n                          <map>\n                            <entry key=\"clipartAsset\">\n                              <value>\n                                <PersistentState>\n                                  <option name=\"values\">\n                                    <map>\n                                      <entry key=\"url\" value=\"jar:file:/home/quadkastpc/Documents/android-studio/plugins/android/lib/android.jar!/images/material/icons/materialicons/arrow_back/baseline_arrow_back_24.xml\" />\n                                    </map>\n                                  </option>\n                                </PersistentState>\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                        <option name=\"values\">\n                          <map>\n                            <entry key=\"color\" value=\"ffffff\" />\n                            <entry key=\"outputName\" value=\"ic_arrow_back\" />\n                          </map>\n                        </option>\n                      </PersistentState>\n                    </value>\n                  </entry>\n                </map>\n              </option>\n            </PersistentState>\n          </value>\n        </entry>\n      </map>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/codeStyles/Project.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <JetCodeStyleSettings>\n      <option name=\"PACKAGES_TO_USE_STAR_IMPORTS\">\n        <value>\n          <package name=\"java.util\" alias=\"false\" withSubpackages=\"false\" />\n          <package name=\"kotlinx.android.synthetic\" alias=\"false\" withSubpackages=\"true\" />\n          <package name=\"io.ktor\" alias=\"false\" withSubpackages=\"true\" />\n        </value>\n      </option>\n      <option name=\"PACKAGES_IMPORT_LAYOUT\">\n        <value>\n          <package name=\"\" alias=\"false\" withSubpackages=\"true\" />\n          <package name=\"java\" alias=\"false\" withSubpackages=\"true\" />\n          <package name=\"javax\" alias=\"false\" withSubpackages=\"true\" />\n          <package name=\"kotlin\" alias=\"false\" withSubpackages=\"true\" />\n          <package name=\"\" alias=\"true\" withSubpackages=\"true\" />\n        </value>\n      </option>\n      <option name=\"CODE_STYLE_DEFAULTS\" value=\"KOTLIN_OFFICIAL\" />\n    </JetCodeStyleSettings>\n    <codeStyleSettings language=\"XML\">\n      <indentOptions>\n        <option name=\"CONTINUATION_INDENT_SIZE\" value=\"4\" />\n      </indentOptions>\n      <arrangement>\n        <rules>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>xmlns:android</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>xmlns:.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*:id</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*:name</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>name</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>style</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>ANDROID_ATTRIBUTE_ORDER</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>.*</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n        </rules>\n      </arrangement>\n    </codeStyleSettings>\n    <codeStyleSettings language=\"kotlin\">\n      <option name=\"CODE_STYLE_DEFAULTS\" value=\"KOTLIN_OFFICIAL\" />\n    </codeStyleSettings>\n  </code_scheme>\n</component>"
  },
  {
    "path": ".idea/codeStyles/codeStyleConfig.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <state>\n    <option name=\"USE_PER_PROJECT_SETTINGS\" value=\"true\" />\n  </state>\n</component>"
  },
  {
    "path": ".idea/compiler.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <bytecodeTargetLevel target=\"11\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/inspectionProfiles/Project_Default.xml",
    "content": "<component name=\"InspectionProjectProfileManager\">\n  <profile version=\"1.0\">\n    <option name=\"myName\" value=\"Project Default\" />\n    <inspection_tool class=\"MoveVariableDeclarationIntoWhen\" enabled=\"false\" level=\"WEAK WARNING\" enabled_by_default=\"false\" />\n  </profile>\n</component>"
  },
  {
    "path": ".idea/jarRepositories.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RemoteRepositoriesConfiguration\">\n    <remote-repository>\n      <option name=\"id\" value=\"central\" />\n      <option name=\"name\" value=\"Maven Central repository\" />\n      <option name=\"url\" value=\"https://repo1.maven.org/maven2\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"jboss.community\" />\n      <option name=\"name\" value=\"JBoss Community repository\" />\n      <option name=\"url\" value=\"https://repository.jboss.org/nexus/content/repositories/public/\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"BintrayJCenter\" />\n      <option name=\"name\" value=\"BintrayJCenter\" />\n      <option name=\"url\" value=\"https://jcenter.bintray.com/\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"Google\" />\n      <option name=\"name\" value=\"Google\" />\n      <option name=\"url\" value=\"https://dl.google.com/dl/android/maven2/\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"maven\" />\n      <option name=\"name\" value=\"maven\" />\n      <option name=\"url\" value=\"https://jitpack.io\" />\n    </remote-repository>\n    <remote-repository>\n      <option name=\"id\" value=\"MavenRepo\" />\n      <option name=\"name\" value=\"MavenRepo\" />\n      <option name=\"url\" value=\"https://repo.maven.apache.org/maven2/\" />\n    </remote-repository>\n  </component>\n</project>"
  },
  {
    "path": ".idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_11\" default=\"false\" project-jdk-name=\"1.8\" project-jdk-type=\"JavaSDK\">\n    <output url=\"file://$PROJECT_DIR$/build/classes\" />\n  </component>\n  <component name=\"ProjectType\">\n    <option name=\"id\" value=\"Android\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/modules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/LetsChat.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/LetsChat.iml\" />\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/app/LetsChat.app.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/app/LetsChat.app.iml\" />\n    </modules>\n  </component>\n</project>"
  },
  {
    "path": ".idea/navEditor.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"navEditor-manualLayoutAlgorithm2\">\n    <option name=\"myPositions\">\n      <map>\n        <entry key=\"nav_graph.xml\">\n          <value>\n            <LayoutPositions>\n              <option name=\"myPositions\">\n                <map>\n                  <entry key=\"FAddGroupMembers\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"988\" />\n                            <option name=\"y\" value=\"1278\" />\n                          </Point>\n                        </option>\n                        <option name=\"myPositions\">\n                          <map>\n                            <entry key=\"action_FAddGroupMembers_to_FCreateGroup\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FContacts\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"925\" />\n                            <option name=\"y\" value=\"343\" />\n                          </Point>\n                        </option>\n                        <option name=\"myPositions\">\n                          <map>\n                            <entry key=\"action_FContacts_to_Chat\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FCountries\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"-50\" />\n                            <option name=\"y\" value=\"660\" />\n                          </Point>\n                        </option>\n                        <option name=\"myPositions\">\n                          <map>\n                            <entry key=\"action_FCountries_to_FLogIn\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FCreateGroup\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"1254\" />\n                            <option name=\"y\" value=\"1273\" />\n                          </Point>\n                        </option>\n                        <option name=\"myPositions\">\n                          <map>\n                            <entry key=\"action_FCreateGroup_to_FGroupChat\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FGroupChat\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"1525\" />\n                            <option name=\"y\" value=\"1193\" />\n                          </Point>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FGroupChatHome\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"644\" />\n                            <option name=\"y\" value=\"1022\" />\n                          </Point>\n                        </option>\n                        <option name=\"myPositions\">\n                          <map>\n                            <entry key=\"action_FGroupChatHome_to_FAddGroupMembers\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                            <entry key=\"action_FGroupChatHome_to_FGroupChat\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FLogIn\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"-263\" />\n                            <option name=\"y\" value=\"295\" />\n                          </Point>\n                        </option>\n                        <option name=\"myPositions\">\n                          <map>\n                            <entry key=\"action_FLogIn_to_FCountries\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                            <entry key=\"action_FLogIn_to_FProfile\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                            <entry key=\"action_FLogIn_to_FSingleChatHome\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                            <entry key=\"action_FLogIn_to_FVerify\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FMyProfile\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"686\" />\n                            <option name=\"y\" value=\"-230\" />\n                          </Point>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FProfile\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"435\" />\n                            <option name=\"y\" value=\"278\" />\n                          </Point>\n                        </option>\n                        <option name=\"myPositions\">\n                          <map>\n                            <entry key=\"action_FProfile_to_FSingleChatHome\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FSearch\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"872\" />\n                            <option name=\"y\" value=\"-39\" />\n                          </Point>\n                        </option>\n                        <option name=\"myPositions\">\n                          <map>\n                            <entry key=\"action_FSearch_to_FSingleChat\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FSingleChat\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"1423\" />\n                            <option name=\"y\" value=\"383\" />\n                          </Point>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FSingleChatHome\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"736\" />\n                            <option name=\"y\" value=\"218\" />\n                          </Point>\n                        </option>\n                        <option name=\"myPositions\">\n                          <map>\n                            <entry key=\"action_FSingleChatHome_to_FContacts\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                            <entry key=\"action_FSingleChatHome_to_FGroupChat\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                            <entry key=\"action_FSingleChat_to_FChat\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                  <entry key=\"FVerify\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"112\" />\n                            <option name=\"y\" value=\"266\" />\n                          </Point>\n                        </option>\n                        <option name=\"myPositions\">\n                          <map>\n                            <entry key=\"action_FVerify_to_FProfile\">\n                              <value>\n                                <LayoutPositions />\n                              </value>\n                            </entry>\n                          </map>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                </map>\n              </option>\n            </LayoutPositions>\n          </value>\n        </entry>\n        <entry key=\"nav_graph_chat.xml\">\n          <value>\n            <LayoutPositions>\n              <option name=\"myPositions\">\n                <map>\n                  <entry key=\"FChat\">\n                    <value>\n                      <LayoutPositions>\n                        <option name=\"myPosition\">\n                          <Point>\n                            <option name=\"x\" value=\"12\" />\n                            <option name=\"y\" value=\"12\" />\n                          </Point>\n                        </option>\n                      </LayoutPositions>\n                    </value>\n                  </entry>\n                </map>\n              </option>\n            </LayoutPositions>\n          </value>\n        </entry>\n      </map>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/runConfigurations.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <option name=\"ignoredProducers\">\n      <set>\n        <option value=\"com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer\" />\n      </set>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 Gowtham Balamurugan\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": "# LetsChat\nLetsChat is a Sample Messaging Android application built to demonstrate the use of Modern Android development tools - (Kotlin, Coroutines, Dagger-Hilt, Architecture Components, MVVM, Room, Coil) and Firebase\n\n- Create a firebase project and replace the google-services.json file which you get from your firebase project console\n- Following firebase services need to be enabled in the firebase console\n  - Phone Auth\n  - Cloud Firestore\n  - Realtime Database\n  - Storage\n  - Composite indexes should be created for contact query(link for enabling indexes could be found from logcat while using the app)\n\n***You can Install and test latest LetsChat app from below 👇***\n\n[![LetsChat App](https://img.shields.io/badge/LetsChat-APK-blue.svg?style=for-the-badge&logo=android)](https://github.com/a914-gowtham/LetsChat/blob/master/app/app-debug.apk)\n\n<p float=\"center\">\n  <img src=\"demo_video.gif\" />\n</p>\n \n## Features ✨\n- One on one chat\n- Group Chat\n- Typing status for one on one and group chat\n- Unread messages count\n- Message status for failed,sent,delivered and seen\n- Supported message types\n  - Text\n  - Voice\n  - Sticker and Gif\n- Attachments \n  - Image\n  - Video - InProgress\n- Notification actions for reply and mark as read\n- Search users by username \n\n## Built With 🛠\n- [Kotlin](https://kotlinlang.org/) - First class and official programming language for Android development.\n- [Coroutines & Flow](https://kotlinlang.org/docs/reference/coroutines-overview.html) - For asynchronous and more..\n- [Android Architecture Components](https://developer.android.com/topic/libraries/architecture) - Collection of libraries that help you design quality, robust, testable, and maintainable apps.\n  - [Navigation Component](https://developer.android.com/guide/navigation/navigation-getting-started) - Handle everything needed for in-app navigation with a single Activity.\n  - [LiveData](https://developer.android.com/topic/libraries/architecture/livedata) - Data objects that notify views when the underlying database changes.\n  - [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel) - Stores UI-related data that isn't destroyed on UI changes. \n  - [DataBinding](https://github.com/android/databinding-samples) - Generates a binding class for each XML layout file present in that module and allows you to more easily write code that interacts with views.Declaratively bind observable data to UI elements.\n   - [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) - WorkManager is an API that makes it easy to schedule deferrable, asynchronous tasks that are expected to run even if the app exits or the device restarts.\n  - [Room](https://developer.android.com/topic/libraries/architecture/room) - SQLite object mapping library.\n- [Dependency Injection](https://developer.android.com/training/dependency-injection) - \n  - [Dagger-Hilt](https://dagger.dev/hilt/) - Standard library to incorporate Dagger dependency injection into an Android application.\n  - [Hilt-ViewModel](https://developer.android.com/training/dependency-injection/hilt-jetpack) - DI for injecting `ViewModel`.\n- [Firebase](https://firebase.google.com/) - \n  - [Cloud Messaging](https://firebase.google.com/products/cloud-messaging) - For Sending Notification to client app.\n  - [Cloud Firestore](https://firebase.google.com/docs/firestore) - Flexible, scalable NoSQL cloud database to store and sync data.\n  - [Cloud Storage](https://firebase.google.com/docs/storage) - For Store and serve user-generated content.\n  - [Authentication](https://firebase.google.com/docs/auth) - For Creating account with mobile number.\n- [Kotlin Serializer](https://github.com/Kotlin/kotlinx.serialization) - Convert Specific Classes to and from JSON.Runtime library with core serialization API and support libraries with various serialization formats.\n- [Coil-kt](https://coil-kt.github.io/coil/) - An image loading library for Android backed by Kotlin Coroutines.\n\n\n\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-parcelize'\napply plugin: 'kotlin-kapt'\napply plugin: 'dagger.hilt.android.plugin'\napply plugin: 'androidx.navigation.safeargs.kotlin'\napply plugin: 'com.google.firebase.crashlytics'\napply plugin: 'com.google.gms.google-services'\napply plugin: 'kotlinx-serialization'\nandroid {\n    compileSdkVersion 30\n    buildToolsVersion \"30.0.3\"\n\n    buildFeatures{\n        dataBinding = true\n        viewBinding = true\n    }\n\n    defaultConfig {\n        applicationId \"com.gowtham.letschat\"\n        minSdkVersion 19\n        targetSdkVersion 30\n        versionCode 1\n        versionName \"1.0\"\n        buildConfigField(\"String\",\"SERVER_KEY\",SERVER_KEY)\n        multiDexEnabled true\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = JavaVersion.VERSION_1_8.toString()\n    }\n\n    sourceSets {\n        main {\n            assets.srcDirs = ['src/main/assets', 'src/main/assets/']\n            res.srcDirs = ['src/main/res', 'src/main/res/drawable']\n        }\n    }\n\n    dexOptions {\n        javaMaxHeapSize \"4g\"\n    }\n\n}\n\ndependencies {\n    def work_version = \"2.5.0\"\n\n    implementation fileTree(dir: \"libs\", include: [\"*.jar\"])\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version\"\n    implementation 'androidx.core:core-ktx:1.5.0'\n    implementation 'androidx.appcompat:appcompat:1.3.0'\n    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'\n    implementation 'com.google.android.material:material:1.3.0'\n    implementation 'androidx.multidex:multidex:2.0.1'\n    implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.11'\n    implementation 'androidx.legacy:legacy-support-v4:1.0.0'\n    implementation \"org.jetbrains.kotlin:kotlin-reflect:$kotlin_version\"\n    // Activity KTX for viewModels()\n    implementation \"androidx.activity:activity-ktx:1.2.3\"\n\n    //Databinding compiler\n    kapt \"com.android.databinding:compiler:3.1.4\"\n\n    //dagger-hilt\n    implementation \"com.google.dagger:hilt-android:2.36\" //don't upgrade unless same version of kapt availale\n    kapt \"com.google.dagger:hilt-android-compiler:2.36\"\n    implementation 'androidx.hilt:hilt-work:1.0.0'\n    kapt \"androidx.hilt:hilt-compiler:1.0.0\"\n\n    //event bus\n    implementation 'org.greenrobot:eventbus:3.2.0'\n\n    implementation \"androidx.recyclerview:recyclerview:1.2.1\"\n\n    //mvvm\n    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'\n\n    //Android Navigation Architecture\n    implementation \"androidx.navigation:navigation-fragment-ktx:2.3.5\"\n    implementation \"androidx.navigation:navigation-ui-ktx:2.3.5\"\n\n    // Room\n    implementation \"androidx.room:room-runtime:2.4.0-alpha03\"\n    kapt \"androidx.room:room-compiler:2.4.0-alpha03\"\n\n    // Kotlin Extensions and Coroutines support for Room\n    implementation \"androidx.room:room-ktx:2.4.0-alpha03\"\n\n    //For device to device notification sending\n    implementation 'com.github.a914-gowtham:fcm-sender:1.0.2'\n\n    //Lottie\n    implementation 'com.airbnb.android:lottie:3.7.0'\n\n    //firebase\n    //By using the Firebase Android BoM, your app will always use compatible versions of the Firebase Android libraries.\n    implementation platform('com.google.firebase:firebase-bom:26.0.0')\n    // When using the BoM, you don't specify versions in Firebase library dependencies\n    implementation 'com.google.firebase:firebase-analytics-ktx'\n    implementation 'com.google.firebase:firebase-auth-ktx'\n    implementation 'com.google.firebase:firebase-firestore-ktx'\n    implementation 'androidx.browser:browser:1.3.0'  //\n    implementation 'com.google.firebase:firebase-storage-ktx'\n    implementation 'com.google.firebase:firebase-messaging-ktx'\n    implementation 'com.google.firebase:firebase-crashlytics-ktx'\n    implementation 'com.google.firebase:firebase-database-ktx'\n\n    implementation 'com.jakewharton.timber:timber:4.7.1'\n\n    //Image loader\n    implementation(\"io.coil-kt:coil:1.2.1\")\n    implementation(\"io.coil-kt:coil-gif:1.0.0\")\n    implementation 'com.github.CanHub:Android-Image-Cropper:3.3.5'\n\n    //image zoom\n    implementation 'com.github.stfalcon-studio:StfalconImageViewer:v1.0.1'\n\n    //Kotlin seriler\n    implementation(\"org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.1\")\n     // Work Manager\n    implementation \"androidx.work:work-runtime-ktx:$work_version\"\n    implementation \"androidx.datastore:datastore-preferences:1.0.0-beta01\"\n\n\n    // Local Unit Tests\n    implementation \"androidx.test:core:1.3.0\"\n    testImplementation \"junit:junit:4.13.2\"\n    testImplementation \"org.hamcrest:hamcrest-all:1.3\"\n    testImplementation \"androidx.arch.core:core-testing:2.1.0\"\n    testImplementation \"org.robolectric:robolectric:4.3.1\"\n    testImplementation \"org.jetbrains.kotlinx:kotlinx-coroutines-test:1.2.1\"\n    testImplementation \"com.google.truth:truth:1.0.1\"\n    testImplementation \"org.mockito:mockito-core:2.21.0\"\n\n    // Instrumented Unit Tests\n    androidTestImplementation \"junit:junit:4.13.2\"\n    androidTestImplementation \"org.jetbrains.kotlinx:kotlinx-coroutines-test:1.2.1\"\n    androidTestImplementation \"androidx.arch.core:core-testing:2.1.0\"\n    androidTestImplementation \"com.google.truth:truth:1.0.1\"\n    androidTestImplementation 'androidx.test.ext:junit:1.1.2'\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'\n    androidTestImplementation \"org.mockito:mockito-core:2.28.2\"\n    androidTestImplementation 'com.google.dagger:hilt-android-testing:2.35'\n    kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.36'\n}"
  },
  {
    "path": "app/google-services.json",
    "content": "{\n  \"project_info\": {\n    \"project_number\": \"713876726773\",\n    \"firebase_url\": \"https://letschat-31c80.firebaseio.com\",\n    \"project_id\": \"letschat-31c80\",\n    \"storage_bucket\": \"letschat-31c80.appspot.com\"\n  },\n  \"client\": [\n    {\n      \"client_info\": {\n        \"mobilesdk_app_id\": \"1:713876726773:android:7516967105f42edfd8b6bc\",\n        \"android_client_info\": {\n          \"package_name\": \"com.gowtham.letschat\"\n        }\n      },\n      \"oauth_client\": [\n        {\n          \"client_id\": \"713876726773-jefdmp8hqi7meehikl7qc0knr5elvgdg.apps.googleusercontent.com\",\n          \"client_type\": 1,\n          \"android_info\": {\n            \"package_name\": \"com.gowtham.letschat\",\n            \"certificate_hash\": \"8f067951f97ceb66ed871e1bdf62404f32ce1101\"\n          }\n        },\n        {\n          \"client_id\": \"713876726773-mrqj2mpsm1jcavcursp6vmelglkeb7i6.apps.googleusercontent.com\",\n          \"client_type\": 1,\n          \"android_info\": {\n            \"package_name\": \"com.gowtham.letschat\",\n            \"certificate_hash\": \"a7ee622ee9d484ca3a3f44b18bfdb642f21bba6d\"\n          }\n        },\n        {\n          \"client_id\": \"713876726773-n8oqdoievdudn72eulv0t5ebqv8mah61.apps.googleusercontent.com\",\n          \"client_type\": 1,\n          \"android_info\": {\n            \"package_name\": \"com.gowtham.letschat\",\n            \"certificate_hash\": \"542c95c560a25358c37923ddd271a737c730c131\"\n          }\n        },\n        {\n          \"client_id\": \"713876726773-0clemuuk99ed2clrqjor4u6s8jkgl98h.apps.googleusercontent.com\",\n          \"client_type\": 3\n        }\n      ],\n      \"api_key\": [\n        {\n          \"current_key\": \"AIzaSyAZfALlXiAfKOOQCAbcgh9wRphqYhhnYOI\"\n        }\n      ],\n      \"services\": {\n        \"appinvite_service\": {\n          \"other_platform_oauth_client\": [\n            {\n              \"client_id\": \"713876726773-0clemuuk99ed2clrqjor4u6s8jkgl98h.apps.googleusercontent.com\",\n              \"client_type\": 3\n            }\n          ]\n        }\n      }\n    }\n  ],\n  \"configuration_version\": \"1\"\n}"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile"
  },
  {
    "path": "app/src/androidTest/java/com/gowtham/letschat/FlowUtilAndroidTest.kt",
    "content": "package com.gowtham.letschat\n\nimport androidx.annotation.VisibleForTesting\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.Observer\nimport com.gowtham.letschat.utils.LogMessage\nimport kotlinx.coroutines.*\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.cancellable\nimport kotlinx.coroutines.flow.collect\nimport kotlinx.coroutines.flow.onCompletion\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.TimeoutException\n\n/**\n * Gets the value of a [LiveData] or waits for it to have one, with a timeout.\n *\n * Use this extension from host-side (JVM) tests. It's recommended to use it alongside\n * `InstantTaskExecutorRule` or a similar mechanism to execute tasks synchronously.\n */\n@VisibleForTesting(otherwise = VisibleForTesting.NONE)\nfun <T> Flow<T>.getOrAwaitValue(\n    time: Long = 2,\n    timeUnit: TimeUnit = TimeUnit.SECONDS,\n    afterObserve: () -> Unit = {}\n): T {\n    var data: T? = null\n    val latch = CountDownLatch(1)\n    val scope= CoroutineScope(Dispatchers.IO).launch {\n       this@getOrAwaitValue.collect {\n            data=it\n            cancel()\n            latch.countDown()\n        }\n    }\n    try {\n        afterObserve.invoke()\n\n        // Don't wait indefinitely if the LiveData is not set.\n        if (!latch.await(time, timeUnit)) {\n            throw TimeoutException(\"LiveData value was never set.\")\n        }\n\n    } finally {\n        if (scope.isActive)\n           scope.cancel()\n    }\n\n    @Suppress(\"UNCHECKED_CAST\")\n    return data as T\n}"
  },
  {
    "path": "app/src/androidTest/java/com/gowtham/letschat/HiltTestRunner.kt",
    "content": "package com.gowtham.letschat\n\nimport android.app.Application\nimport android.content.Context\nimport androidx.test.runner.AndroidJUnitRunner\nimport dagger.hilt.android.testing.HiltTestApplication\n\nclass HiltTestRunner  : AndroidJUnitRunner() {\n    override fun newApplication(\n        cl: ClassLoader?,\n        className: String?,\n        context: Context?\n    ): Application {\n        return super.newApplication(cl, HiltTestApplication::class.java.name, context)\n    }\n}"
  },
  {
    "path": "app/src/androidTest/java/com/gowtham/letschat/LiveDataUtilAndroidTest.kt",
    "content": "package com.gowtham.letschat\n\nimport androidx.annotation.VisibleForTesting\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.Observer\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.TimeoutException\n\n/**\n * Gets the value of a [LiveData] or waits for it to have one, with a timeout.\n *\n * Use this extension from host-side (JVM) tests. It's recommended to use it alongside\n * `InstantTaskExecutorRule` or a similar mechanism to execute tasks synchronously.\n */\n@VisibleForTesting(otherwise = VisibleForTesting.NONE)\nfun <T> LiveData<T>.getOrAwaitValue(\n    time: Long = 2,\n    timeUnit: TimeUnit = TimeUnit.SECONDS,\n    afterObserve: () -> Unit = {}\n): T {\n    var data: T? = null\n    val latch = CountDownLatch(1)\n    val observer = object : Observer<T> {\n        override fun onChanged(o: T?) {\n            data = o\n            latch.countDown()\n            this@getOrAwaitValue.removeObserver(this)\n        }\n    }\n    this.observeForever(observer)\n\n    try {\n        afterObserve.invoke()\n\n        // Don't wait indefinitely if the LiveData is not set.\n        if (!latch.await(time, timeUnit)) {\n            throw TimeoutException(\"LiveData value was never set.\")\n        }\n\n    } finally {\n        this.removeObserver(observer)\n    }\n\n    @Suppress(\"UNCHECKED_CAST\")\n    return data as T\n}"
  },
  {
    "path": "app/src/androidTest/java/com/gowtham/letschat/db/daos/ChatUserDaoTest.kt",
    "content": "package com.gowtham.letschat.db.daos\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.room.Room\nimport androidx.test.core.app.ApplicationProvider\nimport androidx.test.ext.junit.runners.AndroidJUnit4\nimport androidx.test.filters.SmallTest\nimport com.google.common.truth.Truth.assertThat\nimport com.gowtham.letschat.db.ChatUserDatabase\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.models.UserProfile\nimport dagger.hilt.android.testing.HiltAndroidRule\nimport dagger.hilt.android.testing.HiltAndroidTest\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport javax.inject.Inject\nimport javax.inject.Named\n\n@ExperimentalCoroutinesApi\n@SmallTest\n@HiltAndroidTest\nclass ChatUserDaoTest {\n\n    @get:Rule\n    var hiltRule=HiltAndroidRule(this)\n\n    @get:Rule\n    var instantTaskExecutorRule=InstantTaskExecutorRule()\n\n    @Inject\n    @Named(\"test_db\")\n    lateinit var database: ChatUserDatabase\n    private lateinit var chatUserDao: ChatUserDao\n\n    @Before\n    fun setUp(){\n        hiltRule.inject()\n        chatUserDao=database.getChatUserDao()\n    }\n\n\n    @After\n    fun tearDown(){\n        database.close()\n    }\n\n    @Test\n    fun insert_ChatUser() = runBlockingTest {\n         val chatUser=ChatUser(\"testUser1\",\"Gowtham\", UserProfile(\"testUser1\",13232113L,123321321L),)\n         chatUserDao.insertUser(chatUser)\n         val chatUsers=chatUserDao.getChatUserList()\n         assertThat(chatUsers).contains(chatUser)\n    }\n\n    @Test\n    fun get_ChatUser_ById() = runBlockingTest {\n        val user=ChatUser(\"testId\",\"Gowtham\", UserProfile(\"testId\",13232113L,123321321L),)\n        chatUserDao.insertUser(user)\n        val chatUser=chatUserDao.getChatUserById(\"testId\")\n        assertThat(chatUser).isNotNull()\n    }\n\n    @Test\n    fun delete_User_ById() = runBlockingTest {\n        val user=ChatUser(\"testDeleteUserId\",\"Gowtham\", UserProfile(\"testDeleteUserId\",13232113L,123321321L),)\n        chatUserDao.insertUser(user)\n        chatUserDao.deleteUserById(\"testDeleteUserId\")\n        val chatUsers=chatUserDao.getChatUserList()\n        assertThat(chatUsers).doesNotContain(user)\n    }\n\n\n}"
  },
  {
    "path": "app/src/androidTest/java/com/gowtham/letschat/db/daos/GroupDaoTest.kt",
    "content": "package com.gowtham.letschat.db.daos\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.test.filters.SmallTest\nimport com.google.common.truth.Truth\nimport com.google.common.truth.Truth.assertThat\nimport com.gowtham.letschat.db.ChatUserDatabase\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.getOrAwaitValue\nimport com.gowtham.letschat.models.UserProfile\nimport dagger.hilt.android.testing.HiltAndroidRule\nimport dagger.hilt.android.testing.HiltAndroidTest\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport javax.inject.Inject\nimport javax.inject.Named\n\n@ExperimentalCoroutinesApi\n@SmallTest\n@HiltAndroidTest\nclass GroupDaoTest {\n\n    @get:Rule\n    var hiltRule = HiltAndroidRule(this)\n\n    @get:Rule\n    var instantTaskExecutorRule= InstantTaskExecutorRule()\n\n    @Inject\n    @Named(\"test_db\")\n    lateinit var database: ChatUserDatabase\n\n    private lateinit var groupDao: GroupDao\n\n    @Before\n    fun setUp() {\n        hiltRule.inject()\n        groupDao = database.getGroupDao()\n    }\n\n    @After\n    fun tearDown() {\n        database.close()\n    }\n\n    @Test\n    fun insert_Group() = runBlockingTest {\n        val group=Group(\"testId\",members = ArrayList(),profiles = ArrayList())\n        groupDao.insertGroup(group)\n        val groups=groupDao.getAllGroup().getOrAwaitValue()\n        assertThat(groups).contains(group)\n    }\n\n    @Test\n    fun insert_Multiple_Group() {\n        runBlockingTest {\n            val group1=Group(\"testId1\",members = ArrayList(),profiles = ArrayList())\n            val group2=Group(\"testId2\",members = ArrayList(),profiles = ArrayList())\n            groupDao.insertMultipleGroup(listOf(group1,group2))\n            val groups=groupDao.getAllGroup().getOrAwaitValue()\n            assertThat(groups).containsAtLeast(group1,group2)\n        }\n    }\n\n    @Test\n    fun get_Group_ById() {\n        runBlockingTest {\n            val newGroup=Group(\"testId8\",members = ArrayList(),profiles = ArrayList())\n            groupDao.insertGroup(newGroup)\n            val group=groupDao.getGroupById(newGroup.id)\n            assertThat(group).isNotNull()\n        }\n    }\n\n    @Test\n    fun delete_Group_ById() {\n        runBlockingTest {\n            val group=Group(\"testId5\",members = ArrayList(),profiles = ArrayList())\n            groupDao.insertGroup(group)\n            groupDao.deleteGroupById(group.id)\n            val groups=groupDao.getAllGroup().getOrAwaitValue()\n            assertThat(groups).doesNotContain(group)\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/androidTest/java/com/gowtham/letschat/db/daos/GroupMessageDaoTest.kt",
    "content": "package com.gowtham.letschat.db.daos\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.test.filters.SmallTest\nimport com.google.common.truth.Truth.assertThat\nimport com.gowtham.letschat.db.ChatUserDatabase\nimport com.gowtham.letschat.db.data.*\nimport com.gowtham.letschat.getOrAwaitValue\nimport dagger.hilt.android.testing.HiltAndroidRule\nimport dagger.hilt.android.testing.HiltAndroidTest\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport javax.inject.Inject\nimport javax.inject.Named\n\n@ExperimentalCoroutinesApi\n@SmallTest\n@HiltAndroidTest\nclass GroupMessageDaoTest {\n\n    @get:Rule\n    var hiltRule = HiltAndroidRule(this)\n\n    @get:Rule\n    var instantTaskExecutorRule= InstantTaskExecutorRule()\n\n    @Inject\n    @Named(\"test_db\")\n    lateinit var database: ChatUserDatabase\n\n    private lateinit var groupMessageDao: GroupMessageDao\n\n    @Before\n    fun setUp() {\n        hiltRule.inject()\n        groupMessageDao = database.getGroupMessageDao()\n    }\n\n    @After\n    fun tearDown() {\n        database.close()\n    }\n\n    @Test\n    fun insert_Message() = runBlockingTest {\n        val message=GroupMessage(1,\"testGroupId\",\"fromMe\", ArrayList(),\n            \"gowtham\",\"\",textMessage = TextMessage(),\n             imageMessage = ImageMessage(),audioMessage = AudioMessage(),videoMessage = VideoMessage(),\n            fileMessage = FileMessage(),deliveryTime = ArrayList(),seenTime = ArrayList(),status = ArrayList()\n        )\n        groupMessageDao.insertMessage(message)\n        val messages=groupMessageDao.getAllMessages().getOrAwaitValue()\n        assertThat(messages).contains(message)\n    }\n\n    @Test\n    fun insert_Multiple_Messages() {\n        runBlockingTest {\n            val message1=GroupMessage(2,\"testGroupId1\",\"fromMe\", ArrayList(),\n                \"gowtham\",\"\",textMessage = TextMessage(),\n                imageMessage = ImageMessage(),audioMessage = AudioMessage(),videoMessage = VideoMessage(),\n                fileMessage = FileMessage(),deliveryTime = ArrayList(),seenTime = ArrayList(),status = ArrayList()\n            )\n\n            val message2=GroupMessage(3,\"testGroupId2\",\"fromMe\", ArrayList(),\n                \"gowtham\",\"\",textMessage = TextMessage(),\n                imageMessage = ImageMessage(),audioMessage = AudioMessage(),videoMessage = VideoMessage(),\n                fileMessage = FileMessage(),deliveryTime = ArrayList(),seenTime = ArrayList(),status = ArrayList()\n            )\n            groupMessageDao.insertMultipleMessage(listOf(message1,message2))\n            val messages=groupMessageDao.getAllMessages().getOrAwaitValue()\n            assertThat(messages).containsAtLeast(message1,message2)\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/androidTest/java/com/gowtham/letschat/db/daos/MessageDaoTest.kt",
    "content": "package com.gowtham.letschat.db.daos\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport androidx.test.filters.SmallTest\nimport com.google.common.truth.Truth\nimport com.google.common.truth.Truth.assertThat\nimport com.gowtham.letschat.db.ChatUserDatabase\nimport com.gowtham.letschat.db.data.*\nimport com.gowtham.letschat.getOrAwaitValue\nimport com.gowtham.letschat.models.UserProfile\nimport dagger.hilt.android.testing.HiltAndroidRule\nimport dagger.hilt.android.testing.HiltAndroidTest\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport javax.inject.Inject\nimport javax.inject.Named\n\n@ExperimentalCoroutinesApi\n@SmallTest\n@HiltAndroidTest\nclass MessageDaoTest {\n\n    @get:Rule\n    var hiltRule = HiltAndroidRule(this)\n\n    @get:Rule\n    var instantTaskExecutorRule= InstantTaskExecutorRule()\n\n    @Inject\n    @Named(\"test_db\")\n    lateinit var database: ChatUserDatabase\n\n    private lateinit var messageDao: MessageDao\n\n    @Before\n    fun setUp() {\n        hiltRule.inject()\n        messageDao = database.getMessageDao()\n    }\n\n    @After\n    fun tearDown() {\n        database.close()\n    }\n\n    @Test\n    fun insert_Message() = runBlockingTest {\n        val message=Message(2,\n             0,0,\"fromId\",\"toId\",\"Gowtham\",\"\",textMessage = TextMessage(),\n             imageMessage = ImageMessage(),audioMessage = AudioMessage(),videoMessage = VideoMessage(),\n            fileMessage = FileMessage(),chatUserId = \"\",chatUsers = ArrayList(),\n        )\n        messageDao.insertMessage(message)\n        val messages=messageDao.getAllMessages().getOrAwaitValue()\n        assertThat(messages).contains(message)\n    }\n\n    @Test\n    fun insert_Multiple_Messages() {\n        runBlockingTest {\n            val message1=Message(3,\n                0,0,\"fromId\",\"toId\",\"Gowtham\",\"\",textMessage = TextMessage(),\n                imageMessage = ImageMessage(),audioMessage = AudioMessage(),videoMessage = VideoMessage(),\n                fileMessage = FileMessage(),chatUserId = \"\",chatUsers = ArrayList(),\n            )\n            val message2=Message(4,\n                0,0,\"fromId\",\"toId\",\"Gowtham\",\"\",textMessage = TextMessage(),\n                imageMessage = ImageMessage(),audioMessage = AudioMessage(),videoMessage = VideoMessage(),\n                fileMessage = FileMessage(),chatUserId = \"\",chatUsers = ArrayList(),\n            )\n            messageDao.insertMultipleMessage(listOf(message1,message2))\n            val messages=messageDao.getAllMessages().getOrAwaitValue()\n            assertThat(messages).containsAtLeast(message1,message2)\n        }\n    }\n\n    @Test\n    fun get_Message_ById() {\n        runBlockingTest {\n            val messageId=5L\n            val message=Message(messageId,\n                0,0,\"fromId\",\"toId\",\"Gowtham\",\"\",textMessage = TextMessage(),\n                imageMessage = ImageMessage(),audioMessage = AudioMessage(),videoMessage = VideoMessage(),\n                fileMessage = FileMessage(),chatUserId = \"\",chatUsers = ArrayList(),\n            )\n            messageDao.insertMessage(message)\n            val msg=messageDao.getMessageById(messageId)\n            assertThat(msg).isNotNull()\n        }\n    }\n\n\n    @Test\n    fun delete_Message_ById() {\n        runBlockingTest {\n            val messageId=6L\n            val message=Message(messageId,\n                0,0,\"fromId\",\"toId\",\"Gowtham\",\"\",textMessage = TextMessage(),\n                imageMessage = ImageMessage(),audioMessage = AudioMessage(),videoMessage = VideoMessage(),\n                fileMessage = FileMessage(),chatUserId = \"\",chatUsers = ArrayList(),\n            )\n            messageDao.insertMessage(message)\n            messageDao.deleteMessageByCreatedAt(messageId)\n            val messages=messageDao.getAllMessages().getOrAwaitValue()\n            assertThat(messages).doesNotContain(message)\n        }\n    }\n}"
  },
  {
    "path": "app/src/androidTest/java/com/gowtham/letschat/di/TestAppModule.kt",
    "content": "package com.gowtham.letschat.di\n\nimport android.content.Context\nimport androidx.room.Room\nimport com.gowtham.letschat.db.ChatUserDatabase\nimport dagger.Module\nimport dagger.Provides\nimport dagger.hilt.InstallIn\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport dagger.hilt.components.SingletonComponent\nimport javax.inject.Named\n\n\n@Module\n@InstallIn(SingletonComponent::class)\nclass TestAppModule {\n\n    @Provides\n    @Named(\"test_db\")\n    fun provideInMemoryDb(@ApplicationContext context: Context): ChatUserDatabase{\n        return Room.inMemoryDatabaseBuilder(\n             context,\n             ChatUserDatabase::class.java\n         ).allowMainThreadQueries().build()\n    }\n}"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"com.gowtham.letschat\">\n\n    <uses-feature\n        android:name=\"android.hardware.camera\"\n        android:required=\"true\" />\n    <uses-feature android:name=\"android.hardware.camera.autofocus\" />\n    <uses-feature\n        android:glEsVersion=\"0x00020000\"\n        android:required=\"true\" />\n\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.ACCESS_NETWORK_STATE\" />\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.CAMERA\" />\n    <uses-permission android:name=\"android.permission.USE_FULL_SCREEN_INTENT\" />\n    <uses-permission android:name=\"android.permission.DISABLE_KEYGUARD\" />\n    <uses-permission android:name=\"android.permission.ACCESS_NOTIFICATION_POLICY\" />\n    <uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\" />\n    <uses-permission android:name=\"android.permission.ACCESS_MEDIA_LOCATION\" />\n    <uses-permission android:name=\"com.google.android.c2dm.permission.RECEIVE\" />\n    <uses-permission android:name=\"com.google.android.providers.gsf.permission.READ_GSERVICES\" />\n    <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />\n\n    <application\n        android:name=\".MApplication\"\n        android:allowBackup=\"false\"\n        android:hardwareAccelerated=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:requestLegacyExternalStorage=\"true\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\"\n        tools:targetApi=\"q\">\n\n        <receiver\n            android:name=\".utils.GroupMsgActionReceiver\"\n            android:enabled=\"true\"\n            android:exported=\"true\"/>\n\n        <receiver\n            android:name=\".utils.NActionReceiver\"\n            android:enabled=\"true\" />\n\n        <activity android:name=\".ui.activities.ActSplash\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n\n        <activity android:name=\".ui.activities.MainActivity\"\n            android:windowSoftInputMode=\"adjustPan\"/>\n\n        <activity\n            android:name=\"com.theartofdev.edmodo.cropper.CropImageActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/Base.Theme.AppCompat\" />\n\n        <provider\n            android:name=\"androidx.core.content.FileProvider\"\n            android:authorities=\"${applicationId}.fileprovider\"\n            android:exported=\"false\"\n            android:grantUriPermissions=\"true\">\n            <meta-data\n                android:name=\"android.support.FILE_PROVIDER_PATHS\"\n                android:resource=\"@xml/provider_path\" />\n        </provider>\n\n        <meta-data\n            android:name=\"com.google.firebase.messaging.default_notification_icon\"\n            android:resource=\"@drawable/ic_stat_name\" />\n        <meta-data\n            android:name=\"com.google.firebase.messaging.default_notification_channel_id\"\n            android:value=\"@string/default_notification_channel_id\" />\n\n        <service\n            android:name=\".FirebasePush\"\n            android:enabled=\"true\"\n            android:exported=\"false\">\n            <intent-filter>\n                <action android:name=\"com.google.firebase.MESSAGING_EVENT\" />\n            </intent-filter>\n        </service>\n\n        <provider\n            android:name=\"androidx.work.impl.WorkManagerInitializer\"\n            android:authorities=\"${applicationId}.workmanager-init\"\n            tools:node=\"remove\"\n            android:exported=\"false\" />\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/FirebasePush.kt",
    "content": "package com.gowtham.letschat\n\nimport android.app.Notification\nimport android.app.PendingIntent\nimport android.content.Context\nimport android.content.Intent\nimport android.graphics.Bitmap\nimport android.graphics.drawable.BitmapDrawable\nimport androidx.core.app.NotificationCompat\nimport androidx.core.app.NotificationManagerCompat\nimport androidx.core.app.Person\nimport androidx.core.app.RemoteInput\nimport coil.ImageLoader\nimport coil.request.ImageRequest\nimport coil.request.SuccessResult\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.google.firebase.messaging.FirebaseMessagingService\nimport com.google.firebase.messaging.RemoteMessage\nimport com.gowtham.letschat.core.ChatUserUtil\nimport com.gowtham.letschat.core.GroupMsgStatusUpdater\nimport com.gowtham.letschat.core.GroupQuery\nimport com.gowtham.letschat.core.MessageStatusUpdater\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.daos.GroupMessageDao\nimport com.gowtham.letschat.db.daos.MessageDao\nimport com.gowtham.letschat.db.data.*\nimport com.gowtham.letschat.di.GroupCollection\nimport com.gowtham.letschat.di.MessageCollection\nimport com.gowtham.letschat.models.PushMsg\nimport com.gowtham.letschat.ui.activities.MainActivity\nimport com.gowtham.letschat.utils.*\nimport com.gowtham.letschat.utils.Constants.ACTION_GROUP_NEW_MESSAGE\nimport com.gowtham.letschat.utils.Constants.ACTION_LOGGED_IN_ANOTHER_DEVICE\nimport com.gowtham.letschat.utils.Constants.ACTION_MARK_AS_READ\nimport com.gowtham.letschat.utils.Constants.ACTION_NEW_MESSAGE\nimport com.gowtham.letschat.utils.Constants.ACTION_REPLY\nimport com.gowtham.letschat.utils.Constants.CHAT_USER_DATA\nimport com.gowtham.letschat.utils.Constants.GROUP_DATA\nimport dagger.hilt.android.AndroidEntryPoint\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.json.Json\nimport timber.log.Timber\nimport javax.inject.Inject\n\n\nconst val TYPE_LOGGED_IN = \"new_logged_in\"\n\nconst val TYPE_NEW_MESSAGE = \"new_message\"\n\nconst val TYPE_NEW_GROUP = \"new_group\"\n\nconst val TYPE_NEW_GROUP_MESSAGE = \"new_group_message\"\n\nconst val GROUP_KEY = \"com.mygroupkey\"\n\nconst val SUMMARY_ID = 0\n\nconst val KEY_TEXT_REPLY = \"key_text_reply\"\n\n@AndroidEntryPoint\nclass FirebasePush : FirebaseMessagingService(), OnSuccessListener {\n\n    @Inject\n    lateinit var preference: MPreference\n\n    @Inject\n    lateinit var dbRepository: DbRepository\n\n    @Inject\n    lateinit var usersCollection: CollectionReference\n\n    @Inject\n    lateinit var messageStatusUpdater: MessageStatusUpdater\n\n    @Inject\n    lateinit var groupMessageStatusUpdater: GroupMsgStatusUpdater\n\n    @GroupCollection\n    @Inject\n    lateinit var groupCollection: CollectionReference\n\n    private var sentTime: Long? = null\n\n    private lateinit var pushMsg: PushMsg\n\n    private var userId: String? = null\n\n    private lateinit var messagesOfChatUser: List<Message>\n\n    override fun onCreate() {\n        super.onCreate()\n        userId = preference.getUid()\n    }\n\n    override fun onNewToken(token: String) {\n        preference.updatePushToken(token)\n    }\n\n    override fun onMessageReceived(remoteMessage: RemoteMessage) {\n        super.onMessageReceived(remoteMessage)\n\n        try {\n            LogMessage.v(\"Data Payload: ${remoteMessage.data}\")\n            if (preference.isNotLoggedIn() || !preference.isSameDevice())\n                return\n            sentTime = remoteMessage.sentTime\n            val data = remoteMessage.data\n            pushMsg = Json.decodeFromString(data[\"data\"].toString())\n            /* pushMsg.to?.let {\n                 if (it!=userId)\n                     return\n             }*/\n            handleNotification()\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun handleNotification() {\n        when (pushMsg.type) {\n            TYPE_LOGGED_IN -> {\n                preference.setLastDevice(false)\n                val intent = Intent(ACTION_LOGGED_IN_ANOTHER_DEVICE)\n                sendBroadcast(intent)\n            }\n            TYPE_NEW_MESSAGE -> {\n                handleNewMessage()\n            }\n            TYPE_NEW_GROUP -> {\n                handleNewGroup()\n            }\n            TYPE_NEW_GROUP_MESSAGE -> {\n                handleGroupMsg()\n            }\n            else -> {\n\n            }\n        }\n    }\n\n    private fun handleGroupMsg() {\n        //it would be updated by snapshot listeners when app is alive\n        if (!MApplication.isAppRunning) {\n            val message = Json.decodeFromString<GroupMessage>(pushMsg.message_body.toString())\n            CoroutineScope(Dispatchers.IO).launch {\n                dbRepository.insertMessage(message)\n                val group = dbRepository.getGroupById(message.groupId)\n                val messages = dbRepository.getChatsOfGroupList(group?.id.toString())\n                if (group != null) {\n                    group.unRead = messages.filter {\n                        it.from != userId &&\n                                Utils.myIndexOfStatus(userId!!, it) < 3\n                    }.size\n                    dbRepository.insertGroup(group)\n\n                    withContext(Dispatchers.Main) {\n                        showGroupNotification(this@FirebasePush, dbRepository)\n                        //update delivery status\n                        groupMessageStatusUpdater.updateToDelivery(userId!!, messages, group.id)\n                    }\n                } else {\n                    val groupQuery = GroupQuery(message.groupId, dbRepository, preference)\n                    groupQuery.getGroupData(groupCollection)\n                }\n            }\n        }\n    }\n\n    private fun handleNewGroup() {\n        //it would be updated by snapshot listeners when app is alive\n        if (!MApplication.isAppRunning) {\n            val group = Json.decodeFromString<Group>(pushMsg.message_body.toString())\n            val groupQuery = GroupQuery(group.id, dbRepository, preference)\n            groupQuery.getGroupData(groupCollection)\n        }\n    }\n\n    private fun handleNewMessage() {\n        val message = Json.decodeFromString<Message>(pushMsg.message_body.toString())\n        if (message.to != userId || MApplication.isAppRunning) {\n            Timber.v(\"Push notification ignored\")\n            return\n        }\n        val chatUserId = UserUtils.getChatUserId(userId!!, message)  //chatUserId from message\n        message.chatUserId = chatUserId\n        CoroutineScope(Dispatchers.IO).launch {\n            dbRepository.insertMessage(message)\n            val chatUser = dbRepository.getChatUserById(chatUserId)\n            messagesOfChatUser = dbRepository.getChatsOfFriend(chatUserId)\n                .filter { it.to == userId && it.status < 3 }\n            if (chatUser != null) {\n                chatUser.unRead = messagesOfChatUser.size  //set unread msg count\n                dbRepository.insertUser(chatUser)\n                withContext(Dispatchers.Main) {\n                    showNotification(this@FirebasePush, dbRepository)\n                    //update delivery status\n                    messageStatusUpdater.updateToDelivery(messagesOfChatUser, chatUser)\n                }\n            } else {\n                withContext(Dispatchers.Main) {\n                    //update delivery status in listener\n                    val util = ChatUserUtil(dbRepository, usersCollection, this@FirebasePush)\n                    util.queryNewUserProfile(\n                        this@FirebasePush,\n                        chatUserId,\n                        null,\n                        showNotification = true\n                    )\n                }\n            }\n        }\n    }\n\n    private suspend fun getBitmap(url: String): Bitmap {\n        val loader = ImageLoader(this)\n        val request = ImageRequest.Builder(this)\n            .data(url)\n            .build()\n        val result = (loader.execute(request) as SuccessResult).drawable\n        return (result as BitmapDrawable).bitmap\n    }\n\n    companion object {\n        //notification method for common use\n        var messageCount = 0\n        var personCount = 0\n\n        fun showGroupNotification(context: Context, dbRepository: DbRepository) {\n            CoroutineScope(Dispatchers.IO).launch {\n                var groupWithMsgs = dbRepository.getGroupWithMessagesList()\n                groupWithMsgs = groupWithMsgs.filter { it.group.unRead != 0 }\n                checkGroupMessages(context, groupWithMsgs)\n            }\n        }\n\n        fun showNotification(context: Context, dbRepository: DbRepository) {\n            CoroutineScope(Dispatchers.IO).launch {\n                var chatUserWithMessages = dbRepository.getChatUserWithMessagesList()\n                chatUserWithMessages = chatUserWithMessages.filter { it.user.unRead != 0 }\n                checkMessages(context, chatUserWithMessages)\n            }\n        }\n\n        private fun checkGroupMessages(context: Context, groupWithMsgs: List<GroupWithMessages>) {\n            messageCount = 0\n            personCount = 0\n            val myUserId = MPreference(context).getUid().toString()\n            val manager: NotificationManagerCompat = Utils.returnNManager(context)\n            val groupNotifications = ArrayList<Notification>()\n            if (!groupWithMsgs.isNullOrEmpty()) {\n                for (groupMsg in groupWithMsgs) {\n                    /*  if (groupMsg.messages.last().from==myUserId)\n                          continue*/\n                    personCount += 1\n                    val person: Person = Person.Builder().setIcon(null)\n                        .setKey(groupMsg.group.id).setName(Utils.getGroupName(groupMsg.group.id))\n                        .build()\n                    val builder = Utils.createBuilder(context, manager)\n                        .setPriority(NotificationCompat.PRIORITY_DEFAULT)\n                        .setStyle(\n                            NotificationUtils.getGroupStyle(\n                                context,\n                                myUserId,\n                                person,\n                                groupMsg\n                            )\n                        )\n                        .setContentIntent(\n                            NotificationUtils.getGroupMsgIntent(\n                                context,\n                                groupMsg.group\n                            )\n                        )\n                        .setGroup(GROUP_KEY)\n                    builder.addAction(\n                        R.drawable.ic_drafts,\n                        \"mark as read\",\n                        NotificationUtils.getGroupMarkAsPIntent(context, groupMsg)\n                    )\n                    builder.addAction(NotificationUtils.getGroupReplyAction(context, groupMsg))\n                    val notification = builder.build()\n                    groupNotifications.add(notification)\n                }\n            }\n\n            val summaryNotification = NotificationUtils.getSummaryNotification(context, manager)\n            for ((index, notification) in groupNotifications.withIndex()) {\n                val notIdString = groupWithMsgs[index].group.createdAt.toString()\n                val notId = notIdString.substring(notIdString.length - 4)\n                    .toInt() //last 4 digits as notificationId\n                manager.notify(notId, notification)\n            }\n            if (groupNotifications.size > 1)\n                manager.notify(SUMMARY_ID, summaryNotification)\n        }\n\n        private fun checkMessages(\n            context: Context,\n            chatUserWithMessages: List<ChatUserWithMessages>\n        ) {\n\n            if (chatUserWithMessages.isNullOrEmpty())\n                return\n\n            messageCount = 0\n            personCount = 0\n            val notifications = ArrayList<Notification>()\n            val myUserId = MPreference(context).getUid().toString()\n            val manager: NotificationManagerCompat = Utils.returnNManager(context)\n\n            for (user in chatUserWithMessages) {\n                val messages = user.messages.filter { it.status < 3 && it.from != myUserId }\n                if (messages.isNullOrEmpty())\n                    continue\n                personCount += 1\n                Timber.v(\"DocId ${user.user.documentId}\")\n                val person: Person = Person.Builder().setIcon(null)\n                    .setKey(user.user.id).setName(user.user.localName).build()\n                val builder = Utils.createBuilder(context, manager)\n                    .setStyle(NotificationUtils.getStyle(context, person, user))\n                    .setContentIntent(NotificationUtils.getPIntent(context, user.user))\n                    .setGroup(GROUP_KEY)\n                if (!user.user.documentId.isNullOrBlank()) {\n                    builder.addAction(\n                        R.drawable.ic_drafts,\n                        \"mark as read\",\n                        NotificationUtils.getMarkAsPIntent(context, user)\n                    )\n                    builder.addAction(NotificationUtils.getReplyAction(context, user))\n                }\n                val notification = builder.build()\n                notifications.add(notification)\n            }\n\n            val summaryNotification = NotificationUtils.getSummaryNotification(context, manager)\n            for ((index, notification) in notifications.withIndex()) {\n                val notIdString = chatUserWithMessages[index].user.user.createdAt.toString()\n                val notId = notIdString.substring(notIdString.length - 4)\n                    .toInt() //last 4 digits as notificationId\n                manager.notify(notId, notification)\n            }\n\n            if (notifications.size > 1)\n                manager.notify(SUMMARY_ID, summaryNotification)\n        }\n\n    }\n\n    override fun onResult(success: Boolean, data: Any?) {\n        if (success) {\n            messageStatusUpdater.updateToDelivery(messagesOfChatUser, data as ChatUser)\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/MApplication.kt",
    "content": "package com.gowtham.letschat\n\nimport android.content.Context\nimport androidx.hilt.work.HiltWorkerFactory\nimport androidx.lifecycle.LifecycleObserver\nimport androidx.multidex.MultiDexApplication\nimport androidx.work.Configuration\nimport com.google.firebase.FirebaseApp\nimport com.google.firebase.firestore.CollectionReference\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.daos.MessageDao\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.LogMessage\nimport com.gowtham.letschat.utils.MPreference\nimport com.gowtham.letschat.utils.UserUtils\nimport dagger.hilt.android.HiltAndroidApp\nimport timber.log.Timber\nimport javax.inject.Inject\n\n@HiltAndroidApp\nclass MApplication : MultiDexApplication(), LifecycleObserver,Configuration.Provider {\n\n    @Inject\n    lateinit var preference: MPreference\n\n    @Inject\n    lateinit var userDao: ChatUserDao\n\n    @Inject\n    lateinit var messageDao: MessageDao\n\n    @Inject\n    lateinit var userCollection: CollectionReference\n\n    @Inject lateinit var workerFactory: HiltWorkerFactory\n\n    companion object {\n        lateinit var instance: MApplication\n            private set\n        var isAppRunning = false\n        lateinit var appContext: Context\n        lateinit var userDaoo: ChatUserDao\n        lateinit var messageDaoo: MessageDao\n    }\n\n    override fun onCreate() {\n        super.onCreate()\n        instance = this\n        appContext = this\n        userDaoo = userDao\n        messageDaoo=messageDao\n        FirebaseApp.initializeApp(this)\n        initTimber()\n        if (preference.isLoggedIn())\n            checkLastDevice()   //looking for does user is logged in another device.if yes,need to shoe dialog for log in again\n    }\n\n\n    override fun getWorkManagerConfiguration() =\n        Configuration.Builder()\n            .setWorkerFactory(workerFactory)\n            .build()\n\n    private fun initTimber() {\n        if (BuildConfig.DEBUG) {\n            Timber.plant(object : Timber.DebugTree() {\n                override fun createStackElementTag(element: StackTraceElement): String {\n                    return \"LetsChat/${element.fileName}:${element.lineNumber})#${element.methodName}\"\n                }\n            })\n        }\n    }\n\n    private fun checkLastDevice() {\n        userCollection.document(preference.getUid()!!).get().addOnSuccessListener { data ->\n            Timber.v(\"Device Checked\")\n            val appUser = data.toObject(UserProfile::class.java)\n            checkDeviceDetails(appUser)\n        }.addOnFailureListener { e ->\n            LogMessage.v(e.message.toString())\n        }\n    }\n\n    private fun checkDeviceDetails(appUser: UserProfile?) {\n        val device = appUser?.deviceDetails\n        val localDevice = UserUtils.getDeviceId(this)\n        if (device != null) {\n            val sameDevice = device.device_id.equals(localDevice)\n            preference.setLastDevice(sameDevice)\n            Timber.v(\"Device Checked ${device.device_id.equals(localDevice)}\")\n            if (sameDevice)\n                UserUtils.updatePushToken(this,userCollection, true)\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/core/ChatHandler.kt",
    "content": "package com.gowtham.letschat.core\n\nimport android.content.Context\nimport androidx.lifecycle.MutableLiveData\nimport com.google.firebase.firestore.*\nimport com.gowtham.letschat.FirebasePush\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Message\nimport com.gowtham.letschat.fragments.single_chat.toDataClass\nimport com.gowtham.letschat.utils.LogMessage\nimport com.gowtham.letschat.utils.MPreference\nimport com.gowtham.letschat.utils.UserUtils\nimport com.gowtham.letschat.utils.getUnreadCount\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.coroutines.*\nimport timber.log.Timber\nimport javax.inject.Inject\nimport javax.inject.Singleton\n\n@Singleton\nclass ChatHandler @Inject constructor(\n    @ApplicationContext private val context: Context,\n    private val dbRepository: DbRepository,\n    private val usersCollection: CollectionReference,\n    private val preference: MPreference,\n    private val messageStatusUpdater: MessageStatusUpdater\n) {\n\n    private val messagesList: MutableList<Message> by lazy { mutableListOf() }\n\n    private var fromUser = preference.getUid()\n\n    val message = MutableLiveData<String>()\n\n    private lateinit var chatUsers: List<ChatUser>\n\n    private val listOfDocs = ArrayList<String>()\n\n    private lateinit var messageCollectionGroup: Query\n\n    private val chatUserUtil = ChatUserUtil(dbRepository, usersCollection, null)\n\n    private var isFirstQuery = false\n\n    companion object {\n\n        private var listenerDoc1: ListenerRegistration? = null\n        private var instanceCreated = false\n\n        fun removeListeners() {\n            instanceCreated = false\n            listenerDoc1?.remove()\n        }\n    }\n\n    fun initHandler() {\n        if (instanceCreated)\n            return\n        instanceCreated = true\n        fromUser = preference.getUid()\n        Timber.v(\"ChatHandler init\")\n        messageCollectionGroup = UserUtils.getMessageSubCollectionRef()\n        preference.clearCurrentUser()\n\n        listenerDoc1 = messageCollectionGroup.whereArrayContains(\"chatUsers\", fromUser!!)\n            .addSnapshotListener { snapShots, error ->\n                if (error != null || snapShots == null || snapShots.metadata.isFromCache) {\n                    LogMessage.v(\"Error ${snapShots?.metadata?.isFromCache}\")\n                    if(snapShots?.metadata?.isFromCache == true)\n                        onFetchDocuments()\n                    return@addSnapshotListener\n                }else\n                 onSnapShotChanged(snapShots)\n            }\n    }\n\n    private fun onFetchDocuments() {\n        messageCollectionGroup.whereArrayContains(\"chatUsers\", fromUser!!).get().addOnSuccessListener {\n             isFirstQuery=true\n            onSnapShotChanged(it)\n        }\n    }\n\n    private fun onSnapShotChanged(snapShots: QuerySnapshot) {\n        messagesList.clear()\n        listOfDocs.clear()\n        val listOfIds = ArrayList<String>()\n\n        if (isFirstQuery) {\n            snapShots.forEach { doc ->\n                val parentDoc = doc.reference.parent.parent?.id!!\n                val message = doc.data.toDataClass<Message>()\n                message.chatUserId =\n                    if (message.from != fromUser) message.from else message.to\n                messagesList.add(message)\n                if (!listOfDocs.contains(parentDoc)) {\n                    listOfDocs.add(doc.reference.parent.parent?.id.toString())\n                    listOfIds.add(message.chatUserId!!)\n                }\n            }\n            isFirstQuery=false\n        } else\n            for (shot in snapShots.documentChanges) {\n                if (shot.type == DocumentChange.Type.ADDED ||\n                    shot.type == DocumentChange.Type.MODIFIED\n                ) {\n                    val document = shot.document\n                    val parentDoc = document.reference.parent.parent?.id!!\n                    val message = document.data.toDataClass<Message>()\n                    message.chatUserId =\n                        if (message.from != fromUser) message.from else message.to\n                    messagesList.add(message)\n                    if (!listOfDocs.contains(parentDoc)) {\n                        listOfDocs.add(document.reference.parent.parent?.id.toString())\n                        listOfIds.add(message.chatUserId!!)\n                    }\n                }\n            }\n        if (!messagesList.isNullOrEmpty())\n            insertMessageOnDb(listOfIds)\n    }\n\n    private fun insertMessageOnDb(listOfIds: ArrayList<String>) {\n        CoroutineScope(Dispatchers.IO).launch {\n            val contacts = ArrayList<ChatUser>()\n            val newContactIds =\n                ArrayList<String>()  //message from new user not saved in localdb yet\n            chatUsers = dbRepository.getChatUserList()\n            dbRepository.insertMultipleMessage(messagesList)\n            for ((index, doc) in listOfDocs.withIndex()) {\n                val chatUser = chatUsers.firstOrNull { it.id == listOfIds[index] }\n                if (chatUser == null) {\n                    newContactIds.add(listOfIds[index])\n                    //message from unsaved user\n                } else {\n                    chatUser.unRead = if (preference.getOnlineUser() == chatUser.id) 0 else\n                        dbRepository.getChatsOfFriend(chatUser.id).getUnreadCount(chatUser.id)\n                    chatUser.documentId = doc\n                    Timber.v(\"UserId ${chatUser.id}  count ${chatUser.unRead}\")\n                    contacts.add(chatUser)\n                }\n            }\n            dbRepository.insertMultipleUsers(contacts)\n            val currentChatUser = if (preference.getOnlineUser().isNotEmpty())\n                contacts.firstOrNull { it.id == preference.getOnlineUser() }\n            else null\n            val allUnReadMsgs = dbRepository.getAllNonSeenMessage()\n            withContext(Dispatchers.Main) {\n                updateMsgStatus(newContactIds, currentChatUser, allUnReadMsgs)\n            }\n        }\n\n    }\n\n    private fun updateMsgStatus(\n        newContactIds: ArrayList<String>,\n        currentChatUser: ChatUser?,\n        allUnReadMsgs: List<Message>\n    ) {\n        showNotification(newContactIds)\n        if (currentChatUser != null) {\n            val currentUserMsgs = allUnReadMsgs.filter {\n                it.chatUserId == currentChatUser.id\n            }\n            val otherUserMsgs = allUnReadMsgs.filter {\n                it.chatUserId != currentChatUser.id\n            }\n            messageStatusUpdater.updateToDelivery(otherUserMsgs, *chatUsers.toTypedArray())\n            messageStatusUpdater.updateToSeen(\n                currentChatUser.id, currentChatUser.documentId!!, currentUserMsgs\n            )\n        } else {\n            messageStatusUpdater.updateToDelivery(allUnReadMsgs, *chatUsers.toTypedArray())\n        }\n    }\n\n    private fun showNotification(\n        newContactIds: ArrayList<String>\n    ) {\n        if (newContactIds.isEmpty()) {\n            val lastMsgId = messagesList.maxOf { it.createdAt }\n            val msg = messagesList.find { it.createdAt == lastMsgId }\n            if (msg != null && msg.from != fromUser)\n                FirebasePush.showNotification(context, dbRepository)\n        } else {\n            //unsaved new user\n            for (i in 0 until newContactIds.size) {\n                val userId = newContactIds[i]\n                if (userId == preference.getOnlineUser())\n                    continue\n\n                val unreadCount = messagesList.getUnreadCount(userId)\n                chatUserUtil.queryNewUserProfile(\n                    context,\n                    userId,\n                    listOfDocs.firstOrNull { it.contains(userId) }, unreadCount,\n                    showNotification = i == newContactIds.lastIndex\n                )\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/core/ChatUserProfileListener.kt",
    "content": "package com.gowtham.letschat.core\n\nimport android.content.Context\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.ListenerRegistration\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.MPreference\nimport com.gowtham.letschat.utils.UserUtils\nimport com.gowtham.letschat.utils.Utils\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport timber.log.Timber\nimport javax.inject.Inject\nimport javax.inject.Singleton\n\n@Singleton\nclass ChatUserProfileListener @Inject\nconstructor(@ApplicationContext val context: Context,\n             private val userCollectionRef: CollectionReference,\n             private val preference: MPreference,\n             private val dbRepository: DbRepository){\n\n    private var instanceCreated=false\n\n    companion object{\n        private val listOfListeners=ArrayList<ListenerRegistration>()\n        fun removeListener(){\n            listOfListeners.forEach {\n                it.remove()\n            }\n        }\n    }\n\n    private fun getChatUsers() {\n        CoroutineScope(Dispatchers.IO).launch {\n            val users=dbRepository.getChatUserList()\n            withContext(Dispatchers.Main){\n                addSnapShotListener(users)\n            }\n        }\n    }\n\n    private fun addSnapShotListener(users: List<ChatUser>) {\n        val myUserId=preference.getUid().toString()\n        for (user in users){\n            if (user.id==myUserId)\n                continue\n            val listener=  userCollectionRef.document(user.id).addSnapshotListener { profile, error ->\n                if (error!=null) {\n                    Timber.v(error)\n                    return@addSnapshotListener\n                }\n                val userProfile = profile?.toObject(UserProfile::class.java)\n                userProfile?.let { pro->\n                    val chatUser=users.firstOrNull { it.id== pro.uId }\n                    if (chatUser!=null){\n                        chatUser.user=pro\n                        checkForContactSaved(chatUser,pro.mobile?.number!!)\n                        updateInLocal(chatUser)\n                    }\n                }\n            }\n            listOfListeners.add(listener)\n        }\n    }\n\n    private fun updateInLocal(chatUser: ChatUser) {\n        val chatUserId=chatUser.id\n        dbRepository.insertUser(chatUser)\n        //updating in groups\n        CoroutineScope(Dispatchers.IO).launch {\n            val groups=dbRepository.getGroupList()\n            val containingList= mutableListOf<Group>()\n            for (group in groups){\n                val members=group.members\n                val isContains= members?.any { it.id == chatUserId } ?: false\n                if (isContains){\n                    val index=members?.indexOfFirst { it.id==chatUserId }\n                    members!![index!!]=chatUser\n                    containingList.add(group)\n                }\n            }\n            dbRepository.insertMultipleGroup(containingList)\n        }\n    }\n\n    private fun checkForContactSaved(chatUser: ChatUser, mobileNo: String) {\n        if (Utils.isContactPermissionOk(context)) {\n            val contacts = UserUtils.fetchContacts(context)\n            val savedContact=contacts.firstOrNull { it.mobile.contains(mobileNo) }\n            if (savedContact!=null){\n                chatUser.localName=savedContact.name\n                chatUser.locallySaved=true\n            }else{\n                //contact deleted\n                val profile=chatUser.user\n                val mobile = profile.mobile?.country + \" \" + profile.mobile?.number\n                chatUser.localName=mobile\n                chatUser.locallySaved=false\n            }\n        }\n    }\n\n    fun initListener() {\n        if (!instanceCreated) {\n            getChatUsers()\n            instanceCreated=true\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/core/ChatUserUtil.kt",
    "content": "package com.gowtham.letschat.core\n\nimport android.content.Context\nimport com.google.firebase.firestore.CollectionReference\nimport com.gowtham.letschat.FirebasePush\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.OnSuccessListener\nimport com.gowtham.letschat.utils.UserUtils\nimport com.gowtham.letschat.utils.Utils\n\nclass ChatUserUtil(private val dbRepository: DbRepository,\n                   private val usersCollection: CollectionReference,\n                   private val listener: OnSuccessListener?) {\n\n    fun queryNewUserProfile(context: Context,chatUserId: String,docId: String?, unReadCount: Int=1,\n                            showNotification: Boolean=false) {\n        try {\n            usersCollection.document(chatUserId)\n                .get().addOnSuccessListener { profile ->\n                    if (profile.exists()) {\n                        val userProfile = profile.toObject(UserProfile::class.java)\n                        val mobile = userProfile?.mobile?.country + \" \" + userProfile?.mobile?.number\n                        val chatUser = ChatUser(userProfile?.uId!!, mobile, userProfile)\n                        chatUser.unRead=unReadCount\n                        if(docId!=null)\n                            chatUser.documentId=docId\n                        if (Utils.isContactPermissionOk(context)) {\n                            val contacts = UserUtils.fetchContacts(context)\n                            val savedContact=contacts.firstOrNull { it.mobile.contains(userProfile.mobile!!.number) }\n                            savedContact?.let {\n                                chatUser.localName=it.name\n                                chatUser.locallySaved=true\n                            }\n                        }\n                        listener?.onResult(true,chatUser)\n                        dbRepository.insertUser(chatUser)\n                        if(showNotification)\n                        FirebasePush.showNotification(context,dbRepository)\n                    }\n                }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/core/ContactsQuery.kt",
    "content": "package com.gowtham.letschat.core\n\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.UserUtils\nimport timber.log.Timber\n\ninterface QueryCompleteListener{\n    fun onQueryCompleted(queriedList: ArrayList<UserProfile>)\n}\n\nclass ContactsQuery(val list: ArrayList<String>,val position: Int,val listener: QueryCompleteListener){\n\n    private val usersCollection = FirebaseFirestore.getInstance().collection(\"Users\")\n\n    fun makeQuery() {\n        try {\n            usersCollection.whereIn(\"mobile.number\", list).get()\n                .addOnSuccessListener { documents ->\n                    for (document in documents) {\n                        val contact = document.toObject(UserProfile::class.java)\n                        UserUtils.queriedList.add(contact)\n                    }\n                    UserUtils.resultCount += 1\n                    if(UserUtils.resultCount == UserUtils.totalRecursionCount){\n                        listener.onQueryCompleted(UserUtils.queriedList)\n                    }\n                }\n                .addOnFailureListener { exception ->\n                    Timber.wtf(\"Error getting documents: ${exception.message}\")\n                    UserUtils.resultCount += 1\n                    if(UserUtils.resultCount == UserUtils.totalRecursionCount)\n                        listener.onQueryCompleted(UserUtils.queriedList)\n                }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/core/GroupChatHandler.kt",
    "content": "package com.gowtham.letschat.core\n\nimport android.content.Context\nimport com.google.firebase.firestore.*\nimport com.gowtham.letschat.FirebasePush\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.db.data.GroupMessage\nimport com.gowtham.letschat.di.GroupCollection\nimport com.gowtham.letschat.fragments.single_chat.toDataClass\nimport com.gowtham.letschat.utils.LogMessage\nimport com.gowtham.letschat.utils.MPreference\nimport com.gowtham.letschat.utils.UserUtils\nimport com.gowtham.letschat.utils.Utils\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport timber.log.Timber\nimport javax.inject.Inject\nimport javax.inject.Singleton\n\n@Singleton\nclass GroupChatHandler @Inject constructor(\n    @ApplicationContext private val context: Context,\n    private val preference: MPreference,\n    private val userCollection: CollectionReference,\n    @GroupCollection\n    private val groupCollection: CollectionReference,\n    private val dbRepository: DbRepository,\n    private val groupMsgStatusUpdater: GroupMsgStatusUpdater\n) {\n\n    private var userId = preference.getUid()\n\n    private lateinit var messageCollectionGroup: Query\n\n    private val messagesList = mutableListOf<GroupMessage>()\n\n    private val listOfGroup = ArrayList<String>()\n\n    private var isFirstQuery = false\n\n    companion object {\n        private var groupListener: ListenerRegistration? = null\n        private var myProfileListener: ListenerRegistration? = null\n        private var instanceCreated = false\n\n        fun removeListener() {\n            instanceCreated = false\n            groupListener?.remove()\n            myProfileListener?.remove()\n        }\n    }\n\n    fun initHandler() {\n        if (instanceCreated)\n            return\n        else\n            instanceCreated = true\n        userId = preference.getUid()\n        Timber.v(\"GroupChatHandler init\")\n        preference.clearCurrentGroup()\n        messageCollectionGroup = UserUtils.getGroupMsgSubCollectionRef()\n        addGroupsSnapShotListener()\n        addGroupMsgListener()\n    }\n\n    private fun addGroupMsgListener() {\n        try {\n            groupListener = messageCollectionGroup.whereArrayContains(\"to\", userId!!)\n                .addSnapshotListener { snapshots, error ->\n                    if (error != null || snapshots == null || snapshots.metadata.isFromCache) {\n                        LogMessage.v(\"Error ${error?.localizedMessage}\")\n                        return@addSnapshotListener\n                    }\n                    messagesList.clear()\n                    listOfGroup.clear()\n\n                    onSnapShotChanged(snapshots)\n\n                    if (messagesList.isNotEmpty())\n                        updateGroupUnReadCount()\n                }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n\n    }\n\n    private fun onSnapShotChanged(snapshots: QuerySnapshot) {\n        if(isFirstQuery){\n            snapshots.forEach { doc->\n                val message = doc.data.toDataClass<GroupMessage>()\n                if (!listOfGroup.contains(message.groupId))\n                    listOfGroup.add(message.groupId)\n                messagesList.add(message)\n            }\n            isFirstQuery=false\n        }\n        else\n        for (shot in snapshots.documentChanges) {\n            if (shot.type == DocumentChange.Type.ADDED ||\n                shot.type == DocumentChange.Type.MODIFIED\n            ) {\n                val message = shot.document.data.toDataClass<GroupMessage>()\n                if (!listOfGroup.contains(message.groupId))\n                    listOfGroup.add(message.groupId)\n                messagesList.add(message)\n            }\n        }\n    }\n\n    private fun updateGroupUnReadCount() {\n        CoroutineScope(Dispatchers.IO).launch {\n            dbRepository.insertMultipleGroupMessage(messagesList)\n            val groupsWithMsgs = dbRepository.getGroupWithMessagesList()\n            messagesList.clear()\n            for (groupWithMsg in groupsWithMsgs) {\n                val unreadCount = groupWithMsg.messages.filter {\n                    val myStatus = Utils.myMsgStatus(userId.toString(), it)\n                    it.from != userId &&\n                            it.groupId == groupWithMsg.group.id && myStatus < 3\n                }.size\n                groupWithMsg.group.unRead =\n                    if (preference.getOnlineGroup() == groupWithMsg.group.id) 0\n                    else unreadCount\n                messagesList.addAll(groupWithMsg.messages)\n            }\n            val groups = groupsWithMsgs.map {\n                it.group\n            }\n            dbRepository.insertMultipleGroup(groups)\n            changeMsgStatus(groups)\n        }\n    }\n\n    private fun changeMsgStatus(groups: List<Group>) {\n        if (groups.isNotEmpty())\n            FirebasePush.showGroupNotification(context, dbRepository)\n        val currentOnlineGroupId=preference.getOnlineGroup()\n        if(currentOnlineGroupId.isNotEmpty()){\n            val currentGroupMsgs = messagesList.filter {\n                it.groupId == currentOnlineGroupId\n            }\n            val otherGroupMsgs = messagesList.filter {\n                it.groupId != currentOnlineGroupId\n            }\n            groupMsgStatusUpdater.updateToSeen(userId!!, currentGroupMsgs,currentOnlineGroupId)\n            groupMsgStatusUpdater.updateToDelivery(userId!!, otherGroupMsgs, *listOfGroup.toTypedArray())\n        }else\n            groupMsgStatusUpdater.updateToDelivery(userId!!, messagesList, *listOfGroup.toTypedArray())\n\n    }\n\n    private fun addGroupsSnapShotListener() {\n        myProfileListener =\n            userCollection.document(userId.toString()).addSnapshotListener { snapshot, error ->\n                if (error == null) {\n                    val groups = snapshot?.get(\"groups\")\n                    val listOfGroup =\n                        if (groups == null) ArrayList() else groups as ArrayList<String>\n                    CoroutineScope(Dispatchers.IO).launch {\n                        val alreadySavedGroup = dbRepository.getGroupList().map { it.id }\n                        val removedGroups = alreadySavedGroup.toSet().minus(listOfGroup.toSet())\n                        val newGroups = listOfGroup.toSet().minus(alreadySavedGroup.toSet())\n                        queryNewGroups(newGroups)\n                    }\n                }\n            }\n    }\n\n    private fun queryNewGroups(newGroups: Set<String>) {\n        Timber.v(\"New groups ${newGroups.size}\")\n        for (groupId in newGroups) {\n            val groupQuery = GroupQuery(groupId, dbRepository, preference)\n            groupQuery.getGroupData(groupCollection)\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/core/GroupMsgSender.kt",
    "content": "package com.gowtham.letschat.core\n\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.SetOptions\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.db.data.GroupMessage\nimport com.gowtham.letschat.db.data.Message\n\ninterface OnGrpMessageResponse{\n    fun onSuccess(message: GroupMessage)\n    fun onFailed(message: GroupMessage)\n}\n\nclass GroupMsgSender(private val groupCollection: CollectionReference) {\n\n    fun sendMessage(message: GroupMessage,group: Group,listener: OnGrpMessageResponse){\n        message.status[0]=1\n        groupCollection.document(group.id).collection(\"group_messages\")\n            .document(message.createdAt.toString()).set(message, SetOptions.merge())\n            .addOnSuccessListener {\n                listener.onSuccess(message)\n            }.addOnFailureListener {\n                message.status[0]=4\n                listener.onFailed(message)\n            }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/core/GroupMsgStatusUpdater.kt",
    "content": "package com.gowtham.letschat.core\n\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.db.data.GroupMessage\nimport com.gowtham.letschat.di.GroupCollection\nimport com.gowtham.letschat.fragments.single_chat.asMap\nimport com.gowtham.letschat.fragments.single_chat.serializeToMap\nimport com.gowtham.letschat.utils.LogMessage\nimport com.gowtham.letschat.utils.Utils.myIndexOfStatus\nimport com.gowtham.letschat.utils.Utils.myMsgStatus\nimport javax.inject.Inject\nimport javax.inject.Singleton\n\n@Singleton\nclass GroupMsgStatusUpdater @Inject constructor(\n    @GroupCollection\n    private val groupCollection: CollectionReference,\n     private val firestore: FirebaseFirestore) {\n\n    fun updateToDelivery(myUserId: String, messageList: List<GroupMessage>, vararg groupId: String){\n        try {\n            val batch= firestore.batch()\n            for (id in groupId){\n                val msgSubCollection=groupCollection.document(id).collection(\"group_messages\")\n                val filterList=  messageList\n                    .filter { it.from!=myUserId && myMsgStatus(myUserId,it)==0 && it.groupId==id }\n                    .map {\n                        val myIndex=myIndexOfStatus(myUserId,it)\n                        it.status[myIndex]=2\n                        it.deliveryTime[myIndex]=System.currentTimeMillis()\n                        it\n                    }\n                    for (msg in filterList){\n                        LogMessage.v(\"message date ${msg.deliveryTime}\")\n                        batch.update(msgSubCollection\n                            .document(msg.createdAt.toString()),msg.asMap())\n                    }\n            }\n            batch.commit().addOnSuccessListener {\n                LogMessage.v(\"Batch update success from group\")\n            }.addOnFailureListener {\n                LogMessage.v(\"Batch update failure ${it.message} from group\")\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun updateToSeen(myUserId: String, messageList: List<GroupMessage>, groupId: String){\n        val batch= firestore.batch()\n        val currentTime = System.currentTimeMillis()\n        val msgSubCollection=groupCollection.document(groupId).collection(\"group_messages\")\n            val filterList=  messageList\n                .filter { it.from!=myUserId && myMsgStatus(myUserId,it)<3 }\n                .map {\n                    val myIndex=myIndexOfStatus(myUserId,it)\n                    it.status[myIndex]=3\n                    it.deliveryTime[myIndex]= if (it.deliveryTime[myIndex]==0L)\n                        currentTime else it.deliveryTime[myIndex]\n                    it.seenTime[myIndex]=currentTime\n                    it\n                }\n\n            if (filterList.isNotEmpty()){\n                for (msg in filterList){\n                    batch.update(msgSubCollection\n                        .document(msg.createdAt.toString()),msg.serializeToMap())\n                }\n            }\n        batch.commit().addOnSuccessListener {\n            LogMessage.v(\"Seen Batch update success from group\")\n        }.addOnFailureListener {\n            LogMessage.v(\"Seen Batch update failure ${it.message} from group\")\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/core/GroupQuery.kt",
    "content": "package com.gowtham.letschat.core\n\nimport com.google.firebase.firestore.CollectionReference\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.utils.MPreference\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport timber.log.Timber\n\nclass GroupQuery(private val groupId: String,private val dbRepository: DbRepository,private val preference: MPreference) {\n\n    private val myUserId=preference.getUid()!!\n\n   fun getGroupData(groupCollection: CollectionReference){\n       val userId=preference.getUid()\n       groupCollection.document(groupId).get().addOnSuccessListener { snapshot->\n           snapshot?.let { data ->\n               if (!data.exists())\n                   return@addOnSuccessListener\n               val group=data.toObject(Group::class.java)\n               val profiles=group?.profiles\n               val index=profiles!!.indexOfFirst { it.uId==userId }\n               profiles.removeAt(index)\n               profiles.add(0,preference.getUserProfile()!!)  //moving localuser to 0 th index\n               group.profiles=profiles\n               CoroutineScope(Dispatchers.IO).launch {\n                   checkAlreadySavedMember(group, dbRepository.getChatUserList())\n               }\n           }\n       }.addOnFailureListener {\n           Timber.v(\"GroupDataGrtting failed ${it.message}\")\n       }\n    }\n\n    private fun checkAlreadySavedMember(group: Group, list: List<ChatUser>){\n         val chatUsers= ArrayList<ChatUser>()\n        for (profile in group.profiles!!){\n            if (profile.uId==myUserId) {\n                chatUsers.add(ChatUser(myUserId, \"You\", profile))\n                continue\n            }\n            val chatUser=list.firstOrNull { it.id==profile.uId }\n            if (chatUser==null){\n                val localName=\"${profile.mobile?.country} ${profile.mobile?.number}\"\n                val user=ChatUser(profile.uId.toString(),localName,profile)\n                chatUsers.add(user)\n            }else\n                chatUsers.add(chatUser)\n        }\n        group.members=chatUsers\n        group.profiles= ArrayList()\n        dbRepository.insertMultipleUser(chatUsers)\n        dbRepository.insertGroup(group)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/core/MessageSender.kt",
    "content": "package com.gowtham.letschat.core\n\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.FieldValue\nimport com.google.firebase.firestore.SetOptions\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.data.Message\nimport com.gowtham.letschat.utils.LogMessage\nimport com.gowtham.letschat.utils.UserUtils\nimport timber.log.Timber\n\ninterface OnMessageResponse{\n    fun onSuccess(message: Message)\n    fun onFailed(message: Message)\n}\n\nclass MessageSender(private val msgCollection: CollectionReference,\n                    private val dbRepo: DbRepository, private val chatUser: ChatUser,\n                    private val listener: OnMessageResponse) {\n\n    fun checkAndSend(fromUser: String, toUser: String, message: Message) {\n        val docId = chatUser.documentId\n        if (!docId.isNullOrEmpty()){\n            Timber.v(\"Case 0 ${chatUser.documentId}\")\n            send(docId, message)\n       } else {\n            //so we don't create multiple nodes for same chat\n            msgCollection.document(\"${fromUser}_${toUser}\").get()\n                .addOnSuccessListener { documentSnapshot ->\n                    if (documentSnapshot.exists()) {\n                        //this node exists send your message\n                        Timber.v(\"Case 1\")\n                        send(\"${fromUser}_${toUser}\", message)\n                    } else {\n                        //senderId_receiverId node doesn't exist check receiverId_senderId\n                        msgCollection.document(\"${toUser}_${fromUser}\").get()\n                            .addOnSuccessListener { documentSnapshot2 ->\n                                if (documentSnapshot2.exists()) {\n                                    Timber.v(\"Case 2\")\n                                    send(\"${toUser}_${fromUser}\", message)\n                                } else {\n                                    //no previous chat history(senderId_receiverId & receiverId_senderId both don't exist)\n                                    //so we create document senderId_receiverId then messages array then add messageMap to messages\n                                    //this node exists send your message\n                                    //add ids of chat members\n                                    Timber.v(\"Case 3\")\n                                    msgCollection.document(\"${fromUser}_${toUser}\")\n                                        .set(mapOf(\"chat_members\" to FieldValue.arrayUnion(fromUser, toUser)),\n                                            SetOptions.merge()\n                                        ).addOnSuccessListener {\n                                            LogMessage.v(\"chat member update successfully\")\n                                            send(\"${fromUser}_${toUser}\", message)\n                                        }.addOnFailureListener {\n                                            LogMessage.v(\"chat member update failed ${it.message}\")\n                                        }\n                                }\n                            }\n                    }\n                }\n        }\n    }\n\n    private fun send(doc: String, message: Message){\n        try {\n            chatUser.documentId=doc\n            dbRepo.insertUser(chatUser)\n            val chatUserId=message.chatUserId\n            message.chatUserId=null  //chatUserId field is being used only for relation query,changing to null will ignore this field\n            message.status=1\n            message.chatUsers= arrayListOf(message.from,message.to)\n            msgCollection.document(doc).collection(\"messages\").document(message.createdAt.toString()).set(\n                message,\n                SetOptions.merge()\n            ).addOnSuccessListener {\n                    LogMessage.v(\"Message sender Sucesss ${message.createdAt}\")\n                    message.chatUserId=chatUserId\n                    listener.onSuccess(message)\n                }.addOnFailureListener {\n                    message.chatUserId=chatUserId\n                    message.status=4\n                LogMessage.v(\"Message sender Failed ${it.message}\")\n                    listener.onFailed(message)\n                }\n  /*          msgCollection.document(doc)\n                .update(\"messages\",\n                    FieldValue.arrayUnion(message.serializeToMap())).addOnSuccessListener {\n                    LogMessage.v(\"Message sender Sucesss ${message.textMessage?.text}\")\n                    listener.onSuccess(message)\n                }.addOnFailureListener {\n                    message.status=4\n                    LogMessage.v(\"Message sender Failed ${it.message}\")\n                    listener.onFailed(message)\n                }*/\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/core/MessageStatusUpdater.kt",
    "content": "package com.gowtham.letschat.core\n\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Message\nimport com.gowtham.letschat.di.MessageCollection\nimport com.gowtham.letschat.fragments.single_chat.asMap\nimport com.gowtham.letschat.fragments.single_chat.serializeToMap\nimport com.gowtham.letschat.utils.LogMessage\nimport timber.log.Timber\nimport javax.inject.Inject\nimport javax.inject.Singleton\n\n@Singleton\nclass MessageStatusUpdater @Inject constructor(\n    @MessageCollection\n    private val msgCollection: CollectionReference,\n    private val firebaseFirestore: FirebaseFirestore\n) {\n\n    fun updateToDelivery(messageList: List<Message>, vararg chatUsers: ChatUser) {\n        val batch = firebaseFirestore.batch()\n        for (chatUser in chatUsers) {\n            if (chatUser.documentId.isNullOrBlank())\n                continue\n            val msgSubCollection =\n                msgCollection.document(chatUser.documentId!!).collection(\"messages\")\n            val filterList = messageList\n                .filter { msg -> msg.status == 1 && msg.from == chatUser.id }\n                .map {\n                    it.chatUserId = null\n                    it.status = 2\n                    it.deliveryTime = System.currentTimeMillis()\n                    it\n                }\n            if (filterList.isNotEmpty()) {\n                for (msg in filterList) {\n                    batch.update(\n                        msgSubCollection\n                            .document(msg.createdAt.toString()), msg.serializeToMap()\n                    )\n                }\n            }\n        }\n        batch.commit().addOnSuccessListener {\n            LogMessage.v(\"Batch update success from home\")\n        }.addOnFailureListener {\n            LogMessage.v(\"Batch update failure ${it.message} from home\")\n        }\n    }\n\n     fun updateToSeen(toUser: String, docId: String?, messageList: List<Message>) {\n         if(docId==null)\n             return\n        val msgSubCollection = msgCollection.document(docId).collection(\"messages\")\n        val batch = firebaseFirestore.batch()\n        val currentTime = System.currentTimeMillis()\n        val filterList = messageList\n            .filter { msg -> msg.from == toUser && msg.status != 3 }\n            .map {\n                it.status = 3\n                it.chatUserId = null\n                it.deliveryTime = it.deliveryTime\n                it.seenTime = currentTime\n                it\n            }\n        if (filterList.isNotEmpty()) {\n            Timber.v(\"Size of list ${filterList.last().createdAt}\")\n            for (message in filterList) {\n                batch.update(\n                    msgSubCollection\n                        .document(message.createdAt.toString()), message.serializeToMap()\n                )\n            }\n            batch.commit().addOnSuccessListener {\n                LogMessage.v(\"All Message Seen Batch update success\")\n            }.addOnFailureListener {\n                LogMessage.v(\"All Message Seen Batch update failure ${it.message}\")\n            }\n        } else\n            LogMessage.v(\"All message already seen\")\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/ChatUserDatabase.kt",
    "content": "package com.gowtham.letschat.db\n\nimport androidx.room.Database\nimport androidx.room.RoomDatabase\nimport androidx.room.TypeConverters\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.daos.GroupMessageDao\nimport com.gowtham.letschat.db.daos.MessageDao\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.db.data.GroupMessage\nimport com.gowtham.letschat.db.data.Message\n\n@Database(entities = [ChatUser::class, Message::class,Group::class,GroupMessage::class],\n    version = 1, exportSchema = false)\n@TypeConverters(TypeConverter::class)\nabstract class ChatUserDatabase : RoomDatabase()  {\n    abstract fun getChatUserDao(): ChatUserDao\n    abstract fun getMessageDao(): MessageDao\n    abstract fun getGroupDao(): GroupDao\n    abstract fun getGroupMessageDao(): GroupMessageDao\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/DbRepository.kt",
    "content": "package com.gowtham.letschat.db\n\nimport android.content.Context\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.daos.GroupMessageDao\nimport com.gowtham.letschat.db.daos.MessageDao\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.db.data.GroupMessage\nimport com.gowtham.letschat.db.data.Message\nimport com.gowtham.letschat.utils.LogMessage\nimport com.gowtham.letschat.utils.MPreference\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport java.util.*\nimport javax.inject.Inject\nimport javax.inject.Singleton\n\n@Singleton\nclass DbRepository @Inject constructor(\n    private val userDao: ChatUserDao,\n    private val groupDao: GroupDao,\n    private val groupMsgDao: GroupMessageDao,\n    private val messageDao: MessageDao) : DefaultDbRepo {\n\n    override fun insertUser(user: ChatUser) {\n        CoroutineScope(Dispatchers.IO).launch {\n            userDao.insertUser(user)\n        }\n    }\n\n    override fun insertMultipleUser(users: List<ChatUser>) {\n        CoroutineScope(Dispatchers.IO).launch {\n            userDao.insertMultipleUser(users)\n        }\n    }\n\n    override fun getChatUserWithMessages() = userDao.getChatUserWithMessages()\n\n    override fun getChatUserList() = userDao.getChatUserList()\n\n    override fun getChatUserWithMessagesList() = userDao.getChatUserWithMessagesList()\n\n    override fun getChatUserById(id: String) = userDao.getChatUserById(id)\n\n    override fun getAllChatUser() = userDao.getAllChatUser()\n\n    override fun nukeTable() {\n    }\n\n    override fun deleteUserById(userId: String) {\n    }\n\n    fun insertMultipleUser(finalList: ArrayList<ChatUser>) {\n        CoroutineScope(Dispatchers.IO).launch {\n            userDao.insertMultipleUser(finalList)\n        }\n    }\n\n    suspend fun insertMultipleUsers(users: ArrayList<ChatUser>){\n       userDao.insertMultipleUser(users)\n   }\n\n    fun insertGroup(group: Group) {\n        CoroutineScope(Dispatchers.IO).launch {\n            groupDao.insertGroup(group)\n        }\n    }\n\n    suspend fun insertMultipleMessage(messagesList: MutableList<Message>) =\n            messageDao.insertMultipleMessage(messagesList)\n\n\n    suspend fun insertMultipleGroupMessage(messagesList: List<GroupMessage>) =\n            groupMsgDao.insertMultipleMessage(messagesList)\n\n    fun getAllNonSeenMessage() =\n        messageDao.getAllNotSeenMessages()\n\n    fun insertMessage(message: Message) {\n        CoroutineScope(Dispatchers.IO).launch {\n            messageDao.insertMessage(message)\n        }\n    }\n\n    fun insertMessage(message: GroupMessage) {\n        CoroutineScope(Dispatchers.IO).launch {\n            groupMsgDao.insertMessage(message)\n        }\n    }\n\n   suspend fun insertMultipleGroup(groups: List<Group>) =\n            groupDao.insertMultipleGroup(groups)\n\n\n    fun getGroupWithMessages() = groupDao.getGroupWithMessages()\n\n    fun getMessagesByChatUserId(chatUserId: String) = messageDao.getMessagesByChatUserId(chatUserId)\n\n    fun getChatsOfFriend(toUser: String) = messageDao.getChatsOfFriend(toUser)\n\n    fun getGroupById(groupId: String) = groupDao.getGroupById(groupId)\n\n    fun getChatsOfGroupList(groupId: String) = groupMsgDao.getChatsOfGroupList(groupId)\n\n    fun getChatsOfGroup(groupId: String) = groupMsgDao.getChatsOfGroup(groupId)\n\n    fun getGroupWithMessagesList() = groupDao.getGroupWithMessagesList()\n\n    fun getMessageList() = messageDao.getMessageList()\n\n    fun getGroupList() = groupDao.getGroupList()\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/DefaultDbRepo.kt",
    "content": "package com.gowtham.letschat.db\n\nimport androidx.lifecycle.LiveData\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.ChatUserWithMessages\nimport kotlinx.coroutines.flow.Flow\n\ninterface DefaultDbRepo {\n\n    fun insertUser(user: ChatUser)\n\n    fun insertMultipleUser(users: List<ChatUser>)\n\n    fun getAllChatUser(): LiveData<List<ChatUser>>\n\n    fun getChatUserList(): List<ChatUser>\n\n    fun getChatUserById(id: String): ChatUser?\n\n    fun deleteUserById(userId: String)\n\n    fun getChatUserWithMessages(): Flow<List<ChatUserWithMessages>>\n\n    fun getChatUserWithMessagesList(): List<ChatUserWithMessages>\n\n    fun nukeTable()\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/TypeConverter.kt",
    "content": "package com.gowtham.letschat.db\n\nimport androidx.room.TypeConverter\nimport com.gowtham.letschat.db.data.*\nimport com.gowtham.letschat.models.UserProfile\nimport kotlinx.serialization.json.Json\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.decodeFromString\n\nclass TypeConverter {\n\n    @TypeConverter\n    fun fromProfileToString(userProfile: UserProfile): String {\n        return Json.encodeToString(userProfile)\n    }\n\n    @TypeConverter\n    fun fromStringToProfile(userProfile: String): UserProfile {\n        return Json.decodeFromString(userProfile)\n    }\n\n    @TypeConverter\n    fun fromTextMessageToString(textMessage: TextMessage?): String {\n        return Json.encodeToString(textMessage ?: TextMessage())\n    }\n\n    @TypeConverter\n    fun fromStringToTextMessage(messageData: String): TextMessage {\n        return Json.decodeFromString(messageData)\n    }\n\n    @TypeConverter\n    fun fromImageMessageToString(imageMessage: ImageMessage?): String {\n        return Json.encodeToString(imageMessage ?: ImageMessage())\n    }\n\n\n    @TypeConverter\n    fun fromStringToImageMessage(messageData: String): ImageMessage {\n        return Json.decodeFromString(messageData)\n    }\n\n\n    @TypeConverter\n    fun fromAudioMessageToString(audioMessage: AudioMessage?): String {\n        return Json.encodeToString(audioMessage ?: AudioMessage())\n    }\n\n    @TypeConverter\n    fun fromStringToAudioMessage(messageData: String): AudioMessage {\n        return Json.decodeFromString(messageData)\n    }\n\n    @TypeConverter\n    fun fromVideoMessageToString(videoMessage: VideoMessage?): String {\n        return Json.encodeToString(videoMessage ?: VideoMessage())\n    }\n\n    @TypeConverter\n    fun fromStringToVideoMessage(messageData: String): VideoMessage {\n        return Json.decodeFromString(messageData)\n    }\n\n    @TypeConverter\n    fun fromFileMessageToString(fileMessage: FileMessage?): String {\n        return Json.encodeToString(fileMessage ?: FileMessage())\n    }\n\n    @TypeConverter\n    fun fromStringToFileMessage(messageData: String): FileMessage {\n        return Json.decodeFromString(messageData)\n    }\n\n    @TypeConverter\n    fun fromChatUserToString(chatUser: ChatUser): String {\n        return Json.encodeToString(chatUser)\n    }\n\n    @TypeConverter\n    fun fromStringToChatUser(chatUser: String): ChatUser {\n        return Json.decodeFromString(chatUser)\n    }\n\n    @TypeConverter\n    fun fromGroupToString(group: Group): String {\n        return Json.encodeToString(group)\n    }\n\n    @TypeConverter\n    fun fromStringToGroup(group: String): Group {\n        return Json.decodeFromString(group)\n    }\n\n    @TypeConverter\n    fun fromGroupMessageToString(groupMessage: GroupMessage): String {\n        return Json.encodeToString(groupMessage)\n    }\n\n    @TypeConverter\n    fun fromStringToGroupMessage(groupMessage: String): GroupMessage {\n        return Json.decodeFromString(groupMessage)\n    }\n\n    @TypeConverter\n    fun fromToMembersToString(to: ArrayList<String>): String {\n        return Json.encodeToString(to)\n    }\n\n    @TypeConverter\n    fun fromStringToMembers(to: String): ArrayList<String> {\n        return Json.decodeFromString(to)\n    }\n\n    @TypeConverter\n    fun fromProfilesToString(profiles: ArrayList<UserProfile>): String {\n        return Json.encodeToString(profiles)\n    }\n\n    @TypeConverter\n    fun fromStringToProfiles(profilesString: String): ArrayList<UserProfile> {\n        return Json.decodeFromString(profilesString)\n    }\n\n    @TypeConverter\n    fun fromGroupMembersToString(members: ArrayList<ChatUser>): String {\n        return Json.encodeToString(members)\n    }\n\n    @TypeConverter\n    fun fromStringToGroupMembers(members: String): ArrayList<ChatUser> {\n        return Json.decodeFromString(members)\n    }\n\n    @TypeConverter\n    fun fromGroupMsgStatusToString(status: ArrayList<Int>): String {\n        return Json.encodeToString(status)\n    }\n\n    @TypeConverter\n    fun fromStringToGroupMsgStatus(status: String): ArrayList<Int> {\n        return Json.decodeFromString(status)\n    }\n\n    @TypeConverter\n    fun fromSeenStatusListToString(status: ArrayList<Long>): String {\n        return Json.encodeToString(status)\n    }\n\n    @TypeConverter\n    fun fromStringToSeenStatusList(status: String): ArrayList<Long> {\n        return Json.decodeFromString(status)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/daos/ChatUserDao.kt",
    "content": "package com.gowtham.letschat.db.daos\n\nimport androidx.lifecycle.LiveData\nimport androidx.room.*\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.ChatUserWithMessages\nimport kotlinx.coroutines.flow.Flow\n\n@Dao\ninterface ChatUserDao {\n\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\n    suspend fun insertUser(user: ChatUser)\n\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\n    suspend fun insertMultipleUser(users: List<ChatUser>)\n\n    @Query(\"SELECT * FROM ChatUser ORDER BY localName ASC\")\n    fun getAllChatUser(): LiveData<List<ChatUser>>\n\n    @Query(\"SELECT * FROM ChatUser ORDER BY localName ASC\")\n    fun getChatUserList(): List<ChatUser>\n\n    @Query(\"SELECT * FROM ChatUser  WHERE id=:id\")\n    fun getChatUserById(id: String): ChatUser?\n\n    @Query(\"SELECT * FROM ChatUser  WHERE id=:id\")\n    suspend fun getChatUserById2(id: String): ChatUser?\n\n    @Query(\"DELETE FROM ChatUser WHERE id=:userId\")\n    suspend fun deleteUserById(userId: String)\n\n    @Query(\"DELETE FROM ChatUser\")\n    fun nukeTable()\n\n    @Transaction\n    @Query(\"SELECT * FROM ChatUser\")\n    fun getChatUserWithMessages(): Flow<List<ChatUserWithMessages>>\n\n    @Transaction\n    @Query(\"SELECT * FROM ChatUser\")\n    fun getChatUserWithMessagesList(): List<ChatUserWithMessages>\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/daos/GroupDao.kt",
    "content": "package com.gowtham.letschat.db.daos\n\nimport androidx.lifecycle.LiveData\nimport androidx.room.*\nimport com.gowtham.letschat.db.data.ChatUserWithMessages\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.db.data.GroupWithMessages\nimport kotlinx.coroutines.flow.Flow\n\n@Dao\ninterface GroupDao {\n\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\n    suspend fun insertGroup(group: Group)\n\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\n    suspend fun insertMultipleGroup(listOfGroup: List<Group>)\n\n    @Query(\"SELECT * FROM `Group` ORDER BY id ASC\")\n    fun getAllGroup(): LiveData<List<Group>>\n\n    @Query(\"SELECT * FROM `Group` ORDER BY id ASC\")\n    fun getGroupList(): List<Group>\n\n    @Query(\"SELECT * FROM `Group`  WHERE id=:groupId\")\n    fun getGroupById(groupId: String): Group?\n\n    @Query(\"DELETE FROM `Group` WHERE id=:groupId\")\n    suspend fun deleteGroupById(groupId: String)\n\n    @Query(\"DELETE FROM `Group`\")\n    fun nukeTable()\n\n    @Transaction\n    @Query(\"SELECT * FROM `Group`\")\n    fun getGroupWithMessagesList(): List<GroupWithMessages>\n\n    @Transaction\n    @Query(\"SELECT * FROM `Group`\")\n    fun getGroupWithMessages(): Flow<List<GroupWithMessages>>\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/daos/GroupMessageDao.kt",
    "content": "package com.gowtham.letschat.db.daos\n\nimport androidx.lifecycle.LiveData\nimport androidx.room.Dao\nimport androidx.room.Insert\nimport androidx.room.OnConflictStrategy\nimport androidx.room.Query\nimport com.gowtham.letschat.db.data.GroupMessage\nimport com.gowtham.letschat.db.data.GroupWithMessages\nimport com.gowtham.letschat.db.data.Message\nimport kotlinx.coroutines.flow.Flow\n\n@Dao\ninterface GroupMessageDao {\n\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\n    suspend fun insertMessage(message: GroupMessage)\n\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\n    suspend fun insertMultipleMessage(users: List<GroupMessage>)\n\n    @Query(\"SELECT * FROM GroupMessage\")\n    fun getAllMessages(): LiveData<List<GroupMessage>>\n\n    @Query(\"SELECT * FROM GroupMessage\")\n    fun getMessageList(): List<GroupMessage>\n\n    @Query(\"SELECT * FROM GroupMessage WHERE groupId=:groupId\")\n    fun getChatsOfGroupList(groupId: String): List<GroupMessage>\n\n    @Query(\"SELECT * FROM GroupMessage WHERE groupId=:groupId\")\n    fun getChatsOfGroup(groupId: String): Flow<List<GroupMessage>>\n\n    @Query(\"DELETE FROM GroupMessage  WHERE createdAt=:createdAt\")\n    suspend fun deleteMessageByCreatedAt(createdAt: Long)\n\n    @Query(\"DELETE FROM GroupMessage  WHERE groupId=:groupId\")\n    suspend fun deleteMessagesByGroupId(groupId: String)\n\n    @Query(\"DELETE FROM GroupMessage\")\n    fun nukeTable()\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/daos/MessageDao.kt",
    "content": "package com.gowtham.letschat.db.daos\n\nimport androidx.lifecycle.LiveData\nimport androidx.room.*\nimport com.gowtham.letschat.db.data.Message\nimport com.gowtham.letschat.utils.LogMessage\nimport kotlinx.coroutines.flow.Flow\n\n@Dao\ninterface MessageDao {\n\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\n    suspend fun insertMessage(message: Message)\n\n    @Insert(onConflict = OnConflictStrategy.REPLACE)\n    suspend fun insertMultipleMessage(users: List<Message>)\n\n    @Query(\"SELECT * FROM Message\")\n    fun getAllMessages(): Flow<List<Message>>\n\n    @Query(\"SELECT * FROM Message\")\n    fun getMessageList(): List<Message>\n\n    @Query(\"SELECT * FROM Message WHERE `chatUserId`=:chatUserId\")\n    fun getChatsOfFriend(chatUserId: String): List<Message>\n\n    @Query(\"SELECT * FROM Message WHERE `chatUserId`=:chatUserId\")\n    suspend fun getChatsOfFriend2(chatUserId: String): List<Message>\n\n    @Query(\"SELECT * FROM Message WHERE `to`=:chatUserId OR `from`=:chatUserId\")\n    fun getMessagesByChatUserId(chatUserId: String): Flow<List<Message>>\n\n    @Query(\"SELECT * FROM Message  WHERE createdAt=:createdAt\")\n    suspend fun getMessageById(createdAt: Long): Message?\n\n    @Query(\"SELECT * FROM Message  WHERE status<3\")\n    fun getAllNotSeenMessages() : List<Message>\n\n    @Query(\"DELETE FROM Message  WHERE createdAt=:createdAt\")\n    suspend fun deleteMessageByCreatedAt(createdAt: Long)\n\n    @Query(\"DELETE FROM Message WHERE `to`=:userId\")\n    suspend fun deleteMessagesByUserId(userId: String)\n\n    @Query(\"DELETE FROM Message\")\n    fun nukeTable()\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/data/ChatUser.kt",
    "content": "package com.gowtham.letschat.db.data\n\nimport android.os.Parcelable\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey\nimport com.google.firebase.firestore.IgnoreExtraProperties\nimport com.gowtham.letschat.models.UserProfile\nimport kotlinx.serialization.Serializable\n\n@IgnoreExtraProperties\n@Serializable\n@kotlinx.parcelize.Parcelize\n@Entity\ndata class ChatUser(\n    @PrimaryKey\n    var id: String,var localName: String,var user: UserProfile,\n    var documentId: String?=null,var locallySaved: Boolean=false,\n    var unRead: Int=0,var isSearchedUser: Boolean=false,var isSelected: Boolean=false): Parcelable"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/data/ChatUserWithMessages.kt",
    "content": "package com.gowtham.letschat.db.data\n\nimport android.os.Parcelable\nimport androidx.room.Embedded\nimport androidx.room.Relation\n\n@kotlinx.parcelize.Parcelize\nclass ChatUserWithMessages(\n    @Embedded\n    val user: ChatUser,\n    @Relation(\n        parentColumn = \"id\",\n        entityColumn = \"chatUserId\"\n    )\n    val messages: List<Message>) : Parcelable"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/data/Group.kt",
    "content": "package com.gowtham.letschat.db.data\n\nimport android.os.Parcelable\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey\nimport com.google.firebase.firestore.Exclude\nimport com.google.firebase.firestore.IgnoreExtraProperties\nimport com.gowtham.letschat.models.UserProfile\nimport kotlinx.serialization.Serializable\n\n@IgnoreExtraProperties\n@Serializable\n@kotlinx.parcelize.Parcelize\n@Entity\ndata class Group(@PrimaryKey\n                 var id: String=\"\",var createdBy: String=\"\",\n                 var createdAt: Long=0,\n                 var about: String=\"\", var image: String=\"\",\n                 @set:Exclude @get:Exclude\n                 var members: ArrayList<ChatUser>?=null, //only for storing in localdb\n                 var profiles: ArrayList<UserProfile>?=null,\n                 @set:Exclude @get:Exclude\n                 var unRead: Int=0): Parcelable"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/data/GroupMessage.kt",
    "content": "package com.gowtham.letschat.db.data\n\nimport android.os.Parcelable\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey\nimport com.google.firebase.firestore.IgnoreExtraProperties\nimport kotlinx.serialization.Serializable\n\n@IgnoreExtraProperties\n@Serializable\n@kotlinx.parcelize.Parcelize\n@Entity\ndata class GroupMessage(@PrimaryKey\n                        val createdAt: Long, var groupId: String,\n                        val from: String, val to: ArrayList<String>,\n                        val senderName: String,\n                        val senderImage: String,\n                        val status: ArrayList<Int>,//0 th index is status of from user\n                        val deliveryTime: ArrayList<Long>,\n                        val seenTime: ArrayList<Long>,\n                        var type: String=\"text\",//0=text,1=audio,2=image,3=video,4=file,5=s_image\n                        var textMessage: TextMessage?=null,\n                        var imageMessage: ImageMessage?=null,\n                        var audioMessage: AudioMessage?=null,\n                        var videoMessage: VideoMessage?=null,\n                        var fileMessage: FileMessage?=null): Parcelable"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/data/GroupWithMessages.kt",
    "content": "package com.gowtham.letschat.db.data\n\nimport android.os.Parcelable\nimport androidx.room.Embedded\nimport androidx.room.Relation\n\n@kotlinx.parcelize.Parcelize\nclass GroupWithMessages (\n    @Embedded\n    val group: Group,\n    @Relation(\n        parentColumn = \"id\",\n        entityColumn = \"groupId\"\n    )\n    val messages: List<GroupMessage>) : Parcelable"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/db/data/Message.kt",
    "content": "package com.gowtham.letschat.db.data\n\nimport android.os.Parcelable\nimport androidx.room.Entity\nimport androidx.room.PrimaryKey\nimport com.google.firebase.Timestamp\nimport com.google.firebase.firestore.Exclude\nimport com.google.firebase.firestore.IgnoreExtraProperties\nimport com.google.firebase.firestore.ServerTimestamp\nimport kotlinx.serialization.Serializable\n\n@IgnoreExtraProperties\n@Serializable\n@kotlinx.parcelize.Parcelize\n@Entity\ndata class Message(\n    @PrimaryKey\n    val createdAt: Long, var deliveryTime: Long=0L,\n    var seenTime: Long=0L,\n    val from: String, val to: String,\n    val senderName: String,\n    val senderImage: String,\n    var type: String=\"text\",//0=text,1=audio,2=image,3=video,4=file\n    var status: Int=0,//0=sending,1=sent,2=delivered,3=seen,4=failed\n    var textMessage: TextMessage?=null,\n    var imageMessage: ImageMessage?=null,\n    var audioMessage: AudioMessage?=null,\n    var videoMessage: VideoMessage?=null,\n    var fileMessage: FileMessage?=null,\n    var chatUsers: ArrayList<String>?=null,\n    @set:Exclude @get:Exclude\n    var chatUserId: String?=null): Parcelable\n\n@Serializable\n@kotlinx.parcelize.Parcelize\ndata class TextMessage(val text: String?=null): Parcelable\n\n@Serializable\n@kotlinx.parcelize.Parcelize\ndata class AudioMessage(var uri: String?=null,val duration: Int=0): Parcelable\n\n@Serializable\n@kotlinx.parcelize.Parcelize\ndata class ImageMessage(var uri: String?=null,var imageType: String=\"image\"): Parcelable\n\n@Serializable\n@kotlinx.parcelize.Parcelize\ndata class VideoMessage(val uri: String?=null,val duration: Int=0): Parcelable\n\n@Serializable\n@kotlinx.parcelize.Parcelize\ndata class FileMessage(val name: String?=null,\n                       val uri: String?=null,val duration: Int=0): Parcelable\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/di/AppModule.kt",
    "content": "package com.gowtham.letschat.di\n\nimport android.content.Context\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.gowtham.letschat.core.MessageStatusUpdater\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.DefaultDbRepo\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.daos.GroupMessageDao\nimport com.gowtham.letschat.db.daos.MessageDao\nimport com.gowtham.letschat.ui.activities.MainActivity\nimport com.gowtham.letschat.utils.MPreference\nimport dagger.Module\nimport dagger.Provides\nimport dagger.hilt.InstallIn\nimport dagger.hilt.android.internal.managers.ApplicationComponentManager\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport dagger.hilt.components.SingletonComponent\nimport javax.inject.Qualifier\nimport javax.inject.Singleton\n\n@Qualifier\n@Retention(AnnotationRetention.BINARY)\nannotation class MessageCollection\n\n@Qualifier\n@Retention(AnnotationRetention.BINARY)\nannotation class GroupCollection\n\n@Module\n@InstallIn(SingletonComponent::class)\nobject AppModule {\n\n    @Singleton\n    @Provides\n    fun provideFireStoreInstance(): FirebaseFirestore {\n        return FirebaseFirestore.getInstance()\n    }\n\n    @Singleton\n    @Provides\n    fun provideUsersCollectionRef(firestore: FirebaseFirestore): CollectionReference {\n        return firestore.collection(\"Users\")\n    }\n\n    @MessageCollection\n    @Singleton\n    @Provides\n    fun provideMessagesCollectionRef(firestore: FirebaseFirestore): CollectionReference {\n        return firestore.collection(\"Messages\")\n    }\n\n    @GroupCollection\n    @Singleton\n    @Provides\n    fun provideGroupCollectionRef(firestore: FirebaseFirestore): CollectionReference {\n        return firestore.collection(\"Groups\")\n    }\n\n    @Provides\n    fun provideMainActivity(): MainActivity {\n        return MainActivity()\n    }\n\n    @Provides\n    fun provideDefaultDbRepo(userDao: ChatUserDao,\n                             groupDao: GroupDao,\n                             groupMsgDao: GroupMessageDao,\n                             messageDao: MessageDao): DefaultDbRepo {\n        return DbRepository(userDao, groupDao, groupMsgDao, messageDao)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/di/DbModule.kt",
    "content": "package com.gowtham.letschat.di\n\nimport android.content.Context\nimport androidx.room.Room\nimport com.gowtham.letschat.db.ChatUserDatabase\nimport com.gowtham.letschat.utils.Constants.CHAT_USER_DB_NAME\nimport dagger.Module\nimport dagger.Provides\nimport dagger.hilt.InstallIn\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport dagger.hilt.components.SingletonComponent\nimport javax.inject.Singleton\n\n@Module\n@InstallIn(SingletonComponent::class)\nobject DbModule {\n\n    @Singleton\n    @Provides\n    fun provideChatUserDb(@ApplicationContext context: Context): ChatUserDatabase{\n       return Room.databaseBuilder(context,ChatUserDatabase::class.java,\n            CHAT_USER_DB_NAME).build()\n    }\n\n    @Singleton\n    @Provides\n    fun provideChatUserDao(db: ChatUserDatabase) = db.getChatUserDao()\n\n    @Singleton\n    @Provides\n    fun provideMessageDao(db: ChatUserDatabase) = db.getMessageDao()\n\n    @Singleton\n    @Provides\n    fun provideGroupDao(db: ChatUserDatabase) = db.getGroupDao()\n\n    @Singleton\n    @Provides\n    fun provideGroupMessageDao(db: ChatUserDatabase) = db.getGroupMessageDao()\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/FAttachment.kt",
    "content": "package com.gowtham.letschat.fragments\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport com.google.android.material.bottomsheet.BottomSheetDialogFragment\nimport com.gowtham.letschat.databinding.FAttachmentBinding\nimport com.gowtham.letschat.databinding.FImageSrcSheetBinding\nimport com.gowtham.letschat.utils.BottomSheetEvent\nimport org.greenrobot.eventbus.EventBus\n\nclass FAttachment  : BottomSheetDialogFragment() {\n\n    private lateinit var binding: FAttachmentBinding\n\n    companion object{\n        fun newInstance(bundle : Bundle) : FAttachment{\n            val fragment = FAttachment()\n            fragment.arguments=bundle\n            return fragment\n        }\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?): View {\n        binding = FAttachmentBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        binding.imgCamera.setOnClickListener {\n            EventBus.getDefault().post(BottomSheetEvent(0))\n            dismiss()\n        }\n\n        binding.imgGallery.setOnClickListener {\n            EventBus.getDefault().post(BottomSheetEvent(1))\n            dismiss()\n        }\n\n        binding.videoGallery.setOnClickListener {\n            EventBus.getDefault().post(BottomSheetEvent(2))\n            dismiss()\n        }\n\n        binding.videoCamera.setOnClickListener {\n            EventBus.getDefault().post(BottomSheetEvent(3))\n            dismiss()\n        }\n\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/FImageSrcSheet.kt",
    "content": "package com.gowtham.letschat.fragments\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport com.google.android.material.bottomsheet.BottomSheetDialogFragment\nimport com.gowtham.letschat.databinding.FImageSrcSheetBinding\n\ninterface SheetListener{\n    fun selectedItem(index: Int)\n}\nclass FImageSrcSheet constructor() : BottomSheetDialogFragment() {\n\n    private lateinit var binding: FImageSrcSheetBinding\n\n    private lateinit var listener: SheetListener\n\n    companion object{\n        fun newInstance(bundle : Bundle) : FImageSrcSheet{\n            val fragment = FImageSrcSheet()\n            fragment.arguments=bundle\n            return fragment\n        }\n    }\n\n    fun addListener(listener: SheetListener){\n        this.listener=listener\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?): View {\n        binding = FImageSrcSheetBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        binding.txtCamera.setOnClickListener {\n            listener.selectedItem(0)\n            dismiss()\n        }\n\n        binding.txtGallery.setOnClickListener {\n            listener.selectedItem(1)\n            dismiss()\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/MainFragmentFactory.kt",
    "content": "package com.gowtham.letschat.fragments\n\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.FragmentFactory\nimport com.gowtham.letschat.fragments.contacts.FContacts\nimport com.gowtham.letschat.utils.MPreference\nimport javax.inject.Inject\n\nclass MainFragmentFactory @Inject constructor(\nprivate val preference: MPreference\n) : FragmentFactory() {\n\n    override fun instantiate(classLoader: ClassLoader, className: String): Fragment {\n        return when(className) {\n            FContacts::class.java.name -> FContacts(preference)\n            else -> super.instantiate(classLoader, className)\n        }\n\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/add_group_members/AdAddMembers.kt",
    "content": "package com.gowtham.letschat.fragments.add_group_members\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.recyclerview.widget.ListAdapter\nimport androidx.recyclerview.widget.RecyclerView\nimport com.gowtham.letschat.databinding.RowAddMemberBinding\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.utils.DiffCallbackChatUser\nimport com.gowtham.letschat.utils.ItemClickListener\nimport java.util.*\nimport kotlin.collections.ArrayList\n\nclass AdAddMembers(private val context: Context) :\n    ListAdapter<ChatUser, RecyclerView.ViewHolder>(DiffCallbackChatUser()) {\n\n\n    companion object {\n        var allContacts = ArrayList<ChatUser>()\n        lateinit var listener: ItemClickListener\n    }\n\n    fun filter(query: String) {\n        val list = ArrayList<ChatUser>()\n        if (query.isEmpty()) {\n            list.addAll(allContacts)\n        } else {\n            val queryList = allContacts.filter {\n                it.localName.toLowerCase(Locale.getDefault())\n                    .contains(query.toLowerCase(Locale.getDefault()))\n            }\n            list.addAll(queryList)\n        }\n        submitList(list as MutableList<ChatUser>)\n    }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {\n        val layoutInflater = LayoutInflater.from(parent.context)\n        val binding = RowAddMemberBinding.inflate(layoutInflater, parent, false)\n        return MyViewHolder(binding)\n    }\n\n    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {\n        holder as MyViewHolder\n        holder.bind(getItem(position))\n    }\n\n    override fun submitList(list: List<ChatUser>?) {\n        super.submitList(list?.let { ArrayList(it) })\n    }\n\n    class MyViewHolder(val binding: RowAddMemberBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: ChatUser) {\n            binding.chatUser = item\n            binding.viewRoot.setOnClickListener {\n                listener.onItemClicked(it, bindingAdapterPosition)\n            }\n            binding.executePendingBindings()\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/add_group_members/AdChip.kt",
    "content": "package com.gowtham.letschat.fragments.add_group_members\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.recyclerview.widget.ListAdapter\nimport androidx.recyclerview.widget.RecyclerView\nimport com.gowtham.letschat.databinding.RowChipBinding\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.utils.DiffCallbackChatUser\nimport com.gowtham.letschat.utils.ItemClickListener\nimport kotlin.collections.ArrayList\n\nclass AdChip (private val context: Context) :\n            ListAdapter<ChatUser, RecyclerView.ViewHolder>(DiffCallbackChatUser()) {\n\n   companion object{\n         var allAddedContacts=ArrayList<ChatUser>()\n         lateinit var listener: ItemClickListener\n   }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {\n        val layoutInflater = LayoutInflater.from(parent.context)\n         val binding= RowChipBinding.inflate(layoutInflater, parent, false)\n          return MyViewHolder(binding)\n    }\n\n    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {\n        holder as MyViewHolder\n        holder.bind(getItem(position))\n    }\n\n\n    class MyViewHolder(val binding: RowChipBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: ChatUser) {\n            binding.chatUser = item\n            binding.chip.setOnCloseIconClickListener {\n                listener.onItemClicked(it,bindingAdapterPosition)\n            }\n            binding.executePendingBindings()\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/add_group_members/AddGroupViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.add_group_members\n\nimport android.content.Context\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport com.gowtham.letschat.core.QueryCompleteListener\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.LoadState\nimport com.gowtham.letschat.utils.UserUtils\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport timber.log.Timber\nimport javax.inject.Inject\n\n@HiltViewModel\nclass AddGroupViewModel @Inject\nconstructor(@ApplicationContext context: Context,\n            private val dbRepository: DbRepository\n) : ViewModel() {\n\n    private val chipList= MutableLiveData<ArrayList<ChatUser>>()\n\n    private val allContacts= ArrayList<ChatUser>()\n\n    val queryState = MutableLiveData<LoadState>()\n\n    private lateinit var chatUsers: List<ChatUser>\n\n    var isFirstCall=true\n\n    init {\n        Timber.v(\"AddGroupViewModel init\")\n        viewModelScope.launch(Dispatchers.IO) {\n            chatUsers=dbRepository.getChatUserList().filter { it.locallySaved }\n            if (chatUsers.isNullOrEmpty())\n                startQuery()\n        }\n    }\n\n    fun getChatList() = dbRepository.getAllChatUser()\n\n    fun getChipList(): LiveData<ArrayList<ChatUser>>{\n        return chipList\n    }\n\n    fun setChipList(list: List<ChatUser>){\n        val newList=ArrayList<ChatUser>(list.filter { it.isSelected })\n        chipList.value=newList\n    }\n\n    fun setContactList(list: List<ChatUser>) {\n        allContacts.clear()\n        allContacts.addAll(list)\n    }\n\n    fun getContactList() = allContacts\n\n    private fun startQuery() {\n        try {\n            queryState.postValue(LoadState.OnLoading)\n            val success= UserUtils.updateContactsProfiles(onQueryCompleted)\n            if (!success) {\n                Timber.v(\"Recursion error\")\n                queryState.postValue(LoadState.OnFailure(java.lang.Exception(\"Recursion exception\")))\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onCleared() {\n        AdChip.allAddedContacts.clear()\n        allContacts.clear()\n        isFirstCall=true\n        Timber.v(\"OnClear AddGroup\")\n        super.onCleared()\n    }\n\n    private val onQueryCompleted=object : QueryCompleteListener {\n        override fun onQueryCompleted(queriedList: ArrayList<UserProfile>) {\n            try {\n                val localContacts=UserUtils.fetchContacts(context)\n                val finalList = ArrayList<ChatUser>()\n                val queriedList=UserUtils.queriedList\n\n                //set localsaved name to queried users\n                for(doc in queriedList){\n                    val savedNumber=localContacts.firstOrNull { it.mobile == doc.mobile?.number }\n                    if(savedNumber!=null){\n                        val chatUser= UserUtils.getChatUser(doc, chatUsers, savedNumber.name)\n                        finalList.add(chatUser)\n                    }\n                }\n                queryState.value=LoadState.OnSuccess(finalList)\n                CoroutineScope(Dispatchers.IO).launch {\n                    dbRepository.insertMultipleUser(finalList)\n                }\n                setDefaultValues()\n            } catch (e: Exception) {\n                e.printStackTrace()\n            }\n        }\n    }\n\n    private fun setDefaultValues() {\n        //set default values\n        UserUtils.totalRecursionCount=0\n        UserUtils.resultCount=0\n        UserUtils.queriedList.clear()\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/add_group_members/FAddGroupMembers.kt",
    "content": "package com.gowtham.letschat.fragments.add_group_members\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.appcompat.widget.SearchView\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.viewModels\nimport androidx.navigation.fragment.findNavController\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.FAddGroupMembersBinding\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.utils.*\nimport dagger.hilt.android.AndroidEntryPoint\nimport timber.log.Timber\nimport javax.inject.Inject\n\n@AndroidEntryPoint\nclass FAddGroupMembers : Fragment(), ItemClickListener {\n\n    private lateinit var binding: FAddGroupMembersBinding\n\n    @Inject\n    lateinit var preference: MPreference\n\n    private lateinit var searchView: SearchView\n\n    private var contactList = ArrayList<ChatUser>()\n\n    private val adContact: AdAddMembers by lazy {\n        AdAddMembers(requireContext())\n    }\n\n    private val adChip: AdChip by lazy {\n        AdChip(requireContext())\n    }\n\n    private val viewModel: AddGroupViewModel by viewModels()\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        binding = FAddGroupMembersBinding.inflate(layoutInflater, container, false)\n        binding.lifecycleOwner = viewLifecycleOwner\n        setHasOptionsMenu(true)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        Timber.v(\"onViewCreated\")\n        binding.toolbar.setNavigationOnClickListener {\n            findNavController().popBackStack()\n        }\n        binding.fab.setOnClickListener {\n            val addedContacts = AdChip.allAddedContacts\n            if (addedContacts.isNotEmpty()) {\n                val action = FAddGroupMembersDirections.actionFAddGroupMembersToFCreateGroup(\n                    addedContacts.toTypedArray()\n                )\n                findNavController().navigate(action)\n            }\n        }\n        setToolbar()\n        setDataInView()\n        subscribeObservers()\n    }\n\n    private fun setToolbar() {\n        binding.toolbar.inflateMenu(R.menu.menu_search)\n        val searchItem: MenuItem? = binding.toolbar.menu.findItem(R.id.action_search)\n        searchView = searchItem?.actionView as SearchView\n        searchView.apply {\n            maxWidth = Integer.MAX_VALUE\n            queryHint = getString(R.string.txt_search)\n        }\n        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {\n            override fun onQueryTextSubmit(query: String?): Boolean {\n                return true\n            }\n\n            override fun onQueryTextChange(newText: String?): Boolean {\n                adContact.filter(newText.toString())\n                return true\n            }\n        })\n    }\n\n    private fun subscribeObservers() {\n        viewModel.getChatList().observe(viewLifecycleOwner, { contacts ->\n            val allContacts = contacts.filter { it.locallySaved }\n            if (allContacts.isNotEmpty()) {\n                if (viewModel.isFirstCall) {\n                    viewModel.setContactList(allContacts)\n                    viewModel.isFirstCall=false\n                }\n                Timber.v(\"allContacts ->${viewModel.getContactList().first().localName}\")\n                contactList.clear()\n                contactList.addAll(viewModel.getContactList())\n                AdAddMembers.allContacts = contactList\n                adContact.submitList(contactList)\n                if (!searchView.isIconified)\n                    adContact.filter(searchView.query.toString())\n            }\n        })\n\n        viewModel.getChipList().observe(viewLifecycleOwner, { addedList ->\n            AdChip.allAddedContacts = addedList\n            adChip.submitList(addedList.toList())\n            adChip.notifyDataSetChanged()\n            if (addedList.isEmpty()) {\n                binding.txtEmptyMembers.show()\n                binding.fab.hide()} else {\n                binding.txtEmptyMembers.hide()\n                binding.fab.show()\n                binding.listChip.post {\n                    binding.listChip.smoothScrollToPosition(addedList.lastIndex)\n                }\n            }\n        })\n\n        viewModel.queryState.observe(viewLifecycleOwner, {\n            searchView.isEnabled = it !is LoadState.OnLoading\n            when (it) {\n                is LoadState.OnSuccess -> {\n                    val emptyList = it.data as ArrayList<*>\n                    if (emptyList.isEmpty()) {\n                        binding.viewEmpty.show()\n                        binding.progress.hide()\n                        binding.viewEmpty.playAnimation()\n                    }else{\n                        binding.viewHolder.show()\n                        binding.progress.hide()\n                    }\n                }\n                is LoadState.OnFailure -> {\n                    binding.viewHolder.hide()\n                    binding.progress.hide()\n                    binding.viewEmpty.playAnimation()\n                }\n                is LoadState.OnLoading -> {\n                    binding.viewEmpty.hide()\n                    binding.viewHolder.hide()\n                    binding.progress.show()\n                }\n            }\n        })\n    }\n\n    private fun setDataInView() {\n        binding.listContact.adapter = adContact\n        binding.listChip.adapter = adChip\n        AdAddMembers.listener = this\n        AdChip.listener = chipListener\n        adContact.addRestorePolicy()\n        adChip.addRestorePolicy()\n    }\n\n    override fun onItemClicked(v: View, position: Int) {\n        val currentList = ArrayList(adContact.currentList)\n        val user = currentList[position]\n        user.apply {\n            isSelected = !isSelected\n        }\n        currentList.set(position, user)\n        adContact.submitList(currentList)\n        adContact.notifyItemChanged(position)\n        val allContact = AdAddMembers.allContacts\n        val user1 = allContact.find { it.id == user.id }\n        val index = allContact.indexOf(user1)\n        allContact.set(index, user1!!)\n        viewModel.setContactList(allContact) //update in allContacts list\n\n        val chipList = AdChip.allAddedContacts\n        val contains = chipList.find { it.id == user.id }\n        if (contains == null)\n            chipList.add(user)\n        else\n            chipList.set(chipList.indexOf(contains), user)\n        viewModel.setChipList(chipList)  //update chip list\n    }\n\n    private val chipListener: ItemClickListener = object : ItemClickListener {\n        override fun onItemClicked(v: View, position: Int) {\n            val added = AdChip.allAddedContacts\n            var index: Int?\n            val clickedUser = added.get(position)\n\n            val currentList = ArrayList(adContact.currentList)\n            val user = currentList.find { it.id == clickedUser.id }\n            if (user != null) {  //update in current list\n                index = currentList.indexOf(user)\n                user.isSelected = false\n                currentList.set(index, user)\n                adContact.submitList(currentList)\n                adContact.notifyItemChanged(index)\n            }\n\n            val allUsers = AdAddMembers.allContacts //update allContactList\n            val user1 = allUsers.find { it.id == clickedUser.id }\n            val indexAllList = allUsers.indexOf(user1)\n            user1?.isSelected = false\n            allUsers.set(indexAllList, user1!!)\n            viewModel.setContactList(allUsers)\n\n            added.removeAt(position)\n            viewModel.setChipList(added)\n            if (!searchView.isIconified)  //remove from chip list\n                adContact.filter(searchView.query.toString())\n        }\n    }\n\n    override fun onResume() {\n        super.onResume()\n        val chipList = AdChip.allAddedContacts\n        val allUsers = AdAddMembers.allContacts\n        for (user in allUsers)\n            user.isSelected = chipList.contains(user)\n        viewModel.setContactList(allUsers)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/contacts/AdContact.kt",
    "content": "package com.gowtham.letschat.fragments.contacts\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.recyclerview.widget.RecyclerView\nimport com.gowtham.letschat.databinding.RowContactBinding\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.utils.ItemClickListener\nimport java.util.*\nimport kotlin.collections.ArrayList\n\nclass AdContact(context: Context, allUsers: ArrayList<ChatUser>) :\n           RecyclerView.Adapter<AdContact.UserViewModel>() {\n\n    private var users: ArrayList<ChatUser> = allUsers\n\n    private var allUsers: ArrayList<ChatUser> = ArrayList()\n\n    init {\n        this.allUsers.addAll(users)\n    }\n\n    companion object {\n        var itemClickListener: ItemClickListener? = null\n    }\n\n    fun filter(query: String) {\n        try {\n            users.clear()\n            if (query.isEmpty())\n                users.addAll(allUsers)\n            else {\n                for (country in allUsers) {\n                    if (country.localName.toLowerCase(Locale.getDefault())\n                            .contains(query.toLowerCase(Locale.getDefault())))\n                       users.add(country)\n                }\n            }\n            notifyDataSetChanged()\n        } catch (e: Exception) {\n            e.stackTrace\n        }\n    }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewModel {\n        val layoutInflater = LayoutInflater.from(parent.context)\n        val binding = RowContactBinding.inflate(layoutInflater, parent, false)\n        return UserViewModel(binding)\n    }\n\n\n    override fun onBindViewHolder(holder: UserViewModel, position: Int) {\n        holder.bind(users[position])\n    }\n\n    class UserViewModel(val binding: RowContactBinding) : RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: ChatUser) {\n            binding.chatUser = item\n            binding.viewRoot.setOnClickListener { v ->\n                itemClickListener?.onItemClicked(v, bindingAdapterPosition)\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n    override fun getItemCount() = users.size\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/contacts/ContactsViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.contacts\n\nimport android.content.Context\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport com.gowtham.letschat.core.QueryCompleteListener\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.LoadState\nimport com.gowtham.letschat.utils.LogMessage\nimport com.gowtham.letschat.utils.UserUtils\nimport com.gowtham.letschat.utils.toast\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport timber.log.Timber\nimport javax.inject.Inject\n\n\n@HiltViewModel\nclass ContactsViewModel @Inject constructor(\n    @ApplicationContext context: Context,\n    private val dbRepo: DbRepository) : ViewModel() {\n\n    val queryState = MutableLiveData<LoadState>()\n\n    val list= MutableLiveData<ArrayList<ChatUser>>()\n\n    val contactsCount = MutableLiveData(\"0 Contacts\")\n\n    private lateinit var chatUsers: List<ChatUser>\n\n    init {\n        LogMessage.v(\"ContactsViewModel init\")\n        CoroutineScope(Dispatchers.IO).launch{\n            chatUsers=dbRepo.getChatUserList()\n        }\n    }\n\n    fun getContacts()=dbRepo.getAllChatUser()\n\n    fun setContactCount(size: Int) {\n        contactsCount.value=\"$size Contacts\"\n    }\n\n    fun startQuery() {\n        try {\n            queryState.value=LoadState.OnLoading\n            val success=UserUtils.updateContactsProfiles(onQueryCompleted)\n            if (!success)\n                queryState.value=LoadState.OnFailure(java.lang.Exception(\"Recursion exception\"))\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private val onQueryCompleted=object : QueryCompleteListener {\n        override fun onQueryCompleted(queriedList: ArrayList<UserProfile>) {\n            try {\n                LogMessage.v(\"Query Completed ${UserUtils.queriedList.size}\")\n                val localContacts=UserUtils.fetchContacts(context)\n                val finalList = ArrayList<ChatUser>()\n                val list=UserUtils.queriedList\n\n                //set localsaved name to queried users\n                for(doc in list){\n                    val savedNumber=localContacts.firstOrNull { it.mobile == doc.mobile?.number }\n                    if(savedNumber!=null){\n                        val chatUser= UserUtils.getChatUser(doc, chatUsers, savedNumber.name)\n                        Timber.v(\"Contact ${chatUser.documentId}\")\n                        finalList.add(chatUser)\n                    }\n                }\n                contactsCount.value=\"${finalList.size} Contacts\"\n                queryState.value=LoadState.OnSuccess(finalList)\n                CoroutineScope(Dispatchers.IO).launch {\n                    dbRepo.insertMultipleUser(finalList)\n                }\n                context.toast(\"Contacts refreshed\")\n                setDefaultValues()\n            } catch (e: Exception) {\n                e.printStackTrace()\n            }\n        }\n    }\n\n    private fun setDefaultValues() {\n        //set default values\n        UserUtils.totalRecursionCount=0\n        UserUtils.resultCount=0\n        UserUtils.queriedList.clear()\n    }\n\n    override fun onCleared() {\n        LogMessage.v(\"ContactsViewModel OnCleared\")\n        super.onCleared()\n    }\n\n    fun setUnReadCountZero(chatUser: ChatUser) {\n        UserUtils.setUnReadCountZero(dbRepo,chatUser)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/contacts/FContacts.kt",
    "content": "package com.gowtham.letschat.fragments.contacts\n\nimport android.app.Activity\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.appcompat.widget.SearchView\nimport androidx.datastore.preferences.core.Preferences\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.viewModels\nimport androidx.navigation.fragment.findNavController\nimport androidx.recyclerview.widget.RecyclerView\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.FContactsBinding\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.utils.*\nimport dagger.hilt.android.AndroidEntryPoint\nimport javax.inject.Inject\n\n\n@AndroidEntryPoint\nclass FContacts @Inject constructor(private val preference: MPreference) : Fragment(), ItemClickListener {\n \n    private lateinit var binding: FContactsBinding\n\n    private lateinit var context: Activity\n\n    private lateinit var searchView: SearchView\n\n    private lateinit var searchItem: MenuItem\n\n    private lateinit var menuRefresh: MenuItem\n\n    private val viewModel: ContactsViewModel by viewModels()\n\n    private var contactList = ArrayList<ChatUser>()\n\n    private lateinit var adContact: AdContact\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?): View {\n        binding = FContactsBinding.inflate(layoutInflater, container, false)\n        setHasOptionsMenu(true)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        context = requireActivity()\n        binding.lifecycleOwner = viewLifecycleOwner\n        binding.viewmodel = viewModel\n        setToolbar()\n        setDataInView()\n        subscribeObservers()\n    }\n\n    private fun subscribeObservers() {\n        viewModel.getContacts().observe(viewLifecycleOwner, { contacts->\n            LogMessage.v(\"Size ${contacts.size}\")\n            val allContacts=contacts.filter { it.locallySaved }\n            if (allContacts.isEmpty() && viewModel.queryState.value == null)\n                viewModel.startQuery()\n            else {\n                viewModel.setContactCount(allContacts.size)\n                contactList.clear()\n                contactList= allContacts as ArrayList<ChatUser>\n                adContact = AdContact(requireContext(), contactList)\n                binding.listContact.adapter = adContact\n                if(searchItem.isActionViewExpanded)\n                    adContact.filter(searchView.query.toString())\n            }\n        })\n\n        viewModel.queryState.observe(viewLifecycleOwner,{\n            searchItem.isEnabled = it !is LoadState.OnLoading\n            menuRefresh.isEnabled = it !is LoadState.OnLoading\n        })\n    }\n\n    private fun setDataInView() {\n        try {\n            adContact = AdContact(requireContext(), contactList)\n            binding.listContact.adapter = adContact\n            AdContact.itemClickListener = this\n            adContact.stateRestorationPolicy =\n                RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun setToolbar() {\n        try {\n            binding.toolbar.setNavigationIcon(R.drawable.ic_arrow_back)\n            binding.toolbar.setNavigationOnClickListener {\n                findNavController().popBackStack()\n            }\n            binding.toolbar.inflateMenu(R.menu.menu_contacts)\n            searchItem = binding.toolbar.menu.findItem(R.id.action_search)\n            menuRefresh = binding.toolbar.menu.findItem(R.id.action_refresh)\n            menuRefresh.setOnMenuItemClickListener {\n                viewModel.startQuery()\n                true\n            }\n            searchView = searchItem.actionView as SearchView\n            searchView.apply {\n                maxWidth = Integer.MAX_VALUE\n                queryHint = getString(R.string.txt_search)\n            }\n\n            searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {\n                override fun onMenuItemActionExpand(item: MenuItem?): Boolean {\n                    menuRefresh.isVisible = false\n                    return true\n                }\n\n                override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {\n                    menuRefresh.isVisible = true\n                    return true\n                }\n            })\n\n            searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {\n                override fun onQueryTextSubmit(query: String?): Boolean {\n                    return true\n                }\n\n                override fun onQueryTextChange(newText: String?): Boolean {\n                    adContact.filter(newText.toString())\n                    return true\n                }\n            })\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n\n    }\n\n    override fun onItemClicked(v: View, position: Int) {\n        viewModel.setUnReadCountZero(contactList[position])\n        preference.setCurrentUser(contactList[position].user.uId!!)\n        val action = FContactsDirections.actionFContactsToChat(\n            contactList[position]\n        )\n        findNavController().navigate(action)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/countries/AdCountries.kt",
    "content": "package com.gowtham.letschat.fragments.countries\n\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.databinding.DataBindingUtil\nimport androidx.recyclerview.widget.RecyclerView\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.RowCountryBinding\nimport com.gowtham.letschat.models.Country\nimport com.gowtham.letschat.utils.Countries\nimport com.gowtham.letschat.utils.ItemClickListener\nimport java.util.*\nimport kotlin.collections.ArrayList\n\nclass AdCountries : RecyclerView.Adapter<AdCountries.UserViewModel>() {\n\n    lateinit var countries: ArrayList<Country>\n\n    private lateinit var  allCountries: ArrayList<Country>\n\n    fun setData() {\n        this.countries = Countries.getCountries() as ArrayList<Country>\n        allCountries= ArrayList()\n        allCountries.addAll(countries)\n    }\n\n    companion object {\n        var itemClickListener: ItemClickListener? = null\n    }\n\n    fun filter(query: String) {\n        try {\n            countries.clear()\n            if (query.isEmpty())\n                countries.addAll(allCountries)\n            else {\n                for (country in allCountries) {\n                    if (country.name.toLowerCase(Locale.getDefault())\n                            .contains(query.toLowerCase(Locale.getDefault()))\n                    )\n                        countries.add(country)\n                }\n            }\n            notifyDataSetChanged()\n        } catch (e: Exception) {\n            e.stackTrace\n        }\n    }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewModel {\n        val binding: RowCountryBinding = DataBindingUtil.inflate(\n            LayoutInflater.from(parent.context),\n            R.layout.row_country, parent, false\n        )\n        return UserViewModel(binding)\n    }\n\n\n    override fun onBindViewHolder(holder: UserViewModel, position: Int) {\n        holder.bind(countries[position])\n    }\n\n    class UserViewModel(val binding: RowCountryBinding) : RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: Country) {\n            binding.country = item\n            binding.viewRoot.setOnClickListener { v ->\n                itemClickListener?.onItemClicked(v, bindingAdapterPosition)\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n    override fun getItemCount() = countries.size\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/countries/FCountries.kt",
    "content": "package com.gowtham.letschat.fragments.countries\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.appcompat.widget.SearchView\nimport androidx.fragment.app.Fragment\nimport androidx.lifecycle.ViewModelProvider\nimport androidx.navigation.fragment.findNavController\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport androidx.recyclerview.widget.RecyclerView\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.FCountriesBinding\nimport com.gowtham.letschat.ui.activities.SharedViewModel\nimport com.gowtham.letschat.utils.ItemClickListener\nimport com.gowtham.letschat.utils.Utils\nimport dagger.hilt.android.AndroidEntryPoint\n\n\n@AndroidEntryPoint\nclass FCountries : Fragment(), ItemClickListener {\n\n    private lateinit var binding: FCountriesBinding\n\n    private lateinit var recyclerView: RecyclerView\n\n    private lateinit var searchView: SearchView\n\n    private lateinit var adCountry: AdCountries\n\n    private lateinit var sharedViewModel: SharedViewModel\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?): View? {\n        binding = FCountriesBinding.inflate(layoutInflater, container, false)\n        setHasOptionsMenu(true)\n        binding.toolbar.setNavigationOnClickListener {\n            findNavController().popBackStack()\n        }\n        binding.lifecycleOwner = viewLifecycleOwner\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        recyclerView = binding.listCountry\n        sharedViewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)\n        setDataInView()\n    }\n\n    private fun setDataInView() {\n        try {\n            binding.toolbar.inflateMenu(R.menu.menu_search)\n            val searchItem: MenuItem? = binding.toolbar.menu.findItem(R.id.action_search)\n            searchView = searchItem?.actionView as SearchView\n            searchView.apply {\n                maxWidth = Integer.MAX_VALUE\n                queryHint = getString(R.string.txt_search)\n            }\n            searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {\n                override fun onQueryTextSubmit(query: String?): Boolean {\n                    return true\n                }\n\n                override fun onQueryTextChange(newText: String?): Boolean {\n                    adCountry.filter(newText.toString())\n                    return true\n                }\n            })\n            AdCountries.itemClickListener = this\n            adCountry = AdCountries()\n            adCountry.setData()\n            recyclerView.adapter = adCountry\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onItemClicked(v: View, position: Int) {\n        findNavController().popBackStack()\n        sharedViewModel.setCountry(adCountry.countries[position])\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/create_group/CreateGroupViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.create_group\n\nimport android.content.Context\nimport android.net.Uri\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport com.google.android.gms.tasks.OnFailureListener\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.FieldValue\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.google.firebase.firestore.SetOptions\nimport com.gowtham.letschat.TYPE_NEW_GROUP\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.di.GroupCollection\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.*\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\nimport javax.inject.Inject\nimport kotlin.random.Random\n\n@HiltViewModel\nclass CreateGroupViewModel @Inject constructor(\n    @ApplicationContext private val context: Context,\n    private val preference: MPreference,\n    private val userCollection: CollectionReference,\n    private val dbRepo: DbRepository,\n    @GroupCollection\n    private val groupCollection: CollectionReference) : ViewModel() {\n\n    val progressProPic = MutableLiveData(false)\n\n    val groupName = MutableLiveData(\"\")\n\n    val imageUrl = MutableLiveData(\"\")\n\n    val groupCreateStatus = MutableLiveData<LoadState>()\n\n    private val storageRef=UserUtils.getStorageRef(context)\n\n    fun uploadProfileImage(imagePath: Uri) {\n        try {\n            progressProPic.value = true\n            val child = storageRef.child(\"group_${System.currentTimeMillis()}.jpg\")\n            val task = child.putFile(imagePath)\n            task.addOnSuccessListener {\n                child.downloadUrl.addOnCompleteListener { taskResult ->\n                    progressProPic.value = false\n                    imageUrl.value = taskResult.result.toString()\n                }.addOnFailureListener {\n                    OnFailureListener { e ->\n                        progressProPic.value = false\n                        context.toast(e.message.toString())\n                    }\n                }\n            }.addOnProgressListener { taskSnapshot ->\n                val progress: Double =\n                    100.0 * taskSnapshot.bytesTransferred / taskSnapshot.totalByteCount\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun createGroup(memberList: ArrayList<ChatUser>) {\n        groupCreateStatus.value=LoadState.OnLoading\n        val gName=groupName.value+\"_${Random.nextInt(0,100)}\"  //\n        memberList.add(0,ChatUser(preference.getUid()!!,\"You\",preference.getUserProfile()!!))\n        val listOfProfiles=memberList.map { it.user } as ArrayList<UserProfile>\n        val groupData=Group(gName, preference.getUid()!!,\n            System.currentTimeMillis(),\"\",imageUrl.value.toString(),null,listOfProfiles)\n\n        groupCollection.document(gName).set(groupData, SetOptions.merge()).\n        addOnSuccessListener {\n            updateGroupInEveryUserProfile(groupData,memberList)\n        }.addOnFailureListener { exception->\n            groupCreateStatus.value=LoadState.OnFailure(exception)\n            context.toast(exception.message.toString())\n        }\n    }\n\n    private fun updateGroupInEveryUserProfile(group: Group, memberList: ArrayList<ChatUser>) {\n        group.members = memberList\n        group.profiles = ArrayList()\n        val listOfIds = memberList.map { it.id }\n        val batch = FirebaseFirestore.getInstance().batch()\n        for (id in listOfIds) {\n            val userDoc = userCollection.document(id)\n            batch.set(\n                userDoc, mapOf(\"groups\" to FieldValue.arrayUnion(group.id)),\n                SetOptions.merge()\n            )\n        }\n        batch.commit().addOnSuccessListener {\n            LogMessage.v(\"Batch update success for group Creation\")\n            groupCreateStatus.value = LoadState.OnSuccess(group)\n            dbRepo.insertGroup(group)\n            val groupdata = Group(group.id)\n            for (user in group.members!!) {\n                val token = user.user.token\n                if (token.isNotEmpty())\n                    UserUtils.sendPush(context, TYPE_NEW_GROUP,\n                        Json.encodeToString(groupdata), token, user.id)\n            }\n        }.addOnFailureListener { exception ->\n            LogMessage.v(\"Batch update failure ${exception.message}  for group Creation\")\n            groupCreateStatus.value = LoadState.OnFailure(exception)\n            context.toast(exception.message.toString())\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/create_group/FCreateGroup.kt",
    "content": "package com.gowtham.letschat.fragments.create_group\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Bundle\nimport androidx.fragment.app.Fragment\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.viewModels\nimport androidx.navigation.fragment.findNavController\nimport androidx.navigation.fragment.navArgs\nimport com.canhub.cropper.CropImage\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.FCreateGroupBinding\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.fragments.add_group_members.AdAddMembers\nimport com.gowtham.letschat.utils.*\nimport com.gowtham.letschat.views.CustomProgressView\nimport dagger.hilt.android.AndroidEntryPoint\nimport javax.inject.Inject\n\n@AndroidEntryPoint\nclass FCreateGroup : Fragment() {\n\n    @Inject\n    lateinit var chatUserDao: ChatUserDao\n\n    @Inject\n    lateinit var preference: MPreference\n\n    private val viewModel: CreateGroupViewModel by viewModels()\n\n    private lateinit var binding: FCreateGroupBinding\n\n    val args by navArgs<FCreateGroupArgs>()\n\n    private lateinit var memberList: List<ChatUser>\n\n    private var progressView: CustomProgressView?=null\n\n    private val adMembers: AdAddMembers by lazy {\n        AdAddMembers(requireContext())\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?): View? {\n        binding=FCreateGroupBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        binding.lifecycleOwner=viewLifecycleOwner\n        binding.viewmodel=viewModel\n        progressView= CustomProgressView(requireContext())\n        binding.toolbar.setNavigationOnClickListener {\n            findNavController().popBackStack()\n        }\n        binding.imageAddImage.setOnClickListener {\n            ImageUtils.askPermission(this)\n        }\n        binding.fab.setOnClickListener {\n          validate()\n        }\n        setDataInView()\n        subscribeObservers()\n    }\n\n    private fun subscribeObservers() {\n        viewModel.groupCreateStatus.observe(viewLifecycleOwner,{\n            when (it) {\n                is LoadState.OnSuccess -> {\n                    if (findNavController().isValidDestination(R.id.FCreateGroup)) {\n                        progressView?.dismiss()\n                        val group=it.data as Group\n                        preference.setCurrentGroup(group.id)\n                        val action=FCreateGroupDirections.actionFCreateGroupToFGroupChat(group)\n                        findNavController().navigate(action)\n                    }\n                }\n                is LoadState.OnFailure -> {\n                    progressView?.dismiss()\n                }\n                is LoadState.OnLoading -> {\n                    progressView?.show()\n                }\n            }\n        })\n    }\n\n    private fun validate() {\n        val groupName=viewModel.groupName.value.toString().trim()\n        if (groupName.isNotEmpty() && !viewModel.progressProPic.value!!)\n            viewModel.createGroup(memberList as ArrayList<ChatUser>)\n    }\n\n    private fun setDataInView() {\n        binding.edtGroupName.requestFocus()\n        Utils.showSoftKeyboard(requireActivity(),binding.edtGroupName)\n        memberList=args.memberList.toList().map {\n            it.isSelected=false\n            it\n        }\n        val memberCount=memberList.size\n        binding.memberCount=if(memberCount==1) \"$memberCount member\" else \"$memberCount members\"\n        binding.listMembers.adapter = adMembers\n        adMembers.addRestorePolicy()\n        adMembers.submitList(memberList)\n    }\n\n    override fun onRequestPermissionsResult(\n        requestCode: Int,\n        permissions: Array<out String>,\n        grantResults: IntArray) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n        ImageUtils.onImagePerResult(this, *grantResults)\n    }\n\n    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n        super.onActivityResult(requestCode, resultCode, data)\n        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE)\n            onCropResult(data)\n        else\n            ImageUtils.cropImage(requireActivity(), data)\n    }\n\n    private fun onCropResult(data: Intent?) {\n        try {\n            val imagePath: Uri? = ImageUtils.getCroppedImage(data)\n            imagePath?.let {\n                viewModel.uploadProfileImage(it)\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        progressView?.dismissIfShowing()\n        Utils.closeKeyBoard(requireActivity())\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/group_chat/AdGroupChat.kt",
    "content": "package com.gowtham.letschat.fragments.group_chat\n\nimport android.content.Context\nimport android.media.MediaPlayer\nimport android.net.Uri\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.core.content.ContextCompat\nimport androidx.recyclerview.widget.DiffUtil\nimport androidx.recyclerview.widget.ListAdapter\nimport androidx.recyclerview.widget.RecyclerView\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.*\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.GroupMessage\nimport com.gowtham.letschat.fragments.single_chat.AdChat\nimport com.gowtham.letschat.utils.Events.EventAudioMsg\nimport com.gowtham.letschat.utils.ItemClickListener\nimport com.gowtham.letschat.utils.MPreference\nimport com.gowtham.letschat.utils.gone\nimport com.gowtham.letschat.utils.show\nimport org.greenrobot.eventbus.EventBus\nimport timber.log.Timber\nimport java.io.IOException\n\nclass AdGroupChat (private val context: Context,\n                   private val msgClickListener: ItemClickListener) :\n    ListAdapter<GroupMessage, RecyclerView.ViewHolder>(DiffCallbackMessages()) {\n\n    private val preference = MPreference(context)\n\n    companion object {\n        private const val TYPE_TXT_SENT = 0\n        private const val TYPE_TXT_RECEIVED = 1\n        private const val TYPE_IMG_SENT = 2\n        private const val TYPE_IMG_RECEIVE = 3\n        private const val TYPE_STICKER_SENT = 4\n        private const val TYPE_STICKER_RECEIVE = 5\n        private const val TYPE_AUDIO_SENT = 6\n        private const val TYPE_AUDIO_RECEIVE = 7\n        lateinit var messageList: MutableList<GroupMessage>\n        lateinit var chatUserList: MutableList<ChatUser>\n        private var player = MediaPlayer()\n        private var lastPlayedHolder: RowGroupAudioSentBinding?=null\n        private var lastReceivedPlayedHolder: RowGroupAudioReceiveBinding?=null\n        private var lastPlayedAudioId : Long=-1\n\n        fun stopPlaying() {\n            if(player.isPlaying) {\n                lastReceivedPlayedHolder?.progressBar?.abandon()\n                lastPlayedHolder?.progressBar?.abandon()\n                lastReceivedPlayedHolder?.imgPlay?.setImageResource(R.drawable.ic_action_play)\n                lastPlayedHolder?.imgPlay?.setImageResource(R.drawable.ic_action_play)\n                player.apply {\n                    stop()\n                    reset()\n                    EventBus.getDefault().post(EventAudioMsg(false))\n                }\n            }\n        }\n\n        fun isPlaying() = player.isPlaying\n    }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {\n        val layoutInflater = LayoutInflater.from(parent.context)\n        return when (viewType) {\n            TYPE_TXT_SENT -> {\n                val binding = RowGroupTxtSentBinding.inflate(layoutInflater, parent, false)\n                TxtSentMsgHolder(binding)\n            }\n            TYPE_TXT_RECEIVED-> {\n                val binding = RowGrpTxtReceiveBinding.inflate(layoutInflater, parent, false)\n                TxtReceivedMsgHolder(binding)\n            }\n            TYPE_IMG_SENT -> {\n                val binding = RowGroupImageSentBinding.inflate(layoutInflater, parent, false)\n                ImgSentMsgHolder(binding)\n            }\n            TYPE_IMG_RECEIVE->{\n                val binding = RowGroupImageReceiveBinding.inflate(layoutInflater, parent, false)\n                ImgReceivedMsgHolder(binding)\n            }\n            TYPE_STICKER_SENT -> {\n                val binding = RowGroupStickerSentBinding.inflate(layoutInflater, parent, false)\n                StickerSentMsgHolder(binding)\n            }\n            TYPE_STICKER_RECEIVE-> {\n                val binding = RowGroupStickerReceiveBinding.inflate(layoutInflater, parent, false)\n                StickerReceivedMsgHolder(binding)\n            }\n            TYPE_AUDIO_SENT -> {\n                val binding = RowGroupAudioSentBinding.inflate(layoutInflater, parent, false)\n                AudioSentVHolder(binding)\n            }\n            else-> {\n                val binding = RowGroupAudioReceiveBinding.inflate(layoutInflater, parent, false)\n                AudioReceiveVHolder(binding)\n            }\n        }\n    }\n\n    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {\n        when(holder){\n            is TxtSentMsgHolder ->\n                holder.bind(getItem(position))\n            is TxtReceivedMsgHolder ->\n                holder.bind(getItem(position))\n            is ImgSentMsgHolder ->\n                holder.bind(getItem(position),msgClickListener)\n            is ImgReceivedMsgHolder ->\n                holder.bind(getItem(position),msgClickListener)\n            is StickerSentMsgHolder ->\n                holder.bind(getItem(position))\n            is StickerReceivedMsgHolder ->\n                holder.bind(getItem(position))\n            is AudioSentVHolder ->\n                holder.bind(context,getItem(position))\n            is AudioReceiveVHolder ->\n                holder.bind(context,getItem(position))\n        }\n    }\n\n    override fun getItemViewType(position: Int): Int {\n        val message = getItem(position)\n        val fromMe=message.from == preference.getUid()\n        if (fromMe && message.type == \"text\")\n            return TYPE_TXT_SENT\n        else if (!fromMe && message.type == \"text\")\n            return TYPE_TXT_RECEIVED\n        else if (fromMe && message.type == \"image\" && message.imageMessage?.imageType==\"image\")\n            return TYPE_IMG_SENT\n        else if (!fromMe && message.type == \"image\"  && message.imageMessage?.imageType==\"image\")\n            return TYPE_IMG_RECEIVE\n        else if (fromMe && message.type == \"image\" && (message.imageMessage?.imageType==\"sticker\"\n                    || message.imageMessage?.imageType==\"gif\"))\n            return TYPE_STICKER_SENT\n        else if (!fromMe && message.type == \"image\"  && (message.imageMessage?.imageType==\"sticker\"\n                    || message.imageMessage?.imageType==\"gif\"))\n            return TYPE_STICKER_RECEIVE\n        else if (fromMe && message.type == \"audio\")\n            return TYPE_AUDIO_SENT\n        else if (!fromMe && message.type == \"audio\")\n            return TYPE_AUDIO_RECEIVE\n        return super.getItemViewType(position)\n    }\n\n\n    class TxtSentMsgHolder(val binding: RowGroupTxtSentBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: GroupMessage) {\n            binding.message = item\n            if (bindingAdapterPosition>0) {\n                val message = messageList[bindingAdapterPosition - 1]\n                if (message.from == item.from) {\n                    binding.txtMsg.setBackgroundResource(R.drawable.shape_send_msg_corned)\n                }\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n    class TxtReceivedMsgHolder(val binding: RowGrpTxtReceiveBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: GroupMessage) {\n            binding.message = item\n            binding.chatUsers= chatUserList.toTypedArray()\n            if (bindingAdapterPosition>0) {\n                val lastMsg = messageList[bindingAdapterPosition - 1]\n                if (lastMsg.from == item.from) {\n                    binding.apply {\n                        viewDetail.gone()\n                    }\n                    binding.viewMsgHolder.setBackgroundResource(R.drawable.shape_receive_msg_corned)\n                }\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n    class ImgSentMsgHolder(val binding: RowGroupImageSentBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: GroupMessage, msgClickListener: ItemClickListener) {\n            binding.message = item\n            binding.imageMsg.setOnClickListener {\n                msgClickListener.onItemClicked(it,bindingAdapterPosition)\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n    class ImgReceivedMsgHolder(val binding: RowGroupImageReceiveBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: GroupMessage, msgClickListener: ItemClickListener) {\n            binding.message = item\n            binding.chatUsers= chatUserList.toTypedArray()\n            binding.imageMsg.setOnClickListener {\n                msgClickListener.onItemClicked(it,bindingAdapterPosition)\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n    class StickerSentMsgHolder(val binding: RowGroupStickerSentBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: GroupMessage) {\n            binding.message = item\n            binding.executePendingBindings()\n        }\n    }\n\n    class StickerReceivedMsgHolder(val binding: RowGroupStickerReceiveBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: GroupMessage) {\n            binding.message = item\n            binding.chatUsers= chatUserList.toTypedArray()\n            binding.executePendingBindings()\n        }\n    }\n\n    class AudioReceiveVHolder(val binding: RowGroupAudioReceiveBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(context: Context, item: GroupMessage) {\n            binding.message = item\n            binding.progressBar.setStoriesCountDebug(1, 0)\n            binding.progressBar.setAllStoryDuration(item.audioMessage?.duration!!.toLong() * 1000)\n            binding.imgPlay.setOnClickListener {\n                startPlaying(\n                    context,\n                    item,\n                    binding\n                )\n            }\n            binding.executePendingBindings()\n        }\n\n\n        private fun startPlaying(\n            context: Context,\n            item: GroupMessage,\n            currentHolder: RowGroupAudioReceiveBinding\n        ) {\n            if (player.isPlaying) {\n                stopPlaying()\n                if (lastPlayedAudioId == item.createdAt)\n                    return\n            }\n            player = MediaPlayer()\n            lastReceivedPlayedHolder = currentHolder\n            lastPlayedAudioId = item.createdAt\n            currentHolder.progressBuffer.show()\n            currentHolder.imgPlay.gone()\n            player.apply {\n                try {\n                    setDataSource(context, Uri.parse(item.audioMessage?.uri))\n                    prepareAsync()\n                    setOnPreparedListener {\n                        Timber.v(\"Started..\")\n                        start()\n                        currentHolder.progressBuffer.gone()\n                        currentHolder.imgPlay.setImageResource(R.drawable.ic_action_stop)\n                        currentHolder.imgPlay.show()\n                        currentHolder.progressBar.startStories()\n                        EventBus.getDefault().post(EventAudioMsg(true))\n                    }\n                    setOnCompletionListener {\n                        currentHolder.progressBar.abandon()\n                        currentHolder.imgPlay.setImageResource(R.drawable.ic_action_play)\n                        EventBus.getDefault().post(EventAudioMsg(false))\n                    }\n                } catch (e: IOException) {\n                    println(\"ChatFragment.startPlaying:prepare failed\")\n                }\n            }\n        }\n\n    }\n\n    class AudioSentVHolder(val binding: RowGroupAudioSentBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(\n            context: Context,\n            item: GroupMessage) {\n            binding.message = item\n            binding.progressBar.setStoriesCountDebug(1, 0)\n            binding.progressBar.setAllStoryDuration(item.audioMessage?.duration!!.toLong() * 1000)\n            binding.imgPlay.setOnClickListener {\n                startPlaying(\n                    context,\n                    item,\n                    binding\n                )\n            }\n            binding.executePendingBindings()\n        }\n\n        private fun startPlaying(\n            context: Context,\n            item: GroupMessage,\n            currentHolder: RowGroupAudioSentBinding) {\n            if (player.isPlaying) {\n                stopPlaying()\n                if (lastPlayedAudioId == item.createdAt)\n                    return\n            }\n            player = MediaPlayer()\n            lastPlayedHolder = currentHolder\n            lastPlayedAudioId = item.createdAt\n            currentHolder.progressBuffer.show()\n            currentHolder.imgPlay.gone()\n            player.apply {\n                try {\n                    setDataSource(context, Uri.parse(item.audioMessage?.uri))\n                    prepareAsync()\n                    setOnPreparedListener {\n                        Timber.v(\"Started..\")\n                        start()\n                        currentHolder.progressBuffer.gone()\n                        currentHolder.imgPlay.setImageResource(R.drawable.ic_action_stop)\n                        currentHolder.imgPlay.show()\n                        currentHolder.progressBar.startStories()\n                        EventBus.getDefault().post(EventAudioMsg(true))\n                    }\n                    setOnCompletionListener {\n                        currentHolder.progressBar.abandon()\n                        currentHolder.imgPlay.setImageResource(R.drawable.ic_action_play)\n                        EventBus.getDefault().post(EventAudioMsg(false))\n                    }\n                } catch (e: IOException) {\n                    println(\"ChatFragment.startPlaying:prepare failed\")\n                }\n            }\n        }\n\n\n    }\n\nclass DiffCallbackMessages : DiffUtil.ItemCallback<GroupMessage>() {\n    override fun areItemsTheSame(oldItem: GroupMessage, newItem: GroupMessage): Boolean {\n        return oldItem.createdAt == newItem.createdAt\n    }\n\n    override fun areContentsTheSame(oldItem: GroupMessage, newItem: GroupMessage): Boolean {\n        return oldItem == newItem\n    }\n}}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/group_chat/FGroupChat.kt",
    "content": "package com.gowtham.letschat.fragments.group_chat\n\nimport android.Manifest\nimport android.animation.Animator\nimport android.content.Intent\nimport android.content.pm.ActivityInfo\nimport android.media.MediaRecorder\nimport android.net.Uri\nimport android.os.Bundle\nimport android.os.Handler\nimport android.os.Looper\nimport android.text.Editable\nimport android.text.TextWatcher\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.view.inputmethod.InputContentInfoCompat\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.viewModels\nimport androidx.lifecycle.lifecycleScope\nimport androidx.navigation.fragment.findNavController\nimport androidx.navigation.fragment.navArgs\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.canhub.cropper.CropImage\nimport com.gowtham.letschat.databinding.FGroupChatBinding\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.data.*\nimport com.gowtham.letschat.fragments.FAttachment\nimport com.gowtham.letschat.models.MyImage\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.*\nimport com.gowtham.letschat.utils.Events.EventAudioMsg\nimport com.gowtham.letschat.views.CustomEditText\nimport com.stfalcon.imageviewer.StfalconImageViewer\nimport dagger.hilt.android.AndroidEntryPoint\nimport kotlinx.coroutines.flow.collect\nimport kotlinx.coroutines.launch\nimport org.greenrobot.eventbus.EventBus\nimport org.greenrobot.eventbus.Subscribe\nimport org.greenrobot.eventbus.ThreadMode\nimport timber.log.Timber\nimport java.io.IOException\nimport java.util.*\nimport javax.inject.Inject\nimport kotlin.collections.ArrayList\n\n@AndroidEntryPoint\nclass FGroupChat : Fragment(), ItemClickListener, CustomEditText.KeyBoardInputCallbackListener {\n\n    @Inject\n    lateinit var groupDao: GroupDao\n\n    @Inject\n    lateinit var preference: MPreference\n\n    private val viewModel: GroupChatViewModel by viewModels()\n\n    private lateinit var binding: FGroupChatBinding\n\n    val args by navArgs<FGroupChatArgs>()\n\n    lateinit var group: Group\n\n    private var messageList = mutableListOf<GroupMessage>()\n\n    private lateinit var manager: LinearLayoutManager\n\n    private lateinit var localUserId: String\n\n    private lateinit var fromUser: UserProfile\n\n    private var lastAudioFile=\"\"\n\n    private var msgPostponed=false\n\n    var isRecording = false //whether is recoding now or not\n\n    private var recordStart = 0L\n\n    private var recorder: MediaRecorder? = null\n\n    private val REQ_AUDIO_PERMISSION=29\n\n    private var recordDuration = 0L\n\n    private val adChat: AdGroupChat by lazy {\n        AdGroupChat(requireContext(), this)\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?): View {\n        binding = FGroupChatBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        binding.lifecycleOwner = viewLifecycleOwner\n        binding.viewmodel = viewModel\n        group = args.group\n        binding.group = group\n        setViewListeners()\n        binding.viewChatBtm.edtMsg.setKeyBoardInputCallbackListener(this)\n        UserUtils.setUnReadCountGroup(groupDao, group)\n        setDataInView()\n        subscribeObservers()\n\n        lifecycleScope.launch {\n            viewModel.getGroupMessages(group.id).collect { message ->\n                if(message.isEmpty())\n                    return@collect\n                messageList = message as MutableList<GroupMessage>\n                if(AdGroupChat.isPlaying()){\n                    msgPostponed=true\n                    return@collect\n                }\n                AdGroupChat.messageList = messageList\n                adChat.submitList(messageList)\n                Timber.v(\"Message list ${messageList.last()}\")\n                //scroll to last items in recycler (recent messages)\n                if (messageList.isNotEmpty()) {\n                    if (viewModel.getCanScroll())  //scroll only if new message arrived\n                        binding.listMessage.smoothScrollToPos(messageList.lastIndex)\n                    else\n                        viewModel.canScroll(true)\n                }\n            }\n        }\n    }\n\n    private fun setViewListeners() {\n        binding.viewChatBtm.lottieSend.setOnClickListener {\n            sendMessage()\n        }\n        binding.viewChatHeader.viewBack.setOnClickListener {\n            findNavController().popBackStack()\n        }\n        binding.viewChatBtm.imgRecord.setOnClickListener {\n            AdGroupChat.stopPlaying()\n            if(Utils.checkPermission(this, Manifest.permission.RECORD_AUDIO,reqCode = REQ_AUDIO_PERMISSION))\n                startRecording()\n        }\n        binding.viewChatBtm.imageAdd.setOnClickListener {\n            val fragment= FAttachment.newInstance(Bundle())\n            fragment.show(childFragmentManager,\"\")\n        }\n        binding.lottieVoice.setOnClickListener {\n            if (isRecording){\n                stopRecording()\n                val duration=(recordDuration/1000).toInt()\n                if (duration<=1) {\n                    requireContext().toast(\"Nothing is recorded!\")\n                    return@setOnClickListener\n                }\n                val msg=createMessage()\n                msg.type=\"audio\"\n                msg.audioMessage= AudioMessage(lastAudioFile,duration)\n                viewModel.uploadToCloud(msg,lastAudioFile)\n            }\n        }\n    }\n\n    private fun sendMessage() {\n        val msg = binding.viewChatBtm.edtMsg.text?.trim().toString()\n        if (msg.isEmpty())\n            return\n        binding.viewChatBtm.lottieSend.playAnimation()\n        val messageData = TextMessage(msg)\n        val message = createMessage()\n        message.textMessage = messageData\n        viewModel.sendMessage(message)\n        binding.viewChatBtm.edtMsg.setText(\"\")\n    }\n\n    private fun createMessage(): GroupMessage {\n        val toUsers = group.members?.map { it.id } as ArrayList\n        val groupSize = group.members!!.size\n        val statusList = ArrayList<Int>()\n        val deliveryTimeList = ArrayList<Long>()\n        for (index in 0 until groupSize) {\n            statusList.add(0)\n            deliveryTimeList.add(0L)\n        }\n        return GroupMessage(\n            System.currentTimeMillis(), group.id, from = localUserId,\n            to = toUsers, fromUser.userName, fromUser.image, statusList, deliveryTimeList,\n            deliveryTimeList\n        )\n    }\n\n    private fun subscribeObservers() {\n        viewModel.getChatUsers().observe(viewLifecycleOwner, { chatUsers ->\n            AdGroupChat.chatUserList = chatUsers.toMutableList()\n        })\n\n        viewModel.typingUsers.observe(viewLifecycleOwner, { typingUser ->\n            if (typingUser.isEmpty())\n                BindingAdapters.setMemberNames(binding.viewChatHeader.txtMembers, group)\n            else\n                binding.viewChatHeader.txtMembers.text = typingUser\n        })\n    }\n\n    private fun setDataInView() {\n        fromUser = preference.getUserProfile()!!\n        localUserId = fromUser.uId!!\n        manager = LinearLayoutManager(context)\n        binding.listMessage.apply {\n            manager.stackFromEnd = true\n            layoutManager = manager\n            setHasFixedSize(true)\n            isNestedScrollingEnabled = false\n            itemAnimator = null\n        }\n        binding.listMessage.adapter = adChat\n        adChat.addRestorePolicy()\n        viewModel.setGroup(group)\n        binding.viewChatBtm.edtMsg.addTextChangedListener(msgTxtChangeListener)\n        binding.viewChatBtm.lottieSend.addAnimatorListener(object : Animator.AnimatorListener {\n            override fun onAnimationStart(p0: Animator?) {\n\n\n            }\n\n            override fun onAnimationEnd(animation: Animator?, isReverse: Boolean) {\n                super.onAnimationEnd(animation, isReverse)\n            }\n\n            override fun onAnimationEnd(p0: Animator?) {\n                if (Utils.edtValue(binding.viewChatBtm.edtMsg).isEmpty()) {\n                    binding.viewChatBtm.imgRecord.show()\n                    binding.viewChatBtm.lottieSend.gone()\n                }\n            }\n\n            override fun onAnimationCancel(p0: Animator?) {\n            }\n\n            override fun onAnimationRepeat(p0: Animator?) {\n\n\n            }\n        })\n\n        binding.lottieVoice.addAnimatorListener(object : Animator.AnimatorListener{\n            override fun onAnimationStart(p0: Animator?) {\n\n\n            }\n\n            override fun onAnimationEnd(animation: Animator?, isReverse: Boolean) {\n                super.onAnimationEnd(animation, isReverse)\n            }\n\n            override fun onAnimationEnd(p0: Animator?) {\n                binding.viewChatBtm.imgRecord.show()\n                binding.lottieVoice.gone()\n            }\n\n            override fun onAnimationCancel(p0: Animator?) {\n            }\n\n            override fun onAnimationRepeat(p0: Animator?) {\n\n\n            }\n        })\n    }\n\n    private val msgTxtChangeListener = object : TextWatcher {\n        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {\n        }\n\n        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {\n            viewModel.sendTyping(binding.viewChatBtm.edtMsg.trim())\n            if(binding.viewChatBtm.lottieSend.isAnimating)\n                return\n            if(s.isNullOrBlank()) {\n                binding.viewChatBtm.imgRecord.show()\n                binding.viewChatBtm.lottieSend.hide()\n            }\n            else{\n                binding.viewChatBtm.lottieSend.show()\n                binding.viewChatBtm.imgRecord.hide()\n            }\n        }\n\n        override fun afterTextChanged(s: Editable?) {\n        }\n    }\n\n    override fun onItemClicked(v: View, position: Int) {\n        binding.fullSizeImageView.show()\n        StfalconImageViewer.Builder(\n            context,\n            listOf(MyImage(messageList.get(position).imageMessage?.uri!!))) { imageView, myImage ->\n            ImageUtils.loadGalleryImage(myImage.url,imageView)\n        }\n            .withDismissListener { binding.fullSizeImageView.visibility = View.GONE }\n            .show()\n    }\n\n    override fun onResume() {\n        preference.setCurrentGroup(group.id)\n        viewModel.sendCachedTxtMesssages()\n        Utils.removeNotification(requireContext())\n        super.onResume()\n    }\n\n    override fun onCommitContent(\n        inputContentInfo: InputContentInfoCompat?,\n        flags: Int,\n        opts: Bundle?) {\n        val imageMsg = createMessage()\n        val image = ImageMessage(\"${inputContentInfo?.contentUri}\")\n        image.imageType = if (image.uri.toString().endsWith(\".png\")) \"sticker\" else \"gif\"\n        imageMsg.apply {\n            type = \"image\"\n            imageMessage = image\n        }\n        viewModel.uploadToCloud(imageMsg,image.toString())\n    }\n\n    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n        super.onActivityResult(requestCode, resultCode, data)\n        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE)\n            onCropResult(data)\n        else\n            ImageUtils.cropImage(requireActivity(), data, true)\n    }\n\n    private fun onCropResult(data: Intent?) {\n        try {\n            val imagePath: Uri? = ImageUtils.getCroppedImage(data)\n            if (imagePath!=null){\n                val message=createMessage()\n                message.type=\"image\"\n                message.imageMessage=ImageMessage(imagePath.toString())\n                viewModel.uploadToCloud(message,imagePath.toString())\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onRequestPermissionsResult(\n        requestCode: Int,\n        permissions: Array<out String>,grantResults: IntArray) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n        if(requestCode==REQ_AUDIO_PERMISSION){\n            if (Utils.isPermissionOk(*grantResults))\n                startRecording()\n            else\n                requireActivity().toast(\"Audio permission is needed!\")\n        }\n    }\n\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    fun onAttachmentItemClicked(event: BottomSheetEvent) {\n        when (event.position) {\n            0 -> {\n                ImageUtils.takePhoto(requireActivity())\n            }\n            1 -> {\n                ImageUtils.chooseGallery(requireActivity())\n            }\n            2 -> {\n                //create intent for gallery video\n            }\n            3 -> {\n                //create intent for camera video\n            }\n        }\n    }\n\n    private fun startRecording() {\n        binding.lottieVoice.show()\n        binding.lottieVoice.playAnimation()\n        binding.viewChatBtm.edtMsg.apply {\n            isEnabled=false\n            hint=\"Recording...\"\n        }\n        onAudioEvent(EventAudioMsg(true))\n        //name of the file where record will be stored\n        lastAudioFile=\n            \"${requireActivity().externalCacheDir?.absolutePath}/audiorecord${System.currentTimeMillis()}.mp3\"\n        recorder = MediaRecorder().apply {\n            setAudioSource(MediaRecorder.AudioSource.MIC)\n            setOutputFormat(MediaRecorder.OutputFormat.DEFAULT)\n            setOutputFile(lastAudioFile)\n            setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)\n            try {\n                prepare()\n            } catch (e: IOException) {\n                println(\"ChatFragment.startRecording${e.message}\")\n            }\n            start()\n            isRecording=true\n            recordStart = Date().time\n        }\n        Handler(Looper.getMainLooper()).postDelayed({\n            binding.lottieVoice.pauseAnimation()\n        },800)\n    }\n\n\n    private fun stopRecording() {\n        onAudioEvent(EventAudioMsg(false))\n        binding.viewChatBtm.edtMsg.apply {\n            isEnabled=true\n            hint=\"Type Something...\"\n        }\n        Handler(Looper.getMainLooper()).postDelayed({\n            binding.lottieVoice.resumeAnimation()\n        },200)\n        recorder?.apply {\n            stop()\n            release()\n            recorder = null\n        }\n        isRecording=false\n        recordDuration = Date().time - recordStart\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        EventBus.getDefault().register(this)\n    }\n\n    override fun onDestroyView() {\n        super.onDestroyView()\n        stopRecording()\n        AdGroupChat.stopPlaying()\n        EventBus.getDefault().unregister(this)\n    }\n\n    @Subscribe\n    fun onAudioEvent(audioEvent: EventAudioMsg){\n        if (audioEvent.isPlaying){\n            //lock current orientation\n            val currentOrientation=requireActivity().resources.configuration.orientation\n            requireActivity().requestedOrientation = currentOrientation\n        }else {\n            requireActivity().requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED\n            if (msgPostponed){\n                //refresh list\n                AdGroupChat.messageList = messageList\n                adChat.submitList(messageList)\n                msgPostponed=false\n            }\n        }\n    }\n\n    override fun onStop() {\n        super.onStop()\n        preference.clearCurrentGroup()\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        Utils.closeKeyBoard(requireActivity())\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/group_chat/GroupChatViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.group_chat\n\nimport android.content.Context\nimport android.os.Handler\nimport android.os.Looper\nimport android.text.TextUtils\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport androidx.work.Data\nimport androidx.work.OneTimeWorkRequestBuilder\nimport androidx.work.WorkManager\nimport androidx.work.WorkRequest\nimport com.google.firebase.database.DatabaseReference\nimport com.google.firebase.database.FirebaseDatabase\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.FieldValue\nimport com.google.firebase.firestore.ListenerRegistration\nimport com.gowtham.letschat.TYPE_NEW_GROUP_MESSAGE\nimport com.gowtham.letschat.core.GroupMsgSender\nimport com.gowtham.letschat.core.GroupMsgStatusUpdater\nimport com.gowtham.letschat.core.OnGrpMessageResponse\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.daos.GroupMessageDao\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.db.data.GroupMessage\nimport com.gowtham.letschat.di.GroupCollection\nimport com.gowtham.letschat.fragments.single_chat.toDataClass\nimport com.gowtham.letschat.services.GroupUploadWorker\nimport com.gowtham.letschat.utils.Constants\nimport com.gowtham.letschat.utils.LogMessage\nimport com.gowtham.letschat.utils.MPreference\nimport com.gowtham.letschat.utils.UserUtils\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\nimport timber.log.Timber\nimport javax.inject.Inject\n\n@HiltViewModel\nclass GroupChatViewModel @Inject constructor(\n    @ApplicationContext private val context: Context,\n    private val preference: MPreference,\n    private val groupMsgDao: GroupMessageDao,\n    private val chatUserDao: ChatUserDao,\n    private val dbRepository: DbRepository,\n    private val groupMsgStatusUpdater: GroupMsgStatusUpdater,\n    @GroupCollection\n    private val groupCollection: CollectionReference\n) : ViewModel() {\n\n    val message = MutableLiveData<String>()\n\n    val typingUsers = MutableLiveData<String>()\n\n    private val currentGroup = preference.getOnlineGroup()\n\n    private val fromUser = preference.getUid()\n\n    private var isTyping = false\n\n    private var groupListener: ListenerRegistration? = null\n\n    private val typingHandler = Handler(Looper.getMainLooper())\n\n    private var canScroll = false\n\n    private var cleared = false\n\n    private lateinit var group: Group\n\n    init {\n        groupCollection.document(currentGroup).addSnapshotListener { value, error ->\n            try {\n                if (error == null) {\n                    val list = value?.get(\"typing_users\")\n                    val users = if (list == null) ArrayList()\n                    else list as ArrayList<String>\n                    val names = group.members?.filter { users.contains(it.id) && it.id != fromUser }\n                        ?.map { //get locally saved name\n                            it.localName + \" is typing...\"\n                        }\n                    if (users.isNullOrEmpty())\n                        typingUsers.postValue(\"\")\n                    else\n                        typingUsers.postValue(TextUtils.join(\",\", names!!))\n                }\n            } catch (e: Exception) {\n                e.printStackTrace()\n            }\n        }\n    }\n\n    fun getGroupMessages(groupId: String) = groupMsgDao.getChatsOfGroup(groupId)\n\n    fun getChatUsers() = chatUserDao.getAllChatUser()\n\n    fun setGroup(group: Group) {\n        if (!this::group.isInitialized) {\n            this.group = group\n            setSeenAllMessage()\n        }\n    }\n\n    private fun setSeenAllMessage() {\n        if (this::group.isInitialized) {\n            group.unRead=0\n            dbRepository.insertGroup(group)\n            viewModelScope.launch(Dispatchers.IO) {\n                val messageList = dbRepository.getChatsOfGroupList(group.id)\n                withContext(Dispatchers.Main){\n                    groupMsgStatusUpdater.updateToSeen(fromUser!!, messageList, group.id)\n                }\n            }\n        }\n    }\n\n    fun canScroll(can: Boolean) {\n        canScroll = can\n    }\n\n    fun getCanScroll() = canScroll\n\n    fun sendTyping(edtValue: String) {\n        if (edtValue.isEmpty()) {\n            if (isTyping)\n                sendTypingStatus(false, fromUser!!, currentGroup)\n            isTyping = false\n        } else if (!isTyping) {\n            sendTypingStatus(true, fromUser!!, currentGroup)\n            isTyping = true\n            removeTypingCallbacks()\n            typingHandler.postDelayed(typingThread, 4000)\n        }\n    }\n\n    private fun sendTypingStatus(\n        isTyping: Boolean,\n        fromUser: String, currentGroup: String\n    ) {\n        val value =\n            if (isTyping) FieldValue.arrayUnion(fromUser) else FieldValue.arrayRemove(fromUser)\n        groupCollection.document(currentGroup).update(\"typing_users\", value)\n    }\n\n    private val typingThread = Runnable {\n        isTyping = false\n        sendTypingStatus(false, fromUser!!, currentGroup)\n        removeTypingCallbacks()\n    }\n\n    private fun removeTypingCallbacks() {\n        typingHandler.removeCallbacks(typingThread)\n    }\n\n    fun sendCachedTxtMesssages() {\n        CoroutineScope(Dispatchers.IO).launch {\n            updateCacheMessges(groupMsgDao.getChatsOfGroupList(currentGroup))\n        }\n    }\n\n    private suspend fun updateCacheMessges(chatsOfGroup: List<GroupMessage>) {\n        withContext(Dispatchers.Main) {\n            val nonSendMsgs = chatsOfGroup.filter {\n                it.from == fromUser\n                        && it.status[0] == 0 && it.type == \"text\"\n            }\n            LogMessage.v(\"nonSendMsgs Group Size ${nonSendMsgs.size}\")\n            for (cachedMsg in nonSendMsgs) {\n                val messageSender = GroupMsgSender(groupCollection)\n                messageSender.sendMessage(cachedMsg, group, messageListener)\n            }\n        }\n    }\n\n    override fun onCleared() {\n        super.onCleared()\n        cleared = true\n        groupListener?.remove()\n    }\n\n    fun sendMessage(message: GroupMessage) {\n        Handler(Looper.getMainLooper()).postDelayed({\n            val messageSender = GroupMsgSender(groupCollection)\n            messageSender.sendMessage(message, group, messageListener)\n        }, 300)\n        UserUtils.insertGroupMsg(groupMsgDao, message)\n    }\n\n    fun uploadToCloud(message: GroupMessage, fileUri: String) {\n        try {\n            UserUtils.insertGroupMsg(groupMsgDao, message)\n            removeTypingCallbacks()\n            val messageData = Json.encodeToString(message)\n            val groupData = Json.encodeToString(group)\n            val data = Data.Builder()\n                .putString(Constants.MESSAGE_FILE_URI, fileUri)\n                .putString(Constants.MESSAGE_DATA, messageData)\n                .putString(Constants.GROUP_DATA, groupData)\n                .build()\n            val uploadWorkRequest: WorkRequest =\n                OneTimeWorkRequestBuilder<GroupUploadWorker>()\n                    .setInputData(data)\n                    .build()\n            WorkManager.getInstance(context).enqueue(uploadWorkRequest)\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n\n    private val messageListener = object : OnGrpMessageResponse {\n        override fun onSuccess(message: GroupMessage) {\n            LogMessage.v(\"messageListener OnSuccess ${message.textMessage?.text}\")\n            UserUtils.insertGroupMsg(groupMsgDao, message)\n            val users = group.members?.filter { it.user.token.isNotEmpty() }?.map {\n                it.user.token\n                it\n            }\n            users?.forEach {\n                UserUtils.sendPush(\n                    context, TYPE_NEW_GROUP_MESSAGE,\n                    Json.encodeToString(message), it.user.token.toString(), it.id\n                )\n            }\n        }\n\n        override fun onFailed(message: GroupMessage) {\n            LogMessage.v(\"messageListener onFailed ${message.createdAt}\")\n            UserUtils.insertGroupMsg(groupMsgDao, message)\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/group_chat_home/AdGroupChatHome.kt",
    "content": "package com.gowtham.letschat.fragments.group_chat_home\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.recyclerview.widget.DiffUtil\nimport androidx.recyclerview.widget.ListAdapter\nimport androidx.recyclerview.widget.RecyclerView\nimport com.gowtham.letschat.databinding.RowChatBinding\nimport com.gowtham.letschat.databinding.RowGroupChatBinding\nimport com.gowtham.letschat.databinding.RowReceiveMessageBinding\nimport com.gowtham.letschat.databinding.RowSentMessageBinding\nimport com.gowtham.letschat.db.data.ChatUserWithMessages\nimport com.gowtham.letschat.db.data.GroupWithMessages\nimport com.gowtham.letschat.fragments.single_chat_home.AdSingleChatHome\nimport com.gowtham.letschat.utils.ItemClickListener\nimport com.gowtham.letschat.utils.MPreference\nimport java.util.*\n\nclass AdGroupChatHome(private val context: Context) :\n    ListAdapter<GroupWithMessages, RecyclerView.ViewHolder>(DiffCallbackChats()) {\n\n    private val preference = MPreference(context)\n\n    companion object {\n        lateinit var allList: MutableList<GroupWithMessages>\n        lateinit var itemClickListener: ItemClickListener\n    }\n\n    fun filter(query: String) {\n        try {\n            val list= mutableListOf<GroupWithMessages>()\n            if (query.isEmpty())\n                list.addAll(allList)\n            else {\n                for (group in allList) {\n                    if (group.group.id.toLowerCase(Locale.getDefault())\n                            .contains(query.toLowerCase(Locale.getDefault()))) {\n                        list.add(group)\n                    }\n                }\n            }\n            submitList(null)\n            submitList(list)\n        } catch (e: Exception) {\n            e.stackTrace\n        }\n    }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {\n        val layoutInflater = LayoutInflater.from(parent.context)\n        val binding = RowGroupChatBinding.inflate(layoutInflater, parent, false)\n        return ViewHolder(binding)\n    }\n\n    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {\n        val viewHolder=holder as ViewHolder\n        viewHolder.bind(getItem(position))\n    }\n\n    class ViewHolder(val binding: RowGroupChatBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: GroupWithMessages) {\n            binding.groupChat = item\n            binding.viewRoot.setOnClickListener { v ->\n                itemClickListener.onItemClicked(v,bindingAdapterPosition)\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n}\n\nclass DiffCallbackChats : DiffUtil.ItemCallback<GroupWithMessages>() {\n    override fun areItemsTheSame(oldItem: GroupWithMessages, newItem: GroupWithMessages): Boolean {\n        return oldItem.group.id == oldItem.group.id\n    }\n\n    override fun areContentsTheSame(oldItem: GroupWithMessages, newItem: GroupWithMessages): Boolean {\n        return oldItem.messages == newItem.messages && oldItem.group==newItem.group\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/group_chat_home/FGroupChatHome.kt",
    "content": "package com.gowtham.letschat.fragments.group_chat_home\n\nimport android.app.Activity\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.fragment.app.viewModels\nimport androidx.lifecycle.lifecycleScope\nimport androidx.navigation.fragment.findNavController\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.FGroupChatHomeBinding\nimport com.gowtham.letschat.db.data.GroupWithMessages\nimport com.gowtham.letschat.ui.activities.SharedViewModel\nimport com.gowtham.letschat.utils.*\nimport dagger.hilt.android.AndroidEntryPoint\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.flow.collect\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport javax.inject.Inject\n\n\n@AndroidEntryPoint\nclass FGroupChatHome : Fragment(),ItemClickListener{\n\n    private val viewModel: GroupChatHomeViewModel by viewModels()\n\n    private lateinit var binding: FGroupChatHomeBinding\n\n    private val sharedViewModel by activityViewModels<SharedViewModel>()\n\n    @Inject\n    lateinit var preference: MPreference\n\n    private lateinit var activity: Activity\n\n    private val groups= mutableListOf<GroupWithMessages>()\n\n    private val adGroupHome by lazy {\n        AdGroupChatHome(requireContext())\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?): View? {\n        binding = FGroupChatHomeBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        activity=requireActivity()\n        binding.lifecycleOwner = viewLifecycleOwner\n        setDataInView()\n        subscribeObservers()\n    }\n\n    private fun subscribeObservers() {\n        lifecycleScope.launch {\n            viewModel.getGroupMessages().collect { groupWithmsgs ->\n                updateList(groupWithmsgs)\n            }\n        }\n\n        sharedViewModel.getState().observe(viewLifecycleOwner,{state->\n            if (state is ScreenState.IdleState){\n                CoroutineScope(Dispatchers.IO).launch {\n                    updateList(viewModel.getGroupMessagesAsList())\n                }\n            }\n        })\n\n        sharedViewModel.lastQuery.observe(viewLifecycleOwner,{\n            if (sharedViewModel.getState().value is ScreenState.SearchState)\n                adGroupHome.filter(it)\n        })\n    }\n\n    private suspend fun updateList(groupWithmsgs: List<GroupWithMessages>) {\n        withContext(Dispatchers.Main){\n            if (!groupWithmsgs.isNullOrEmpty()) {\n                val list1=  groupWithmsgs.filter { it.messages.isEmpty() }\n                    .sortedByDescending { it.group.createdAt }.toMutableList()\n                val groupHasMsgsList=groupWithmsgs.filter { it.messages.isNotEmpty() }.\n                sortedBy { it.messages.last().createdAt }\n\n                for (a in groupHasMsgsList)\n                    list1.add(0,a)\n\n                adGroupHome.submitList(list1)\n                AdGroupChatHome.allList=list1\n                groups.clear()\n                groups.addAll(list1)\n                if(sharedViewModel.getState().value is ScreenState.SearchState)\n                    adGroupHome.filter(sharedViewModel.lastQuery.value.toString())\n            }else\n                binding.imageEmpty.show()\n        }\n    }\n\n    private fun setDataInView() {\n        binding.listGroup.adapter = adGroupHome\n        binding.listGroup.itemAnimator = null\n        AdGroupChatHome.itemClickListener=this\n        adGroupHome.addRestorePolicy()\n    }\n\n    override fun onRequestPermissionsResult(\n        requestCode: Int,\n        permissions: Array<out String>,\n        grantResults: IntArray) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n        if (Utils.isPermissionOk(*grantResults) &&\n            findNavController().isValidDestination(R.id.FGroupChatHome)){\n            findNavController().navigate(R.id.action_FGroupChatHome_to_FAddGroupMembers)\n        }\n        else\n            activity.toast(\"Permission is needed!\")\n    }\n\n    override fun onItemClicked(v: View, position: Int) {\n        sharedViewModel.setState(ScreenState.IdleState)\n        val group = adGroupHome.currentList[position].group\n        preference.setCurrentGroup(group.id)\n        val action = FGroupChatHomeDirections.actionFGroupChatHomeToFGroupChat(group)\n        findNavController().navigate(action)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/group_chat_home/GroupChatHomeViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.group_chat_home\n\nimport androidx.lifecycle.ViewModel\nimport com.google.firebase.firestore.CollectionReference\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.utils.MPreference\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport javax.inject.Inject\n\n@HiltViewModel\nclass GroupChatHomeViewModel @Inject constructor(\n    private val preference: MPreference,\n    private val dbRepository: DbRepository,\n    private val usersCollection: CollectionReference) : ViewModel()  {\n\n\n    fun getGroupMessages() = dbRepository.getGroupWithMessages()\n\n    fun getGroupMessagesAsList() = dbRepository.getGroupWithMessagesList()\n\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/login/FLogin.kt",
    "content": "package com.gowtham.letschat.fragments.login\n\nimport android.content.Context\nimport android.os.Bundle\nimport android.telephony.TelephonyManager\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.lifecycle.ViewModelProvider\nimport androidx.navigation.fragment.findNavController\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.FLoginBinding\nimport com.gowtham.letschat.models.Country\nimport com.gowtham.letschat.ui.activities.SharedViewModel\nimport com.gowtham.letschat.utils.*\nimport com.gowtham.letschat.views.CustomProgressView\nimport dagger.hilt.android.AndroidEntryPoint\n\n@AndroidEntryPoint\nclass FLogin : Fragment() {\n\n    private var country: Country? = null\n\n    private lateinit var binding: FLoginBinding\n\n    private val sharedViewModel by activityViewModels<SharedViewModel>()\n\n    private var progressView: CustomProgressView?=null\n\n    private val viewModel by activityViewModels<LogInViewModel>()\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?): View? {\n        binding = FLoginBinding.inflate(layoutInflater, container, false)\n        binding.lifecycleOwner = viewLifecycleOwner\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        progressView = CustomProgressView(requireContext())\n        setDataInView()\n        subscribeObservers()\n    }\n\n    private fun setDataInView() {\n        binding.viewmodel = viewModel\n        setDefaultCountry()\n        binding.txtCountryCode.setOnClickListener {\n            Utils.closeKeyBoard(requireActivity())\n            findNavController().navigate(R.id.action_FLogIn_to_FCountries)\n        }\n        binding.btnGetOtp.setOnClickListener {\n            validate()\n        }\n    }\n\n    private fun validate() {\n        try {\n            Utils.closeKeyBoard(requireActivity())\n            val mobileNo = viewModel.mobile.value?.trim()\n            val country = viewModel.country.value\n            when {\n                Validator.isMobileNumberEmpty(mobileNo) -> snack(requireActivity(), \"Enter valid mobile number\")\n                country == null -> snack(requireActivity(), \"Select a country\")\n                !Validator.isValidNo(country.code, mobileNo!!) -> snack(\n                    requireActivity(),\n                    \"Enter valid mobile number\"\n                )\n                Utils.isNoInternet(requireContext()) -> snackNet(requireActivity())\n                else -> {\n                    viewModel.setMobile()\n                    viewModel.setProgress(true)\n                }\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun setDefaultCountry() {\n        try {\n            country = Utils.getDefaultCountry()\n            val manager =\n                requireActivity().getSystemService(Context.TELEPHONY_SERVICE) as (TelephonyManager)?\n            manager?.let {\n                val countryCode = Utils.clearNull(manager.networkCountryIso)\n                if (countryCode.isEmpty())\n                    return\n                val countries = Countries.getCountries()\n                for (i in countries) {\n                    if (i.code.equals(countryCode, true))\n                        country = i\n                }\n                viewModel.setCountry(country!!)\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun subscribeObservers() {\n        try {\n            sharedViewModel.country.observe(viewLifecycleOwner, {\n                viewModel.setCountry(it)\n            })\n\n            viewModel.getProgress().observe(viewLifecycleOwner, {\n                progressView?.toggle(it)\n            })\n\n            viewModel.getVerificationId().observe(viewLifecycleOwner, { vCode ->\n                vCode?.let {\n                    viewModel.setProgress(false)\n                    viewModel.resetTimer()\n                    viewModel.setVCodeNull()\n                    viewModel.setEmptyText()\n                    if (findNavController().isValidDestination(R.id.FLogIn))\n                    findNavController().navigate(R.id.action_FLogIn_to_FVerify)\n                }\n            })\n\n            viewModel.getFailed().observe(viewLifecycleOwner, {\n                progressView?.dismiss()\n            })\n\n            viewModel.getTaskResult().observe(viewLifecycleOwner, { taskId ->\n                if (taskId!=null && viewModel.getCredential().value?.smsCode.isNullOrEmpty())\n                    viewModel.fetchUser(taskId)\n            })\n\n            viewModel.userProfileGot.observe(viewLifecycleOwner, { success ->\n                if (success && viewModel.getCredential().value?.smsCode.isNullOrEmpty()\n                               && findNavController().isValidDestination(R.id.FLogIn)) {\n                    requireActivity().toastLong(\"Authenticated successfully using Instant verification\")\n                    findNavController().navigate(R.id.action_FLogIn_to_FProfile)\n                }\n            })\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n    /*       val action = FMobileDirections.actionFMobileToFVerify(\n             Country(\n                 code = \"sd\",\n                 name = \"sda\",\n                 noCode = \"+83\",\n                 money = \"mon\"\n             )\n         )\n         findNavController().navigate(action)*/\n\n    override fun onDestroy() {\n        try {\n            progressView?.dismissIfShowing()\n            super.onDestroy()\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/login/FVerify.kt",
    "content": "package com.gowtham.letschat.fragments.login\n\nimport android.os.Bundle\nimport android.text.Editable\nimport android.text.TextWatcher\nimport android.view.KeyEvent\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.EditText\nimport androidx.databinding.DataBindingUtil\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.navigation.fragment.findNavController\nimport com.google.firebase.auth.PhoneAuthProvider\nimport com.gowtham.letschat.BuildConfig\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.FVerifyBinding\nimport com.gowtham.letschat.utils.*\nimport com.gowtham.letschat.views.CustomProgressView\nimport dagger.hilt.android.AndroidEntryPoint\nimport javax.inject.Inject\n\n@AndroidEntryPoint\nclass FVerify : Fragment() {\n\n    private lateinit var binding: FVerifyBinding\n\n    private val viewModel by activityViewModels<LogInViewModel>()\n\n    private lateinit var edtTexts: ArrayList<EditText>\n\n    @Inject\n    lateinit var preferences: MPreference\n\n    private var progressView: CustomProgressView?=null\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View? {\n        binding = FVerifyBinding.inflate(layoutInflater, container, false)\n        binding.lifecycleOwner = viewLifecycleOwner\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        binding.viewmodel = viewModel\n        progressView = CustomProgressView(requireContext())\n        setDataInView()\n        subscribeObservers()\n/*\n        if (arguments != null) {\n            val s = FVerifyArgs.fromBundle(requireArguments()).country\n            s.name.printMeD()\n        } else\n            \"argument is null\".printMeD()*/\n    }\n\n    private fun setDataInView() {\n        try {\n            edtTexts = ArrayList()\n            edtTexts.add(binding.edtOne)\n            edtTexts.add(binding.edtTwo)\n            edtTexts.add(binding.edtThree)\n            edtTexts.add(binding.edtFour)\n            edtTexts.add(binding.edtFive)\n            edtTexts.add(binding.edtSix)\n            addListener()\n            if (viewModel.resendTxt.value.isNullOrEmpty())\n                viewModel.startTimer()\n            binding.btnVerify.setOnClickListener {\n                validateOtp()\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun validateOtp() {\n        try {\n            val otp = getOtpValue()\n            when {\n                otp.length < 6 -> snack(requireActivity(), \"Enter valid otp\")\n                Utils.isNoInternet(requireContext()) -> {\n                    snackNet(requireActivity())\n                }\n                else -> {\n                    \"VCode:: ${viewModel.verifyCode}\".printMeD()\n                    \"OTP:: $otp\".printMeD()\n                    val credential = PhoneAuthProvider.getCredential(viewModel.verifyCode, otp)\n                    viewModel.setCredential(credential)\n                }\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun getOtpValue(): String {\n        try {\n            var otp = \"\"\n            for (edtTxt in edtTexts)\n                otp += edtTxt.trim()\n            return otp\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n        return \"\"\n    }\n\n    private fun addListener() {\n        try {\n            for (editText in edtTexts) {\n                editText.addTextChangedListener(OtpWatcher(editText))\n                editText.setOnKeyListener { _, keyCode: Int, _ ->\n                    if (keyCode == KeyEvent.KEYCODE_DEL)\n                        onKeyListener()\n                    false\n                }\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun onKeyListener() {\n        try {\n            val edtView: EditText = edtTexts[viewModel.ediPosition]\n            if (edtView.trim().isEmpty() && viewModel.ediPosition > 0) {\n                viewModel.ediPosition -= 1\n                edtTexts[viewModel.ediPosition].requestFocus()\n            } else edtView.requestFocus()\n        } catch (e: java.lang.Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun subscribeObservers() {\n        try {\n            viewModel.getCredential().observe(viewLifecycleOwner, { credential ->\n                credential?.let {\n                    val otp = credential.smsCode\n                    edtTexts.forEachIndexed { i, editText ->\n                        editText.text = otp?.get(i)?.toEditable()\n                    }\n                    viewModel.setVProgress(true)\n                }\n            })\n\n            viewModel.getVProgress().observe(viewLifecycleOwner, { show ->\n                progressView?.toggle(show)\n            })\n\n            viewModel.getFailed().observe(viewLifecycleOwner, {\n                viewModel.setVProgress(false)\n            })\n\n            viewModel.getVerificationId().observe(viewLifecycleOwner, { vCode ->\n                vCode?.let {\n                    viewModel.setVProgress(false)\n                    viewModel.setVCodeNull()\n                    viewModel.startTimer()\n                }\n            })\n\n            viewModel.getTaskResult().observe(viewLifecycleOwner, { taskId ->\n                taskId?.let {\n                    viewModel.fetchUser(taskId)\n                }\n            })\n\n            viewModel.userProfileGot.observe(viewLifecycleOwner, { success ->\n                if (success && findNavController().isValidDestination(R.id.FVerify))\n                    findNavController().navigate(R.id.action_FVerify_to_FProfile)\n            })\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    inner class OtpWatcher(private val v: View) : TextWatcher {\n        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {\n        }\n\n        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {\n        }\n\n        override fun afterTextChanged(s: Editable?) {\n            val text = s.toString()\n            when (v.id) {\n                R.id.edt_one ->\n                    changeFocus(text, 0, 1)\n                R.id.edt_two ->\n                    changeFocus(text, 0, 2)\n                R.id.edt_three ->\n                    changeFocus(text, 1, 3)\n                R.id.edt_four ->\n                    changeFocus(text, 2, 4)\n                R.id.edt_five ->\n                    changeFocus(text, 3, 5)\n                R.id.edt_six ->\n                    changeFocus(text, 4, 5)\n                else -> {\n                    if (text.isEmpty())\n                        edtTexts[5].requestFocus()\n                }\n            }\n        }\n    }\n\n    private fun changeFocus(text: String, previous1: Int, next: Int) {\n        viewModel.ediPosition = next - 1\n        edtTexts[if (text.isEmpty()) previous1 else next].requestFocus()\n    }\n\n    override fun onDestroy() {\n        progressView?.dismissIfShowing()\n        viewModel.clearAll()\n        super.onDestroy()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/login/LogInViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.login\n\nimport android.content.Context\nimport android.os.CountDownTimer\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport com.google.android.gms.tasks.Task\nimport com.google.firebase.auth.AuthResult\nimport com.google.firebase.auth.PhoneAuthCredential\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.TYPE_LOGGED_IN\nimport com.gowtham.letschat.models.Country\nimport com.gowtham.letschat.models.ModelMobile\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.*\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport dagger.hilt.android.scopes.ActivityRetainedScoped\nimport dagger.hilt.android.scopes.ActivityScoped\nimport timber.log.Timber\nimport java.util.*\nimport javax.inject.Inject\nimport javax.inject.Singleton\n\n\n@HiltViewModel\nclass LogInViewModel @Inject\nconstructor(@ApplicationContext private val context: Context,\n            private val logInRepo: LoginRepo, private val preference: MPreference) :\n    ViewModel() {\n\n    val country = MutableLiveData<Country>()\n\n    val mobile = MutableLiveData<String>()\n\n    val userProfileGot=MutableLiveData<Boolean>()\n\n    private val progress = MutableLiveData(false)\n\n    private val verifyProgress = MutableLiveData(false)\n\n    var canResend: Boolean = false\n\n    val resendTxt = MutableLiveData<String>()\n\n    val otpOne = MutableLiveData<String>()\n\n    val otpTwo = MutableLiveData<String>()\n\n    val otpThree = MutableLiveData<String>()\n\n    val otpFour = MutableLiveData<String>()\n\n    val otpFive = MutableLiveData<String>()\n\n    val otpSix = MutableLiveData<String>()\n\n    var ediPosition = 0\n\n    var verifyCode: String = \"\"\n\n    private lateinit var timer: CountDownTimer\n\n    init {\n        \"LogInViewModel init\".printMeD()\n    }\n\n    fun setCountry(country: Country) {\n        this.country.value = country\n    }\n\n    fun setMobile() {\n        logInRepo.clearOldAuth()\n        saveMobile()\n        logInRepo.setMobile(country.value!!, mobile.value!!)\n    }\n\n    fun setProgress(show: Boolean) {\n        progress.value = show\n    }\n\n    fun getProgress(): LiveData<Boolean> {\n        return progress\n    }\n\n    fun resendClicked() {\n        \"Resend Clicked\".printMeD()\n        if (canResend) {\n            setVProgress(true)\n            setMobile()\n        }\n    }\n\n    fun startTimer() {\n        try {\n            canResend = false\n            timer = object : CountDownTimer(60000, 1000) {\n                override fun onTick(millisUntilFinished: Long) {\n                    setTimerTxt(millisUntilFinished / 1000)\n                }\n\n                override fun onFinish() {\n                    canResend = true\n                    resendTxt.value = \"Resend\"\n                }\n            }\n            timer.start()\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun resetTimer() {\n        canResend = false\n        resendTxt.value = \"\"\n        if (this::timer.isInitialized)\n        timer.cancel()\n    }\n\n    private fun setTimerTxt(seconds: Long) {\n        try {\n            val s = seconds % 60\n            val m = seconds / 60 % 60\n            if (s == 0L && m == 0L) return\n            val resend: String =\n                context.getString(R.string.txt_resend) + \" in \" + String.format(\n                    Locale.getDefault(),\n                    \"%02d:%02d\",\n                    m,\n                    s\n                )\n            resendTxt.value = resend\n        } catch (e: java.lang.Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun setEmptyText(){\n        otpOne.value=\"\"\n        otpTwo.value=\"\"\n        otpThree.value=\"\"\n        otpFour.value=\"\"\n        otpFive.value=\"\"\n        otpSix.value=\"\"\n    }\n\n    fun setVProgress(show: Boolean) {\n        verifyProgress.value = show\n    }\n\n    fun getVProgress(): LiveData<Boolean> {\n        return verifyProgress\n    }\n\n    fun getCredential(): LiveData<PhoneAuthCredential> {\n        return logInRepo.getCredential()\n    }\n\n    fun setCredential(credential: PhoneAuthCredential) {\n        setVProgress(true)\n        logInRepo.setCredential(credential)\n    }\n\n    fun setVCodeNull(){\n        verifyCode=logInRepo.getVCode().value!!\n        logInRepo.setVCodeNull()\n    }\n\n    fun getVerificationId(): MutableLiveData<String> {\n        return logInRepo.getVCode()\n    }\n\n    fun getTaskResult(): LiveData<Task<AuthResult>> {\n        return logInRepo.getTaskResult()\n    }\n\n    fun getFailed(): LiveData<LogInFailedState> {\n        return logInRepo.getFailed()\n    }\n\n    private fun saveMobile() =\n       preference.saveMobile(ModelMobile(country.value!!.noCode,mobile.value!!))\n\n    fun fetchUser(taskId: Task<AuthResult>) {\n        val db = FirebaseFirestore.getInstance()\n        val user = taskId.result?.user\n        Timber.v(\"FetchUser:: ${user?.uid}\")\n        val noteRef = db.document(\"Users/\" + user?.uid)\n        noteRef.get()\n            .addOnSuccessListener { data ->\n                Timber.v(\"Uss:: ${preference.getUid()}\")\n                preference.setUid(user?.uid.toString())\n                Timber.v(\"Uss11:: ${preference.getUid()}\")\n                preference.setLogin()\n                preference.setLogInTime()\n                setVProgress(false)\n                progress.value=false\n                if (data.exists()) {\n                    val appUser = data.toObject(UserProfile::class.java)\n                    Timber.v(\"UserId ${appUser?.uId}\")\n                    preference.saveProfile(appUser!!)\n                    //if device id is not same,send new_user_logged type notification to the token\n                   checkLastDevice(appUser)\n                }\n                userProfileGot.value=true\n            }.addOnFailureListener { e ->\n                setVProgress(false)\n                progress.value=false\n                context.toast(e.message.toString())\n            }\n    }\n\n    private fun checkLastDevice(appUser: UserProfile?) {\n        try {\n            if (appUser!=null){\n                val localDevice = UserUtils.getDeviceId(context)\n                val deviceDetails=appUser.deviceDetails\n                val sameDevice=deviceDetails?.device_id.equals(localDevice)\n                if (!sameDevice)\n                    UserUtils.sendPush(context,TYPE_LOGGED_IN,\"\", appUser.token,appUser.uId!!)\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun clearAll(){\n        userProfileGot.value=false\n        logInRepo.clearOldAuth()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/login/LoginRepo.kt",
    "content": "package com.gowtham.letschat.fragments.login\n\nimport android.content.Context\nimport android.os.Handler\nimport android.os.Looper\nimport android.util.Log\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport com.google.android.gms.tasks.Task\nimport com.google.firebase.FirebaseException\nimport com.google.firebase.auth.*\nimport com.gowtham.letschat.models.Country\nimport com.gowtham.letschat.ui.activities.MainActivity\nimport com.gowtham.letschat.utils.LogInFailedState\nimport com.gowtham.letschat.utils.printMeD\nimport com.gowtham.letschat.utils.toast\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport dagger.hilt.android.scopes.ActivityRetainedScoped\nimport timber.log.Timber\nimport java.util.concurrent.TimeUnit\nimport javax.inject.Inject\n\nclass LoginRepo @Inject constructor(@ActivityRetainedScoped val actContxt: MainActivity,\n                                    @ApplicationContext val context: Context) :\n    PhoneAuthProvider.OnVerificationStateChangedCallbacks() {\n\n    private val verificationId: MutableLiveData<String> = MutableLiveData()\n\n    private val credential: MutableLiveData<PhoneAuthCredential> = MutableLiveData()\n\n    private val taskResult: MutableLiveData<Task<AuthResult>> = MutableLiveData()\n\n    private val failedState: MutableLiveData<LogInFailedState> = MutableLiveData()\n\n    private val auth = FirebaseAuth.getInstance()\n\n    init {\n        \"LoginRepo init\".printMeD()\n    }\n\n    fun setMobile(country: Country, mobile: String) {\n        Timber.v(\"Mobile $mobile\")\n        val number = country.noCode + \" \" + mobile\n        val options = PhoneAuthOptions.newBuilder(auth)\n            .setPhoneNumber(number)\n            .setTimeout(60L, TimeUnit.SECONDS)\n            .setActivity(actContxt)\n            .setCallbacks(this)\n            .build()\n        PhoneAuthProvider.verifyPhoneNumber(options)\n    }\n\n    override fun onVerificationCompleted(credential: PhoneAuthCredential) {\n        Timber.v(\"onVerificationCompleted:$credential\")\n        this.credential.value = credential\n        Handler(Looper.getMainLooper()).postDelayed({\n            signInWithPhoneAuthCredential(credential)\n        }, 1000)\n    }\n\n    override fun onVerificationFailed(exp: FirebaseException) {\n        \"onVerficationFailed:: ${exp.message}\".printMeD()\n        failedState.value = LogInFailedState.Verification\n        when (exp) {\n            is FirebaseAuthInvalidCredentialsException ->\n                context.toast(\"Invalid Request\")\n            else -> context.toast(exp.message.toString())\n        }\n    }\n\n    override fun onCodeSent(verificationId: String, token: PhoneAuthProvider.ForceResendingToken) {\n        Timber.v(\"onCodeSent:$verificationId\")\n        this.verificationId.value = verificationId\n        context.toast(\"Verification code sent successfully\")\n    }\n\n    private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {\n        FirebaseAuth.getInstance().signInWithCredential(credential)\n            .addOnCompleteListener { task ->\n                if (task.isSuccessful) {\n                    Timber.v(\"signInWithCredential:success\")\n                    taskResult.value = task\n                } else {\n                    Timber.v(\"signInWithCredential:failure ${task.exception}\")\n                    if (task.exception is FirebaseAuthInvalidCredentialsException)\n                        context.toast(\"Invalid verification code!\")\n                    failedState.value = LogInFailedState.SignIn\n                }\n            }\n    }\n\n    fun setCredential(credential: PhoneAuthCredential) {\n        signInWithPhoneAuthCredential(credential)\n    }\n\n    fun getVCode(): MutableLiveData<String> {\n        return verificationId\n    }\n\n    fun setVCodeNull() {\n        verificationId.value = null\n    }\n\n    fun clearOldAuth(){\n        credential.value=null\n        taskResult.value=null\n    }\n\n    fun getCredential(): LiveData<PhoneAuthCredential> {\n        return credential\n    }\n\n    fun getTaskResult(): LiveData<Task<AuthResult>> {\n        return taskResult\n    }\n\n    fun getFailed(): LiveData<LogInFailedState> {\n        return failedState\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/myprofile/FMyProfile.kt",
    "content": "package com.gowtham.letschat.fragments.myprofile\n\nimport android.app.Activity\nimport android.app.Dialog\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.viewModels\nimport com.canhub.cropper.CropImage\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.AlertLogoutBinding\nimport com.gowtham.letschat.databinding.FMyProfileBinding\nimport com.gowtham.letschat.db.ChatUserDatabase\nimport com.gowtham.letschat.utils.*\nimport com.gowtham.letschat.views.CustomProgressView\nimport dagger.hilt.android.AndroidEntryPoint\nimport javax.inject.Inject\n\n\n@AndroidEntryPoint\nclass FMyProfile : Fragment(R.layout.f_my_profile) {\n\n    private lateinit var binding: FMyProfileBinding\n\n    @Inject\n    lateinit var preferenec: MPreference\n\n    @Inject\n    lateinit var db: ChatUserDatabase\n\n    private lateinit var dialog: Dialog\n\n    private val viewModel: FMyProfileViewModel by viewModels()\n\n    private lateinit var context: Activity\n\n    private var progressView: CustomProgressView? = null\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        binding = FMyProfileBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        context = requireActivity()\n        progressView = CustomProgressView(context)\n        binding.lifecycleOwner = viewLifecycleOwner\n        binding.viewModel = viewModel\n        binding.imageProfile.setOnClickListener {\n             ImageUtils.askPermission(this)\n        }\n        binding.btnSaveChanges.setOnClickListener {\n            val newName = viewModel.userName.value\n            val about = viewModel.about.value\n            val image=viewModel.imageUrl.value\n            when {\n                viewModel.isUploading.value!! -> context.toast(\"Profile picture is uploading!\")\n                newName.isNullOrBlank() -> context.toast(\"User name can't be empty!\")\n                else -> {\n                    context.window.decorView.clearFocus()\n                    viewModel.saveChanges(newName,about ?: \"\" ,image ?: \"\")\n                }\n            }\n        }\n        binding.btnLogout.setOnClickListener {\n            dialog.show()\n        }\n        initDialog()\n        subscribeObservers()\n    }\n\n    private fun subscribeObservers() {\n        viewModel.profileUpdateState.observe(viewLifecycleOwner, {\n            if (it is LoadState.OnLoading) {\n                progressView?.show()\n            } else\n                progressView?.dismiss()\n        })\n    }\n\n    private fun initDialog() {\n        try {\n            dialog = Dialog(requireContext())\n            val layoutBinder = AlertLogoutBinding.inflate(layoutInflater)\n            dialog.setContentView(layoutBinder.root)\n            dialog.window?.setLayout(\n                ViewGroup.LayoutParams.MATCH_PARENT,\n                ViewGroup.LayoutParams.WRAP_CONTENT\n            )\n            layoutBinder.txtOk.setOnClickListener {\n                dialog.dismiss()\n                UserUtils.logOut(requireActivity(), preferenec, db)\n            }\n            layoutBinder.txtCancel.setOnClickListener {\n                dialog.dismiss()\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n        super.onActivityResult(requestCode, resultCode, data)\n        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE)\n            onCropResult(data)\n        else\n            ImageUtils.cropImage(context, data, true)\n    }\n\n    private fun onCropResult(data: Intent?) {\n        try {\n            val imagePath: Uri? = ImageUtils.getCroppedImage(data)\n            imagePath?.let {\n                viewModel.uploadProfileImage(it)\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onRequestPermissionsResult(\n        requestCode: Int,\n        permissions: Array<out String>,\n        grantResults: IntArray\n    ) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n        ImageUtils.onImagePerResult(this, *grantResults)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/myprofile/FMyProfileViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.myprofile\n\nimport android.content.Context\nimport android.net.Uri\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport com.google.android.gms.tasks.OnFailureListener\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.SetOptions\nimport com.google.firebase.storage.UploadTask\nimport com.gowtham.letschat.utils.LoadState\nimport com.gowtham.letschat.utils.MPreference\nimport com.gowtham.letschat.utils.UserUtils\nimport com.gowtham.letschat.utils.toast\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport timber.log.Timber\nimport java.util.*\nimport javax.inject.Inject\n\n@HiltViewModel\nclass FMyProfileViewModel @Inject constructor(\n    @ApplicationContext private val context: Context,\n    private val preference: MPreference\n) : ViewModel() {\n\n    private var userProfile = preference.getUserProfile()\n\n    val userName = MutableLiveData(userProfile?.userName)\n\n    val imageUrl = MutableLiveData(userProfile?.image)\n\n    val about = MutableLiveData(userProfile?.about)\n\n    val isUploading = MutableLiveData(false)\n\n    private val mobileData = userProfile?.mobile\n\n    private val storageRef = UserUtils.getStorageRef(context)\n\n    private val docuRef = UserUtils.getDocumentRef(context)\n\n    val mobile = MutableLiveData(\"${mobileData?.country} ${mobileData?.number}\")\n\n    val profileUpdateState = MutableLiveData<LoadState>()\n\n    private lateinit var uploadTask: UploadTask\n\n    init {\n        Timber.v(\"FMyProfileViewModel init\")\n    }\n\n    fun uploadProfileImage(imagePath: Uri) {\n        try {\n            isUploading.value = true\n            val child = storageRef.child(\"profile_picture_${System.currentTimeMillis()}.jpg\")\n            if (this::uploadTask.isInitialized && uploadTask.isInProgress)\n                uploadTask.cancel()\n            uploadTask = child.putFile(imagePath)\n            uploadTask.addOnSuccessListener {\n                child.downloadUrl.addOnCompleteListener { taskResult ->\n                    isUploading.value = false\n                    imageUrl.value = taskResult.result.toString()\n                }.addOnFailureListener {\n                    OnFailureListener { e ->\n                        isUploading.value = false\n                        context.toast(e.message.toString())\n                    }\n                }\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun saveChanges(name: String, strAbout: String, image: String) {\n        name.toLowerCase(Locale.getDefault())\n        updateProfileData(name, strAbout, image)\n    }\n\n    private fun updateProfileData(name: String, strAbout: String, image: String) {\n        try {\n            profileUpdateState.value = LoadState.OnLoading\n            val profile = userProfile!!\n            profile.userName = name\n            profile.about = strAbout\n            profile.image = image\n            profile.updatedAt = System.currentTimeMillis()\n            docuRef.set(profile, SetOptions.merge()).addOnSuccessListener {\n                context.toast(\"Profile updated!\")\n                userProfile = profile\n                preference.saveProfile(profile)\n                profileUpdateState.value = LoadState.OnSuccess()\n            }.addOnFailureListener { e ->\n                context.toast(e.message.toString())\n                profileUpdateState.value = LoadState.OnFailure(e)\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onCleared() {\n        super.onCleared()\n        if (this::uploadTask.isInitialized && uploadTask.isInProgress)\n            uploadTask.cancel()\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/profile/FProfile.kt",
    "content": "package com.gowtham.letschat.fragments.profile\n\nimport android.app.Activity\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.databinding.DataBindingUtil\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.viewModels\nimport androidx.navigation.fragment.findNavController\nimport com.canhub.cropper.CropImage\nimport com.google.firebase.firestore.CollectionReference\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.FProfileBinding\nimport com.gowtham.letschat.databinding.FVerifyBinding\nimport com.gowtham.letschat.models.UserStatus\nimport com.gowtham.letschat.ui.activities.MainActivity\nimport com.gowtham.letschat.utils.*\nimport com.gowtham.letschat.views.CustomProgressView\nimport dagger.hilt.android.AndroidEntryPoint\nimport org.greenrobot.eventbus.EventBus\nimport javax.inject.Inject\n\n@AndroidEntryPoint\nclass FProfile : Fragment() {\n\n    private lateinit var binding: FProfileBinding\n\n    private lateinit var context: Activity\n\n    @Inject\n    lateinit var preference: MPreference\n\n    @Inject\n    lateinit var userCollection: CollectionReference\n\n    private var progressView: CustomProgressView? = null\n\n    private val viewModel: ProfileViewModel by viewModels()\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?,\n        savedInstanceState: Bundle?): View? {\n        binding = FProfileBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        context = requireActivity()\n        UserUtils.updatePushToken(context,userCollection,true)\n        EventBus.getDefault().post(UserStatus())\n        binding.lifecycleOwner = viewLifecycleOwner\n        binding.viewmodel = viewModel\n        progressView = CustomProgressView(context)\n        binding.imgProPic.setOnClickListener { ImageUtils.askPermission(this) }\n        binding.fab.setOnClickListener { validate() }\n        subscribeObservers()\n    }\n\n    private fun subscribeObservers() {\n        viewModel.progressProPic.observe(viewLifecycleOwner, { uploaded ->\n            binding.progressPro.toggle(uploaded)\n        })\n\n        viewModel.profileUpdateState.observe(viewLifecycleOwner, {\n            when (it) {\n                is LoadState.OnSuccess -> {\n                    if (findNavController().isValidDestination(R.id.FProfile)) {\n                        progressView?.dismiss()\n                        findNavController().navigate(R.id.action_FProfile_to_FSingleChatHome)\n                    }\n                }\n                is LoadState.OnFailure -> {\n                    progressView?.dismiss()\n                }\n                is LoadState.OnLoading -> {\n                    progressView?.show()\n                }\n            }\n        })\n\n        viewModel.checkUserNameState.observe(viewLifecycleOwner,{\n            when (it) {\n                is LoadState.OnFailure -> {\n                    progressView?.dismiss()\n                }\n                is LoadState.OnLoading -> {\n                    progressView?.show()\n                }\n            }\n        })\n    }\n\n    private fun validate() {\n        val name = viewModel.name.value\n        if (!name.isNullOrEmpty() && name.length > 1 && !viewModel.progressProPic.value!!)\n            viewModel.storeProfileData()\n    }\n\n\n    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n        super.onActivityResult(requestCode, resultCode, data)\n        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE)\n            onCropResult(data)\n        else\n            ImageUtils.cropImage(context, data, true)\n    }\n\n    private fun onCropResult(data: Intent?) {\n        try {\n            val imagePath: Uri? = ImageUtils.getCroppedImage(data)\n            imagePath?.let {\n                viewModel.uploadProfileImage(it)\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onRequestPermissionsResult(\n        requestCode: Int,\n        permissions: Array<out String>,\n        grantResults: IntArray) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n        ImageUtils.onImagePerResult(this, *grantResults)\n    }\n\n    override fun onDestroy() {\n        try {\n            progressView?.dismissIfShowing()\n            super.onDestroy()\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/profile/ProfileViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.profile\n\nimport android.content.Context\nimport android.net.Uri\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport com.google.android.gms.tasks.OnFailureListener\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.SetOptions\nimport com.gowtham.letschat.models.ModelDeviceDetails\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.*\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.json.Json\nimport java.util.*\nimport javax.inject.Inject\n\n@HiltViewModel\nclass ProfileViewModel @Inject\nconstructor(\n    @ApplicationContext private val context: Context,\n    private val preference: MPreference\n) : ViewModel() {\n\n    val progressProPic = MutableLiveData(false)\n\n    val profileUpdateState = MutableLiveData<LoadState>()\n\n    val checkUserNameState = MutableLiveData<LoadState>()\n\n    val name = MutableLiveData(\"\")\n\n    private val storageRef = UserUtils.getStorageRef(context)\n\n    private val docuRef = UserUtils.getDocumentRef(context)\n\n    val profilePicUrl = MutableLiveData(\"\")\n\n    private var about = \"\"\n\n    private var createdAt: Long = System.currentTimeMillis()\n\n    init {\n        LogMessage.v(\"ProfileViewModel\")\n        val userProfile = preference.getUserProfile()\n        userProfile?.let {\n            name.value = userProfile.userName\n            profilePicUrl.value = userProfile.image\n            about = userProfile.about\n            createdAt = userProfile.createdAt ?: System.currentTimeMillis()\n        }\n    }\n\n    fun uploadProfileImage(imagePath: Uri) {\n        try {\n            progressProPic.value = true\n            val child = storageRef.child(\"profile_picture_${System.currentTimeMillis()}.jpg\")\n            val task = child.putFile(imagePath)\n            task.addOnSuccessListener {\n                child.downloadUrl.addOnCompleteListener { taskResult ->\n                    progressProPic.value = false\n                    profilePicUrl.value = taskResult.result.toString()\n                }.addOnFailureListener {\n                    OnFailureListener { e ->\n                        progressProPic.value = false\n                        context.toast(e.message.toString())\n                    }\n                }\n            }.addOnProgressListener { taskSnapshot ->\n                val progress: Double =\n                    100.0 * taskSnapshot.bytesTransferred / taskSnapshot.totalByteCount\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun storeProfileData() {\n        try {\n            profileUpdateState.value = LoadState.OnLoading\n            val profile = UserProfile(\n                preference.getUid()!!,\n                createdAt,\n                System.currentTimeMillis(),\n                profilePicUrl.value!!,\n                name.value!!.toLowerCase(Locale.getDefault()),\n                about,\n                mobile = preference.getMobile(),\n                token = preference.getPushToken().toString(),\n                deviceDetails =\n                Json.decodeFromString<ModelDeviceDetails>(\n                    UserUtils.getDeviceInfo(context).toString()\n                )\n            )\n            docuRef.set(profile, SetOptions.merge()).addOnSuccessListener {\n                preference.saveProfile(profile)\n                profileUpdateState.value = LoadState.OnSuccess()\n            }.addOnFailureListener { e ->\n                context.toast(e.message.toString())\n                profileUpdateState.value = LoadState.OnFailure(e)\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onCleared() {\n        LogMessage.v(\"ProfileViewModel Cleared\")\n        super.onCleared()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/search/FSearch.kt",
    "content": "package com.gowtham.letschat.fragments.search\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.fragment.app.viewModels\nimport androidx.lifecycle.lifecycleScope\nimport androidx.navigation.fragment.findNavController\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.FSearchBinding\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.fragments.contacts.AdContact\nimport com.gowtham.letschat.fragments.single_chat_home.FSingleChatHomeDirections\nimport com.gowtham.letschat.ui.activities.SharedViewModel\nimport com.gowtham.letschat.utils.*\nimport dagger.hilt.android.AndroidEntryPoint\nimport kotlinx.coroutines.flow.collect\nimport kotlinx.coroutines.launch\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.json.Json\nimport timber.log.Timber\nimport java.util.*\nimport javax.inject.Inject\n\n\n@AndroidEntryPoint\nclass FSearch : Fragment(R.layout.f_search), ItemClickListener {\n\n    private lateinit var binding: FSearchBinding\n\n    private val sharedViewModel by activityViewModels<SharedViewModel>()\n\n    private val viewModel: FSearchViewModel by viewModels()\n\n    private val userList = arrayListOf<ChatUser>()\n\n    @Inject\n    lateinit var preference: MPreference\n\n    private val adapter: AdContact by lazy {\n        AdContact(requireContext(), userList)\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View {\n        binding = FSearchBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        binding.lifecycleOwner = viewLifecycleOwner\n        setDataInView()\n        subscribeObservers()\n    }\n\n    private fun setDataInView() {\n        AdContact.itemClickListener=this\n        binding.apply {\n            listUsers.setHasFixedSize(true)\n            listUsers.itemAnimator = null\n            listUsers.adapter = adapter\n        }\n    }\n\n\n    private fun subscribeObservers() {\n        sharedViewModel.getState().observe(viewLifecycleOwner, { state ->\n            if (state is ScreenState.IdleState) {\n                //show recent list\n                binding.txtNoUser.gone()\n                binding.viewEmpty.show()\n            } else {\n                if (sharedViewModel.lastQuery.value.isNullOrBlank()) {\n                    binding.viewEmpty.show()\n                    binding.txtNoUser.gone()\n                }\n            }\n        })\n\n        lifecycleScope.launch {\n            viewModel.getCachedList().collect { listData ->\n                Timber.v(\"List data $listData\")\n                //can be used to show recently searched user list\n            }\n        }\n\n        viewModel.getLoadState().observe(viewLifecycleOwner, { state ->\n            userList.clear()\n            adapter.notifyDataSetChanged()\n            when (state) {\n                is LoadState.OnLoading -> {\n                    binding.apply {\n                        txtNoUser.gone()\n                        viewEmpty.gone()\n                        progressBar.show()\n                    }\n                }\n                is LoadState.OnSuccess -> {\n                    binding.progressBar.gone()\n                    val list = state.data as List<ChatUser>\n                    if (list.isEmpty()) {\n                        binding.apply {\n                            txtNoUser.show()\n                            viewEmpty.gone()\n                        }\n                    } else {\n                        binding.apply {\n                            txtNoUser.gone()\n                            viewEmpty.gone()\n                        }\n                    }\n                    userList.addAll(list)\n                    adapter.notifyDataSetChanged()\n                }\n                is LoadState.OnFailure -> {\n                    binding.apply {\n                        progressBar.gone()\n                        txtNoUser.show()\n                    }\n                }\n            }\n        })\n\n        sharedViewModel.lastQuery.observe(viewLifecycleOwner, {\n            if (sharedViewModel.getState().value is ScreenState.SearchState) {\n                if (it.isBlank()) {\n                    binding.apply {\n                        viewEmpty.show()\n                        txtNoUser.gone()\n                        userList.clear()\n                        userList.addAll(emptyList())\n                        adapter.notifyDataSetChanged()\n                    }\n                } else\n                    viewModel.makeQuery(it.toLowerCase(Locale.getDefault()))\n            }\n        })\n    }\n\n    override fun onItemClicked(v: View, position: Int) {\n        val chatUser=userList[position]\n        preference.setCurrentUser(chatUser.id)\n        val action=FSearchDirections.actionFSearchToFSingleChat(chatUser)\n        findNavController().navigate(action)\n    }\n\n    override fun onDestroyView() {\n        super.onDestroyView()\n//        viewModel.clearCachedUser()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/search/FSearchViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.search\n\nimport android.os.Handler\nimport android.os.Looper\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport com.gowtham.letschat.utils.Constants\nimport com.gowtham.letschat.utils.DataStorePreference\nimport com.gowtham.letschat.utils.LoadState\nimport com.gowtham.letschat.utils.LogMessage\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport javax.inject.Inject\n\n\n@HiltViewModel\nclass FSearchViewModel @Inject constructor(repository: SearchRepo,\n                                               private val dataStorePreference: DataStorePreference): ViewModel() {\n\n    private val searchHandler = Handler(Looper.getMainLooper())\n\n    private var lastQuery=\"\"\n\n    private var currentQuery=MutableLiveData<String>()\n\n    private var _loadState=MutableLiveData<LoadState>()\n\n    val loadState get() = _loadState\n\n    init {\n        LogMessage.v(\"FSearchViewModel\")\n    }\n/*\n    val users= Transformations.switchMap(currentQuery){ query->\n        callMe(query)\n    }\n\n    private fun callMe(query: String?): LiveData<Any> {\n        return users\n    }*/\n\n    fun getCachedList() = dataStorePreference.getList()\n\n    fun makeQuery(query: String){\n        if(lastQuery==query)\n            return\n        lastQuery=query\n        removeTypingCallbacks()\n        searchHandler.postDelayed(queryThread, 400)\n    }\n\n    fun setLoadState(state: LoadState){\n        _loadState.value=state\n    }\n\n    fun getLoadState(): LiveData<LoadState>{\n        return _loadState\n    }\n\n    private val queryThread = Runnable {\n        currentQuery.value=lastQuery\n        repository.makeQuery(lastQuery,_loadState)\n        removeTypingCallbacks()\n    }\n\n\n\n    private fun removeTypingCallbacks() {\n        searchHandler.removeCallbacks(queryThread)\n    }\n\n    fun clearCachedUser() {\n        dataStorePreference.storeList(Constants.KEY_LAST_QUERIED_LIST, emptyList())\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/search/SearchRepo.kt",
    "content": "package com.gowtham.letschat.fragments.search\n\nimport androidx.lifecycle.MutableLiveData\nimport com.google.firebase.firestore.CollectionReference\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.Constants\nimport com.gowtham.letschat.utils.DataStorePreference\nimport com.gowtham.letschat.utils.LoadState\nimport com.gowtham.letschat.utils.MPreference\nimport timber.log.Timber\nimport javax.inject.Inject\nimport javax.inject.Singleton\n\n@Singleton\nclass SearchRepo  @Inject constructor(\n    private val usersCollection: CollectionReference,private val dataStore: DataStorePreference,\n    private val preference: MPreference){\n\n    fun makeQuery(query: String, loadState: MutableLiveData<LoadState>) {\n        try {\n            loadState.value=LoadState.OnLoading\n            usersCollection.whereEqualTo(\"userName\", query).get()\n                .addOnSuccessListener { documents ->\n                    val list= arrayListOf<ChatUser>()\n                    for (document in documents) {\n                        val profile = document.toObject(UserProfile::class.java)\n                        if (profile.uId==preference.getUid())\n                            continue\n                        val chatUser=ChatUser(profile.uId.toString(),profile.userName,profile,locallySaved = false,\n                            isSearchedUser = true)\n                        list.add(chatUser)\n                    }\n                    loadState.value=LoadState.OnSuccess(list)\n                    dataStore.storeList(Constants.KEY_LAST_QUERIED_LIST,list)\n                }\n                .addOnFailureListener { exception ->\n                    loadState.value=LoadState.OnFailure(exception)\n                    Timber.wtf(\"Error getting documents: ${exception.message}\")\n                }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/single_chat/AdChat.kt",
    "content": "package com.gowtham.letschat.fragments.single_chat\n\nimport android.content.Context\nimport android.media.MediaPlayer\nimport android.net.Uri\nimport android.os.CountDownTimer\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport android.widget.ImageView\nimport android.widget.ProgressBar\nimport androidx.core.content.ContextCompat\nimport androidx.recyclerview.widget.DiffUtil\nimport androidx.recyclerview.widget.ListAdapter\nimport androidx.recyclerview.widget.RecyclerView\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.*\nimport com.gowtham.letschat.db.data.Message\nimport com.gowtham.letschat.utils.*\nimport com.gowtham.letschat.utils.Events.EventAudioMsg\nimport com.gowtham.letschat.utils.Events.EventUpdateRecycleItem\nimport org.greenrobot.eventbus.EventBus\nimport timber.log.Timber\nimport java.io.IOException\nimport java.util.ArrayList\nimport kotlin.properties.Delegates\n\nclass AdChat(private val context: Context, private val msgClickListener: ItemClickListener) :\n    ListAdapter<Message, RecyclerView.ViewHolder>(DiffCallbackMessages()) {\n\n    private val preference = MPreference(context)\n\n    companion object {\n        private const val TYPE_TXT_SENT = 0\n        private const val TYPE_TXT_RECEIVED = 1\n        private const val TYPE_IMG_SENT = 2\n        private const val TYPE_IMG_RECEIVE = 3\n        private const val TYPE_STICKER_SENT = 4\n        private const val TYPE_STICKER_RECEIVE = 5\n        private const val TYPE_AUDIO_SENT = 6\n        private const val TYPE_AUDIO_RECEIVE = 7\n        private var lastPlayedHolder: RowAudioSentBinding?=null\n        private var lastReceivedPlayedHolder: RowAudioReceiveBinding?=null\n        private var lastPlayedAudioId : Long=-1\n        private var player = MediaPlayer()\n        lateinit var messageList: MutableList<Message>\n\n        fun stopPlaying() {\n            if(player.isPlaying) {\n                lastReceivedPlayedHolder?.progressBar?.abandon()\n                lastPlayedHolder?.progressBar?.abandon()\n                lastReceivedPlayedHolder?.imgPlay?.setImageResource(R.drawable.ic_action_play)\n                lastPlayedHolder?.imgPlay?.setImageResource(R.drawable.ic_action_play)\n                player.apply {\n                    stop()\n                    reset()\n                    EventBus.getDefault().post(EventAudioMsg(false))\n                }\n            }\n        }\n\n     fun isPlaying() = player.isPlaying\n    }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {\n        val layoutInflater = LayoutInflater.from(parent.context)\n        return when (viewType) {\n            TYPE_TXT_SENT -> {\n                val binding = RowSentMessageBinding.inflate(layoutInflater, parent, false)\n                TxtSentVHolder(binding)\n            }\n            TYPE_TXT_RECEIVED-> {\n                val binding = RowReceiveMessageBinding.inflate(layoutInflater, parent, false)\n                TxtReceiveVHolder(binding)\n            }\n            TYPE_IMG_SENT-> {\n                val binding = RowImageSentBinding.inflate(layoutInflater, parent, false)\n                ImageSentVHolder(binding)\n            }\n            TYPE_IMG_RECEIVE-> {\n                val binding = RowImageReceiveBinding.inflate(layoutInflater, parent, false)\n                ImageReceiveVHolder(binding)\n            }\n            TYPE_STICKER_SENT-> {\n                val binding = RowStickerSentBinding.inflate(layoutInflater, parent, false)\n                StickerSentVHolder(binding)\n            }\n            TYPE_STICKER_RECEIVE-> {\n                val binding = RowStickerReceiveBinding.inflate(layoutInflater, parent, false)\n                StickerReceiveVHolder(binding)\n            }\n            TYPE_AUDIO_SENT-> {\n                val binding = RowAudioSentBinding.inflate(layoutInflater, parent, false)\n                AudioSentVHolder(binding)\n            }\n            else-> {\n                val binding = RowAudioReceiveBinding.inflate(layoutInflater, parent, false)\n                AudioReceiveVHolder(binding)\n            }\n        }\n    }\n\n    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {\n        when(holder){\n            is TxtSentVHolder ->\n                holder.bind(context,getItem(position))\n            is TxtReceiveVHolder ->\n                holder.bind(context,getItem(position))\n            is ImageSentVHolder ->\n                holder.bind(getItem(position),msgClickListener)\n            is ImageReceiveVHolder ->\n                holder.bind(getItem(position),msgClickListener)\n            is StickerSentVHolder ->\n                holder.bind(getItem(position))\n            is StickerReceiveVHolder ->\n                holder.bind(getItem(position))\n            is AudioSentVHolder ->\n                holder.bind(context,getItem(position))\n            is AudioReceiveVHolder ->\n                holder.bind(context,getItem(position))\n        }\n    }\n\n    override fun getItemViewType(position: Int): Int {\n        val message = getItem(position)\n        val fromMe=message.from == preference.getUid()\n        if (fromMe && message.type == \"text\")\n            return TYPE_TXT_SENT\n        else if (!fromMe && message.type == \"text\")\n            return TYPE_TXT_RECEIVED\n        else if (fromMe && message.type == \"image\" && message.imageMessage?.imageType==\"image\")\n            return TYPE_IMG_SENT\n        else if (!fromMe && message.type == \"image\" && message.imageMessage?.imageType==\"image\")\n            return TYPE_IMG_RECEIVE\n        else if (fromMe && message.type == \"image\" && (message.imageMessage?.imageType==\"sticker\"\n                    || message.imageMessage?.imageType==\"gif\"))\n            return TYPE_STICKER_SENT\n        else if (!fromMe && message.type == \"image\"  && (message.imageMessage?.imageType==\"sticker\"\n                    || message.imageMessage?.imageType==\"gif\"))\n            return TYPE_STICKER_RECEIVE\n        else if (fromMe && message.type == \"audio\")\n            return TYPE_AUDIO_SENT\n        else if (!fromMe && message.type == \"audio\")\n            return TYPE_AUDIO_RECEIVE\n        return super.getItemViewType(position)\n    }\n\n    class TxtSentVHolder(val binding: RowSentMessageBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(context: Context,item: Message) {\n            binding.message = item\n            binding.messageList= messageList as ArrayList<Message>\n            if (bindingAdapterPosition>0) {\n                val message = messageList[bindingAdapterPosition - 1]\n                if (message.from == item.from)\n                    binding.txtMsg.setBackgroundResource(R.drawable.shape_send_msg_corned)\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n    class TxtReceiveVHolder(val binding: RowReceiveMessageBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(context:Context,item: Message) {\n            binding.message = item\n            if (bindingAdapterPosition>0) {\n                val message = messageList[bindingAdapterPosition - 1]\n                if (message.from == item.from)\n                    binding.txtMsg.setBackgroundResource(R.drawable.shape_receive_msg_corned)\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n    class ImageSentVHolder(val binding: RowImageSentBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: Message, msgClickListener: ItemClickListener) {\n            binding.message = item\n            binding.imageMsg.setOnClickListener {\n                msgClickListener.onItemClicked(it,bindingAdapterPosition)\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n    class ImageReceiveVHolder(val binding: RowImageReceiveBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: Message,msgClickListener: ItemClickListener) {\n            binding.message = item\n            binding.imageMsg.setOnClickListener {\n                msgClickListener.onItemClicked(it,bindingAdapterPosition)\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n    class StickerSentVHolder(val binding: RowStickerSentBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: Message) {\n            binding.message = item\n            binding.executePendingBindings()\n        }\n    }\n\n    class StickerReceiveVHolder(val binding: RowStickerReceiveBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: Message) {\n            binding.message = item\n            binding.executePendingBindings()\n        }\n    }\n\n    class AudioReceiveVHolder(val binding: RowAudioReceiveBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(context: Context,item: Message) {\n            binding.message = item\n            binding.progressBar.setStoriesCountDebug(1,0)\n            binding.progressBar.setAllStoryDuration(item.audioMessage?.duration!!.toLong()*1000)\n            binding.imgPlay.setOnClickListener {\n                startPlaying(\n                    context,\n                    item,\n                    binding)\n            }\n            binding.executePendingBindings()\n        }\n\n        private fun startPlaying(\n            context: Context,\n            item: Message,\n            currentHolder: RowAudioReceiveBinding) {\n            if (player.isPlaying){\n                stopPlaying()\n                lastReceivedPlayedHolder?.progressBar?.abandon()\n                lastReceivedPlayedHolder?.imgPlay?.setImageResource(R.drawable.ic_action_play)\n                lastPlayedHolder?.imgPlay?.setImageResource(R.drawable.ic_action_play)\n                lastPlayedHolder?.progressBar?.abandon()\n                if (lastPlayedAudioId==item.createdAt)\n                    return\n\n            }\n            player= MediaPlayer()\n            lastReceivedPlayedHolder =currentHolder\n            lastPlayedAudioId=item.createdAt\n            currentHolder.progressBuffer.show()\n            currentHolder.imgPlay.gone()\n            player.apply {\n                try {\n                    setDataSource(context, Uri.parse(item.audioMessage?.uri))\n                    prepareAsync()\n                    setOnPreparedListener {\n                        Timber.v(\"Started..\")\n                        start()\n                        currentHolder.progressBuffer.gone()\n                        currentHolder.imgPlay.setImageResource(R.drawable.ic_action_stop)\n                        currentHolder.imgPlay.show()\n                        currentHolder.progressBar.startStories()\n                        EventBus.getDefault().post(EventAudioMsg(true))\n                    }\n                    setOnCompletionListener {\n                        currentHolder.progressBar.abandon()\n                        currentHolder.imgPlay.setImageResource(R.drawable.ic_action_play)\n                        EventBus.getDefault().post(EventAudioMsg(false))\n                    }\n                } catch (e: IOException) {\n                    println(\"ChatFragment.startPlaying:prepare failed\")\n                }\n            }\n        }\n    }\n\n    class AudioSentVHolder(val binding: RowAudioSentBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(\n            context: Context,\n            item: Message,) {\n            binding.message = item\n            binding.progressBar.setStoriesCountDebug(1,0)\n            binding.progressBar.setAllStoryDuration(item.audioMessage?.duration!!.toLong()*1000)\n            binding.imgPlay.setOnClickListener {\n               startPlaying(\n                    context,\n                    item,\n                    binding)\n            }\n            binding.executePendingBindings()\n        }\n\n        private fun startPlaying(\n            context: Context,\n            item: Message,\n            currentHolder: RowAudioSentBinding) {\n            if (player.isPlaying){\n                stopPlaying()\n                if (lastPlayedAudioId==item.createdAt)\n                    return\n            }\n            player= MediaPlayer()\n            lastPlayedHolder =currentHolder\n            lastPlayedAudioId=item.createdAt\n            currentHolder.progressBuffer.show()\n            currentHolder.imgPlay.gone()\n            player.apply {\n                try {\n                    setDataSource(context, Uri.parse(item.audioMessage?.uri))\n                    prepareAsync()\n                    setOnPreparedListener {\n                        Timber.v(\"Started..\")\n                        start()\n                        currentHolder.progressBuffer.gone()\n                        currentHolder.imgPlay.setImageResource(R.drawable.ic_action_stop)\n                        currentHolder.imgPlay.show()\n                        currentHolder.progressBar.startStories()\n                        EventBus.getDefault().post(EventAudioMsg(true))\n                    }\n                    setOnCompletionListener {\n                        currentHolder.progressBar.abandon()\n                        currentHolder.imgPlay.setImageResource(R.drawable.ic_action_play)\n                        EventBus.getDefault().post(EventAudioMsg(false))\n                    }\n                } catch (e: IOException) {\n                    println(\"ChatFragment.startPlaying:prepare failed\")\n                }\n            }\n        }\n    }\n}\n\nclass DiffCallbackMessages : DiffUtil.ItemCallback<Message>() {\n    override fun areItemsTheSame(oldItem: Message, newItem: Message): Boolean {\n        return oldItem.createdAt == newItem.createdAt\n    }\n\n    override fun areContentsTheSame(oldItem: Message, newItem: Message): Boolean {\n        return oldItem == newItem\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/single_chat/FSingleChat.kt",
    "content": "package com.gowtham.letschat.fragments.single_chat\n\nimport android.Manifest\nimport android.animation.Animator\nimport android.app.Activity\nimport android.content.Intent\nimport android.content.pm.ActivityInfo\nimport android.media.MediaRecorder\nimport android.net.Uri\nimport android.os.Bundle\nimport android.os.Handler\nimport android.os.Looper\nimport android.provider.ContactsContract\nimport android.text.Editable\nimport android.text.TextWatcher\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.core.view.inputmethod.InputContentInfoCompat\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.viewModels\nimport androidx.lifecycle.lifecycleScope\nimport androidx.navigation.fragment.findNavController\nimport androidx.navigation.fragment.navArgs\nimport androidx.recyclerview.widget.LinearLayoutManager\nimport com.canhub.cropper.CropImage\nimport com.gowtham.letschat.databinding.FSingleChatBinding\nimport com.gowtham.letschat.db.data.*\nimport com.gowtham.letschat.fragments.FAttachment\nimport com.gowtham.letschat.models.MyImage\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.*\nimport com.gowtham.letschat.utils.Events.EventAudioMsg\nimport com.gowtham.letschat.utils.Utils.edtValue\nimport com.gowtham.letschat.views.CustomEditText\nimport com.stfalcon.imageviewer.StfalconImageViewer\nimport dagger.hilt.android.AndroidEntryPoint\nimport kotlinx.coroutines.flow.collect\nimport kotlinx.coroutines.launch\nimport org.greenrobot.eventbus.EventBus\nimport org.greenrobot.eventbus.Subscribe\nimport org.greenrobot.eventbus.ThreadMode\nimport timber.log.Timber\nimport java.io.IOException\nimport java.util.*\nimport javax.inject.Inject\nimport kotlin.collections.ArrayList\n\n\n@AndroidEntryPoint\nclass FSingleChat : Fragment(), ItemClickListener,CustomEditText.KeyBoardInputCallbackListener {\n\n    private lateinit var binding: FSingleChatBinding\n\n    @Inject\n    lateinit var preference: MPreference\n\n    private lateinit var chatUser: ChatUser\n\n    private lateinit var fromUser: UserProfile\n\n    private lateinit var toUser: UserProfile\n\n    private var messageList = mutableListOf<Message>()\n\n    private val viewModel: SingleChatViewModel by viewModels()\n\n    private lateinit var localUserId: String\n\n    private var recorder: MediaRecorder? = null\n\n    val args by navArgs<FSingleChatArgs>()\n\n    private lateinit var manager: LinearLayoutManager\n\n    private lateinit var chatUserId: String\n\n    var isRecording = false //whether is recoding now or not\n\n    private var recordStart = 0L\n\n    private var recordDuration = 0L\n\n    private val REQ_AUDIO_PERMISSION=29\n\n    private var lastAudioFile=\"\"\n\n    private var msgPostponed=false\n\n    private val adChat: AdChat by lazy {\n        AdChat(requireContext(), this)\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?): View {\n        binding = FSingleChatBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        binding.viewmodel=viewModel\n        chatUser= args.chatUserProfile!!\n        viewModel.setUnReadCountZero(chatUser)\n        setListeners()\n        if(!chatUser.locallySaved && !chatUser.isSearchedUser)\n            binding.viewChatHeader.imageAddContact.show()\n        viewModel.canScroll(false)\n        binding.viewChatBtm.edtMsg.setKeyBoardInputCallbackListener(this)\n        setDataInView()\n        subscribeObservers()\n\n        lifecycleScope.launch {\n            viewModel.getMessagesByChatUserId(chatUserId).collect { mMessagesList ->\n                if(mMessagesList.isEmpty())\n                    return@collect\n                messageList = mMessagesList as MutableList<Message>\n                if(AdChat.isPlaying()){\n                    msgPostponed=true\n                    return@collect\n                }\n                AdChat.messageList = messageList\n                adChat.submitList(mMessagesList)\n                //scroll to last items in recycler (recent messages)\n                if (messageList.isNotEmpty()) {\n                    if (viewModel.getCanScroll())  //scroll only if new message arrived\n                        binding.listMessage.smoothScrollToPos(messageList.lastIndex)\n                    else\n                        viewModel.canScroll(true)\n                }\n            }\n        }\n    }\n\n    private fun setListeners() {\n        binding.viewChatBtm.lottieSend.setOnClickListener {\n            sendMessage()\n        }\n        binding.viewChatHeader.viewBack.setOnClickListener {\n            findNavController().popBackStack()\n        }\n        binding.viewChatBtm.imgRecord.setOnClickListener {\n            AdChat.stopPlaying()\n            if(Utils.checkPermission(this, Manifest.permission.RECORD_AUDIO,reqCode = REQ_AUDIO_PERMISSION))\n                startRecording()\n        }\n        binding.lottieVoice.setOnClickListener {\n            if (isRecording){\n                stopRecording()\n                val duration=(recordDuration/1000).toInt()\n                if (duration<=1) {\n                    requireContext().toast(\"Nothing is recorded!\")\n                    return@setOnClickListener\n                }\n                val msg=createMessage().apply {\n                    type=\"audio\"\n                    audioMessage= AudioMessage(lastAudioFile,duration)\n                    chatUsers= ArrayList()\n                }\n                viewModel.uploadToCloud(msg,lastAudioFile)\n            }\n        }\n        binding.viewChatHeader.imageAddContact.setOnClickListener {\n            if (Utils.askContactPermission(this))\n                openSaveIntent()\n        }\n        binding.viewChatBtm.imageAdd.setOnClickListener {\n            val fragment=FAttachment.newInstance(Bundle())\n            fragment.show(childFragmentManager,\"\")\n        }\n    }\n\n    private fun setDataInView() {\n        try {\n            fromUser = preference.getUserProfile()!!\n            localUserId=fromUser.uId!!\n            manager= LinearLayoutManager(context)\n            binding.listMessage.apply {\n                manager.stackFromEnd=true\n                layoutManager=manager\n                setHasFixedSize(true)\n                isNestedScrollingEnabled=false\n                itemAnimator = null\n            }\n            binding.listMessage.adapter = adChat\n            adChat.addRestorePolicy()\n            viewModel.setChatUser(chatUser)\n            toUser=chatUser.user\n            chatUserId=toUser.uId!!\n            binding.chatUser = chatUser\n            binding.viewChatBtm.edtMsg.addTextChangedListener(msgTxtChangeListener)\n            binding.viewChatBtm.lottieSend.addAnimatorListener(object : Animator.AnimatorListener {\n                override fun onAnimationStart(p0: Animator?) {\n\n\n                }\n\n                override fun onAnimationEnd(animation: Animator?, isReverse: Boolean) {\n                    super.onAnimationEnd(animation, isReverse)\n                }\n\n                override fun onAnimationEnd(p0: Animator?) {\n                    if (edtValue(binding.viewChatBtm.edtMsg).isEmpty()) {\n                        binding.viewChatBtm.imgRecord.show()\n                        binding.viewChatBtm.lottieSend.gone()\n                    }\n                }\n\n                override fun onAnimationCancel(p0: Animator?) {\n                }\n\n                override fun onAnimationRepeat(p0: Animator?) {\n\n\n                }\n            })\n\n            binding.lottieVoice.addAnimatorListener(object : Animator.AnimatorListener{\n                override fun onAnimationStart(p0: Animator?) {\n\n\n                }\n\n                override fun onAnimationEnd(animation: Animator?, isReverse: Boolean) {\n                    super.onAnimationEnd(animation, isReverse)\n                }\n\n                override fun onAnimationEnd(p0: Animator?) {\n                    binding.viewChatBtm.imgRecord.show()\n                    binding.lottieVoice.gone()\n                }\n\n                override fun onAnimationCancel(p0: Animator?) {\n                }\n\n                override fun onAnimationRepeat(p0: Animator?) {\n\n\n                }\n            })\n\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun subscribeObservers() {\n        //pass messages list for recycler to show\n        viewModel.chatUserOnlineStatus.observe(viewLifecycleOwner, {\n            Utils.setOnlineStatus(binding.viewChatHeader.txtLastSeen, it, localUserId)\n        })\n    }\n\n    private fun openSaveIntent() {\n        val contactIntent = Intent(ContactsContract.Intents.Insert.ACTION)\n        contactIntent.type = ContactsContract.RawContacts.CONTENT_TYPE\n        contactIntent\n            .putExtra(ContactsContract.Intents.Insert.NAME, chatUser.user.userName)\n            .putExtra(ContactsContract.Intents.Insert.PHONE, chatUser.user.mobile?.number.toString())\n        startActivityForResult(contactIntent, REQ_ADD_CONTACT)\n    }\n\n    private fun sendMessage() {\n        val msg = edtValue(binding.viewChatBtm.edtMsg)\n        if (msg.isEmpty())\n            return\n        binding.viewChatBtm.lottieSend.playAnimation()\n        val message = createMessage().apply {\n            textMessage=TextMessage(msg)\n            chatUsers= ArrayList()\n        }\n        viewModel.sendMessage(message)\n        binding.viewChatBtm.edtMsg.setText(\"\")\n    }\n\n    private fun createMessage(): Message {\n        return Message(\n            System.currentTimeMillis(),\n            from = preference.getUid().toString(),\n            chatUserId=chatUserId,\n            to = toUser.uId!!, senderName = fromUser.userName,\n            senderImage = fromUser.image\n        )\n    }\n\n    private val msgTxtChangeListener=object : TextWatcher{\n        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {\n        }\n\n        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {\n            viewModel.sendTyping(binding.viewChatBtm.edtMsg.trim())\n            if(binding.viewChatBtm.lottieSend.isAnimating)\n                return\n            if(s.isNullOrBlank()) {\n                binding.viewChatBtm.imgRecord.show()\n                binding.viewChatBtm.lottieSend.hide()\n            }\n            else{\n                binding.viewChatBtm.lottieSend.show()\n                binding.viewChatBtm.imgRecord.hide()\n            }\n        }\n\n        override fun afterTextChanged(s: Editable?) {\n        }\n    }\n\n    override fun onItemClicked(v: View, position: Int) {\n        val message=messageList.get(position)\n        if (message.type==\"image\" && message.imageMessage!!.imageType==\"image\") {\n            binding.fullSizeImageView.show()\n            StfalconImageViewer.Builder(\n                context,\n                listOf(MyImage(messageList.get(position).imageMessage?.uri!!))\n            ) { imageView, myImage ->\n                ImageUtils.loadGalleryImage(myImage.url, imageView)\n            }\n                .withDismissListener { binding.fullSizeImageView.visibility = View.GONE }\n                .show()\n        }\n    }\n\n    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n        super.onActivityResult(requestCode, resultCode, data)\n        if (requestCode == REQ_ADD_CONTACT){\n            if (resultCode == Activity.RESULT_OK) {\n                binding.viewChatHeader.imageAddContact.gone()\n                val contacts=UserUtils.fetchContacts(requireContext())\n                val savedName=contacts.firstOrNull { it.mobile==chatUser.user.mobile?.number }\n                savedName?.let {\n                    binding.viewChatHeader.txtLocalName.text=it.name\n                    chatUser.localName=it.name\n                    chatUser.locallySaved=true\n                    viewModel.insertUser(chatUser)\n                }\n            }else if (resultCode == Activity.RESULT_CANCELED) {\n                Timber.v(\"Cancelled Added Contact\")\n            }\n        }else if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE)\n            onCropResult(data)\n        else\n            ImageUtils.cropImage(requireActivity(), data, true)\n    }\n\n    private fun onCropResult(data: Intent?) {\n        try {\n            val imagePath: Uri? = ImageUtils.getCroppedImage(data)\n            if (imagePath!=null){\n                val message=createMessage().apply {\n                    type=\"image\"\n                    imageMessage=ImageMessage(imagePath.toString())\n                    chatUsers= ArrayList()\n                }\n                viewModel.uploadToCloud(message,imagePath.toString())\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onRequestPermissionsResult(\n        requestCode: Int,\n        permissions: Array<out String>,grantResults: IntArray) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n        if(requestCode==REQ_AUDIO_PERMISSION){\n            if (Utils.isPermissionOk(*grantResults))\n                startRecording()\n            else\n                requireActivity().toast(\"Audio permission is needed!\")\n        }else if (Utils.isPermissionOk(*grantResults))\n            openSaveIntent()\n    }\n\n    override fun onCommitContent(inputContentInfo: InputContentInfoCompat?,\n        flags: Int,\n        opts: Bundle?) {\n        val imageMsg=createMessage()\n        val image=ImageMessage(\"${inputContentInfo?.contentUri}\")\n        image.imageType=if(image.uri.toString().endsWith(\".png\")) \"sticker\" else \"gif\"\n        imageMsg.apply {\n            type=\"image\"\n            imageMessage=image\n            chatUsers= ArrayList()\n        }\n        viewModel.uploadToCloud(imageMsg,image.toString())\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    fun onAttachmentItemClicked(event: BottomSheetEvent){\n        when(event.position){\n            0->{\n                ImageUtils.takePhoto(requireActivity())\n            }\n            1->{\n                ImageUtils.chooseGallery(requireActivity())\n            }\n            2->{\n                //create intent for gallery video\n            }\n            3->{\n                //create intent for camera video\n            }\n        }\n    }\n\n    private fun startRecording() {\n        binding.lottieVoice.show()\n        binding.lottieVoice.playAnimation()\n        binding.viewChatBtm.edtMsg.apply {\n            isEnabled=false\n            hint=\"Recording...\"\n        }\n        onAudioEvent(EventAudioMsg(true))\n        //name of the file where record will be stored\n        lastAudioFile=\n            \"${requireActivity().externalCacheDir?.absolutePath}/audiorecord${System.currentTimeMillis()}.mp3\"\n        recorder = MediaRecorder().apply {\n            setAudioSource(MediaRecorder.AudioSource.MIC)\n            setOutputFormat(MediaRecorder.OutputFormat.DEFAULT)\n            setOutputFile(lastAudioFile)\n            setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)\n            try {\n                prepare()\n            } catch (e: IOException) {\n                println(\"ChatFragment.startRecording${e.message}\")\n            }\n            start()\n            isRecording=true\n            recordStart = Date().time\n        }\n        Handler(Looper.getMainLooper()).postDelayed({\n            binding.lottieVoice.pauseAnimation()\n        },800)\n    }\n\n    private fun stopRecording() {\n        onAudioEvent(EventAudioMsg(false))\n        binding.viewChatBtm.edtMsg.apply {\n            isEnabled=true\n            hint=\"Type Something...\"\n        }\n        Handler(Looper.getMainLooper()).postDelayed({\n            binding.lottieVoice.resumeAnimation()\n        },200)\n        recorder?.apply {\n            stop()\n            release()\n            recorder = null\n        }\n        isRecording=false\n        recordDuration = Date().time - recordStart\n    }\n\n\n    override fun onResume() {\n        viewModel.setSeenAllMessage()\n        preference.setCurrentUser(chatUserId)\n        viewModel.sendCachedTxtMesssages()\n        Utils.removeNotification(requireContext())\n        super.onResume()\n    }\n\n    override fun onDestroy() {\n        Utils.closeKeyBoard(requireActivity())\n        super.onDestroy()\n    }\n\n    override fun onStop() {\n        super.onStop()\n        preference.clearCurrentUser()\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        EventBus.getDefault().register(this)\n    }\n\n    override fun onDestroyView() {\n        super.onDestroyView()\n        stopRecording()\n        AdChat.stopPlaying()\n        EventBus.getDefault().unregister(this)\n    }\n\n    @Subscribe\n    fun onAudioEvent(audioEvent: EventAudioMsg){\n        if (audioEvent.isPlaying){\n            //lock current orientation\n            val currentOrientation=requireActivity().resources.configuration.orientation\n            requireActivity().requestedOrientation = currentOrientation\n        }else {\n            requireActivity().requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED\n            if (msgPostponed){\n                //refresh list\n                AdChat.messageList = messageList\n                adChat.submitList(messageList)\n                msgPostponed=false\n            }\n        }\n    }\n\n    companion object{\n        private const val REQ_ADD_CONTACT=22\n    }\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/single_chat/SingleChatViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.single_chat\n\nimport android.content.Context\nimport android.os.Handler\nimport android.os.Looper\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.viewModelScope\nimport androidx.work.Data\nimport androidx.work.OneTimeWorkRequestBuilder\nimport androidx.work.WorkManager\nimport androidx.work.WorkRequest\nimport com.google.firebase.database.*\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.google.gson.reflect.TypeToken\nimport com.gowtham.letschat.TYPE_NEW_MESSAGE\nimport com.gowtham.letschat.core.MessageSender\nimport com.gowtham.letschat.core.MessageStatusUpdater\nimport com.gowtham.letschat.core.OnMessageResponse\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Message\nimport com.gowtham.letschat.di.MessageCollection\nimport com.gowtham.letschat.models.UserStatus\nimport com.gowtham.letschat.services.UploadWorker\nimport com.gowtham.letschat.utils.Constants.CHAT_USER_DATA\nimport com.gowtham.letschat.utils.Constants.MESSAGE_DATA\nimport com.gowtham.letschat.utils.Constants.MESSAGE_FILE_URI\nimport com.gowtham.letschat.utils.LogMessage\nimport com.gowtham.letschat.utils.MPreference\nimport com.gowtham.letschat.utils.UserUtils\nimport com.gowtham.letschat.utils.Utils\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\nimport javax.inject.Inject\nimport kotlin.reflect.full.memberProperties\n\n@HiltViewModel\nclass SingleChatViewModel @Inject\nconstructor(\n    @ApplicationContext private val context: Context,\n    private val dbRepository: DbRepository,\n    @MessageCollection\n    private val messageCollection: CollectionReference,\n    private val preference: MPreference,\n    private val firebaseFireStore: FirebaseFirestore,\n    ) : ViewModel() {\n\n    private val database = FirebaseDatabase.getInstance()\n\n    private val toUser = preference.getOnlineUser()\n\n    private val fromUser = preference.getUid()\n\n    val message = MutableLiveData<String>()\n\n    private val statusRef: DatabaseReference = database.getReference(\"Users/$toUser\")\n\n    private var statusListener: ValueEventListener? = null\n\n    val chatUserOnlineStatus = MutableLiveData(UserStatus())\n\n    private val messageStatusUpdater=MessageStatusUpdater(messageCollection,firebaseFireStore)\n\n    private lateinit var chatUser: ChatUser\n\n    private val typingHandler = Handler(Looper.getMainLooper())\n\n    private var isTyping = false\n\n    private var canScroll = false\n\n    private var chatUserOnline = false\n\n    init {\n        statusListener = statusRef.addValueEventListener(object : ValueEventListener {\n            override fun onDataChange(snapshot: DataSnapshot) {\n                val userStatus = snapshot.getValue(UserStatus::class.java)\n                chatUserOnlineStatus.value = userStatus\n                chatUserOnline = userStatus?.status == \"online\"\n            }\n\n            override fun onCancelled(error: DatabaseError) {\n            }\n        })\n    }\n\n    fun setChatUser(chatUser: ChatUser) {\n        if (!this::chatUser.isInitialized) {\n            this.chatUser = chatUser\n            setSeenAllMessage()\n        }\n    }\n\n    fun canScroll(can: Boolean) {\n        canScroll = can\n    }\n\n    fun getCanScroll() = canScroll\n\n    fun getMessagesByChatUserId(chatUserId: String) =\n        dbRepository.getMessagesByChatUserId(chatUserId)\n\n    fun sendMessage(message: Message) {\n        Handler(Looper.getMainLooper()).postDelayed({\n            val messageSender = MessageSender(\n                messageCollection,\n                dbRepository,\n                chatUser,\n                messageListener\n            )\n            messageSender.checkAndSend(fromUser!!, toUser, message)\n        }, 400)\n        dbRepository.insertMessage(message)\n        removeTypingCallbacks()\n    }\n\n    fun sendCachedTxtMesssages() {\n        //Send msg that is not sent succesfully in last time\n        CoroutineScope(Dispatchers.IO).launch {\n            updateCacheMessges(dbRepository.getChatsOfFriend(toUser))\n        }\n    }\n\n    private suspend fun updateCacheMessges(listOfMessage: List<Message>) {\n        withContext(Dispatchers.Main) {\n            val nonSendMsgs =\n                listOfMessage.filter { it.from == fromUser && it.status == 0 && it.type == \"text\" }\n            LogMessage.v(\"nonSendMsgs Size ${nonSendMsgs.size}\")\n            if (nonSendMsgs.isNotEmpty()) {\n                for (cachedMsg in nonSendMsgs) {\n                    val messageSender = MessageSender(\n                        messageCollection,\n                        dbRepository,\n                        chatUser,\n                        messageListener\n                    )\n                    messageSender.checkAndSend(fromUser!!, toUser, cachedMsg)\n                }\n            }\n        }\n    }\n\n    private val messageListener = object : OnMessageResponse {\n        override fun onSuccess(message: Message) {\n            LogMessage.v(\"messageListener OnSuccess ${message.textMessage?.text}\")\n            dbRepository.insertMessage(message)\n            if (chatUser.user.token.isNotEmpty())\n                UserUtils.sendPush(\n                    context,\n                    TYPE_NEW_MESSAGE,\n                    Json.encodeToString(message),\n                    chatUser.user.token,\n                    message.to\n                )\n        }\n\n        override fun onFailed(message: Message) {\n            LogMessage.v(\"messageListener onFailed ${message.createdAt}\")\n            dbRepository.insertMessage(message)\n        }\n    }\n\n    override fun onCleared() {\n        LogMessage.v(\"SingleChat cleared\")\n        statusListener?.let {\n            statusRef.removeEventListener(it)\n        }\n        super.onCleared()\n    }\n\n    fun setSeenAllMessage() {\n        LogMessage.v(\"SetSeenAllMessage called\")\n        if (this::chatUser.isInitialized) {\n            chatUser.unRead = 0\n            dbRepository.insertUser(chatUser)\n            viewModelScope.launch(Dispatchers.IO) {\n                val messageList = dbRepository.getChatsOfFriend(chatUser.id)\n                withContext(Dispatchers.Main){\n                    if(messageList.isNotEmpty())\n                      updateToSeen(messageList)\n                }\n            }\n        }\n    }\n\n    private fun updateToSeen(messageList: List<Message>) {\n        chatUser.documentId?.let {\n            messageStatusUpdater.updateToSeen(toUser, it, messageList)\n        }\n    }\n\n    fun sendTyping(edtValue: String) {\n        if (edtValue.isEmpty()) {\n            if (isTyping)\n                UserUtils.sendTypingStatus(database, false, fromUser!!, toUser)\n            isTyping = false\n        } else if (!isTyping) {\n            UserUtils.sendTypingStatus(database, true, fromUser!!, toUser)\n            isTyping = true\n            removeTypingCallbacks()\n            typingHandler.postDelayed(typingThread, 4000)\n        }\n    }\n\n    private val typingThread = Runnable {\n        isTyping = false\n        UserUtils.sendTypingStatus(database, false, fromUser!!, toUser)\n        removeTypingCallbacks()\n    }\n\n    private fun removeTypingCallbacks() {\n        typingHandler.removeCallbacks(typingThread)\n    }\n\n    fun setUnReadCountZero(chatUser: ChatUser) {\n        UserUtils.setUnReadCountZero(dbRepository, chatUser)\n    }\n\n    fun insertUser(chatUser: ChatUser) {\n        dbRepository.insertUser(chatUser)\n    }\n\n    fun uploadToCloud(message: Message, fileUri: String) {\n        try {\n            dbRepository.insertMessage(message)\n            removeTypingCallbacks()\n            val messageData = Json.encodeToString(message)\n            val chatUserData = Json.encodeToString(chatUser)\n            val data = Data.Builder()\n                .putString(MESSAGE_FILE_URI, fileUri)\n                .putString(MESSAGE_DATA, messageData)\n                .putString(CHAT_USER_DATA, chatUserData)\n                .build()\n            val uploadWorkRequest: WorkRequest =\n                OneTimeWorkRequestBuilder<UploadWorker>()\n                    .setInputData(data)\n                    .build()\n            WorkManager.getInstance(context).enqueue(uploadWorkRequest)\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n}\n\n\n//convert a data class to a map\nfun <T> T.serializeToMap(): Map<String, Any> {\n    return convert()\n}\n\n//convert a map to a data class\ninline fun <reified T> Map<String, Any>.toDataClass(): T {\n    return convert()\n}\n\n//convert an object of type I to type O\ninline fun <I, reified O> I.convert(): O {\n    val json = Utils.getGSONObj().toJson(this)\n    return Utils.getGSONObj().fromJson(json, object : TypeToken<O>() {}.type)\n}\n\ninline fun <reified T : Any> T.asMap(): Map<String, Any?> {\n    val props = T::class.memberProperties.associateBy { it.name }\n    return props.keys.associateWith { props[it]?.get(this) }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/single_chat_home/AdSingleChatHome.kt",
    "content": "package com.gowtham.letschat.fragments.single_chat_home\n\nimport android.content.Context\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\nimport androidx.recyclerview.widget.DiffUtil\nimport androidx.recyclerview.widget.ListAdapter\nimport androidx.recyclerview.widget.RecyclerView\nimport com.gowtham.letschat.databinding.RowChatBinding\nimport com.gowtham.letschat.databinding.RowReceiveMessageBinding\nimport com.gowtham.letschat.databinding.RowSentMessageBinding\nimport com.gowtham.letschat.db.data.ChatUserWithMessages\nimport com.gowtham.letschat.utils.ItemClickListener\nimport com.gowtham.letschat.utils.MPreference\nimport java.util.*\n\nclass AdSingleChatHome(private val context: Context) :\n    ListAdapter<ChatUserWithMessages, RecyclerView.ViewHolder>(DiffCallbackChats()) {\n\n    private val preference = MPreference(context)\n\n    companion object {\n        lateinit var allChatList: MutableList<ChatUserWithMessages>\n        lateinit var itemClickListener: ItemClickListener\n    }\n\n    fun filter(query: String) {\n        try {\n            val list= mutableListOf<ChatUserWithMessages>()\n            if (query.isEmpty())\n                list.addAll(allChatList)\n            else {\n                for (contact in allChatList) {\n                    if (contact.user.localName.toLowerCase(Locale.getDefault())\n                            .contains(query.toLowerCase(Locale.getDefault()))) {\n                        list.add(contact)\n                    }\n                }\n            }\n            submitList(null)\n            submitList(list)\n        } catch (e: Exception) {\n            e.stackTrace\n        }\n    }\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {\n        val layoutInflater = LayoutInflater.from(parent.context)\n        val binding = RowChatBinding.inflate(layoutInflater, parent, false)\n        return ViewHolder(binding)\n    }\n\n    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {\n        val viewHolder=holder as ViewHolder\n        viewHolder.bind(getItem(position))\n    }\n\n    class ViewHolder(val binding: RowChatBinding) :\n        RecyclerView.ViewHolder(binding.root) {\n        fun bind(item: ChatUserWithMessages) {\n            binding.chatUser = item\n            binding.viewRoot.setOnClickListener { v ->\n                itemClickListener.onItemClicked(v,bindingAdapterPosition)\n            }\n            binding.executePendingBindings()\n        }\n    }\n\n}\n\nclass DiffCallbackChats : DiffUtil.ItemCallback<ChatUserWithMessages>() {\n    override fun areItemsTheSame(oldItem: ChatUserWithMessages, newItem: ChatUserWithMessages): Boolean {\n        return oldItem.user.id == oldItem.user.id\n    }\n\n    override fun areContentsTheSame(oldItem: ChatUserWithMessages, newItem: ChatUserWithMessages): Boolean {\n        return oldItem.messages == newItem.messages && oldItem.user==newItem.user\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/single_chat_home/FSingleChatHome.kt",
    "content": "package com.gowtham.letschat.fragments.single_chat_home\n\nimport android.app.Activity\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.activityViewModels\nimport androidx.fragment.app.viewModels\nimport androidx.lifecycle.ViewModelProvider\nimport androidx.lifecycle.lifecycleScope\nimport androidx.navigation.fragment.findNavController\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.core.ChatHandler\nimport com.gowtham.letschat.core.ChatUserProfileListener\nimport com.gowtham.letschat.core.GroupChatHandler\nimport com.gowtham.letschat.databinding.FSingleChatHomeBinding\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.data.ChatUserWithMessages\nimport com.gowtham.letschat.db.daos.MessageDao\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.ui.activities.SharedViewModel\nimport com.gowtham.letschat.utils.*\nimport dagger.hilt.android.AndroidEntryPoint\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.flow.collect\nimport kotlinx.coroutines.flow.filter\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport timber.log.Timber\nimport javax.inject.Inject\n\n\n@AndroidEntryPoint\nclass FSingleChatHome : Fragment(),ItemClickListener {\n\n    @Inject\n    lateinit var preference: MPreference\n\n    @Inject\n    lateinit var chatUserDao: ChatUserDao\n\n    @Inject\n    lateinit var messageDao: MessageDao\n\n    private lateinit var activity: Activity\n\n    private lateinit var profile: UserProfile\n\n    private var chatList = mutableListOf<ChatUserWithMessages>()\n\n    private val sharedViewModel by activityViewModels<SharedViewModel>()\n\n    private lateinit var binding: FSingleChatHomeBinding\n\n    private val viewModel: SingleChatHomeViewModel by viewModels()\n\n    private val adChat: AdSingleChatHome by lazy {\n        AdSingleChatHome(requireContext())\n    }\n\n    @Inject\n    lateinit var chatHandler: ChatHandler\n\n    @Inject\n    lateinit var groupChatHandler: GroupChatHandler\n\n    @Inject\n    lateinit var chatUsersListener: ChatUserProfileListener\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?): View {\n        binding = FSingleChatHomeBinding.inflate(layoutInflater, container, false)\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n\n        activity = requireActivity()\n        binding.lifecycleOwner = viewLifecycleOwner\n        chatHandler.initHandler()\n        groupChatHandler.initHandler()\n        chatUsersListener.initListener()\n        profile = preference.getUserProfile()!!\n        setDataInView()\n        subScribeObservers()\n    }\n\n    private fun subScribeObservers() {\n        lifecycleScope.launch {\n            viewModel.getChatUsers().collect { list ->\n                updateList(list)\n            }\n        }\n\n        sharedViewModel.getState().observe(viewLifecycleOwner,{state->\n            if (state is ScreenState.IdleState){\n                CoroutineScope(Dispatchers.IO).launch {\n                    updateList(viewModel.getChatUsersAsList())\n                }\n            }\n        })\n        sharedViewModel.lastQuery.observe(viewLifecycleOwner,{\n            if (sharedViewModel.getState().value is ScreenState.SearchState)\n                adChat.filter(it)\n        })\n    }\n\n    private suspend fun updateList(list: List<ChatUserWithMessages>) {\n        withContext(Dispatchers.Main){\n            val filteredList = list.filter { it.messages.isNotEmpty() }\n            if (filteredList.isNotEmpty()) {\n                binding.imageEmpty.gone()\n                chatList = filteredList as MutableList<ChatUserWithMessages>\n                //sort by recent message\n                chatList = filteredList.sortedByDescending { it.messages.last().createdAt }\n                    .toMutableList()\n                AdSingleChatHome.allChatList=chatList\n                adChat.submitList(chatList)\n                if(sharedViewModel.getState().value is ScreenState.SearchState)\n                    adChat.filter(sharedViewModel.lastQuery.value.toString())\n            }else\n                binding.imageEmpty.show()\n        }\n    }\n\n    private fun setDataInView() {\n        binding.listChat.itemAnimator = null\n        binding.listChat.adapter = adChat\n        AdSingleChatHome.itemClickListener = this\n    }\n\n    override fun onRequestPermissionsResult(\n        requestCode: Int,\n        permissions: Array<out String>,\n        grantResults: IntArray) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n        if (Utils.isPermissionOk(*grantResults)){\n            if (findNavController().isValidDestination(R.id.FSingleChatHome))\n                findNavController().navigate(R.id.action_FSingleChatHome_to_FContacts)\n        }\n        else\n            activity.toast(\"Permission is needed!\")\n    }\n\n    override fun onItemClicked(v: View, position: Int) {\n        sharedViewModel.setState(ScreenState.IdleState)\n        val chatUser=adChat.currentList[position]\n        preference.setCurrentUser(chatUser.user.id)\n        val action= FSingleChatHomeDirections.actionFSingleChatToFChat(chatUser.user)\n        findNavController().navigate(action)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/fragments/single_chat_home/SingleChatHomeViewModel.kt",
    "content": "package com.gowtham.letschat.fragments.single_chat_home\n\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport com.gowtham.letschat.db.DefaultDbRepo\nimport com.gowtham.letschat.db.data.ChatUser\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport javax.inject.Inject\n\n@HiltViewModel\nclass SingleChatHomeViewModel  @Inject\nconstructor(private val dbRepo: DefaultDbRepo): ViewModel() {\n\n    val message= MutableLiveData<String>()\n\n    fun getChatUsers() = dbRepo.getChatUserWithMessages()\n\n    fun getChatUsersAsList() = dbRepo.getChatUserWithMessagesList()\n\n    fun insertChatUser(chatUser: ChatUser) = dbRepo.insertUser(chatUser)\n\n    fun insertMultipleChatUser(users : List<ChatUser>) = dbRepo.insertMultipleUser(users)\n\n    fun getAllChatUser() = dbRepo.getAllChatUser()\n\n    fun deleteUser(userId: String) = dbRepo.deleteUserById(userId)\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/models/Contact.kt",
    "content": "package com.gowtham.letschat.models\n\n\ndata class Contact(var name: String,var mobile: String)"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/models/Country.kt",
    "content": "package com.gowtham.letschat.models\n\nimport android.os.Parcel\nimport android.os.Parcelable\nimport kotlinx.parcelize.Parceler\nimport kotlinx.parcelize.Parcelize\nimport kotlinx.serialization.Serializable\n\n@Serializable\n@Parcelize\ndata class Country(\n    val code: String, val name: String, val noCode: String,\n    val money: String\n) : Parcelable\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/models/ModelDeviceDetails.kt",
    "content": "package com.gowtham.letschat.models\n\nimport android.os.Parcel\nimport android.os.Parcelable\nimport kotlinx.parcelize.Parceler\nimport kotlinx.parcelize.Parcelize\nimport kotlinx.serialization.Serializable\n\n@Serializable\n@Parcelize\ndata class ModelDeviceDetails(var device_id: String?=null,var device_model: String?=null,\n                          var device_brand: String?=null,var device_country: String?=null,\n                         var device_os_v: String?=null,var app_version: String?=null,\n                              var package_name: String?=null,var device_type: String?=null): Parcelable"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/models/ModelMobile.kt",
    "content": "package com.gowtham.letschat.models\n\nimport android.os.Parcelable\nimport kotlinx.parcelize.Parceler\nimport kotlinx.parcelize.Parcelize\nimport kotlinx.serialization.Serializable\n\n@Serializable\n@Parcelize\ndata class ModelMobile(\n    var country: String=\"\", var number: String=\"\"): Parcelable\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/models/MyImage.kt",
    "content": "package com.gowtham.letschat.models\n\ndata class MyImage(val url: String)"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/models/PushMsg.kt",
    "content": "package com.gowtham.letschat.models\n\nimport com.google.firebase.firestore.IgnoreExtraProperties\nimport kotlinx.serialization.Serializable\n\n@Serializable\n@IgnoreExtraProperties\ndata class PushMsg(var type: String?=null,var to: String?=null,var title: String?=null,\n                   var message: String?=null,var message_body: String?=null) {\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/models/UserProfile.kt",
    "content": "package com.gowtham.letschat.models\n\nimport android.os.Parcelable\nimport com.google.firebase.firestore.IgnoreExtraProperties\nimport com.google.firebase.firestore.PropertyName\nimport kotlinx.parcelize.Parceler\nimport kotlinx.parcelize.Parcelize\nimport kotlinx.serialization.Serializable\n\n@Serializable\n@IgnoreExtraProperties\n@Parcelize\ndata class UserProfile(var uId: String?=null,var createdAt: Long?=null,\n                       var updatedAt: Long?=null,\n                       var image: String=\"\", var userName: String=\"\",\n                       var about: String=\"\",\n                       var token :String=\"\",\n                       var mobile: ModelMobile?=null,\n                       @get:PropertyName(\"device_details\")\n                       @set:PropertyName(\"device_details\")\n                       var deviceDetails: ModelDeviceDetails?=null) : Parcelable"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/models/UserStatus.kt",
    "content": "package com.gowtham.letschat.models\n\ndata class UserStatus (val status: String=\"offline\",val last_seen: Long=0,\n                       val typing_status: String=\"non_typing\",val chatuser: String?=null) {\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/services/GroupUploadWorker.kt",
    "content": "package com.gowtham.letschat.services\n\nimport android.content.Context\nimport android.net.Uri\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.Worker\nimport androidx.work.WorkerParameters\nimport com.google.firebase.firestore.CollectionReference\nimport com.gowtham.letschat.TYPE_NEW_GROUP_MESSAGE\nimport com.gowtham.letschat.core.GroupMsgSender\nimport com.gowtham.letschat.core.OnGrpMessageResponse\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.db.data.GroupMessage\nimport com.gowtham.letschat.di.GroupCollection\nimport com.gowtham.letschat.utils.Constants\nimport com.gowtham.letschat.utils.UserUtils\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\nimport timber.log.Timber\nimport java.io.FileInputStream\nimport java.util.concurrent.CountDownLatch\n\n@HiltWorker\nclass GroupUploadWorker @AssistedInject constructor(\n    @Assisted appContext: Context,\n    @Assisted workerParams: WorkerParameters,\n    @GroupCollection\n    val groupCollection: CollectionReference,\n    private val dbRepository: DbRepository):\n    Worker(appContext, workerParams) {\n\n    private val params=workerParams\n\n    override fun doWork(): Result {\n        val stringData=params.inputData.getString(Constants.MESSAGE_DATA) ?: \"\"\n        val message= Json.decodeFromString<GroupMessage>(stringData)\n\n        val url=params.inputData.getString(Constants.MESSAGE_FILE_URI)!!\n        val sourceName=getSourceName(message,url)\n        val storageRef=UserUtils.getStorageRef(applicationContext)\n        val child = storageRef.child(\n            \"group/${message.to}/$sourceName\")\n       val task = if(url.contains(\".mp3\")) {\n            val stream = FileInputStream(url)  //audio message\n            child.putStream(stream)\n        }else\n            child.putFile(Uri.parse(message.imageMessage?.uri))\n\n        val countDownLatch = CountDownLatch(1)\n        val result= arrayOf(Result.failure())\n        task.addOnSuccessListener {\n            child.downloadUrl.addOnCompleteListener { taskResult ->\n                Timber.v(\"TaskResult ${taskResult.result.toString()}\")\n                val imgUrl=taskResult.result.toString()\n                sendMessage(message,imgUrl,result,countDownLatch)\n            }.addOnFailureListener { e ->\n                Timber.v(\"TaskResult Failed ${e.message}\")\n                result[0]= Result.failure()\n                message.status[0]=4\n                dbRepository.insertMessage(message)\n                countDownLatch.countDown()\n            }\n        }\n        countDownLatch.await()\n        return result[0]\n    }\n\n    private fun sendMessage(\n        message: GroupMessage,imgUrl: String,\n        result: Array<Result>,\n        countDownLatch: CountDownLatch) {\n        val group=Json.decodeFromString<Group>(params.inputData.getString(Constants.GROUP_DATA)!!)\n        setUrl(message,imgUrl)\n        val messageSender = GroupMsgSender(groupCollection)\n        messageSender.sendMessage(message, group, object : OnGrpMessageResponse{\n            override fun onSuccess(message: GroupMessage) {\n                sendPushToMembers(group,message)\n                result[0]= Result.success()\n                countDownLatch.countDown()\n            }\n\n            override fun onFailed(message: GroupMessage) {\n                result[0]= Result.failure()\n                dbRepository.insertMessage(message)\n                countDownLatch.countDown()\n            }\n        })\n    }\n\n    private fun setUrl(message: GroupMessage, imgUrl: String) {\n        if (message.type==\"audio\")\n            message.audioMessage?.uri=imgUrl\n        else\n            message.imageMessage?.uri=imgUrl\n    }\n\n    private fun sendPushToMembers(group: Group, message: GroupMessage) {\n        val users = group.members?.filter { it.user.token.isNotEmpty() }?.map {\n            it.user.token\n            it\n        }\n        users?.forEach {\n            UserUtils.sendPush(\n                applicationContext, TYPE_NEW_GROUP_MESSAGE,\n                Json.encodeToString(message), it.user.token, it.id\n            )\n        }\n    }\n\n    private fun getSourceName(message: GroupMessage, url: String): String {\n        val createdAt=message.createdAt.toString()\n        val num=createdAt.substring(createdAt.length - 5)\n        val extension=url.substring(url.lastIndexOf('.'))\n        return \"${message.type}_$num$extension\"\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/services/UploadWorker.kt",
    "content": "package com.gowtham.letschat.services\n\nimport android.content.Context\nimport android.net.Uri\nimport androidx.hilt.work.HiltWorker\nimport androidx.work.Worker\nimport androidx.work.WorkerParameters\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.storage.UploadTask\nimport com.gowtham.letschat.TYPE_NEW_MESSAGE\nimport com.gowtham.letschat.core.MessageSender\nimport com.gowtham.letschat.core.OnMessageResponse\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Message\nimport com.gowtham.letschat.di.MessageCollection\nimport com.gowtham.letschat.utils.Constants\nimport com.gowtham.letschat.utils.UserUtils\nimport dagger.assisted.Assisted\nimport dagger.assisted.AssistedInject\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\nimport timber.log.Timber\nimport java.io.FileInputStream\nimport java.util.concurrent.CountDownLatch\n\n@HiltWorker\nclass UploadWorker @AssistedInject constructor(\n    @Assisted appContext: Context,\n    @Assisted workerParams: WorkerParameters,\n    @MessageCollection\n    val msgCollection: CollectionReference,\n    val dbRepository: DbRepository):\n    Worker(appContext, workerParams) {\n\n    private val params=workerParams\n\n    override fun doWork(): Result {\n        val stringData=params.inputData.getString(Constants.MESSAGE_DATA) ?: \"\"\n        val message= Json.decodeFromString<Message>(stringData)\n\n        val url=params.inputData.getString(Constants.MESSAGE_FILE_URI)!!\n        val sourceName=getSourceName(message,url)\n        val storageRef=UserUtils.getStorageRef(applicationContext)\n\n        val child = storageRef.child(\n            \"chats/${message.to}/$sourceName\")\n        val task: UploadTask\n        task = if(url.contains(\".mp3\")) {\n            val stream = FileInputStream(url)  //audio message\n            child.putStream(stream)\n        }else\n            child.putFile(Uri.parse(message.imageMessage?.uri))\n\n        val countDownLatch = CountDownLatch(1)\n        val result= arrayOf(Result.failure())\n        task.addOnSuccessListener {\n            child.downloadUrl.addOnCompleteListener { taskResult ->\n                Timber.v(\"TaskResult ${taskResult.result.toString()}\")\n                val downloadUrl=taskResult.result.toString()\n                sendMessage(message,downloadUrl,result,countDownLatch)\n            }.addOnFailureListener { e ->\n                Timber.v(\"TaskResult Failed ${e.message}\")\n                result[0]= Result.failure()\n                message.status=4\n                dbRepository.insertMessage(message)\n                countDownLatch.countDown()\n            }\n        }\n        countDownLatch.await()\n        return result[0]\n    }\n\n    private fun getSourceName(message: Message, url: String): String {\n        val createdAt=message.createdAt.toString()\n        val num=createdAt.substring(createdAt.length - 5)\n        val extension=url.substring(url.lastIndexOf('.'))\n        return \"${message.type}_$num$extension\"\n    }\n\n    private fun sendMessage(message: Message,downloadUrl: String,result: Array<Result>,\n        countDownLatch: CountDownLatch) {\n        val chatUser=Json.decodeFromString<ChatUser>(params.inputData.getString(Constants.CHAT_USER_DATA)!!)\n        setUrl(message,downloadUrl)\n        val messageSender = MessageSender(\n            msgCollection,\n            dbRepository,\n            chatUser,object : OnMessageResponse{\n                override fun onSuccess(message: Message) {\n                    UserUtils.sendPush(applicationContext, TYPE_NEW_MESSAGE, Json.encodeToString(message)\n                        , chatUser.user.token,message.to)\n                    result[0]= Result.success()\n                    countDownLatch.countDown()\n                }\n\n                override fun onFailed(message: Message) {\n                    result[0]= Result.failure()\n                    dbRepository.insertMessage(message)\n                    countDownLatch.countDown()\n                }\n            }\n        )\n        messageSender.checkAndSend(message.from, message.to, message)\n    }\n\n    private fun setUrl(message: Message, imgUrl: String) {\n        if (message.type==\"audio\")\n            message.audioMessage?.uri=imgUrl\n        else\n            message.imageMessage?.uri=imgUrl\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/ui/activities/ActBase.kt",
    "content": "package com.gowtham.letschat.ui.activities\n\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport android.content.IntentFilter\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport com.google.firebase.database.*\nimport com.google.firebase.ktx.Firebase\nimport com.gowtham.letschat.MApplication\nimport com.gowtham.letschat.db.ChatUserDatabase\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.daos.GroupMessageDao\nimport com.gowtham.letschat.db.daos.MessageDao\nimport com.gowtham.letschat.models.UserStatus\nimport com.gowtham.letschat.utils.*\nimport dagger.hilt.android.AndroidEntryPoint\nimport org.greenrobot.eventbus.EventBus\nimport org.greenrobot.eventbus.Subscribe\nimport org.greenrobot.eventbus.ThreadMode\nimport timber.log.Timber\nimport javax.inject.Inject\n\n@AndroidEntryPoint\nopen class ActBase : AppCompatActivity() {\n\n    private val database = FirebaseDatabase.getInstance()\n\n    @Inject\n    lateinit var preference: MPreference\n\n    @Inject\n    lateinit var chatUserDao: ChatUserDao\n\n    @Inject\n    lateinit var msgDao: MessageDao\n\n    @Inject\n    lateinit var groupDao: GroupDao\n\n    @Inject\n    lateinit var messageDao: GroupMessageDao\n\n    @Inject\n    lateinit var db: ChatUserDatabase\n\n    private var connectedRef: DatabaseReference?=null\n\n    private val newLogInReceiver: BroadcastReceiver = object : BroadcastReceiver() {\n        override fun onReceive(context: Context, intent: Intent) {\n            if (Constants.ACTION_LOGGED_IN_ANOTHER_DEVICE == intent.action)\n                Utils.showLoggedInAlert(this@ActBase, preference,db )\n        }\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        EventBus.getDefault().register(this)\n        MApplication.isAppRunning=true\n        registerReceiver(newLogInReceiver, IntentFilter(Constants.ACTION_LOGGED_IN_ANOTHER_DEVICE))\n        if (!preference.getUid().isNullOrEmpty())\n           updateStatus()\n    }\n\n    override fun onResume() {\n        MApplication.isAppRunning=true\n        super.onResume()\n    }\n\n    private fun updateStatus(){\n        try {\n            val lastOnlineRef = database.getReference(\"/Users/${preference.getUid()}/last_seen\")\n            val status = database.getReference(\"/Users/${preference.getUid()}/status\")\n            connectedRef = database.getReference(\".info/connected\")\n            connectedRef?.addValueEventListener(object : ValueEventListener {\n                override fun onDataChange(snapshot: DataSnapshot) {\n                    val connected: Boolean = (snapshot.value ?: false) as Boolean\n                    if (connected) {\n                        LogMessage.v(\"Online status updated##\")\n                        status.setValue(\"online\")\n                        lastOnlineRef.onDisconnect().setValue(ServerValue.TIMESTAMP)\n                        status.onDisconnect().setValue(\"offline\")\n                    }\n                }\n\n                override fun onCancelled(error: DatabaseError) {\n                    LogMessage.v(\"Listener was cancelled at .info/connected ${error.message}\")\n                }\n            })\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    fun onProfileUpdated(event: UserStatus) {  //will be triggered only when initial profile update completed\n      if (event.status==\"online\")\n          updateStatus()\n        else{\n          val status = database.getReference(\"/Users/${preference.getUid()}/status\")\n          status.setValue(\"offline\")\n        }\n    }\n\n    override fun onDestroy() {\n        MApplication.isAppRunning=false\n        EventBus.getDefault().unregister(this)\n        Timber.v(\"onDestroy\")\n        unregisterReceiver(newLogInReceiver)\n        super.onDestroy()\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/ui/activities/ActSplash.kt",
    "content": "package com.gowtham.letschat.ui.activities\n\nimport android.content.Intent\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.lifecycle.Observer\nimport androidx.lifecycle.ViewModelProvider\nimport com.google.firebase.firestore.CollectionReference\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.MPreference\nimport com.gowtham.letschat.utils.UserUtils\nimport dagger.hilt.android.AndroidEntryPoint\nimport javax.inject.Inject\n\n@AndroidEntryPoint\nclass ActSplash : AppCompatActivity() {\n\n    @Inject\n    lateinit var preference: MPreference\n\n    @Inject\n    lateinit var userCollection: CollectionReference\n\n    private lateinit var sharedViewModel: SharedViewModel\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.act_splash)\n\n        sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)\n        UserUtils.updatePushToken(this, userCollection,false)\n        sharedViewModel.onFromSplash()\n        sharedViewModel.openMainAct.observe(this, {\n            startActivity(Intent(this, MainActivity::class.java))\n            finish()\n        })\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/ui/activities/MainActivity.kt",
    "content": "package com.gowtham.letschat.ui.activities\n\nimport android.content.Intent\nimport android.os.Bundle\nimport android.os.Handler\nimport android.os.Looper\nimport android.view.Menu\nimport android.view.MenuInflater\nimport android.view.MenuItem\nimport androidx.activity.viewModels\nimport androidx.appcompat.widget.SearchView\nimport androidx.databinding.DataBindingUtil\nimport androidx.fragment.app.Fragment\nimport androidx.fragment.app.FragmentManager\nimport androidx.lifecycle.lifecycleScope\nimport androidx.navigation.NavController\nimport androidx.navigation.NavOptions\nimport androidx.navigation.Navigation\nimport androidx.navigation.fragment.FragmentNavigator\nimport androidx.navigation.fragment.NavHostFragment\nimport androidx.navigation.ui.AppBarConfiguration\nimport androidx.navigation.ui.setupWithNavController\nimport com.google.android.material.bottomnavigation.BottomNavigationView\nimport com.gowtham.letschat.BuildConfig\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.databinding.ActivityMainBinding\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.Group\nimport com.gowtham.letschat.fragments.single_chat_home.FSingleChatHomeDirections\nimport com.gowtham.letschat.utils.*\nimport kotlinx.coroutines.flow.collect\nimport kotlinx.coroutines.flow.conflate\nimport kotlinx.coroutines.launch\nimport timber.log.Timber\n\n\nclass MainActivity : ActBase() {\n\n    private lateinit var binding: ActivityMainBinding\n\n    private lateinit var navController: NavController\n\n    private val sharedViewModel: SharedViewModel by viewModels()\n\n    private lateinit var searchView: SearchView\n\n    private lateinit var searchItem: MenuItem\n\n    private var stopped=false\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)\n        setSupportActionBar(binding.toolbar)\n    }\n\n    override fun onPostCreate(savedInstanceState: Bundle?) {\n        super.onPostCreate(savedInstanceState)\n        binding.fab.setOnClickListener {\n            if (searchItem.isActionViewExpanded)\n               searchItem.collapseActionView()\n            if (Utils.askContactPermission(returnFragment()!!)) {\n                if (navController.isValidDestination(R.id.FSingleChatHome))\n                    navController.navigate(R.id.action_FSingleChatHome_to_FContacts)\n                else if (navController.isValidDestination(R.id.FGroupChatHome))\n                    navController.navigate(R.id.action_FGroupChatHome_to_FAddGroupMembers)\n            }\n        }\n        setDataInView()\n        subscribeObservers()\n\n    }\n\n    private fun subscribeObservers() {\n        val badge = binding.bottomNav.getOrCreateBadge(R.id.nav_chat)\n        badge.isVisible = false\n        val groupChatBadge = binding.bottomNav.getOrCreateBadge(R.id.nav_group)\n        groupChatBadge.isVisible = false\n        lifecycleScope.launch {\n            groupDao.getGroupWithMessages().conflate().collect { list ->\n                val count = list.filter { it.group.unRead != 0 }\n                groupChatBadge.isVisible = count.isNotEmpty() //hide if 0\n                groupChatBadge.number = count.size\n            }\n        }\n\n        lifecycleScope.launch {\n            chatUserDao.getChatUserWithMessages().conflate().collect { list ->\n                val count = list.filter { it.user.unRead != 0 && it.messages.isNotEmpty() }\n                badge.isVisible = count.isNotEmpty() //hide if 0\n                badge.number = count.size\n            }\n        }\n\n    }\n\n    private fun setDataInView() {\n        try {\n            navController = Navigation.findNavController(this, R.id.nav_host_fragment)\n            navController.addOnDestinationChangedListener { _, destination, _ ->\n                onDestinationChanged(destination.id)\n            }\n            val appBarConfiguration = AppBarConfiguration(setOf(R.id.FSingleChatHome))\n            binding.toolbar.setupWithNavController(navController, appBarConfiguration)\n            binding.bottomNav.setOnNavigationItemSelectedListener(onBottomNavigationListener)\n\n            val isNewMessage = intent.action == Constants.ACTION_NEW_MESSAGE\n            val isNewGroupMessage = intent.action == Constants.ACTION_GROUP_NEW_MESSAGE\n            val userData = intent.getParcelableExtra<ChatUser>(Constants.CHAT_USER_DATA)\n            val groupData = intent.getParcelableExtra<Group>(Constants.GROUP_DATA)\n\n            if (preference.isLoggedIn() && navController.isValidDestination(R.id.FLogIn)) {\n                if (preference.getUserProfile() == null)\n                    navController.navigate(R.id.action_FLogIn_to_FProfile)\n                else\n                    navController.navigate(R.id.action_FLogIn_to_FSingleChatHome)\n            }\n\n            //single chat message notification clicked\n            if (isNewMessage && navController.isValidDestination(R.id.FSingleChatHome)) {\n                preference.setCurrentUser(userData!!.id)\n                val action = FSingleChatHomeDirections.actionFSingleChatToFChat(userData)\n                navController.navigate(action)\n            } else if (isNewGroupMessage && navController.isValidDestination(R.id.FSingleChatHome)) {\n                preference.setCurrentGroup(groupData!!.id)\n                val action = FSingleChatHomeDirections.actionFSingleChatHomeToFGroupChat(groupData)\n                navController.navigate(action)\n            }\n\n            if (!preference.isSameDevice())\n                Utils.showLoggedInAlert(this, preference, db)\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun onDestinationChanged(currentDestination: Int) {\n        try {\n            when(currentDestination) {\n                R.id.FSingleChatHome -> {\n                    binding.bottomNav.selectedItemId = R.id.nav_chat\n                    showView()\n                }\n                R.id.FGroupChatHome -> {\n                    binding.bottomNav.selectedItemId = R.id.nav_group\n                    showView()\n                }\n                R.id.FSearch -> {\n                    binding.bottomNav.selectedItemId = R.id.nav_search\n                    showView()\n                    binding.fab.hide()\n                }\n                R.id.FMyProfile -> {\n                    binding.bottomNav.selectedItemId = R.id.nav_profile\n                    showView()\n                    binding.fab.hide()\n                }\n                else -> {\n                    binding.bottomNav.gone()\n                    binding.fab.gone()\n                    binding.toolbar.gone()\n                }\n            }\n            Handler(Looper.getMainLooper()).postDelayed({ //delay time for searchview\n                if (this::searchItem.isInitialized) {\n                    if (currentDestination == R.id.FMyProfile) {\n                        searchItem.collapseActionView()\n                        searchItem.isVisible = false\n                    }else\n                        searchItem.isVisible = true\n                }\n            }, 500)\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    override fun onCreateOptionsMenu(menu: Menu): Boolean {\n        val inflater: MenuInflater = menuInflater\n        inflater.inflate(R.menu.menu_search, menu)\n        initToolbarItem()\n        return true\n    }\n\n    private fun initToolbarItem() {\n        searchItem = binding.toolbar.menu.findItem(R.id.action_search)\n        searchView = searchItem.actionView as SearchView\n        searchView.apply {\n            maxWidth = Integer.MAX_VALUE\n            queryHint = getString(R.string.txt_search)\n        }\n\n        searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {\n            override fun onMenuItemActionExpand(item: MenuItem?): Boolean {\n                sharedViewModel.setState(ScreenState.SearchState)\n                return true\n            }\n\n            override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {\n                  if (!stopped)\n                    sharedViewModel.setState(ScreenState.IdleState)\n                return true\n            }\n        })\n\n        sharedViewModel.getState().observe(this, { state ->\n            if (state is ScreenState.SearchState && searchView.isIconified) {\n                searchItem.expandActionView()\n                searchView.setQuery(sharedViewModel.getLastQuery().value, false)\n            }\n        })\n\n        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {\n            override fun onQueryTextSubmit(query: String?): Boolean {\n                return true\n            }\n\n            override fun onQueryTextChange(newText: String?): Boolean {\n                sharedViewModel.setLastQuery(newText.toString())\n                return true\n            }\n        })\n\n    }\n\n    private fun showView() {\n        binding.bottomNav.show()\n        binding.fab.show()\n        binding.toolbar.show()\n    }\n\n    private fun isNotSameDestination(destination: Int): Boolean {\n        return destination != Navigation.findNavController(this, R.id.nav_host_fragment)\n            .currentDestination!!.id\n    }\n\n    private val onBottomNavigationListener =\n        BottomNavigationView.OnNavigationItemSelectedListener { item ->\n            when (item.itemId) {\n                R.id.nav_chat -> {\n                    val navOptions =\n                        NavOptions.Builder().setPopUpTo(R.id.nav_host_fragment, true).build()\n                    if (isNotSameDestination(R.id.FSingleChatHome)) {\n                        searchItem.collapseActionView()\n                        Navigation.findNavController(this, R.id.nav_host_fragment)\n                            .navigate(R.id.FSingleChatHome, null, navOptions)\n                    }\n                    true\n                }\n                R.id.nav_group -> {\n                    if (isNotSameDestination(R.id.FGroupChatHome)) {\n                        searchItem.collapseActionView()\n                        Navigation.findNavController(this, R.id.nav_host_fragment)\n                            .navigate(R.id.FGroupChatHome)\n                    }\n                    true\n                }\n                R.id.nav_search -> {\n                    if (isNotSameDestination(R.id.FSearch)) {\n                        searchItem.collapseActionView()\n                        Navigation.findNavController(this, R.id.nav_host_fragment)\n                            .navigate(R.id.FSearch)\n                    }\n                    true\n                }\n                else -> {\n                    if (isNotSameDestination(R.id.FMyProfile)) {\n                        searchItem.collapseActionView()\n                        Navigation.findNavController(this, R.id.nav_host_fragment)\n                            .navigate(R.id.FMyProfile)\n                    }\n                    true\n                }\n            }\n\n        }\n\n\n    fun returnFragment(): Fragment? {\n        val navHostFragment: Fragment? =\n            supportFragmentManager.findFragmentById(R.id.nav_host_fragment)\n        return navHostFragment?.childFragmentManager?.fragments?.get(0)\n    }\n\n    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n        super.onActivityResult(requestCode, resultCode, data)\n        val navHostFragment = supportFragmentManager.fragments.first() as? NavHostFragment\n        if (navHostFragment != null) {\n            val childFragments = navHostFragment.childFragmentManager.fragments\n            childFragments.forEach { fragment ->\n                fragment.onActivityResult(requestCode, resultCode, data)\n            }\n        }\n    }\n\n    override fun onRequestPermissionsResult(\n        requestCode: Int,\n        permissions: Array<out String>,\n        grantResults: IntArray) {\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n        /* val navHostFragment = supportFragmentManager.fragments.first() as? NavHostFragment\n         if (navHostFragment != null) {\n             val childFragments = navHostFragment.childFragmentManager.fragments\n             childFragments.forEach { fragment ->\n                 fragment.onRequestPermissionsResult(requestCode, permissions, grantResults)\n             }\n         }*/\n    }\n\n    override fun onBackPressed() {\n        if (navController.isValidDestination(R.id.FSingleChatHome))\n            finish()\n        else if (navController.isValidDestination(R.id.FMyProfile) ||\n            navController.isValidDestination(R.id.FGroupChatHome) ||\n            navController.isValidDestination(R.id.FSearch)) {\n            val navOptions =\n                NavOptions.Builder().setPopUpTo(R.id.nav_host_fragment, true).build()\n            Navigation.findNavController(this, R.id.nav_host_fragment)\n                .navigate(R.id.FSingleChatHome, null, navOptions)\n        } else\n            super.onBackPressed()\n    }\n\n    override fun onStop() {\n        super.onStop()\n        Timber.v(\"onSdd\")\n        stopped=true\n    }\n\n    override fun onResume() {\n        super.onResume()\n        Timber.v(\"onResime\")\n        stopped=false\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/ui/activities/SharedViewModel.kt",
    "content": "package com.gowtham.letschat.ui.activities\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport androidx.lifecycle.ViewModel\nimport com.gowtham.letschat.db.daos.ChatUserDao\nimport com.gowtham.letschat.models.Country\nimport com.gowtham.letschat.utils.MPreference\nimport com.gowtham.letschat.utils.ScreenState\nimport com.gowtham.letschat.utils.printMeD\nimport dagger.hilt.android.lifecycle.HiltViewModel\nimport dagger.hilt.android.scopes.ActivityScoped\nimport timber.log.Timber\nimport java.util.*\nimport javax.inject.Inject\nimport javax.inject.Singleton\nimport kotlin.concurrent.schedule\n\n@HiltViewModel\nclass SharedViewModel @Inject constructor() : ViewModel() {\n\n    val country = MutableLiveData<Country>()\n\n    val openMainAct = MutableLiveData<Boolean>()\n\n    private val _state = MutableLiveData<ScreenState>(ScreenState.IdleState)\n\n    val lastQuery = MutableLiveData<String>()\n\n    val listOfQuery = arrayListOf(\"\")\n\n    private var timer: TimerTask? = null\n\n    init {\n        \"Init SharedViewModel\".printMeD()\n    }\n\n    fun getLastQuery(): LiveData<String> {\n        return lastQuery\n    }\n\n    fun setLastQuery(query: String) {\n        Timber.v(\"Last Query $query\")\n        listOfQuery.add(query)\n        lastQuery.value = query\n    }\n\n    fun setState(state: ScreenState) {\n        Timber.v(\"State $state\")\n        _state.value = state\n    }\n\n    fun getState(): LiveData<ScreenState> {\n        return _state\n    }\n\n    fun setCountry(country: Country) {\n        this.country.value = country\n    }\n\n\n    fun onFromSplash() {\n        if (timer == null) {\n            timer = Timer().schedule(2000) {\n                openMainAct.postValue(true)\n            }\n        }\n    }\n\n    override fun onCleared() {\n        super.onCleared()\n        \"onCleared SharedViewModel\".printMeD()\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/BindingAdapters.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.graphics.Typeface\nimport android.graphics.drawable.Drawable\nimport android.net.Uri\nimport android.text.Spannable\nimport android.text.SpannableStringBuilder\nimport android.text.TextUtils\nimport android.view.View\nimport android.widget.ImageView\nimport android.widget.ProgressBar\nimport android.widget.TextView\nimport androidx.core.view.setPadding\nimport androidx.core.widget.ImageViewCompat\nimport androidx.databinding.BindingAdapter\nimport androidx.databinding.InverseMethod\nimport coil.ImageLoader\nimport coil.decode.GifDecoder\nimport coil.load\nimport coil.request.CachePolicy\nimport coil.request.ImageRequest\nimport coil.request.SuccessResult\nimport coil.transform.CircleCropTransformation\nimport com.airbnb.lottie.LottieAnimationView\nimport com.google.android.material.chip.Chip\nimport com.gowtham.letschat.MApplication\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.db.data.*\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport timber.log.Timber\nimport java.io.File\nimport java.util.*\nimport kotlin.collections.ArrayList\n\nobject BindingAdapters {\n\n    @BindingAdapter(\"main\", \"secondText\")\n    @JvmStatic\n    fun setBoldString(view: TextView, maintext: String, sequence: String) {\n        view.text = getBoldText(maintext, sequence)\n    }\n\n    @JvmStatic\n    fun getBoldText(text: String, name: String): SpannableStringBuilder {\n        val str = SpannableStringBuilder(text)\n        val textPosition = text.indexOf(name)\n        str.setSpan(\n            android.text.style.StyleSpan(Typeface.BOLD),\n            textPosition, textPosition + name.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE\n        )\n        return str\n    }\n\n    @BindingAdapter(\"imageUrl\")\n    @JvmStatic\n    fun loadImage(view: ImageView, url: String?) {\n        if(url.isNullOrEmpty())\n            return\n        else {\n            ImageViewCompat.setImageTintList(view, null) //removing image tint\n            view.setPadding(0)\n        }\n        ImageUtils.loadUserImage(view, url)\n    }\n\n    @BindingAdapter(\"lastMessage\")\n    @JvmStatic\n    fun setLastMessage(txtView: TextView, msgList: List<Message>) {\n        val lastMsg=msgList.last()\n        txtView.text= getLastMsgTxt(lastMsg)\n    }\n\n    @InverseMethod(\"messageBsg\")\n    @JvmStatic\n    fun messageBsg(msg: Message): String {\n            return \"sd\"\n    }\n\n    @BindingAdapter(\"message\" , \"messageList\" , \"adapterPos\")\n    @JvmStatic\n    fun messageBackground(txtView: TextView,msg: Message,list: ArrayList<Message>,adapterPos: Int) {\n             txtView.setBackgroundResource(R.drawable.shape_send_msg)\nif (list.size<=2){\n    val message=list[adapterPos-1]\n    if (message.from==\"me\"){\n\n    }\n}\n\n    }\n\n    @BindingAdapter(\"loadImage\")\n    @JvmStatic\n    fun loadImage(imgView: ImageView, message: Message) {\n        val url=message.imageMessage?.uri\n        val imageType=message.imageMessage?.imageType\n        loadMsgImage(imgView,url!!,imageType!!)\n    }\n\n    @BindingAdapter(\"loadGroupMsgImage\")\n    @JvmStatic\n    fun loadGrpMsgImage(imgView: ImageView, message: GroupMessage) {\n        val url=message.imageMessage?.uri\n        val imageType=message.imageMessage?.imageType\n        loadMsgImage(imgView,url.toString(),imageType.toString())\n    }\n\n    private fun loadMsgImage(imgView: ImageView, url: String, imageType: String) {\n        try {\n            if (imageType==\"gif\") {\n                val imageLoader = ImageLoader.Builder(imgView.context)\n                    .componentRegistry {\n                        add(GifDecoder())\n                    }\n                    .build()\n                imgView.load(url,imageLoader){\n                    diskCachePolicy(CachePolicy.ENABLED)\n                    placeholder(R.drawable.gif)\n                    error(R.drawable.gif)\n                }\n            }else {\n                val isSticker=imageType==\"sticker\"\n                val placeHolder=if(isSticker) R.drawable.ic_sticker else R.drawable.ic_gal_pholder\n                imgView.load(url) {\n                    diskCachePolicy(CachePolicy.ENABLED)\n                    placeholder(placeHolder)\n                    error(placeHolder)\n                }}\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun getLastMsgTxt(msg: Message) : String{\n        return when(msg.type){\n            \"text\" -> {\n                msg.textMessage?.text.toString()\n            }\n            \"audio\" -> {\n                \"Audio\"\n            }\n            \"image\" -> {\n                msg.imageMessage?.imageType.toString().capitalize(Locale.getDefault())\n            }\n            \"video\" -> {\n                \"Video\"\n            }\n            \"file\" -> {\n                \"File\"\n            }\n            else->{ \"Steotho Image\" }\n        }\n    }\n\n    fun getLastMsgTxt(msg: GroupMessage) : String{\n        return when(msg.type){\n            \"text\" -> {\n                msg.textMessage?.text.toString()\n            }\n            \"audio\" -> {\n                \"Audio\"\n            }\n            \"image\" -> {\n                msg.imageMessage?.imageType.toString().capitalize(Locale.getDefault())\n            }\n            \"video\" -> {\n                \"Video\"\n            }\n            \"file\" -> {\n                \"File\"\n            }\n            else->{ \"Steotho image\" }\n        }\n    }\n\n    @BindingAdapter(\"messageSendTime\")\n    @JvmStatic\n    fun setMessageTime(txtView: TextView, msgList: List<Message>) {\n        val lastMsg=msgList.last()\n        val sentTime = lastMsg.createdAt\n        txtView.text = Utils.getTime(sentTime)\n    }\n\n    @BindingAdapter(\"showMsgTime\")\n    @JvmStatic\n    fun showMsgTime(txtView: TextView, lastMsg: Message) {\n        val sentTime = lastMsg.createdAt\n        txtView.text = Utils.getTime(sentTime)\n    }\n\n    @BindingAdapter(\"showGrpMsgTime\")\n    @JvmStatic\n    fun showGrpMsgTime(txtView: TextView, lastMsg: GroupMessage) {\n        val sentTime = lastMsg.createdAt\n        txtView.text = Utils.getTime(sentTime)\n    }\n\n    @BindingAdapter(\"loadAsDrawable\")\n    @JvmStatic\n    fun loadAsDrawable(chip: Chip, user: ChatUser) {\n        val url=user.user.image\n       if(url.isNotEmpty()){\n           CoroutineScope(Dispatchers.IO).launch {\n               val drawable= getBitmap(url)\n               withContext(Dispatchers.Main){\n                   chip.chipIcon=drawable\n               }\n           }\n       }\n    }\n\n\n    private suspend fun getBitmap(url: String): Drawable {\n        val context=MApplication.appContext\n        val loader= ImageLoader(context)\n        val request= ImageRequest.Builder(context)\n            .data(url)\n            .transformations(CircleCropTransformation())\n            .build()\n        return (loader.execute(request) as SuccessResult).drawable\n    }\n\n    @BindingAdapter(\"messageStatus\")\n    @JvmStatic\n    fun setState(txtStatus: TextView, status: Int) {\n        txtStatus.text=when(status){\n            0 -> \"Sending..\"\n            1 -> \"Sent\"\n            2 -> \"Delivered\"\n            3 -> \"Seen\"\n            else-> \"Failed\"\n        }\n    }\n\n    @BindingAdapter(\"groupMessageStatus\")\n    @JvmStatic\n    fun groupMsgStatus(txtStatus: TextView, message: GroupMessage) {\n        val preference=MPreference(MApplication.appContext)\n        val statusList=message.status\n        val myStatus=statusList.first()\n        if (message.from==preference.getUid())\n            statusList.removeAt(0)\n        val deliveried=message.status.any{ it==2 || it==3 }  //if anyone has seen the message\n        val seen=message.status.all{ it==3 }  //all members seen the messge\n\n        txtStatus.text= when {\n            myStatus==0 -> \"Sending\"\n            seen -> \"Seen\"\n            deliveried -> \"Delivered\"\n            myStatus==1 -> \"Sent\"\n            else -> \"Failed\"\n        }\n    }\n\n    @BindingAdapter(\"progressState\")\n    @JvmStatic\n    fun setProgressState(view: ProgressBar, state: LoadState?) {\n        state?.let {\n            view.visibility=when(it){\n                LoadState.OnLoading -> View.VISIBLE\n                else ->\n                    View.GONE\n            }\n        }\n    }\n\n    @BindingAdapter(\"setUnReadCount\")\n    @JvmStatic\n    fun setUnReadCount(txtView: TextView, msgList: List<Message>) {\n        val fromUser=MPreference(txtView.context).getUid()\n        val unReadCount=msgList.filter { it.to==fromUser && it.status<3 }.size\n        txtView.text = unReadCount.toString()\n        txtView.visibility= if (unReadCount==0) View.GONE else View.VISIBLE\n    }\n\n    @BindingAdapter(\"setUnReadCount2\")\n    @JvmStatic\n    fun setUnReadCount(txtView: TextView, count: Int) {\n        Timber.v(\"setUnReadCount2 $count\")\n        txtView.text = count.toString()\n        txtView.visibility= if (count==0) View.GONE else View.VISIBLE\n    }\n\n    @BindingAdapter(\"showSelected\")\n    @JvmStatic\n    fun showSelected(view: LottieAnimationView, isSelected: Boolean) {\n        if (isSelected) {\n            view.playAnimation()\n            view.show()\n        }else\n            view.gone()\n    }\n\n    @BindingAdapter(\"showTxtView\")\n    @JvmStatic\n    fun setChipIcon(txtView: TextView, user: ChatUser) {\n        if(user.user.image.isEmpty())\n            txtView.text=user.localName.first().toString()\n        else\n            txtView.gone()\n    }\n\n    @BindingAdapter(\"setMemberNames\")\n    @JvmStatic\n    fun setMemberNames(txtView: TextView, group: Group) {\n        val members =group.members?.map { chatUser->\n            val savedName=chatUser.localName\n            if (savedName.isNotEmpty())\n             savedName\n            else\n                \"${chatUser.user.mobile?.country} ${chatUser.user.mobile?.number}\"\n        }\n        members?.let {\n            txtView.text=TextUtils.join(\", \", it)\n        }\n    }\n\n    @BindingAdapter(\"setGroupName\")\n    @JvmStatic\n    fun setGroupName(txtView: TextView, group: Group) {\n            txtView.text=Utils.getGroupName(group.id)\n    }\n\n    @BindingAdapter(\"groupLastMessage\")\n    @JvmStatic\n    fun groupLastMessage(txtView: TextView, group: GroupWithMessages) {\n        val messages=group.messages\n        if (messages.isEmpty()){\n            val createdBy=group.group.createdBy\n            val msg=\"Created by ${group.group.members?.first { it.id==createdBy }?.localName}\"\n            txtView.text=msg\n        }\n        else{\n            val message=messages.last()\n            val localName=group.group.members?.first { it.id==message.from }?.localName\n            val txtMsg=\"$localName : ${getLastMsgTxt(message)}\"\n            txtView.text=txtMsg\n        }\n    }\n\n    @BindingAdapter(\"setGroupMessageSendTime\")\n    @JvmStatic\n    fun setGroupMessageSendTime(txtView: TextView, msgList: List<GroupMessage>) {\n        if (msgList.isNotEmpty()) {\n            val lastMsg = msgList.last()\n            val sentTime = lastMsg.createdAt\n            txtView.text = Utils.getTime(sentTime)\n        }\n    }\n\n    @BindingAdapter(\"setGroupUnReadCount\")\n    @JvmStatic\n    fun setGroupUnReadCount(txtView: TextView, unReadCount: Int) {\n        if(unReadCount==0)\n            txtView.gone()\n        else {\n            txtView.text = unReadCount.toString()\n            txtView.show()\n        }\n    }\n\n    @BindingAdapter(\"chatUsers\", \"message\")\n    @JvmStatic\n    fun setChatUserName(txtView: TextView, users: Array<ChatUser>, message: GroupMessage) {\n       val messageOwner= users.first { message.from==it.id }\n       txtView.text=messageOwner.localName\n    }\n\n    @BindingAdapter(\"showUserIdIfNotLocalSaved\", \"currentMessage\")\n    @JvmStatic\n    fun showUserIdIfNotLocalSaved(\n        txtView: TextView,\n        users: Array<ChatUser>, message: GroupMessage\n    ) {\n        val messageOwner= users.first { message.from==it.id }\n        txtView.text=messageOwner.user.userName\n        if (messageOwner.locallySaved)\n            txtView.gone()\n        else\n            txtView.show()\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/BottomSheetEvent.kt",
    "content": "package com.gowtham.letschat.utils\n\ndata class BottomSheetEvent(var position: Int)"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/ConnectionChangeEvent.kt",
    "content": "package com.gowtham.letschat.utils\n\nclass ConnectionChangeEvent(val message: String)\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/Constants.kt",
    "content": "package com.gowtham.letschat.utils\n\nobject Constants {\n\n    const val VIEW_TYPE=\"view_type\"\n\n    const val VIEW_CT=43\n\n    const val KEY_LAST_QUERIED_LIST=\"last_queried_list\"\n\n    const val CHAT_USER_DB_NAME=\"chat_user_db\"\n\n    const val ACTION_LOGGED_IN_ANOTHER_DEVICE=\"action_logged_in_another_device\"\n\n    const val ACTION_NEW_MESSAGE=\"action_new_message\"\n\n    const val ACTION_GROUP_NEW_MESSAGE=\"action_group_new_message\"\n\n    const val ACTION_MARK_AS_READ=\"action_mark_as_read\"\n\n    const val ACTION_REPLY=\"action_reply\"\n\n    const val CHAT_USER_DATA=\"chat_user_data\"\n\n    const val GROUP_DATA=\"group_data\"\n\n    const val CHAT_DATA=\"chat_data\"\n\n    const val MESSAGE_DATA=\"message_data\"\n\n    const val MESSAGE_FILE_URI=\"message_file_uri\"\n\n    const val FCM_SERVER_KEY=\"AAAApjZeY_U:APA91bG5Ifs2wIABgd1edHXKvXaRm1yG7bUj3A0VY8TBvF00i-l7yQw82FF10dkhUj56uAC_fZHVqN5_h4IIGQ21Jpiyj_uszjG8Lez1aOSX0YF-Nhp1qDt_CcAIBv64uHubsLkmudVF\"\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/Countries.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport com.gowtham.letschat.models.Country\n\nobject Countries {\n\n    private val COUNTRIES= arrayOf(\n        Country(\"AF\", \"Afghanistan\", \"+93\", \"AFN\"),\n        Country(\"AX\", \"Aland Islands\", \"+358\", \"EUR\"),\n        Country(\"AL\", \"Albania\", \"+355\", \"ALL\"),\n        Country(\"DZ\", \"Algeria\", \"+213\", \"DZD\"),\n        Country(\"AS\", \"American Samoa\", \"+1\", \"USD\"),\n        Country(\"AD\", \"Andorra\", \"+376\", \"EUR\"),\n        Country(\"AO\", \"Angola\", \"+244\", \"AOA\"),\n        Country(\"AI\", \"Anguilla\", \"+1\", \"XCD\"),\n        Country(\"AQ\", \"Antarctica\", \"+672\", \"USD\"),\n        Country(\"AG\", \"Antigua and Barbuda\", \"+1\", \"XCD\"),\n        Country(\"AR\", \"Argentina\", \"+54\", \"ARS\"),\n        Country(\"AM\", \"Armenia\", \"+374\", \"AMD\"),\n        Country(\"AW\", \"Aruba\", \"+297\", \"AWG\"),\n        Country(\"AU\", \"Australia\", \"+61\", \"AUD\"),\n        Country(\"AT\", \"Austria\", \"+43\", \"EUR\"),\n        Country(\"AZ\", \"Azerbaijan\", \"+994\", \"AZN\"),\n        Country(\"BS\", \"Bahamas\", \"+1\", \"BSD\"),\n        Country(\"BH\", \"Bahrain\", \"+973\", \"BHD\"),\n        Country(\"BD\", \"Bangladesh\", \"+880\", \"BDT\"),\n        Country(\"BB\", \"Barbados\", \"+1\", \"BBD\"),\n        Country(\"BY\", \"Belarus\", \"+375\", \"BYR\"),\n        Country(\"BE\", \"Belgium\", \"+32\", \"EUR\"),\n        Country(\"BZ\", \"Belize\", \"+501\", \"BZD\"),\n        Country(\"BJ\", \"Benin\", \"+229\", \"XOF\"),\n        Country(\"BM\", \"Bermuda\", \"+1\", \"BMD\"),\n        Country(\"BT\", \"Bhutan\", \"+975\", \"BTN\"),\n        Country(\"BO\", \"Bolivia, Plurinational State of\", \"+591\", \"BOB\"),\n        Country(\"BA\", \"Bosnia and Herzegovina\", \"+387\", \"BAM\"),\n        Country(\"BQ\", \"Bonaire\", \"+599\", \"USD\"),\n        Country(\"BW\", \"Botswana\", \"+267\", \"BWP\"),\n        Country(\"BV\", \"Bouvet Island\", \"+47\", \"NOK\"),\n        Country(\"BR\", \"Brazil\", \"+55\", \"BRL\"),\n        Country(\"IO\", \"British Indian Ocean Territory\", \"+246\", \"USD\"),\n        Country(\"BN\", \"Brunei Darussalam\", \"+673\", \"BND\"),\n        Country(\"BG\", \"Bulgaria\", \"+359\", \"BGN\"),\n        Country(\"BF\", \"Burkina Faso\", \"+226\", \"XOF\"),\n        Country(\"BI\", \"Burundi\", \"+257\", \"BIF\"),\n        Country(\"KH\", \"Cambodia\", \"+855\", \"KHR\"),\n        Country(\"CM\", \"Cameroon\", \"+237\", \"XAF\"),\n        Country(\"CA\", \"Canada\", \"+1\", \"CAD\"),\n        Country(\"CV\", \"Cape Verde\", \"+238\", \"CVE\"),\n        Country(\"KY\", \"Cayman Islands\", \"+345\", \"KYD\"),\n        Country(\"CF\", \"Central African Republic\", \"+236\", \"XAF\"),\n        Country(\"TD\", \"Chad\", \"+235\", \"XAF\"),\n        Country(\"CL\", \"Chile\", \"+56\", \"CLP\"),\n        Country(\"CN\", \"China\", \"+86\", \"CNY\"),\n        Country(\"CX\", \"Christmas Island\", \"+61\", \"AUD\"),\n        Country(\"CC\", \"Cocos (Keeling) Islands\", \"+61\", \"AUD\"),\n        Country(\"CO\", \"Colombia\", \"+57\", \"COP\"),\n        Country(\"KM\", \"Comoros\", \"+269\", \"KMF\"),\n        Country(\"CD\", \"Congo, The Democratic Republic of the\", \"+243\", \"CDF\"),\n        Country(\"CG\", \"Congo\", \"+242\", \"XAF\"),\n        Country(\"CK\", \"Cook Islands\", \"+682\", \"NZD\"),\n        Country(\"CR\", \"Costa Rica\", \"+506\", \"CRC\"),\n        Country(\"HR\", \"Croatia\", \"+385\", \"HRK\"),\n        Country(\"CU\", \"Cuba\", \"+53\", \"CUP\"),\n        Country(\"CW\", \"Curacao\", \"+599\", \"ANG\"),\n        Country(\"CY\", \"Cyprus\", \"+357\", \"EUR\"),\n        Country(\"CZ\", \"Czech Republic\", \"+420\", \"CZK\"),\n        Country(\"DK\", \"Denmark\", \"+45\", \"DKK\"),\n        Country(\"DJ\", \"Djibouti\", \"+253\", \"DJF\"),\n        Country(\"DM\", \"Dominica\", \"+1\", \"XCD\"),\n        Country(\"DO\", \"Dominican Republic\", \"+1\", \"DOP\"),\n        Country(\"TL\", \"East Timor\", \"+670\", \"USD\"),\n        Country(\"EC\", \"Ecuador\", \"+593\", \"USD\"),\n        Country(\"EG\", \"Egypt\", \"+20\", \"EGP\"),\n        Country(\"SV\", \"El Salvador\", \"+503\", \"SVC\"),\n        Country(\"GQ\", \"Equatorial Guinea\", \"+240\", \"XAF\"),\n        Country(\"ER\", \"Eritrea\", \"+291\", \"ERN\"),\n        Country(\"EE\", \"Estonia\", \"+372\", \"EUR\"),\n        Country(\"ET\", \"Ethiopia\", \"+251\", \"ETB\"),\n        Country(\"FK\", \"Falkland Islands (Malvinas)\", \"+500\", \"FKP\"),\n        Country(\"FO\", \"Faroe Islands\", \"+298\", \"DKK\"),\n        Country(\"FJ\", \"Fiji\", \"+679\", \"FJD\"),\n        Country(\"FI\", \"Finland\", \"+358\", \"EUR\"),\n        Country(\"FR\", \"France\", \"+33\", \"EUR\"),\n        Country(\"GF\", \"French Guiana\", \"+594\", \"EUR\"),\n        Country(\"TF\", \"French Southern Territories\", \"+262\", \"EUR\"),\n        Country(\"PF\", \"French Polynesia\", \"+689\", \"XPF\"),\n        Country(\"GA\", \"Gabon\", \"+241\", \"XAF\"),\n        Country(\"GM\", \"Gambia\", \"+220\", \"GMD\"),\n        Country(\"GE\", \"Georgia\", \"+995\", \"GEL\"),\n        Country(\"DE\", \"Germany\", \"+49\", \"EUR\"),\n        Country(\"GH\", \"Ghana\", \"+233\", \"GHS\"),\n        Country(\"GI\", \"Gibraltar\", \"+350\", \"GIP\"),\n        Country(\"GR\", \"Greece\", \"+30\", \"EUR\"),\n        Country(\"GL\", \"Greenland\", \"+299\", \"DKK\"),\n        Country(\"GD\", \"Grenada\", \"+1\", \"XCD\"),\n        Country(\"GP\", \"Guadeloupe\", \"+590\", \"EUR\"),\n        Country(\"GU\", \"Guam\", \"+1\", \"USD\"),\n        Country(\"GT\", \"Guatemala\", \"+502\", \"GTQ\"),\n        Country(\"GG\", \"Guernsey\", \"+44\", \"GGP\"),\n        Country(\"GN\", \"Guinea\", \"+224\", \"GNF\"),\n        Country(\"GW\", \"Guinea-Bissau\", \"+245\", \"XOF\"),\n        Country(\"GY\", \"Guyana\", \"+595\", \"GYD\"),\n        Country(\"HT\", \"Haiti\", \"+509\", \"HTG\"),\n        Country(\"HM\", \"Heard Island and McDonald Islands\", \"+000\", \"AUD\"),\n        Country(\"VA\", \"Holy See (Vatican City State)\", \"+379\", \"EUR\"),\n        Country(\"HN\", \"Honduras\", \"+504\", \"HNL\"),\n        Country(\"HK\", \"Hong Kong\", \"+852\", \"HKD\"),\n        Country(\"HU\", \"Hungary\", \"+36\", \"HUF\"),\n        Country(\"IS\", \"Iceland\", \"+354\", \"ISK\"),\n        Utils.getDefaultCountry(),\n        Country(\"ID\", \"Indonesia\", \"+62\", \"IDR\"),\n        Country(\"IR\", \"Iran, Islamic Republic of\", \"+98\", \"IRR\"),\n        Country(\"IQ\", \"Iraq\", \"+964\", \"IQD\"),\n        Country(\"IE\", \"Ireland\", \"+353\", \"EUR\"),\n        Country(\"IM\", \"Isle of Man\", \"+44\", \"GBP\"),\n        Country(\"IL\", \"Israel\", \"+972\", \"ILS\"),\n        Country(\"IT\", \"Italy\", \"+39\", \"EUR\"),\n        Country(\"CI\", \"Ivory Coast\", \"+225\", \"XOF\"),\n        Country(\"JM\", \"Jamaica\", \"+1\", \"JMD\"),\n        Country(\"JP\", \"Japan\", \"+81\", \"JPY\"),\n        Country(\"JE\", \"Jersey\", \"+44\", \"JEP\"),\n        Country(\"JO\", \"Jordan\", \"+962\", \"JOD\"),\n        Country(\"KZ\", \"Kazakhstan\", \"+7\", \"KZT\"),\n        Country(\"KE\", \"Kenya\", \"+254\", \"KES\"),\n        Country(\"KI\", \"Kiribati\", \"+686\", \"AUD\"),\n        Country(\"XK\", \"Kosovo\", \"+383\", \"EUR\"),\n        Country(\"KW\", \"Kuwait\", \"+965\", \"KWD\"),\n        Country(\"KG\", \"Kyrgyzstan\", \"+996\", \"KGS\"),\n        Country(\"LA\", \"Lao People's Democratic Republic\", \"+856\", \"LAK\"),\n        Country(\"LV\", \"Latvia\", \"+371\", \"LVL\"),\n        Country(\"LB\", \"Lebanon\", \"+961\", \"LBP\"),\n        Country(\"LS\", \"Lesotho\", \"+266\", \"LSL\"),\n        Country(\"LR\", \"Liberia\", \"+231\", \"LRD\"),\n        Country(\"LY\", \"Libyan Arab Jamahiriya\", \"+218\", \"LYD\"),\n        Country(\"LI\", \"Liechtenstein\", \"+423\", \"CHF\"),\n        Country(\"LT\", \"Lithuania\", \"+370\", \"LTL\"),\n        Country(\"LU\", \"Luxembourg\", \"+352\", \"EUR\"),\n        Country(\"MO\", \"Macao\", \"+853\", \"MOP\"),\n        Country(\n            \"MK\", \"Macedonia, The Former Yugoslav Republic of\", \"+389\",\n            \"MKD\"\n        ),\n        Country(\"MG\", \"Madagascar\", \"+261\", \"MGA\"),\n        Country(\"MW\", \"Malawi\", \"+265\", \"MWK\"),\n        Country(\"MY\", \"Malaysia\", \"+60\", \"MYR\"),\n        Country(\"MV\", \"Maldives\", \"+960\", \"MVR\"),\n        Country(\"ML\", \"Mali\", \"+223\", \"XOF\"),\n        Country(\"MT\", \"Malta\", \"+356\", \"EUR\"),\n        Country(\"MH\", \"Marshall Islands\", \"+692\", \"USD\"),\n        Country(\"MQ\", \"Martinique\", \"+596\", \"EUR\"),\n        Country(\"MR\", \"Mauritania\", \"+222\", \"MRO\"),\n        Country(\"MU\", \"Mauritius\", \"+230\", \"MUR\"),\n        Country(\"YT\", \"Mayotte\", \"+262\", \"EUR\"),\n        Country(\"MX\", \"Mexico\", \"+52\", \"MXN\"),\n        Country(\"FM\", \"Micronesia, Federated States of\", \"+691\", \"USD\"),\n        Country(\"MD\", \"Moldova, Republic of\", \"+373\", \"MDL\"),\n        Country(\"MC\", \"Monaco\", \"+377\", \"EUR\"),\n        Country(\"MN\", \"Mongolia\", \"+976\", \"MNT\"),\n        Country(\"ME\", \"Montenegro\", \"+382\", \"EUR\"),\n        Country(\"MS\", \"Montserrat\", \"+1\", \"XCD\"),\n        Country(\"MA\", \"Morocco\", \"+212\", \"MAD\"),\n        Country(\"MZ\", \"Mozambique\", \"+258\", \"MZN\"),\n        Country(\"MM\", \"Myanmar\", \"+95\", \"MMK\"),\n        Country(\"NA\", \"Namibia\", \"+264\", \"NAD\"),\n        Country(\"NR\", \"Nauru\", \"+674\", \"AUD\"),\n        Country(\"NP\", \"Nepal\", \"+977\", \"NPR\"),\n        Country(\"NL\", \"Netherlands\", \"+31\", \"EUR\"),\n        Country(\"NC\", \"New Caledonia\", \"+687\", \"XPF\"),\n        Country(\"NZ\", \"New Zealand\", \"+64\", \"NZD\"),\n        Country(\"NI\", \"Nicaragua\", \"+505\", \"NIO\"),\n        Country(\"NE\", \"Niger\", \"+227\", \"XOF\"),\n        Country(\"NG\", \"Nigeria\", \"+234\", \"NGN\"),\n        Country(\"NU\", \"Niue\", \"+683\", \"NZD\"),\n        Country(\"NF\", \"Norfolk Island\", \"+672\", \"AUD\"),\n        Country(\"MP\", \"Northern Mariana Islands\", \"+1\", \"USD\"),\n        Country(\"KP\", \"North Korea\", \"+850\", \"KPW\"),\n        Country(\"NO\", \"Norway\", \"+47\", \"NOK\"),\n        Country(\"OM\", \"Oman\", \"+968\", \"OMR\"),\n        Country(\"PK\", \"Pakistan\", \"+92\", \"PKR\"),\n        Country(\"PW\", \"Palau\", \"+680\", \"USD\"),\n        Country(\"PS\", \"Palestinian Territory, Occupied\", \"+970\", \"ILS\"),\n        Country(\"PA\", \"Panama\", \"+507\", \"PAB\"),\n        Country(\"PG\", \"Papua New Guinea\", \"+675\", \"PGK\"),\n        Country(\"PY\", \"Paraguay\", \"+595\", \"PYG\"),\n        Country(\"PE\", \"Peru\", \"+51\", \"PEN\"),\n        Country(\"PH\", \"Philippines\", \"+63\", \"PHP\"),\n        Country(\"PN\", \"Pitcairn\", \"+872\", \"NZD\"),\n        Country(\"PL\", \"Poland\", \"+48\", \"PLN\"),\n        Country(\"PT\", \"Portugal\", \"+351\", \"EUR\"),\n        Country(\"PR\", \"Puerto Rico\", \"+1\", \"USD\"),\n        Country(\"QA\", \"Qatar\", \"+974\", \"QAR\"),\n        Country(\"RO\", \"Romania\", \"+40\", \"RON\"),\n        Country(\"RU\", \"Russia\", \"+7\", \"RUB\"),\n        Country(\"RW\", \"Rwanda\", \"+250\", \"RWF\"),\n        Country(\"RE\", \"Reunion\", \"+262\", \"EUR\"),\n        Country(\"BL\", \"Saint Barthelemy\", \"+590\", \"EUR\"),\n        Country(\n            \"SH\", \"Saint Helena, Ascension and Tristan Da Cunha\", \"+290\",\n            \"SHP\"\n        ),\n        Country(\"KN\", \"Saint Kitts and Nevis\", \"+1\", \"XCD\"),\n        Country(\"LC\", \"Saint Lucia\", \"+1\", \"XCD\"),\n        Country(\"MF\", \"Saint Martin\", \"+590\", \"EUR\"),\n        Country(\"PM\", \"Saint Pierre and Miquelon\", \"+508\", \"EUR\"),\n        Country(\"VC\", \"Saint Vincent and the Grenadines\", \"+1\", \"XCD\"),\n        Country(\"WS\", \"Samoa\", \"+685\", \"WST\"),\n        Country(\"SM\", \"San Marino\", \"+378\", \"EUR\"),\n        Country(\"ST\", \"Sao Tome and Principe\", \"+239\", \"STD\"),\n        Country(\"SA\", \"Saudi Arabia\", \"+966\", \"SAR\"),\n        Country(\"SN\", \"Senegal\", \"+221\", \"XOF\"),\n        Country(\"RS\", \"Serbia\", \"+381\", \"RSD\"),\n        Country(\"SC\", \"Seychelles\", \"+248\", \"SCR\"),\n        Country(\"SL\", \"Sierra Leone\", \"+232\", \"SLL\"),\n        Country(\"SG\", \"Singapore\", \"+65\", \"SGD\"),\n        Country(\"SX\", \"Sint Maarten\", \"+1\", \"ANG\"),\n        Country(\"SK\", \"Slovakia\", \"+421\", \"EUR\"),\n        Country(\"SI\", \"Slovenia\", \"+386\", \"EUR\"),\n        Country(\"SB\", \"Solomon Islands\", \"+677\", \"SBD\"),\n        Country(\"SO\", \"Somalia\", \"+252\", \"SOS\"),\n        Country(\"ZA\", \"South Africa\", \"+27\", \"ZAR\"),\n        Country(\"SS\", \"South Sudan\", \"+211\", \"SSP\"),\n        Country(\n            \"GS\", \"South Georgia and the South Sandwich Islands\", \"+500\",\n            \"GBP\"\n        ),\n        Country(\"KR\", \"South Korea\", \"+82\", \"KRW\"),\n        Country(\"ES\", \"Spain\", \"+34\", \"EUR\"),\n        Country(\"LK\", \"Sri Lanka\", \"+94\", \"LKR\"),\n        Country(\"SD\", \"Sudan\", \"+249\", \"SDG\"),\n        Country(\"SR\", \"Suriname\", \"+597\", \"SRD\"),\n        Country(\"SJ\", \"Svalbard and Jan Mayen\", \"+47\", \"NOK\"),\n        Country(\"SZ\", \"Swaziland\", \"+268\", \"SZL\"),\n        Country(\"SE\", \"Sweden\", \"+46\", \"SEK\"),\n        Country(\"CH\", \"Switzerland\", \"+41\", \"CHF\"),\n        Country(\"SY\", \"Syrian Arab Republic\", \"+963\", \"SYP\"),\n        Country(\"TW\", \"Taiwan\", \"+886\", \"TWD\"),\n        Country(\"TJ\", \"Tajikistan\", \"+992\", \"TJS\"),\n        Country(\"TZ\", \"Tanzania, United Republic of\", \"+255\", \"TZS\"),\n        Country(\"TH\", \"Thailand\", \"+66\", \"THB\"),\n        Country(\"TG\", \"Togo\", \"+228\", \"XOF\"),\n        Country(\"TK\", \"Tokelau\", \"+690\", \"NZD\"),\n        Country(\"TO\", \"Tonga\", \"+676\", \"TOP\"),\n        Country(\"TT\", \"Trinidad and Tobago\", \"+1\", \"TTD\"),\n        Country(\"TN\", \"Tunisia\", \"+216\", \"TND\"),\n        Country(\"TR\", \"Turkey\", \"+90\", \"TRY\"),\n        Country(\"TM\", \"Turkmenistan\", \"+993\", \"TMT\"),\n        Country(\"TC\", \"Turks and Caicos Islands\", \"+1\", \"USD\"),\n        Country(\"TV\", \"Tuvalu\", \"+688\", \"AUD\"),\n        Country(\"UM\", \"U.S. Minor Outlying Islands\", \"+1\", \"USD\"),\n        Country(\"UG\", \"Uganda\", \"+256\", \"UGX\"),\n        Country(\"UA\", \"Ukraine\", \"+380\", \"UAH\"),\n        Country(\"AE\", \"United Arab Emirates\", \"+971\", \"AED\"),\n        Country(\"GB\", \"United Kingdom\", \"+44\", \"GBP\"),\n        Country(\"US\", \"United States\", \"+1\", \"USD\"),\n        Country(\"UY\", \"Uruguay\", \"+598\", \"UYU\"),\n        Country(\"UZ\", \"Uzbekistan\", \"+998\", \"UZS\"),\n        Country(\"VU\", \"Vanuatu\", \"+678\", \"VUV\"),\n        Country(\"VE\", \"Venezuela, Bolivarian Republic of\", \"+58\", \"VEF\"),\n        Country(\"VN\", \"Vietnam\", \"+84\", \"VND\"),\n        Country(\"VG\", \"Virgin Islands, British\", \"+1\", \"USD\"),\n        Country(\"VI\", \"Virgin Islands, U.S.\", \"+1\", \"USD\"),\n        Country(\"WF\", \"Wallis and Futuna\", \"+681\", \"XPF\"),\n        Country(\"EH\", \"Western Sahara\", \"+212\", \"MAD\"),\n        Country(\"YE\", \"Yemen\", \"+967\", \"YER\"),\n        Country(\"ZM\", \"Zambia\", \"+260\", \"ZMW\"),\n        Country(\"ZW\", \"Zimbabwe\", \"+263\", \"USD\")\n    )\n\n    fun getCountries(): List<Country>{\n        return COUNTRIES.toList()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/DataStorePreference.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.content.Context\nimport androidx.datastore.core.DataStore\nimport androidx.datastore.preferences.core.Preferences\nimport androidx.datastore.preferences.core.edit\nimport androidx.datastore.preferences.core.stringPreferencesKey\nimport androidx.datastore.preferences.preferencesDataStore\nimport com.gowtham.letschat.db.data.ChatUser\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.map\nimport kotlinx.coroutines.launch\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\nimport javax.inject.Inject\nimport javax.inject.Singleton\n\n@Singleton\nclass DataStorePreference @Inject constructor(@ApplicationContext private val context: Context){\n\n    val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = \"search_results\")\n\n    fun storeList(key: String,value: List<ChatUser>){\n        CoroutineScope(Dispatchers.IO).launch {\n           val dataStoreKey= stringPreferencesKey(key)\n            context.dataStore.edit {\n                it[dataStoreKey]=Json.encodeToString(value)\n            }\n        }\n    }\n\n    fun getList(): Flow<String>{\n        val listKey = stringPreferencesKey(Constants.KEY_LAST_QUERIED_LIST)\n        return context.dataStore.data\n            .map { preferences ->\n                // No type safety.\n                preferences[listKey] ?: \"\"\n            }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/DiffCallbackChatUser.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport androidx.recyclerview.widget.DiffUtil\nimport com.gowtham.letschat.db.data.ChatUser\n\nclass DiffCallbackChatUser  : DiffUtil.ItemCallback<ChatUser>() {\n    override fun areItemsTheSame(oldItem: ChatUser, newItem: ChatUser): Boolean {\n        return oldItem.id == newItem.id\n    }\n\n    override fun areContentsTheSame(oldItem: ChatUser, newItem: ChatUser): Boolean {\n        return oldItem.isSelected == newItem.isSelected &&\n                oldItem.locallySaved==newItem.locallySaved &&\n                oldItem.unRead==newItem.unRead &&\n                oldItem.localName ==newItem.localName\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/Event.kt",
    "content": "package com.gowtham.letschat.utils\n\nopen class Event<out T>(private val content: T) {\n\n    var hasBeenHandled = false\n        private set // Allow external read but not write\n\n    /**\n     * Returns the content and prevents its use again.\n     */\n    fun getContentIfNotHandled(): T? {\n        return if (hasBeenHandled) {\n            null\n        } else {\n            hasBeenHandled = true\n            content\n        }\n    }\n\n    /**\n     * Returns the content, even if it's already been handled.\n     */\n    fun peekContent(): T = content\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/Events/EventAudioMsg.kt",
    "content": "package com.gowtham.letschat.utils.Events\n\nclass EventAudioMsg(val isPlaying: Boolean)"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/Events/EventUpdateRecycleItem.kt",
    "content": "package com.gowtham.letschat.utils.Events\n\nclass EventUpdateRecycleItem(val adapterPosition: Int)"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/GroupMsgActionReceiver.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport androidx.annotation.CallSuper\nimport androidx.core.app.RemoteInput\nimport com.google.firebase.firestore.CollectionReference\nimport com.gowtham.letschat.KEY_TEXT_REPLY\nimport com.gowtham.letschat.MApplication\nimport com.gowtham.letschat.TYPE_NEW_GROUP\nimport com.gowtham.letschat.TYPE_NEW_GROUP_MESSAGE\nimport com.gowtham.letschat.core.*\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.daos.GroupMessageDao\nimport com.gowtham.letschat.db.data.*\nimport com.gowtham.letschat.di.GroupCollection\nimport com.gowtham.letschat.di.MessageCollection\nimport com.gowtham.letschat.models.UserProfile\nimport dagger.hilt.android.AndroidEntryPoint\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\nimport javax.inject.Inject\n\nabstract class HiltGroupBroadcastReceiver : BroadcastReceiver(){\n    @CallSuper\n    override fun onReceive(p0: Context?, p1: Intent?) { }\n}\n\n@AndroidEntryPoint\nclass GroupMsgActionReceiver : HiltGroupBroadcastReceiver(), OnGrpMessageResponse {\n\n    @Inject\n    lateinit var preference: MPreference\n\n    @GroupCollection\n    @Inject\n    lateinit var grpCollection: CollectionReference\n\n    @Inject\n    lateinit var groupDao: GroupDao\n\n    @Inject\n    lateinit var groupMsgStatusUpdater: GroupMsgStatusUpdater\n\n    @Inject\n    lateinit var groupMsgDao: GroupMessageDao\n\n    lateinit var groupWithMsg: GroupWithMessages\n\n    private var notificationId: Int=0\n\n    lateinit var context: Context\n\n    private lateinit var myUserId: String\n\n    private lateinit var group: Group\n\n    private lateinit var profile: UserProfile\n\n    override fun onReceive(context: Context?, intent: Intent?) {\n        super.onReceive(context, intent)\n        this.context=context!!\n        myUserId = preference.getUid()!!\n        profile=preference.getUserProfile()!!\n        groupWithMsg = intent!!.getParcelableExtra(Constants.GROUP_DATA)!!\n        group=groupWithMsg.group\n        val notiIdString = groupWithMsg.group.createdAt.toString()\n        //last 4 digits as notificationId\n        notificationId= notiIdString.substring(notiIdString.length - 4)\n            .toInt()\n        if (intent.action == Constants.ACTION_MARK_AS_READ) {\n            groupMsgStatusUpdater.updateToSeen(myUserId, groupWithMsg.messages, group.id)\n            Utils.removeNotificationById(context, notificationId)\n            updateOnDb()\n        }else{\n            val reply = getMessageText(intent)\n            if (!reply.isNullOrBlank()) {\n                val txtMessage=TextMessage(reply)\n                val message = createMessage()\n                message.textMessage=txtMessage\n                val messageSender = GroupMsgSender(grpCollection)\n                messageSender.sendMessage(message, group,this)\n            }\n        }\n    }\n\n    private fun createMessage(): GroupMessage {\n        val toUsers=groupWithMsg.group.members?.map { it.id } as ArrayList\n        val groupSize=group.members!!.size\n        val statusList=ArrayList<Int>()\n        val deliveryTimeList=ArrayList<Long>()\n        for (index in 0 until groupSize){\n            statusList.add(0)\n            deliveryTimeList.add(0L)\n        }\n        return GroupMessage(System.currentTimeMillis(), group.id, from = myUserId,\n            to = toUsers, profile.userName, profile.image, statusList, deliveryTimeList,\n            deliveryTimeList)\n    }\n\n\n    private fun updateOnDb() {\n        val list= groupWithMsg.messages.filter {\n                 Utils.myMsgStatus(myUserId,it)<3 && it.from!=myUserId }.map {\n            it.status[Utils.myIndexOfStatus(myUserId,it)]=3\n            it\n        }\n        //change status to seen for other messagea of the user\n        UserUtils.setUnReadCountGroup(groupDao,groupWithMsg.group)\n        UserUtils.insertMutlipleGroupMsg(groupMsgDao,list)\n    }\n\n    private fun getMessageText(intent: Intent): String? {\n        return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY).toString()\n    }\n\n    override fun onSuccess(message: GroupMessage) {\n        Utils.removeNotificationById(context, notificationId)\n        //update to seen status\n        groupMsgStatusUpdater.updateToSeen(myUserId, groupWithMsg.messages,group.id)\n        updateOnDb()\n        UserUtils.insertGroupMsg(groupMsgDao,message)\n        for (user in group.members!!) {\n            val token = user.user.token\n            if (token.isNotEmpty())\n                UserUtils.sendPush(context, TYPE_NEW_GROUP_MESSAGE,\n                    Json.encodeToString(message), token, user.id)\n        }\n    }\n\n    override fun onFailed(message: GroupMessage) {\n        UserUtils.insertGroupMsg(groupMsgDao,message)\n    }\n\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/ImageUtils.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.Manifest\nimport android.app.Activity\nimport android.content.ContentResolver\nimport android.content.Context\nimport android.content.Intent\nimport android.graphics.Bitmap\nimport android.net.Uri\nimport android.os.Build\nimport android.os.Bundle\nimport android.provider.MediaStore\nimport android.text.TextUtils\nimport android.webkit.MimeTypeMap\nimport android.widget.ImageView\nimport androidx.core.content.FileProvider\nimport androidx.fragment.app.Fragment\nimport coil.load\nimport coil.request.CachePolicy\nimport coil.transform.CircleCropTransformation\nimport com.canhub.cropper.CropImage\nimport com.canhub.cropper.CropImageView\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.fragments.FImageSrcSheet\nimport com.gowtham.letschat.fragments.SheetListener\nimport java.io.*\nimport kotlin.random.Random\n\nobject ImageUtils {\n\n    private const val FROM_GALLERY = 116\n\n    private const val TAKE_PHOTO = 111\n\n    private var photoUri: Uri? = null\n\n    fun askPermission(context: Fragment) {\n        if (checkStoragePermission(context))\n            showCameraOptions(context)\n    }\n\n    fun loadUserImage(imageView: ImageView, imgUrl: String){\n        imageView.load(imgUrl) {\n            crossfade(true)\n            crossfade(300)\n            diskCachePolicy(CachePolicy.ENABLED)\n            placeholder(R.drawable.ic_other_user)\n            error(R.drawable.ic_other_user)\n            transformations(CircleCropTransformation())\n        }\n    }\n\n    private fun checkStoragePermission(context: Fragment): Boolean {\n        return Utils.checkPermission(\n            context, Manifest.permission.WRITE_EXTERNAL_STORAGE,\n            Manifest.permission.CAMERA\n        )\n    }\n\n    private fun showCameraOptions(context: Fragment) {\n        photoUri = null\n        val builder = FImageSrcSheet.newInstance(Bundle())\n        builder.addListener(object : SheetListener {\n            override fun selectedItem(index: Int) {\n                if (index == 0)\n                    takePhoto(context.requireActivity())\n                else\n                    chooseGallery(context.requireActivity())\n            }\n        },)\n        builder.show(context.childFragmentManager, \"\")\n    }\n\n    public fun chooseGallery(context: Activity) {\n        try {\n            val intent = Intent(Intent.ACTION_PICK)\n            intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, \"image/*\")\n            context.startActivityForResult(intent, FROM_GALLERY)\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    public fun takePhoto(context: Activity) {\n        val fileName = \"Snap_\" + System.currentTimeMillis() / 1000 + \".jpg\"\n        openCameraIntent(context, MediaStore.ACTION_IMAGE_CAPTURE, fileName, TAKE_PHOTO)\n    }\n\n    private fun openCameraIntent(\n        context: Activity,\n        action: String,\n        fileName: String,\n        reqCode: Int) {\n        try {\n            val intent = Intent(action)\n            if (intent.resolveActivity(context.packageManager) != null) {\n                val file = File(createImageFolder(context, \"\"), fileName)\n                photoUri = if (isNougat())\n                    FileProvider.getUriForFile(context, providerPath(context), file)\n                else Uri.fromFile(file)\n                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)\n                intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)\n                intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)\n                context.startActivityForResult(intent, reqCode)\n                context.overridePendingTransition(\n                    android.R.anim.fade_in,\n                    android.R.anim.fade_out\n                )\n            } else\n                context.toast(\"Camera not available\")\n        } catch (e: java.lang.Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun cropImage(context: Activity, data: Intent?, squareCrop: Boolean = true) {\n        val imgUri: Uri? = getPhotoUri(data)\n        imgUri?.let {\n            val cropImage = CropImage.activity(imgUri)\n                .setOutputCompressFormat(Bitmap.CompressFormat.JPEG)\n                .setGuidelines(CropImageView.Guidelines.ON)\n            if (squareCrop)\n                cropImage.setAspectRatio(1, 1)\n            cropImage.start(context)\n        }\n    }\n\n    fun getCroppedImage(data: Intent?): Uri? {\n        try {\n            val result = CropImage.getActivityResult(data)\n            return result?.originalUri\n        } catch (e: java.lang.Exception) {\n            e.printStackTrace()\n        }\n        return null\n    }\n    private fun getPhotoUri(data: Intent?): Uri? {\n        return if (data == null || data.data == null) photoUri else data.data\n    }\n\n    private fun createImageFolder(context: Context, path: String): String? {\n        val folderPath = context.getExternalFilesDir(\"\")\n            ?.absolutePath + \"/\" + context.getString(R.string.app_name)\n        try {\n            val file = File(\"$folderPath/$path\")\n            if (!file.exists()) file.mkdirs()\n            return file.absolutePath\n        } catch (e: java.lang.Exception) {\n            e.printStackTrace()\n        }\n        return folderPath\n    }\n\n    private fun isNougat(): Boolean {\n        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N\n    }\n\n    private fun providerPath(context: Context): String {\n        return context.packageName + \".fileprovider\"\n    }\n\n    fun onImagePerResult(context: Fragment, vararg result: Int) {\n        if (Utils.isPermissionOk(*result))\n            showCameraOptions(context)\n        else\n            context.requireContext().toast(R.string.txt_file_p_error)\n    }\n\n    fun getUriPath(context: Context, uri: Uri, vararg data: String): String? {\n        return if (uri.toString()\n                .contains(providerPath(context))\n        ) uri.path else if (isGoogleOldPhotosUri(uri)) uri.lastPathSegment else if (isGoogleNewPhotosUri(\n                uri\n            ) || isPicasaPhotoUri(uri)\n        ) copyFile(context, uri, *data) else {\n            val result: String?\n            val cursor = context.contentResolver.query(uri, null, null, null, null)\n            if (cursor == null) result = uri.path else {\n                cursor.moveToFirst()\n                result = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA))\n                cursor.close()\n            }\n            result ?: \"\"\n        }\n    }\n\n    private fun isGoogleOldPhotosUri(uri: Uri): Boolean {\n        return \"com.google.android.apps.photos.content\" == uri.authority\n    }\n\n    private fun isGoogleNewPhotosUri(uri: Uri): Boolean {\n        return \"com.google.android.apps.photos.contentprovider\" == uri.authority\n    }\n\n    private fun isPicasaPhotoUri(uri: Uri?): Boolean {\n        return (uri != null && !TextUtils.isEmpty(uri.authority)\n                && (uri.authority!!.startsWith(\"com.android.gallery3d\")\n                || uri.authority!!.startsWith(\"com.google.android.gallery3d\")))\n    }\n\n    private fun copyFile(context: Context, uri: Uri, vararg data: String): String? {\n        var filePath: String\n        var inputStream: InputStream? = null\n        var outStream: BufferedOutputStream? = null\n        try {\n            val extension = getExtension(context, uri, data[1])\n            inputStream = context.contentResolver.openInputStream(uri)\n            val extDir = context.externalCacheDir\n            if (extDir == null || inputStream == null) return \"\"\n            filePath = (extDir.absolutePath + \"/\" + data[0]\n                    + \"_\" + Random.nextInt(100) + extension)\n            outStream = BufferedOutputStream(FileOutputStream(filePath))\n            val buf = ByteArray(2048)\n            var len: Int\n            while (inputStream.read(buf).also { len = it } > 0) {\n                outStream.write(buf, 0, len)\n            }\n        } catch (e: java.lang.Exception) {\n            e.printStackTrace()\n            filePath = \"\"\n        } finally {\n            try {\n                inputStream?.close()\n                outStream?.close()\n            } catch (e: IOException) {\n                e.printStackTrace()\n            }\n        }\n        return filePath\n    }\n\n    private fun getExtension(context: Context, uri: Uri, actual: String): String {\n        try {\n            val extension: String?\n            extension = if (uri.scheme != null && uri.scheme == ContentResolver.SCHEME_CONTENT) {\n                val mime = MimeTypeMap.getSingleton()\n                mime.getExtensionFromMimeType(context.contentResolver.getType(uri))\n            } else MimeTypeMap.getFileExtensionFromUrl(\n                Uri.fromFile(File(uri.path)).toString()\n            )\n            return if (extension == null || extension.isEmpty()) actual else extension\n        } catch (e: java.lang.Exception) {\n            e.printStackTrace()\n        }\n        return actual\n    }\n\n    fun loadGalleryImage(url: String, imageView: ImageView) {\n        imageView.load(url){\n            crossfade(true)\n            crossfade(300)\n            diskCachePolicy(CachePolicy.ENABLED)\n            placeholder(R.drawable.ic_gal_pholder)\n            error(R.drawable.ic_broken_image)\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/ItemClickListener.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.view.View\n\ninterface ItemClickListener {\n    fun onItemClicked(v: View, position: Int)\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/LoadState.kt",
    "content": "package com.gowtham.letschat.utils\n\nsealed class LoadState {\n\n    class OnSuccess(val data: Any?=null): LoadState(){\n        override fun toString(): String {\n            return \"OnSuccess State\"\n        }\n    }\n\n    class OnFailure(val e: Exception): LoadState(){\n        override fun toString(): String {\n            return \"OnFailure State\"\n        }\n    }\n\n    object OnLoading : LoadState() {\n        override fun toString(): String {\n            return \"OnLoading State\"\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/LogInFailedState.kt",
    "content": "package com.gowtham.letschat.utils\n\nenum class LogInFailedState {\n    Verification,\n    SignIn\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/LogMessage.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.util.Log\nimport com.gowtham.letschat.BuildConfig.DEBUG\n\nobject LogMessage {\n\n    private val logVisible = DEBUG\n\n    internal fun v(msg: String) {\n        if (logVisible) Log.v(\"LetsChat\",msg)\n    }\n\n    internal fun e(msg: String) {\n        if (logVisible) Log.e(\"LetsChat\",msg)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/MPreference.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.content.Context\nimport android.content.SharedPreferences\nimport com.google.gson.Gson\nimport com.gowtham.letschat.models.ModelMobile\nimport com.gowtham.letschat.models.UserProfile\nimport dagger.hilt.android.qualifiers.ApplicationContext\nimport javax.inject.Inject\nimport javax.inject.Singleton\n\n@Singleton\nclass MPreference @Inject constructor(@ApplicationContext private val context: Context) {\n\n    private val UID = \"userId\"\n\n    private val LOGIN=\"login\"\n\n    private val USER=\"user\"\n\n    private val MOBILE=\"mobile\"\n\n    private val TOKEN=\"token\"\n\n    private val ONLINE_USER=\"online_user\"\n\n    private val ONLINE_GROUP=\"online_group\"\n\n    private val LOGIN_TIME=\"login_time\"\n\n    private val LAST_LOGGED_DEVICE_SAME=\"last_logged_device_same\"\n\n    private val PREFS_FILENAME = \"com.gowtham.letschat.prefs\"\n\n    private val sharedPreferences: SharedPreferences =\n        context.getSharedPreferences(PREFS_FILENAME, 0)\n\n    private val editor = sharedPreferences.edit()\n\n    private fun storeString(key: String, value: String) {\n        editor.run {\n            putString(key, value)\n            apply()\n        }\n    }\n\n    private fun storeLong(key: String, value: Long) {\n        editor.run {\n            putLong(key, value)\n            apply()\n        }\n    }\n\n    private fun storeBoolean(key: String, value: Boolean) =\n        editor.run {\n            putBoolean(key, value)\n            apply()\n        }\n\n    private fun getString(key: String) =\n        sharedPreferences.getString(key, \"\")\n\n    fun clearAll() =\n        editor?.run {\n            clear()\n            apply()\n        }\n\n    fun setLogin(){\n        storeBoolean(LOGIN, true)}\n\n    fun setLastDevice(same: Boolean){\n        storeBoolean(LAST_LOGGED_DEVICE_SAME, same)}\n\n    fun setLogInTime(){\n        storeLong(LOGIN_TIME,System.currentTimeMillis())\n    }\n\n    fun getLogInTime()=\n        sharedPreferences.getLong(LOGIN_TIME, 0)\n\n    fun setCurrentUser(id: String){\n        storeString(ONLINE_USER, id)\n    }\n\n    fun clearCurrentUser() {\n        setCurrentUser(\"\")\n    }\n\n    fun getOnlineUser(): String {\n        return getString(ONLINE_USER) ?: \"\"\n    }\n\n    fun setCurrentGroup(id: String){\n        storeString(ONLINE_GROUP, id)\n    }\n\n    fun clearCurrentGroup() {\n        setCurrentGroup(\"\")\n    }\n\n    fun getOnlineGroup(): String {\n        return getString(ONLINE_GROUP) ?: \"\"\n    }\n\n\n    fun isSameDevice()=\n        sharedPreferences.getBoolean(LAST_LOGGED_DEVICE_SAME, true)\n\n    fun isLoggedIn()= sharedPreferences.getBoolean(LOGIN, false)\n\n    fun isNotLoggedIn()= !isLoggedIn()\n\n    fun setUid(uid: String) =  storeString(UID, uid)\n\n    fun getUid()= getString(UID)\n\n    fun saveProfile(profile: UserProfile){\n        storeString(USER, Gson().toJson(profile))\n    }\n\n    fun saveMobile(mobile: ModelMobile){\n        storeString(MOBILE, Gson().toJson(mobile))\n    }\n\n    fun updatePushToken(token: String){\n        storeString(TOKEN, token)\n    }\n\n    fun getPushToken() = getString(TOKEN)\n\n    fun getUserProfile(): UserProfile?  {\n        val str=getString(USER)\n        if (str.isNullOrBlank())\n            return null\n        return Gson().fromJson(str, UserProfile::class.java)\n    }\n\n    fun getMobile(): ModelMobile?  {\n        val str=getString(MOBILE)\n        if (str.isNullOrBlank())\n            return null\n        return Gson().fromJson(str, ModelMobile::class.java)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/NActionReceiver.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.content.BroadcastReceiver\nimport android.content.Context\nimport android.content.Intent\nimport androidx.annotation.CallSuper\nimport androidx.core.app.RemoteInput\nimport com.google.firebase.firestore.CollectionReference\nimport com.gowtham.letschat.KEY_TEXT_REPLY\nimport com.gowtham.letschat.TYPE_NEW_MESSAGE\nimport com.gowtham.letschat.core.MessageSender\nimport com.gowtham.letschat.core.MessageStatusUpdater\nimport com.gowtham.letschat.core.OnMessageResponse\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.daos.MessageDao\nimport com.gowtham.letschat.db.data.ChatUserWithMessages\nimport com.gowtham.letschat.db.data.Message\nimport com.gowtham.letschat.db.data.TextMessage\nimport com.gowtham.letschat.di.MessageCollection\nimport com.gowtham.letschat.utils.Constants.ACTION_MARK_AS_READ\nimport com.gowtham.letschat.utils.Constants.ACTION_REPLY\nimport com.gowtham.letschat.utils.Constants.CHAT_DATA\nimport dagger.hilt.android.AndroidEntryPoint\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.serialization.encodeToString\nimport kotlinx.serialization.json.Json\nimport javax.inject.Inject\n\nabstract class HiltBroadcastReceiver : BroadcastReceiver(){\n    @CallSuper\n    override fun onReceive(context: Context?, intent: Intent?) { }\n}\n\n@AndroidEntryPoint\nclass NActionReceiver : HiltBroadcastReceiver(), OnMessageResponse {\n\n    @Inject\n    lateinit var preference: MPreference\n\n    @Inject\n    lateinit var messageDao: MessageDao\n\n    @Inject\n    lateinit var messageStatusUpdater: MessageStatusUpdater\n\n    @Inject\n    lateinit var dbRepo: DbRepository\n\n    @MessageCollection\n    @Inject\n    lateinit var messageCollection: CollectionReference\n\n    private var notificationId: Int=0\n\n    lateinit var context: Context\n\n    lateinit var chatUser: ChatUserWithMessages\n\n    private lateinit var myUserId: String\n\n    private lateinit var chatUserId: String\n\n    override fun onReceive(context: Context?, intent: Intent?) {\n        super.onReceive(context, intent)\n        try {\n            this.context=context!!\n            myUserId = preference.getUid()!!\n            chatUser = intent!!.getParcelableExtra(CHAT_DATA)!!\n            val notiIdString = chatUser.user.user.createdAt.toString()\n            //last 4 digits as notificationId\n            notificationId= notiIdString.substring(notiIdString.length - 4)\n                .toInt()\n\n            chatUserId = UserUtils.getChatUserId(myUserId, chatUser.messages.last())\n            if (intent.action == ACTION_MARK_AS_READ) {\n                chatUser.messages.let {\n                    messageStatusUpdater.updateToSeen(\n                        chatUserId,chatUser.user.documentId!!,it)\n                }\n                Utils.removeNotificationById(context, notificationId)\n                updateOnDb()\n            } else if (intent.action == ACTION_REPLY) {\n                val reply = getMessageText(intent)\n                if (reply.isNotBlank()) {\n                    val message = createMessage(reply, myUserId, chatUserId)\n                    message.chatUserId=chatUserId\n                    val messageSender = MessageSender(messageCollection,\n                        dbRepo,\n                        chatUser.user,\n                        this)\n                    messageSender.checkAndSend(myUserId, chatUserId, message)\n                }\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n\n    }\n\n    private fun updateOnDb() {\n        val list= chatUser.messages.filter {  it.status<3 && it.to==myUserId }.map {\n            it.status=3\n            it\n        }\n        //seen message other message of this user\n        chatUser.user.unRead=0\n        dbRepo.insertUser(chatUser.user)\n        CoroutineScope(Dispatchers.IO).launch {\n            dbRepo.insertMultipleMessage(list.toMutableList())\n        }\n    }\n\n    private fun createMessage(reply: String, myUserId: String,\n                              chatUserId: String): Message {\n        val profile = preference.getUserProfile()!!\n        val txtMessage = TextMessage(reply)\n        return Message(\n            System.currentTimeMillis(),\n            from = myUserId,\n            to = chatUserId,\n            senderName = profile.userName,\n            senderImage = profile.image,\n            textMessage = txtMessage,\n            status = 0\n        )\n    }\n\n    private fun getMessageText(intent: Intent): String {\n        return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY).toString()\n    }\n\n    override fun onSuccess(message: Message) {\n        Utils.removeNotificationById(context, notificationId)\n        //update to seen status\n        chatUser.messages.let {\n            messageStatusUpdater.updateToSeen(\n                chatUserId,chatUser.user.documentId!!,it)\n        }\n        updateOnDb()\n        val token=chatUser.user.user.token\n        if (token.isNotBlank())\n            UserUtils.sendPush(context, TYPE_NEW_MESSAGE,Json.encodeToString(message),token,message.to)\n        dbRepo.insertMessage(message)\n    }\n\n    override fun onFailed(message: Message) {\n        dbRepo.insertMessage(message)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/NotificationUtils.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.app.Notification\nimport android.app.PendingIntent\nimport android.content.Context\nimport android.content.Intent\nimport androidx.core.app.NotificationCompat\nimport androidx.core.app.NotificationManagerCompat\nimport androidx.core.app.Person\nimport androidx.core.app.RemoteInput\nimport com.gowtham.letschat.FirebasePush\nimport com.gowtham.letschat.GROUP_KEY\nimport com.gowtham.letschat.KEY_TEXT_REPLY\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.db.data.*\nimport com.gowtham.letschat.ui.activities.MainActivity\n\nobject NotificationUtils {\n\n    fun getSummaryNotification(context: Context,\n                                       manager: NotificationManagerCompat): Notification {\n        return Utils.createBuilder(context, manager,true)\n            .setContentTitle(\"emailObject.getSummary()\")\n            .setContentText(\"${FirebasePush.messageCount} new messages\")\n            .setSmallIcon(R.drawable.ic_stat_name)\n            .setStyle(\n                NotificationCompat.InboxStyle()\n                .addLine(\"Alex Faarborg Check this out\")\n                .addLine(\"Jeff Chang Launch Party\")\n                .addLine(\"Jeff Chang Launch Party\")\n                .setBigContentTitle(\"${FirebasePush.messageCount} new messages\")\n                .setSummaryText(\"${FirebasePush.messageCount} new messages from ${FirebasePush.personCount} friends\"))\n            .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN)\n            .setGroup(GROUP_KEY)\n            .setContentIntent(getHomeIntent(context))\n            .setGroupSummary(true)\n            .build()\n    }\n\n    fun getReplyAction(context: Context, user: ChatUserWithMessages): NotificationCompat.Action {\n        val replyLabel = \"Reply\"\n        val remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {\n            setLabel(replyLabel)\n            build()\n        }\n        return NotificationCompat.Action.Builder(\n            R.drawable.ic_send,\n            \"Reply\", getReplyPIntent(context,user))\n            .addRemoteInput(remoteInput)\n            .build()\n    }\n\n    fun getGroupReplyAction(context: Context, user: GroupWithMessages): NotificationCompat.Action {\n        val replyLabel = \"Reply\"\n        val remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {\n            setLabel(replyLabel)\n            build()\n        }\n        return NotificationCompat.Action.Builder(\n            R.drawable.ic_send,\n            \"Reply\", getGroupReplyPIntent(context,user))\n            .addRemoteInput(remoteInput)\n            .build()\n    }\n\n    private fun getHomeIntent(context: Context): PendingIntent {\n        val intent= Intent(context, MainActivity::class.java)\n        intent.flags = (Intent.FLAG_ACTIVITY_CLEAR_TASK\n                or Intent.FLAG_ACTIVITY_NEW_TASK)\n        return PendingIntent.getActivity(\n            context, 2, intent, PendingIntent.FLAG_ONE_SHOT or\n                    PendingIntent.FLAG_UPDATE_CURRENT)\n    }\n\n    fun getMarkAsPIntent(context: Context, user: ChatUserWithMessages): PendingIntent {\n        val snoozeIntent = Intent(context, NActionReceiver::class.java).apply {\n            putExtra(Constants.CHAT_DATA,user)\n            action = Constants.ACTION_MARK_AS_READ\n        }\n        return PendingIntent.getBroadcast(context, 1, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT)\n    }\n\n    private fun getReplyPIntent(context: Context, user: ChatUserWithMessages): PendingIntent {\n        val intent = Intent(context, NActionReceiver::class.java).apply {\n            putExtra(Constants.CHAT_DATA,user)\n            action = Constants.ACTION_REPLY\n        }\n\n        return PendingIntent.getBroadcast(context,\n            5,\n            intent,\n            PendingIntent.FLAG_UPDATE_CURRENT)\n    }\n\n    fun getGroupReplyPIntent(context: Context, user: GroupWithMessages): PendingIntent {\n        val intent = Intent(context, GroupMsgActionReceiver::class.java).apply {\n            putExtra(Constants.GROUP_DATA,user)\n            action = Constants.ACTION_REPLY\n        }\n        return PendingIntent.getBroadcast(context,\n            6,\n            intent,\n            PendingIntent.FLAG_UPDATE_CURRENT)\n    }\n\n     fun getGroupMarkAsPIntent(context: Context, user: GroupWithMessages): PendingIntent {\n        val snoozeIntent = Intent(context, GroupMsgActionReceiver::class.java).apply {\n            putExtra(Constants.GROUP_DATA,user)\n            action = Constants.ACTION_MARK_AS_READ\n        }\n        return PendingIntent.getBroadcast(context, 1, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT)\n    }\n\n     fun getPIntent(context: Context, user: ChatUser): PendingIntent {\n        val intent= Intent(context, MainActivity::class.java)\n        intent.action= Constants.ACTION_NEW_MESSAGE\n        intent.putExtra(Constants.CHAT_USER_DATA, user)\n        intent.flags = (Intent.FLAG_ACTIVITY_CLEAR_TASK\n                or Intent.FLAG_ACTIVITY_NEW_TASK)\n        return PendingIntent.getActivity(\n            context, 0, intent, PendingIntent.FLAG_ONE_SHOT or\n                    PendingIntent.FLAG_UPDATE_CURRENT)\n    }\n\n     fun getGroupMsgIntent(context: Context, group: Group): PendingIntent {\n        val intent= Intent(context, MainActivity::class.java)\n        intent.action= Constants.ACTION_GROUP_NEW_MESSAGE\n        intent.putExtra(Constants.GROUP_DATA, group)\n        intent.flags = (Intent.FLAG_ACTIVITY_CLEAR_TASK\n                or Intent.FLAG_ACTIVITY_NEW_TASK)\n        return PendingIntent.getActivity(\n            context, 0, intent, PendingIntent.FLAG_ONE_SHOT or\n                    PendingIntent.FLAG_UPDATE_CURRENT)\n    }\n\n     fun getStyle(context: Context, person: Person, user: ChatUserWithMessages)\n            : NotificationCompat.Style{\n        val style= NotificationCompat.MessagingStyle(person)\n        val chatPerson: Person = Person.Builder().setIcon(null)\n            .setKey(user.user.id).setName(user.user.localName).build()\n        val messages=user.messages.filter { it.status<3 && it.from!=MPreference(context).getUid()}\n        for (message in messages) {\n            FirebasePush.messageCount +=1\n            style.addMessage(BindingAdapters.getLastMsgTxt(message), message.createdAt, chatPerson)\n        }\n        return style\n    }\n\n     fun getGroupStyle(\n        context: Context, myUserId: String, person: Person, group: GroupWithMessages)\n            : NotificationCompat.Style{\n        val style= NotificationCompat.MessagingStyle(person)\n        val members=group.group.members ?: ArrayList()\n        val messages=group.messages\n        val filterMessages=messages.filter {\n            it.from != myUserId &&\n                    Utils.myMsgStatus(myUserId, it) < 3\n        }\n        if (filterMessages.isNotEmpty()) {\n            for (msg in filterMessages)\n                style.addMessage(getGroupMsg(members,msg), msg.createdAt,person)\n            FirebasePush.messageCount += 1\n        }\n        return style\n    }\n\n    private fun getGroupMsg(members: ArrayList<ChatUser>,\n                            msg: GroupMessage): String {\n        val user=members.first { it.id==msg.from }.localName\n        return \"$user : ${BindingAdapters.getLastMsgTxt(msg)}\"\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/OnSuccessListener.kt",
    "content": "package com.gowtham.letschat.utils\n\ninterface OnSuccessListener {\n    fun onResult(success: Boolean,data: Any?=null)\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/ScreenState.kt",
    "content": "package com.gowtham.letschat.utils\n\nsealed class ScreenState {\n\n    object IdleState : ScreenState(){\n        override fun toString(): String {\n            return \"IdleState State\"\n        }\n    }\n\n    object SearchState : ScreenState(){\n        override fun toString(): String {\n            return \"SearchState State\"\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/UserUtils.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.annotation.SuppressLint\nimport android.app.Activity\nimport android.content.Context\nimport android.content.pm.PackageManager\nimport android.os.Build\nimport android.provider.ContactsContract\nimport android.provider.Settings\nimport com.fcmsender.FCMSender\nimport com.google.firebase.auth.FirebaseAuth\nimport com.google.firebase.database.FirebaseDatabase\nimport com.google.firebase.firestore.CollectionReference\nimport com.google.firebase.firestore.DocumentReference\nimport com.google.firebase.firestore.FirebaseFirestore\nimport com.google.firebase.firestore.Query\nimport com.google.firebase.installations.FirebaseInstallations\nimport com.google.firebase.ktx.Firebase\nimport com.google.firebase.storage.StorageReference\nimport com.google.firebase.storage.ktx.storage\nimport com.gowtham.letschat.MApplication\nimport com.gowtham.letschat.core.*\nimport com.gowtham.letschat.db.ChatUserDatabase\nimport com.gowtham.letschat.db.DbRepository\nimport com.gowtham.letschat.db.daos.GroupDao\nimport com.gowtham.letschat.db.daos.GroupMessageDao\nimport com.gowtham.letschat.db.data.*\nimport com.gowtham.letschat.fragments.group_chat_home.AdGroupChatHome\nimport com.gowtham.letschat.fragments.single_chat_home.AdSingleChatHome\nimport com.gowtham.letschat.models.Contact\nimport com.gowtham.letschat.models.ModelDeviceDetails\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.models.UserStatus\nimport com.gowtham.letschat.ui.activities.ActSplash\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.withContext\nimport kotlinx.serialization.decodeFromString\nimport kotlinx.serialization.json.Json\nimport org.greenrobot.eventbus.EventBus\nimport org.json.JSONObject\nimport timber.log.Timber\nimport java.util.*\nimport kotlin.collections.ArrayList\nimport kotlin.collections.HashMap\nimport kotlin.system.measureNanoTime\n\nobject UserUtils {\n\n    var queriedList=ArrayList<UserProfile>()\n\n    var resultCount=0\n\n    const val NOTIFICATION_ID=22\n\n    var totalRecursionCount=0\n\n    fun updatePushToken(context: Context,userCollection: CollectionReference, isSave: Boolean) {\n        try {\n            if (Utils.isNetConnected(context)) {\n                FirebaseInstallations.getInstance().getToken(false).addOnSuccessListener { result->\n                    MPreference(context).updatePushToken(result.token)\n                    if (isSave)\n                        updateDeviceDetails(context,userCollection)\n                }\n            }\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    private fun updateDeviceDetails(context: Context,userCollection: CollectionReference) {\n        val preference = MPreference(context)\n        val token = preference.getPushToken()\n        Timber.v(\"AAA ${preference.getUid()}\")\n        Timber.v(\"BB ${preference.getUserProfile()?.uId}\")\n        if (token.isNullOrEmpty())\n            updatePushToken(context,userCollection, true)\n        else if (Utils.isNetConnected(context)) {\n            val profile = preference.getUserProfile()?.apply {\n                this.token=token\n                this.deviceDetails=\n                    Json.decodeFromString<ModelDeviceDetails>(getDeviceInfo(context).toString())\n            }\n            val updateData = hashMapOf(\n                \"token\" to token,\n                \"updatedAt\" to System.currentTimeMillis(),\n                \"device_details\" to Json.decodeFromString<ModelDeviceDetails>(getDeviceInfo(context).toString()),\n            )\n            userCollection.document(preference.getUid()!!).update(updateData).addOnSuccessListener {\n                preference.saveProfile(profile!!)\n                LogMessage.v(\"Token Updated $token##\")\n            }\n        }\n    }\n\n    fun getStorageRef(context: Context): StorageReference {\n        val preference = MPreference(context)\n        val ref = Firebase.storage.getReference(\"Users\")\n        return ref.child(preference.getUid().toString())\n    }\n\n    fun getDocumentRef(context: Context): DocumentReference {\n        val preference = MPreference(context)\n        val db = FirebaseFirestore.getInstance()\n        return db.collection(\"Users\").document(preference.getUid()!!)\n    }\n\n    fun getMessageSubCollectionRef(): Query {\n        val db = FirebaseFirestore.getInstance()\n        return db.collectionGroup(\"messages\")\n    }\n\n    fun getGroupMsgSubCollectionRef(): Query {\n        val db = FirebaseFirestore.getInstance()\n        return db.collectionGroup(\"group_messages\")\n    }\n\n    fun fetchContacts(context: Context): List<Contact> {\n        val preference=MPreference(context)\n        val names = ArrayList<String>()\n        val numbers = ArrayList<String>()\n        val contacts=ArrayList<Contact>()\n        val uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI\n        val projection = arrayOf(\n            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,\n            ContactsContract.CommonDataKinds.Phone.NUMBER\n        )\n        val selection: String? =\n            null //it's like a where concept in mysql\n        val selectionArgs: Array<String>? = null\n        val sortOrder: String? = null\n        val resolver = context.contentResolver\n        val cursor = resolver.query(uri, projection, selection, selectionArgs, sortOrder)\n        while (cursor!!.moveToNext()) {\n            val name =\n                cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))\n            val number =\n                cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))\n            if(number.contains(preference.getMobile()!!.number))\n                continue\n            names.add(name)\n            numbers.add(number)\n            contacts.add(Contact(name, number))\n        }\n        cursor.close()\n        val hashMap=getCountryCodeRemovedList(context, contacts)\n        contacts.clear()\n        for (number in hashMap.keys){\n            contacts.add(Contact(hashMap[number].toString(), number))\n        }\n        return contacts.sortedWith(compareBy { it.name })\n    }\n\n    private fun getCountryCodeRemovedList(context: Context, contacts: ArrayList<Contact>): HashMap<String, String> {\n        val hashMap:HashMap<String, String> = HashMap() //hashmap to get rid of duplication\n        val preference=MPreference(context)\n        contacts.forEach { contact ->\n            if (contact.mobile.length <= 5 ||\n                contact.mobile.contains(preference.getMobile()?.number!!))\n                return@forEach\n            var mobile=contact.mobile\n            for (country in Countries.getCountries()) {\n                if (mobile.contains(country.noCode)) {\n                    mobile = contact.mobile.replace(country.noCode, \"\")\n                    break\n                }\n            }\n            hashMap[mobile.replace(\" \", \"\")] = contact.name\n        }\n        return hashMap\n    }\n\n    fun getDeviceInfo(context: Context): JSONObject {\n        try {\n            val deviceInfo = JSONObject()\n            deviceInfo.put(\"device_id\", getDeviceId(context))\n            deviceInfo.put(\"device_model\", Build.MODEL)\n            deviceInfo.put(\"device_brand\", Build.BOARD)\n            deviceInfo.put(\"device_country\", Locale.getDefault())\n            deviceInfo.put(\"device_os_v\", Build.VERSION.RELEASE)\n            deviceInfo.put(\"app_version\", getVersionName(context))\n            deviceInfo.put(\"package_name\", context.packageName)\n            deviceInfo.put(\"device_type\", \"android\")\n            return deviceInfo\n        } catch (e: java.lang.Exception) {\n            e.printStackTrace()\n        }\n        return JSONObject()\n    }\n\n    @SuppressLint(\"HardwareIds\")\n    fun getDeviceId(context: Context): String? {\n        return Settings.Secure.getString(\n            context.contentResolver,\n            Settings.Secure.ANDROID_ID\n        )\n    }\n\n    private fun getVersionName(context: Context): String? {\n        try {\n            val packageName = context.packageName\n            val pInfo = context.packageManager.getPackageInfo(packageName, 0)\n            return pInfo.versionName\n        } catch (e: PackageManager.NameNotFoundException) {\n            e.printStackTrace()\n        }\n        return \"1.0\"\n    }\n\n    fun logOut(context: Activity, preference: MPreference,db: ChatUserDatabase) {\n        try {\n            CoroutineScope(Dispatchers.IO).launch {\n                db.clearAllTables()\n            }\n            EventBus.getDefault().post(UserStatus(\"offline\"))\n            ChatHandler.removeListeners()\n            GroupChatHandler.removeListener()\n            ChatUserProfileListener.removeListener()\n            AdSingleChatHome.allChatList= emptyList<ChatUserWithMessages>().toMutableList()\n            AdGroupChatHome.allList= emptyList<GroupWithMessages>().toMutableList()\n            FirebaseAuth.getInstance().signOut()\n            preference.clearAll()\n            Utils.startNewActivity(context, ActSplash::class.java)\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun sendPush(context: Context, type: String,body: String, token: String,to: String) {\n        try {\n            val data=JSONObject()\n            val pushData=JSONObject()\n            data.put(\"type\", type)\n            data.put(\"message_body\",body)\n            data.put(\"to\",to)\n            pushData.put(\"data\",data)\n            val push = FCMSender.Builder()\n                .serverKey(Constants.FCM_SERVER_KEY)\n                .setData(pushData)\n                .toTokenOrTopic(token)\n                .responseListener(object : FCMSender.ResponseListener {\n                    override fun onFailure(errorCode: Int,message: String) {\n                        LogMessage.v(\"notification sent Failed to $token\")\n                    }\n\n                    override fun onSuccess(response: String) {\n                        LogMessage.v(\"notification sent Successfully to $token\")\n                    }\n                }).build()\n            push.sendPush(context)\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun setUnReadCountZero(repo: DbRepository, chatUser: ChatUser) {\n        try {\n            val time= measureNanoTime {\n                chatUser.unRead=0\n                repo.insertUser(chatUser)\n            }\n            Timber.v(\"Taken time $time\")\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n\n    fun getChatUserId(fromUser: String, message: Message)= if (message.from != fromUser) message.from\n    else message.to\n\n    fun sendTypingStatus(database: FirebaseDatabase, isTyping: Boolean, vararg users: String) {\n        try {\n            val typingRef = database.getReference(\"/Users/${users[0]}/typing_status\")\n            val chatUserRef = database.getReference(\"/Users/${users[0]}/chatuser\")\n            typingRef.setValue(if (isTyping) \"typing\" else \"not_typing\")\n            chatUserRef.setValue(users[1])\n            typingRef.onDisconnect().setValue(\"not_typing\")\n            chatUserRef.onDisconnect().setValue(\"\")\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n    }\n\n    fun updateContactsProfiles(listener :QueryCompleteListener?): Boolean {\n        Timber.v(\"Query Called\")\n        val allContacts = fetchContacts(MApplication.appContext).toMutableList()\n        val listOfMobiles = ArrayList<String>()\n        allContacts.forEach {\n            listOfMobiles.add(it.mobile)\n        }\n        if(listOfMobiles.isEmpty())\n            return false\n        return makeQueryRecursively(listOfMobiles, 1,listener ?: onQueryCompleted)\n    }\n\n    private tailrec fun makeQueryRecursively(listOfMobNos: ArrayList<String>, position: Int\n                                             ,listener :QueryCompleteListener): Boolean {\n        val firstTen = ArrayList<String>()\n        val size = if (listOfMobNos.size < 10) listOfMobNos.size else 10\n        for (index in 0 until size)\n            firstTen.add(listOfMobNos[index])\n        listOfMobNos.subList(0, size).clear()  //remove queried elements\n        val contactsQuery = ContactsQuery(firstTen, position,listener)\n        contactsQuery.makeQuery()\n\n        return if (listOfMobNos.isEmpty()) {\n            totalRecursionCount=position\n            LogMessage.v(\"Queried times $position\")\n            true\n        }else makeQueryRecursively(listOfMobNos, position + 1,listener)\n    }\n\n    fun getChatUser(\n        doc: UserProfile,\n        chatUsers: List<ChatUser>,\n        savedName: String): ChatUser {\n        var existData: ChatUser? = null\n        if (chatUsers.isNotEmpty()) {\n            val contact = chatUsers.firstOrNull { it.id == doc.uId }\n            contact?.let {\n                existData=it\n            }\n        }\n        return existData?.apply {\n            user = doc\n            localName = savedName\n            locallySaved=true\n        } ?: ChatUser(doc.uId.toString(), savedName, doc,locallySaved = true)\n    }\n\n\n    private val onQueryCompleted=object : QueryCompleteListener {\n        override fun onQueryCompleted(queriedList: ArrayList<UserProfile>) {\n            try {\n                Timber.v(\"onQueryCompleted ${queriedList.size}\")\n                val localContacts= fetchContacts(MApplication.appContext)\n                val finalList = ArrayList<ChatUser>()\n                //set localsaved name to queried users\n                CoroutineScope(Dispatchers.IO).launch {\n                    val chatUsers=MApplication.userDaoo.getChatUserList()\n                    withContext(Dispatchers.Main){\n                        for(doc in queriedList){\n                            val savedNumber=localContacts.firstOrNull { it.mobile == doc.mobile?.number }\n                            if(savedNumber!=null){\n                                val chatUser=getChatUser(doc,chatUsers,savedNumber.name)\n                                finalList.add(chatUser)\n                            }\n                        }\n                        setDefaultValues()\n                        withContext(Dispatchers.IO){\n                            MApplication.userDaoo.insertMultipleUser(finalList)\n                        }\n                    }\n                }\n            } catch (e: Exception) {\n                e.printStackTrace()\n            }\n        }\n    }\n\n    private fun setDefaultValues() {\n        totalRecursionCount =0\n        resultCount =0\n        queriedList.clear()\n    }\n\n    fun setUnReadCountGroup(groupDao: GroupDao, group: Group) {\n        CoroutineScope(Dispatchers.IO).launch {\n            group.unRead=0\n            groupDao.insertGroup(group)\n        }\n    }\n\n    fun insertGroupMsg(groupMsgDao: GroupMessageDao, message: GroupMessage) {\n        CoroutineScope(Dispatchers.IO).launch {\n            groupMsgDao.insertMessage(message)\n        }\n    }\n\n    fun insertMutlipleGroupMsg(groupMsgDao: GroupMessageDao, messages: List<GroupMessage>) {\n        CoroutineScope(Dispatchers.IO).launch {\n            groupMsgDao.insertMultipleMessage(messages)\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/Utils.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.annotation.SuppressLint\nimport android.app.*\nimport android.content.Context\nimport android.content.Intent\nimport android.content.pm.PackageManager\nimport android.graphics.Color\nimport android.media.AudioAttributes\nimport android.media.RingtoneManager\nimport android.net.ConnectivityManager\nimport android.net.NetworkCapabilities\nimport android.os.Build\nimport android.view.View\nimport android.view.ViewGroup\nimport android.view.inputmethod.InputMethodManager\nimport android.widget.EditText\nimport android.widget.TextView\nimport androidx.core.app.NotificationCompat\nimport androidx.core.app.NotificationManagerCompat\nimport androidx.core.content.ContextCompat\nimport androidx.fragment.app.Fragment\nimport com.google.gson.Gson\nimport com.google.gson.GsonBuilder\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.db.ChatUserDatabase\nimport com.gowtham.letschat.db.data.GroupMessage\nimport com.gowtham.letschat.models.Country\nimport com.gowtham.letschat.models.UserStatus\nimport java.text.SimpleDateFormat\n\nobject Utils {\n\n    private const val PERMISSION_REQ_CODE = 114\n\n  /*  private const val MIN: Long=1000 * 60\n    private const val HOUR= MIN * 60\n    private const val DAY= HOUR* 24\n    private const val WEEK= DAY * 7\n    private const val MONTH= WEEK * 4\n    private const val YEAR= MONTH * 12*/\n\n    fun getDefaultCountry() = Country(\"IN\", \"India\", \"+91\", \"INR\")\n\n    fun clearNull(str: String?) = str?.trim() ?: \"\"\n\n    @Suppress(\"DEPRECATION\")\n    fun isNetConnected(context: Context): Boolean {\n        val connectivityManager =\n            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager\n        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {\n            val capabilities =\n                connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)\n            (capabilities != null &&\n                    ((capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) ||\n                            capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||\n                            capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)))\n        } else {\n            val activeNetworkInfo = connectivityManager.activeNetworkInfo\n            (activeNetworkInfo != null && activeNetworkInfo.isConnected)\n        }\n    }\n\n    fun isNoInternet(context: Context) = !isNetConnected(context)\n\n    fun getColor(context: Context, color: Int): Int {\n        return ContextCompat.getColor(context, color)\n    }\n\n    fun checkPermission(context: Fragment,\n                        vararg permissions: String,reqCode: Int= PERMISSION_REQ_CODE): Boolean {\n        var allPermitted = false\n        for (permission in permissions) {\n            allPermitted = (ContextCompat.checkSelfPermission(context.requireContext(), permission)\n                    == PackageManager.PERMISSION_GRANTED)\n            if (!allPermitted) break\n        }\n        if (allPermitted) return true\n        context.requestPermissions(\n            permissions,\n            reqCode\n        )\n        return false\n    }\n\n    fun getGSONObj(): Gson {\n        return GsonBuilder().create()\n    }\n\n/*    fun <T> fromGson(json: String?, className: Class<T>?): T {\n        return getGSONObj().fromJson(json, className)\n    }*/\n\n    fun isPermissionOk(vararg results: Int): Boolean {\n        var isAllGranted = true\n        for (result in results) {\n            if (PackageManager.PERMISSION_GRANTED != result) {\n                isAllGranted = false\n                break\n            }\n        }\n        return isAllGranted\n    }\n\n    fun startNewActivity(activity: Activity, className: Class<*>?) {\n        val intent = Intent(activity, className)\n        intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or\n                Intent.FLAG_ACTIVITY_CLEAR_TOP or\n                Intent.FLAG_ACTIVITY_NEW_TASK\n        activity.startActivity(intent)\n        activity.finish()\n    }\n\n    fun askContactPermission(context: Fragment): Boolean {\n        return checkPermission(\n            context, android.Manifest.permission.READ_CONTACTS,\n            android.Manifest.permission.WRITE_CONTACTS\n        )\n    }\n\n    fun isContactPermissionOk(context: Context): Boolean{\n        return (ContextCompat.checkSelfPermission(context, android.Manifest.permission.READ_CONTACTS)\n                == PackageManager.PERMISSION_GRANTED) &&\n                (ContextCompat.checkSelfPermission(\n                    context,\n                    android.Manifest.permission.WRITE_CONTACTS\n                )\n                        == PackageManager.PERMISSION_GRANTED)\n    }\n\n    fun showLoggedInAlert(\n        context: Activity, preference: MPreference,\n        db: ChatUserDatabase) {\n        try {\n            val dialog = Dialog(context)\n            dialog.setCancelable(false)\n            dialog.setContentView(R.layout.alert_dialog)\n            dialog.window!!.setLayout(\n                ViewGroup.LayoutParams.MATCH_PARENT,\n                ViewGroup.LayoutParams.WRAP_CONTENT\n            )\n            dialog.findViewById<TextView>(R.id.txt_log_out).setOnClickListener {\n                dialog.dismiss()\n                UserUtils.logOut(context, preference, db)\n            }\n            dialog.show()\n        } catch (e: Exception) {\n        }\n    }\n\n   /* fun dpToPx(dp: Int): Int {\n        return (dp * Resources.getSystem().displayMetrics.density).toInt()\n    }\n*/\n    fun setOnlineStatus(txtView: TextView, status: UserStatus, uId: String) {\n        txtView.visibility= View.VISIBLE\n        txtView.text= when {\n            status.typing_status==\"typing\" && uId==status.chatuser -> {\n                \"typing...\"\n            }\n            status.status==\"online\" -> {\n                \"online\"\n            }\n            status.last_seen>0L -> {\n                \"last seen ${getLastSeen(status.last_seen)}\"\n            }\n            else -> {\n                \"...\"\n            }\n        }\n    }\n\n    fun createBuilder(\n        context: Context,\n        manager: NotificationManagerCompat,\n        isSummary: Boolean = false\n    ): NotificationCompat.Builder {\n        val channelId = context.packageName\n        val notBuilder = NotificationCompat.Builder(context, channelId)\n        notBuilder.setSmallIcon(R.drawable.ic_stat_name)\n        notBuilder.setAutoCancel(true)\n        notBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)\n        notBuilder.setDefaults(Notification.DEFAULT_ALL)\n        notBuilder.priority = NotificationCompat.PRIORITY_HIGH\n        val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)\n        notBuilder.setSound(soundUri)\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n            val importance=if (isSummary) NotificationManager.IMPORTANCE_HIGH else\n                NotificationManager.IMPORTANCE_DEFAULT\n            val channel = NotificationChannel(\n                channelId, context.getString(R.string.txt_notifications),\n                importance\n            )\n            channel.importance =importance\n            channel.shouldShowLights()\n            channel.lightColor = Color.BLUE\n            channel.canBypassDnd()\n            val audioAttributes = AudioAttributes.Builder()\n                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)\n                .setUsage(AudioAttributes.USAGE_NOTIFICATION)\n                .build()\n            channel.setSound(soundUri, audioAttributes)\n            channel.description = context.getString(R.string.txt_not_description)\n            notBuilder.setChannelId(channelId)\n            manager.createNotificationChannel(channel)\n        }\n        return notBuilder\n    }\n\n    fun returnNManager(context: Context): NotificationManagerCompat {\n        return NotificationManagerCompat.from(context)\n    }\n\n    fun removeNotification(context: Context){\n        val manager= returnNManager(context)\n        manager.cancelAll()\n    }\n\n    fun removeNotificationById(context: Context, id: Int){\n        val manager= returnNManager(context)\n        manager.cancel(id)\n    }\n\n    fun getGroupName(groupId: String) =\n        groupId.substring(0, groupId.lastIndexOf(\"_\"))\n\n    fun closeKeyBoard(activity: Activity){\n        val view=activity.currentFocus\n        val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager\n        view?.let {\n            imm.hideSoftInputFromWindow(it.windowToken, 0)\n        }\n    }\n\n    fun showSoftKeyboard(activity: Activity, view: View) {\n        if (view.requestFocus()) {\n            val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager\n            imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)\n        }\n    }\n\n    fun myMsgStatus(myUserId: String, msg: GroupMessage): Int{\n        val indexOfMine=myIndexOfStatus(myUserId, msg)\n        return msg.status[indexOfMine]\n    }\n\n    fun myIndexOfStatus(myUserId: String, msg: GroupMessage): Int{\n        return msg.to.indexOf(myUserId)\n    }\n\n    @SuppressLint(\"SimpleDateFormat\")\n    fun getTime(sentTime: Long): String{\n        val currentTime=System.currentTimeMillis()\n        val dayCount = (currentTime - sentTime)/(24 * 60 * 60 * 1000)\n        val calender= java.util.Calendar.getInstance()\n        calender.timeInMillis=sentTime\n        val date=calender.time\n        return when{\n            dayCount> 1L -> {\n                //DD/MM/YYYY format\n                SimpleDateFormat(\"dd/MMM/yyyy\").format(date)\n            }\n            dayCount==1L -> {\n                \"Yesterday\"\n            }\n            else->{\n                //hh:mm aa\n                SimpleDateFormat(\"hh:mm aa\").format(date)\n            }\n        }\n    }\n\n    @SuppressLint(\"SimpleDateFormat\")\n    fun getLastSeen(lastSeen: Long): String{\n        val currentTime=System.currentTimeMillis()\n        val dayCount = (currentTime - lastSeen)/(24 * 60 * 60 * 1000)\n        val calender= java.util.Calendar.getInstance()\n        calender.timeInMillis=lastSeen\n        val date=calender.time\n        return when{\n            dayCount> 1L -> {\n                //DD/MM/YYYY format\n                SimpleDateFormat(\"dd/MMM/yyyy\").format(date)\n            }\n            dayCount==1L -> {\n                \"yesterday ${SimpleDateFormat(\"hh:mm aa\").format(date)}\"\n            }\n            else->{\n                //hh:mm aa\n                \"today ${SimpleDateFormat(\"hh:mm aa\").format(date)}\"\n            }\n        }\n    }\n\n    fun edtValue(edtMsg: EditText): String {\n      return edtMsg.text!!.trim().toString()\n    }\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/Validator.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport com.google.i18n.phonenumbers.PhoneNumberUtil\nimport com.google.i18n.phonenumbers.Phonenumber.PhoneNumber\n\nobject Validator {\n\n    fun isValidNo(code: String, mobileNo: String): Boolean {\n        try {\n            val phoneUtil = PhoneNumberUtil.getInstance()\n            val phNumberProto: PhoneNumber = phoneUtil.parse(\n                mobileNo, code\n            )\n            return phoneUtil.isValidNumber(phNumberProto)\n        } catch (e: Exception) {\n            e.printStackTrace()\n        }\n        return false\n    }\n\n    fun isMobileNumberEmpty(mobileNo: String?): Boolean{\n        return mobileNo.isNullOrEmpty()\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/utils/ViewUtils.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.app.Activity\nimport android.content.Context\nimport android.os.Handler\nimport android.os.Looper\nimport android.text.Editable\nimport android.util.Log\nimport android.view.View\nimport android.widget.EditText\nimport android.widget.ProgressBar\nimport android.widget.Toast\nimport androidx.navigation.NavController\nimport androidx.recyclerview.widget.ListAdapter\nimport androidx.recyclerview.widget.RecyclerView\nimport com.google.android.material.snackbar.Snackbar\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.db.data.Message\nimport com.gowtham.letschat.views.CustomProgressView\nimport timber.log.Timber\n\nfun String.printMeD(){\n    Log.d(\"LetsChat:: \",this)\n}\n\nfun Context.toast(msg: String){\n   Toast.makeText(this,msg,Toast.LENGTH_SHORT).show()\n}\n\nfun Context.toastLong(msg: String){\n    Toast.makeText(this,msg,Toast.LENGTH_LONG).show()\n}\n\nfun Context.toast(msg: Int){\n    Toast.makeText(this,getString(msg),Toast.LENGTH_SHORT).show()\n}\n\nfun Context.toastNet(){\n    Toast.makeText(this,R.string.err_no_net,Toast.LENGTH_SHORT).show()\n}\n\nfun snack(context: Activity,msg: String){\n    Snackbar.make(context.findViewById(android.R.id.content),msg,2000).show()\n}\n\nfun snackNet(context: Activity){\n    Snackbar.make(context.findViewById(android.R.id.content),R.string.err_no_net,2000).show()\n}\n\nfun View.gone(){\n    this.visibility=View.GONE\n}\n\nfun View.show(){\n    this.visibility=View.VISIBLE\n}\n\nfun List<Message>.getUnreadCount(userId: String): Int {\n   return this.filter { it.from==userId &&\n            it.status<3 }.size\n}\n\nfun View.hide(){\n    this.visibility=View.INVISIBLE\n}\n\nfun CustomProgressView.toggle(show: Boolean){\n    if (show)\n        this.show()\n    else\n        this.dismiss();\n}\n\nfun CustomProgressView.dismissIfShowing(){\n    if (this.isShowing)\n        this.dismiss()\n}\n\nfun ProgressBar.toggle(show: Boolean){\n    if (show)\n        this.show()\n    else\n        this.gone();\n}\n\nfun EditText.trim() =\n    this.text.toString().trim()\n\nfun Char.toEditable(): Editable =  Editable.Factory.getInstance().newEditable(this.toString())\n\nfun NavController.isValidDestination(destination: Int): Boolean {\n    return destination == this.currentDestination!!.id\n}\n\nfun RecyclerView.smoothScrollToPos(position: Int) {\n    Handler(Looper.getMainLooper()).postDelayed({\n        this.smoothScrollToPosition(position)\n    }, 300)\n}\n\n\nfun <T, VH : RecyclerView.ViewHolder> ListAdapter<T, VH>.updateList(list: List<T>?) {\n    this.submitList(\n        if (list == this.currentList) {\n            Timber.v(\"Same list\")\n            list.toList()\n        } else {\n            Timber.v(\"Not Same list\")\n            list\n        }\n    )\n}\n\nfun  <T, VH : RecyclerView.ViewHolder> ListAdapter<T,VH>.addRestorePolicy(){\n    stateRestorationPolicy =\n        RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY\n}\n"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/views/CustomEditText.kt",
    "content": "package com.gowtham.letschat.views\n\nimport android.content.Context\nimport android.os.Build\nimport android.os.Bundle\nimport android.util.AttributeSet\nimport android.view.inputmethod.EditorInfo\nimport android.view.inputmethod.InputConnection\nimport androidx.appcompat.widget.AppCompatEditText\nimport androidx.core.os.BuildCompat\nimport androidx.core.view.inputmethod.EditorInfoCompat\nimport androidx.core.view.inputmethod.InputConnectionCompat\nimport androidx.core.view.inputmethod.InputConnectionCompat.OnCommitContentListener\nimport androidx.core.view.inputmethod.InputContentInfoCompat\n\n\nclass CustomEditText : AppCompatEditText {\n    lateinit var imgTypeString: Array<String>\n    private var keyBoardInputCallbackListener: KeyBoardInputCallbackListener? = null\n\n    constructor(context: Context) : super(context) {\n        initView()\n    }\n\n    constructor(context: Context, attrs: AttributeSet?) :\n            super(context, attrs) {\n        initView()\n    }\n\n    private fun initView() {\n        imgTypeString = arrayOf(\n            \"image/png\",\n            \"image/gif\",\n            \"image/jpeg\",\n            \"image/webp\"\n        )\n    }\n\n    override fun onCreateInputConnection(outAttrs: EditorInfo?): InputConnection {\n        val ic: InputConnection = super.onCreateInputConnection(outAttrs)!!\n        EditorInfoCompat.setContentMimeTypes(\n            outAttrs!!,\n            imgTypeString\n        )\n        return InputConnectionCompat.createWrapper(ic, outAttrs, callback)\n    }\n\n    val callback =\n        OnCommitContentListener { inputContentInfo, flags, opts ->\n            // read and display inputContentInfo asynchronously\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 && flags and\n                InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION != 0) {\n                try {\n                    inputContentInfo.requestPermission()\n                } catch (e: Exception) {\n                    return@OnCommitContentListener false // return false if failed\n                }\n            }\n            var supported = false\n            for (mimeType in imgTypeString) {\n                if (inputContentInfo.description.hasMimeType(mimeType)) {\n                    supported = true\n                    break\n                }\n            }\n            if (!supported)\n                return@OnCommitContentListener false\n            keyBoardInputCallbackListener?.onCommitContent(inputContentInfo, flags, opts)\n            true // return true if succeeded\n        }\n\n    interface KeyBoardInputCallbackListener {\n        fun onCommitContent(\n            inputContentInfo: InputContentInfoCompat?,\n            flags: Int, opts: Bundle?\n        )\n    }\n\n    fun setKeyBoardInputCallbackListener(keyBoardInputCallbackListener: KeyBoardInputCallbackListener?) {\n        this.keyBoardInputCallbackListener = keyBoardInputCallbackListener\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/views/CustomProgress.kt",
    "content": "package com.gowtham.letschat.views\n\nimport android.content.Context\nimport android.graphics.BlendMode\nimport android.graphics.BlendModeColorFilter\nimport android.graphics.PorterDuff\nimport android.os.Build\nimport android.util.AttributeSet\nimport android.widget.ProgressBar\nimport androidx.annotation.RequiresApi\nimport com.gowtham.letschat.R\nimport com.gowtham.letschat.utils.Utils\n\n@Suppress(\"DEPRECATION\")\nclass CustomProgress : ProgressBar {\n    constructor(context: Context) : super(context) {\n        setTintColor(context)\n    }\n\n    constructor(\n        context: Context,\n        attrs: AttributeSet?\n    ) : super(context, attrs) {\n        setTintColor(context)\n    }\n\n    constructor(\n        context: Context,\n        attrs: AttributeSet?,\n        defStyleAttr: Int\n    ) : super(context, attrs, defStyleAttr) {\n        setTintColor(context)\n    }\n\n    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)\n    constructor(\n        context: Context,\n        attrs: AttributeSet?,\n        defStyleAttr: Int,\n        defStyleRes: Int\n    ) : super(context, attrs, defStyleAttr, defStyleRes) {\n        setTintColor(context)\n    }\n\n    private fun setTintColor(context: Context) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {\n            this.indeterminateDrawable.colorFilter = BlendModeColorFilter(\n                Utils.getColor(\n                    context, R.color.colorTheme\n                ), BlendMode.SRC_ATOP\n            )\n        } else {\n            this.indeterminateDrawable.setColorFilter(\n                Utils.getColor(\n                    context, R.color.colorTheme\n                ), PorterDuff.Mode.MULTIPLY\n            )\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/views/CustomProgressView.kt",
    "content": "package com.gowtham.letschat.views\n\nimport android.app.Dialog\nimport android.content.Context\nimport android.graphics.Color\nimport android.graphics.drawable.ColorDrawable\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.view.Window\nimport com.gowtham.letschat.R\n\nclass CustomProgressView constructor(context: Context) :\n    Dialog(context) {\n    init {\n        val view: View =\n            LayoutInflater.from(context).inflate(R.layout.progress_dialog, null)\n        requestWindowFeature(Window.FEATURE_NO_TITLE)\n        this.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)\n        this.window?.setBackgroundDrawable(\n            ColorDrawable(Color.TRANSPARENT)\n        )\n        setCancelable(false)\n        this.setContentView(view)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/views/MainNavHostFragment.kt",
    "content": "package com.gowtham.letschat.views\n\nimport android.content.Context\nimport androidx.navigation.fragment.NavHostFragment\nimport com.gowtham.letschat.fragments.MainFragmentFactory\nimport dagger.hilt.android.AndroidEntryPoint\nimport javax.inject.Inject\n\n@AndroidEntryPoint\nclass MainNavHostFragment : NavHostFragment(){\n\n    @Inject\n    lateinit var fragmentFactory: MainFragmentFactory\n\n    override fun onAttach(context: Context) {\n        super.onAttach(context)\n        childFragmentManager.fragmentFactory = fragmentFactory\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/views/PausableProgressBar.kt",
    "content": "package com.gowtham.letschat.views\n\nimport android.content.Context\nimport android.util.AttributeSet\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.animation.Animation\nimport android.view.animation.LinearInterpolator\nimport android.widget.FrameLayout\nimport com.gowtham.letschat.R\n\nclass PausableProgressBar @JvmOverloads constructor(\n    context: Context,\n    attrs: AttributeSet? = null,\n    defStyleAttr: Int = 0\n) : FrameLayout(context, attrs, defStyleAttr) {\n\n    private var frontProgressView: View? = null\n    private var maxProgressView: View? = null\n    private var animation: PausableScaleAnimation? = null\n    private var duration = DEFAULT_PROGRESS_DURATION.toLong()\n    private var callback: Callback? = null\n    private var isStarted = false\n\n    init {\n        LayoutInflater.from(context).inflate(R.layout.pausable_progress, this)\n        frontProgressView = findViewById(R.id.front_progress)\n        maxProgressView = findViewById(R.id.max_progress)\n    }\n\n    fun setDuration(duration: Long) {\n        this.duration = duration\n        if (animation != null){\n            animation = null\n            startProgress()\n        }\n    }\n\n    fun setCallback(callback: Callback) {\n        this.callback = callback\n    }\n\n    fun setMax() {\n        finishProgress(true)\n    }\n\n    fun setMin() {\n        finishProgress(false)\n    }\n\n    fun setMinWithoutCallback() {\n        maxProgressView!!.setBackgroundResource(R.color.progress_secondary)\n        maxProgressView!!.visibility = View.VISIBLE\n        if (animation != null) {\n            animation!!.setAnimationListener(null)\n            animation!!.cancel()\n        }\n    }\n\n    fun setMaxWithoutCallback() {\n        maxProgressView!!.setBackgroundResource(R.color.progress_max_active)\n        maxProgressView!!.visibility = View.VISIBLE\n        if (animation != null) {\n            animation!!.setAnimationListener(null)\n            animation!!.cancel()\n        }\n    }\n\n    private fun finishProgress(isMax: Boolean) {\n        if (isMax) maxProgressView!!.setBackgroundResource(R.color.progress_max_active)\n        maxProgressView!!.visibility = if (isMax) View.VISIBLE else View.GONE\n        if (animation != null) {\n            animation!!.setAnimationListener(null)\n            animation!!.cancel()\n            if (callback != null) {\n                callback!!.onFinishProgress()\n            }\n        }\n    }\n\n    fun startProgress() {\n        maxProgressView!!.visibility = View.GONE\n        if (duration <= 0) duration = DEFAULT_PROGRESS_DURATION\n        animation =\n            PausableScaleAnimation(\n                0f,\n                1f,\n                1f,\n                1f,\n                Animation.ABSOLUTE,\n                0f,\n                Animation.RELATIVE_TO_SELF,\n                0f\n            )\n        animation!!.duration = duration\n        animation!!.interpolator = LinearInterpolator()\n        animation!!.setAnimationListener(object : Animation.AnimationListener {\n            override fun onAnimationStart(animation: Animation) {\n                if (isStarted) {\n                    return\n                }\n                isStarted = true\n                frontProgressView!!.visibility = View.VISIBLE\n                if (callback != null) callback!!.onStartProgress()\n            }\n\n            override fun onAnimationEnd(animation: Animation) {\n                isStarted = false\n                if (callback != null) callback!!.onFinishProgress()\n            }\n\n            override fun onAnimationRepeat(animation: Animation) {\n                //NO-OP\n            }\n        })\n        animation!!.fillAfter = true\n        frontProgressView!!.startAnimation(animation)\n    }\n\n    fun pauseProgress() {\n        if (animation != null) {\n            animation!!.pause()\n        }\n    }\n\n    fun resumeProgress() {\n        if (animation != null) {\n            animation!!.resume()\n        }\n    }\n\n    fun clear() {\n        if (animation != null) {\n            animation!!.setAnimationListener(null)\n            animation!!.cancel()\n            animation = null\n        }\n    }\n\n    interface Callback {\n        fun onStartProgress()\n        fun onFinishProgress()\n    }\n\n    companion object {\n        private const val DEFAULT_PROGRESS_DURATION = 4000L\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/views/PausableScaleAnimation.kt",
    "content": "package com.gowtham.letschat.views\n\nimport android.view.animation.ScaleAnimation\nimport android.view.animation.Transformation\n\nclass PausableScaleAnimation internal constructor(\n    fromX: Float, toX: Float, fromY: Float,\n    toY: Float, pivotXType: Int, pivotXValue: Float, pivotYType: Int,\n    pivotYValue: Float\n) : ScaleAnimation(\n    fromX, toX, fromY, toY, pivotXType, pivotXValue, pivotYType,\n    pivotYValue\n) {\n    private var elapsedAtPause: Long = 0\n    private var isPaused = false\n    override fun getTransformation(\n        currentTime: Long,\n        outTransformation: Transformation,\n        scale: Float\n    ): Boolean {\n        if (isPaused && elapsedAtPause == 0L) {\n            elapsedAtPause = currentTime - startTime\n        }\n        if (isPaused) {\n            startTime = currentTime - elapsedAtPause\n        }\n        return super.getTransformation(currentTime, outTransformation, scale)\n    }\n\n    fun pause() {\n        if (isPaused) return\n        elapsedAtPause = 0\n        isPaused = true\n    }\n\n    fun resume() {\n        isPaused = false\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/gowtham/letschat/views/StoriesProgressView.kt",
    "content": "package com.gowtham.letschat.views\n\nimport android.content.Context\nimport android.util.AttributeSet\nimport android.view.View\nimport android.widget.LinearLayout\nimport com.gowtham.letschat.R\n\nclass StoriesProgressView @JvmOverloads constructor(\n    context: Context,\n    attrs: AttributeSet? = null,\n    defStyle: Int = 0\n) : LinearLayout(context, attrs, defStyle) {\n\n    private val progressBars: MutableList<PausableProgressBar> = ArrayList()\n    private var storiesListener: StoriesListener? = null\n    private var storiesCount = -1\n    private var current = -1\n    private var isSkipStart = false\n    private var isReverseStart = false\n    private var position = -1\n    private var isComplete = false\n\n    init {\n        orientation = HORIZONTAL\n        val typedArray = context.obtainStyledAttributes(attrs,\n            R.styleable.StoriesProgressView\n        )\n        storiesCount = typedArray.getInt(R.styleable.StoriesProgressView_progressCount, 0)\n        typedArray.recycle()\n        bindViews()\n    }\n\n    private fun bindViews() {\n        progressBars.clear()\n        removeAllViews()\n        for (i in 0 until storiesCount) {\n            val p = createProgressBar()\n            p.tag = \"p($position) c($i)\" // debug\n            progressBars.add(p)\n            addView(p)\n            if (i + 1 < storiesCount) {\n                addView(createSpace())\n            }\n        }\n    }\n\n    private fun createProgressBar(): PausableProgressBar {\n        return PausableProgressBar(context).apply {\n            layoutParams =\n                PROGRESS_BAR_LAYOUT_PARAM\n        }\n    }\n\n    private fun createSpace(): View {\n        return View(context).apply {\n            layoutParams =\n                SPACE_LAYOUT_PARAM\n        }\n    }\n\n    private fun callback(index: Int): PausableProgressBar.Callback {\n        return object : PausableProgressBar.Callback {\n            override fun onStartProgress() {\n                current = index\n            }\n\n            override fun onFinishProgress() {\n                if (isReverseStart) {\n                    if (storiesListener != null) storiesListener!!.onPrev()\n                    if (0 <= current - 1) {\n                        val p = progressBars[current - 1]\n                        p.setMinWithoutCallback()\n                        progressBars[--current].startProgress()\n                    } else {\n                        progressBars[current].startProgress()\n                    }\n                    isReverseStart = false\n                    return\n                }\n                val next = current + 1\n                if (next <= progressBars.size - 1) {\n                    if (storiesListener != null) storiesListener!!.onNext()\n                    progressBars[next].startProgress()\n                    ++current\n                } else {\n                    isComplete = true\n                    if (storiesListener != null) storiesListener!!.onComplete()\n                }\n                isSkipStart = false\n            }\n        }\n    }\n\n    fun setStoriesCountDebug(storiesCount: Int, position: Int) {\n        this.storiesCount = storiesCount\n        this.position = position\n        bindViews()\n    }\n\n    fun setStoriesListener(storiesListener: StoriesListener?) {\n        this.storiesListener = storiesListener\n    }\n\n    fun skip() {\n        if (isSkipStart || isReverseStart) return\n        if (isComplete) return\n        if (current < 0) return\n        val p = progressBars[current]\n        isSkipStart = true\n        p.setMax()\n    }\n\n    fun reverse() {\n        if (isSkipStart || isReverseStart) return\n        if (isComplete) return\n        if (current < 0) return\n        val p = progressBars[current]\n        isReverseStart = true\n        p.setMin()\n    }\n\n    fun setAllStoryDuration(duration: Long) {\n        for (i in progressBars.indices) {\n            progressBars[i].setDuration(duration)\n            progressBars[i].setCallback(callback(i))\n        }\n    }\n\n    fun startStories() {\n        if (progressBars.size > 0) {\n            progressBars[0].startProgress()\n        }\n    }\n\n    fun startStories(from: Int) {\n        for (i in progressBars.indices) {\n            progressBars[i].clear()\n        }\n        for (i in 0 until from) {\n            if (progressBars.size > i) {\n                progressBars[i].setMaxWithoutCallback()\n            }\n        }\n        if (progressBars.size > from) {\n            progressBars[from].startProgress()\n        }\n    }\n\n    fun destroy() {\n        for (p in progressBars) {\n            p.clear()\n        }\n    }\n\n    fun abandon() {\n        if (progressBars.size > current && current >= 0) {\n            progressBars[current].setMinWithoutCallback()\n        }\n    }\n\n    fun pause() {\n        if (current < 0) return\n        progressBars[current].pauseProgress()\n    }\n\n    fun resume() {\n        if (current < 0 && progressBars.size > 0) {\n            progressBars[0].startProgress()\n            return\n        }\n        progressBars[current].resumeProgress()\n    }\n\n    fun getProgressWithIndex(index: Int): PausableProgressBar {\n        return progressBars[index]\n    }\n\n    companion object {\n        private val PROGRESS_BAR_LAYOUT_PARAM = LayoutParams(0, LayoutParams.WRAP_CONTENT, 1F)\n        private val SPACE_LAYOUT_PARAM = LayoutParams(5, LayoutParams.WRAP_CONTENT)\n    }\n\n    interface StoriesListener {\n        fun onNext()\n        fun onPrev()\n        fun onComplete()\n    }\n}"
  },
  {
    "path": "app/src/main/res/anim/slide_in_right.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <translate android:fromXDelta=\"300\"\n        android:toXDelta=\"0\"\n        android:duration=\"500\" />\n\n    <alpha android:fromAlpha=\"0\"\n        android:toAlpha=\"1\"\n        android:duration=\"500\" />\n\n</set>"
  },
  {
    "path": "app/src/main/res/anim/slide_out_left.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <translate android:fromXDelta=\"0\"\n        android:toXDelta=\"-300\"\n        android:duration=\"500\" />\n\n    <alpha android:fromAlpha=\"1\"\n        android:toAlpha=\"0\"\n        android:duration=\"500\" />\n\n</set>"
  },
  {
    "path": "app/src/main/res/drawable/ic_arrow_back.xml",
    "content": "<vector android:height=\"24dp\" android:tint=\"#FFFFFF\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"24dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"#FFFFFF\" android:pathData=\"M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_arrow_down.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\">\n  <path\n      android:fillColor=\"#000\"\n      android:pathData=\"M7.41,8.59L12,13.17l4.59,-4.58L18,10l-6,6 -6,-6 1.41,-1.41z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_arrow_r8.xml",
    "content": "<vector android:height=\"30dp\" android:tint=\"#FFFFFF\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"30dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M8.59,16.59L13.17,12 8.59,7.41 10,6l6,6 -6,6 -1.41,-1.41z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_clear.xml",
    "content": "<vector android:height=\"40dp\" android:tint=\"@color/colorBlack\"\n    android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n    android:width=\"40dp\" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <path android:fillColor=\"@android:color/white\" android:pathData=\"M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_close_24px.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\">\n  <path\n      android:fillColor=\"#fff\"\n      android:pathData=\"M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path\n        android:fillColor=\"#3DDC84\"\n        android:pathData=\"M0,0h108v108h-108z\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M9,0L9,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,0L19,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,0L29,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,0L39,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,0L49,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,0L59,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,0L69,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,0L79,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M89,0L89,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M99,0L99,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,9L108,9\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,19L108,19\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,29L108,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,39L108,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,49L108,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,59L108,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,69L108,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,79L108,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,89L108,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,99L108,99\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,29L89,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,39L89,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,49L89,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,59L89,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,69L89,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,79L89,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,19L29,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,19L39,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,19L49,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,19L59,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,19L69,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,19L79,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_menu_24px.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"24\"\n    android:viewportHeight=\"24\">\n  <path\n      android:fillColor=\"#fff\"\n      android:pathData=\"M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_search.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:width=\"24dp\"\n        android:height=\"24dp\"\n        android:viewportWidth=\"24.0\"\n        android:viewportHeight=\"24.0\">\n    <path\n        android:fillColor=\"#fff\"\n        android:pathData=\"M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/selector_menu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@drawable/shape_menu_active\" android:state_selected=\"true\" />\n    <item android:drawable=\"@drawable/shape_menu_active\" android:state_activated=\"true\" />\n    <item android:drawable=\"@drawable/shape_menu_non_active\" />\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/shape_audio_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n<corners android:radius=\"12dp\"/>\n\n    <solid android:color=\"@color/colorPrimary2\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_border_line.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n\n    <solid android:color=\"@color/colorWhite\"/>\n\n    <stroke android:color=\"@color/colorPrimary2\"\n        android:width=\"2dp\"/>\n\n    <corners android:radius=\"8dp\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_btn_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <corners android:radius=\"10dp\"/>\n    <solid android:color=\"@color/colorPrimary\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_circle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"oval\">\n\n    <solid android:color=\"@color/colorPrimary2\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_circle_blue.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"oval\">\n\n    <solid android:color=\"@color/colorAccent\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_contact_selected.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n    <solid android:color=\"@color/colorPrimaryLt\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_divider.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\"\n    >\n\n    <solid android:color=\"@color/colorWhite\"/>\n<size android:height=\"0.5dp\"\n    android:width=\"3dp\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_edit_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <stroke android:width=\"2dp\"\n        android:color=\"@color/colorPrimaryLt\"/>\n\n    <solid android:color=\"@color/colorDefaultBg\"/>\n\n    <corners android:radius=\"6dp\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_gradient.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n\n    <corners android:radius=\"8dp\"/>\n\n    <solid android:color=\"@color/colorPrimary2\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_home_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <corners android:topLeftRadius=\"28dp\"\n        android:topRightRadius=\"28dp\"/>\n\n    <solid android:color=\"@color/colorWhite\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_menu_active.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <corners android:radius=\"8dp\"/>\n    <solid android:color=\"#63FFFFFF\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_menu_non_active.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <corners android:radius=\"8dp\"/>\n    <solid android:color=\"@android:color/transparent\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_msg_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n    <solid android:color=\"@color/colorPrimaryLt\"  />\n\n    <corners android:bottomRightRadius=\"24dp\"\n        android:bottomLeftRadius=\"24dp\"\n        android:topLeftRadius=\"24dp\"\n        android:topRightRadius=\"24dp\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_radius.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <corners android:topRightRadius=\"16dp\"\n        android:topLeftRadius=\"16dp\"/>\n\n    <solid android:color=\"#fff\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_receive_msg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n\n    <solid android:color=\"@color/colorPrimary2\"/>\n\n    <corners android:topRightRadius=\"12dp\"\n        android:bottomLeftRadius=\"12dp\"\n        android:bottomRightRadius=\"12dp\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_receive_msg_corned.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n\n    <solid android:color=\"@color/colorPrimary2\"/>\n\n    <corners android:topRightRadius=\"12dp\"\n        android:bottomLeftRadius=\"12dp\"\n        android:topLeftRadius=\"12dp\"\n        android:bottomRightRadius=\"12dp\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_send_msg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n\n    <solid android:color=\"@color/colorPrimary2\"/>\n\n    <corners android:topLeftRadius=\"12dp\"\n        android:bottomLeftRadius=\"12dp\"\n        android:bottomRightRadius=\"12dp\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_send_msg_corned.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n\n    <solid android:color=\"@color/colorPrimary2\"/>\n\n    <corners android:topLeftRadius=\"12dp\"\n        android:bottomLeftRadius=\"12dp\"\n        android:topRightRadius=\"12dp\"\n        android:bottomRightRadius=\"12dp\"/>\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/shape_unread_count.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n    <solid android:color=\"@color/colorPrimary2\"  />\n\n    <corners android:bottomRightRadius=\"16dp\"\n        android:bottomLeftRadius=\"16dp\"\n        android:topLeftRadius=\"16dp\"\n        android:topRightRadius=\"16dp\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path android:pathData=\"M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"85.84757\"\n                android:endY=\"92.4963\"\n                android:startX=\"42.9492\"\n                android:startY=\"49.59793\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\" />\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\" />\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        android:pathData=\"M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/layout/act_chat.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n        style=\"@style/StyleRoot\">\n\n\n        <FrameLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\">\n\n            <fragment\n                android:id=\"@+id/nav_host_chat\"\n                android:name=\"androidx.navigation.fragment.NavHostFragment\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                app:defaultNavHost=\"true\" />\n        </FrameLayout>\n\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/act_splash.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.activities.ActSplash\">\n\n    <ImageView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:src=\"@drawable/ic_chat_logo\"/>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n        style=\"@style/FView\"\n        tools:ignore=\"VectorDrawableCompat\">\n\n        <LinearLayout\n            style=\"@style/FView\">\n\n            <com.google.android.material.appbar.AppBarLayout\n                style=\"@style/VView\">\n\n                <androidx.appcompat.widget.Toolbar\n                    android:id=\"@+id/toolbar\"\n                    style=\"@style/CustomToolBar\"\n                    app:title=\"LetsChat\"\n                    app:titleTextColor=\"@color/colorWhite\" />\n            </com.google.android.material.appbar.AppBarLayout>\n\n                <androidx.fragment.app.FragmentContainerView\n                    android:id=\"@+id/nav_host_fragment\"\n                    android:name=\"com.gowtham.letschat.views.MainNavHostFragment\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"0dp\"\n                    android:layout_weight=\"1\"\n                    app:defaultNavHost=\"true\"\n                    app:navGraph=\"@navigation/nav_graph\" />\n\n            <com.google.android.material.bottomnavigation.BottomNavigationView\n                android:id=\"@+id/bottom_nav\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"bottom\"\n                android:background=\"@color/colorPrimary\"\n                app:itemTextColor=\"@color/colorWhite\"\n                app:itemIconTint=\"@color/colorWhite\"\n                app:menu=\"@menu/menu_btm_nav\" />\n        </LinearLayout>\n\n        <com.google.android.material.floatingactionbutton.FloatingActionButton\n            android:id=\"@+id/fab\"\n            style=\"@style/StyleFab\"\n            android:layout_gravity=\"top\"\n            app:layout_anchor=\"@id/bottom_nav\"\n            app:layout_anchorGravity=\"top|end\"\n            app:srcCompat=\"@drawable/ic_add\"\n            app:useCompatPadding=\"true\"/>\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/activity_main2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n        style=\"@style/FView\"\n        tools:ignore=\"VectorDrawableCompat\">\n\n        <com.google.android.material.appbar.AppBarLayout\n            style=\"@style/VView\">\n\n            <androidx.appcompat.widget.Toolbar\n                android:id=\"@+id/toolbar\"\n                style=\"@style/CustomToolBar\"\n                app:layout_scrollFlags=\"scroll|enterAlways\"\n                app:title=\"LetsChat\"\n                app:titleTextColor=\"@color/colorWhite\" />\n        </com.google.android.material.appbar.AppBarLayout>\n\n        <FrameLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            >\n\n        <androidx.fragment.app.FragmentContainerView\n            android:id=\"@+id/nav_host_fragment\"\n            android:name=\"androidx.navigation.fragment.NavHostFragment\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            app:defaultNavHost=\"true\"\n            app:navGraph=\"@navigation/nav_graph\" />\n        </FrameLayout>\n\n        <com.google.android.material.bottomnavigation.BottomNavigationView\n            android:id=\"@+id/bottom_nav\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"bottom\"\n            app:layout_behavior=\"com.google.android.material.behavior.HideBottomViewOnScrollBehavior\"\n            android:background=\"@color/colorPrimary\"\n            app:itemTextColor=\"@color/colorWhite\"\n            app:itemIconTint=\"@color/colorWhite\"\n            app:menu=\"@menu/menu_btm_nav\" />\n\n        <com.google.android.material.floatingactionbutton.FloatingActionButton\n            android:id=\"@+id/fab\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"top\"\n            app:layout_anchor=\"@id/bottom_nav\"\n            app:layout_anchorGravity=\"top|end\"\n            app:layout_behavior=\"com.google.android.material.floatingactionbutton.FloatingActionButton$Behavior\"\n            app:srcCompat=\"@drawable/ic_add\"\n            app:useCompatPadding=\"true\"\n            />\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/alert_dialog.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    style=\"@style/VView\"\n    android:padding=\"20dp\">\n\n    <TextView\n        style=\"@style/TxtSemiSmallStyle\"\n        android:textSize=\"18sp\"\n        android:paddingTop=\"8dp\"\n        android:text=\"@string/txt_logged_in_head\"/>\n\n    <TextView\n      style=\"@style/TxtRgStyle\"\n        android:maxLines=\"3\"\n        android:textSize=\"16sp\"\n        android:layout_marginTop=\"5dp\"\n        android:text=\"@string/txt_login_again\"/>\n\n    <TextView\n        android:id=\"@+id/txt_log_out\"\n        style=\"@style/TxtSemiSmallStyle\"\n        android:textSize=\"15sp\"\n        android:layout_marginTop=\"10dp\"\n        android:layout_gravity=\"end\"\n        android:textColor=\"@color/colorTheme\"\n        android:padding=\"8dp\"\n        android:text=\"@string/txt_logout\"/>\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/alert_logout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n\n    </data>\n\n    <RelativeLayout style=\"@style/VView\"\n        android:padding=\"16dp\">\n\n        <TextView\n            android:id=\"@+id/txt_title\"\n            style=\"@style/TxtSemiSmallStyle\"\n            android:text=\"@string/txt_want_2_logout\"\n            android:textSize=\"20sp\"/>\n\n        <TextView\n            android:id=\"@+id/txt_sub_title\"\n            android:layout_below=\"@id/txt_title\"\n            style=\"@style/TxtRgStyle\"\n            android:gravity=\"start\"\n            android:layout_marginTop=\"5dp\"\n            android:text=\"@string/txt_alert_msg\"/>\n\n        <TextView\n            android:id=\"@+id/txt_cancel\"\n            style=\"@style/TxtSemiSmallStyle\"\n            android:layout_below=\"@id/txt_sub_title\"\n            android:layout_toStartOf=\"@+id/txt_ok\"\n            android:padding=\"10dp\"\n            android:layout_marginTop=\"5dp\"\n            android:text=\"@string/txt_cancel\"\n            android:background=\"?attr/selectableItemBackground\"\n            android:clickable=\"true\"\n            android:focusable=\"true\"\n            android:textSize=\"18sp\" />\n\n        <TextView\n            android:layout_marginTop=\"5dp\"\n            android:id=\"@+id/txt_ok\"\n            style=\"@style/TxtSemiSmallStyle\"\n            android:text=\"@string/txt_ok\"\n            android:paddingStart=\"12dp\"\n            android:paddingTop=\"10dp\"\n            android:paddingBottom=\"10dp\"\n            android:paddingEnd=\"12dp\"\n            android:layout_below=\"@id/txt_sub_title\"\n            android:layout_alignParentEnd=\"true\"\n            android:background=\"?attr/selectableItemBackground\"\n            android:clickable=\"true\"\n            android:focusable=\"true\"\n            android:textSize=\"18sp\"/>\n    </RelativeLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_add_group_members.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n        style=\"@style/StyleRoot\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout style=\"@style/VView\">\n\n            <com.google.android.material.appbar.AppBarLayout style=\"@style/VView\">\n                <androidx.appcompat.widget.Toolbar\n                    android:id=\"@+id/toolbar\"\n                    style=\"@style/CustomToolBar\"\n                    app:title=\"Add Friends\" />\n            </com.google.android.material.appbar.AppBarLayout>\n\n            <LinearLayout\n                android:id=\"@+id/view_holder\"\n                style=\"@style/VView\">\n\n            <RelativeLayout\n                style=\"@style/VView\"\n                android:layout_marginStart=\"5dp\"\n                android:layout_marginEnd=\"5dp\">\n\n                <androidx.recyclerview.widget.RecyclerView\n                    android:id=\"@+id/list_chip\"\n                    style=\"@style/StyleList\"\n                    android:orientation=\"horizontal\"\n                    tools:listitem=\"@layout/row_chip\" />\n\n                <TextView\n                    android:id=\"@+id/txt_empty_members\"\n                    style=\"@style/TxtSemiSmallStyle\"\n                    android:layout_height=\"48dp\"\n                    android:layout_marginStart=\"10dp\"\n                    android:gravity=\"center_vertical\"\n                    android:text=\"@string/txt_add_a_friend\"\n                    android:textSize=\"18sp\" />\n\n            </RelativeLayout>\n\n            <androidx.recyclerview.widget.RecyclerView\n                android:id=\"@+id/list_contact\"\n                style=\"@style/StyleList\"\n                tools:listitem=\"@layout/row_add_member\" />\n\n            </LinearLayout>\n        </LinearLayout>\n\n        <com.google.android.material.floatingactionbutton.FloatingActionButton\n            android:id=\"@+id/fab\"\n            style=\"@style/StyleFab\"\n            android:visibility=\"gone\"\n            app:srcCompat=\"@drawable/ic_action_arrow_right\" />\n\n        <ProgressBar\n            android:id=\"@+id/progress\"\n            style=\"@style/WView\"\n            android:visibility=\"gone\"\n            android:layout_gravity=\"center\" />\n\n        <com.airbnb.lottie.LottieAnimationView\n            android:id=\"@+id/view_empty\"\n            android:layout_width=\"250dp\"\n            android:layout_height=\"250dp\"\n            android:layout_gravity=\"center\"\n            app:lottie_rawRes=\"@raw/empty_state\"/>\n\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_attachment.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n\n    </data>\n\n    <LinearLayout\n        style=\"@style/VView\"\n        tools:ignore=\"ContentDescription\">\n\n            <TextView\n                android:id=\"@+id/img_camera\"\n                style=\"@style/TxtBottomSheetStyle\"\n                android:text=\"@string/take_photo\"\n                app:drawableStartCompat=\"@drawable/ic_take_camera\" />\n\n        <TextView\n            android:id=\"@+id/img_gallery\"\n            style=\"@style/TxtBottomSheetStyle\"\n            android:text=\"@string/txt_gallery\"\n            app:drawableStartCompat=\"@drawable/ic_folder\" />\n\n        <TextView\n            android:id=\"@+id/video_camera\"\n            style=\"@style/TxtBottomSheetStyle\"\n            android:text=\"@string/txt_take_video\"\n            app:drawableStartCompat=\"@drawable/ic_v_camera\" />\n\n        <TextView\n            android:id=\"@+id/video_gallery\"\n            style=\"@style/TxtBottomSheetStyle\"\n            android:text=\"@string/txt_gallery\"\n            app:drawableStartCompat=\"@drawable/ic_v_folder\" />\n        </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_contacts.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"viewmodel\"\n            type=\"com.gowtham.letschat.fragments.contacts.ContactsViewModel\" />\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n        style=\"@style/StyleRoot\"\n        tools:ignore=\"ContentDescription,UseCompoundDrawables\">\n\n        <com.google.android.material.appbar.AppBarLayout\n            style=\"@style/VView\">\n\n            <androidx.appcompat.widget.Toolbar\n                android:id=\"@+id/toolbar\"\n                style=\"@style/CustomToolBar\"\n                app:layout_scrollFlags=\"scroll|enterAlways\"\n                app:theme=\"@style/ThemeOverlay.AppCompat.Dark.ActionBar\"\n                android:contentInsetLeft=\"0dp\"\n                android:contentInsetStart=\"0dp\"\n                app:contentInsetLeft=\"0dp\"\n                app:contentInsetStart=\"0dp\"\n                app:contentInsetStartWithNavigation=\"0dp\">\n\n                <LinearLayout style=\"@style/WVView\">\n\n                    <TextView\n                        style=\"@style/TxtSemiSmallStyle\"\n                        android:text=\"@string/txt_select_a_contact\"\n                        android:textColor=\"@color/colorWhite\"\n                        android:textSize=\"18sp\" />\n\n                    <TextView\n                        style=\"@style/TxtRgStyle\"\n                        android:text= \"@{viewmodel.contactsCount}\"\n                        android:textColor=\"@color/colorWhite\"\n                        android:textSize=\"15sp\" />\n\n                </LinearLayout>\n\n            </androidx.appcompat.widget.Toolbar>\n\n            <ProgressBar\n                android:id=\"@+id/progress\"\n                style=\"@style/Base.Widget.AppCompat.ProgressBar.Horizontal\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"-10dp\"\n                android:layout_marginBottom=\"-10dp\"\n                android:visibility=\"gone\"\n                app:progressState=\"@{viewmodel.queryState}\"\n                android:indeterminate=\"true\"/>\n\n        </com.google.android.material.appbar.AppBarLayout>\n\n        <LinearLayout\n           style=\"@style/VView\"\n            app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n            <androidx.recyclerview.widget.RecyclerView\n                android:id=\"@+id/list_contact\"\n                style=\"@style/ListView\"\n                app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n                tools:listitem=\"@layout/row_contact\" />\n\n        </LinearLayout>\n\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_countries.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n        style=\"@style/StyleRoot\"\n        tools:ignore=\"ContentDescription\">\n        <com.google.android.material.appbar.AppBarLayout\n            style=\"@style/VView\">\n\n            <androidx.appcompat.widget.Toolbar\n                android:id=\"@+id/toolbar\"\n                style=\"@style/CustomToolBar\"\n                app:layout_scrollFlags=\"scroll|enterAlways\"\n                app:title=\"LetsChat\"\n                app:theme=\"@style/ThemeOverlay.AppCompat.Dark.ActionBar\"\n                app:titleTextColor=\"@color/colorWhite\" />\n        </com.google.android.material.appbar.AppBarLayout>\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/list_country\"\n            style=\"@style/VView\"\n            app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n            tools:listitem=\"@layout/row_country\"\n            app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"/>\n\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_create_group.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"ContentDescription,Autofill\">\n\n    <data>\n\n        <import type=\"android.view.View\" />\n\n        <variable\n            name=\"viewmodel\"\n            type=\"com.gowtham.letschat.fragments.create_group.CreateGroupViewModel\" />\n\n        <variable\n            name=\"memberCount\"\n            type=\"String\" />\n\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n       style=\"@style/FView\">\n\n\n    <LinearLayout style=\"@style/FView\">\n\n        <com.google.android.material.appbar.AppBarLayout style=\"@style/VView\">\n\n            <androidx.appcompat.widget.Toolbar\n                android:id=\"@+id/toolbar\"\n                style=\"@style/CustomToolBar\"\n                app:title=\"Create Group\" />\n        </com.google.android.material.appbar.AppBarLayout>\n\n\n        <LinearLayout\n            style=\"@style/LView\"\n            android:padding=\"12dp\">\n\n            <RelativeLayout\n                android:layout_width=\"60dp\"\n                android:layout_height=\"60dp\">\n\n                <ImageView\n                    android:id=\"@+id/image_add_image\"\n                    style=\"@style/FView\"\n                    imageUrl=\"@{viewmodel.imageUrl}\"\n                    android:padding=\"16dp\"\n                    android:background=\"@drawable/shape_circle_blue\"\n                    android:src=\"@drawable/ic_add_pic\"\n                    app:tint=\"@color/colorWhite\" />\n\n                <ProgressBar\n                    android:id=\"@+id/progress_circular\"\n                    style=\"@style/VView\"\n                    android:layout_width=\"24dp\"\n                    android:layout_height=\"24dp\"\n                    android:layout_centerInParent=\"true\"\n                    android:theme=\"@style/progressColor\"\n                    android:visibility=\"@{viewmodel.progressProPic ? View.VISIBLE : View.GONE}\" />\n\n            </RelativeLayout>\n\n            <EditText\n                android:id=\"@+id/edt_group_name\"\n                style=\"@style/LWView\"\n                android:text=\"@={viewmodel.groupName}\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_marginStart=\"10dp\"\n                android:fontFamily=\"@font/font_semi\"\n                android:hint=\"@string/txt_group_name\"\n                android:imeOptions=\"actionDone\"\n                android:inputType=\"textCapWords|text\"\n                android:maxLength=\"35\"\n                android:padding=\"12dp\"\n                android:textColor=\"@color/colorTxt\"\n                android:textColorHint=\"@color/colorHint\"\n                android:textSize=\"18sp\" />\n\n        </LinearLayout>\n\n        <View\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"10dp\"\n            android:background=\"@color/colorPrimaryLt\" />\n\n\n        <TextView\n            style=\"@style/TxtSemiSmallStyle\"\n            android:layout_marginStart=\"16dp\"\n            android:layout_marginTop=\"10dp\"\n            android:text=\"@{memberCount}\"\n            android:textColor=\"@color/colorAccent\"\n            android:textSize=\"16sp\" />\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/list_members\"\n            style=\"@style/StyleList\"\n            tools:listitem=\"@layout/row_add_member\" />\n\n    </LinearLayout>\n\n            <com.google.android.material.floatingactionbutton.FloatingActionButton\n            android:id=\"@+id/fab\"\n            style=\"@style/StyleFab\"\n            app:srcCompat=\"@drawable/ic_action_arrow_right\" />\n\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_group_chat.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:bind=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n        <variable\n            name=\"group\"\n            type=\"com.gowtham.letschat.db.data.Group\" />\n\n        <variable\n            name=\"viewmodel\"\n            type=\"com.gowtham.letschat.fragments.group_chat.GroupChatViewModel\" />\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n        style=\"@style/FView\"\n        android:focusable=\"true\"\n        android:fitsSystemWindows=\"true\"\n        android:focusableInTouchMode=\"true\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout style=\"@style/FView\">\n\n            <include\n                android:id=\"@+id/view_chat_header\"\n                bind:group=\"@{group}\"\n                bind:viewmodel=\"@{viewmodel}\"\n                layout=\"@layout/view_group_chat_toolbar\" />\n\n            <androidx.recyclerview.widget.RecyclerView\n                android:id=\"@+id/list_message\"\n                tools:listitem=\"@layout/row_sent_message\"\n                style=\"@style/VWView\" />\n\n            <include\n                android:id=\"@+id/view_chat_btm\"\n                bind:viewmodel=\"@{viewmodel}\"\n                layout=\"@layout/view_group_chat_btm\" />\n\n        </LinearLayout>\n\n\n        <ImageView\n            android:id=\"@+id/fullSizeImageView\"\n            style=\"@style/FView\"\n            android:background=\"@color/colorBlack\"\n            android:visibility=\"gone\"\n             />\n\n        <com.airbnb.lottie.LottieAnimationView\n            android:id=\"@+id/lottie_voice\"\n            android:layout_width=\"65dp\"\n            android:layout_height=\"65dp\"\n            android:layout_gravity=\"end|bottom\"\n            android:visibility=\"gone\"\n            bind:lottie_rawRes=\"@raw/lottie_voice\"/>\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_group_chat_home.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n       style=\"@style/StyleRoot\">\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/list_group\"\n            style=\"@style/StyleList\"\n            tools:listitem=\"@layout/row_group_chat\"\n            />\n\n        <ImageView\n            android:id=\"@+id/image_empty\"\n            style=\"@style/WView\"\n            android:visibility=\"gone\"\n            android:layout_gravity=\"center\"\n            android:src=\"@drawable/ic_group_msg\"/>\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_image_src_sheet.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n\n    </data>\n\n    <androidx.constraintlayout.widget.ConstraintLayout\n        style=\"@style/FView\">\n\n        <TextView\n            android:id=\"@+id/textView\"\n            style=\"@style/TxtRgStyle\"\n            android:layout_marginStart=\"12dp\"\n            android:layout_marginTop=\"12dp\"\n            android:text=\"@string/txt_select_a_option\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\" />\n\n        <TextView\n            android:id=\"@+id/txt_camera\"\n            style=\"@style/TxtBottomSheetStyle\"\n            android:layout_marginTop=\"10dp\"\n            android:text=\"@string/take_photo\"\n            android:background=\"?android:attr/selectableItemBackground\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/textView\"\n            app:drawableStartCompat=\"@drawable/ic_take_camera\" />\n\n        <TextView\n            android:id=\"@+id/txt_gallery\"\n            style=\"@style/TxtBottomSheetStyle\"\n            android:text=\"@string/txt_gallery\"\n            android:background=\"?android:attr/selectableItemBackground\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/txt_camera\"\n            app:drawableStartCompat=\"@drawable/ic_folder\" />\n\n    </androidx.constraintlayout.widget.ConstraintLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_login.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n        <variable\n            name=\"viewmodel\"\n            type=\"com.gowtham.letschat.fragments.login.LogInViewModel\" />\n    </data>\n\n    <androidx.core.widget.NestedScrollView style=\"@style/ScrollRoot\">\n\n        <androidx.coordinatorlayout.widget.CoordinatorLayout\n            style=\"@style/StyleRoot\"\n            android:id=\"@+id/view_holder\">\n\n            <ImageView\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:scaleType=\"centerCrop\"\n                android:src=\"@drawable/ic_chat_bg\" />\n\n            <LinearLayout style=\"@style/FView\"\n                android:focusable=\"true\"\n                android:focusableInTouchMode=\"true\">\n\n                <LinearLayout\n                    style=\"@style/VWView\"\n                    android:layout_marginTop=\"190dp\"\n                    android:background=\"@drawable/shape_home_bg\"\n                    android:elevation=\"5dp\"\n                    android:padding=\"20dp\">\n\n                    <TextView\n                        style=\"@style/TxtSemiStyle\"\n                        android:layout_marginTop=\"15dp\"\n                        android:text=\"@string/txt_welcome\" />\n\n                    <TextView\n                        style=\"@style/TxtRgStyle\"\n                        android:layout_marginTop=\"15dp\"\n                        android:gravity=\"start\"\n                        android:text=\"@string/txt_will_send_otp\" />\n\n                    <TextView\n                        style=\"@style/TxtRgStyle\"\n                        android:layout_marginTop=\"30dp\"\n                        android:text=\"@string/txt_enter_mob_no\" />\n\n                    <LinearLayout\n                        style=\"@style/LView\"\n                        android:layout_marginTop=\"10dp\"\n                        android:background=\"@drawable/shape_edit_bg\">\n\n                        <TextView\n                            style=\"@style/WView\"\n                            android:layout_marginStart=\"5dp\"\n                            app:drawableEndCompat=\"@drawable/ic_arrow_down\"\n                            android:fontFamily=\"@font/font_semi\"\n                            android:gravity=\"center\"\n                            android:padding=\"6dp\"\n                            android:id=\"@+id/txt_country_code\"\n                            android:text=\"@{viewmodel.country.noCode}\"\n                            android:textColor=\"@color/colorBlack\"\n                            android:textSize=\"20sp\" />\n\n                        <EditText\n                            style=\"@style/LWView\"\n                            android:id=\"@+id/edt_mobile\"\n                            android:background=\"@android:color/transparent\"\n                            android:fontFamily=\"@font/font_semi\"\n                            android:inputType=\"number\"\n                            android:padding=\"10dp\"\n                            android:text=\"@={viewmodel.mobile}\"\n                            android:textColor=\"@color/colorBlack\"\n                            android:textSize=\"20sp\" />\n                    </LinearLayout>\n\n                    <TextView\n                        style=\"@style/BtnStyle\"\n                        android:id=\"@+id/btn_get_otp\"\n                        android:layout_marginTop=\"80dp\"\n                        android:text=\"@string/txt_get_otp\" />\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </androidx.coordinatorlayout.widget.CoordinatorLayout>\n    </androidx.core.widget.NestedScrollView>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_my_profile.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n        <import type=\"android.view.View\" />\n\n        <variable\n            name=\"viewModel\"\n            type=\"com.gowtham.letschat.fragments.myprofile.FMyProfileViewModel\" />\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n        style=\"@style/StyleRoot\"\n        android:padding=\"16dp\"\n        tools:ignore=\"ContentDescription\">\n\n        <androidx.core.widget.NestedScrollView\n            style=\"@style/FView\">\n\n        <LinearLayout\n            style=\"@style/FView\"\n            android:gravity=\"center_horizontal\">\n\n            <RelativeLayout\n                android:layout_width=\"120dp\"\n                android:layout_height=\"120dp\">\n                <ImageView\n                    android:id=\"@+id/image_profile\"\n                    style=\"@style/FView\"\n                    imageUrl=\"@{viewModel.imageUrl}\"\n                    android:src=\"@drawable/ic_other_user\" />\n\n                <ProgressBar\n                    android:id=\"@+id/progress_pro\"\n                    android:layout_width=\"35dp\"\n                    android:layout_height=\"35dp\"\n                    android:layout_centerInParent=\"true\"\n                    android:visibility=\"@{viewModel.isUploading ? View.VISIBLE : View.GONE}\" />\n            </RelativeLayout>\n\n\n            <com.google.android.material.textfield.TextInputLayout\n                style=\"@style/StyleInputLayout\"\n                android:layout_marginTop=\"25dp\"\n                android:hint=\"@string/txt_u_name\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    style=\"@style/StyleEdtInput\"\n                    android:id=\"@+id/edt_user_name\"\n                    android:inputType=\"textPersonName|textCapWords\"\n                    android:text=\"@={viewModel.userName}\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <com.google.android.material.textfield.TextInputLayout\n                style=\"@style/StyleInputLayout\"\n                android:layout_marginTop=\"15dp\"\n                android:hint=\"@string/txt_your_status\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    style=\"@style/StyleEdtInput\"\n                    android:inputType=\"textMultiLine|textCapSentences\"\n                    android:maxLength=\"60\"\n                    android:maxLines=\"3\"\n                    android:id=\"@+id/edt_status\"\n                    android:text=\"@={viewModel.about}\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <com.google.android.material.textfield.TextInputLayout\n                style=\"@style/StyleInputLayout\"\n                android:layout_marginTop=\"15dp\"\n                android:hint=\"@string/txt_mob_num\">\n\n                <com.google.android.material.textfield.TextInputEditText\n                    style=\"@style/StyleEdtInput\"\n                    android:clickable=\"false\"\n                    android:cursorVisible=\"false\"\n                    android:focusable=\"false\"\n                    android:focusableInTouchMode=\"false\"\n                    android:text=\"@={viewModel.mobile}\" />\n\n            </com.google.android.material.textfield.TextInputLayout>\n\n            <View style=\"@style/VWView\" />\n\n\n            <LinearLayout\n                style=\"@style/LView\"\n                android:layout_marginTop=\"50dp\"\n                android:layout_marginBottom=\"30dp\">\n\n                <TextView\n                    android:id=\"@+id/btn_logout\"\n                    style=\"@style/StyleButton\"\n                    android:layout_marginEnd=\"5dp\"\n                    android:background=\"@drawable/shape_border_line\"\n                    android:text=\"@string/txt_log_out\"\n                    android:textColor=\"@color/colorPrimary2\" />\n\n                <TextView\n                    android:id=\"@+id/btn_save_changes\"\n                    style=\"@style/StyleButton\"\n                    android:layout_marginStart=\"5dp\"\n                    android:text=\"@string/txt_save_changes\" />\n            </LinearLayout>\n        </LinearLayout>\n        </androidx.core.widget.NestedScrollView>\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_profile.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n        <import type=\"android.view.View\" />\n\n        <variable\n            name=\"viewmodel\"\n            type=\"com.gowtham.letschat.fragments.profile.ProfileViewModel\" />\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout style=\"@style/StyleRoot\">\n\n        <LinearLayout\n            style=\"@style/VView\"\n            android:layout_marginTop=\"35dp\"\n            android:gravity=\"center_horizontal\"\n            android:padding=\"12dp\">\n\n\n            <RelativeLayout\n                android:layout_width=\"110dp\"\n                android:layout_height=\"110dp\">\n\n                <ImageView\n                    android:id=\"@+id/img_pro_pic\"\n                    style=\"@style/FView\"\n                    android:src=\"@drawable/ic_other_user\"\n                    app:imageUrl=\"@{viewmodel.profilePicUrl}\"/>\n\n                <ProgressBar\n                    android:id=\"@+id/progress_pro\"\n                    android:layout_width=\"35dp\"\n                    android:layout_height=\"35dp\"\n                    android:layout_centerInParent=\"true\"\n                    android:visibility=\"@{viewmodel.progressProPic ? View.VISIBLE : View.GONE}\" />\n\n            </RelativeLayout>\n\n            <EditText\n                android:id=\"@+id/edt_name\"\n                style=\"@style/VView\"\n                android:layout_marginTop=\"35dp\"\n                android:background=\"@android:color/transparent\"\n                android:fontFamily=\"@font/font_semi\"\n                android:hint=\"@string/txt_user_name\"\n                android:inputType=\"textPersonName|textCapWords\"\n                android:padding=\"8dp\"\n                android:text=\"@={viewmodel.name}\"\n                android:textColor=\"@color/colorBlack\"\n                android:textSize=\"20sp\" />\n\n            <View style=\"@style/LineView\" />\n\n            <TextView\n                style=\"@style/TxtRgStyle\"\n                android:layout_marginStart=\"10dp\"\n                android:layout_marginTop=\"15dp\"\n                android:layout_marginEnd=\"10dp\"\n                android:fontFamily=\"@font/font_semi\"\n                android:text=\"@string/txt_pic_name_desc\" />\n\n        </LinearLayout>\n\n        <com.google.android.material.floatingactionbutton.FloatingActionButton\n            android:id=\"@+id/fab\"\n            style=\"@style/StyleFab\"\n            android:src=\"@drawable/ic_arrow_r8\" />\n\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_search.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n\n\n    </data>\n\n    <RelativeLayout style=\"@style/StyleRoot\">\n\n        <androidx.recyclerview.widget.RecyclerView\n            android:id=\"@+id/list_users\"\n            style=\"@style/StyleList\"\n            tools:listitem=\"@layout/row_search_contact\" />\n\n        <ProgressBar\n            android:id=\"@+id/progress_bar\"\n            style=\"@style/WView\"\n            android:layout_centerInParent=\"true\"\n            android:visibility=\"gone\"\n            tools:visibility=\"visible\" />\n\n        <TextView\n            android:id=\"@+id/txt_no_user\"\n            style=\"@style/TxtRgStyle\"\n            android:layout_centerInParent=\"true\"\n            android:text=\"No results found for this query\"\n            android:visibility=\"gone\"\n            tools:visibility=\"visible\" />\n\n        <TextView\n            android:id=\"@+id/view_empty\"\n            style=\"@style/TxtRgStyle\"\n            android:text=\"Search someone..\"\n            android:layout_centerInParent=\"true\"/>\n    </RelativeLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_single_chat.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:bind=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n        <variable\n            name=\"chatUser\"\n            type=\"com.gowtham.letschat.db.data.ChatUser\" />\n\n        <variable\n            name=\"viewmodel\"\n            type=\"com.gowtham.letschat.fragments.single_chat.SingleChatViewModel\" />\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n       style=\"@style/FView\"\n        android:focusable=\"true\"\n        android:fitsSystemWindows=\"true\"\n        android:focusableInTouchMode=\"true\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout style=\"@style/FView\">\n\n            <include\n                android:id=\"@+id/view_chat_header\"\n                bind:chatUser=\"@{chatUser}\"\n                bind:viewmodel=\"@{viewmodel}\"\n                layout=\"@layout/view_chat_toolbar\" />\n\n            <androidx.recyclerview.widget.RecyclerView\n                android:id=\"@+id/list_message\"\n                tools:listitem=\"@layout/row_sent_message\"\n                style=\"@style/VWView\" />\n\n            <include\n                android:id=\"@+id/view_chat_btm\"\n                bind:viewmodel=\"@{viewmodel}\"\n                layout=\"@layout/view_chat_btm\" />\n\n        </LinearLayout>\n        <ImageView\n            android:id=\"@+id/fullSizeImageView\"\n            style=\"@style/FView\"\n            android:background=\"@color/colorBlack\"\n            android:visibility=\"gone\" />\n\n        <com.airbnb.lottie.LottieAnimationView\n            android:id=\"@+id/lottie_voice\"\n            android:layout_width=\"65dp\"\n            android:layout_height=\"65dp\"\n            android:layout_gravity=\"end|bottom\"\n            android:visibility=\"gone\"\n            bind:lottie_rawRes=\"@raw/lottie_voice\"/>\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_single_chat_home.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n     style=\"@style/StyleRoot\">\n\n            <androidx.recyclerview.widget.RecyclerView\n                android:id=\"@+id/list_chat\"\n                style=\"@style/FView\"\n                app:layoutManager=\"androidx.recyclerview.widget.LinearLayoutManager\"\n                tools:listitem=\"@layout/row_chat\" />\n\n        <ImageView\n            android:id=\"@+id/image_empty\"\n            style=\"@style/WView\"\n            android:visibility=\"gone\"\n            android:layout_gravity=\"center\"\n            android:src=\"@drawable/ic_messaging\"/>\n\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/f_verify.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n            <variable\n                name=\"viewmodel\"\n                type=\"com.gowtham.letschat.fragments.login.LogInViewModel\" />\n\n    </data>\n\n    <androidx.core.widget.NestedScrollView\n        style=\"@style/ScrollRoot\"\n        tools:ignore=\"LabelFor,Autofill\">\n\n        <androidx.coordinatorlayout.widget.CoordinatorLayout\n            style=\"@style/StyleRoot\"\n            android:id=\"@+id/view_holder\">\n\n            <ImageView\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:scaleType=\"centerCrop\"\n                android:src=\"@drawable/ic_otp\" />\n\n            <LinearLayout style=\"@style/FView\">\n\n                <LinearLayout\n                    style=\"@style/VWView\"\n                    android:layout_marginTop=\"190dp\"\n                    android:background=\"@drawable/shape_home_bg\"\n                    android:elevation=\"5dp\"\n                    android:paddingTop=\"5dp\"\n                    android:padding=\"20dp\">\n\n                    <TextView\n                        style=\"@style/TxtSemiStyle\"\n                        android:layout_marginTop=\"15dp\"\n                        android:textSize=\"22sp\"\n                        android:text=\"@string/txt_otp_verification\" />\n\n                    <TextView\n                        style=\"@style/TxtRgStyle\"\n                        android:layout_marginTop=\"15dp\"\n                        app:main=\"@{@string/txt_enter_otp+` `+viewmodel.country.noCode+` `+viewmodel.mobile}\"\n                        app:secondText=\"@{viewmodel.country.noCode+` `+viewmodel.mobile}\" />\n\n                    <LinearLayout\n                        style=\"@style/LView\"\n                        android:layout_marginTop=\"20dp\">\n\n                        <EditText style=\"@style/EdtOTPStyle\"\n                            android:id=\"@+id/edt_one\"\n                            android:text=\"@={viewmodel.otpOne}\"\n                            />\n\n                        <View\n                            style=\"@style/LWView\"\n                            android:layout_height=\"1dp\" />\n\n                        <EditText style=\"@style/EdtOTPStyle\"\n                            android:id=\"@+id/edt_two\"\n                            android:text=\"@={viewmodel.otpTwo}\"\n                            />\n\n                        <View\n                            style=\"@style/LWView\"\n                            android:layout_height=\"1dp\" />\n\n                        <EditText style=\"@style/EdtOTPStyle\"\n                            android:id=\"@+id/edt_three\"\n                            android:text=\"@={viewmodel.otpThree}\"\n                            />\n\n                        <View\n                            style=\"@style/LWView\"\n                            android:layout_height=\"1dp\" />\n\n                        <EditText style=\"@style/EdtOTPStyle\"\n                            android:id=\"@+id/edt_four\"\n                            android:text=\"@={viewmodel.otpFour}\"/>\n\n                        <View\n                            style=\"@style/LWView\"\n                            android:layout_height=\"1dp\" />\n\n                        <EditText style=\"@style/EdtOTPStyle\"\n                            android:id=\"@+id/edt_five\"\n                            android:text=\"@={viewmodel.otpFive}\"/>\n\n                        <View\n                            style=\"@style/LWView\"\n                            android:layout_height=\"1dp\" />\n\n                        <EditText style=\"@style/EdtOTPStyle\"\n                            android:id=\"@+id/edt_six\"\n                            android:text=\"@={viewmodel.otpSix}\"/>\n                    </LinearLayout>\n\n                    <LinearLayout\n                        style=\"@style/LView\"\n                        android:layout_marginTop=\"20dp\"\n                        android:gravity=\"center\">\n\n                        <TextView\n                            style=\"@style/TxtRgStyle\"\n                            android:textSize=\"16sp\"\n                            android:layout_marginEnd=\"5dp\"\n                            android:text=\"@string/txt_dont_receive\" />\n\n                        <TextView\n                            style=\"@style/TxtRgStyle\"\n                            android:textSize=\"16sp\"\n                            android:fontFamily=\"@font/font_semi\"\n                            android:onClick=\"@{() -> viewmodel.resendClicked()}\"\n                            android:text=\"@{viewmodel.resendTxt}\" />\n                    </LinearLayout>\n\n                    <TextView\n                        style=\"@style/BtnStyle\"\n                        android:id=\"@+id/btn_verify\"\n                        android:layout_marginTop=\"80dp\"\n                        android:text=\"@string/txt_verify\" />\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </androidx.coordinatorlayout.widget.CoordinatorLayout>\n    </androidx.core.widget.NestedScrollView>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/load_state_footer.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:gravity=\"center_horizontal\"\n    android:orientation=\"vertical\"\n    android:padding=\"8dp\">\n\n    <ProgressBar\n        android:id=\"@+id/progress_bar\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <TextView\n        android:id=\"@+id/text_view_error\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Results could not be loaded\" />\n\n    <Button\n        android:id=\"@+id/button_retry\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Retry\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/pausable_progress.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <View\n        android:id=\"@+id/back_progress\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/progress_bar_height\"\n        android:background=\"@color/progress_secondary\" />\n\n    <View\n        android:id=\"@+id/front_progress\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/progress_bar_height\"\n        android:background=\"@color/progress_primary\"\n        android:visibility=\"invisible\"\n        tools:visibility=\"visible\"/>\n\n    <View\n        android:id=\"@+id/max_progress\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/progress_bar_height\"\n        android:background=\"#fff\"\n        android:visibility=\"gone\" />\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/progress_dialog.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:layout_gravity=\"top|center_horizontal\"\n    android:background=\"@android:color/transparent\"\n    android:clickable=\"true\"\n    android:focusable=\"true\"\n    android:gravity=\"center\"\n    android:orientation=\"vertical\">\n\n    <com.gowtham.letschat.views.CustomProgress\n        android:layout_width=\"45dp\"\n        android:layout_height=\"45dp\"\n        android:layout_centerHorizontal=\"true\"\n        android:padding=\"5dp\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/row_add_member.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n        <import type=\"android.view.View\" />\n\n        <variable\n            name=\"chatUser\"\n            type=\"com.gowtham.letschat.db.data.ChatUser\" />\n    </data>\n\n    <LinearLayout\n        android:id=\"@+id/view_root\"\n        style=\"@style/VView\"\n        android:paddingStart=\"12dp\"\n        android:paddingTop=\"8dp\"\n        android:paddingEnd=\"12dp\"\n        android:paddingBottom=\"8dp\">\n\n        <LinearLayout\n            style=\"@style/LView\"\n            tools:ignore=\"ContentDescription\">\n\n            <RelativeLayout\n                android:layout_width=\"45dp\"\n                android:layout_height=\"45dp\">\n\n                <ImageView\n                    android:id=\"@+id/image_profile\"\n                    style=\"@style/FView\"\n                    android:src=\"@drawable/ic_other_user\"\n                    app:imageUrl=\"@{chatUser.user.image}\" />\n\n                <TextView\n                    android:visibility=\"@{(chatUser.user.image==null || chatUser.user.image.isEmpty) ? View.VISIBLE : View.GONE}\"\n                    android:text=\"@{chatUser.localName}\"\n                    android:layout_width=\"45dp\"\n                    android:layout_height=\"45dp\"\n                    style=\"@style/TxtNoImageUrlStyle\" />\n                \n                <com.airbnb.lottie.LottieAnimationView\n                    android:layout_width=\"25dp\"\n                    android:layout_height=\"25dp\"\n                    app:lottie_speed=\"1.5\"\n                    showSelected=\"@{chatUser.selected}\"\n                    app:lottie_rawRes=\"@raw/lottie_tick\"\n                    android:layout_alignParentBottom=\"true\"\n                    android:layout_alignParentEnd=\"true\"  />\n            </RelativeLayout>\n\n            <LinearLayout\n                style=\"@style/LWView\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_marginStart=\"10dp\"\n                android:layout_marginEnd=\"10dp\">\n\n                <TextView\n                    style=\"@style/TxtSemiSmallStyle\"\n                    android:ellipsize=\"end\"\n                    android:maxLines=\"1\"\n                    android:text=\"@{chatUser.localName}\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    style=\"@style/WView\"\n                    android:ellipsize=\"end\"\n                    android:maxLines=\"1\"\n                    android:text=\"@{chatUser.user.about}\"\n                    android:textColor=\"@color/colorGrey\"\n                    android:textSize=\"14sp\"\n                    android:visibility=\"@{chatUser.user.about.empty ? View.GONE : View.VISIBLE}\" />\n            </LinearLayout>\n        </LinearLayout>\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_audio_receive.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.Message\" />\n    </data>\n\n    <LinearLayout\n        style=\"@style/VView\"\n        android:paddingStart=\"12dp\"\n        android:paddingEnd=\"12dp\"\n        android:paddingBottom=\"10dp\"\n        android:paddingTop=\"10dp\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginStart=\"5dp\"\n        android:layout_marginEnd=\"120dp\"\n        android:background=\"@drawable/shape_audio_bg\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout style=\"@style/LView\">\n\n            <RelativeLayout\n               style=\"@style/WView\">\n\n                <ProgressBar\n                    android:id=\"@+id/progress_buffer\"\n                    style=\"@style/WView\"\n                    android:layout_marginEnd=\"5dp\"\n                    android:layout_width=\"26dp\"\n                    android:layout_height=\"26dp\"\n                    android:layout_centerInParent=\"true\"\n                    android:visibility=\"@{message.status==0 ? View.VISIBLE : View.GONE}\" />\n\n                <ImageView\n                    android:id=\"@+id/img_play\"\n                    android:layout_centerInParent=\"true\"\n                    android:layout_width=\"26dp\"\n                    android:layout_height=\"26dp\"\n                    android:padding=\"4dp\"\n                    android:src=\"@drawable/ic_action_play\" />\n            </RelativeLayout>\n\n            <com.gowtham.letschat.views.StoriesProgressView\n                android:id=\"@+id/progress_bar\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center_vertical\"\n                android:paddingLeft=\"8dp\"\n                android:paddingRight=\"8dp\"\n                android:layout_marginStart=\"10dp\" />\n\n        </LinearLayout>\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                android:textColor=\"@color/colorWhite\"\n                app:showMsgTime=\"@{message}\" />\n\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_audio_sent.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.Message\" />\n    </data>\n\n    <LinearLayout\n        style=\"@style/VView\"\n        android:paddingStart=\"12dp\"\n        android:paddingEnd=\"12dp\"\n        android:paddingBottom=\"10dp\"\n        android:paddingTop=\"10dp\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginEnd=\"5dp\"\n        android:layout_marginStart=\"120dp\"\n        android:background=\"@drawable/shape_audio_bg\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout style=\"@style/LView\">\n\n            <RelativeLayout\n                style=\"@style/WView\">\n\n                <ProgressBar\n                    android:id=\"@+id/progress_buffer\"\n                    style=\"@style/WView\"\n                    android:layout_marginEnd=\"5dp\"\n                    android:layout_width=\"26dp\"\n                    android:layout_height=\"26dp\"\n                    android:layout_centerInParent=\"true\"\n                    android:visibility=\"@{message.status==0 ? View.VISIBLE : View.GONE}\" />\n\n                <ImageView\n                    android:id=\"@+id/img_play\"\n                    android:layout_width=\"26dp\"\n                    android:layout_height=\"26dp\"\n                    android:padding=\"4dp\"\n                    android:layout_centerInParent=\"true\"\n                    android:visibility=\"@{message.status==0 ? View.GONE : View.VISIBLE}\"\n                    android:src=\"@drawable/ic_action_play\" />\n            </RelativeLayout>\n\n            <com.gowtham.letschat.views.StoriesProgressView\n                android:id=\"@+id/progress_bar\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center_vertical\"\n                android:paddingLeft=\"8dp\"\n                android:paddingRight=\"8dp\"\n                android:layout_marginStart=\"10dp\" />\n\n        </LinearLayout>\n\n        <LinearLayout\n            style=\"@style/WLView\"\n            android:layout_gravity=\"end\">\n\n            <TextView\n                android:id=\"@+id/txt_msg_status\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"14sp\"\n                android:textColor=\"@color/colorWhite\"\n                android:layout_marginEnd=\"5dp\"\n                android:layout_gravity=\"center_vertical\"\n                android:visibility=\"@{message.status==0 ? View.GONE : View.VISIBLE}\"\n                messageStatus=\"@{message.status}\" />\n\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                android:textColor=\"@color/colorWhite\"\n                app:showMsgTime=\"@{message}\" />\n        </LinearLayout>\n\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_chat.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"chatUser\"\n            type=\"com.gowtham.letschat.db.data.ChatUserWithMessages\" />\n    </data>\n    <LinearLayout\n        android:id=\"@+id/view_root\"\n        style=\"@style/VView\"\n        android:background=\"?attr/selectableItemBackground\"\n        android:paddingStart=\"8dp\"\n        android:paddingTop=\"5dp\"\n        android:paddingEnd=\"8dp\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout\n            style=\"@style/LView\">\n\n            <RelativeLayout style=\"@style/WView\">\n\n                <ImageView\n                    android:id=\"@+id/image_profile\"\n                    android:layout_width=\"50dp\"\n                    android:layout_height=\"50dp\"\n                    android:src=\"@drawable/ic_other_user\"\n                    app:imageUrl=\"@{chatUser.user.user.image}\" />\n\n                <TextView\n                    android:visibility=\"@{(chatUser.user.user.image==null || chatUser.user.user.image.isEmpty) ? View.VISIBLE : View.GONE}\"\n                    android:text=\"@{chatUser.user.localName}\"\n                    style=\"@style/TxtNoImageUrlStyle\" />\n            </RelativeLayout>\n\n\n            <LinearLayout\n                style=\"@style/LWView\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_marginStart=\"15dp\"\n                android:layout_marginEnd=\"10dp\">\n\n                <TextView\n                    style=\"@style/TxtSemiSmallStyle\"\n                    android:ellipsize=\"end\"\n                    android:maxLines=\"1\"\n                    android:textSize=\"16sp\"\n                    android:text=\"@{chatUser.user.localName}\" />\n\n                <LinearLayout style=\"@style/WLView\"\n                    android:layout_width=\"match_parent\">\n\n                    <TextView\n                        style=\"@style/LWView\"\n                        android:maxLines=\"1\"\n                        lastMessage=\"@{chatUser.messages}\"\n                        android:textColor=\"@color/colorGrey\"\n                        android:ellipsize=\"end\"\n                        android:textSize=\"14sp\" />\n\n                    <TextView\n                        style=\"@style/TxtRgStyle\"\n                        android:gravity=\"start\"\n                        android:maxLines=\"1\"\n                        android:layout_marginStart=\"7dp\"\n                        messageSendTime=\"@{chatUser.messages}\"\n                        android:textColor=\"@color/colorGreyLt\"\n                        android:textSize=\"12sp\" />\n                </LinearLayout>\n            </LinearLayout>\n\n\n            <TextView\n                style=\"@style/TxtRgStyle\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_marginEnd=\"1dp\"\n                android:background=\"@drawable/shape_unread_count\"\n                android:paddingStart=\"7dp\"\n                android:paddingEnd=\"7dp\"\n                android:paddingBottom=\"2dp\"\n                setUnReadCount2=\"@{chatUser.user.unRead}\"\n                android:textColor=\"@color/colorWhite\"\n                android:textSize=\"15sp\" />\n\n\n        </LinearLayout>\n\n        <View\n            style=\"@style/LineView\"\n            android:layout_marginStart=\"65dp\"\n            android:layout_marginTop=\"10dp\"\n            android:background=\"@color/colorGreyLt\" />\n\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_chip.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n    <variable\n        name=\"chatUser\"\n        type=\"com.gowtham.letschat.db.data.ChatUser\"/>\n    </data>\n\n    <RelativeLayout\n        style=\"@style/WView\">\n\n    <com.google.android.material.chip.Chip\n        android:id=\"@+id/chip\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@{chatUser.localName}\"\n        app:chipIcon=\"@drawable/ic_other_user\"\n        app:chipIconSize=\"34dp\"\n        app:chipBackgroundColor=\"@color/colorPrimary2\"\n        android:layout_marginEnd=\"5dp\"\n        android:layout_centerVertical=\"true\"\n        android:checkable=\"false\"\n        loadAsDrawable=\"@{chatUser}\"\n        app:chipStartPadding=\"0dp\"\n        app:closeIconTint=\"@color/colorWhite\"\n        style=\"@style/Widget.MaterialComponents.Chip.Entry\"\n        android:textColor=\"@color/colorWhite\" />\n\n        <TextView\n            android:id=\"@+id/txtUrl\"\n            android:layout_width=\"34dp\"\n            android:layout_height=\"34dp\"\n            showTxtView=\"@{chatUser}\"\n            android:textSize=\"16sp\"\n            android:layout_centerVertical=\"true\"\n            style=\"@style/TxtNoImageUrlStyle\"/>\n\n    </RelativeLayout>\n\n</layout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_contact.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n        <import type=\"android.view.View\" />\n\n        <variable\n            name=\"chatUser\"\n            type=\"com.gowtham.letschat.db.data.ChatUser\" />\n    </data>\n\n    <LinearLayout\n        android:id=\"@+id/view_root\"\n        style=\"@style/VView\"\n        android:background=\"?attr/selectableItemBackground\"\n        android:paddingStart=\"12dp\"\n        android:paddingTop=\"8dp\"\n        android:paddingEnd=\"12dp\"\n        android:paddingBottom=\"8dp\">\n\n        <LinearLayout\n            style=\"@style/LView\"\n            tools:ignore=\"ContentDescription\">\n\n            <RelativeLayout style=\"@style/WView\">\n\n                <ImageView\n                    android:id=\"@+id/image_profile\"\n                    android:layout_width=\"50dp\"\n                    android:layout_height=\"50dp\"\n                    android:src=\"@drawable/ic_other_user\"\n                    app:imageUrl=\"@{chatUser.user.image}\" />\n\n                <TextView\n                    android:visibility=\"@{(chatUser.user.image==null || chatUser.user.image.isEmpty) ? View.VISIBLE : View.GONE}\"\n                    android:text=\"@{chatUser.localName}\"\n                    style=\"@style/TxtNoImageUrlStyle\" />\n            </RelativeLayout>\n\n            <LinearLayout\n                style=\"@style/LWView\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_marginStart=\"15dp\"\n                android:layout_marginEnd=\"10dp\">\n\n                <TextView\n                    style=\"@style/TxtSemiSmallStyle\"\n                    android:ellipsize=\"end\"\n                    android:maxLines=\"1\"\n                    android:text=\"@{chatUser.localName}\"\n                    android:textSize=\"17sp\" />\n\n                <TextView\n                    style=\"@style/WView\"\n                    android:ellipsize=\"end\"\n                    android:maxLines=\"1\"\n                    android:text=\"@{chatUser.user.about}\"\n                    android:textColor=\"@color/colorGrey\"\n                    android:textSize=\"15sp\"\n                    android:visibility=\"@{chatUser.user.about.empty ? View.GONE : View.VISIBLE}\" />\n            </LinearLayout>\n        </LinearLayout>\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_country.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n        <variable\n            name=\"country\"\n            type=\"com.gowtham.letschat.models.Country\" />\n    </data>\n\n        <LinearLayout\n            style=\"@style/LView\"\n            android:clickable=\"true\"\n            android:focusable=\"true\"\n            android:padding=\"16dp\"\n            android:id=\"@+id/view_root\"\n            android:background=\"?attr/selectableItemBackground\"\n            >\n\n            <TextView\n                android:id=\"@+id/txt_name\"\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_weight=\"1\"\n                android:fontFamily=\"@font/font_semi\"\n                android:singleLine=\"true\"\n                android:text=\"@{country.name}\"\n                android:textColor=\"@color/colorTxt\"\n                android:textSize=\"16sp\" />\n\n            <TextView\n                android:id=\"@+id/txt_code\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_marginStart=\"10dp\"\n                android:text=\"@{country.noCode}\"\n                android:fontFamily=\"@font/font_semi\"\n                android:textColor=\"@color/colorTxt\"\n                android:textSize=\"16sp\" />\n\n        </LinearLayout>\n\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_group_audio_receive.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.GroupMessage\" />\n    </data>\n\n    <LinearLayout\n        style=\"@style/VView\"\n        android:paddingStart=\"12dp\"\n        android:paddingEnd=\"12dp\"\n        android:paddingBottom=\"10dp\"\n        android:paddingTop=\"10dp\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginStart=\"5dp\"\n        android:layout_marginEnd=\"120dp\"\n        android:background=\"@drawable/shape_audio_bg\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout style=\"@style/LView\">\n\n            <RelativeLayout\n               style=\"@style/WView\">\n\n                <ProgressBar\n                    android:id=\"@+id/progress_buffer\"\n                    style=\"@style/WView\"\n                    android:layout_marginEnd=\"5dp\"\n                    android:layout_width=\"26dp\"\n                    android:layout_height=\"26dp\"\n                    android:visibility=\"gone\"\n                    android:layout_centerInParent=\"true\" />\n\n                <ImageView\n                    android:id=\"@+id/img_play\"\n                    android:layout_centerInParent=\"true\"\n                    android:layout_width=\"26dp\"\n                    android:layout_height=\"26dp\"\n                    android:padding=\"4dp\"\n                    android:src=\"@drawable/ic_action_play\" />\n            </RelativeLayout>\n\n            <com.gowtham.letschat.views.StoriesProgressView\n                android:id=\"@+id/progress_bar\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center_vertical\"\n                android:paddingLeft=\"8dp\"\n                android:paddingRight=\"8dp\"\n                android:layout_marginStart=\"10dp\" />\n\n        </LinearLayout>\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                android:textColor=\"@color/colorWhite\"\n                app:showGrpMsgTime=\"@{message}\" />\n\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_group_audio_sent.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.GroupMessage\" />\n    </data>\n\n    <LinearLayout\n        style=\"@style/VView\"\n        android:paddingStart=\"12dp\"\n        android:paddingEnd=\"12dp\"\n        android:paddingBottom=\"10dp\"\n        android:paddingTop=\"10dp\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginEnd=\"5dp\"\n        android:layout_marginStart=\"120dp\"\n        android:background=\"@drawable/shape_audio_bg\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout style=\"@style/LView\">\n\n            <RelativeLayout\n                style=\"@style/WView\">\n\n                <ProgressBar\n                    android:id=\"@+id/progress_buffer\"\n                    style=\"@style/WView\"\n                    android:layout_marginEnd=\"5dp\"\n                    android:layout_width=\"26dp\"\n                    android:layout_height=\"26dp\"\n                    android:layout_centerInParent=\"true\"\n                    android:visibility=\"@{message.status[0]==0 ? View.VISIBLE : View.GONE}\" />\n\n                <ImageView\n                    android:id=\"@+id/img_play\"\n                    android:layout_width=\"26dp\"\n                    android:layout_height=\"26dp\"\n                    android:padding=\"4dp\"\n                    android:layout_centerInParent=\"true\"\n                    android:visibility=\"@{message.status[0]==0 ? View.GONE : View.VISIBLE}\"\n                    android:src=\"@drawable/ic_action_play\" />\n            </RelativeLayout>\n\n            <com.gowtham.letschat.views.StoriesProgressView\n                android:id=\"@+id/progress_bar\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center_vertical\"\n                android:paddingLeft=\"8dp\"\n                android:paddingRight=\"8dp\"\n                android:layout_marginStart=\"10dp\" />\n\n        </LinearLayout>\n\n        <LinearLayout\n            style=\"@style/WLView\"\n            android:layout_gravity=\"end\">\n\n            <TextView\n                android:id=\"@+id/txt_msg_status\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"14sp\"\n                android:textColor=\"@color/colorWhite\"\n                android:layout_marginEnd=\"5dp\"\n                android:layout_gravity=\"center_vertical\"\n                android:visibility=\"@{message.status[0]==0 ? View.GONE : View.VISIBLE}\"\n                app:groupMessageStatus=\"@{message}\" />\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                android:textColor=\"@color/colorWhite\"\n                app:showGrpMsgTime=\"@{message}\" />\n        </LinearLayout>\n\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_group_chat.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"groupChat\"\n            type=\"com.gowtham.letschat.db.data.GroupWithMessages\" />\n    </data>\n    <LinearLayout\n        android:id=\"@+id/view_root\"\n        style=\"@style/VView\"\n        android:background=\"?attr/selectableItemBackground\"\n        android:paddingStart=\"8dp\"\n        android:paddingTop=\"5dp\"\n        android:paddingEnd=\"8dp\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout\n            style=\"@style/LView\">\n\n            <RelativeLayout style=\"@style/WView\">\n\n                <ImageView\n                    android:id=\"@+id/image_profile\"\n                    android:layout_width=\"50dp\"\n                    android:layout_height=\"50dp\"\n                    android:src=\"@drawable/ic_other_user\"\n                    app:imageUrl=\"@{groupChat.group.image}\" />\n\n                <TextView\n                    android:visibility=\"@{(groupChat.group.image==null || groupChat.group.image.isEmpty) ? View.VISIBLE : View.GONE}\"\n                    android:text=\"@{groupChat.group.id}\"\n                    style=\"@style/TxtNoImageUrlStyle\" />\n            </RelativeLayout>\n\n\n            <LinearLayout\n                style=\"@style/LWView\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_marginStart=\"15dp\"\n                android:layout_marginEnd=\"10dp\">\n\n                <TextView\n                    style=\"@style/TxtSemiSmallStyle\"\n                    android:ellipsize=\"end\"\n                    android:maxLines=\"1\"\n                    android:textSize=\"16sp\"\n                    setGroupName=\"@{groupChat.group}\"/>\n\n                <LinearLayout\n                    android:layout_width=\"match_parent\"\n                    style=\"@style/WLView\">\n\n                    <TextView\n                        style=\"@style/LWView\"\n                        android:maxLines=\"1\"\n                        android:ellipsize=\"end\"\n                        groupLastMessage=\"@{groupChat}\"\n                        android:textColor=\"@color/colorGrey\"\n                        android:textSize=\"14sp\" />\n\n                    <TextView\n                        style=\"@style/TxtRgStyle\"\n                        android:gravity=\"start\"\n                        android:maxLines=\"1\"\n                        android:layout_marginStart=\"7dp\"\n                        setGroupMessageSendTime=\"@{groupChat.messages}\"\n                        android:textColor=\"@color/colorGreyLt\"\n                        android:textSize=\"12sp\" />\n                </LinearLayout>\n            </LinearLayout>\n\n            <TextView\n                style=\"@style/TxtRgStyle\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_marginEnd=\"1dp\"\n                android:background=\"@drawable/shape_unread_count\"\n                android:paddingStart=\"7dp\"\n                android:paddingEnd=\"7dp\"\n                android:paddingBottom=\"2dp\"\n                setGroupUnReadCount=\"@{groupChat.group.unRead}\"\n                android:textColor=\"@color/colorWhite\"\n                android:textSize=\"15sp\" />\n\n        </LinearLayout>\n\n        <View\n            style=\"@style/LineView\"\n            android:layout_marginStart=\"65dp\"\n            android:layout_marginTop=\"10dp\"\n            android:background=\"@color/colorGreyLt\" />\n\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_group_image_receive.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.GroupMessage\" />\n\n        <variable\n            name=\"chatUsers\"\n            type=\"com.gowtham.letschat.db.data.ChatUser[]\" />\n\n    </data>\n\n    <LinearLayout\n        style=\"@style/VView\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginBottom=\"5dp\">\n\n        <LinearLayout\n            style=\"@style/WVView\"\n            android:layout_marginEnd=\"90dp\"\n            android:paddingStart=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:paddingEnd=\"10dp\"\n            android:paddingBottom=\"5dp\">\n\n            <LinearLayout style=\"@style/LView\">\n\n                <TextView\n                    style=\"@style/TxtSemiSmallStyle\"\n                    android:layout_width=\"0dp\"\n                    android:layout_weight=\"1\"\n                    android:hint=\"Name\"\n                    android:textColor=\"@color/colorTop\"\n                    chatUsers=\"@{chatUsers}\"\n                    message=\"@{message}\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    style=\"@style/TxtRgStyle\"\n                    showUserIdIfNotLocalSaved=\"@{chatUsers}\"\n                    currentMessage=\"@{message}\"\n                    android:textColor=\"@color/colorDefaultBg\"\n                    android:textSize=\"14sp\" />\n\n            </LinearLayout>\n\n            <ImageView\n                loadGroupMsgImage=\"@{message}\"\n                android:layout_width=\"240dp\"\n                android:layout_height=\"280dp\"\n                android:scaleType=\"centerCrop\"\n                android:id=\"@+id/image_msg\" />\n        </LinearLayout>\n\n        <TextView\n            android:id=\"@+id/txt_msg_time\"\n            style=\"@style/TxtRgStyle\"\n            android:layout_marginStart=\"5dp\"\n            showGrpMsgTime=\"@{message}\"\n            android:textSize=\"16sp\" />\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_group_image_sent.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.GroupMessage\" />\n    </data>\n\n    <LinearLayout style=\"@style/VView\"\n        android:layout_marginEnd=\"5dp\"\n        android:layout_marginTop=\"5dp\">\n\n            <ImageView\n                loadGroupMsgImage=\"@{message}\"\n                android:layout_gravity=\"end\"\n                android:layout_width=\"240dp\"\n                android:layout_height=\"280dp\"\n                android:scaleType=\"centerCrop\"\n                android:id=\"@+id/image_msg\" />\n\n        <LinearLayout\n            style=\"@style/WLView\"\n            android:layout_marginEnd=\"2dp\"\n            android:layout_gravity=\"end\">\n\n            <TextView\n                android:id=\"@+id/txt_msg_status\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"14sp\"\n                android:layout_marginEnd=\"5dp\"\n                android:visibility=\"@{message.status[0]==0 ? View.GONE : View.VISIBLE}\"\n                groupMessageStatus=\"@{message}\" />\n\n            <ProgressBar\n                style=\"@style/WView\"\n                android:layout_marginEnd=\"5dp\"\n                android:layout_width=\"20dp\"\n                android:layout_height=\"20dp\"\n                android:layout_gravity=\"center_vertical\"\n                android:visibility=\"@{message.status[0]==0 ? View.VISIBLE : View.GONE}\" />\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                showGrpMsgTime=\"@{message}\" />\n        </LinearLayout>\n\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_group_sticker_receive.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.GroupMessage\" />\n\n        <variable\n            name=\"chatUsers\"\n            type=\"com.gowtham.letschat.db.data.ChatUser[]\" />\n\n    </data>\n\n    <LinearLayout\n        style=\"@style/VView\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginBottom=\"5dp\">\n\n        <LinearLayout\n            style=\"@style/WVView\"\n            android:layout_marginEnd=\"90dp\"\n            android:paddingStart=\"5dp\"\n            android:paddingTop=\"5dp\"\n            android:paddingEnd=\"10dp\"\n            android:paddingBottom=\"5dp\">\n\n            <LinearLayout style=\"@style/LView\">\n\n                <TextView\n                    style=\"@style/TxtSemiSmallStyle\"\n                    android:layout_width=\"0dp\"\n                    android:layout_weight=\"1\"\n                    android:hint=\"Name\"\n                    android:textColor=\"@color/colorTop\"\n                    chatUsers=\"@{chatUsers}\"\n                    message=\"@{message}\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    style=\"@style/TxtRgStyle\"\n                    showUserIdIfNotLocalSaved=\"@{chatUsers}\"\n                    currentMessage=\"@{message}\"\n                    android:textColor=\"@color/colorDefaultBg\"\n                    android:textSize=\"14sp\" />\n\n            </LinearLayout>\n\n            <ImageView\n                style=\"@style/WView\"\n                loadGroupMsgImage=\"@{message}\"\n                android:minHeight=\"130dp\"\n                android:minWidth=\"130dp\"\n                android:scaleType=\"fitCenter\"\n                android:id=\"@+id/image_msg\" />\n        </LinearLayout>\n\n        <TextView\n            android:id=\"@+id/txt_msg_time\"\n            style=\"@style/TxtRgStyle\"\n            android:layout_marginStart=\"5dp\"\n            showGrpMsgTime=\"@{message}\"\n            android:textSize=\"16sp\" />\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_group_sticker_sent.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.GroupMessage\" />\n    </data>\n\n    <LinearLayout style=\"@style/VView\"\n        android:layout_marginEnd=\"5dp\">\n\n            <ImageView\n                style=\"@style/WView\"\n                loadGroupMsgImage=\"@{message}\"\n                android:layout_gravity=\"end\"\n                android:layout_marginStart=\"60dp\"\n                android:minHeight=\"130dp\"\n                android:minWidth=\"130dp\"\n                android:scaleType=\"fitCenter\"\n                android:id=\"@+id/image_msg\" />\n\n        <LinearLayout\n            style=\"@style/WLView\"\n            android:layout_marginEnd=\"2dp\"\n            android:layout_gravity=\"end\">\n\n            <TextView\n                android:id=\"@+id/txt_msg_status\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"14sp\"\n                android:layout_marginEnd=\"5dp\"\n                android:visibility=\"@{message.status[0]==0 ? View.GONE : View.VISIBLE}\"\n                groupMessageStatus=\"@{message}\" />\n\n            <ProgressBar\n                style=\"@style/WView\"\n                android:layout_marginEnd=\"5dp\"\n                android:layout_width=\"20dp\"\n                android:layout_height=\"20dp\"\n                android:layout_gravity=\"center_vertical\"\n                android:visibility=\"@{message.status[0]==0 ? View.VISIBLE : View.GONE}\" />\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                showGrpMsgTime=\"@{message}\" />\n        </LinearLayout>\n\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_group_txt_sent.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.GroupMessage\" />\n    </data>\n\n    <LinearLayout\n        style=\"@style/VView\"\n        android:layout_marginEnd=\"5dp\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginBottom=\"5dp\">\n\n        <TextView\n            android:id=\"@+id/txt_msg\"\n            style=\"@style/WView\"\n            android:text=\"@{message.textMessage.text}\"\n            android:paddingStart=\"12dp\"\n            android:paddingEnd=\"10dp\"\n            android:paddingTop=\"3dp\"\n            android:paddingBottom=\"5dp\"\n            android:layout_gravity=\"end\"\n            android:layout_marginStart=\"90dp\"\n            android:textSize=\"18sp\"\n            android:textColor=\"@color/colorWhite\"\n            android:background=\"@drawable/shape_send_msg\" />\n\n        <LinearLayout\n            style=\"@style/WLView\"\n            android:layout_marginEnd=\"2dp\"\n            android:layout_gravity=\"end\">\n\n            <TextView\n                android:id=\"@+id/txt_msg_status\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"14sp\"\n                android:layout_marginEnd=\"5dp\"\n                groupMessageStatus=\"@{message}\" />\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                showGrpMsgTime=\"@{message}\" />\n        </LinearLayout>\n\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_grp_txt_receive.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.GroupMessage\" />\n\n        <variable\n            name=\"chatUsers\"\n            type=\"com.gowtham.letschat.db.data.ChatUser[]\" />\n\n    </data>\n\n    <LinearLayout\n        style=\"@style/VView\"\n        android:layout_marginStart=\"5dp\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginBottom=\"5dp\">\n\n        <LinearLayout\n            android:id=\"@+id/view_msg_holder\"\n            style=\"@style/VView\"\n            android:layout_marginEnd=\"90dp\"\n            android:background=\"@drawable/shape_receive_msg\"\n            android:paddingStart=\"12dp\"\n            android:paddingTop=\"5dp\"\n            android:paddingEnd=\"10dp\"\n            android:paddingBottom=\"5dp\">\n\n            <LinearLayout\n                android:id=\"@+id/view_detail\"\n                style=\"@style/LView\">\n\n                <TextView\n                    style=\"@style/TxtSemiSmallStyle\"\n                    android:layout_width=\"0dp\"\n                    android:layout_weight=\"1\"\n                    android:hint=\"Name\"\n                    android:textColor=\"@color/colorTop\"\n                    chatUsers=\"@{chatUsers}\"\n                    message=\"@{message}\"\n                    android:textSize=\"16sp\" />\n\n                <TextView\n                    style=\"@style/TxtRgStyle\"\n                    showUserIdIfNotLocalSaved=\"@{chatUsers}\"\n                    currentMessage=\"@{message}\"\n                    android:textColor=\"@color/colorDefaultBg\"\n                    android:textSize=\"14sp\" />\n\n            </LinearLayout>\n\n            <TextView\n                android:id=\"@+id/txt_msg\"\n                style=\"@style/WView\"\n                android:hint=\"This is received message\"\n                android:text=\"@{message.textMessage.text}\"\n                android:textColor=\"@color/colorWhite\"\n                android:textSize=\"18sp\" />\n\n\n        </LinearLayout>\n\n        <TextView\n            android:id=\"@+id/txt_msg_time\"\n            style=\"@style/TxtRgStyle\"\n            android:layout_marginStart=\"2dp\"\n            showGrpMsgTime=\"@{message}\"\n            android:textSize=\"16sp\" />\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_image_receive.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.Message\" />\n    </data>\n\n    <LinearLayout style=\"@style/VView\"\n        android:layout_marginEnd=\"60dp\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginStart=\"5dp\">\n\n        <ImageView\n            loadImage=\"@{message}\"\n            android:layout_gravity=\"start\"\n            android:layout_width=\"240dp\"\n            android:layout_height=\"280dp\"\n            android:scaleType=\"centerCrop\"\n            android:id=\"@+id/image_msg\" />\n\n        <LinearLayout\n            style=\"@style/WLView\"\n            android:layout_marginStart=\"2dp\"\n            android:layout_gravity=\"start\">\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                showMsgTime=\"@{message}\" />\n\n        </LinearLayout>\n\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_image_sent.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.Message\" />\n    </data>\n\n    <LinearLayout style=\"@style/VView\"\n        android:layout_marginEnd=\"5dp\"\n        android:layout_marginTop=\"5dp\">\n\n            <ImageView\n                loadImage=\"@{message}\"\n                android:layout_gravity=\"end\"\n                android:layout_width=\"240dp\"\n                android:layout_height=\"280dp\"\n                android:scaleType=\"centerCrop\"\n                android:id=\"@+id/image_msg\" />\n\n        <LinearLayout\n            style=\"@style/WLView\"\n            android:layout_marginEnd=\"2dp\"\n            android:layout_gravity=\"end\">\n\n            <TextView\n                android:id=\"@+id/txt_msg_status\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"14sp\"\n                android:layout_marginEnd=\"5dp\"\n                android:visibility=\"@{message.status==0 ? View.GONE : View.VISIBLE}\"\n                messageStatus=\"@{message.status}\" />\n\n            <ProgressBar\n                style=\"@style/WView\"\n                android:layout_marginEnd=\"5dp\"\n                android:layout_width=\"20dp\"\n                android:layout_height=\"20dp\"\n                android:layout_gravity=\"center_vertical\"\n                android:visibility=\"@{message.status==0 ? View.VISIBLE : View.GONE}\" />\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                showMsgTime=\"@{message}\" />\n        </LinearLayout>\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_receive_message.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.Message\" />\n    </data>\n\n    <LinearLayout\n        style=\"@style/WVView\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginStart=\"5dp\"\n        android:layout_marginBottom=\"5dp\">\n\n        <TextView\n            android:id=\"@+id/txt_msg\"\n            style=\"@style/WView\"\n            android:text=\"@{message.textMessage.text}\"\n            android:hint=\"This is received message\"\n            android:paddingStart=\"12dp\"\n            android:paddingEnd=\"10dp\"\n            android:paddingTop=\"5dp\"\n            android:paddingBottom=\"5dp\"\n            android:layout_marginEnd=\"90dp\"\n            android:textSize=\"18sp\"\n            android:textColor=\"@color/colorWhite\"\n            android:background=\"@drawable/shape_receive_msg\" />\n\n        <TextView\n            android:layout_marginStart=\"2dp\"\n            android:id=\"@+id/txt_msg_time\"\n            style=\"@style/TxtRgStyle\"\n            android:textSize=\"16sp\"\n            showMsgTime=\"@{message}\" />\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_search_contact.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n        <import type=\"android.view.View\" />\n\n        <variable\n            name=\"profile\"\n            type=\"com.gowtham.letschat.models.UserProfile\" />\n    </data>\n\n    <LinearLayout\n        android:id=\"@+id/view_root\"\n        style=\"@style/VView\"\n        android:background=\"?attr/selectableItemBackground\"\n        android:paddingStart=\"12dp\"\n        android:paddingTop=\"8dp\"\n        android:paddingEnd=\"12dp\"\n        android:paddingBottom=\"8dp\">\n\n        <LinearLayout\n            style=\"@style/LView\"\n            tools:ignore=\"ContentDescription\">\n\n            <RelativeLayout style=\"@style/WView\">\n\n                <ImageView\n                    android:id=\"@+id/image_profile\"\n                    android:layout_width=\"50dp\"\n                    android:layout_height=\"50dp\"\n                    android:src=\"@drawable/ic_other_user\"\n                    app:imageUrl=\"@{profile.image}\" />\n\n                <TextView\n                    android:visibility=\"@{profile.image.isEmpty ? View.VISIBLE : View.GONE}\"\n                    android:text=\"@{profile.userName}\"\n                    style=\"@style/TxtNoImageUrlStyle\" />\n            </RelativeLayout>\n\n            <LinearLayout\n                style=\"@style/LWView\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_marginStart=\"15dp\"\n                android:layout_marginEnd=\"10dp\">\n\n                <TextView\n                    style=\"@style/TxtSemiSmallStyle\"\n                    android:ellipsize=\"end\"\n                    android:maxLines=\"1\"\n                    android:text=\"@{profile.userName}\"\n                    android:textSize=\"17sp\" />\n\n                <TextView\n                    style=\"@style/WView\"\n                    android:ellipsize=\"end\"\n                    android:maxLines=\"1\"\n                    android:text=\"@{profile.about}\"\n                    android:textColor=\"@color/colorGrey\"\n                    android:textSize=\"15sp\"\n                    android:visibility=\"@{profile.about.empty ? View.GONE : View.VISIBLE}\" />\n            </LinearLayout>\n        </LinearLayout>\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "app/src/main/res/layout/row_sent_message.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n        <import type=\"com.gowtham.letschat.utils.BindingAdapters\"/>\n        <import type=\"java.util.ArrayList\"/>\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.Message\" />\n\n        <variable\n            name=\"adapterPosition\"\n            type=\"Integer\" />\n\n        <variable\n            name=\"messageList\"\n            type=\"ArrayList&lt;com.gowtham.letschat.db.data.Message&gt;\"\n            />\n    </data>\n\n    <LinearLayout\n        style=\"@style/VView\"\n        android:layout_marginEnd=\"5dp\"\n        android:layout_marginTop=\"5dp\"\n        android:layout_marginBottom=\"5dp\">\n\n        <TextView\n            android:id=\"@+id/txt_msg\"\n            style=\"@style/WView\"\n            android:text=\"@{message.textMessage.text}\"\n            android:paddingStart=\"12dp\"\n            android:paddingEnd=\"10dp\"\n            android:paddingTop=\"3dp\"\n            android:paddingBottom=\"5dp\"\n            android:layout_gravity=\"end\"\n            android:layout_marginStart=\"90dp\"\n            android:textSize=\"18sp\"\n            android:textColor=\"@color/colorWhite\"\n            android:background=\"@drawable/shape_send_msg\" />\n\n        <LinearLayout\n            style=\"@style/WLView\"\n            android:layout_marginEnd=\"2dp\"\n            android:layout_gravity=\"end\">\n\n            <TextView\n                android:id=\"@+id/txt_msg_status\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"14sp\"\n                android:layout_marginEnd=\"5dp\"\n                messageStatus=\"@{message.status}\" />\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                showMsgTime=\"@{message}\"  />\n        </LinearLayout>\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_sticker_receive.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.Message\" />\n    </data>\n\n    <LinearLayout style=\"@style/VView\"\n        android:layout_marginEnd=\"60dp\"\n        android:layout_marginStart=\"5dp\">\n\n        <ImageView\n            style=\"@style/WView\"\n            loadImage=\"@{message}\"\n            android:layout_gravity=\"start\"\n            android:minHeight=\"130dp\"\n            android:minWidth=\"130dp\"\n            android:scaleType=\"fitCenter\"\n            android:id=\"@+id/image_msg\" />\n\n        <LinearLayout\n            style=\"@style/WLView\"\n            android:layout_marginStart=\"2dp\"\n            android:layout_gravity=\"start\">\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                showMsgTime=\"@{message}\" />\n\n        </LinearLayout>\n\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/row_sticker_sent.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <data>\n        <import type=\"android.view.View\" />\n        <variable\n            name=\"message\"\n            type=\"com.gowtham.letschat.db.data.Message\" />\n    </data>\n\n    <LinearLayout style=\"@style/VView\"\n        android:layout_marginEnd=\"5dp\">\n\n            <ImageView\n                style=\"@style/WView\"\n                loadImage=\"@{message}\"\n                android:layout_gravity=\"end\"\n                android:layout_marginStart=\"60dp\"\n                android:minHeight=\"130dp\"\n                android:minWidth=\"130dp\"\n                android:scaleType=\"fitCenter\"\n                android:id=\"@+id/image_msg\" />\n\n        <LinearLayout\n            style=\"@style/WLView\"\n            android:layout_marginEnd=\"2dp\"\n            android:layout_gravity=\"end\">\n\n            <TextView\n                android:id=\"@+id/txt_msg_status\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"14sp\"\n                android:layout_marginEnd=\"5dp\"\n                android:visibility=\"@{message.status==0 ? View.GONE : View.VISIBLE}\"\n                messageStatus=\"@{message.status}\" />\n\n            <ProgressBar\n                style=\"@style/WView\"\n                android:layout_marginEnd=\"5dp\"\n                android:layout_width=\"20dp\"\n                android:layout_height=\"20dp\"\n                android:layout_gravity=\"center_vertical\"\n                android:visibility=\"@{message.status==0 ? View.VISIBLE : View.GONE}\" />\n\n            <TextView\n                android:id=\"@+id/txt_msg_time\"\n                style=\"@style/TxtRgStyle\"\n                android:textSize=\"16sp\"\n                showMsgTime=\"@{message}\" />\n        </LinearLayout>\n\n\n    </LinearLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/view_chat_btm.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n        <variable\n            name=\"viewmodel\"\n            type=\"com.gowtham.letschat.fragments.single_chat.SingleChatViewModel\" />\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n        style=\"@style/LView\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout\n            style=\"@style/LView\"\n            android:gravity=\"center_vertical\"\n            android:padding=\"5dp\"\n            android:layout_marginBottom=\"5dp\">\n\n            <ImageView\n                android:id=\"@+id/image_add\"\n                android:layout_width=\"40dp\"\n                android:layout_height=\"40dp\"\n                android:layout_gravity=\"bottom\"\n                android:layout_marginStart=\"5dp\"\n                android:layout_marginBottom=\"3dp\"\n                android:src=\"@drawable/ic_add_circle\"\n                app:tint=\"@color/colorPrimary\" />\n\n            <RelativeLayout\n                style=\"@style/LWView\"\n                android:layout_marginStart=\"5dp\"\n                android:layout_marginEnd=\"3dp\"\n                android:background=\"@drawable/shape_msg_bg\">\n\n                <com.gowtham.letschat.views.CustomEditText\n                    android:id=\"@+id/edt_msg\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginStart=\"8dp\"\n                    android:layout_marginEnd=\"5dp\"\n                    android:background=\"@null\"\n                    android:hint=\"@string/txt_message\"\n                    android:text=\"@={viewmodel.message}\"\n                    android:inputType=\"textCapSentences|textMultiLine\"\n                    android:maxLines=\"4\"\n                    android:textColorHint=\"@color/colorPrimary\"\n                    android:padding=\"8dp\"\n                    android:textColor=\"@color/colorPrimary\"\n                    android:importantForAutofill=\"no\" />\n            </RelativeLayout>\n\n            <ImageView\n                android:id=\"@+id/img_record\"\n                android:layout_width=\"40dp\"\n                android:layout_height=\"40dp\"\n                android:layout_gravity=\"bottom\"\n                android:layout_marginEnd=\"5dp\"\n                android:padding=\"3dp\"\n                android:layout_marginBottom=\"3dp\"\n                android:src=\"@drawable/ic_mic\"\n                app:tint=\"@color/colorPrimary\" />\n\n        </LinearLayout>\n\n        <com.airbnb.lottie.LottieAnimationView\n            android:id=\"@+id/lottie_send\"\n            android:layout_width=\"45dp\"\n            android:layout_height=\"45dp\"\n            android:layout_gravity=\"end|bottom\"\n            android:layout_marginEnd=\"7dp\"\n            android:layout_marginBottom=\"10dp\"\n            android:visibility=\"gone\"\n            app:lottie_rawRes=\"@raw/lottie_send\" />\n\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/view_chat_toolbar.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    tools:ignore=\"ContentDescription\">\n\n    <data>\n        <import type=\"android.view.View\" />\n\n        <variable\n            name=\"chatUser\"\n            type=\"com.gowtham.letschat.db.data.ChatUser\" />\n\n        <variable\n            name=\"viewmodel\"\n            type=\"com.gowtham.letschat.fragments.single_chat.SingleChatViewModel\" />\n    </data>\n\n    <com.google.android.material.appbar.AppBarLayout\n        style=\"@style/VView\">\n\n        <androidx.appcompat.widget.Toolbar\n            android:id=\"@+id/toolbar\"\n            style=\"@style/CustomToolBar\"\n            app:contentInsetStart=\"10dp\"\n            app:navigationIcon=\"@null\"\n            app:theme=\"@style/ThemeOverlay.AppCompat.Dark.ActionBar\">\n\n            <LinearLayout style=\"@style/LView\">\n\n                <LinearLayout\n                    style=\"@style/WView\"\n                    android:id=\"@+id/view_back\">\n\n                    <ImageView\n                        style=\"@style/WView\"\n                        android:layout_gravity=\"center_vertical\"\n                        android:layout_marginEnd=\"5dp\"\n                        android:src=\"@drawable/ic_arrow_back\"\n                        />\n\n                    <RelativeLayout style=\"@style/WView\">\n\n                        <ImageView\n                            android:layout_width=\"45dp\"\n                            android:layout_height=\"45dp\"\n\n                            android:src=\"@drawable/ic_other_user\"\n                            app:imageUrl=\"@{chatUser.user.image}\" />\n\n                        <TextView\n                            android:layout_width=\"45dp\"\n                            android:layout_height=\"45dp\"\n                            android:visibility=\"@{(chatUser.user.image==null || chatUser.user.image.isEmpty) ? View.VISIBLE : View.GONE}\"\n                            android:text=\"@{chatUser.localName}\"\n                            style=\"@style/TxtNoImageUrlStyle\" />\n                    </RelativeLayout>\n\n                </LinearLayout>\n\n                <LinearLayout\n                    style=\"@style/LWView\"\n                    android:layout_marginStart=\"10dp\">\n\n                    <TextView\n                        android:id=\"@+id/txt_local_name\"\n                        style=\"@style/TxtSemiSmallStyle\"\n                        android:text=\"@{chatUser.localName}\"\n                        android:textColor=\"@color/colorWhite\"\n                        android:maxLines=\"1\"\n                        android:textSize=\"18sp\" />\n\n                    <TextView\n                        android:id=\"@+id/txt_last_seen\"\n                        style=\"@style/TxtRgStyle\"\n                        android:textColor=\"@color/colorWhite\"\n                        android:maxLines=\"1\"\n                        android:textSize=\"15sp\" />\n\n                </LinearLayout>\n\n                <ImageView\n                    android:id=\"@+id/image_add_contact\"\n                    android:layout_width=\"35dp\"\n                    android:layout_height=\"35dp\"\n                    android:layout_marginEnd=\"15dp\"\n                    android:padding=\"6dp\"\n                    android:background=\"?attr/selectableItemBackgroundBorderless\"\n                    android:visibility=\"gone\"\n                    android:layout_gravity=\"center_vertical\"\n                    android:src=\"@drawable/ic_person_add\" />\n            </LinearLayout>\n        </androidx.appcompat.widget.Toolbar>\n\n    </com.google.android.material.appbar.AppBarLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/view_group_chat_btm.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <data>\n        <variable\n            name=\"viewmodel\"\n            type=\"com.gowtham.letschat.fragments.group_chat.GroupChatViewModel\" />\n    </data>\n\n    <androidx.coordinatorlayout.widget.CoordinatorLayout\n        style=\"@style/LView\"\n        tools:ignore=\"ContentDescription\">\n\n        <LinearLayout\n            style=\"@style/LView\"\n            android:gravity=\"center_vertical\"\n            android:padding=\"5dp\"\n            android:layout_marginBottom=\"5dp\">\n\n            <ImageView\n                android:id=\"@+id/image_add\"\n                android:layout_width=\"40dp\"\n                android:layout_height=\"40dp\"\n                android:layout_gravity=\"bottom\"\n                android:layout_marginStart=\"5dp\"\n                android:layout_marginBottom=\"3dp\"\n                android:src=\"@drawable/ic_add_circle\"\n                app:tint=\"@color/colorPrimary\" />\n\n            <RelativeLayout\n                style=\"@style/LWView\"\n                android:layout_marginStart=\"5dp\"\n                android:layout_marginEnd=\"3dp\"\n                android:background=\"@drawable/shape_msg_bg\">\n\n                <com.gowtham.letschat.views.CustomEditText\n                    android:id=\"@+id/edt_msg\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_marginStart=\"8dp\"\n                    android:layout_marginEnd=\"5dp\"\n                    android:background=\"@null\"\n                    android:hint=\"@string/txt_message\"\n                    android:text=\"@={viewmodel.message}\"\n                    android:inputType=\"textCapSentences|textMultiLine\"\n                    android:maxLines=\"4\"\n                    android:textColorHint=\"@color/colorPrimary\"\n                    android:padding=\"8dp\"\n                    android:textColor=\"@color/colorPrimary\"\n                    android:importantForAutofill=\"no\" />\n            </RelativeLayout>\n\n            <ImageView\n                android:id=\"@+id/img_record\"\n                android:layout_width=\"40dp\"\n                android:layout_height=\"40dp\"\n                android:layout_gravity=\"bottom\"\n                android:layout_marginEnd=\"5dp\"\n                android:padding=\"3dp\"\n                android:layout_marginBottom=\"3dp\"\n                android:src=\"@drawable/ic_mic\"\n                app:tint=\"@color/colorPrimary\" />\n\n        </LinearLayout>\n\n        <com.airbnb.lottie.LottieAnimationView\n            android:id=\"@+id/lottie_send\"\n            android:layout_width=\"45dp\"\n            android:layout_height=\"45dp\"\n            android:layout_gravity=\"end|bottom\"\n            android:layout_marginEnd=\"7dp\"\n            android:layout_marginBottom=\"10dp\"\n            android:visibility=\"gone\"\n            app:lottie_rawRes=\"@raw/lottie_send\" />\n\n    </androidx.coordinatorlayout.widget.CoordinatorLayout>\n\n</layout>"
  },
  {
    "path": "app/src/main/res/layout/view_group_chat_toolbar.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    tools:ignore=\"ContentDescription\">\n\n    <data>\n        <import type=\"android.view.View\" />\n\n        <variable\n            name=\"group\"\n            type=\"com.gowtham.letschat.db.data.Group\" />\n\n        <variable\n            name=\"viewmodel\"\n            type=\"com.gowtham.letschat.fragments.group_chat.GroupChatViewModel\" />\n    </data>\n\n    <com.google.android.material.appbar.AppBarLayout\n        style=\"@style/VView\">\n\n        <androidx.appcompat.widget.Toolbar\n            android:id=\"@+id/toolbar\"\n            style=\"@style/CustomToolBar\"\n            app:contentInsetStart=\"10dp\"\n            app:navigationIcon=\"@null\"\n            app:theme=\"@style/ThemeOverlay.AppCompat.Dark.ActionBar\">\n\n            <LinearLayout style=\"@style/LView\">\n\n                <LinearLayout\n                    style=\"@style/WView\"\n                    android:id=\"@+id/view_back\">\n\n                    <ImageView\n                        style=\"@style/WView\"\n                        android:layout_gravity=\"center_vertical\"\n                        android:layout_marginEnd=\"5dp\"\n                        android:src=\"@drawable/ic_arrow_back\"\n                        />\n\n                    <RelativeLayout style=\"@style/WView\">\n\n                        <ImageView\n                            android:layout_width=\"45dp\"\n                            android:layout_height=\"45dp\"\n                            android:src=\"@drawable/ic_other_user\"\n                            app:imageUrl=\"@{group.image}\" />\n\n                        <TextView\n                            android:layout_width=\"45dp\"\n                            android:layout_height=\"45dp\"\n                            android:visibility=\"@{(group.image==null || group.image.isEmpty) ? View.VISIBLE : View.GONE}\"\n                            android:text=\"@{group.id}\"\n                            style=\"@style/TxtNoImageUrlStyle\" />\n                    </RelativeLayout>\n\n                </LinearLayout>\n\n                <LinearLayout\n                    style=\"@style/LWView\"\n                    android:layout_marginStart=\"10dp\">\n\n                    <TextView\n                        android:id=\"@+id/txt_local_name\"\n                        style=\"@style/TxtSemiSmallStyle\"\n                        setGroupName=\"@{group}\"\n                        android:textColor=\"@color/colorWhite\"\n                        android:maxLines=\"1\"\n                        android:textSize=\"18sp\" />\n\n                    <TextView\n                        android:id=\"@+id/txt_members\"\n                        style=\"@style/TxtRgStyle\"\n                        android:textColor=\"@color/colorWhite\"\n                        android:maxLines=\"1\"\n                        setMemberNames=\"@{group}\"\n                        android:textSize=\"15sp\" />\n\n                </LinearLayout>\n\n            </LinearLayout>\n        </androidx.appcompat.widget.Toolbar>\n\n    </com.google.android.material.appbar.AppBarLayout>\n</layout>"
  },
  {
    "path": "app/src/main/res/menu/menu_btm_nav.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n<item\n    android:id=\"@+id/nav_chat\"\n    android:title=\"@string/txt_chats\"\n    android:enabled=\"true\"\n    android:icon=\"@drawable/ic_chat\"/>\n\n    <item\n        android:id=\"@+id/nav_group\"\n        android:title=\"@string/txt_group\"\n        android:enabled=\"true\"\n        android:icon=\"@drawable/ic_group\"/>\n\n    <item\n        android:id=\"@+id/nav_search\"\n        android:title=\"@string/txt_search\"\n        android:enabled=\"true\"\n        android:icon=\"@drawable/ic_search_nav\"/>\n\n    <item\n        android:id=\"@+id/nav_profile\"\n        android:title=\"@string/txt_profile\"\n        android:enabled=\"true\"\n        android:icon=\"@drawable/ic_account_circle\"/>\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_contacts.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:id=\"@+id/action_search\"\n        android:icon=\"@drawable/ic_search\"\n        android:title=\"@string/txt_search\"\n        app:actionViewClass=\"androidx.appcompat.widget.SearchView\"\n        app:showAsAction=\"collapseActionView|always\"\n        />\n\n    <item\n        android:title=\"@string/txt_refresh\"\n        android:id=\"@+id/action_refresh\"\n        />\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_option.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n        android:id=\"@+id/action_take\"\n        android:title=\"@string/take_photo\" />\n\n    <item android:title=\"@string/txt_gallery\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_search.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"AlwaysShowAction,UnusedAttribute\">\n\n    <item\n        android:id=\"@+id/action_search\"\n        android:icon=\"@drawable/ic_search\"\n        android:title=\"@string/txt_search\"\n        app:actionViewClass=\"androidx.appcompat.widget.SearchView\"\n        app:showAsAction=\"collapseActionView|always\"\n        />\n</menu>"
  },
  {
    "path": "app/src/main/res/navigation/nav_graph.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<navigation xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/nav_graph\"\n    app:startDestination=\"@id/FLogIn\">\n\n    <fragment\n        android:id=\"@+id/FLogIn\"\n        android:name=\"com.gowtham.letschat.fragments.login.FLogin\"\n        android:label=\"FLogIn\"\n        tools:layout=\"@layout/f_login\">\n        <action\n            android:id=\"@+id/action_FLogIn_to_FCountries\"\n            app:destination=\"@id/FCountries\"\n            app:enterAnim=\"@anim/slide_in_right\"\n            app:exitAnim=\"@anim/slide_out_left\"\n            app:popEnterAnim=\"@android:anim/slide_in_left\"\n            app:popExitAnim=\"@android:anim/slide_out_right\" />\n        <action\n            android:id=\"@+id/action_FLogIn_to_FVerify\"\n            app:destination=\"@id/FVerify\" />\n        <action\n            android:id=\"@+id/action_FLogIn_to_FProfile\"\n            app:destination=\"@id/FProfile\"\n            app:launchSingleTop=\"true\"\n            app:popUpTo=\"@+id/nav_graph\"\n            app:popUpToInclusive=\"true\" />\n        <action\n            android:id=\"@+id/action_FLogIn_to_FSingleChatHome\"\n            app:destination=\"@id/FSingleChatHome\"\n            app:launchSingleTop=\"true\"\n            app:popUpTo=\"@+id/nav_graph\"\n            app:popUpToInclusive=\"true\" />\n    </fragment>\n\n    <fragment\n        android:id=\"@+id/FCountries\"\n        android:name=\"com.gowtham.letschat.fragments.countries.FCountries\"\n        android:label=\"FCountries\"\n        tools:layout=\"@layout/f_countries\">\n        <action\n            android:id=\"@+id/action_FCountries_to_FLogIn\"\n            app:destination=\"@id/FLogIn\" />\n    </fragment>\n\n    <fragment\n        android:id=\"@+id/FVerify\"\n        android:name=\"com.gowtham.letschat.fragments.login.FVerify\"\n        android:label=\"FVerify\"\n        tools:layout=\"@layout/f_verify\">\n        <action\n            android:id=\"@+id/action_FVerify_to_FProfile\"\n            app:destination=\"@id/FProfile\"\n            app:launchSingleTop=\"true\"\n            app:popUpTo=\"@+id/nav_graph\"\n            app:popUpToInclusive=\"true\" />\n    </fragment>\n\n    <fragment\n        android:id=\"@+id/FProfile\"\n        android:name=\"com.gowtham.letschat.fragments.profile.FProfile\"\n        android:label=\"FProfile\"\n        tools:layout=\"@layout/f_profile\">\n        <action\n            android:id=\"@+id/action_FProfile_to_FSingleChatHome\"\n            app:destination=\"@id/FSingleChatHome\"\n            app:launchSingleTop=\"true\"\n            app:popUpTo=\"@+id/nav_graph\"\n            app:popUpToInclusive=\"true\" />\n    </fragment>\n\n    <fragment\n        android:id=\"@+id/FSingleChatHome\"\n        android:name=\"com.gowtham.letschat.fragments.single_chat_home.FSingleChatHome\"\n        android:label=\"FSingleChatHome\"\n        tools:layout=\"@layout/f_single_chat_home\">\n        <action\n            android:id=\"@+id/action_FSingleChatHome_to_FContacts\"\n            app:destination=\"@id/FContacts\"\n           />\n       <action\n            android:id=\"@+id/action_FSingleChat_to_FChat\"\n            app:destination=\"@id/FSingleChat\" />\n        <action\n            android:id=\"@+id/action_FSingleChatHome_to_FGroupChat\"\n            app:destination=\"@id/FGroupChat\" />\n    </fragment>\n\n    <fragment\n        android:id=\"@+id/FGroupChatHome\"\n        android:name=\"com.gowtham.letschat.fragments.group_chat_home.FGroupChatHome\"\n        android:label=\"FGroupChatHome\"\n        tools:layout=\"@layout/f_group_chat_home\" >\n        <action\n            android:id=\"@+id/action_FGroupChatHome_to_FAddGroupMembers\"\n            app:destination=\"@id/FAddGroupMembers\" />\n        <action\n            android:id=\"@+id/action_FGroupChatHome_to_FGroupChat\"\n            app:destination=\"@id/FGroupChat\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/FSearch\"\n        android:name=\"com.gowtham.letschat.fragments.search.FSearch\"\n        android:label=\"FSearch\"\n        tools:layout=\"@layout/f_search\" >\n        <action\n            android:id=\"@+id/action_FSearch_to_FSingleChat\"\n            app:destination=\"@id/FSingleChat\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/FMyProfile\"\n        android:name=\"com.gowtham.letschat.fragments.myprofile.FMyProfile\"\n        android:label=\"FMyProfile\"\n        tools:layout=\"@layout/f_my_profile\" />\n    <fragment\n        android:id=\"@+id/FContacts\"\n        android:name=\"com.gowtham.letschat.fragments.contacts.FContacts\"\n        android:label=\"FContacts\"\n        tools:layout=\"@layout/f_contacts\">\n        <action\n            android:id=\"@+id/action_FContacts_to_Chat\"\n            app:destination=\"@id/FSingleChat\"\n            app:popUpTo=\"@id/FSingleChatHome\" >\n        </action>\n    </fragment>\n\n    <fragment\n        android:id=\"@+id/FSingleChat\"\n        android:name=\"com.gowtham.letschat.fragments.single_chat.FSingleChat\"\n        android:label=\"FSingleChat\"\n        tools:layout=\"@layout/f_single_chat\" >\n        <argument\n            android:defaultValue=\"@null\"\n            app:nullable=\"true\"\n            android:name=\"chatUserProfile\"\n            app:argType=\"com.gowtham.letschat.db.data.ChatUser\"/>\n    </fragment>\n\n    <fragment\n        android:id=\"@+id/FAddGroupMembers\"\n        android:name=\"com.gowtham.letschat.fragments.add_group_members.FAddGroupMembers\"\n        android:label=\"FAddGroupMembers\"\n        tools:layout=\"@layout/f_add_group_members\">\n        <action\n            android:id=\"@+id/action_FAddGroupMembers_to_FCreateGroup\"\n            app:destination=\"@id/FCreateGroup\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/FCreateGroup\"\n        android:name=\"com.gowtham.letschat.fragments.create_group.FCreateGroup\"\n        android:label=\"f_create_group\"\n        tools:layout=\"@layout/f_create_group\" >\n        <argument\n            android:name=\"memberList\"\n            app:argType=\"com.gowtham.letschat.db.data.ChatUser[]\"/>\n        <action\n            android:id=\"@+id/action_FCreateGroup_to_FGroupChat\"\n            app:destination=\"@id/FGroupChat\"\n            app:popUpTo=\"@id/FGroupChatHome\"/>\n    </fragment>\n    <fragment\n        android:id=\"@+id/FGroupChat\"\n        android:name=\"com.gowtham.letschat.fragments.group_chat.FGroupChat\"\n        android:label=\"FGroupChat\" >\n\n        <argument\n            android:name=\"group\"\n            app:argType=\"com.gowtham.letschat.db.data.Group\"/>\n\n    </fragment>\n</navigation>"
  },
  {
    "path": "app/src/main/res/raw/empty_state.json",
    "content": "{\"v\":\"5.5.5\",\"fr\":60,\"ip\":0,\"op\":225,\"w\":985,\"h\":910,\"nm\":\"▽ Group 62\",\"ddd\":0,\"assets\":[{\"id\":\"comp_0\",\"layers\":[{\"ddd\":0,\"ind\":1,\"ty\":4,\"nm\":\"Shape Layer 16\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[492.5,455,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":2,\"ty\":4,\"nm\":\"Shape Layer 14\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[492.5,455,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0]],\"o\":[[0,0],[0,0]],\"v\":[[-40.75,-106.75],[-17.5,-96.5]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.350949754902,0.350949754902,0.350949754902,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":3,\"ix\":5},\"lc\":2,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":0,\"k\":0,\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.075],\"y\":[0.344]},\"t\":44,\"s\":[0]},{\"t\":70,\"s\":[100]}],\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":3,\"ty\":4,\"nm\":\"Shape Layer 13\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[492.5,455,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0]],\"o\":[[0,0],[0,0]],\"v\":[[-62.25,-138.25],[-14.5,-118.25]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.350949754902,0.350949754902,0.350949754902,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":3,\"ix\":5},\"lc\":2,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":0,\"k\":0,\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.075],\"y\":[0.344]},\"t\":41,\"s\":[0]},{\"t\":67,\"s\":[100]}],\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":4,\"ty\":4,\"nm\":\"Shape Layer 12\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[492.5,455,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0]],\"o\":[[0,0],[0,0]],\"v\":[[-58.5,-154.5],[-9.75,-133]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.350949754902,0.350949754902,0.350949754902,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":3,\"ix\":5},\"lc\":2,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":0,\"k\":0,\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.075],\"y\":[0.344]},\"t\":38,\"s\":[0]},{\"t\":64,\"s\":[100]}],\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":5,\"ty\":4,\"nm\":\"Shape Layer 11\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[492.5,455,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0]],\"o\":[[0,0],[0,0]],\"v\":[[-54.25,-171],[-5.75,-150.25]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.350949754902,0.350949754902,0.350949754902,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":3,\"ix\":5},\"lc\":2,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":0,\"k\":0,\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.075],\"y\":[0.344]},\"t\":37,\"s\":[0]},{\"t\":63,\"s\":[100]}],\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":6,\"ty\":4,\"nm\":\"Shape Layer 10\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[492.5,455,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0]],\"o\":[[0,0],[0,0]],\"v\":[[-46.5,-185.5],[2.75,-165.25]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.350949754902,0.350949754902,0.350949754902,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":3,\"ix\":5},\"lc\":2,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":0,\"k\":0,\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.075],\"y\":[0.344]},\"t\":34,\"s\":[0]},{\"t\":60,\"s\":[100]}],\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":7,\"ty\":4,\"nm\":\"Shape Layer 9\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[492.5,455,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0.295,3.052],[-2.065,1.835],[-3.494,-0.079],[-1.058,-3.597],[7,1.25]],\"o\":[[0,0],[-0.25,-2.588],[1.985,-1.764],[4.428,0.1],[2.5,8.5],[-1.984,-0.354]],\"v\":[[-1.25,-183],[-3.143,-188.688],[-0.5,-196],[8.497,-199.346],[18.5,-193.25],[5.25,-180]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.350949754902,0.350949754902,0.350949754902,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":3,\"ix\":5},\"lc\":2,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":0,\"k\":0,\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.075],\"y\":[0.344]},\"t\":38,\"s\":[0]},{\"t\":64,\"s\":[100]}],\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":8,\"ty\":4,\"nm\":\"Shape Layer 8\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[492.5,455,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0]],\"o\":[[0,0],[0,0]],\"v\":[[-32.75,-207],[-15.75,-200.5]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.350949754902,0.350949754902,0.350949754902,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":3,\"ix\":5},\"lc\":2,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":0,\"k\":0,\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.075],\"y\":[0.344]},\"t\":32,\"s\":[0]},{\"t\":58,\"s\":[100]}],\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":9,\"ty\":4,\"nm\":\"Page\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[471.356,299.63,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[1.82,-7.34],[-0.31,0.1],[6.69,2.57],[0.94,0.38],[0.17,0.55],[-0.03,0.35],[-0.04,0.42],[-0.11,0.88],[-0.32,1.7],[-5.49,8.32],[-1.22,1.37],[0.3,-0.08],[-7.46,-2.75],[-0.76,-0.25],[0.1,-0.37],[0.32,-0.7],[1.27,-2.91],[1.3,-3.61],[-0.12,0.33],[-3.33,7.16],[0.06,0.02],[7.84,4.29],[0.18,-0.21],[2.26,-4.92],[1.2,-5.73],[0.26,-3.47],[-0.94,-0.49],[-0.9,-0.36],[-7.11,-3.21],[-0.08,0.31],[-2.56,7.12],[0.11,-0.33]],\"o\":[[-2.56,7.12],[0.3,-0.11],[-6.54,-2.95],[-0.95,-0.36],[-0.53,-0.22],[-0.1,-0.34],[0.03,-0.42],[0.08,-0.9],[0.21,-1.71],[1.85,-9.78],[1,-1.53],[-0.3,0.08],[7,3.82],[0.75,0.27],[0.37,0.13],[-0.19,0.74],[-1.32,2.89],[-1.54,3.52],[-0.12,0.32],[2.69,-7.43],[0.04,-0.07],[-8.28,-3.26],[-0.26,-0.14],[-3.61,4.09],[-2.44,5.32],[-0.71,3.41],[-0.08,1.02],[0.85,0.44],[7.25,2.86],[0.24,0.11],[1.82,-7.34],[0.11,-0.32],[0,0]],\"v\":[[10.354,5.075],[3.894,26.805],[4.814,26.495],[-14.936,17.865],[-17.766,16.755],[-19.726,15.665],[-19.636,14.405],[-19.536,13.135],[-19.256,10.465],[-18.456,5.355],[-7.426,-22.275],[-4.156,-26.715],[-5.046,-26.475],[17.204,-17.565],[19.454,-16.725],[19.624,-16.475],[18.614,-14.275],[14.724,-5.585],[10.354,5.075],[11.374,4.935],[20.764,-16.875],[20.664,-17.045],[-4.226,-26.965],[-5.106,-26.725],[-13.706,-12.625],[-19.186,4.025],[-20.646,14.355],[-20.136,16.545],[-17.466,17.685],[3.994,26.975],[4.914,26.665],[11.374,4.935],[10.354,5.075]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.501960992813,0.501960992813,0.501960992813,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[300,300],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Fill 50\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":2,\"ix\":5},\"lc\":1,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":10,\"ty\":4,\"nm\":\"Shape Layer 7\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[412.178,346.625,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-80.322,-108.375,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[8,6.5],[-2.5,-33.5],[0,0],[-38.5,76]],\"o\":[[-28.5,25],[22.5,10.5],[0,0],[-37.5,-13.5]],\"v\":[[-33,-235.5],[-81,-108],[-8.5,-75.5],[40,-206]],\"c\":true},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.501960784314,0.501960784314,0.501960784314,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":2,\"ix\":5},\"lc\":1,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":11,\"ty\":4,\"nm\":\"Page 6\",\"sr\":1,\"ks\":{\"o\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.026],\"y\":[0.06]},\"t\":40,\"s\":[0]},{\"t\":63,\"s\":[100]}],\"ix\":11},\"r\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.194],\"y\":[1.028]},\"o\":{\"x\":[0.067],\"y\":[1.268]},\"t\":41,\"s\":[-10]},{\"t\":99,\"s\":[0]}],\"ix\":10},\"p\":{\"a\":0,\"k\":[493.663,378.251,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-25.808,62.423,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[-1.62,-1.21],[-0.23,0.21],[0.33,-0.4],[0.65,-0.91],[1.37,-2.16],[2.62,-7.94],[0.61,-1.97],[-0.29,0.08],[0.37,0.2],[-0.5,-0.27],[-0.38,-0.2],[-0.1,0.33],[-1.81,4.54],[-4.14,5.99],[-0.68,0.93],[-0.36,0.46],[-0.11,0.16],[0.59,0.19],[0.48,0.36],[1.69,1.11],[-0.48,-0.31]],\"o\":[[1.69,1.11],[0.23,-0.21],[-0.59,-0.2],[-0.73,0.85],[-1.48,2.08],[-4.51,7.05],[-0.65,1.96],[0.29,-0.08],[-0.37,-0.2],[-0.38,-0.21],[0.37,0.2],[0.24,0.14],[1.43,-4.67],[2.69,-6.8],[0.66,-0.96],[0.35,-0.47],[0.12,-0.15],[0.29,-0.41],[0.33,0.11],[-1.62,-1.21],[-0.38,-0.24],[0,0]],\"v\":[[4.827,-20.462],[9.817,-17.002],[10.497,-17.632],[9.107,-16.842],[7.087,-14.152],[2.777,-7.802],[-7.743,14.778],[-9.583,20.688],[-8.703,20.448],[-9.813,19.848],[-10.593,20.438],[-9.483,21.038],[-8.603,20.808],[-3.843,6.978],[6.687,-12.052],[8.697,-14.902],[9.757,-16.302],[10.137,-16.752],[9.907,-16.952],[10.597,-17.592],[5.617,-21.052],[4.827,-20.462]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.501960992813,0.501960992813,0.501960992813,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[300,300],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Fill 32\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":12,\"ty\":4,\"nm\":\"Shape Layer 15\",\"sr\":1,\"ks\":{\"o\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.026],\"y\":[0.06]},\"t\":40,\"s\":[0]},{\"t\":63,\"s\":[100]}],\"ix\":11},\"r\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.194],\"y\":[1.028]},\"o\":{\"x\":[0.067],\"y\":[1.268]},\"t\":41,\"s\":[-10]},{\"t\":99,\"s\":[0]}],\"ix\":10},\"p\":{\"a\":0,\"k\":[490.97,360.535,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-1.53,-94.465,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[17.418,-67.064],[0,0]],\"o\":[[0,0],[3.461,-18.041],[0,0]],\"v\":[[34.284,-193.75],[-1.5,-94.5],[45.75,-187.5]],\"c\":true},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.87740502451,0.87740502451,0.87740502451,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[101.989,99.963],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":14,\"ty\":4,\"nm\":\"Page 7\",\"sr\":1,\"ks\":{\"o\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.026],\"y\":[0.06]},\"t\":46,\"s\":[0]},{\"t\":69,\"s\":[100]}],\"ix\":11},\"r\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.194],\"y\":[1.028]},\"o\":{\"x\":[0.067],\"y\":[1.268]},\"t\":47,\"s\":[-10]},{\"t\":105,\"s\":[0]}],\"ix\":10},\"p\":{\"a\":0,\"k\":[492.459,373.771,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-34.569,50.461,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[-1.11,-1.29],[-0.29,0.15],[0.5,-0.44],[1.43,-1.36],[3.2,-5.07],[1.59,-3.68],[-0.14,0.33],[-3.98,5.09],[-3.34,3.09],[-0.79,0.69],[-0.32,0.26],[-0.09,0.1],[0.72,0.38],[0.3,0.35],[1.24,1.17],[-0.3,-0.27]],\"o\":[[1.23,1.17],[0.29,-0.15],[-0.85,-0.45],[-1.48,1.31],[-4.35,4.12],[-2.14,3.39],[-0.21,0.47],[2.57,-5.93],[2.81,-3.59],[0.77,-0.71],[0.3,-0.27],[0.11,-0.09],[0.28,-0.33],[0.22,0.12],[-1.11,-1.28],[-0.27,-0.25],[0,0]],\"v\":[[7.548,-16.61],[11.158,-13],[12.038,-13.46],[9.188,-11.73],[4.827,-7.7],[-6.553,6.14],[-12.132,16.78],[-11.182,16.82],[-1.372,0.18],[7.977,-9.69],[10.307,-11.79],[11.238,-12.58],[11.598,-12.86],[11.227,-12.95],[12.107,-13.41],[8.488,-17.02],[7.548,-16.61]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.501960992813,0.501960992813,0.501960992813,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[300,300],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Fill 28\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":15,\"ty\":4,\"nm\":\"Shape Layer 17\",\"sr\":1,\"ks\":{\"o\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.026],\"y\":[0.06]},\"t\":46,\"s\":[0]},{\"t\":69,\"s\":[100]}],\"ix\":11},\"r\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.194],\"y\":[1.028]},\"o\":{\"x\":[0.067],\"y\":[1.268]},\"t\":47,\"s\":[-10]},{\"t\":105,\"s\":[0]}],\"ix\":10},\"p\":{\"a\":0,\"k\":[507.867,343.3,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[15.367,-111.7,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0],[23,-38]],\"o\":[[0,0],[0,0],[6,-20.5]],\"v\":[[49.5,-177.75],[58.75,-170.25],[13,-114.5]],\"c\":true},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.87740502451,0.87740502451,0.87740502451,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0}]},{\"id\":\"comp_1\",\"layers\":[{\"ddd\":0,\"ind\":1,\"ty\":4,\"nm\":\"Fill 1\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[157.973,122.959,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0.59,2],[-17.79,0],[-6.7,-1.16],[-6.74,0.1],[-5.95,13.01],[7.48,9.32],[5.81,2.71],[15.74,-5.22],[1.25,-4.87]],\"o\":[[2.03,0.36],[-0.6,-2.04],[6.8,0],[6.65,1.15],[7.45,-0.11],[5.02,-10.99],[-4.01,-5],[-8.29,-3.86],[-15.73,5.22],[-9.75,38.06]],\"v\":[[-24.755,40.762],[-23.845,38.382],[-16.395,25.092],[3.765,27.882],[23.905,29.462],[49.315,10.522],[44.985,-19.118],[24.515,-33.998],[-24.755,-38.848],[-50.005,-14.248]],\"c\":true},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.944113016129,0.944113016129,0.944113016129,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[300,300],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Fill 1\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0}]}],\"layers\":[{\"ddd\":0,\"ind\":1,\"ty\":0,\"nm\":\"Pre-comp 1\",\"refId\":\"comp_0\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.511],\"y\":[1]},\"o\":{\"x\":[0.012],\"y\":[0.399]},\"t\":52,\"s\":[-80]},{\"t\":147,\"s\":[0]}],\"ix\":10},\"p\":{\"a\":0,\"k\":[488.737,378.563,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[488.574,378.572,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.509,0.509,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.005,0.005,0.333],\"y\":[0.874,0.874,0]},\"t\":65,\"s\":[0,0,100]},{\"t\":190,\"s\":[100,100,100]}],\"ix\":6}},\"ao\":0,\"w\":985,\"h\":910,\"ip\":56,\"op\":3656,\"st\":56,\"bm\":0},{\"ddd\":0,\"ind\":2,\"ty\":4,\"nm\":\"Shape Layer 6\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[485.213,615.857,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-5.5,168.211,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.325,0.325,0.667],\"y\":[0.995,0.995,1]},\"o\":{\"x\":[0.333,0.333,0.333],\"y\":[0,0,0]},\"t\":58,\"s\":[100,100,100]},{\"i\":{\"x\":[0.349,0.349,0.667],\"y\":[0.741,0.741,1]},\"o\":{\"x\":[0.693,0.693,0.333],\"y\":[0.018,0.018,0]},\"t\":98,\"s\":[138.645,138.645,100]},{\"i\":{\"x\":[0.568,0.568,0.667],\"y\":[2.815,2.815,1]},\"o\":{\"x\":[0.385,0.385,0.333],\"y\":[2.381,2.381,0]},\"t\":137,\"s\":[96,96,100]},{\"i\":{\"x\":[0.624,0.624,0.667],\"y\":[0.963,0.963,1]},\"o\":{\"x\":[0.468,0.468,0.333],\"y\":[0.158,0.158,0]},\"t\":180,\"s\":[95,95,100]},{\"i\":{\"x\":[0.541,0.541,0.667],\"y\":[0.506,0.506,1]},\"o\":{\"x\":[0.468,0.468,0.333],\"y\":[-0.017,-0.017,0]},\"t\":230,\"s\":[120,120,100]},{\"i\":{\"x\":[0.459,0.459,0.667],\"y\":[1.04,1.04,1]},\"o\":{\"x\":[0.36,0.36,0.333],\"y\":[0.613,0.613,0]},\"t\":293,\"s\":[100,100,100]},{\"i\":{\"x\":[0.727,0.727,0.667],\"y\":[0.551,0.551,1]},\"o\":{\"x\":[0.45,0.45,0.333],\"y\":[0.035,0.035,0]},\"t\":318,\"s\":[96,96,100]},{\"i\":{\"x\":[0.638,0.638,0.667],\"y\":[1.012,1.012,1]},\"o\":{\"x\":[0.349,0.349,0.333],\"y\":[0.533,0.533,0]},\"t\":360,\"s\":[120,120,100]},{\"i\":{\"x\":[0.437,0.437,0.667],\"y\":[0.5,0.5,1]},\"o\":{\"x\":[0.657,0.657,0.333],\"y\":[0.057,0.057,0]},\"t\":383,\"s\":[134,134,100]},{\"t\":402,\"s\":[114,114,100]}],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"d\":1,\"ty\":\"el\",\"s\":{\"a\":0,\"k\":[14.774,21.711],\"ix\":2},\"p\":{\"a\":0,\"k\":[0,0],\"ix\":3},\"nm\":\"Ellipse Path 1\",\"mn\":\"ADBE Vector Shape - Ellipse\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,0.850980451995,0.61568627451,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[1.887,157.355],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Ellipse 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":53,\"op\":3653,\"st\":53,\"bm\":0},{\"ddd\":0,\"ind\":3,\"ty\":4,\"nm\":\"Shape Layer 5\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[372.523,613.982,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[9.274,168.211,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.325,0.325,0.667],\"y\":[0.995,0.995,1]},\"o\":{\"x\":[0.333,0.333,0.333],\"y\":[0,0,0]},\"t\":58,\"s\":[100,100,100]},{\"i\":{\"x\":[0.349,0.349,0.667],\"y\":[0.741,0.741,1]},\"o\":{\"x\":[0.693,0.693,0.333],\"y\":[0.018,0.018,0]},\"t\":98,\"s\":[138.645,138.645,100]},{\"i\":{\"x\":[0.568,0.568,0.667],\"y\":[2.815,2.815,1]},\"o\":{\"x\":[0.385,0.385,0.333],\"y\":[2.381,2.381,0]},\"t\":137,\"s\":[96,96,100]},{\"i\":{\"x\":[0.624,0.624,0.667],\"y\":[0.963,0.963,1]},\"o\":{\"x\":[0.468,0.468,0.333],\"y\":[0.158,0.158,0]},\"t\":180,\"s\":[95,95,100]},{\"i\":{\"x\":[0.541,0.541,0.667],\"y\":[0.506,0.506,1]},\"o\":{\"x\":[0.468,0.468,0.333],\"y\":[-0.017,-0.017,0]},\"t\":230,\"s\":[120,120,100]},{\"i\":{\"x\":[0.459,0.459,0.667],\"y\":[1.04,1.04,1]},\"o\":{\"x\":[0.36,0.36,0.333],\"y\":[0.613,0.613,0]},\"t\":293,\"s\":[100,100,100]},{\"i\":{\"x\":[0.727,0.727,0.667],\"y\":[0.551,0.551,1]},\"o\":{\"x\":[0.45,0.45,0.333],\"y\":[0.035,0.035,0]},\"t\":318,\"s\":[96,96,100]},{\"i\":{\"x\":[0.638,0.638,0.667],\"y\":[1.012,1.012,1]},\"o\":{\"x\":[0.349,0.349,0.333],\"y\":[0.533,0.533,0]},\"t\":360,\"s\":[120,120,100]},{\"i\":{\"x\":[0.437,0.437,0.667],\"y\":[0.5,0.5,1]},\"o\":{\"x\":[0.657,0.657,0.333],\"y\":[0.057,0.057,0]},\"t\":383,\"s\":[134,134,100]},{\"t\":402,\"s\":[114,114,100]}],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"d\":1,\"ty\":\"el\",\"s\":{\"a\":0,\"k\":[14.774,21.711],\"ix\":2},\"p\":{\"a\":0,\"k\":[0,0],\"ix\":3},\"nm\":\"Ellipse Path 1\",\"mn\":\"ADBE Vector Shape - Ellipse\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,0.850980451995,0.61568627451,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[1.887,157.355],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Ellipse 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":53,\"op\":3653,\"st\":53,\"bm\":0},{\"ddd\":0,\"ind\":4,\"ty\":4,\"nm\":\"Shape Layer 4\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[395.437,594.09,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-30.188,139.09,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[-13.625,11.375]],\"o\":[[0,0],[13.625,-11.375]],\"v\":[[-40.375,136.375],[-20,136.875]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.619607843137,0.501960784314,0.321568627451,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":4,\"ix\":5},\"lc\":2,\"lj\":2,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.626],\"y\":[1]},\"o\":{\"x\":[0.695],\"y\":[0]},\"t\":38,\"s\":[50]},{\"t\":73,\"s\":[100]}],\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.634],\"y\":[1]},\"o\":{\"x\":[0.882],\"y\":[0]},\"t\":38,\"s\":[50]},{\"t\":73,\"s\":[0]}],\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":38,\"op\":3638,\"st\":38,\"bm\":0},{\"ddd\":0,\"ind\":5,\"ty\":4,\"nm\":\"Shape Layer 3\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[462.312,594.09,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-30.188,139.09,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[-13.625,11.375]],\"o\":[[0,0],[13.625,-11.375]],\"v\":[[-40.375,136.375],[-20,136.875]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.619607843137,0.501960784314,0.321568627451,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":4,\"ix\":5},\"lc\":2,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.626],\"y\":[1]},\"o\":{\"x\":[0.695],\"y\":[0]},\"t\":38,\"s\":[50]},{\"t\":73,\"s\":[100]}],\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.634],\"y\":[1]},\"o\":{\"x\":[0.882],\"y\":[0]},\"t\":38,\"s\":[50]},{\"t\":73,\"s\":[0]}],\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":38,\"op\":3638,\"st\":38,\"bm\":0},{\"ddd\":0,\"ind\":6,\"ty\":4,\"nm\":\"Shape Layer 2\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[427.688,624.517,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-64.812,169.517,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[-2.25,-5],[-20.75,22.25]],\"o\":[[2,3.875],[22.08,-23.676]],\"v\":[[-84.375,163.625],[-45.25,165]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.619607843137,0.501960784314,0.321568627451,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":4,\"ix\":5},\"lc\":2,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.626],\"y\":[1]},\"o\":{\"x\":[0.695],\"y\":[0]},\"t\":54,\"s\":[50]},{\"i\":{\"x\":[0.526],\"y\":[1]},\"o\":{\"x\":[0.167],\"y\":[0]},\"t\":89,\"s\":[100]},{\"i\":{\"x\":[0.334],\"y\":[1]},\"o\":{\"x\":[0.453],\"y\":[0]},\"t\":155.562,\"s\":[80]},{\"i\":{\"x\":[0.461],\"y\":[1]},\"o\":{\"x\":[0.63],\"y\":[0]},\"t\":239,\"s\":[100]},{\"i\":{\"x\":[0.42],\"y\":[1]},\"o\":{\"x\":[0.485],\"y\":[0]},\"t\":325,\"s\":[80]},{\"t\":408.4375,\"s\":[100]}],\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.634],\"y\":[1]},\"o\":{\"x\":[0.882],\"y\":[0]},\"t\":54,\"s\":[50]},{\"i\":{\"x\":[0.575],\"y\":[1]},\"o\":{\"x\":[0.167],\"y\":[0]},\"t\":89,\"s\":[0]},{\"i\":{\"x\":[0.634],\"y\":[1]},\"o\":{\"x\":[0.568],\"y\":[0]},\"t\":155.562,\"s\":[20]},{\"i\":{\"x\":[0.562],\"y\":[1]},\"o\":{\"x\":[0.373],\"y\":[0]},\"t\":239,\"s\":[0]},{\"i\":{\"x\":[0.568],\"y\":[1]},\"o\":{\"x\":[0.499],\"y\":[0]},\"t\":325,\"s\":[20]},{\"t\":408.4375,\"s\":[0]}],\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":54,\"op\":3654,\"st\":54,\"bm\":0},{\"ddd\":0,\"ind\":9,\"ty\":4,\"nm\":\"Bubbel 2\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[385.71,440.982,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-29.71,24.982,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0,0,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.648,0.648,0.333],\"y\":[0,0,0]},\"t\":21,\"s\":[0,0,100]},{\"t\":84,\"s\":[-100,100,100]}],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[-1.25,-0.9],[-1.04,0.06],[-4.13,1.83],[-0.16,0.068],[-0.385,0.148],[1.549,1.633],[3.32,-5.46]],\"o\":[[0.78,0.56],[2.33,-0.12],[0.162,-0.071],[0.396,-0.168],[8.268,-3.182],[-3.02,-3.21],[0.02,1.45]],\"v\":[[-11.36,3.79],[-8.4,4.49],[-1.23,1.99],[-0.746,1.781],[0.425,1.307],[12.74,-2.26],[-13,-0.15]],\"c\":true},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.850000023842,0.850000023842,0.850000023842,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[300,300],\"ix\":3},\"r\":{\"a\":0,\"k\":-210,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Fill 1\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":-38,\"op\":3562,\"st\":-38,\"bm\":0},{\"ddd\":0,\"ind\":10,\"ty\":4,\"nm\":\"Bubble\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[656.185,350.788,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-17.205,11.132,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0,0,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.039,0.039,0.333],\"y\":[0.31,0.31,0]},\"t\":67,\"s\":[0,0,100]},{\"t\":117,\"s\":[100,100,100]}],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[-1.21,-0.79],[-0.94,-0.12],[-2.08,1.93],[1.57,1.52],[-0.07,-4.55]],\"o\":[[0.02,1.26],[0.75,0.48],[3.25,0.41],[1.24,-1.14],[-2.91,-2.79],[0,0]],\"v\":[[-7,-0.31],[-5.42,3.12],[-2.76,3.9],[4.31,1.55],[6.5,-2.1],[-7,-0.31]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.850000023842,0.850000023842,0.850000023842,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[300,300],\"ix\":3},\"r\":{\"a\":0,\"k\":-195,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Fill 1\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":11,\"ty\":4,\"nm\":\"bubble\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[574.516,424.335,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-50.367,24.951,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0,0,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.009,0.009,0.333],\"y\":[0.234,0.234,0]},\"t\":57,\"s\":[0,0,100]},{\"t\":127,\"s\":[100,100,100]}],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[-1.81,-1.47],[-1.51,0.09],[-5.96,2.98],[2.37,2.84],[4.78,-8.91]],\"o\":[[1.12,0.91],[3.35,-0.19],[13.21,-6.6],[-4.36,-5.23],[0.03,2.37]],\"v\":[[-16.37,6.182],[-12.1,7.322],[-1.77,3.252],[18.37,-3.688],[-18.74,-0.238]],\"c\":true},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.949999988079,0.949999988079,0.949999988079,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[300,300],\"ix\":3},\"r\":{\"a\":0,\"k\":-195,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Fill 1\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":17,\"ty\":0,\"nm\":\"Big Bubble\",\"refId\":\"comp_1\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[413.5,444.008,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[81.5,245.508,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0,0,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.019,0.019,0.333],\"y\":[0.528,0.528,0]},\"t\":29,\"s\":[0,0,100]},{\"t\":167,\"s\":[98,98,100]}],\"ix\":6}},\"ao\":0,\"w\":315,\"h\":246,\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":21,\"ty\":4,\"nm\":\"Shape Layer 1\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[492.5,455,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0],[4.25,-20.25],[3,-10.25],[4.25,-6.25],[10,-2.25],[4.052,5.462],[1.25,14.5],[0.75,-10.25],[0,0],[0,0]],\"o\":[[0,0],[0,0],[-2,30.25],[-3.458,11.815],[-5,7.75],[-11.649,2.621],[-5.75,-7.75],[-1.801,-20.888],[0.5,-12.5],[0,0],[0,0]],\"v\":[[-119,6],[152,9.25],[146.75,130.75],[136.75,188.25],[123.5,216.5],[99.25,236],[76.5,225.5],[67,188],[69,127],[76.75,57.5],[81.875,24.375]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.996078431373,0.894117647059,0.741176470588,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":3,\"ix\":5},\"lc\":1,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":0,\"k\":0,\"ix\":1},\"e\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":0,\"s\":[0]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":2,\"s\":[38]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":4,\"s\":[49]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":7,\"s\":[60]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":9,\"s\":[67]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":12,\"s\":[69]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":20,\"s\":[69]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":23,\"s\":[72.333]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":27,\"s\":[76.111]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":29,\"s\":[81]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":32,\"s\":[88]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":35,\"s\":[95]},{\"t\":41,\"s\":[100]}],\"ix\":2},\"o\":{\"a\":0,\"k\":-360,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":22,\"ty\":4,\"nm\":\"Folder Front 3\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[443.987,587.909,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":1,\"k\":[{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":20,\"s\":[{\"i\":[[0,0],[4.237,-0.553],[6.394,8.698],[0,0],[-2.871,-1.286],[-3.656,-0.473],[-2.84,-0.45],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-6.456,1.023],[-6.763,0.03],[0,0],[1.519,2.125],[1.529,0.685],[2.583,0.334],[3.31,0.53],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.294,34.924],[45.85,35.334],[-44.306,30.374],[-45.848,28.739],[-40.316,32.971],[-33.09,34.337],[-26.383,35.167],[-17.903,35.734],[-6.203,36.171],[0.494,36.601],[14.494,36.701],[27.927,36.751],[38.654,36.271],[49.294,34.541]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":22,\"s\":[{\"i\":[[0,0],[3.987,-0.137],[34.561,10.657],[0,0],[-1.263,-0.523],[-2.739,-0.515],[-2.654,-0.303],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-3.623,0.69],[-29.58,-0.12],[0,0],[2.644,3.833],[1.404,0.643],[2.38,0.448],[3.33,0.381],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.793,34.341],[41.184,35.667],[-44.89,29.457],[-46.515,28.031],[-40.233,33.012],[-34.048,34.337],[-25.716,35.334],[-17.736,35.942],[-6.453,36.504],[0.494,36.601],[14.493,36.701],[27.593,36.501],[38.653,36.021],[49.293,34.541]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":23,\"s\":[{\"i\":[[0,0],[2.456,2.744],[33.977,11.933],[-0.91,-2.287],[-2.696,-1.758],[-2.504,-0.442],[-3.091,-0.257],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-4.862,0.836],[-29.58,-0.12],[0,0],[0.91,2.287],[2.696,1.758],[2.172,0.383],[3.341,0.277],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.793,34.341],[41.298,31.12],[-47.713,23.154],[-46.989,26.202],[-42.359,32.189],[-35.908,34.348],[-28.28,35.12],[-19.096,35.854],[-9.443,36.358],[0.494,36.601],[14.494,36.701],[27.593,36.501],[38.653,36.021],[49.293,34.541]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":25,\"s\":[{\"i\":[[0,0],[3.071,5.697],[33.227,13.573],[0,0],[-1.346,-1.857],[-2.406,-0.473],[-2.84,-0.45],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-4.622,0.857],[-29.58,-0.12],[0,0],[0.394,3.333],[0.84,1.159],[2.555,0.503],[3.31,0.53],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.793,34.341],[39.684,27.417],[-48.223,17.207],[-47.89,20.197],[-45.066,29.637],[-39.423,33.254],[-31.883,34.584],[-20.736,35.901],[-13.286,36.171],[0.494,36.601],[14.494,36.701],[27.593,36.501],[38.653,36.021],[49.293,34.541]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":27,\"s\":[{\"i\":[[0,0],[0.74,7.15],[33.22,13.544],[0,0],[-1.262,-3.352],[-1.185,-0.936],[-2.84,-0.45],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-6.465,1.026],[-29.58,-0.12],[0,0],[0.727,5.833],[0.925,2.458],[1.511,1.194],[3.31,0.53],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.793,34.341],[38.931,22.714],[-49.057,12.108],[-48.89,15.774],[-46.817,27.216],[-43.09,31.92],[-35.716,34.251],[-25.736,35.401],[-13.286,36.171],[0.494,36.601],[14.493,36.701],[27.593,36.501],[38.653,36.021],[49.293,34.541]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":30,\"s\":[{\"i\":[[0,0],[-0.679,12.947],[39.061,7.24],[0,0],[-0.654,-2.477],[-2.073,-1.89],[-2.84,-0.45],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-10.622,2.19],[-31.846,5.78],[0,0],[0.227,3.833],[0.654,2.477],[2.125,1.938],[3.31,0.53],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.794,34.341],[38.35,5.084],[-49.39,4.957],[-48.973,15.031],[-47.733,24.971],[-43.756,31.421],[-35.716,34.251],[-25.736,35.401],[-13.286,36.171],[0.494,36.601],[14.493,36.701],[27.594,36.501],[38.654,36.021],[49.294,34.541]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":32,\"s\":[{\"i\":[[0,0],[-3.068,20.113],[32.74,2.487],[0,0],[-1.171,-4.286],[-2.798,-2.377],[-2.84,-0.45],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-12.4,2.857],[-30.335,1.847],[0,0],[0.561,5.167],[0.944,3.462],[2.182,1.873],[3.31,0.53],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.794,34.341],[39.406,-5.916],[-49.39,-7.487],[-49.362,11.475],[-47.511,24.471],[-43.756,31.421],[-35.716,34.251],[-25.736,35.401],[-13.286,36.171],[0.494,36.601],[14.493,36.701],[27.594,36.501],[38.654,36.021],[49.294,34.541]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":33,\"s\":[{\"i\":[[0,0],[-2.513,15.613],[29.58,0.11],[-0.061,-4.667],[-1.733,-5.097],[-1.678,-1.783],[-2.84,-0.45],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-13.289,3.19],[-29.58,-0.12],[0,0],[0.061,4.667],[1.154,3.393],[1.594,1.693],[3.31,0.53],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.794,34.341],[39.684,-6.416],[-49.39,-13.709],[-49.806,9.864],[-47.983,24.471],[-43.756,31.421],[-35.716,34.251],[-25.736,35.401],[-13.286,36.171],[0.494,36.601],[14.493,36.701],[27.594,36.501],[38.654,36.021],[49.294,34.541]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":34,\"s\":[{\"i\":[[0,0],[-3.358,18.268],[50.384,5.02],[0,0],[-0.763,-2.607],[-1.822,-1.473],[-2.84,-0.45],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-15.151,4.647],[-29.58,-0.12],[0,0],[0.154,6.328],[0.594,2.032],[2.236,1.808],[3.31,0.53],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.794,34.341],[40.889,-17.615],[-49.047,-17.989],[-49.233,5.285],[-47.233,24.387],[-43.84,30.754],[-35.716,34.251],[-25.736,35.401],[-13.286,36.171],[0.494,36.601],[14.493,36.701],[27.594,36.501],[38.654,36.021],[49.294,34.541]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":35,\"s\":[{\"i\":[[0,0],[-4.203,20.923],[31.924,0.663],[0,0],[-1.948,-8.876],[-1.671,-1.454],[-2.84,-0.45],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-17.014,6.105],[-29.58,-0.12],[0,0],[0.062,6.887],[0.832,3.789],[1.937,1.685],[3.31,0.53],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.794,34.341],[41.594,-23.648],[-49.647,-23.213],[-49.558,-0.023],[-47.381,24.239],[-43.766,31.345],[-35.716,34.251],[-25.736,35.401],[-13.286,36.171],[0.494,36.601],[14.494,36.701],[27.594,36.501],[38.654,36.021],[49.294,34.541]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":38,\"s\":[{\"i\":[[0,0],[-4.31,21.26],[29.58,0.11],[0,0],[-0.444,-5.59],[-3.16,-2.62],[-2.84,-0.45],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-17.25,6.29],[-29.58,-0.12],[0,0],[-2.773,16.167],[0.362,4.56],[2.21,1.84],[3.31,0.53],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.794,34.341],[42.684,-31.583],[-49.223,-32.376],[-50.223,-14.303],[-49.191,19.054],[-43.756,31.421],[-35.716,34.251],[-25.736,35.401],[-13.286,36.171],[0.494,36.601],[14.494,36.701],[27.594,36.501],[38.654,36.021],[49.294,34.541]],\"c\":true}]},{\"t\":41,\"s\":[{\"i\":[[0,0],[-4.31,21.26],[29.58,0.11],[0.729,-13.637],[-2.596,-16.19],[-3.16,-2.62],[-2.84,-0.45],[-3.34,-0.28],[-4.16,-0.18],[-4.6,-0.08],[-4.67,0.02],[-4.37,0.13],[-3.68,0.24],[-3.43,1.26]],\"o\":[[-17.25,6.29],[-29.58,-0.12],[0,0],[-0.606,11.333],[0.649,4.051],[2.21,1.84],[3.31,0.53],[4.14,0.35],[4.59,0.21],[4.67,0.09],[4.37,-0.01],[3.69,-0.1],[3.59,-0.22],[0,0]],\"v\":[[49.794,34.341],[43.684,-36.249],[-49.556,-36.709],[-51.223,-19.469],[-49.9,18.887],[-43.756,31.421],[-35.716,34.251],[-25.736,35.401],[-13.286,36.171],[0.494,36.601],[14.494,36.701],[27.594,36.501],[38.654,36.021],[49.294,34.541]],\"c\":true}]}],\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.980392156863,0.81568627451,0.564705882353,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[300,300],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Fill 8\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":20,\"op\":3583,\"st\":-17,\"bm\":0},{\"ddd\":0,\"ind\":23,\"ty\":4,\"nm\":\"Folder back 2\",\"sr\":1,\"ks\":{\"o\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.667],\"y\":[1]},\"o\":{\"x\":[0.333],\"y\":[0]},\"t\":0,\"s\":[0]},{\"t\":11,\"s\":[100]}],\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[509.689,578.168,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.278431372549,0.286274509804,0.627450980392,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":177,\"ix\":5},\"lc\":1,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.90588241278,0.725490196078,0.454901990704,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":1,\"k\":[{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":0,\"s\":[{\"i\":[[0,0],[-0.478,2.311],[-0.2,5.873],[-0.009,0.31],[-0.039,0.46],[0.318,8.583],[-0.061,0.318],[-0.624,-5.547],[0,0],[3.45,0.69],[0,0],[0,0],[0,0],[0,0],[0,0],[-26.247,0.049]],\"o\":[[3.58,-0.22],[1.161,-5.62],[0.013,-0.377],[0.184,-6.359],[0.523,-6.099],[-0.01,-0.271],[0.286,-1.49],[0.382,3.394],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[26.246,-0.049]],\"v\":[[44.257,-46.898],[44.647,-49.211],[45.327,-48.851],[45.36,-49.88],[44.981,-49.348],[44.887,-47.366],[44.857,-48.257],[44.927,-50.475],[45.154,-50.291],[-45.826,-51.271],[-45.456,-50.302],[-45.592,-48.794],[-45.586,-48.25],[-45.581,-47.825],[-45.579,-47.68],[-4.771,-49.365]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":2,\"s\":[{\"i\":[[0,0],[-0.011,-1.816],[0.062,1.037],[-0.001,0.033],[0.031,1.047],[-0.061,-0.825],[-0.015,-0.011],[-0.093,-0.419],[0,0],[3.45,0.69],[-0.189,-3.089],[0,0],[0.042,-1.084],[0,0],[0,0],[-25.262,-0.666]],\"o\":[[0.66,-0.164],[-0.186,1.251],[0.001,-0.029],[0.028,-0.675],[0.078,-5.196],[0.061,0.912],[0.111,0.089],[0.09,0.526],[0,0],[0,0],[0.189,3.089],[0,0],[-0.042,1.084],[0,0],[0,0],[25.238,0.167]],\"v\":[[44.793,-18.572],[45.483,-21.82],[45.391,-26.952],[45.395,-27.046],[45.467,-30.126],[45.641,-34.875],[45.673,-35.184],[45.541,-37.099],[45.487,-38.291],[-45.493,-39.271],[-44.714,-32.086],[-44.72,-24.326],[-44.816,-22.082],[-44.717,-20.416],[-44.84,-19.228],[-2.429,-16.081]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":3,\"s\":[{\"i\":[[0,0],[-0.05,0.011],[0.042,0.862],[-0.002,0.029],[0.005,0.754],[-0.036,0.386],[-0.007,0.156],[-0.107,2.895],[0,0],[3.45,0.69],[-0.248,-3.965],[0.01,-1.116],[0.021,-0.542],[0.034,-0.44],[0,0],[-26.369,-0.954]],\"o\":[[0.543,-0.319],[0.004,-1.393],[0.002,-0.026],[0.038,-0.595],[0.078,-3.485],[0.031,0.312],[0.052,-1.096],[0.09,-2.04],[0,0],[0,0],[0.248,3.965],[-0.01,1.116],[-0.021,0.542],[-0.023,0.299],[0,0],[26.357,0.704]],\"v\":[[44.463,-12.235],[45.211,-17.349],[45.255,-23.589],[45.261,-23.671],[45.37,-26.258],[45.501,-31.131],[45.557,-34.679],[45.463,-35.058],[45.487,-38.291],[-45.493,-39.271],[-44.605,-28.796],[-44.404,-19.695],[-44.369,-16.415],[-44.32,-14.476],[-44.423,-12.879],[-6.215,-6.951]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":4,\"s\":[{\"i\":[[0,0],[-0.089,1.839],[0.023,0.687],[-0.002,0.025],[-0.02,0.462],[-0.011,1.597],[0.001,0.323],[-0.122,6.209],[0,0],[3.45,0.69],[-0.306,-4.841],[0.021,-2.233],[0,0],[0.069,-0.881],[0,0],[-27.476,-1.241]],\"o\":[[0.426,-0.475],[0.195,-4.037],[0.002,-0.022],[0.048,-0.516],[0.078,-1.775],[0.002,-0.287],[-0.006,-2.282],[0.091,-4.606],[0,0],[0,0],[0.306,4.841],[-0.021,2.233],[0,0],[-0.047,0.598],[0,0],[27.476,1.241]],\"v\":[[44.132,-5.898],[44.939,-12.878],[45.119,-20.226],[45.126,-20.297],[45.272,-22.389],[45.361,-27.386],[45.44,-34.173],[45.385,-33.017],[45.487,-38.291],[-45.493,-39.271],[-44.497,-25.505],[-44.087,-15.063],[-43.922,-10.998],[-43.923,-8.536],[-44.007,-6.531],[-10.001,2.179]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":6,\"s\":[{\"i\":[[0,0],[-0.175,1.963],[-0.019,1.687],[-0.001,0.049],[-0.007,0.462],[-0.011,1.589],[-0.028,0.322],[-0.163,6.208],[0,0],[3.45,0.69],[-0.286,-6.835],[0.068,-3.354],[0,0],[0,0],[0,0],[-23.174,-0.045]],\"o\":[[0.593,-2.6],[0.411,-4.62],[0,-0.022],[0.016,-0.996],[0.078,-4.983],[0.002,-0.292],[0.66,-7.622],[0.207,-7.887],[0,0],[0,0],[0.286,6.835],[-0.069,3.414],[0,0],[0,0],[0,0],[23.174,0.045]],\"v\":[[42.091,12.977],[44.148,0.956],[45.161,-12.851],[45.162,-12.958],[45.314,-20.681],[45.404,-27.336],[45.607,-31.507],[45.552,-32.017],[45.487,-38.291],[-45.493,-39.271],[-44.31,-22.748],[-43.622,0.089],[-43.701,6.659],[-44.114,9.642],[-44.279,12.802],[-11.199,18.207]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":9,\"s\":[{\"i\":[[0,0],[-1.232,4.97],[-0.013,0.383],[-0.006,0.199],[-0.154,1.176],[0.08,-0.548],[0.004,-0.044],[-0.049,0.106],[0,0],[3.45,0.69],[-0.473,-10.523],[0,0],[0,0],[0.898,-2.465],[0,0],[-26.941,-1.093]],\"o\":[[5.385,-2.183],[1.745,-7.036],[0.007,-0.208],[0.123,-4.094],[-0.172,-0.9],[-0.003,0.017],[-0.131,1.426],[0.049,-0.106],[0,0],[0,0],[0.139,19.523],[0,0],[0,0],[-1.188,3.259],[0,0],[26.941,1.093]],\"v\":[[31.424,34.602],[41.564,17.872],[44.661,-7.268],[44.68,-7.878],[44.897,-15.014],[45.033,-22.181],[45.273,-28.34],[45.427,-32.808],[45.487,-38.291],[-45.493,-39.271],[-41.331,-5.104],[-41.837,15.187],[-42.838,23.245],[-44.09,28.301],[-46.34,31.969],[-17.799,37.993]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":10,\"s\":[{\"i\":[[0,0],[-2.311,4.874],[-0.333,2.187],[-0.017,0.253],[-0.132,0.923],[-0.212,2.875],[-0.041,0.752],[-0.087,2.14],[0,0],[3.45,0.69],[-0.196,-15.078],[0.757,-6.678],[0.536,-2.364],[0.648,-2.211],[0,0],[-22.907,-1.026]],\"o\":[[7.579,-1.739],[2.967,-7.092],[0.008,-0.157],[0.18,-3.631],[0.022,-1.032],[0.007,-0.091],[0.051,-1.519],[0.102,-2.7],[0,0],[0,0],[0.139,10.746],[-0.157,1.382],[-0.214,1.469],[-0.906,3.09],[0,0],[34.903,3.264]],\"v\":[[26.924,37.352],[39.342,23.22],[44.189,-2.532],[44.226,-3.154],[44.842,-12.403],[45.114,-19.433],[45.343,-25.34],[45.482,-32.086],[45.487,-38.291],[-45.493,-39.271],[-41.997,-3.993],[-42.282,16.097],[-43.227,25.45],[-44.506,30.297],[-46.729,33.469],[-20.094,38.655]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":11,\"s\":[{\"i\":[[0,0],[-3.389,4.778],[-0.653,3.991],[-0.028,0.307],[-0.111,0.671],[-0.505,6.297],[-0.086,1.547],[-0.125,4.174],[0,0],[3.45,0.69],[-0.742,-10.556],[0.125,-2.779],[0.265,-3.071],[0.685,-2.905],[0,0],[-18.873,-0.96]],\"o\":[[9.774,-1.294],[4.189,-7.147],[0.009,-0.106],[0.238,-3.169],[0.215,-1.165],[0.016,-0.199],[0.233,-4.464],[0.154,-5.293],[0,0],[0,0],[0.806,11.468],[-0.125,2.779],[-0.568,3.151],[-0.685,2.905],[0,0],[19.088,0.88]],\"v\":[[21.924,37.602],[37.12,28.567],[43.716,2.205],[43.773,1.571],[44.786,-9.792],[45.196,-16.685],[45.412,-22.34],[45.538,-31.364],[45.487,-38.291],[-45.493,-39.271],[-42.164,-8.382],[-42.726,16.841],[-43.616,26.322],[-45.173,32.459],[-47.118,34.969],[-22.39,39.317]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":12,\"s\":[{\"i\":[[0,0],[-4.457,4.685],[-0.974,5.795],[-0.039,0.361],[-0.089,0.418],[-0.797,9.72],[-0.131,2.343],[-0.163,6.208],[0,0],[3.45,0.69],[-0.126,-10.529],[0.187,-4.168],[0.397,-4.607],[0.852,-2.631],[0,0],[-14.839,-0.893]],\"o\":[[10.051,-0.516],[7.328,-7.703],[0.009,-0.056],[0.295,-2.706],[0.245,-1.15],[0.025,-0.307],[0.414,-7.409],[0.207,-7.887],[0,0],[0,0],[0.139,11.69],[-0.187,4.168],[-0.853,4.726],[-0.852,2.631],[0,0],[15.161,0.773]],\"v\":[[17.174,39.102],[33.564,33.206],[43.077,7.149],[43.153,6.504],[44.564,-6.764],[45.11,-13.563],[45.356,-19.09],[45.51,-30.392],[45.487,-38.291],[-45.493,-39.271],[-42.331,-1.104],[-42.337,16.584],[-43.172,26.86],[-45.173,34.121],[-47.507,36.469],[-24.685,39.979]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":15,\"s\":[{\"i\":[[0,0],[-4.922,4.13],[-1.685,4.437],[-0.014,0.054],[-0.068,0.457],[-0.777,10.297],[-0.028,0.322],[-0.163,6.208],[0,0],[3.45,0.69],[-0.289,-8.419],[1.021,-8.777],[0,0],[3.352,-3.507],[0,0],[0,0]],\"o\":[[21.135,-0.766],[1.828,-2.786],[0.008,-0.021],[0.965,-3.613],[0.995,-6.65],[0.025,-0.326],[0.66,-7.622],[0.207,-7.887],[0,0],[0,0],[0.306,8.922],[-1.021,8.777],[0,0],[-3.352,3.507],[0,0],[0,0]],\"v\":[[10.674,39.686],[34.814,33.289],[39.994,24.316],[41.594,18.449],[42.981,10.069],[44.695,-8.202],[45.19,-19.173],[45.677,-32.558],[45.487,-38.291],[-45.493,-39.271],[-41.831,-9.836],[-41.837,16.309],[-45.088,28.953],[-49.006,34.579],[-56.007,37.969],[-28.372,39.734]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":18,\"s\":[{\"i\":[[0,0],[-3.431,1.278],[-2.373,5.272],[-0.013,0.033],[-0.089,0.453],[-0.219,4.759],[-0.018,0.323],[-0.163,6.208],[0,0],[3.45,0.69],[-0.473,-13.483],[0.187,-5.06],[1.646,-4.532],[0.981,-0.539],[0,0],[0,0]],\"o\":[[27.246,-0.436],[5.707,-2.108],[0.009,-0.02],[0.274,-0.685],[1.243,-6.319],[0.015,-0.323],[0.446,-7.795],[0.207,-7.887],[0,0],[0,0],[0.473,13.483],[-0.187,5.06],[-2.43,5.769],[-3.724,2.045],[0,0],[0,0]],\"v\":[[-6.34,40.016],[27.784,37.419],[38.587,25.134],[38.637,25.009],[41.742,15.437],[43.696,1.625],[44.363,-6.702],[45.013,-24.46],[45.487,-38.291],[-45.493,-39.271],[-42.497,-11.897],[-41.837,13.526],[-44.011,25.734],[-51.506,35.208],[-58.315,37.304],[-38.901,39.173]],\"c\":true}]},{\"t\":20,\"s\":[{\"i\":[[0,0],[-11.363,2.599],[-1.337,2.042],[-1.054,2.897],[-0.187,0.423],[-0.205,5.037],[-0.027,0.322],[-0.146,6.209],[0,0],[3.452,0.681],[-0.168,-11.809],[0,0],[2.034,-5.359],[4.824,-2.192],[0,0],[0,0]],\"o\":[[3.579,-0.23],[6.392,-1.462],[0.012,-0.019],[1.054,-2.897],[1.014,-2.294],[0.013,-0.323],[0.639,-7.624],[0.186,-7.888],[0,0],[0,0],[0.168,11.809],[0,0],[-1.133,3.641],[-4.584,1.977],[0,0],[0,0]],\"v\":[[-10.47,40.057],[26,38.298],[35.395,31.795],[38.838,25.15],[40.712,19.296],[43.514,3.465],[44.181,-3.501],[45.276,-25.014],[45.384,-38.414],[-45.599,-39.147],[-43.859,-10.723],[-43.435,11.278],[-45.392,23.945],[-52.515,34.778],[-60.654,36.759],[-46.518,38.602]],\"c\":true}]}],\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.90588241278,0.725490196078,0.454901990704,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[-0.115,0.074],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[300,300],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Fill 6\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":2,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":25,\"ty\":4,\"nm\":\"Shadow\",\"sr\":1,\"ks\":{\"o\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.667],\"y\":[1]},\"o\":{\"x\":[0.333],\"y\":[0]},\"t\":17,\"s\":[0]},{\"t\":42,\"s\":[100]}],\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[461.597,695.146,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0,0,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.333,0.333,0.333],\"y\":[0,0,0]},\"t\":17,\"s\":[17,17,100]},{\"t\":30,\"s\":[100,100,100]}],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[1.48,-0.56],[10.66,-0.02],[20,0],[-12.36,2.88],[-14.22,0.38],[-12.88,-0.85],[0.51,-2.66]],\"o\":[[-0.1,0.48],[-10.36,3.95],[-20.02,0.04],[-12.49,-0.83],[14.07,-3.28],[12.89,-0.35],[2.18,0.15],[0,0]],\"v\":[[57.478,0.585],[55.198,2.145],[21.928,4.895],[-38.122,4.085],[-52.782,-1.725],[-9.232,-4.905],[29.438,-4.145],[57.478,0.585]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.933000028133,0.933000028133,0.933000028133,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[300,300],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Fill 4\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":3600,\"st\":0,\"bm\":0}],\"markers\":[]}"
  },
  {
    "path": "app/src/main/res/raw/lottie_send.json",
    "content": "{\"v\":\"5.1.15\",\"fr\":25,\"ip\":0,\"op\":40,\"w\":50,\"h\":50,\"nm\":\"ic_arrow\",\"ddd\":0,\"assets\":[],\"layers\":[{\"ddd\":0,\"ind\":1,\"ty\":4,\"nm\":\"Capa de formas 1\",\"td\":1,\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[25,25,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ty\":\"rc\",\"d\":1,\"s\":{\"a\":0,\"k\":[54.95,29.706],\"ix\":2},\"p\":{\"a\":0,\"k\":[0,0],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":4},\"nm\":\"Trazado de rectángulo 1\",\"mn\":\"ADBE Vector Shape - Rect\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,0,0,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"nm\":\"Relleno 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0.229,1.426],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transformar\"}],\"nm\":\"Rectángulo 1\",\"np\":3,\"cix\":2,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":30,\"op\":31,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":2,\"ty\":4,\"nm\":\"Arrow\",\"tt\":2,\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":1,\"k\":[{\"i\":{\"x\":0.667,\"y\":1},\"o\":{\"x\":0.333,\"y\":0},\"n\":\"0p667_1_0p333_0\",\"t\":0,\"s\":[25.5,24.75,0],\"e\":[16.5,24.75,0],\"to\":[-1.5,0,0],\"ti\":[-9.16666698455811,0,0]},{\"i\":{\"x\":0.667,\"y\":1},\"o\":{\"x\":0.333,\"y\":0},\"n\":\"0p667_1_0p333_0\",\"t\":5,\"s\":[16.5,24.75,0],\"e\":[80.5,24.75,0],\"to\":[9.16666698455811,0,0],\"ti\":[-10.6666669845581,0,0]},{\"i\":{\"x\":0.667,\"y\":0.667},\"o\":{\"x\":0.333,\"y\":0.333},\"n\":\"0p667_0p667_0p333_0p333\",\"t\":10,\"s\":[80.5,24.75,0],\"e\":[80.5,24.75,0],\"to\":[0,0,0],\"ti\":[0,0,0]},{\"i\":{\"x\":0.667,\"y\":1},\"o\":{\"x\":0.333,\"y\":0},\"n\":\"0p667_1_0p333_0\",\"t\":30,\"s\":[80.5,24.75,0],\"e\":[-41.5,24.75,0],\"to\":[-20.3333339691162,0,0],\"ti\":[8,0,0]},{\"i\":{\"x\":0.667,\"y\":1},\"o\":{\"x\":0.333,\"y\":0},\"n\":\"0p667_1_0p333_0\",\"t\":31,\"s\":[-41.5,24.75,0],\"e\":[32.5,24.75,0],\"to\":[-8,0,0],\"ti\":[-11.1666669845581,0,0]},{\"i\":{\"x\":0.667,\"y\":1},\"o\":{\"x\":0.333,\"y\":0},\"n\":\"0p667_1_0p333_0\",\"t\":35,\"s\":[32.5,24.75,0],\"e\":[25.5,24.75,0],\"to\":[11.1666669845581,0,0],\"ti\":[1.16666662693024,0,0]},{\"t\":40}],\"ix\":2},\"a\":{\"a\":0,\"k\":[23.25,18,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[70,70,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],\"o\":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],\"v\":[[23,0],[-23,17.75],[-23,3.94],[10.5,0],[-23,-3.94],[-23,-17.75]],\"c\":true},\"ix\":2},\"nm\":\"Trazado 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.2235294117647059,0.2549019607843137,0.3215686274509804,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"nm\":\"Relleno 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[23.25,18],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transformar\"}],\"nm\":\"Grupo 1\",\"np\":2,\"cix\":2,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":40,\"st\":0,\"bm\":0}],\"markers\":[]}"
  },
  {
    "path": "app/src/main/res/raw/lottie_tick.json",
    "content": "{\"v\":\"5.5.9\",\"fr\":30,\"ip\":0,\"op\":40,\"w\":80,\"h\":80,\"nm\":\"Success Checkmark\",\"ddd\":0,\"assets\":[],\"layers\":[{\"ddd\":0,\"ind\":1,\"ty\":4,\"nm\":\"Check Mark\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[40,40,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[-1.312,6,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0],[0,0]],\"o\":[[0,0],[0,0],[0,0]],\"v\":[[-15.75,8],[-8,16],[13.125,-4]],\"c\":false},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.667],\"y\":[1]},\"o\":{\"x\":[0.333],\"y\":[0]},\"t\":25,\"s\":[0]},{\"t\":33,\"s\":[100]}],\"ix\":1},\"e\":{\"a\":0,\"k\":0,\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":6,\"ix\":5},\"lc\":2,\"lj\":2,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Shape 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":40,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":2,\"ty\":4,\"nm\":\"Circle Flash\",\"sr\":1,\"ks\":{\"o\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":25,\"s\":[0]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":30,\"s\":[98]},{\"t\":38,\"s\":[0]}],\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[40,40,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.667,0.667,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.333,0.333,0.333],\"y\":[0,0,0]},\"t\":25,\"s\":[0,0,100]},{\"t\":30,\"s\":[100,100,100]}],\"ix\":6}},\"ao\":0,\"shapes\":[{\"d\":1,\"ty\":\"el\",\"s\":{\"a\":0,\"k\":[64,64],\"ix\":2},\"p\":{\"a\":0,\"k\":[0,0],\"ix\":3},\"nm\":\"Ellipse Path 1\",\"mn\":\"ADBE Vector Shape - Ellipse\",\"hd\":false},{\"ty\":\"gf\",\"o\":{\"a\":0,\"k\":100,\"ix\":10},\"r\":1,\"bm\":0,\"g\":{\"p\":3,\"k\":{\"a\":0,\"k\":[0,0.342,0.671,0.974,0.5,0.198,0.509,0.902,1,0.054,0.347,0.83],\"ix\":9}},\"s\":{\"a\":0,\"k\":[0,0],\"ix\":5},\"e\":{\"a\":0,\"k\":[100,0],\"ix\":6},\"t\":1,\"nm\":\"Gradient Fill 1\",\"mn\":\"ADBE Vector Graphic - G-Fill\",\"hd\":false}],\"ip\":0,\"op\":40,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":3,\"ty\":4,\"nm\":\"Circle Stroke\",\"sr\":1,\"ks\":{\"o\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":36,\"s\":[100]},{\"t\":39,\"s\":[0]}],\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[39.022,39.022,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.667,0.667,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.333,0.333,0.333],\"y\":[0,0,0]},\"t\":16,\"s\":[100,100,100]},{\"i\":{\"x\":[0.667,0.667,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.333,0.333,0.333],\"y\":[0,0,0]},\"t\":22,\"s\":[80,80,100]},{\"i\":{\"x\":[0.667,0.667,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.333,0.333,0.333],\"y\":[0,0,0]},\"t\":25,\"s\":[120,120,100]},{\"t\":29,\"s\":[100,100,100]}],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"d\":1,\"ty\":\"el\",\"s\":{\"a\":0,\"k\":[60,60],\"ix\":2},\"p\":{\"a\":0,\"k\":[0,0],\"ix\":3},\"nm\":\"Ellipse Path 1\",\"mn\":\"ADBE Vector Shape - Ellipse\",\"hd\":false},{\"ty\":\"tm\",\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.667],\"y\":[1]},\"o\":{\"x\":[0.333],\"y\":[0]},\"t\":0,\"s\":[0]},{\"t\":16,\"s\":[100]}],\"ix\":1},\"e\":{\"a\":0,\"k\":0,\"ix\":2},\"o\":{\"a\":0,\"k\":0,\"ix\":3},\"m\":1,\"ix\":2,\"nm\":\"Trim Paths 1\",\"mn\":\"ADBE Vector Filter - Trim\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.309803921569,0.58431372549,0.929411764706,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":4,\"ix\":5},\"lc\":2,\"lj\":2,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0.978,0.978],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Ellipse 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":40,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":4,\"ty\":4,\"nm\":\"Circle Green Fill\",\"sr\":1,\"ks\":{\"o\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":21,\"s\":[0]},{\"t\":28,\"s\":[98]}],\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[40,40,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0,0],\"ix\":1},\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.667,0.667,0.667],\"y\":[1,1,1]},\"o\":{\"x\":[0.333,0.333,0.333],\"y\":[0,0,0]},\"t\":21,\"s\":[0,0,100]},{\"t\":28,\"s\":[100,100,100]}],\"ix\":6}},\"ao\":0,\"shapes\":[{\"d\":1,\"ty\":\"el\",\"s\":{\"a\":0,\"k\":[64,64],\"ix\":2},\"p\":{\"a\":0,\"k\":[0,0],\"ix\":3},\"nm\":\"Ellipse Path 1\",\"mn\":\"ADBE Vector Shape - Ellipse\",\"hd\":false},{\"ty\":\"gf\",\"o\":{\"a\":0,\"k\":100,\"ix\":10},\"r\":1,\"bm\":0,\"g\":{\"p\":3,\"k\":{\"a\":0,\"k\":[0,0.4,0.69,0.957,0.5,0.268,0.563,0.942,1,0.136,0.435,0.928],\"ix\":9}},\"s\":{\"a\":0,\"k\":[0,0],\"ix\":5},\"e\":{\"a\":0,\"k\":[100,0],\"ix\":6},\"t\":1,\"nm\":\"Gradient Fill 1\",\"mn\":\"ADBE Vector Graphic - G-Fill\",\"hd\":false}],\"ip\":0,\"op\":40,\"st\":0,\"bm\":0}],\"markers\":[]}"
  },
  {
    "path": "app/src/main/res/raw/lottie_voice.json",
    "content": "{\"v\":\"5.1.15\",\"fr\":15,\"ip\":0,\"op\":30,\"w\":250,\"h\":250,\"nm\":\"Komp 4\",\"ddd\":0,\"assets\":[],\"layers\":[{\"ddd\":0,\"ind\":1,\"ty\":4,\"nm\":\"mikrofon Konturen\",\"parent\":3,\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[7.614,18.5,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[27.5,36,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0],[-5.951,0],[0,5.951],[0.009,0.13],[0,0],[0,0],[0,0],[0.094,-0.007],[0,0]],\"o\":[[0,0],[0,5.951],[5.951,0],[0,-0.132],[0,0],[0,0],[0,0],[-0.094,-0.007],[0,0],[0,0]],\"v\":[[-10.792,-10.777],[-10.792,-0.001],[0,10.792],[10.792,-0.001],[10.775,-0.393],[10.762,-0.583],[10.762,-10.777],[0.142,-10.786],[-0.142,-10.786],[-0.292,-10.777]],\"c\":true},\"ix\":2},\"nm\":\"Pfad 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ind\":1,\"ty\":\"sh\",\"ix\":2,\"ks\":{\"a\":0,\"k\":{\"i\":[[6.345,0],[0,6.346],[0,0],[0,0],[-0.127,-0.009],[0,0],[0,0],[0,0],[0,-0.149]],\"o\":[[-6.346,0],[0,0],[0,0],[0.127,-0.009],[0,0],[0,0],[0,0],[0.01,0.146],[0,6.346]],\"v\":[[0,11.508],[-11.508,-0.001],[-11.508,-11.493],[-0.191,-11.499],[0.192,-11.499],[0.31,-11.493],[11.478,-11.493],[11.489,-0.441],[11.508,-0.001]],\"c\":true},\"ix\":2},\"nm\":\"Pfad 2\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"mm\",\"mm\":1,\"nm\":\"Pfade zusammenführen 1\",\"mn\":\"ADBE Vector Filter - Merge\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"nm\":\"Fläche 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[27.589,40.493],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transformieren\"}],\"nm\":\"Gruppe 1\",\"np\":4,\"cix\":2,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,-6.368],[6.369,0],[0,6.368],[-6.368,0]],\"o\":[[0,6.368],[-6.368,0],[0,-6.368],[6.369,0]],\"v\":[[11.531,-0.001],[-0.001,11.531],[-11.531,-0.001],[-0.001,-11.531]],\"c\":true},\"ix\":2},\"nm\":\"Pfad 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"nm\":\"Fläche 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[27.59,17.667],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transformieren\"}],\"nm\":\"Gruppe 2\",\"np\":2,\"cix\":2,\"ix\":2,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0],[0,0],[0,0]],\"o\":[[0,0],[0,0],[0,0],[0,0]],\"v\":[[-11.515,5.758],[11.515,5.758],[11.515,-5.758],[-11.515,-5.758]],\"c\":true},\"ix\":2},\"nm\":\"Pfad 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"nm\":\"Fläche 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[27.605,23.424],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transformieren\"}],\"nm\":\"Gruppe 3\",\"np\":2,\"cix\":2,\"ix\":3,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[10.329,0],[0,10.259]],\"o\":[[0,10.259],[-10.329,0],[0,0]],\"v\":[[18.702,-9.288],[0,9.288],[-18.702,-9.288]],\"c\":false},\"ix\":2},\"nm\":\"Pfad 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":2,\"ix\":5},\"lc\":2,\"lj\":2,\"nm\":\"Kontur 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[27.5,49.385],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transformieren\"}],\"nm\":\"Gruppe 4\",\"np\":2,\"cix\":2,\"ix\":4,\"mn\":\"ADBE Vector Group\",\"hd\":false},{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0]],\"o\":[[0,0],[0,0]],\"v\":[[27.363,58.674],[27.363,65.864]],\"c\":false},\"ix\":2},\"nm\":\"Pfad 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[1,1,1,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":3,\"ix\":5},\"lc\":1,\"lj\":2,\"nm\":\"Kontur 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transformieren\"}],\"nm\":\"Gruppe 5\",\"np\":2,\"cix\":2,\"ix\":5,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":3.6,\"op\":23,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":3,\"ty\":4,\"nm\":\"Formebene 18\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[125.21100000000001,125,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[7.825,18.5,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"d\":1,\"ty\":\"el\",\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":2.4,\"s\":[0,0],\"e\":[100,100]},{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":4.2,\"s\":[100,100],\"e\":[100,100]},{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":23,\"s\":[100,100],\"e\":[0,0]},{\"t\":24.80009765625}],\"ix\":2},\"p\":{\"a\":0,\"k\":[0,0],\"ix\":3},\"nm\":\"Elliptischer Pfad 1\",\"mn\":\"ADBE Vector Shape - Ellipse\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.2235294117647059,0.2549019607843137,0.3215686274509804,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":2,\"ix\":5},\"lc\":1,\"lj\":1,\"ml\":4,\"nm\":\"Kontur 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.2235294117647059,0.2549019607843137,0.3215686274509804,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"nm\":\"Fläche 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[7.5,18.5],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transformieren\"}],\"nm\":\"Ellipse 1\",\"np\":3,\"cix\":2,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":2.4,\"op\":26,\"st\":-13.8,\"bm\":0},{\"ddd\":0,\"ind\":4,\"ty\":4,\"nm\":\"Formebene 19\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[125.21100000000001,125,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[7.825,18.5,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"d\":1,\"ty\":\"el\",\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":2.4,\"s\":[0,0],\"e\":[100,100]},{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":4.2,\"s\":[100,100],\"e\":[175,175]},{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":6.6,\"s\":[175,175],\"e\":[175,175]},{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":21.2,\"s\":[175,175],\"e\":[0,0]},{\"t\":22.9998046875}],\"ix\":2},\"p\":{\"a\":0,\"k\":[0,0],\"ix\":3},\"nm\":\"Elliptischer Pfad 1\",\"mn\":\"ADBE Vector Shape - Ellipse\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.28627450980392155,0.32941176470588235,0.40784313725490196,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"nm\":\"Fläche 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[7.5,18.5],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transformieren\"}],\"nm\":\"Ellipse 1\",\"np\":2,\"cix\":2,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":2.4,\"op\":24,\"st\":-13.8,\"bm\":0},{\"ddd\":0,\"ind\":5,\"ty\":4,\"nm\":\"Formebene 20\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[125.21100000000001,125,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[7.825,18.5,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"d\":1,\"ty\":\"el\",\"s\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":2.4,\"s\":[0,0],\"e\":[100,100]},{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":4.2,\"s\":[100,100],\"e\":[175,175]},{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":6.6,\"s\":[175,175],\"e\":[200,200]},{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":9,\"s\":[200,200],\"e\":[200,200]},{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":20,\"s\":[200,200],\"e\":[245,245]},{\"i\":{\"x\":[0.833,0.833],\"y\":[0.833,0.833]},\"o\":{\"x\":[0.167,0.167],\"y\":[0.167,0.167]},\"n\":[\"0p833_0p833_0p167_0p167\",\"0p833_0p833_0p167_0p167\"],\"t\":21.2,\"s\":[245,245],\"e\":[0,0]},{\"t\":22.9998046875}],\"ix\":2},\"p\":{\"a\":0,\"k\":[0,0],\"ix\":3},\"nm\":\"Elliptischer Pfad 1\",\"mn\":\"ADBE Vector Shape - Ellipse\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.2235294117647059,0.2549019607843137,0.3215686274509804,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":0,\"k\":2,\"ix\":5},\"lc\":1,\"lj\":1,\"ml\":4,\"nm\":\"Kontur 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[7.5,18.5],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transformieren\"}],\"nm\":\"Ellipse 1\",\"np\":2,\"cix\":2,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":2.4,\"op\":25,\"st\":-13.8,\"bm\":0}],\"markers\":[]}"
  },
  {
    "path": "app/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <declare-styleable name=\"CircularImageView\">\n        <attr name=\"border\" format=\"boolean\" />\n        <attr name=\"border_width\" format=\"dimension\" />\n        <attr name=\"border_color\" format=\"color\" />\n        <attr name=\"shadow\" format=\"boolean\" />\n    </declare-styleable>\n\n    <declare-styleable name=\"Theme\">\n        <attr name=\"circularImageViewStyle\" format=\"reference\" />\n    </declare-styleable>\n    <declare-styleable name=\"RoundImageView\">\n        <attr name=\"border_radius\" format=\"dimension\" />\n    </declare-styleable>\n    <declare-styleable name=\"StoriesProgressView\">\n        <attr name=\"progressCount\" format=\"integer|reference\"/>\n    </declare-styleable>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#394152</color>\n    <color name=\"colorPrimary2\">#495468</color>\n    <color name=\"colorPrimaryDark\">#2e3543</color>\n    <color name=\"colorAccent\">#1A84F3</color>\n<!--72A3FC-->\n<!--    2892FC-->\n    <color name=\"colorTheme\">#3580FF</color>\n    <color name=\"colorSecondary\">#757575</color>\n    <color name=\"colorSkyTheme\">#4A90E2</color>\n    <color name=\"colorWhite\">#fff</color>\n    <color name=\"colorBlack\">#000</color>\n    <color name=\"colorTxt\">#212121</color>\n    <color name=\"colorHint\">#707070</color>\n    <color name=\"colorPrimaryLt\">#615C5585</color>\n    <color name=\"colorBlackLt\">#80000000</color>\n    <color name=\"colorWhiteLt\">#80FFFFFF</color>\n    <color name=\"colorThemeRed\">#F00606</color>\n    <color name=\"colorDefaultBg\">#f8f9fa</color>\n    <color name=\"colorGreyLt\">#AD87868A</color>\n    <color name=\"colorGrey\">#F869696C</color>\n    <color name=\"colorBlue\">#6478FB</color>\n    <color name=\"colorOrange\">#F9583A</color>\n    <color name=\"colorTop\">#4676E5</color>\n    <color name=\"colorBottom\">#7C71E9</color>\n    <color name=\"progress_primary\">@color/white</color>\n    <color name=\"progress_secondary\">@color/gray_scale</color>\n    <color name=\"progress_max_active\">@color/white</color>\n    <color name=\"gray_scale\">#74FFFFFF</color>\n    <color name=\"white\">#fff</color>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/dimen.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <dimen name=\"set_margin\">56dp</dimen>\n    <dimen name=\"zero_margin\">0dp</dimen>\n    <dimen name=\"menu_btm\">220dp</dimen>\n    <dimen name=\"img_lmg\">15dp</dimen>\n    <dimen name=\"cmt_lr_pad\">15dp</dimen>\n    <dimen name=\"cmt_tb_pad\">7dp</dimen>\n    <dimen name=\"search_pad\">-100dp</dimen>\n    <dimen name=\"progress_bar_height\">2dp</dimen>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/ids.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <item name=\"item_click_support\" type=\"id\" />\n    <item name=\"view_root\" type=\"id\" />\n    <item name=\"toolbar\" type=\"id\" />\n    <item name=\"btn_gps\" type=\"id\" />\n    <item name=\"list_view\" type=\"id\" />\n    <item name=\"view_container\" type=\"id\" />\n    <item name=\"txt_frag\" type=\"id\" />\n</resources>"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">LetsChat</string>\n    <string name=\"txt_otp_verification\">OTP Verification</string>\n    <string name=\"txt_will_send_otp\">We will send you an <b> One Time Password </b>to this mobile number</string>\n    <string name=\"txt_enter_otp\">Enter the OTP sent to </string>\n    <string name=\"txt_enter_mob_no\">Enter Mobile Number</string>\n    <string name=\"txt_get_otp\">Get otp</string>\n    <string name=\"txt_dont_receive\">Don\\'t receive the OTP?</string>\n    <string name=\"txt_welcome\">Welcome!</string>\n    <string name=\"txt_search_here\">Search here</string>\n    <string name=\"txt_select_coun\">Select a country</string>\n    <string name=\"err_no_net\">No Internet Connection</string>\n\n    <string name=\"hello_blank_fragment\">Hello blank fragment</string>\n    <string name=\"txt_verify\">Verify</string>\n    <string name=\"txt_resend\">Resend</string>\n    <string name=\"txt_name\">Name</string>\n    <string name=\"txt_pic_name_desc\">This user name and picture will be visible to your Letschat users.Other users can find you by searching.</string>\n    <string name=\"txt_options\">Options</string>\n\n    <string name=\"take_photo\">Take Photo</string>\n    <string name=\"txt_gallery\">Open Gallery</string>\n    <string name=\"txt_file_p_error\">Permission Denied. Please enable permission !</string>\n    <string name=\"txt_profile\">Profile</string>\n    <string name=\"txt_search\">Search</string>\n    <string name=\"txt_group\">Groups</string>\n    <string name=\"txt_chats\">Chats</string>\n    <string name=\"txt_letschat_contact\">Letschat Contacts</string>\n    <string name=\"txt_refresh\">Refresh</string>\n    <string name=\"txt_contacts\">Contacts</string>\n    <string name=\"txt_select_a_contact\">Select Contact</string>\n    <string name=\"txt_invite_friends\">Invite friends</string>\n    <string name=\"txt_add_contact\">Add Contact</string>\n    <string name=\"txt_logout\">Logout</string>\n    <string name=\"txt_login_again\">Please,login again to verify your number</string>\n    <string name=\"txt_logged_in_head\">This number is logged in another device!</string>\n    <string name=\"default_notification_channel_id\">default</string>\n\n    <string name=\"txt_notifications\">Notifications</string>\n    <string name=\"txt_not_description\">Enable Notification</string>\n    <string name=\"txt_message\">Type something...</string>\n    <string name=\"txt_user_name\">User Name</string>\n    <string name=\"txt_u_name\">User name</string>\n    <string name=\"txt_add_contacts\">Add contacts</string>\n    <string name=\"txt_add_group_mems\">Add Group Members</string>\n    <string name=\"txt_group_name\">Enter group name</string>\n    <string name=\"txt_add_a_friend\">Add a friend</string>\n    <string name=\"txt_select_a_option\">Select a option</string>\n    <string name=\"txt_log_out\">LogOut</string>\n    <string name=\"txt_save_changes\">Save changes</string>\n    <string name=\"txt_your_status\">Status</string>\n    <string name=\"txt_mob_num\">Mobile number</string>\n    <string name=\"txt_want_2_logout\">Do you want to logout!</string>\n    <string name=\"txt_alert_msg\">No worries,when you login again,Your messages will be recovered automatically</string>\n    <string name=\"txt_cancel\">Cancel</string>\n    <string name=\"txt_ok\">Ok</string>\n    <string name=\"txt_take_video\">Take Video</string>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.MaterialComponents.Light.NoActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n        <item name=\"android:textColorPrimary\">@android:color/white</item>\n        <item name=\"android:textColorSecondary\">@android:color/white</item>\n        <item name=\"android:textColorPrimaryInverse\">@android:color/white</item>\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n        <item name=\"searchViewStyle\">@style/MySearchViewStyle</item>\n        <item name=\"actionBarTheme\">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>\n        <item name=\"windowActionModeOverlay\">true</item>\n        <item name=\"android:windowLightStatusBar\" tools:targetApi=\"23\">false</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\" tools:targetApi=\"lollipop\">true</item>\n    </style>\n\n    <style name=\"LWView\">\n        <item name=\"android:layout_width\">0dp</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:orientation\">vertical</item>\n        <item name=\"android:layout_weight\">1</item>\n    </style>\n\n    <style name=\"VWView\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">0dp</item>\n        <item name=\"android:orientation\">vertical</item>\n        <item name=\"android:layout_weight\">1</item>\n    </style>\n\n    <style name=\"VView\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:orientation\">vertical</item>\n    </style>\n\n    <style name=\"WView\">\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n    </style>\n\n    <style name=\"LineView\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">0.5dp</item>\n        <item name=\"android:background\">@color/colorHint</item>\n    </style>\n\n    <style name=\"LineLView\">\n        <item name=\"android:layout_width\">1dp</item>\n        <item name=\"android:layout_height\">match_parent</item>\n        <item name=\"android:background\">@color/colorHint</item>\n    </style>\n\n    <style name=\"FView\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">match_parent</item>\n        <item name=\"android:orientation\">vertical</item>\n    </style>\n\n    <style name=\"FormPad\" parent=\"FView\">\n        <item name=\"android:padding\">15dp</item>\n    </style>\n\n    <style name=\"WLView\">\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:orientation\">horizontal</item>\n    </style>\n\n    <style name=\"WVView\">\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:orientation\">vertical</item>\n    </style>\n\n    <style name=\"LView\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:orientation\">horizontal</item>\n    </style>\n\n\n    <style name=\"ScrollRoot\" parent=\"FView\">\n        <item name=\"android:background\">@color/colorWhite</item>\n        <item name=\"android:id\">@id/view_root</item>\n        <item name=\"android:clickable\">true</item>\n    </style>\n\n    <style name=\"StyleRoot\" parent=\"Widget.Support.CoordinatorLayout\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">match_parent</item>\n        <item name=\"android:background\">@color/colorWhite</item>\n        <item name=\"android:id\">@id/view_root</item>\n        <item name=\"android:clickable\">true</item>\n    </style>\n\n    <style name=\"progressColor\" parent=\"Widget.AppCompat.ProgressBar\">\n        <item name=\"colorControlActivated\">@color/colorPrimary</item>\n    </style>\n\n\n    <style name=\"StyleList\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"layoutManager\">androidx.recyclerview.widget.LinearLayoutManager</item>\n        <item name=\"android:orientation\">vertical</item>\n    </style>\n\n    <style name=\"EdtOTPStyle\">\n        <item name=\"android:layout_width\">40dp</item>\n        <item name=\"android:layout_height\">40dp</item>\n        <item name=\"android:background\">@drawable/shape_edit_bg</item>\n        <item name=\"android:textSize\">18sp</item>\n        <item name=\"android:textColor\">@color/colorBlack</item>\n        <item name=\"android:fontFamily\">@font/font_semi</item>\n        <item name=\"android:gravity\">center</item>\n        <item name=\"android:inputType\">number</item>\n        <item name=\"android:maxLength\">1</item>\n    </style>\n\n    <style name=\"BtnClear\">\n        <item name=\"android:layout_width\">30dp</item>\n        <item name=\"android:layout_height\">30dp</item>\n        <item name=\"android:layout_gravity\">center_vertical</item>\n        <item name=\"android:padding\">5dp</item>\n        <item name=\"android:src\">@drawable/ic_clear</item>\n        <item name=\"android:tint\">@color/colorSecondary</item>\n    </style>\n\n    <style name=\"CustomToolBar\">\n        <item name=\"android:id\">@id/toolbar</item>\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">?attr/actionBarSize</item>\n        <item name=\"background\">?attr/colorPrimary</item>\n        <item name=\"elevation\">4dp</item>\n        <item name=\"titleTextColor\">@color/colorWhite</item>\n        <item name=\"theme\">@style/ToolbarColoredBackArrow</item>\n        <item name=\"contentInsetStartWithNavigation\">0dp</item>\n        <item name=\"navigationIcon\">@drawable/ic_arrow_back</item>\n        <item name=\"popupTheme\">@style/ThemeOverlay.AppCompat.Light</item>\n    </style>\n\n    <style name=\"ToolbarColoredBackArrow\" parent=\"AppTheme\">\n        <item name=\"colorControlNormal\">@android:color/white</item>\n    </style>\n\n    <style name=\"MySearchViewStyle\" parent=\"Widget.AppCompat.Light.SearchView\">\n        <item name=\"searchHintIcon\">@null</item>\n        <item name=\"android:maxWidth\">1000dp</item>\n    </style>\n\n    <style name=\"ListView\" parent=\"VView\">\n        <item name=\"android:id\">@id/list_view</item>\n    </style>\n\n    <style name=\"TxtSemiStyle\" >\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:fontFamily\">@font/font_semi</item>\n        <item name=\"android:textColor\">@color/colorBlack</item>\n        <item name=\"android:textSize\">25sp</item>\n    </style>\n\n    <style name=\"TxtSemiSmallStyle\" >\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:fontFamily\">@font/font_semi</item>\n        <item name=\"android:textColor\">@color/colorBlack</item>\n        <item name=\"android:textSize\">20sp</item>\n    </style>\n\n    <style name=\"TxtBottomSheetStyle\" >\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:fontFamily\">@font/font_semi</item>\n        <item name=\"android:textColor\">@color/colorBlack</item>\n        <item name=\"android:textSize\">18sp</item>\n        <item name=\"android:padding\">12dp</item>\n        <item name=\"android:drawablePadding\">10dp</item>\n    </style>\n\n    <style name=\"TxtRgStyle\" >\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:fontFamily\">@font/font_rg</item>\n        <item name=\"android:textColor\">@color/colorBlack</item>\n        <item name=\"android:textSize\">18sp</item>\n        <item name=\"android:gravity\">center</item>\n    </style>\n\n    <style name=\"BtnStyle\" >\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:fontFamily\">@font/font_semi</item>\n        <item name=\"android:background\">@drawable/shape_btn_bg</item>\n        <item name=\"android:textColor\">@color/colorWhite</item>\n        <item name=\"android:textSize\">20sp</item>\n        <item name=\"android:textAllCaps\">true</item>\n        <item name=\"android:padding\">8dp</item>\n        <item name=\"android:gravity\">center</item>\n    </style>\n\n    <style name=\"StyleFab\" >\n        <item name=\"android:layout_width\">wrap_content</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:layout_gravity\">bottom|end</item>\n        <item name=\"android:layout_margin\">15dp</item>\n        <item name=\"useCompatPadding\">true</item>\n        <item name=\"elevation\">5dp</item>\n        <item name=\"backgroundTint\">@color/colorAccent</item>\n        <item name=\"tint\">@color/colorWhite</item>\n    </style>\n\n    <style name=\"ImageRowStyle\" >\n        <item name=\"android:layout_width\">50dp</item>\n        <item name=\"android:layout_height\">50dp</item>\n        <item name=\"android:padding\">15dp</item>\n        <item name=\"android:background\">@drawable/shape_circle</item>\n    </style>\n\n    <style name=\"TxtNoImageUrlStyle\" >\n        <item name=\"android:layout_width\">50dp</item>\n        <item name=\"android:layout_height\">50dp</item>\n        <item name=\"android:textSize\">20sp</item>\n        <item name=\"android:fontFamily\">@font/font_semi</item>\n        <item name=\"android:gravity\">center</item>\n        <item name=\"android:textAllCaps\">true</item>\n        <item name=\"android:maxLength\">1</item>\n        <item name=\"android:textColor\">@color/colorWhite</item>\n        <item name=\"android:background\">@drawable/shape_circle_blue</item>\n    </style>\n\n    <style name=\"StyleButton\">\n        <item name=\"android:layout_width\">0dp</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:orientation\">vertical</item>\n        <item name=\"android:layout_weight\">1</item>\n        <item name=\"android:textSize\">16sp</item>\n        <item name=\"android:fontFamily\">@font/font_semi</item>\n        <item name=\"android:padding\">10dp</item>\n        <item name=\"android:textAllCaps\">true</item>\n        <item name=\"android:gravity\">center</item>\n        <item name=\"android:textColor\">@color/colorWhite</item>\n        <item name=\"android:background\">@drawable/shape_gradient</item>\n    </style>\n\n    <style name=\"StyleInputLayout\" parent=\"Widget.MaterialComponents.TextInputLayout.OutlinedBox\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n    </style>\n\n    <style name=\"StyleEdtInput\">\n        <item name=\"android:layout_width\">match_parent</item>\n        <item name=\"android:layout_height\">wrap_content</item>\n        <item name=\"android:textColor\">@color/colorTxt</item>\n        <item name=\"android:textSize\">16sp</item>\n        <item name=\"android:fontFamily\">@font/font_semi</item>\n    </style>\n</resources>"
  },
  {
    "path": "app/src/main/res/xml/network_security_config.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<network-security-config>\n        <base-config cleartextTrafficPermitted=\"true\"/>\n</network-security-config>"
  },
  {
    "path": "app/src/main/res/xml/provider_path.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<paths xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <cache-path name=\"cache\" path=\".\" />\n    <external-path name=\"external\" path=\".\" />\n\n    <root-path name=\"root\" path=\".\" />\n    <files-path name=\"my_images\" path=\"/\" />\n    <files-path name=\"my_images\" path=\"myfile/\"/>\n    <files-path name=\"files\" path=\".\" />\n\n    <external-path name=\"external_files\" path=\".\" />\n    <external-path name=\"images\" path=\"Pictures\" />\n    <external-path name=\"my_images\" path=\".\" />\n    <external-files-path name=\"images\" path=\"Pictures\"/>\n    <external-files-path name=\"camera_image\" path=\"Pictures/\"/>\n    <external-files-path name=\"external_files\" path=\".\" />\n    <external-files-path name=\"my_images\" path=\"my_images\" />\n\n    <external-cache-path name=\"external_cache\" path=\".\" />\n</paths>"
  },
  {
    "path": "app/src/release/res/values/google_maps_api.xml",
    "content": "<resources>\n    <!--\n    TODO: Before you release your application, you need a Google Maps API key.\n\n    To do this, you can either add your release key credentials to your existing\n    key, or create a new key.\n\n    Note that this file specifies the API key for the release build target.\n    If you have previously set up a key for the debug target with the debug signing certificate,\n    you will also need to set up a key for your release certificate.\n\n    Follow the directions here:\n\n    https://developers.google.com/maps/documentation/android/signup\n\n    Once you have your key (it starts with \"AIza\"), replace the \"google_maps_key\"\n    string in this file.\n    -->\n    <string name=\"google_maps_key\" templateMergeStrategy=\"preserve\" translatable=\"false\">YOUR_KEY_HERE</string>\n</resources>"
  },
  {
    "path": "app/src/test/java/com/gowtham/letschat/LiveDataUtilAndroid.kt",
    "content": "package com.gowtham.letschat\n\nimport androidx.annotation.VisibleForTesting\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.Observer\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.TimeoutException\n\n/**\n * Gets the value of a [LiveData] or waits for it to have one, with a timeout.\n *\n * Use this extension from host-side (JVM) tests. It's recommended to use it alongside\n * `InstantTaskExecutorRule` or a similar mechanism to execute tasks synchronously.\n */\n@VisibleForTesting(otherwise = VisibleForTesting.NONE)\nfun <T> LiveData<T>.getOrAwaitValues(\n    time: Long = 2,\n    timeUnit: TimeUnit = TimeUnit.SECONDS,\n    afterObserve: () -> Unit = {}\n): T {\n    var data: T? = null\n    val latch = CountDownLatch(1)\n    val observer = object : Observer<T> {\n        override fun onChanged(o: T?) {\n            data = o\n            latch.countDown()\n            this@getOrAwaitValues.removeObserver(this)\n        }\n    }\n    this.observeForever(observer)\n\n    try {\n        afterObserve.invoke()\n\n        // Don't wait indefinitely if the LiveData is not set.\n        if (!latch.await(time, timeUnit)) {\n            throw TimeoutException(\"LiveData value was never set.\")\n        }\n\n    } finally {\n        this.removeObserver(observer)\n    }\n\n    @Suppress(\"UNCHECKED_CAST\")\n    return data as T\n}"
  },
  {
    "path": "app/src/test/java/com/gowtham/letschat/db/DbRepositoryTest.kt",
    "content": "package com.gowtham.letschat.db\n\nimport androidx.lifecycle.LiveData\nimport androidx.lifecycle.MutableLiveData\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.db.data.ChatUserWithMessages\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.emptyFlow\n\nclass DbRepositoryTest : DefaultDbRepo {\n\n    private val users = mutableListOf<ChatUser>()\n\n    private val chatUserList=MutableLiveData<List<ChatUser>>(users)\n\n    override fun insertUser(user: ChatUser) {\n        users.add(user)\n        chatUserList.value=users\n    }\n\n    override fun insertMultipleUser(usersList: List<ChatUser>) {\n        users.addAll(usersList)\n        chatUserList.value=users\n    }\n\n    override fun getAllChatUser(): LiveData<List<ChatUser>> {\n        return chatUserList\n    }\n\n    override fun getChatUserList(): List<ChatUser> {\n          return users;\n    }\n\n    override fun getChatUserById(id: String): ChatUser? {\n            return users.firstOrNull { it.id==id }\n    }\n\n    override fun deleteUserById(userId: String) {\n          users.removeIf { it.id==userId }\n          chatUserList.value=users\n    }\n\n    override fun getChatUserWithMessages(): Flow<List<ChatUserWithMessages>> {\n        return emptyFlow()\n    }\n\n    override fun getChatUserWithMessagesList(): List<ChatUserWithMessages> {\n       return emptyList()\n    }\n\n    override fun nukeTable() {\n\n    }\n\n}"
  },
  {
    "path": "app/src/test/java/com/gowtham/letschat/fragments/single_chat_home/SingleChatHomeViewModelTest.kt",
    "content": "package com.gowtham.letschat.fragments.single_chat_home\n\nimport androidx.arch.core.executor.testing.InstantTaskExecutorRule\nimport com.google.common.truth.Truth.assertThat\nimport com.gowtham.letschat.db.DbRepositoryTest\nimport com.gowtham.letschat.db.data.ChatUser\nimport com.gowtham.letschat.getOrAwaitValues\nimport com.gowtham.letschat.models.ModelMobile\nimport com.gowtham.letschat.models.UserProfile\nimport com.gowtham.letschat.utils.MainCoroutineRule\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.runBlockingTest\nimport org.junit.Before\nimport org.junit.Rule\nimport org.junit.Test\nimport java.util.*\nimport kotlin.collections.HashSet\n\n@ExperimentalCoroutinesApi\nclass SingleChatHomeViewModelTest {\n\n    @get:Rule\n    var instantTaskExecutorRule = InstantTaskExecutorRule()\n\n    @get:Rule\n    var mainCoroutineRule = MainCoroutineRule()\n\n    private lateinit var viewModel: SingleChatHomeViewModel\n\n    @Before\n    fun setUp(){\n       viewModel= SingleChatHomeViewModel(DbRepositoryTest())\n    }\n\n    @Test\n    fun insert_ChatUser() = runBlockingTest{\n        val chatUser=ChatUser(\"testId\",\"Gowtham\", UserProfile(\"testId\",13232113L,123321321L),)\n        viewModel.insertChatUser(chatUser)\n        val chatUsers=viewModel.getAllChatUser().getOrAwaitValues()\n        assertThat(chatUsers).contains(chatUser)\n    }\n\n    @Test\n    fun insert_MultipleUser()=runBlockingTest {\n        val chatUser1=ChatUser(\"testId1\",\"Gowtham\", UserProfile(\"testId1\",13232113L,123321321L),)\n        val chatUser2=ChatUser(\"testId2\",\"Gowtham\", UserProfile(\"testId2\",13232113L,123321321L),)\n        viewModel.insertMultipleChatUser(arrayListOf(chatUser1,chatUser2))\n        val list=viewModel.getAllChatUser().getOrAwaitValues()\n        assertThat(list).containsExactly(chatUser1,chatUser2)\n    }\n\n    @Test\n    fun delete_User_ById() = runBlockingTest {\n        val user=ChatUser(\"testDeleteUserId\",\"Gowtham\", UserProfile(\"testDeleteUserId\",13232113L,123321321L),)\n        viewModel.insertChatUser(user)\n        viewModel.deleteUser(\"testDeleteUserId\")\n        val chatUsers=viewModel.getAllChatUser().getOrAwaitValues()\n        assertThat(chatUsers).doesNotContain(user)\n    }\n\n\n\n}"
  },
  {
    "path": "app/src/test/java/com/gowtham/letschat/utils/MainCoroutineRule.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport kotlinx.coroutines.CoroutineDispatcher\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.TestCoroutineDispatcher\nimport kotlinx.coroutines.test.TestCoroutineScope\nimport kotlinx.coroutines.test.resetMain\nimport kotlinx.coroutines.test.setMain\nimport org.junit.rules.TestWatcher\nimport org.junit.runner.Description\n\n@ExperimentalCoroutinesApi\nclass MainCoroutineRule(\n    private val dispatcher: CoroutineDispatcher = TestCoroutineDispatcher()\n) : TestWatcher(), TestCoroutineScope by TestCoroutineScope(dispatcher) {\n\n    override fun starting(description: Description?) {\n        super.starting(description)\n        Dispatchers.setMain(dispatcher)\n    }\n\n    override fun finished(description: Description?) {\n        super.finished(description)\n        cleanupTestCoroutines()\n        Dispatchers.resetMain()\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/gowtham/letschat/utils/ValidatorTest.kt",
    "content": "package com.gowtham.letschat.utils\n\nimport android.util.Log\nimport com.google.common.truth.Truth.assertThat\nimport org.junit.Test\n\n\nclass ValidatorTest {\n\n    @Test\n    fun invalidNo_returnsFalse() {\n        val result = Validator.isValidNo(\"IN\", \"950561160\")\n        assertThat(result).isFalse()\n    }\n\n    @Test\n    fun validNo_returnsTrue() {\n        val result = Validator.isValidNo(\"IN\", \"9500561160\")\n        assertThat(result).isTrue()\n    }\n\n    @Test\n    fun isMobileNumberEmpty_returnsTrue() {\n        val result=Validator.isMobileNumberEmpty(\"\")\n        assertThat(result).isTrue()\n    }\n}\n\nfun main() {\n    print(\"main: ${findSum(4)}\")\n}\n\nfun findSum(n: Int): Int {\n    var sum = 0 // ---------------------> constant time\n    for (i in 1..n)\n        for (j in 1..i)\n            sum++ // -------------------> it will run [n * (n + 1) / 2]\n    return sum // ----------------------> constant time\n}"
  },
  {
    "path": "build.gradle",
    "content": "buildscript {\n    ext.kotlin_version = \"1.5.10\"\n    repositories {\n        google()\n        mavenCentral()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:4.2.1'\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.36'\n        classpath \"androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5\"\n        classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.0'\n        classpath 'com.google.gms:google-services:4.3.8'\n        classpath \"org.jetbrains.kotlin:kotlin-serialization:$kotlin_version\"\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        mavenCentral()\n        maven { url 'https://jitpack.io' }\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}"
  },
  {
    "path": "firebase.json",
    "content": "{\n  \"functions\": {\n    \"predeploy\": [\n      \"npm --prefix \\\"$RESOURCE_DIR\\\" run lint\"\n    ]\n  }\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Tue Oct 13 22:15:33 IST 2020\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.7.1-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx2048m\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n# AndroidX package structure to make it clearer which packages are bundled with the\n# Android operating system, and which are packaged with your app\"s APK\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\nandroid.useAndroidX=true\n# Automatically convert third-party libraries to use AndroidX\nandroid.enableJetifier=true\n# Kotlin code style for this project: \"official\" or \"obsolete\":\nkotlin.code.style=official\nSERVER_KEY=\"sdssd\""
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windows variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app'\nrootProject.name = \"LetsChat\""
  }
]