[
  {
    "path": ".gitignore",
    "content": "# Built application files\n*.apk\n*.ap_\n\n# 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/assetWizardSettings.xml\n.idea/dictionaries\n.idea/libraries\n.idea/caches\n\n# Keystore files\n# Uncomment the following line if you do not want to check your keystore files in.\n#*.jks\n\n# External native build folder generated in Android Studio 2.2 and later\n.externalNativeBuild\n\n# Google Services (e.g. APIs or Firebase)\ngoogle-services.json\n\n# Freeline\nfreeline.py\nfreeline/\nfreeline_project_description.json\n\n# fastlane\nfastlane/report.xml\nfastlane/Preview.html\nfastlane/screenshots\nfastlane/test_output\nfastlane/readme.md\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Robert\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": "# <img src=\"https://github.com/robertlevonyan/camerax-demo/blob/master/camerax-demo/app/src/main/ic_launcher-web.png\"  width=\"50\" height=\"50\" /> &nbsp;&nbsp;&nbsp; Camera X Demo\n\n|A demo camera application created with Android Jetpack CameraX API|<img src=\"https://github.com/robertlevonyan/camerax-demo/blob/master/media/camerax.png\"  width=\"450\" />|\n|----------------------------------------------------------------------------------------------|-----------|\n\n[![API](https://img.shields.io/badge/API-21%2B-yellow.svg?style=flat-square)](https://android-arsenal.com/api?level=21)\n\n### UI Structure and features \n\n| <p align=\"start\">1. Take photo </p><p align=\"start\"> 2. Switch camera </p><p align=\"start\"> 3. Open gallery </p><p align=\"start\"> 4. Select timer </p><p align=\"start\"> 5. Toggle grid </p><p align=\"start\"> 6. Select flashlight mode </p><p align=\"start\"> 7. Toggle HDR (if device supports)</p><p align=\"start\">8. Record video </p>|<img src=\"https://github.com/robertlevonyan/camerax-demo/blob/master/media/c1.jpg\" width=\"250\" />|<img src=\"https://github.com/robertlevonyan/camerax-demo/blob/master/media/v1.jpg\" width=\"250\" />|\n|-----------------------------------|---------------------------------------------|---------------------------------------------------|\n||<h2 align=\"center\">Some Screenshots</h2>||\n|<img src=\"https://github.com/robertlevonyan/camerax-demo/blob/master/media/c2.jpg\" width=\"250\" />|<img src=\"https://github.com/robertlevonyan/camerax-demo/blob/master/media/c3.jpg\" width=\"250\" /> |<img src=\"https://github.com/robertlevonyan/camerax-demo/blob/master/media/c4.jpg\" width=\"250\" />\n\n## How to switch between photo and video\n\n<img src=\"https://github.com/robertlevonyan/CameraXDemo/blob/master/media/switch.gif\" width=\"500\" />\n\n## Contact\n\n- **Email**: me@robertlevonyan.com\n- **Website**: https://robertlevonyan.com/\n- **Medium**: https://medium.com/@RobertLevonyan\n- **Twitter**: https://twitter.com/@RobertLevonyan\n- **Facebook**: https://facebook.com/robert.levonyan\n- **Google Play**: https://play.google.com/store/apps/dev?id=5477562049350283357\n\n<a href=\"https://www.buymeacoffee.com/robertlevonyan\">\n  <img src=\"https://github.com/robertlevonyan/camerax-demo/blob/master/media/coffee.jpeg\"  width=\"300\" />\n</a>\n\n## Licence\n\n```\nMIT License\n\nCopyright (c) 2019 Robert\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```\n"
  },
  {
    "path": "camerax-demo/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n/.idea/navEditor.xml\n/.idea/assetWizardSettings.xml\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n/gradlew\n/gradlew.bat\n/.idea/compiler.xml\n/.idea/gradle.xml\n/.idea/jarRepositories.xml\n/.idea/misc.xml\n/.idea/vcs.xml\n/.idea/\n/.idea/codeStyles/\n/.idea/.gitignore\n"
  },
  {
    "path": "camerax-demo/.idea/.gitignore",
    "content": "# Default ignored files\n/shelf/\n/workspace.xml\n"
  },
  {
    "path": "camerax-demo/.idea/codeStyles/Project.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <option name=\"RIGHT_MARGIN\" value=\"140\" />\n    <JetCodeStyleSettings>\n      <option name=\"CODE_STYLE_DEFAULTS\" value=\"KOTLIN_OFFICIAL\" />\n    </JetCodeStyleSettings>\n    <codeStyleSettings language=\"XML\">\n      <option name=\"FORCE_REARRANGE_MODE\" value=\"1\" />\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": "camerax-demo/.idea/codeStyles/codeStyleConfig.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <state>\n    <option name=\"USE_PER_PROJECT_SETTINGS\" value=\"true\" />\n  </state>\n</component>"
  },
  {
    "path": "camerax-demo/app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "camerax-demo/app/build.gradle.kts",
    "content": "plugins {\n    alias(libs.plugins.android.application)\n    alias(libs.plugins.kotlin.android)\n    alias(libs.plugins.android.nav.safeargs)\n}\n\nandroid {\n    compileSdk = 35\n    defaultConfig {\n        applicationId = \"com.robertlevonyan.demo.camerax\"\n        minSdk = 21\n        targetSdk = 35\n        versionCode = 1\n        versionName = \"1.0\"\n        testInstrumentationRunner = \"androidx.test.runner.AndroidJUnitRunner\"\n    }\n    buildTypes {\n        getByName(\"release\") {\n            isMinifyEnabled = true\n            proguardFiles(getDefaultProguardFile(\"proguard-android-optimize.txt\"), \"proguard-rules.pro\")\n        }\n    }\n    compileOptions {\n        sourceCompatibility = JavaVersion.VERSION_17\n        targetCompatibility = JavaVersion.VERSION_17\n    }\n    kotlinOptions {\n        jvmTarget = \"17\"\n    }\n    buildFeatures {\n        viewBinding = true\n    }\n    namespace = \"com.robertlevonyan.demo.camerax\"\n}\n\ndependencies {\n    implementation(libs.kotlinx.coroutines.core)\n    implementation(libs.kotlinx.coroutines.android)\n    implementation(libs.material)\n    implementation(libs.androidx.appcompat)\n    implementation(libs.core.ktx)\n    implementation(libs.androidx.constraintlayout)\n    implementation(libs.androidx.camera.core)\n    implementation(libs.androidx.camera.camera2)\n    implementation(libs.androidx.camera.lifecycle)\n    implementation(libs.androidx.camera.extensions)\n    implementation(libs.androidx.camera.view)\n    implementation(libs.androidx.fragment.ktx)\n    implementation(libs.androidx.navigation.fragment.ktx)\n    implementation(libs.androidx.navigation.ui.ktx)\n    implementation(libs.lifecycle.runtime.ktx)\n    implementation(libs.androidx.viewpager2)\n    implementation(libs.coil)\n    implementation(libs.coil.video)\n}\n"
  },
  {
    "path": "camerax-demo/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.kts.\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\n"
  },
  {
    "path": "camerax-demo/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\n    <uses-permission android:name=\"android.permission.CAMERA\" />\n    <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />\n<!--    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />-->\n<!--    <uses-permission-->\n<!--        android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"-->\n<!--        tools:ignore=\"ScopedStorage\" />-->\n    <uses-permission android:name=\"android.permission.ACCESS_MEDIA_LOCATION\" />\n\n    <application\n        android:name=\".CameraXApplication\"\n        android:allowBackup=\"false\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\"\n        tools:ignore=\"GoogleAppIndexingWarning\">\n        <activity\n            android:name=\".MainActivity\"\n            android:exported=\"true\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\">\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        <provider\n            android:name=\"androidx.core.content.FileProvider\"\n            android:authorities=\"com.robertlevonyan.demo.camerax.provider\"\n            android:exported=\"false\"\n            android:grantUriPermissions=\"true\">\n            <meta-data\n                android:name=\"android.support.FILE_PROVIDER_PATHS\"\n                android:resource=\"@xml/provider_paths\" />\n        </provider>\n    </application>\n</manifest>\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/CameraXApplication.kt",
    "content": "package com.robertlevonyan.demo.camerax\n\nimport android.app.Application\nimport coil.ImageLoader\nimport coil.ImageLoaderFactory\nimport coil.decode.VideoFrameDecoder\n\nclass CameraXApplication: Application(), ImageLoaderFactory {\n    override fun newImageLoader(): ImageLoader = ImageLoader.Builder(this)\n        .components {\n            add(VideoFrameDecoder.Factory())\n        }\n        .build()\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/MainActivity.kt",
    "content": "package com.robertlevonyan.demo.camerax\n\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\n\nclass MainActivity : AppCompatActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_main)\n    }\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/adapter/Media.kt",
    "content": "package com.robertlevonyan.demo.camerax.adapter\n\nimport android.net.Uri\nimport java.util.*\n\ndata class Media(\n    val uri: Uri,\n    val isVideo: Boolean,\n    val date: Long,\n)\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/adapter/MediaAdapter.kt",
    "content": "package com.robertlevonyan.demo.camerax.adapter\n\nimport android.net.Uri\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.ImageView\nimport androidx.recyclerview.widget.ListAdapter\nimport androidx.recyclerview.widget.RecyclerView\nimport coil.load\nimport com.robertlevonyan.demo.camerax.R\nimport com.robertlevonyan.demo.camerax.utils.layoutInflater\n\n/**\n * This is an adapter to preview taken photos or videos\n * */\nclass MediaAdapter(\n    private val onItemClick: (Boolean, Uri) -> Unit,\n    private val onDeleteClick: (Boolean, Uri) -> Unit,\n) : ListAdapter<Media, MediaAdapter.PicturesViewHolder>(MediaDiffCallback()) {\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =\n        PicturesViewHolder(parent.context.layoutInflater.inflate(R.layout.item_picture, parent, false))\n\n    override fun onBindViewHolder(holder: PicturesViewHolder, position: Int) {\n        holder.bind(getItem(position))\n    }\n\n    fun shareImage(currentPage: Int, action: (Media) -> Unit) {\n        if (currentPage < itemCount) {\n            action(getItem(currentPage))\n        }\n    }\n\n    fun deleteImage(currentPage: Int) {\n        if (currentPage < itemCount) {\n            val media = getItem(currentPage)\n            val allMedia = currentList.toMutableList()\n            allMedia.removeAt(currentPage)\n            submitList(allMedia)\n            onDeleteClick(allMedia.size == 0, media.uri)\n        }\n    }\n\n    inner class PicturesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {\n        private val imagePreview: ImageView = itemView.findViewById(R.id.imagePreview)\n        private val imagePlay: ImageView = itemView.findViewById(R.id.imagePlay)\n\n        fun bind(item: Media) {\n            imagePlay.visibility = if (item.isVideo) View.VISIBLE else View.GONE\n            imagePreview.load(item.uri)\n            imagePreview.setOnClickListener { onItemClick(item.isVideo, item.uri) }\n        }\n    }\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/adapter/MediaDiffCallback.kt",
    "content": "package com.robertlevonyan.demo.camerax.adapter\n\nimport androidx.recyclerview.widget.DiffUtil\n\nclass MediaDiffCallback : DiffUtil.ItemCallback<Media>() {\n    override fun areItemsTheSame(oldItem: Media, newItem: Media): Boolean = oldItem.uri == newItem.uri\n\n    override fun areContentsTheSame(oldItem: Media, newItem: Media): Boolean = oldItem == newItem\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/analyzer/LuminosityAnalyzer.kt",
    "content": "package com.robertlevonyan.demo.camerax.analyzer\n\nimport android.util.Log\nimport androidx.camera.core.ImageAnalysis\nimport androidx.camera.core.ImageProxy\nimport java.nio.ByteBuffer\nimport java.util.concurrent.TimeUnit\n\nclass LuminosityAnalyzer: ImageAnalysis.Analyzer {\n    private var lastAnalyzedTimestamp = 0L\n\n    private fun ByteBuffer.toByteArray(): ByteArray {\n        rewind()    // Rewind the buffer to zero\n        val data = ByteArray(remaining())\n        get(data)   // Copy the buffer into a byte array\n        return data // Return the byte array\n    }\n\n    override fun analyze(image: ImageProxy) {\n        val currentTimestamp = System.currentTimeMillis()\n        // Calculate the average luma no more often than every second\n        if (currentTimestamp - lastAnalyzedTimestamp >= TimeUnit.SECONDS.toMillis(1)) {\n            // Since format in ImageAnalysis is YUV, image.planes[0]\n            // contains the Y (luminance) plane\n            val buffer = image.planes[0].buffer\n            // Extract image data from callback object\n            val data = buffer.toByteArray()\n            // Convert the data into an array of pixel values\n            val pixels = data.map { it.toInt() and 0xFF }\n            // Compute average luminance for the image\n            val luma = pixels.average()\n            // Log the new luma value\n            Log.e(\"CameraXDemo\", \"Average luminosity: $luma\")\n            // Update timestamp of last analyzed frame\n            lastAnalyzedTimestamp = currentTimestamp\n        }\n    }\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/enums/CameraTimer.kt",
    "content": "package com.robertlevonyan.demo.camerax.enums\n\nenum class CameraTimer {\n    OFF,\n    S3,\n    S10\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/fragments/BaseFragment.kt",
    "content": "package com.robertlevonyan.demo.camerax.fragments\n\nimport android.Manifest\nimport android.content.ContentUris\nimport android.content.pm.PackageManager\nimport android.net.Uri\nimport android.os.Build\nimport android.os.Bundle\nimport android.os.Environment\nimport android.provider.MediaStore\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport androidx.activity.OnBackPressedCallback\nimport androidx.activity.result.contract.ActivityResultContracts\nimport androidx.core.app.ActivityCompat\nimport androidx.core.content.ContextCompat\nimport androidx.core.content.FileProvider\nimport androidx.fragment.app.Fragment\nimport androidx.viewbinding.ViewBinding\nimport com.google.android.material.snackbar.Snackbar\nimport com.robertlevonyan.demo.camerax.R\nimport com.robertlevonyan.demo.camerax.adapter.Media\nimport java.io.File\n\n/**Parent class of all the fragments in this project*/\nabstract class BaseFragment<B : ViewBinding>(private val fragmentLayout: Int) : Fragment() {\n    /**\n     *  Generic ViewBinding of the subclasses\n     * */\n    abstract val binding: B\n\n    // The Folder location where all the files will be stored\n    protected val outputDirectory: String by lazy {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {\n            \"${Environment.DIRECTORY_DCIM}/CameraXDemo/\"\n        } else {\n            \"${requireContext().getExternalFilesDir(Environment.DIRECTORY_DCIM)}/CameraXDemo/\"\n        }\n    }\n\n    // The permissions we need for the app to work properly\n    private val permissions = mutableListOf(\n        Manifest.permission.CAMERA,\n        Manifest.permission.RECORD_AUDIO,\n//        Manifest.permission.READ_EXTERNAL_STORAGE,\n    ).apply {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {\n            add(Manifest.permission.ACCESS_MEDIA_LOCATION)\n        }\n    }\n\n    private val permissionRequest = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->\n        if (permissions.all { it.value }) {\n            onPermissionGranted()\n        } else {\n            view?.let { v ->\n                Snackbar.make(v, R.string.message_no_permissions, Snackbar.LENGTH_INDEFINITE)\n                    .setAction(R.string.label_ok) { ActivityCompat.finishAffinity(requireActivity()) }\n                    .show()\n            }\n        }\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?\n    ): View {\n        // Adding an option to handle the back press in fragment\n        requireActivity().onBackPressedDispatcher.addCallback(\n            viewLifecycleOwner,\n            object : OnBackPressedCallback(true) {\n                override fun handleOnBackPressed() {\n                    onBackPressed()\n                }\n            })\n\n        return binding.root\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        if (allPermissionsGranted()) {\n            onPermissionGranted()\n        } else {\n            permissionRequest.launch(permissions.toTypedArray())\n        }\n    }\n\n    protected fun getMedia(): List<Media> = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {\n        getMediaQPlus()\n    } else {\n        getMediaQMinus()\n    }.reversed()\n\n    private fun getMediaQPlus(): List<Media> {\n        val items = mutableListOf<Media>()\n        val contentResolver = requireContext().applicationContext.contentResolver\n\n        contentResolver.query(\n            MediaStore.Video.Media.EXTERNAL_CONTENT_URI,\n            arrayOf(\n                MediaStore.Video.Media._ID,\n                MediaStore.Video.Media.RELATIVE_PATH,\n                MediaStore.Video.Media.DATE_TAKEN,\n            ),\n            null,\n            null,\n            \"${MediaStore.Video.Media.DISPLAY_NAME} ASC\"\n        )?.use { cursor ->\n            val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)\n            val pathColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.RELATIVE_PATH)\n            val dateColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_TAKEN)\n\n            while (cursor.moveToNext()) {\n                val id = cursor.getLong(idColumn)\n                val path = cursor.getString(pathColumn)\n                val date = cursor.getLong(dateColumn)\n\n                val contentUri: Uri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id)\n\n                if (path == outputDirectory) {\n                    items.add(Media(contentUri, true, date))\n                }\n            }\n        }\n\n        contentResolver.query(\n            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,\n            arrayOf(\n                MediaStore.Images.Media._ID,\n                MediaStore.Images.Media.RELATIVE_PATH,\n                MediaStore.Images.Media.DATE_TAKEN,\n            ),\n            null,\n            null,\n            \"${MediaStore.Images.Media.DISPLAY_NAME} ASC\"\n        )?.use { cursor ->\n            val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)\n            val pathColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.RELATIVE_PATH)\n            val dateColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_TAKEN)\n\n            while (cursor.moveToNext()) {\n                val id = cursor.getLong(idColumn)\n                val path = cursor.getString(pathColumn)\n                val date = cursor.getLong(dateColumn)\n\n                val contentUri: Uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)\n\n                if (path == outputDirectory) {\n                    items.add(Media(contentUri, false, date))\n                }\n            }\n        }\n        return items\n    }\n\n    private fun getMediaQMinus(): List<Media> {\n        val items = mutableListOf<Media>()\n\n        File(outputDirectory).listFiles()?.forEach {\n            val authority = requireContext().applicationContext.packageName + \".provider\"\n            val mediaUri = FileProvider.getUriForFile(requireContext(), authority, it)\n            items.add(Media(mediaUri, it.extension == \"mp4\", it.lastModified()))\n        }\n\n        return items\n    }\n\n    /**\n     * Check for the permissions\n     */\n    protected fun allPermissionsGranted() = permissions.all {\n        ContextCompat.checkSelfPermission(requireContext(), it) == PackageManager.PERMISSION_GRANTED\n    }\n\n    /**\n     * A function which will be called after the permission check\n     * */\n    open fun onPermissionGranted() = Unit\n\n    /**\n     * An abstract function which will be called on the Back button press\n     * */\n    abstract fun onBackPressed()\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/fragments/CameraFragment.kt",
    "content": "package com.robertlevonyan.demo.camerax.fragments\n\nimport android.annotation.SuppressLint\nimport android.content.ContentValues\nimport android.content.Context\nimport android.content.res.Configuration\nimport android.hardware.display.DisplayManager\nimport android.net.Uri\nimport android.os.Build\nimport android.os.Bundle\nimport android.os.Handler\nimport android.os.HandlerThread\nimport android.provider.MediaStore\nimport android.util.DisplayMetrics\nimport android.util.Log\nimport android.view.GestureDetector\nimport android.view.View\nimport android.widget.Toast\nimport androidx.camera.core.*\nimport androidx.camera.core.ImageCapture.*\nimport androidx.camera.extensions.ExtensionMode\nimport androidx.camera.extensions.ExtensionsManager\nimport androidx.camera.lifecycle.ProcessCameraProvider\nimport androidx.camera.view.PreviewView\nimport androidx.core.content.ContextCompat\nimport androidx.core.view.WindowInsetsCompat\nimport androidx.lifecycle.lifecycleScope\nimport androidx.navigation.Navigation\nimport coil.load\nimport coil.request.ErrorResult\nimport coil.request.ImageRequest\nimport coil.transform.CircleCropTransformation\nimport com.robertlevonyan.demo.camerax.R\nimport com.robertlevonyan.demo.camerax.analyzer.LuminosityAnalyzer\nimport com.robertlevonyan.demo.camerax.databinding.FragmentCameraBinding\nimport com.robertlevonyan.demo.camerax.enums.CameraTimer\nimport com.robertlevonyan.demo.camerax.utils.*\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\nimport java.io.File\nimport java.util.concurrent.ExecutionException\nimport kotlin.math.abs\nimport kotlin.math.max\nimport kotlin.math.min\nimport kotlin.properties.Delegates\n\nclass CameraFragment : BaseFragment<FragmentCameraBinding>(R.layout.fragment_camera) {\n    // An instance for display manager to get display change callbacks\n    private val displayManager by lazy { requireContext().getSystemService(Context.DISPLAY_SERVICE) as DisplayManager }\n\n    // An instance of a helper function to work with Shared Preferences\n    private val prefs by lazy { SharedPrefsManager.newInstance(requireContext()) }\n\n    private var preview: Preview? = null\n    private var cameraProvider: ProcessCameraProvider? = null\n    private var imageCapture: ImageCapture? = null\n    private var imageAnalyzer: ImageAnalysis? = null\n\n    // A lazy instance of the current fragment's view binding\n    override val binding: FragmentCameraBinding by lazy { FragmentCameraBinding.inflate(layoutInflater) }\n\n    private var displayId = -1\n\n    // Selector showing which camera is selected (front or back)\n    private var lensFacing = CameraSelector.DEFAULT_BACK_CAMERA\n    private var hdrCameraSelector: CameraSelector? = null\n\n    // Selector showing which flash mode is selected (on, off or auto)\n    private var flashMode by Delegates.observable(FLASH_MODE_OFF) { _, _, new ->\n        binding.btnFlash.setImageResource(\n            when (new) {\n                FLASH_MODE_ON -> R.drawable.ic_flash_on\n                FLASH_MODE_AUTO -> R.drawable.ic_flash_auto\n                else -> R.drawable.ic_flash_off\n            }\n        )\n    }\n\n    // Selector showing is grid enabled or not\n    private var hasGrid = false\n\n    // Selector showing is hdr enabled or not (will work, only if device's camera supports hdr on hardware level)\n    private var hasHdr = false\n\n    // Selector showing is there any selected timer and it's value (3s or 10s)\n    private var selectedTimer = CameraTimer.OFF\n\n    /**\n     * A display listener for orientation changes that do not trigger a configuration\n     * change, for example if we choose to override config change in manifest or for 180-degree\n     * orientation changes.\n     */\n    private val displayListener = object : DisplayManager.DisplayListener {\n        override fun onDisplayAdded(displayId: Int) = Unit\n        override fun onDisplayRemoved(displayId: Int) = Unit\n\n        @SuppressLint(\"UnsafeExperimentalUsageError\", \"UnsafeOptInUsageError\")\n        override fun onDisplayChanged(displayId: Int) = view?.let { view ->\n            if (displayId == this@CameraFragment.displayId) {\n                preview?.targetRotation = view.display.rotation\n                imageCapture?.targetRotation = view.display.rotation\n                imageAnalyzer?.targetRotation = view.display.rotation\n            }\n        } ?: Unit\n    }\n\n    @SuppressLint(\"ClickableViewAccessibility\")\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        flashMode = prefs.getInt(KEY_FLASH, FLASH_MODE_OFF)\n        hasGrid = prefs.getBoolean(KEY_GRID, false)\n        hasHdr = prefs.getBoolean(KEY_HDR, false)\n        initViews()\n\n        displayManager.registerDisplayListener(displayListener, null)\n\n        binding.run {\n            viewFinder.addOnAttachStateChangeListener(object :\n                View.OnAttachStateChangeListener {\n                override fun onViewDetachedFromWindow(v: View) =\n                    displayManager.registerDisplayListener(displayListener, null)\n\n                override fun onViewAttachedToWindow(v: View) =\n                    displayManager.unregisterDisplayListener(displayListener)\n            })\n\n            btnTakePicture.setOnClickListener { takePicture() }\n            btnGallery.setOnClickListener { openPreview() }\n            btnSwitchCamera.setOnClickListener { toggleCamera() }\n            btnTimer.setOnClickListener { selectTimer() }\n            btnGrid.setOnClickListener { toggleGrid() }\n            btnFlash.setOnClickListener { selectFlash() }\n            btnHdr.setOnClickListener { toggleHdr() }\n            btnTimerOff.setOnClickListener { closeTimerAndSelect(CameraTimer.OFF) }\n            btnTimer3.setOnClickListener { closeTimerAndSelect(CameraTimer.S3) }\n            btnTimer10.setOnClickListener { closeTimerAndSelect(CameraTimer.S10) }\n            btnFlashOff.setOnClickListener { closeFlashAndSelect(FLASH_MODE_OFF) }\n            btnFlashOn.setOnClickListener { closeFlashAndSelect(FLASH_MODE_ON) }\n            btnFlashAuto.setOnClickListener { closeFlashAndSelect(FLASH_MODE_AUTO) }\n            btnExposure.setOnClickListener { flExposure.visibility = View.VISIBLE }\n            flExposure.setOnClickListener { flExposure.visibility = View.GONE }\n\n            // This swipe gesture adds a fun gesture to switch between video and photo\n            val swipeGestures = SwipeGestureDetector().apply {\n                setSwipeCallback(right = {\n                    Navigation.findNavController(view).navigate(R.id.action_camera_to_video)\n                })\n            }\n            val gestureDetectorCompat = GestureDetector(requireContext(), swipeGestures)\n            viewFinder.setOnTouchListener { _, motionEvent ->\n                if (gestureDetectorCompat.onTouchEvent(motionEvent)) return@setOnTouchListener false\n                return@setOnTouchListener true\n            }\n        }\n    }\n\n    /**\n     * Create some initial states\n     * */\n    private fun initViews() {\n        binding.btnGrid.setImageResource(if (hasGrid) R.drawable.ic_grid_on else R.drawable.ic_grid_off)\n        binding.groupGridLines.visibility = if (hasGrid) View.VISIBLE else View.GONE\n        adjustInsets()\n    }\n\n    /**\n     * This methods adds all necessary margins to some views based on window insets and screen orientation\n     * */\n    private fun adjustInsets() {\n        activity?.window?.fitSystemWindows()\n        binding.btnTakePicture.onWindowInsets { view, windowInsets ->\n            if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {\n                view.bottomMargin =\n                    windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom\n            } else {\n                view.endMargin = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).right\n            }\n        }\n        binding.btnTimer.onWindowInsets { view, windowInsets ->\n            view.topMargin = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top\n        }\n        binding.llTimerOptions.onWindowInsets { view, windowInsets ->\n            if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {\n                view.topPadding =\n                    windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top\n            } else {\n                view.startPadding =\n                    windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).left\n            }\n        }\n        binding.llFlashOptions.onWindowInsets { view, windowInsets ->\n            if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {\n                view.topPadding =\n                    windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top\n            } else {\n                view.startPadding =\n                    windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).left\n            }\n        }\n    }\n\n    /**\n     * Change the facing of camera\n     *  toggleButton() function is an Extension function made to animate button rotation\n     * */\n    @SuppressLint(\"RestrictedApi\")\n    fun toggleCamera() = binding.btnSwitchCamera.toggleButton(\n        flag = lensFacing == CameraSelector.DEFAULT_BACK_CAMERA,\n        rotationAngle = 180f,\n        firstIcon = R.drawable.ic_outline_camera_rear,\n        secondIcon = R.drawable.ic_outline_camera_front,\n    ) {\n        lensFacing = if (it) {\n            CameraSelector.DEFAULT_BACK_CAMERA\n        } else {\n            CameraSelector.DEFAULT_FRONT_CAMERA\n        }\n\n        startCamera()\n    }\n\n    /**\n     * Navigate to PreviewFragment\n     * */\n    private fun openPreview() {\n        if (getMedia().isEmpty()) return\n        view?.let { Navigation.findNavController(it).navigate(R.id.action_camera_to_preview) }\n    }\n\n    /**\n     * Show timer selection menu by circular reveal animation.\n     *  circularReveal() function is an Extension function which is adding the circular reveal\n     * */\n    private fun selectTimer() = binding.llTimerOptions.circularReveal(binding.btnTimer)\n\n    /**\n     * This function is called from XML view via Data Binding to select a timer\n     *  possible values are OFF, S3 or S10\n     *  circularClose() function is an Extension function which is adding circular close\n     * */\n    private fun closeTimerAndSelect(timer: CameraTimer) =\n        binding.llTimerOptions.circularClose(binding.btnTimer) {\n            selectedTimer = timer\n            binding.btnTimer.setImageResource(\n                when (timer) {\n                    CameraTimer.S3 -> R.drawable.ic_timer_3\n                    CameraTimer.S10 -> R.drawable.ic_timer_10\n                    CameraTimer.OFF -> R.drawable.ic_timer_off\n                }\n            )\n        }\n\n    /**\n     * Show flashlight selection menu by circular reveal animation.\n     *  circularReveal() function is an Extension function which is adding the circular reveal\n     * */\n    private fun selectFlash() = binding.llFlashOptions.circularReveal(binding.btnFlash)\n\n    /**\n     * This function is called from XML view via Data Binding to select a FlashMode\n     *  possible values are ON, OFF or AUTO\n     *  circularClose() function is an Extension function which is adding circular close\n     * */\n    private fun closeFlashAndSelect(@FlashMode flash: Int) =\n        binding.llFlashOptions.circularClose(binding.btnFlash) {\n            flashMode = flash\n            binding.btnFlash.setImageResource(\n                when (flash) {\n                    FLASH_MODE_ON -> R.drawable.ic_flash_on\n                    FLASH_MODE_OFF -> R.drawable.ic_flash_off\n                    else -> R.drawable.ic_flash_auto\n                }\n            )\n            imageCapture?.flashMode = flashMode\n            prefs.putInt(KEY_FLASH, flashMode)\n        }\n\n    /**\n     * Turns on or off the grid on the screen\n     * */\n    private fun toggleGrid() {\n        binding.btnGrid.toggleButton(\n            flag = hasGrid,\n            rotationAngle = 180f,\n            firstIcon = R.drawable.ic_grid_off,\n            secondIcon = R.drawable.ic_grid_on,\n        ) { flag ->\n            hasGrid = flag\n            prefs.putBoolean(KEY_GRID, flag)\n            binding.groupGridLines.visibility = if (flag) View.VISIBLE else View.GONE\n        }\n    }\n\n    /**\n     * Turns on or off the HDR if available\n     * */\n    private fun toggleHdr() {\n        binding.btnHdr.toggleButton(\n            flag = hasHdr,\n            rotationAngle = 360f,\n            firstIcon = R.drawable.ic_hdr_off,\n            secondIcon = R.drawable.ic_hdr_on,\n        ) { flag ->\n            hasHdr = flag\n            prefs.putBoolean(KEY_HDR, flag)\n            startCamera()\n        }\n    }\n\n    override fun onPermissionGranted() {\n        // Each time apps is coming to foreground the need permission check is being processed\n        binding.viewFinder.let { vf ->\n            vf.post {\n                // Setting current display ID\n                displayId = vf.display.displayId\n                startCamera()\n                lifecycleScope.launch(Dispatchers.IO) {\n                    // Do on IO Dispatcher\n                    setLastPictureThumbnail()\n                }\n            }\n        }\n    }\n\n    private fun setLastPictureThumbnail() = binding.btnGallery.post {\n        getMedia().firstOrNull() // check if there are any photos or videos in the app directory\n            ?.let { setGalleryThumbnail(it.uri) } // preview the last one\n            ?: binding.btnGallery.setImageResource(R.drawable.ic_no_picture) // or the default placeholder\n    }\n\n    /**\n     * Unbinds all the lifecycles from CameraX, then creates new with new parameters\n     * */\n    private fun startCamera() {\n        // This is the CameraX PreviewView where the camera will be rendered\n        val viewFinder = binding.viewFinder\n\n        val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())\n        cameraProviderFuture.addListener({\n            try {\n                cameraProvider = cameraProviderFuture.get()\n            } catch (e: InterruptedException) {\n                Toast.makeText(requireContext(), \"Error starting camera\", Toast.LENGTH_SHORT).show()\n                return@addListener\n            } catch (e: ExecutionException) {\n                Toast.makeText(requireContext(), \"Error starting camera\", Toast.LENGTH_SHORT).show()\n                return@addListener\n            }\n\n            // The display information\n            val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }\n            // The ratio for the output image and preview\n            val aspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)\n            // The display rotation\n            val rotation = viewFinder.display.rotation\n\n            val localCameraProvider = cameraProvider\n                ?: throw IllegalStateException(\"Camera initialization failed.\")\n\n            // The Configuration of camera preview\n            preview = Preview.Builder()\n                .setTargetAspectRatio(aspectRatio) // set the camera aspect ratio\n                .setTargetRotation(rotation) // set the camera rotation\n                .build()\n\n            // The Configuration of image capture\n            imageCapture = Builder()\n                .setCaptureMode(CAPTURE_MODE_MAXIMIZE_QUALITY) // setting to have pictures with highest quality possible (may be slow)\n                .setFlashMode(flashMode) // set capture flash\n                .setTargetAspectRatio(aspectRatio) // set the capture aspect ratio\n                .setTargetRotation(rotation) // set the capture rotation\n                .build()\n\n            checkForHdrExtensionAvailability()\n\n            // The Configuration of image analyzing\n            imageAnalyzer = ImageAnalysis.Builder()\n                .setTargetAspectRatio(aspectRatio) // set the analyzer aspect ratio\n                .setTargetRotation(rotation) // set the analyzer rotation\n                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) // in our analysis, we care about the latest image\n                .build()\n                .also { setLuminosityAnalyzer(it) }\n\n            // Unbind the use-cases before rebinding them\n            localCameraProvider.unbindAll()\n            // Bind all use cases to the camera with lifecycle\n            bindToLifecycle(localCameraProvider, viewFinder)\n        }, ContextCompat.getMainExecutor(requireContext()))\n    }\n\n    private fun checkForHdrExtensionAvailability() {\n        // Create a Vendor Extension for HDR\n        val extensionsManagerFuture = ExtensionsManager.getInstanceAsync(\n            requireContext(), cameraProvider ?: return,\n        )\n        extensionsManagerFuture.addListener(\n            {\n                val extensionsManager = extensionsManagerFuture.get() ?: return@addListener\n                val cameraProvider = cameraProvider ?: return@addListener\n\n                val isAvailable = extensionsManager.isExtensionAvailable(lensFacing, ExtensionMode.HDR)\n\n                // check for any extension availability\n                println(\"AUTO \" + extensionsManager.isExtensionAvailable(lensFacing, ExtensionMode.AUTO))\n                println(\"HDR \" + extensionsManager.isExtensionAvailable(lensFacing, ExtensionMode.HDR))\n                println(\"FACE RETOUCH \" + extensionsManager.isExtensionAvailable(lensFacing, ExtensionMode.FACE_RETOUCH))\n                println(\"BOKEH \" + extensionsManager.isExtensionAvailable(lensFacing, ExtensionMode.BOKEH))\n                println(\"NIGHT \" + extensionsManager.isExtensionAvailable(lensFacing, ExtensionMode.NIGHT))\n                println(\"NONE \" + extensionsManager.isExtensionAvailable(lensFacing, ExtensionMode.NONE))\n\n                // Check if the extension is available on the device\n                if (!isAvailable) {\n                    // If not, hide the HDR button\n                    binding.btnHdr.visibility = View.GONE\n                } else if (hasHdr) {\n                    // If yes, turn on if the HDR is turned on by the user\n                    binding.btnHdr.visibility = View.VISIBLE\n                    hdrCameraSelector =\n                        extensionsManager.getExtensionEnabledCameraSelector(lensFacing, ExtensionMode.HDR)\n                }\n            },\n            ContextCompat.getMainExecutor(requireContext())\n        )\n    }\n\n    private fun setLuminosityAnalyzer(imageAnalysis: ImageAnalysis) {\n        // Use a worker thread for image analysis to prevent glitches\n        val analyzerThread = HandlerThread(\"LuminosityAnalysis\").apply { start() }\n        imageAnalysis.setAnalyzer(\n            ThreadExecutor(Handler(analyzerThread.looper)),\n            LuminosityAnalyzer()\n        )\n    }\n\n    private fun bindToLifecycle(localCameraProvider: ProcessCameraProvider, viewFinder: PreviewView) {\n        try {\n            localCameraProvider.bindToLifecycle(\n                viewLifecycleOwner, // current lifecycle owner\n                hdrCameraSelector ?: lensFacing, // either front or back facing\n                preview, // camera preview use case\n                imageCapture, // image capture use case\n                imageAnalyzer, // image analyzer use case\n            ).run {\n                // Init camera exposure control\n                cameraInfo.exposureState.run {\n                    val lower = exposureCompensationRange.lower\n                    val upper = exposureCompensationRange.upper\n\n                    binding.sliderExposure.run {\n                        valueFrom = lower.toFloat()\n                        valueTo = upper.toFloat()\n                        stepSize = 1f\n                        value = exposureCompensationIndex.toFloat()\n\n                        addOnChangeListener { _, value, _ ->\n                            cameraControl.setExposureCompensationIndex(value.toInt())\n                        }\n                    }\n                }\n            }\n\n            // Attach the viewfinder's surface provider to preview use case\n            preview?.setSurfaceProvider(viewFinder.surfaceProvider)\n        } catch (e: Exception) {\n            Log.e(TAG, \"Failed to bind use cases\", e)\n        }\n    }\n\n    /**\n     *  Detecting the most suitable aspect ratio for current dimensions\n     *\n     *  @param width - preview width\n     *  @param height - preview height\n     *  @return suitable aspect ratio\n     */\n    private fun aspectRatio(width: Int, height: Int): Int {\n        val previewRatio = max(width, height).toDouble() / min(width, height)\n        if (abs(previewRatio - RATIO_4_3_VALUE) <= abs(previewRatio - RATIO_16_9_VALUE)) {\n            return AspectRatio.RATIO_4_3\n        }\n        return AspectRatio.RATIO_16_9\n    }\n\n    @Suppress(\"NON_EXHAUSTIVE_WHEN\")\n    private fun takePicture() = lifecycleScope.launch(Dispatchers.Main) {\n        // Show a timer based on user selection\n        when (selectedTimer) {\n            CameraTimer.S3 -> for (i in 3 downTo 1) {\n                binding.tvCountDown.text = i.toString()\n                delay(1000)\n            }\n            CameraTimer.S10 -> for (i in 10 downTo 1) {\n                binding.tvCountDown.text = i.toString()\n                delay(1000)\n            }\n            CameraTimer.OFF -> {}\n        }\n        binding.tvCountDown.text = \"\"\n        captureImage()\n    }\n\n    private fun captureImage() {\n        val localImageCapture = imageCapture ?: throw IllegalStateException(\"Camera initialization failed.\")\n\n        // Setup image capture metadata\n        val metadata = Metadata().apply {\n            // Mirror image when using the front camera\n            isReversedHorizontal = lensFacing == CameraSelector.DEFAULT_FRONT_CAMERA\n        }\n        MediaStore.Images.Media.EXTERNAL_CONTENT_URI\n        // Options fot the output image file\n        val outputOptions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {\n            val contentValues = ContentValues().apply {\n                put(MediaStore.MediaColumns.DISPLAY_NAME, System.currentTimeMillis())\n                put(MediaStore.MediaColumns.MIME_TYPE, \"image/jpeg\")\n                put(MediaStore.MediaColumns.RELATIVE_PATH, outputDirectory)\n            }\n\n            val contentResolver = requireContext().contentResolver\n\n            // Create the output uri\n            val contentUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)\n\n            OutputFileOptions.Builder(contentResolver, contentUri, contentValues)\n        } else {\n            File(outputDirectory).mkdirs()\n            val file = File(outputDirectory, \"${System.currentTimeMillis()}.jpg\")\n\n            OutputFileOptions.Builder(file)\n        }.setMetadata(metadata).build()\n\n        localImageCapture.takePicture(\n            outputOptions, // the options needed for the final image\n            requireContext().mainExecutor(), // the executor, on which the task will run\n            object : OnImageSavedCallback { // the callback, about the result of capture process\n                override fun onImageSaved(outputFileResults: OutputFileResults) {\n                    // This function is called if capture is successfully completed\n                    outputFileResults.savedUri\n                        ?.let { uri ->\n                            setGalleryThumbnail(uri)\n                            Log.d(TAG, \"Photo saved in $uri\")\n                        }\n                        ?: setLastPictureThumbnail()\n                }\n\n                override fun onError(exception: ImageCaptureException) {\n                    // This function is called if there is an errors during capture process\n                    val msg = \"Photo capture failed: ${exception.message}\"\n                    Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()\n                    Log.e(TAG, msg)\n                    exception.printStackTrace()\n                }\n            }\n        )\n    }\n\n    private fun setGalleryThumbnail(savedUri: Uri?) = binding.btnGallery.load(savedUri) {\n        placeholder(R.drawable.ic_no_picture)\n        transformations(CircleCropTransformation())\n        listener(object : ImageRequest.Listener {\n            override fun onError(request: ImageRequest, result: ErrorResult) {\n                super.onError(request, result)\n                binding.btnGallery.load(savedUri) {\n                    placeholder(R.drawable.ic_no_picture)\n                    transformations(CircleCropTransformation())\n//                    fetcher(VideoFrameUriFetcher(requireContext()))\n                }\n            }\n        })\n    }\n\n    override fun onDestroyView() {\n        super.onDestroyView()\n        displayManager.unregisterDisplayListener(displayListener)\n    }\n\n    override fun onBackPressed() = when {\n        binding.llTimerOptions.visibility == View.VISIBLE -> binding.llTimerOptions.circularClose(binding.btnTimer)\n        binding.llFlashOptions.visibility == View.VISIBLE -> binding.llFlashOptions.circularClose(binding.btnFlash)\n        else -> requireActivity().finish()\n    }\n\n    companion object {\n        private const val TAG = \"CameraXDemo\"\n\n        const val KEY_FLASH = \"sPrefFlashCamera\"\n        const val KEY_GRID = \"sPrefGridCamera\"\n        const val KEY_HDR = \"sPrefHDR\"\n\n        private const val RATIO_4_3_VALUE = 4.0 / 3.0 // aspect ratio 4x3\n        private const val RATIO_16_9_VALUE = 16.0 / 9.0 // aspect ratio 16x9\n    }\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/fragments/PreviewFragment.kt",
    "content": "package com.robertlevonyan.demo.camerax.fragments\n\nimport android.content.Intent\nimport android.os.Bundle\nimport android.view.View\nimport androidx.core.view.WindowInsetsCompat\nimport androidx.navigation.Navigation\nimport com.robertlevonyan.demo.camerax.R\nimport com.robertlevonyan.demo.camerax.adapter.MediaAdapter\nimport com.robertlevonyan.demo.camerax.databinding.FragmentPreviewBinding\nimport com.robertlevonyan.demo.camerax.utils.*\n\nclass PreviewFragment : BaseFragment<FragmentPreviewBinding>(R.layout.fragment_preview) {\n    private val mediaAdapter = MediaAdapter(\n        onItemClick = { isVideo, uri ->\n            if (!isVideo) {\n                val visibility = if (binding.groupPreviewActions.visibility == View.VISIBLE) View.GONE else View.VISIBLE\n                binding.groupPreviewActions.visibility = visibility\n            } else {\n                val play = Intent(Intent.ACTION_VIEW, uri).apply { setDataAndType(uri, \"video/mp4\") }\n                startActivity(play)\n            }\n        },\n        onDeleteClick = { isEmpty, uri ->\n            if (isEmpty) onBackPressed()\n\n            val resolver = requireContext().applicationContext.contentResolver\n            resolver.delete(uri, null, null)\n        },\n    )\n    private var currentPage = 0\n    override val binding: FragmentPreviewBinding by lazy { FragmentPreviewBinding.inflate(layoutInflater) }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        adjustInsets()\n\n        // Check for the permissions and show files\n        if (allPermissionsGranted()) {\n            binding.pagerPhotos.apply {\n                adapter = mediaAdapter.apply { submitList(getMedia()) }\n                onPageSelected { page -> currentPage = page }\n            }\n        }\n\n        binding.btnBack.setOnClickListener { onBackPressed() }\n        binding.btnShare.setOnClickListener { shareImage() }\n        binding.btnDelete.setOnClickListener { deleteImage() }\n    }\n\n    /**\n     * This methods adds all necessary margins to some views based on window insets and screen orientation\n     * */\n    private fun adjustInsets() {\n        activity?.window?.fitSystemWindows()\n        binding.btnBack.onWindowInsets { view, windowInsets ->\n            view.topMargin = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top\n        }\n        binding.btnShare.onWindowInsets { view, windowInsets ->\n            view.bottomMargin = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom\n        }\n    }\n\n    private fun shareImage() {\n        mediaAdapter.shareImage(currentPage) { share(it) }\n    }\n\n    private fun deleteImage() {\n        mediaAdapter.deleteImage(currentPage)\n    }\n\n    override fun onBackPressed() {\n        view?.let { Navigation.findNavController(it).popBackStack() }\n    }\n\n}"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/fragments/VideoFragment.kt",
    "content": "package com.robertlevonyan.demo.camerax.fragments\n\nimport android.animation.ObjectAnimator\nimport android.annotation.SuppressLint\nimport android.content.ContentValues\nimport android.content.Context\nimport android.content.res.Configuration\nimport android.hardware.camera2.CameraCharacteristics\nimport android.hardware.camera2.CameraMetadata\nimport android.hardware.display.DisplayManager\nimport android.net.Uri\nimport android.os.Bundle\nimport android.provider.MediaStore\nimport android.util.DisplayMetrics\nimport android.util.Log\nimport android.view.GestureDetector\nimport android.view.View\nimport android.widget.Toast\nimport androidx.camera.camera2.interop.Camera2CameraInfo\nimport androidx.camera.camera2.interop.ExperimentalCamera2Interop\nimport androidx.camera.core.*\nimport androidx.camera.lifecycle.ProcessCameraProvider\nimport androidx.camera.video.*\nimport androidx.core.animation.doOnCancel\nimport androidx.core.content.ContextCompat\nimport androidx.core.view.WindowInsetsCompat\nimport androidx.lifecycle.lifecycleScope\nimport androidx.navigation.Navigation\nimport coil.load\nimport coil.request.ErrorResult\nimport coil.request.ImageRequest\nimport coil.transform.CircleCropTransformation\nimport com.robertlevonyan.demo.camerax.R\nimport com.robertlevonyan.demo.camerax.databinding.FragmentVideoBinding\nimport com.robertlevonyan.demo.camerax.utils.*\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport kotlin.math.abs\nimport kotlin.math.max\nimport kotlin.math.min\nimport kotlin.properties.Delegates\n\n\n@ExperimentalCamera2Interop\n@SuppressLint(\"RestrictedApi\")\nclass VideoFragment : BaseFragment<FragmentVideoBinding>(R.layout.fragment_video) {\n    // An instance for display manager to get display change callbacks\n    private val displayManager by lazy { requireContext().getSystemService(Context.DISPLAY_SERVICE) as DisplayManager }\n\n    // An instance of a helper function to work with Shared Preferences\n    private val prefs by lazy { SharedPrefsManager.newInstance(requireContext()) }\n\n    private var camera: Camera? = null\n    private var cameraProvider: ProcessCameraProvider? = null\n    private var preview: Preview? = null\n    private var videoCapture: VideoCapture<Recorder>? = null\n\n    private var displayId = -1\n\n    // Selector showing which camera is selected (front or back)\n    private var lensFacing = CameraSelector.DEFAULT_BACK_CAMERA\n\n    // Selector showing which flash mode is selected (on, off or auto)\n    private var flashMode by Delegates.observable(ImageCapture.FLASH_MODE_OFF) { _, _, new ->\n        binding.btnFlash.setImageResource(\n            when (new) {\n                ImageCapture.FLASH_MODE_ON -> R.drawable.ic_flash_on\n                ImageCapture.FLASH_MODE_AUTO -> R.drawable.ic_flash_auto\n                else -> R.drawable.ic_flash_off\n            }\n        )\n    }\n\n    // Selector showing is grid enabled or not\n    private var hasGrid = false\n\n    // Selector showing is flash enabled or not\n    private var isTorchOn = false\n\n    // Selector showing is recording currently active\n    private var isRecording = false\n    private val animateRecord by lazy {\n        ObjectAnimator.ofFloat(binding.btnRecordVideo, View.ALPHA, 1f, 0.5f).apply {\n            repeatMode = ObjectAnimator.REVERSE\n            repeatCount = ObjectAnimator.INFINITE\n            doOnCancel { binding.btnRecordVideo.alpha = 1f }\n        }\n    }\n\n    // A lazy instance of the current fragment's view binding\n    override val binding: FragmentVideoBinding by lazy { FragmentVideoBinding.inflate(layoutInflater) }\n\n    /**\n     * A display listener for orientation changes that do not trigger a configuration\n     * change, for example if we choose to override config change in manifest or for 180-degree\n     * orientation changes.\n     */\n    private val displayListener = object : DisplayManager.DisplayListener {\n        override fun onDisplayAdded(displayId: Int) = Unit\n        override fun onDisplayRemoved(displayId: Int) = Unit\n\n        @SuppressLint(\"UnsafeExperimentalUsageError\", \"UnsafeOptInUsageError\")\n        override fun onDisplayChanged(displayId: Int) = view?.let { view ->\n            if (displayId == this@VideoFragment.displayId) {\n                preview?.targetRotation = view.display.rotation\n                videoCapture?.targetRotation = view.display.rotation\n            }\n        } ?: Unit\n    }\n\n    @SuppressLint(\"ClickableViewAccessibility\")\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        hasGrid = prefs.getBoolean(KEY_GRID, false)\n        initViews()\n\n        displayManager.registerDisplayListener(displayListener, null)\n\n        binding.run {\n            viewFinder.addOnAttachStateChangeListener(object :\n                View.OnAttachStateChangeListener {\n                override fun onViewDetachedFromWindow(v: View) =\n                    displayManager.registerDisplayListener(displayListener, null)\n\n                override fun onViewAttachedToWindow(v: View) =\n                    displayManager.unregisterDisplayListener(displayListener)\n            })\n            binding.btnRecordVideo.setOnClickListener { recordVideo() }\n            btnGallery.setOnClickListener { openPreview() }\n            btnSwitchCamera.setOnClickListener { toggleCamera() }\n            btnGrid.setOnClickListener { toggleGrid() }\n            btnFlash.setOnClickListener { toggleFlash() }\n\n            // This swipe gesture adds a fun gesture to switch between video and photo\n            val swipeGestures = SwipeGestureDetector().apply {\n                setSwipeCallback(left = {\n                    Navigation.findNavController(view).navigate(R.id.action_video_to_camera)\n                })\n            }\n\n            val gestureDetectorCompat = GestureDetector(requireContext(), swipeGestures)\n            viewFinder.setOnTouchListener { _, motionEvent ->\n                if (gestureDetectorCompat.onTouchEvent(motionEvent)) return@setOnTouchListener false\n                return@setOnTouchListener true\n            }\n        }\n    }\n\n    /**\n     * Create some initial states\n     * */\n    private fun initViews() {\n        binding.btnGrid.setImageResource(if (hasGrid) R.drawable.ic_grid_on else R.drawable.ic_grid_off)\n        binding.groupGridLines.visibility = if (hasGrid) View.VISIBLE else View.GONE\n\n        adjustInsets()\n    }\n\n    /**\n     * This methods adds all necessary margins to some views based on window insets and screen orientation\n     * */\n    private fun adjustInsets() {\n        activity?.window?.fitSystemWindows()\n        binding.btnRecordVideo.onWindowInsets { view, windowInsets ->\n            if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {\n                view.bottomMargin = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom\n            } else {\n                view.endMargin = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).right\n            }\n        }\n        binding.btnFlash.onWindowInsets { view, windowInsets ->\n            view.topMargin = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top\n        }\n    }\n\n    /**\n     * Change the facing of camera\n     *  toggleButton() function is an Extension function made to animate button rotation\n     * */\n    private fun toggleCamera() = binding.btnSwitchCamera.toggleButton(\n        flag = lensFacing == CameraSelector.DEFAULT_BACK_CAMERA,\n        rotationAngle = 180f,\n        firstIcon = R.drawable.ic_outline_camera_rear,\n        secondIcon = R.drawable.ic_outline_camera_front,\n    ) {\n        lensFacing = if (it) {\n            CameraSelector.DEFAULT_BACK_CAMERA\n        } else {\n            CameraSelector.DEFAULT_FRONT_CAMERA\n        }\n\n        startCamera()\n    }\n\n    /**\n     * Unbinds all the lifecycles from CameraX, then creates new with new parameters\n     * */\n    private fun startCamera() {\n        // This is the Texture View where the camera will be rendered\n        val viewFinder = binding.viewFinder\n\n        val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())\n        cameraProviderFuture.addListener({\n            cameraProvider = cameraProviderFuture.get()\n\n            // The display information\n            val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }\n            // The ratio for the output image and preview\n            val aspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)\n            // The display rotation\n            val rotation = viewFinder.display.rotation\n\n            val localCameraProvider = cameraProvider\n                ?: throw IllegalStateException(\"Camera initialization failed.\")\n\n            // The Configuration of camera preview\n            preview = Preview.Builder()\n                .setTargetAspectRatio(aspectRatio) // set the camera aspect ratio\n                .setTargetRotation(rotation) // set the camera rotation\n                .build()\n\n            val cameraInfo = localCameraProvider.availableCameraInfos.filter {\n                Camera2CameraInfo\n                    .from(it)\n                    .getCameraCharacteristic(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_BACK\n            }\n\n            val supportedQualities = QualitySelector.getSupportedQualities(cameraInfo[0])\n            val qualitySelector = QualitySelector.fromOrderedList(\n                listOf(Quality.UHD, Quality.FHD, Quality.HD, Quality.SD),\n                FallbackStrategy.lowerQualityOrHigherThan(Quality.SD)\n            )\n            val recorder = Recorder.Builder()\n                .setExecutor(ContextCompat.getMainExecutor(requireContext())).setQualitySelector(qualitySelector)\n                .build()\n            videoCapture = VideoCapture.withOutput(recorder)\n\n            localCameraProvider.unbindAll() // unbind the use-cases before rebinding them\n\n            try {\n                // Bind all use cases to the camera with lifecycle\n                camera = localCameraProvider.bindToLifecycle(\n                    viewLifecycleOwner, // current lifecycle owner\n                    lensFacing, // either front or back facing\n                    preview, // camera preview use case\n                    videoCapture, // video capture use case\n                )\n\n                // Attach the viewfinder's surface provider to preview use case\n                preview?.setSurfaceProvider(viewFinder.surfaceProvider)\n            } catch (e: Exception) {\n                Log.e(TAG, \"Failed to bind use cases\", e)\n            }\n        }, ContextCompat.getMainExecutor(requireContext()))\n    }\n\n    /**\n     *  Detecting the most suitable aspect ratio for current dimensions\n     *\n     *  @param width - preview width\n     *  @param height - preview height\n     *  @return suitable aspect ratio\n     */\n    private fun aspectRatio(width: Int, height: Int): Int {\n        val previewRatio = max(width, height).toDouble() / min(width, height)\n        if (abs(previewRatio - RATIO_4_3_VALUE) <= abs(previewRatio - RATIO_16_9_VALUE)) {\n            return AspectRatio.RATIO_4_3\n        }\n        return AspectRatio.RATIO_16_9\n    }\n\n    /**\n     * Navigate to PreviewFragment\n     * */\n    private fun openPreview() {\n        view?.let { Navigation.findNavController(it).navigate(R.id.action_video_to_preview) }\n    }\n\n    var recording: Recording? = null\n\n    @SuppressLint(\"MissingPermission\")\n    private fun recordVideo() {\n        if (recording != null) {\n            animateRecord.cancel()\n            recording?.stop()\n        }\n        val name = \"CameraX-recording-${System.currentTimeMillis()}.mp4\"\n        val contentValues = ContentValues().apply {\n            put(MediaStore.Video.Media.DISPLAY_NAME, name)\n        }\n        val mediaStoreOutput = MediaStoreOutputOptions.Builder(\n            requireContext().contentResolver,\n            MediaStore.Video.Media.EXTERNAL_CONTENT_URI\n        )\n            .setContentValues(contentValues)\n            .build()\n        recording = videoCapture?.output\n            ?.prepareRecording(requireContext(), mediaStoreOutput)\n            ?.withAudioEnabled()\n            ?.start(ContextCompat.getMainExecutor(requireContext())) { event ->\n                when (event) {\n                    is VideoRecordEvent.Start -> {\n                        animateRecord.start()\n                    }\n                    is VideoRecordEvent.Finalize -> {\n                        if (!event.hasError()) {\n                            val msg = \"Video capture succeeded: \" +\n                                    \"${event.outputResults.outputUri}\"\n                            Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT)\n                                .show()\n                            Log.d(TAG, msg)\n                        } else {\n                            recording?.close()\n                            recording = null\n                            Log.e(TAG, \"Video capture ends with error: \" +\n                                    \"${event.error}\")\n                        }\n                    }\n                }\n            }\n        isRecording = !isRecording\n    }\n\n    /**\n     * Turns on or off the grid on the screen\n     * */\n    private fun toggleGrid() = binding.btnGrid.toggleButton(\n        flag = hasGrid,\n        rotationAngle = 180f,\n        firstIcon = R.drawable.ic_grid_off,\n        secondIcon = R.drawable.ic_grid_on\n    ) { flag ->\n        hasGrid = flag\n        prefs.putBoolean(KEY_GRID, flag)\n        binding.groupGridLines.visibility = if (flag) View.VISIBLE else View.GONE\n    }\n\n    /**\n     * Turns on or off the flashlight\n     * */\n    private fun toggleFlash() = binding.btnFlash.toggleButton(\n        flag = flashMode == ImageCapture.FLASH_MODE_ON,\n        rotationAngle = 360f,\n        firstIcon = R.drawable.ic_flash_off,\n        secondIcon = R.drawable.ic_flash_on\n    ) { flag ->\n        isTorchOn = flag\n        flashMode = if (flag) ImageCapture.FLASH_MODE_ON else ImageCapture.FLASH_MODE_OFF\n        camera?.cameraControl?.enableTorch(flag)\n    }\n\n    override fun onPermissionGranted() {\n        // Each time apps is coming to foreground the need permission check is being processed\n        binding.viewFinder.let { vf ->\n            vf.post {\n                // Setting current display ID\n                displayId = vf.display.displayId\n                startCamera()\n                lifecycleScope.launch(Dispatchers.IO) {\n                    // Do on IO Dispatcher\n                    setLastPictureThumbnail()\n                }\n                camera?.cameraControl?.enableTorch(isTorchOn)\n            }\n        }\n    }\n\n    private fun setLastPictureThumbnail() = binding.btnGallery.post {\n        getMedia().firstOrNull() // check if there are any photos or videos in the app directory\n            ?.let { setGalleryThumbnail(it.uri) } // preview the last one\n            ?: binding.btnGallery.setImageResource(R.drawable.ic_no_picture) // or the default placeholder\n    }\n\n    private fun setGalleryThumbnail(savedUri: Uri?) = binding.btnGallery.let { btnGallery ->\n        // Do the work on view's thread, this is needed, because the function is called in a Coroutine Scope's IO Dispatcher\n        btnGallery.post {\n            btnGallery.load(savedUri) {\n                placeholder(R.drawable.ic_no_picture)\n                transformations(CircleCropTransformation())\n                listener(object : ImageRequest.Listener {\n                    override fun onError(request: ImageRequest, result: ErrorResult) {\n                        super.onError(request, result)\n                        binding.btnGallery.load(savedUri) {\n                            placeholder(R.drawable.ic_no_picture)\n                            transformations(CircleCropTransformation())\n//                            fetcher(VideoFrameUriFetcher(requireContext()))\n                        }\n                    }\n                })\n            }\n        }\n    }\n\n    override fun onBackPressed() = requireActivity().finish()\n\n    override fun onStop() {\n        super.onStop()\n        camera?.cameraControl?.enableTorch(false)\n    }\n\n    companion object {\n        private const val TAG = \"CameraXDemo\"\n\n        const val KEY_GRID = \"sPrefGridVideo\"\n\n        private const val RATIO_4_3_VALUE = 4.0 / 3.0 // aspect ratio 4x3\n        private const val RATIO_16_9_VALUE = 16.0 / 9.0 // aspect ratio 16x9\n    }\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/utils/Extensions.kt",
    "content": "package com.robertlevonyan.demo.camerax.utils\n\nimport android.animation.Animator\nimport android.animation.AnimatorListenerAdapter\nimport android.content.Context\nimport android.content.Intent\nimport android.content.res.Configuration\nimport android.os.Build\nimport android.view.*\nimport android.view.View.*\nimport android.widget.ImageButton\nimport androidx.annotation.DrawableRes\nimport androidx.core.animation.doOnEnd\nimport androidx.core.animation.doOnStart\nimport androidx.core.view.ViewCompat\nimport androidx.core.view.WindowCompat\nimport androidx.core.view.WindowInsetsCompat\nimport androidx.core.view.updateLayoutParams\nimport androidx.fragment.app.Fragment\nimport androidx.viewpager2.widget.ViewPager2\nimport com.robertlevonyan.demo.camerax.adapter.Media\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.delay\nimport kotlinx.coroutines.launch\nimport java.util.concurrent.Executor\n\nfun ImageButton.toggleButton(\n    flag: Boolean, rotationAngle: Float, @DrawableRes firstIcon: Int, @DrawableRes secondIcon: Int,\n    action: (Boolean) -> Unit\n) {\n    if (flag) {\n        if (rotationY == 0f) rotationY = rotationAngle\n        animate().rotationY(0f).apply {\n            setListener(object : AnimatorListenerAdapter() {\n                override fun onAnimationEnd(animation: Animator) {\n                    super.onAnimationEnd(animation)\n                    action(!flag)\n                }\n            })\n        }.duration = 200\n        GlobalScope.launch(Dispatchers.Main) {\n            delay(100)\n            setImageResource(firstIcon)\n        }\n    } else {\n        if (rotationY == rotationAngle) rotationY = 0f\n        animate().rotationY(rotationAngle).apply {\n            setListener(object : AnimatorListenerAdapter() {\n                override fun onAnimationEnd(animation: Animator) {\n                    super.onAnimationEnd(animation)\n                    action(!flag)\n                }\n            })\n        }.duration = 200\n        GlobalScope.launch(Dispatchers.Main) {\n            delay(100)\n            setImageResource(secondIcon)\n        }\n    }\n}\n\nfun ViewGroup.circularReveal(button: ImageButton) {\n    ViewAnimationUtils.createCircularReveal(\n        this,\n        button.x.toInt() + button.width / 2,\n        button.y.toInt() + button.height / 2,\n        0f,\n        if (button.context.resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) this.width.toFloat() else this.height.toFloat()\n    ).apply {\n        duration = 500\n        doOnStart { visibility = VISIBLE }\n    }.start()\n}\n\nfun ViewGroup.circularClose(button: ImageButton, action: () -> Unit = {}) {\n    ViewAnimationUtils.createCircularReveal(\n        this,\n        button.x.toInt() + button.width / 2,\n        button.y.toInt() + button.height / 2,\n        if (button.context.resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) this.width.toFloat() else this.height.toFloat(),\n        0f\n    ).apply {\n        duration = 500\n        doOnStart { action() }\n        doOnEnd { visibility = GONE }\n    }.start()\n}\n\nfun View.onWindowInsets(action: (View, WindowInsetsCompat) -> Unit) {\n    ViewCompat.requestApplyInsets(this)\n    ViewCompat.setOnApplyWindowInsetsListener(this) { v, insets ->\n        action(v, insets)\n        insets\n    }\n}\n\nfun Window.fitSystemWindows() {\n    WindowCompat.setDecorFitsSystemWindows(this, false)\n}\n\nfun Fragment.share(media: Media, title: String = \"Share with...\") {\n    val share = Intent(Intent.ACTION_SEND)\n    share.type = \"image/*\"\n    share.putExtra(Intent.EXTRA_STREAM, media.uri)\n    startActivity(Intent.createChooser(share, title))\n}\n\nfun ViewPager2.onPageSelected(action: (Int) -> Unit) {\n    registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {\n        override fun onPageSelected(position: Int) {\n            super.onPageSelected(position)\n            action(position)\n        }\n    })\n}\n\nfun Context.mainExecutor(): Executor = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {\n    mainExecutor\n} else {\n    MainExecutor()\n}\n\nval Context.layoutInflater: LayoutInflater\n    get() = LayoutInflater.from(this)\n\nvar View.topMargin: Int\n    get() = (this.layoutParams as ViewGroup.MarginLayoutParams).topMargin\n    set(value) {\n        updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin = value }\n    }\n\nvar View.topPadding: Int\n    get() = paddingTop\n    set(value) {\n        updateLayoutParams { setPaddingRelative(paddingStart, value, paddingEnd, paddingBottom) }\n    }\n\nvar View.bottomMargin: Int\n    get() = (this.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin\n    set(value) {\n        updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin = value }\n    }\n\nvar View.endMargin: Int\n    get() = (this.layoutParams as ViewGroup.MarginLayoutParams).marginEnd\n    set(value) {\n        updateLayoutParams<ViewGroup.MarginLayoutParams> { marginEnd = value }\n    }\n\nvar View.startMargin: Int\n    get() = (this.layoutParams as ViewGroup.MarginLayoutParams).marginStart\n    set(value) {\n        updateLayoutParams<ViewGroup.MarginLayoutParams> { marginStart = value }\n    }\n\nvar View.startPadding: Int\n    get() = paddingStart\n    set(value) {\n        updateLayoutParams { setPaddingRelative(value, paddingTop, paddingEnd, paddingBottom) }\n    }"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/utils/MainExecutor.kt",
    "content": "package com.robertlevonyan.demo.camerax.utils\n\nimport android.os.Handler\nimport android.os.Looper\n\nclass MainExecutor : ThreadExecutor(Handler(Looper.getMainLooper())) {\n    override fun execute(runnable: Runnable) {\n        handler.post(runnable)\n    }\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/utils/SharedPrefsManager.kt",
    "content": "package com.robertlevonyan.demo.camerax.utils\n\nimport android.content.Context\n\nclass SharedPrefsManager private constructor(private val context: Context) {\n    private val preferences = context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE)\n\n    companion object {\n        private const val PREFERENCES = \"sPrefs\"\n\n        @Synchronized\n        fun newInstance(context: Context) = SharedPrefsManager(context)\n    }\n\n    fun putBoolean(key: String, value: Boolean) = preferences.edit().putBoolean(key, value).apply()\n\n    fun putInt(key: String, value: Int) = preferences.edit().putInt(key, value).apply()\n\n    fun getBoolean(key: String, defValue: Boolean) = preferences.getBoolean(key, defValue)\n\n    fun getInt(key: String, defValue: Int) = preferences.getInt(key, defValue)\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/utils/SwipeGestureDetector.kt",
    "content": "package com.robertlevonyan.demo.camerax.utils\n\nimport android.view.GestureDetector\nimport android.view.MotionEvent\nimport kotlin.math.abs\n\nclass SwipeGestureDetector : GestureDetector.SimpleOnGestureListener() {\n    companion object {\n        private const val MIN_SWIPE_DISTANCE_X = 100\n    }\n\n    var swipeCallback: SwipeCallback? = null\n\n    override fun onFling(e1: MotionEvent?, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {\n        e1 ?: return super.onFling(e1, e2, velocityX, velocityY)\n\n        val deltaX = e1.x - e2.x\n        val deltaXAbs = abs(deltaX)\n\n        if (deltaXAbs >= MIN_SWIPE_DISTANCE_X) {\n            if (deltaX > 0) {\n                swipeCallback?.onLeftSwipe()\n            } else {\n                swipeCallback?.onRightSwipe()\n            }\n        }\n\n        return true\n    }\n\n    interface SwipeCallback {\n        fun onLeftSwipe()\n\n        fun onRightSwipe()\n    }\n\n    fun setSwipeCallback(left: ()-> Unit = {}, right: ()-> Unit = {}) {\n        swipeCallback = object : SwipeCallback {\n            override fun onLeftSwipe() {\n                left()\n            }\n\n            override fun onRightSwipe() {\n                right()\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/kotlin/com/robertlevonyan/demo/camerax/utils/ThreadExecutor.kt",
    "content": "package com.robertlevonyan.demo.camerax.utils\n\nimport android.os.Handler\nimport java.util.concurrent.Executor\n\nopen class ThreadExecutor(protected val handler: Handler) : Executor {\n    override fun execute(runnable: Runnable) {\n        handler.post(runnable)\n    }\n}\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/anim/slide_in.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:duration=\"300\"\n    android:fromXDelta=\"100%\"\n    android:toXDelta=\"0%\" />"
  },
  {
    "path": "camerax-demo/app/src/main/res/anim/slide_in_pop.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:duration=\"300\"\n    android:fromXDelta=\"-100%\"\n    android:toXDelta=\"0%\" />"
  },
  {
    "path": "camerax-demo/app/src/main/res/anim/slide_out.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:duration=\"300\"\n    android:fromXDelta=\"0%\"\n    android:toXDelta=\"-100%\" />"
  },
  {
    "path": "camerax-demo/app/src/main/res/anim/slide_out_pop.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:duration=\"300\"\n    android:fromXDelta=\"0%\"\n    android:toXDelta=\"100%\" />"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/bg_button_round.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    <solid android:color=\"@color/colorButtonGreyBg\"/>\n</shape>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/bg_options.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    <corners android:radius=\"16dp\" />\n    <solid android:color=\"@color/colorPrimaryDark\" />\n</shape>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_arrow_back.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=\"@android:color/white\"\n        android:pathData=\"M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_delete.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=\"@android:color/white\"\n        android:pathData=\"M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z\"/>\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_edit.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=\"@android:color/white\"\n        android:pathData=\"M14.06,9L15,9.94L5.92,19H5V18.08L14.06,9M17.66,3C17.41,3 17.15,3.1 16.96,3.29L15.13,5.12L18.88,8.87L20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18.17,3.09 17.92,3 17.66,3M14.06,6.19L3,17.25V21H6.75L17.81,9.94L14.06,6.19Z\"/>\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_exposure.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=\"@android:color/white\"\n        android:pathData=\"M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM17.59,5L5,17.59L5,5h12.59zM6.41,19L19,6.41L19,19L6.41,19zM6,7h5v1.5L6,8.5zM16,12.5h-1.5v2h-2L12.5,16h2v2L16,18v-2h2v-1.5h-2z\" />\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_flash_auto.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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=\"@android:color/white\"\n        android:pathData=\"M16.85,7.65L18,4L19.15,7.65M19,2H17L13.8,11H15.7L16.4,9H19.6L20.3,11H22.2M3,2V14H6V23L13,11H9L13,2H3Z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_flash_off.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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=\"@android:color/white\"\n        android:pathData=\"M17,10H13L17,2H7V4.18L15.46,12.64M3.27,3L2,4.27L7,9.27V13H10V22L13.58,15.86L17.73,20L19,18.73L3.27,3Z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_flash_on.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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=\"@android:color/white\"\n        android:pathData=\"M7,2V13H10V22L17,10H13L17,2H7Z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_grid_off.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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=\"@android:color/white\"\n        android:pathData=\"M0,2.77L1.28,1.5L22.5,22.72L21.23,24L19.23,22H4C2.92,22 2,21.1 2,20V4.77L0,2.77M10,4V7.68L8,5.68V4H6.32L4.32,2H20A2,2 0 0,1 22,4V19.7L20,17.7V16H18.32L16.32,14H20V10H16V13.68L14,11.68V10H12.32L10.32,8H14V4H10M16,4V8H20V4H16M16,20H17.23L16,18.77V20M4,8H5.23L4,6.77V8M10,14H11.23L10,12.77V14M14,20V16.77L13.23,16H10V20H14M8,20V16H4V20H8M8,14V10.77L7.23,10H4V14H8Z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_grid_on.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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=\"@android:color/white\"\n        android:pathData=\"M10,4V8H14V4H10M16,4V8H20V4H16M16,10V14H20V10H16M16,16V20H20V16H16M14,20V16H10V20H14M8,20V16H4V20H8M8,14V10H4V14H8M8,8V4H4V8H8M10,14H14V10H10V14M4,2H20A2,2 0 0,1 22,4V20A2,2 0 0,1 20,22H4C2.92,22 2,21.1 2,20V4A2,2 0 0,1 4,2Z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_hdr_off.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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=\"@android:color/white\"\n        android:pathData=\"M17.5,15V13H18.6L19.5,15H21L20.1,12.9C20.6,12.7 21,12.1 21,11.5V10.5C21,9.7 20.3,9 19.5,9H16V13.9L17.1,15H17.5M17.5,10.5H19.5V11.5H17.5V10.5M13,10.5V10.9L14.5,12.4V10.5C14.5,9.7 13.8,9 13,9H11.1L12.6,10.5H13M9.5,9.5L2.5,2.5L1.4,3.5L6.9,9H6.5V11H4.5V9H3V15H4.5V12.5H6.5V15H8V10.1L9.5,11.6V15H12.9L20.5,22.6L21.6,21.5L9.5,9.5Z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_hdr_on.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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=\"@android:color/white\"\n        android:pathData=\"M21,11.5V10.5C21,9.7 20.3,9 19.5,9H16V15H17.5V13H18.6L19.5,15H21L20.1,12.9C20.6,12.6 21,12.1 21,11.5M19.5,11.5H17.5V10.5H19.5V11.5M6.5,11H4.5V9H3V15H4.5V12.5H6.5V15H8V9H6.5V11M13,9H9.5V15H13C13.8,15 14.5,14.3 14.5,13.5V10.5C14.5,9.7 13.8,9 13,9M13,13.5H11V10.5H13V13.5Z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"50.303032\"\n    android:viewportHeight=\"50.303032\">\n  <group android:translateX=\"8.551516\"\n      android:translateY=\"8.551516\">\n    <path\n        android:pathData=\"M18.5,19l-1.9,0.7L14.7,19l0.7,1.9l-0.7,1.9l1.9,-0.7l1.9,0.7L17.8,21L18.5,19M23.9,13.6H21l-1.7,-1.8h-5.5l-1.7,1.8H9.3c-1,0 -1.8,0.8 -1.8,1.8v11c0,1 0.8,1.8 1.8,1.8h14.7c1,0 1.8,-0.8 1.8,-1.8v-11C25.8,14.4 24.9,13.6 23.9,13.6M23.9,26.5H9.3v-11H13l0.6,-0.6l1.1,-1.2h3.9l1.1,1.2l0.6,0.6h3.8V26.5M16.6,16.4c-2.6,0 -4.6,2 -4.6,4.6s2,4.6 4.6,4.6s4.6,-2 4.6,-4.6S19.2,16.4 16.6,16.4M16.6,23.7c-1.6,0 -2.8,-1.2 -2.8,-2.8s1.2,-2.8 2.8,-2.8s2.8,1.2 2.8,2.8S18.2,23.7 16.6,23.7z\"\n        android:fillColor=\"#1A1A18\"/>\n    <path\n        android:pathData=\"M18.6,19l-2,0.8l-2,-0.8l0.8,2l-0.8,2l2,-0.8l2,0.8l-0.8,-2L18.6,19\"\n        android:fillColor=\"#E7A942\"/>\n    <path\n        android:pathData=\"M33.2,7.9H11.8C10.3,7.9 9,6.6 9,5.1v0c0,-1.5 1.2,-2.8 2.8,-2.8h21.4V7.9z\"\n        android:fillColor=\"#E7A942\"/>\n    <path\n        android:pathData=\"M12.7,3.6h1c0.3,0 0.6,0.1 0.8,0.2c0.2,0.1 0.4,0.3 0.5,0.5c0.1,0.2 0.2,0.5 0.2,0.7S15.1,5.6 15,5.8c-0.1,0.2 -0.3,0.4 -0.5,0.5c-0.2,0.1 -0.5,0.2 -0.8,0.2h-1V3.6zM13.7,6c0.3,0 0.5,-0.1 0.7,-0.2c0.2,-0.2 0.2,-0.4 0.2,-0.7c0,-0.3 -0.1,-0.5 -0.2,-0.7c-0.2,-0.2 -0.4,-0.2 -0.7,-0.2h-0.4V6H13.7z\"\n        android:fillColor=\"#1A1A18\"/>\n    <path\n        android:pathData=\"M16,6.4c-0.2,-0.1 -0.3,-0.2 -0.4,-0.4s-0.1,-0.3 -0.1,-0.6c0,-0.2 0,-0.4 0.1,-0.5c0.1,-0.2 0.2,-0.3 0.4,-0.4c0.2,-0.1 0.3,-0.1 0.5,-0.1c0.2,0 0.4,0 0.5,0.1c0.2,0.1 0.3,0.2 0.3,0.4c0.1,0.2 0.1,0.3 0.1,0.5c0,0.1 0,0.1 0,0.2h-1.5c0,0.2 0.1,0.3 0.2,0.4s0.2,0.1 0.4,0.1c0.1,0 0.2,0 0.3,-0.1C16.9,5.9 17,5.9 17,5.8L17.4,6c-0.2,0.4 -0.5,0.5 -0.9,0.5C16.3,6.5 16.1,6.5 16,6.4zM17,5.2c0,-0.1 0,-0.1 -0.1,-0.2s-0.1,-0.1 -0.2,-0.2c-0.1,0 -0.2,-0.1 -0.3,-0.1c-0.1,0 -0.2,0 -0.3,0.1C16.1,5 16,5.1 16,5.2H17z\"\n        android:fillColor=\"#1A1A18\"/>\n    <path\n        android:pathData=\"M17.9,4.4h0.5v0.3h0c0.1,-0.1 0.1,-0.2 0.3,-0.2c0.1,-0.1 0.2,-0.1 0.4,-0.1c0.1,0 0.3,0 0.4,0.1c0.1,0.1 0.2,0.2 0.2,0.3c0.1,-0.1 0.2,-0.2 0.3,-0.3c0.1,-0.1 0.3,-0.1 0.4,-0.1c0.2,0 0.4,0.1 0.5,0.2C21,4.7 21,4.9 21,5.2v1.3h-0.5V5.3c0,-0.1 0,-0.2 -0.1,-0.3c-0.1,-0.1 -0.1,-0.1 -0.3,-0.1c-0.1,0 -0.2,0.1 -0.3,0.2s-0.1,0.3 -0.1,0.4v1h-0.5V5.3c0,-0.1 0,-0.2 -0.1,-0.3C19,4.9 19,4.9 18.8,4.9c-0.1,0 -0.2,0.1 -0.3,0.2c-0.1,0.1 -0.1,0.3 -0.1,0.4v1h-0.5V4.4z\"\n        android:fillColor=\"#1A1A18\"/>\n    <path\n        android:pathData=\"M21.9,6.4c-0.2,-0.1 -0.3,-0.2 -0.4,-0.4s-0.1,-0.3 -0.1,-0.6c0,-0.2 0,-0.4 0.1,-0.6c0.1,-0.2 0.2,-0.3 0.4,-0.4s0.4,-0.1 0.6,-0.1c0.2,0 0.4,0 0.6,0.1s0.3,0.2 0.4,0.4c0.1,0.2 0.1,0.3 0.1,0.6c0,0.2 0,0.4 -0.1,0.6s-0.2,0.3 -0.4,0.4s-0.4,0.1 -0.6,0.1C22.3,6.5 22.1,6.5 21.9,6.4zM22.8,6c0.1,0 0.2,-0.1 0.2,-0.2c0.1,-0.1 0.1,-0.2 0.1,-0.3c0,-0.1 0,-0.2 -0.1,-0.3S22.9,5 22.8,4.9c-0.1,0 -0.2,-0.1 -0.3,-0.1c-0.1,0 -0.2,0 -0.3,0.1C22.1,5 22.1,5 22,5.1s-0.1,0.2 -0.1,0.3s0,0.2 0.1,0.3c0.1,0.1 0.1,0.2 0.2,0.2C22.3,6 22.4,6 22.5,6C22.6,6 22.7,6 22.8,6z\"\n        android:fillColor=\"#1A1A18\"/>\n  </group>\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_no_picture.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportWidth=\"197.76\"\n    android:viewportHeight=\"197.76\">\n    <path\n        android:fillColor=\"@color/colorButtonGreyBg\"\n        android:pathData=\"M98.88,98.88m-98.88,0a98.88,98.88 0,1 1,197.76 0a98.88,98.88 0,1 1,-197.76 0\" />\n    <path\n        android:pathData=\"M69,72.74L80.21,72.74l7.47,-7.47h22.4L117.54,72.74h11.21a7.47,7.47 0,0 1,7.47 7.47v44.81a7.47,7.47 0,0 1,-7.47 7.47L69,132.49A7.47,7.47 0,0 1,61.54 125.02L61.54,80.21a7.47,7.47 0,0 1,7.47 -7.47m34,16.62L95.33,99.54l5.79,7.73 -3.25,2.47L88.68,97.54 76.47,113.82h44.82Z\"\n        android:strokeWidth=\"7\"\n        android:strokeColor=\"@android:color/white\" />\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_outline_camera_enhance.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=\"#FF000000\"\n      android:pathData=\"M12,10l-0.94,2.06L9,13l2.06,0.94L12,16l0.94,-2.06L15,13l-2.06,-0.94zM20,5h-3.17L15,3L9,3L7.17,5L4,5c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,7c0,-1.1 -0.9,-2 -2,-2zM20,19L4,19L4,7h4.05l0.59,-0.65L9.88,5h4.24l1.24,1.35 0.59,0.65L20,7v12zM12,8c-2.76,0 -5,2.24 -5,5s2.24,5 5,5 5,-2.24 5,-5 -2.24,-5 -5,-5zM12,16c-1.65,0 -3,-1.35 -3,-3s1.35,-3 3,-3 3,1.35 3,3 -1.35,3 -3,3z\"/>\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_outline_camera_front.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=\"@android:color/white\"\n        android:pathData=\"M5,20v2h5v2l3,-3 -3,-3v2zM14,20h5v2h-5zM11.99,8C13.1,8 14,7.1 14,6s-0.9,-2 -2.01,-2S10,4.9 10,6s0.89,2 1.99,2zM17,0L7,0C5.9,0 5,0.9 5,2v14c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,2c0,-1.1 -0.9,-2 -2,-2zM17,16L7,16v-2h10v2zM17,12.5c0,-1.67 -3.33,-2.5 -5,-2.5s-5,0.83 -5,2.5L7,2h10v10.5z\" />\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_outline_camera_rear.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=\"@android:color/white\"\n        android:pathData=\"M5,20v2h5v2l3,-3 -3,-3v2zM14,20h5v2h-5zM17,0L7,0C5.9,0 5,0.9 5,2v14c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,2c0,-1.1 -0.9,-2 -2,-2zM17,16L7,16L7,2h10v14zM12,7c1.1,0 2,-0.9 1.99,-2 0,-1.1 -0.9,-2 -2,-2S10,3.9 10,5s0.89,2 2,2z\" />\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_play.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=\"@android:color/white\"\n        android:pathData=\"M8.5,8.64L13.77,12L8.5,15.36V8.64M6.5,5V19L17.5,12\" />\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_share.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=\"@android:color/white\"\n      android:pathData=\"M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92s2.92,-1.31 2.92,-2.92c0,-1.61 -1.31,-2.92 -2.92,-2.92zM18,4c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM6,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM18,20.02c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1z\"/>\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_take_picture.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"@dimen/button_size_big\"\n    android:height=\"@dimen/button_size_big\"\n    android:viewportWidth=\"214.68\"\n    android:viewportHeight=\"214.68\">\n    <path\n        android:fillAlpha=\"1\"\n        android:fillColor=\"#fff\"\n        android:pathData=\"M107.34,107.34m-98.88,0a98.88,98.88 0,1 1,197.76 0a98.88,98.88 0,1 1,-197.76 0\" />\n    <path\n        android:fillAlpha=\"0.5\"\n        android:fillColor=\"#fff\"\n        android:pathData=\"M107.34,107.34m-107.34,0a107.34,107.34 0,1 1,214.68 0a107.34,107.34 0,1 1,-214.68 0\"\n        android:strokeAlpha=\"0.5\" />\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_take_video.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"@dimen/button_size_big\"\n    android:height=\"@dimen/button_size_big\"\n    android:viewportWidth=\"214.68\"\n    android:viewportHeight=\"214.68\">\n    <path\n        android:fillAlpha=\"0.5\"\n        android:fillColor=\"#fff\"\n        android:pathData=\"M107.34,107.34m-107.34,0a107.34,107.34 0,1 1,214.68 0a107.34,107.34 0,1 1,-214.68 0\"\n        android:strokeAlpha=\"0.5\" />\n    <path\n        android:fillColor=\"#cc3636\"\n        android:pathData=\"M107.34,107.34m-98.88,0a98.88,98.88 0,1 1,197.76 0a98.88,98.88 0,1 1,-197.76 0\" />\n</vector>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_timer_10.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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=\"@android:color/white\"\n        android:pathData=\"M12.9,13.22C12.9,13.82 12.86,14.33 12.78,14.75C12.7,15.17 12.58,15.5 12.42,15.77C12.26,16.03 12.06,16.22 11.83,16.34C11.6,16.46 11.32,16.5 11,16.5C10.71,16.5 10.43,16.46 10.19,16.34C9.95,16.22 9.75,16.03 9.59,15.77C9.43,15.5 9.3,15.17 9.21,14.75C9.12,14.33 9.08,13.82 9.08,13.22V10.72C9.08,10.12 9.12,9.61 9.21,9.2C9.3,8.79 9.42,8.46 9.59,8.2C9.75,7.95 9.95,7.77 10.19,7.65C10.43,7.54 10.7,7.5 11,7.5C11.31,7.5 11.58,7.54 11.81,7.65C12.05,7.76 12.25,7.94 12.41,8.2C12.57,8.45 12.7,8.78 12.78,9.19C12.86,9.6 12.91,10.11 12.91,10.71V13.22M13.82,7.05C13.5,6.65 13.07,6.35 12.59,6.17C12.12,6 11.58,5.9 11,5.9C10.42,5.9 9.89,6 9.41,6.17C8.93,6.35 8.5,6.64 8.18,7.05C7.84,7.46 7.58,8 7.39,8.64C7.21,9.29 7.11,10.09 7.11,11.03V12.95C7.11,13.89 7.2,14.69 7.39,15.34C7.58,16 7.84,16.53 8.19,16.94C8.53,17.35 8.94,17.65 9.42,17.83C9.9,18 10.43,18.11 11,18.11C11.6,18.11 12.13,18 12.6,17.83C13.08,17.65 13.5,17.35 13.82,16.94C14.16,16.53 14.42,16 14.6,15.34C14.78,14.69 14.88,13.89 14.88,12.95V11.03C14.88,10.09 14.79,9.29 14.6,8.64C14.42,8 14.16,7.45 13.82,7.05M23.78,14.37C23.64,14.09 23.43,13.84 23.15,13.63C22.87,13.42 22.54,13.24 22.14,13.1C21.74,12.96 21.29,12.83 20.79,12.72C20.44,12.65 20.15,12.57 19.92,12.5C19.69,12.41 19.5,12.33 19.37,12.24C19.23,12.15 19.14,12.05 19.09,11.94C19.04,11.83 19,11.7 19,11.55C19,11.41 19.04,11.27 19.1,11.14C19.16,11 19.25,10.89 19.37,10.8C19.5,10.7 19.64,10.62 19.82,10.56C20,10.5 20.22,10.47 20.46,10.47C20.71,10.47 20.93,10.5 21.12,10.58C21.31,10.65 21.47,10.75 21.6,10.87C21.73,11 21.82,11.13 21.89,11.29C21.95,11.45 22,11.61 22,11.78H23.94C23.94,11.39 23.86,11.03 23.7,10.69C23.54,10.35 23.31,10.06 23,9.81C22.71,9.56 22.35,9.37 21.92,9.22C21.5,9.07 21,9 20.46,9C19.95,9 19.5,9.07 19.07,9.21C18.66,9.35 18.3,9.54 18,9.78C17.72,10 17.5,10.3 17.34,10.62C17.18,10.94 17.11,11.27 17.11,11.63C17.11,12 17.19,12.32 17.34,12.59C17.5,12.87 17.7,13.11 18,13.32C18.25,13.53 18.58,13.7 18.96,13.85C19.34,14 19.77,14.11 20.23,14.21C20.62,14.29 20.94,14.38 21.18,14.47C21.42,14.56 21.61,14.66 21.75,14.76C21.88,14.86 21.97,15 22,15.1C22.07,15.22 22.09,15.35 22.09,15.5C22.09,15.81 21.96,16.06 21.69,16.26C21.42,16.46 21.03,16.55 20.5,16.55C20.3,16.55 20.09,16.53 19.88,16.47C19.67,16.42 19.5,16.34 19.32,16.23C19.15,16.12 19,15.97 18.91,15.79C18.8,15.61 18.74,15.38 18.73,15.12H16.84C16.84,15.5 16.92,15.83 17.08,16.17C17.24,16.5 17.47,16.82 17.78,17.1C18.09,17.37 18.47,17.59 18.93,17.76C19.39,17.93 19.91,18 20.5,18C21.04,18 21.5,17.95 21.95,17.82C22.38,17.69 22.75,17.5 23.06,17.28C23.37,17.05 23.6,16.77 23.77,16.45C23.94,16.13 24,15.78 24,15.39C24,15 23.93,14.65 23.78,14.37M0,7.72V9.4L3,8.4V18H5V6H4.75L0,7.72Z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_timer_3.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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=\"@android:color/white\"\n        android:pathData=\"M20.87,14.37C20.73,14.09 20.5,13.84 20.24,13.63C19.96,13.42 19.63,13.24 19.23,13.1C18.83,12.96 18.38,12.83 17.88,12.72C17.53,12.65 17.24,12.57 17,12.5C16.78,12.41 16.6,12.33 16.46,12.24C16.32,12.15 16.23,12.05 16.18,11.94C16.13,11.83 16.1,11.7 16.1,11.55C16.1,11.4 16.13,11.27 16.19,11.14C16.25,11 16.34,10.89 16.46,10.8C16.58,10.7 16.73,10.62 16.91,10.56C17.09,10.5 17.31,10.47 17.55,10.47C17.8,10.47 18,10.5 18.21,10.58C18.4,10.65 18.56,10.75 18.69,10.87C18.82,11 18.91,11.13 19,11.29C19.04,11.45 19.08,11.61 19.08,11.78H21.03C21.03,11.39 20.95,11.03 20.79,10.69C20.63,10.35 20.4,10.06 20.1,9.81C19.8,9.56 19.44,9.37 19,9.22C18.58,9.07 18.09,9 17.55,9C17.04,9 16.57,9.07 16.16,9.21C15.75,9.35 15.39,9.54 15.1,9.78C14.81,10 14.59,10.3 14.43,10.62C14.27,10.94 14.2,11.27 14.2,11.63C14.2,12 14.28,12.31 14.43,12.59C14.58,12.87 14.8,13.11 15.07,13.32C15.34,13.53 15.67,13.7 16.05,13.85C16.43,14 16.86,14.11 17.32,14.21C17.71,14.29 18.03,14.38 18.27,14.47C18.5,14.56 18.7,14.66 18.84,14.76C18.97,14.86 19.06,15 19.11,15.1C19.16,15.22 19.18,15.35 19.18,15.5C19.18,15.81 19.05,16.06 18.78,16.26C18.5,16.46 18.12,16.55 17.61,16.55C17.39,16.55 17.18,16.53 16.97,16.47C16.76,16.42 16.57,16.34 16.41,16.23C16.24,16.12 16.11,15.97 16,15.79C15.89,15.61 15.83,15.38 15.82,15.12H13.93C13.93,15.5 14,15.83 14.17,16.17C14.33,16.5 14.56,16.82 14.87,17.1C15.18,17.37 15.56,17.59 16,17.76C16.5,17.93 17,18 17.6,18C18.13,18 18.61,17.95 19.04,17.82C19.47,17.69 19.84,17.5 20.15,17.28C20.46,17.05 20.69,16.77 20.86,16.45C21.03,16.13 21.11,15.78 21.11,15.39C21.09,15 21,14.65 20.87,14.37M11.61,12.97C11.45,12.73 11.25,12.5 11,12.32C10.74,12.13 10.43,11.97 10.06,11.84C10.36,11.7 10.63,11.54 10.86,11.34C11.09,11.14 11.28,10.93 11.43,10.7C11.58,10.47 11.7,10.24 11.77,10C11.85,9.75 11.88,9.5 11.88,9.26C11.88,8.71 11.79,8.22 11.6,7.8C11.42,7.38 11.16,7.03 10.82,6.74C10.5,6.46 10.09,6.24 9.62,6.1C9.17,5.97 8.65,5.9 8.09,5.9C7.54,5.9 7.03,6 6.57,6.14C6.1,6.31 5.7,6.54 5.37,6.83C5.04,7.12 4.77,7.46 4.59,7.86C4.39,8.25 4.3,8.69 4.3,9.15H6.28C6.28,8.89 6.33,8.66 6.42,8.46C6.5,8.26 6.64,8.08 6.8,7.94C6.97,7.8 7.16,7.69 7.38,7.61C7.6,7.53 7.84,7.5 8.11,7.5C8.72,7.5 9.17,7.65 9.47,7.96C9.77,8.27 9.91,8.71 9.91,9.28C9.91,9.55 9.87,9.8 9.79,10C9.71,10.24 9.58,10.43 9.41,10.59C9.24,10.75 9.03,10.87 8.78,10.96C8.53,11.05 8.23,11.09 7.89,11.09H6.72V12.66H7.9C8.24,12.66 8.54,12.7 8.81,12.77C9.08,12.85 9.31,12.96 9.5,13.12C9.69,13.28 9.84,13.5 9.94,13.73C10.04,13.97 10.1,14.27 10.1,14.6C10.1,15.22 9.92,15.69 9.57,16C9.22,16.35 8.73,16.5 8.12,16.5C7.83,16.5 7.56,16.47 7.32,16.38C7.08,16.3 6.88,16.18 6.71,16C6.54,15.86 6.41,15.68 6.32,15.46C6.23,15.24 6.18,15 6.18,14.74H4.19C4.19,15.29 4.3,15.77 4.5,16.19C4.72,16.61 5,16.96 5.37,17.24C5.73,17.5 6.14,17.73 6.61,17.87C7.08,18 7.57,18.08 8.09,18.08C8.66,18.08 9.18,18 9.67,17.85C10.16,17.7 10.58,17.47 10.93,17.17C11.29,16.87 11.57,16.5 11.77,16.07C11.97,15.64 12.07,15.14 12.07,14.59C12.07,14.3 12.03,14 11.96,13.73C11.88,13.5 11.77,13.22 11.61,12.97Z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/drawable/ic_timer_off.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<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=\"@android:color/white\"\n        android:pathData=\"M12,20A7,7 0 0,1 5,13C5,11.72 5.35,10.5 5.95,9.5L15.5,19.04C14.5,19.65 13.28,20 12,20M3,4L1.75,5.27L4.5,8.03C3.55,9.45 3,11.16 3,13A9,9 0 0,0 12,22C13.84,22 15.55,21.45 17,20.5L19.5,23L20.75,21.73L13.04,14L3,4M11,9.44L13,11.44V8H11M15,1H9V3H15M19.04,4.55L17.62,5.97C16.07,4.74 14.12,4 12,4C10.17,4 8.47,4.55 7.05,5.5L8.5,6.94C9.53,6.35 10.73,6 12,6A7,7 0 0,1 19,13C19,14.27 18.65,15.47 18.06,16.5L19.5,17.94C20.45,16.53 21,14.83 21,13C21,10.88 20.26,8.93 19.03,7.39L20.45,5.97L19.04,4.55Z\" />\n</vector>"
  },
  {
    "path": "camerax-demo/app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <androidx.fragment.app.FragmentContainerView\n        android:id=\"@+id/fragmentNavHost\"\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"
  },
  {
    "path": "camerax-demo/app/src/main/res/layout/fragment_camera.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:animateLayoutChanges=\"true\"\n    android:background=\"@android:color/black\"\n    tools:context=\".fragments.CameraFragment\">\n\n    <androidx.camera.view.PreviewView\n        android:id=\"@+id/viewFinder\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.4\"\n        android:background=\"@android:color/black\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"@id/btnTakePicture\" />\n\n    <ImageButton\n        android:id=\"@+id/btnTakePicture\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@android:color/transparent\"\n        android:padding=\"@dimen/double_margin\"\n        android:src=\"@drawable/ic_take_picture\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnGallery\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:scaleType=\"centerCrop\"\n        android:src=\"@drawable/ic_no_picture\"\n        app:layout_constraintBottom_toBottomOf=\"@id/btnTakePicture\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toEndOf=\"@id/btnTakePicture\"\n        app:layout_constraintTop_toTopOf=\"@id/btnTakePicture\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnSwitchCamera\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@drawable/bg_button_round\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_outline_camera_front\"\n        app:layout_constraintBottom_toBottomOf=\"@id/btnTakePicture\"\n        app:layout_constraintEnd_toStartOf=\"@id/btnTakePicture\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"@id/btnTakePicture\"\n        tools:ignore=\"ContentDescription\" />\n\n    <View\n        android:id=\"@+id/viewBg2\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.4\"\n        android:background=\"@android:color/black\"\n        android:elevation=\"1dp\"\n        app:layout_constraintBottom_toBottomOf=\"@id/btnFlash\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnTimer\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_timer_off\"\n        app:layout_constraintEnd_toStartOf=\"@+id/btnGrid\"\n        app:layout_constraintHorizontal_bias=\"0.5\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnGrid\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_grid_off\"\n        app:layout_constraintEnd_toStartOf=\"@+id/btnFlash\"\n        app:layout_constraintHorizontal_bias=\"0.5\"\n        app:layout_constraintStart_toEndOf=\"@+id/btnTimer\"\n        app:layout_constraintTop_toTopOf=\"@id/btnTimer\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnFlash\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_flash_off\"\n        app:layout_constraintEnd_toStartOf=\"@+id/btnHdr\"\n        app:layout_constraintHorizontal_bias=\"0.5\"\n        app:layout_constraintStart_toEndOf=\"@+id/btnGrid\"\n        app:layout_constraintTop_toTopOf=\"@id/btnGrid\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnHdr\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_hdr_off\"\n        app:layout_constraintEnd_toStartOf=\"@id/btnExposure\"\n        app:layout_constraintHorizontal_bias=\"0.5\"\n        app:layout_constraintStart_toEndOf=\"@+id/btnFlash\"\n        app:layout_constraintTop_toTopOf=\"@id/btnFlash\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnExposure\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_exposure\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.5\"\n        app:layout_constraintStart_toEndOf=\"@+id/btnHdr\"\n        app:layout_constraintTop_toTopOf=\"@id/btnFlash\"\n        tools:ignore=\"ContentDescription\" />\n\n    <View\n        android:id=\"@+id/gridVertical1\"\n        android:layout_width=\"1dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.33\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/gridVertical2\"\n        android:layout_width=\"1dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.66\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/gridHorizontal1\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"1dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.33\" />\n\n    <View\n        android:id=\"@+id/gridHorizontal2\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"1dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.66\" />\n\n    <androidx.constraintlayout.widget.Group\n        android:id=\"@+id/groupGridLines\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:visibility=\"gone\"\n        app:constraint_referenced_ids=\"gridVertical1,gridVertical2,gridHorizontal1,gridHorizontal2\" />\n\n    <LinearLayout\n        android:id=\"@+id/llTimerOptions\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@android:color/black\"\n        android:elevation=\"3dp\"\n        android:orientation=\"horizontal\"\n        android:paddingStart=\"@dimen/fab_margin\"\n        android:paddingTop=\"@dimen/double_margin\"\n        android:paddingEnd=\"@dimen/fab_margin\"\n        android:paddingBottom=\"@dimen/fab_margin\"\n        android:visibility=\"gone\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\">\n\n        <ImageButton\n            android:id=\"@+id/btnTimerOff\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"@dimen/button_size_small\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_timer_off\"\n            tools:ignore=\"ContentDescription\" />\n\n        <ImageButton\n            android:id=\"@+id/btnTimer3\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"@dimen/button_size_small\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_timer_3\"\n            tools:ignore=\"ContentDescription\" />\n\n        <ImageButton\n            android:id=\"@+id/btnTimer10\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"@dimen/button_size_small\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_timer_10\"\n            tools:ignore=\"ContentDescription\" />\n    </LinearLayout>\n\n    <LinearLayout\n        android:id=\"@+id/llFlashOptions\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@android:color/black\"\n        android:elevation=\"3dp\"\n        android:orientation=\"horizontal\"\n        android:paddingStart=\"@dimen/fab_margin\"\n        android:paddingTop=\"@dimen/double_margin\"\n        android:paddingEnd=\"@dimen/fab_margin\"\n        android:paddingBottom=\"@dimen/fab_margin\"\n        android:visibility=\"gone\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\">\n\n        <ImageButton\n            android:id=\"@+id/btnFlashOff\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"@dimen/button_size_small\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_flash_off\"\n            tools:ignore=\"ContentDescription\" />\n\n        <ImageButton\n            android:id=\"@+id/btnFlashAuto\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"@dimen/button_size_small\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_flash_auto\"\n            tools:ignore=\"ContentDescription\" />\n\n        <ImageButton\n            android:id=\"@+id/btnFlashOn\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"@dimen/button_size_small\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_flash_on\"\n            tools:ignore=\"ContentDescription\" />\n    </LinearLayout>\n\n    <FrameLayout\n        android:id=\"@+id/flExposure\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:elevation=\"3dp\"\n        android:orientation=\"horizontal\"\n        android:padding=\"@dimen/double_margin\"\n        android:visibility=\"gone\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\">\n\n        <com.google.android.material.slider.Slider\n            android:id=\"@+id/sliderExposure\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:layout_margin=\"@dimen/fab_margin\"\n            android:background=\"@drawable/bg_options\"\n            android:paddingHorizontal=\"@dimen/fab_margin\"\n            android:paddingVertical=\"@dimen/double_margin\"\n            android:progressBackgroundTint=\"@android:color/white\"\n            app:haloColor=\"@color/colorAccent\"\n            app:thumbColor=\"@color/colorAccent\" />\n    </FrameLayout>\n\n    <TextView\n        android:id=\"@+id/tvCountDown\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:elevation=\"4dp\"\n        android:textColor=\"@android:color/white\"\n        android:textSize=\"@dimen/count_down_text_size\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        tools:text=\"0\" />\n</androidx.constraintlayout.widget.ConstraintLayout>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/layout/fragment_preview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout 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/layoutRoot\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@android:color/black\"\n    tools:context=\".fragments.PreviewFragment\">\n\n    <androidx.viewpager2.widget.ViewPager2\n        android:id=\"@+id/pagerPhotos\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:orientation=\"horizontal\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/bgTop\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.4\"\n        android:background=\"@android:color/black\"\n        app:layout_constraintBottom_toBottomOf=\"@id/btnBack\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/bgBottom\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.4\"\n        android:background=\"@android:color/black\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"@id/btnShare\" />\n\n    <ImageButton\n        android:id=\"@+id/btnBack\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"?selectableItemBackgroundBorderless\"\n        android:fitsSystemWindows=\"false\"\n        android:padding=\"@dimen/fab_margin\"\n        android:src=\"@drawable/ic_arrow_back\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnShare\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"?selectableItemBackgroundBorderless\"\n        android:fitsSystemWindows=\"false\"\n        android:padding=\"@dimen/fab_margin\"\n        android:src=\"@drawable/ic_share\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.3\"\n        app:layout_constraintStart_toStartOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnDelete\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"?selectableItemBackgroundBorderless\"\n        android:fitsSystemWindows=\"false\"\n        android:padding=\"@dimen/fab_margin\"\n        android:src=\"@drawable/ic_delete\"\n        app:layout_constraintBottom_toBottomOf=\"@id/btnShare\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.7\"\n        app:layout_constraintStart_toStartOf=\"parent\" />\n\n    <androidx.constraintlayout.widget.Group\n        android:id=\"@+id/groupPreviewActions\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        app:constraint_referenced_ids=\"bgTop,bgBottom,btnBack,btnShare,btnDelete\" />\n</androidx.constraintlayout.widget.ConstraintLayout>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/layout/fragment_video.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@android:color/black\"\n    tools:context=\".fragments.VideoFragment\">\n\n    <androidx.camera.view.PreviewView\n        android:id=\"@+id/viewFinder\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.4\"\n        android:background=\"@android:color/black\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"@id/btnRecordVideo\" />\n\n    <ImageButton\n        android:id=\"@+id/btnRecordVideo\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@android:color/transparent\"\n        android:padding=\"@dimen/double_margin\"\n        android:src=\"@drawable/ic_take_video\"\n        app:backgroundTint=\"@android:color/transparent\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnGallery\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:scaleType=\"centerCrop\"\n        android:src=\"@drawable/ic_no_picture\"\n        app:layout_constraintBottom_toBottomOf=\"@id/btnRecordVideo\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toEndOf=\"@id/btnRecordVideo\"\n        app:layout_constraintTop_toTopOf=\"@id/btnRecordVideo\" />\n\n    <ImageButton\n        android:id=\"@+id/btnSwitchCamera\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@drawable/bg_button_round\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_outline_camera_front\"\n        app:layout_constraintBottom_toBottomOf=\"@id/btnRecordVideo\"\n        app:layout_constraintEnd_toStartOf=\"@id/btnRecordVideo\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"@id/btnRecordVideo\" />\n\n    <View\n        android:id=\"@+id/viewBg2\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.4\"\n        android:background=\"@android:color/black\"\n        android:elevation=\"1dp\"\n        app:layout_constraintBottom_toBottomOf=\"@id/btnFlash\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnGrid\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_grid_off\"\n        app:layout_constraintBottom_toBottomOf=\"@id/btnFlash\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.3\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"@id/btnFlash\" />\n\n    <ImageButton\n        android:id=\"@+id/btnFlash\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_flash_off\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.7\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/gridVertical1\"\n        android:layout_width=\"1dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.33\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/gridVertical2\"\n        android:layout_width=\"1dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.66\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/gridHorizontal1\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"1dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.33\" />\n\n    <View\n        android:id=\"@+id/gridHorizontal2\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"1dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.66\" />\n\n    <androidx.constraintlayout.widget.Group\n        android:id=\"@+id/groupGridLines\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:visibility=\"gone\"\n        app:constraint_referenced_ids=\"gridVertical1,gridVertical2,gridHorizontal1,gridHorizontal2\" />\n</androidx.constraintlayout.widget.ConstraintLayout>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/layout/item_picture.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=\"match_parent\">\n\n    <ImageView\n        android:id=\"@+id/imagePreview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:scaleType=\"fitCenter\" />\n\n    <ImageView\n        android:id=\"@+id/imagePlay\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:padding=\"@dimen/fab_margin\"\n        android:src=\"@drawable/ic_play\" />\n</FrameLayout>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/layout-land/fragment_camera.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:animateLayoutChanges=\"true\"\n    android:background=\"@android:color/black\"\n    tools:context=\".fragments.CameraFragment\">\n\n    <androidx.camera.view.PreviewView\n        android:id=\"@+id/viewFinder\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.0\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.0\" />\n\n    <View\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.4\"\n        android:background=\"@android:color/black\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"@id/btnTakePicture\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnTakePicture\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@android:color/transparent\"\n        android:padding=\"@dimen/double_margin\"\n        android:src=\"@drawable/ic_take_picture\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnGallery\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:scaleType=\"centerCrop\"\n        android:src=\"@drawable/ic_no_picture\"\n        app:layout_constraintBottom_toTopOf=\"@id/btnTakePicture\"\n        app:layout_constraintEnd_toEndOf=\"@id/btnTakePicture\"\n        app:layout_constraintStart_toStartOf=\"@id/btnTakePicture\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnSwitchCamera\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@drawable/bg_button_round\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_outline_camera_front\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"@id/btnTakePicture\"\n        app:layout_constraintStart_toStartOf=\"@id/btnTakePicture\"\n        app:layout_constraintTop_toBottomOf=\"@id/btnTakePicture\"\n        tools:ignore=\"ContentDescription\" />\n\n    <View\n        android:id=\"@+id/viewBg2\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.4\"\n        android:background=\"@android:color/black\"\n        android:elevation=\"1dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"@id/btnFlash\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnTimer\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_timer_off\"\n        app:layout_constraintBottom_toTopOf=\"@+id/btnGrid\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnGrid\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_grid_off\"\n        app:layout_constraintBottom_toTopOf=\"@+id/btnFlash\"\n        app:layout_constraintStart_toStartOf=\"@id/btnTimer\"\n        app:layout_constraintTop_toBottomOf=\"@+id/btnTimer\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnFlash\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_flash_off\"\n        app:layout_constraintBottom_toTopOf=\"@+id/btnHdr\"\n        app:layout_constraintStart_toStartOf=\"@id/btnGrid\"\n        app:layout_constraintTop_toBottomOf=\"@+id/btnGrid\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnHdr\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_hdr_off\"\n        app:layout_constraintBottom_toTopOf=\"@id/btnExposure\"\n        app:layout_constraintStart_toStartOf=\"@id/btnFlash\"\n        app:layout_constraintTop_toBottomOf=\"@+id/btnFlash\"\n        tools:ignore=\"ContentDescription\" />\n\n    <ImageButton\n        android:id=\"@+id/btnExposure\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_exposure\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"@id/btnFlash\"\n        app:layout_constraintTop_toBottomOf=\"@+id/btnHdr\"\n        tools:ignore=\"ContentDescription\" />\n\n    <View\n        android:id=\"@+id/gridVertical1\"\n        android:layout_width=\"1dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.33\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/gridVertical2\"\n        android:layout_width=\"1dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.66\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/gridHorizontal1\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"1dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.33\" />\n\n    <View\n        android:id=\"@+id/gridHorizontal2\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"1dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.66\" />\n\n    <androidx.constraintlayout.widget.Group\n        android:id=\"@+id/groupGridLines\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:visibility=\"invisible\"\n        app:constraint_referenced_ids=\"gridVertical1,gridVertical2,gridHorizontal1,gridHorizontal2\" />\n\n    <LinearLayout\n        android:id=\"@+id/llTimerOptions\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"0dp\"\n        android:background=\"@android:color/black\"\n        android:elevation=\"3dp\"\n        android:orientation=\"vertical\"\n        android:paddingStart=\"@dimen/fab_margin\"\n        android:paddingTop=\"@dimen/double_margin\"\n        android:paddingEnd=\"@dimen/fab_margin\"\n        android:paddingBottom=\"@dimen/fab_margin\"\n        android:visibility=\"gone\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\">\n\n        <ImageButton\n            android:id=\"@+id/btnTimerOff\"\n            android:layout_width=\"@dimen/button_size_small\"\n            android:layout_height=\"0dp\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_timer_off\"\n            tools:ignore=\"ContentDescription\" />\n\n        <ImageButton\n            android:id=\"@+id/btnTimer3\"\n            android:layout_width=\"@dimen/button_size_small\"\n            android:layout_height=\"0dp\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_timer_3\"\n            tools:ignore=\"ContentDescription\" />\n\n        <ImageButton\n            android:id=\"@+id/btnTimer10\"\n            android:layout_width=\"@dimen/button_size_small\"\n            android:layout_height=\"0dp\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_timer_10\"\n            tools:ignore=\"ContentDescription\" />\n    </LinearLayout>\n\n    <LinearLayout\n        android:id=\"@+id/llFlashOptions\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"0dp\"\n        android:background=\"@android:color/black\"\n        android:elevation=\"3dp\"\n        android:orientation=\"vertical\"\n        android:paddingStart=\"@dimen/fab_margin\"\n        android:paddingTop=\"@dimen/double_margin\"\n        android:paddingEnd=\"@dimen/fab_margin\"\n        android:paddingBottom=\"@dimen/fab_margin\"\n        android:visibility=\"gone\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\">\n\n        <ImageButton\n            android:id=\"@+id/btnFlashOff\"\n            android:layout_width=\"@dimen/button_size_small\"\n            android:layout_height=\"0dp\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_flash_off\"\n            tools:ignore=\"ContentDescription\" />\n\n        <ImageButton\n            android:id=\"@+id/btnFlashAuto\"\n            android:layout_width=\"@dimen/button_size_small\"\n            android:layout_height=\"0dp\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_flash_auto\"\n            tools:ignore=\"ContentDescription\" />\n\n        <ImageButton\n            android:id=\"@+id/btnFlashOn\"\n            android:layout_width=\"@dimen/button_size_small\"\n            android:layout_height=\"0dp\"\n            android:layout_weight=\"1\"\n            android:background=\"@android:color/transparent\"\n            android:src=\"@drawable/ic_flash_on\"\n            tools:ignore=\"ContentDescription\" />\n    </LinearLayout>\n\n    <FrameLayout\n        android:id=\"@+id/flExposure\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:elevation=\"3dp\"\n        android:orientation=\"horizontal\"\n        android:padding=\"@dimen/double_margin\"\n        android:visibility=\"gone\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\">\n\n        <com.google.android.material.slider.Slider\n            android:id=\"@+id/sliderExposure\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:layout_margin=\"@dimen/double_margin\"\n            android:background=\"@drawable/bg_options\"\n            android:paddingHorizontal=\"@dimen/fab_margin\"\n            android:paddingVertical=\"@dimen/double_margin\"\n            android:progressBackgroundTint=\"@android:color/white\"\n            app:haloColor=\"@color/colorAccent\"\n            app:thumbColor=\"@color/colorAccent\" />\n    </FrameLayout>\n\n    <TextView\n        android:id=\"@+id/tvCountDown\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:elevation=\"4dp\"\n        android:textColor=\"@android:color/white\"\n        android:textSize=\"@dimen/count_down_text_size\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        tools:text=\"0\" />\n</androidx.constraintlayout.widget.ConstraintLayout>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/layout-land/fragment_video.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@android:color/black\"\n    tools:context=\".fragments.CameraFragment\">\n\n    <androidx.camera.view.PreviewView\n        android:id=\"@+id/viewFinder\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.4\"\n        android:background=\"@android:color/black\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"@id/btnRecordVideo\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnRecordVideo\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@android:color/transparent\"\n        android:padding=\"@dimen/double_margin\"\n        android:src=\"@drawable/ic_take_video\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnGallery\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:scaleType=\"centerCrop\"\n        android:src=\"@drawable/ic_no_picture\"\n        app:layout_constraintBottom_toTopOf=\"@id/btnRecordVideo\"\n        app:layout_constraintEnd_toEndOf=\"@id/btnRecordVideo\"\n        app:layout_constraintStart_toStartOf=\"@id/btnRecordVideo\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnSwitchCamera\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@drawable/bg_button_round\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_outline_camera_front\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"@id/btnRecordVideo\"\n        app:layout_constraintStart_toStartOf=\"@id/btnRecordVideo\"\n        app:layout_constraintTop_toBottomOf=\"@id/btnRecordVideo\" />\n\n    <View\n        android:id=\"@+id/viewBg2\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.4\"\n        android:background=\"@android:color/black\"\n        android:elevation=\"1dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"@id/btnFlash\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <ImageButton\n        android:id=\"@+id/btnGrid\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_grid_off\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"@id/btnFlash\"\n        app:layout_constraintStart_toStartOf=\"@id/btnFlash\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.3\" />\n\n    <ImageButton\n        android:id=\"@+id/btnFlash\"\n        android:layout_width=\"@dimen/button_size_small\"\n        android:layout_height=\"@dimen/button_size_small\"\n        android:background=\"@android:color/transparent\"\n        android:elevation=\"1dp\"\n        android:padding=\"@dimen/half_margin\"\n        android:scaleType=\"centerInside\"\n        android:src=\"@drawable/ic_flash_off\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.7\" />\n\n    <View\n        android:id=\"@+id/gridVertical1\"\n        android:layout_width=\"1dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.33\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/gridVertical2\"\n        android:layout_width=\"1dp\"\n        android:layout_height=\"0dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.66\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <View\n        android:id=\"@+id/gridHorizontal1\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"1dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.33\" />\n\n    <View\n        android:id=\"@+id/gridHorizontal2\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"1dp\"\n        android:alpha=\"0.5\"\n        android:background=\"@android:color/white\"\n        android:elevation=\"2dp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_bias=\"0.66\" />\n\n    <androidx.constraintlayout.widget.Group\n        android:id=\"@+id/groupGridLines\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:visibility=\"gone\"\n        app:constraint_referenced_ids=\"gridVertical1,gridVertical2,gridHorizontal1,gridHorizontal2\" />\n</androidx.constraintlayout.widget.ConstraintLayout>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/menu/menu_main.xml",
    "content": "<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:context=\"com.robertlevonyan.demo.camerax.MainActivity\">\n    <item android:id=\"@+id/action_settings\"\n          android:title=\"@string/action_settings\"\n          android:orderInCategory=\"100\"\n          app:showAsAction=\"never\"/>\n</menu>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "camerax-demo/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "camerax-demo/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_host\"\n    app:startDestination=\"@id/cameraFragment\">\n\n    <fragment\n        android:id=\"@+id/cameraFragment\"\n        android:name=\"com.robertlevonyan.demo.camerax.fragments.CameraFragment\"\n        android:label=\"fragment_camera\"\n        tools:layout=\"@layout/fragment_camera\" >\n        <action\n            android:id=\"@+id/action_camera_to_preview\"\n            app:destination=\"@id/previewFragment\"\n            app:enterAnim=\"@anim/slide_in\"\n            app:exitAnim=\"@anim/slide_out\"\n            app:popEnterAnim=\"@anim/slide_in_pop\"\n            app:popExitAnim=\"@anim/slide_out_pop\"\n            app:popUpTo=\"@+id/cameraFragment\" />\n        <action\n            android:id=\"@+id/action_camera_to_video\"\n            app:destination=\"@id/videoFragment\"\n            app:enterAnim=\"@anim/nav_default_enter_anim\"\n            app:exitAnim=\"@anim/nav_default_exit_anim\"\n            app:launchSingleTop=\"true\"\n            app:popEnterAnim=\"@anim/nav_default_pop_enter_anim\"\n            app:popExitAnim=\"@anim/nav_default_pop_exit_anim\"\n            app:popUpTo=\"@+id/nav_host\"\n            app:popUpToInclusive=\"true\" />\n    </fragment>\n    <fragment\n        android:id=\"@+id/previewFragment\"\n        android:name=\"com.robertlevonyan.demo.camerax.fragments.PreviewFragment\"\n        android:label=\"fragment_preview\"\n        tools:layout=\"@layout/fragment_preview\" />\n    <fragment\n        android:id=\"@+id/videoFragment\"\n        android:name=\"com.robertlevonyan.demo.camerax.fragments.VideoFragment\"\n        android:label=\"fragment_video\"\n        tools:layout=\"@layout/fragment_video\" >\n        <action\n            android:id=\"@+id/action_video_to_preview\"\n            app:destination=\"@id/previewFragment\"\n            app:popUpTo=\"@+id/videoFragment\" />\n        <action\n            android:id=\"@+id/action_video_to_camera\"\n            app:destination=\"@id/cameraFragment\"\n            app:enterAnim=\"@anim/nav_default_enter_anim\"\n            app:exitAnim=\"@anim/nav_default_exit_anim\"\n            app:launchSingleTop=\"true\"\n            app:popEnterAnim=\"@anim/nav_default_pop_enter_anim\"\n            app:popExitAnim=\"@anim/nav_default_pop_exit_anim\"\n            app:popUpTo=\"@+id/nav_host\"\n            app:popUpToInclusive=\"true\" />\n    </fragment>\n</navigation>"
  },
  {
    "path": "camerax-demo/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#1a1a18</color>\n    <color name=\"colorPrimaryDark\">#80000000</color>\n    <color name=\"colorAccent\">#e7a942</color>\n    <color name=\"colorButtonGreyBg\">#444444</color>\n</resources>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <dimen name=\"half_margin\">8dp</dimen>\n    <dimen name=\"fab_margin\">16dp</dimen>\n    <dimen name=\"medium_margin\">24dp</dimen>\n    <dimen name=\"double_margin\">32dp</dimen>\n\n    <dimen name=\"button_size_shutter\">100dp</dimen>\n    <dimen name=\"button_size_big\">56dp</dimen>\n    <dimen name=\"button_size_small\">36dp</dimen>\n    <dimen name=\"count_down_text_size\">72sp</dimen>\n</resources>\n"
  },
  {
    "path": "camerax-demo/app/src/main/res/values/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"ic_launcher_background\">#F1F1F1</color>\n</resources>"
  },
  {
    "path": "camerax-demo/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">CameraX Demo</string>\n    <string name=\"action_settings\">Settings</string>\n    <string name=\"message_no_permissions\">The app cannot work without permissions</string>\n    <string name=\"label_ok\">OK</string>\n\n    <!-- TODO: Remove or change this placeholder text -->\n    <string name=\"hello_blank_fragment\">Hello blank fragment</string>\n    <string name=\"cd_take_picture\">Take picture</string>\n    <string name=\"cb_open_gallery\">Navigate to Gallery</string>\n    <string name=\"cb_switch\">Switch between front and back cameras</string>\n    <string name=\"cb_timer\">Select a timer</string>\n</resources>"
  },
  {
    "path": "camerax-demo/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <style name=\"AppTheme\" parent=\"Theme.MaterialComponents.Light.DarkActionBar\">\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:navigationBarColor\">@color/colorPrimaryDark</item>\n    </style>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.MaterialComponents.Dark.ActionBar\" />\n\n    <style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.MaterialComponents.Dark\" />\n\n</resources>"
  },
  {
    "path": "camerax-demo/app/src/main/res/xml/provider_paths.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<paths>\n  <external-path name=\"external_files\" path=\".\"/>\n</paths>"
  },
  {
    "path": "camerax-demo/build.gradle.kts",
    "content": "plugins {\n    alias(libs.plugins.android.application) apply false\n    alias(libs.plugins.kotlin.android) apply false\n    alias(libs.plugins.ksp) apply false\n    alias(libs.plugins.android.nav.safeargs) apply false\n}\n\ntasks.register(\"clean\", Delete::class) {\n    delete(layout.buildDirectory)\n}\n"
  },
  {
    "path": "camerax-demo/gradle/libs.versions.toml",
    "content": "[versions]\nandroidGradlePlugin = \"8.9.1\"\nandroidxComposeBom = \"2025.04.00\"\nactivityKtx = \"1.10.1\"\nappcompat = \"1.7.0\"\ncamera = \"1.4.2\"\ncoil = \"2.7.0\"\ncoilVideo = \"2.4.0\"\nconstraintlayoutVersion = \"2.2.1\"\nfragmentKtx = \"1.8.6\"\nksp = \"2.1.20-2.0.0\"\nkotlin = \"2.1.20\"\nkotlinxCoroutines = \"1.10.2\"\nmaterial = \"1.12.0\"\ncoreKtx = \"1.16.0\"\nmultidex = \"2.0.1\"\ncomposePaging = \"3.3.6\"\ncomposeCoil = \"2.7.0\"\nlifecycle = \"2.8.7\"\nnavigation = \"2.8.9\"\nviewpager2 = \"1.1.0\"\n\n[libraries]\nandroidx-appcompat = { module = \"androidx.appcompat:appcompat\", version.ref = \"appcompat\" }\nandroidx-camera-camera2 = { module = \"androidx.camera:camera-camera2\", version.ref = \"camera\" }\nandroidx-camera-core = { module = \"androidx.camera:camera-core\", version.ref = \"camera\" }\nandroidx-camera-extensions = { module = \"androidx.camera:camera-extensions\", version.ref = \"camera\" }\nandroidx-camera-lifecycle = { module = \"androidx.camera:camera-lifecycle\", version.ref = \"camera\" }\nandroidx-camera-view = { module = \"androidx.camera:camera-view\", version.ref = \"camera\" }\nandroidx-constraintlayout = { module = \"androidx.constraintlayout:constraintlayout\", version.ref = \"constraintlayoutVersion\" }\nandroidx-fragment-ktx = { module = \"androidx.fragment:fragment-ktx\", version.ref = \"fragmentKtx\" }\nandroidx-navigation-fragment-ktx = { module = \"androidx.navigation:navigation-fragment-ktx\", version.ref = \"navigation\" }\nandroidx-navigation-ui-ktx = { module = \"androidx.navigation:navigation-ui-ktx\", version.ref = \"navigation\" }\nandroidx-viewpager2 = { module = \"androidx.viewpager2:viewpager2\", version.ref = \"viewpager2\" }\ncoil = { module = \"io.coil-kt:coil\", version.ref = \"coil\" }\ncoil-video = { module = \"io.coil-kt:coil-video\", version.ref = \"coilVideo\" }\nkotlinx-coroutines-core = { group = \"org.jetbrains.kotlinx\", name = \"kotlinx-coroutines-core\", version.ref = \"kotlinxCoroutines\" }\nkotlinx-coroutines-android = { group = \"org.jetbrains.kotlinx\", name = \"kotlinx-coroutines-android\", version.ref = \"kotlinxCoroutines\" }\nmaterial = { group = \"com.google.android.material\", name = \"material\", version.ref = \"material\" }\nfirebase-analytics-ktx = { group = \"com.google.firebase\", name = \"firebase-analytics-ktx\" }\nfirebase-crashlytics-ktx = { group = \"com.google.firebase\", name = \"firebase-crashlytics-ktx\" }\nfirebase-firestore-ktx = { group = \"com.google.firebase\", name = \"firebase-firestore-ktx\" }\ncore-ktx = { group = \"androidx.core\", name = \"core-ktx\", version.ref = \"coreKtx\" }\nmultidex = { group = \"androidx.multidex\", name = \"multidex\", version.ref = \"multidex\" }\nlifecycle-runtime-ktx = { group = \"androidx.lifecycle\", name = \"lifecycle-runtime-ktx\", version.ref = \"lifecycle\" }\nandroidx-compose-bom = { group = \"androidx.compose\", name = \"compose-bom\", version.ref = \"androidxComposeBom\" }\nandroidx-compose-material3 = { group = \"androidx.compose.material3\", name = \"material3\" }\nandroidx-compose-material3-windowsize = { group = \"androidx.compose.material3\", name = \"material3-window-size-class\" }\nandroidx-compose-foundation = { group = \"androidx.compose.foundation\", name = \"foundation\" }\nandroidx-compose-ui = { group = \"androidx.compose.ui\", name = \"ui\" }\nandroidx-compose-ui-tooling = { group = \"androidx.compose.ui\", name = \"ui-tooling\" }\nactivity-compose = { group = \"androidx.activity\", name = \"activity-compose\", version.ref = \"activityKtx\" }\ncompose-paging = { group = \"androidx.paging\", name = \"paging-compose\", version.ref = \"composePaging\" }\ncompose-coil = { group = \"io.coil-kt\", name = \"coil-compose\", version.ref = \"composeCoil\" }\n\n[bundles]\nfirebase = [\"firebase-analytics-ktx\", \"firebase-crashlytics-ktx\", \"firebase-firestore-ktx\"]\ncompose = [\"androidx-compose-material3\", \"androidx-compose-material3-windowsize\", \"androidx-compose-foundation\", \"androidx-compose-ui\", \"androidx-compose-ui-tooling\"]\n\n[plugins]\nandroid-application = { id = \"com.android.application\", version.ref = \"androidGradlePlugin\" }\nksp = { id = \"com.google.devtools.ksp\", version.ref = \"ksp\" }\nkotlin-android = { id = \"org.jetbrains.kotlin.android\", version.ref = \"kotlin\" }\nkotlin-parcelize = { id = \"org.jetbrains.kotlin.plugin.parcelize\", version.ref = \"kotlin\" }\nkotlin-serialization = { id = \"org.jetbrains.kotlin.plugin.serialization\", version.ref = \"kotlin\" }\ncompose-compiler = { id = \"org.jetbrains.kotlin.plugin.compose\", version.ref = \"kotlin\" }\nandroid-nav-safeargs = { id = \"androidx.navigation.safeargs.kotlin\", version.ref = \"navigation\" }"
  },
  {
    "path": "camerax-demo/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Fri Oct 27 14:13:16 AMT 2023\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.11.1-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "camerax-demo/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=-Xmx1536m\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\nandroid.defaults.buildfeatures.buildconfig=true\nandroid.nonTransitiveRClass=false\nandroid.nonFinalResIds=false\n"
  },
  {
    "path": "camerax-demo/settings.gradle",
    "content": "pluginManagement {\n    repositories {\n        gradlePluginPortal()\n        google()\n        mavenCentral()\n    }\n}\ndependencyResolutionManagement {\n    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n    repositories {\n        google()\n        mavenCentral()\n    }\n}\n\nrootProject.name = \"camerax-demo\"\ninclude ':app'\n"
  }
]