[
  {
    "path": ".editorconfig",
    "content": "[*.{kt,kts}]\n\nmax_line_length=130\n\n"
  },
  {
    "path": ".github/workflows/publish_release.yml",
    "content": "name: Publish Release\n\non:\n  release:\n    types: [published]\n\njobs:\n  release:\n    name: Release Publish\n    runs-on: [ubuntu-latest]\n    steps:\n      - uses: actions/checkout@v1\n      - name: Set up JDK 11\n        uses: actions/setup-java@v2\n        with:\n          distribution: 'zulu'\n          java-version: '11'\n      - name: Build & run unit tests\n        shell: bash\n        run: ./gradlew --continue build testRelease\n      - name: Publish release\n        run: ./gradlew publish --no-daemon --no-parallel --stacktrace -PVERSION_NAME=${{github.event.release.name}}\n        env:\n          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_REPOSITORY_USERNAME }}\n          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_REPOSITORY_PASSWORD }}\n          ORG_GRADLE_PROJECT_SIGNING_PRIVATE_KEY: ${{ secrets.GPG_SIGNING_PRIVATE_KEY }}\n          ORG_GRADLE_PROJECT_SIGNING_PASSWORD: ${{ secrets.GPG_SIGNING_PASSWORD }}\n"
  },
  {
    "path": ".github/workflows/publish_snapshot.yml",
    "content": "name: Publish Snapshot\non:\n  push:\n    branches:\n      master\n\njobs:\n  master:\n    name: Snapshot Publish\n    runs-on: [ ubuntu-latest ]\n    env:\n      SLACK_CHANNEL: android\n    steps:\n      - uses: actions/checkout@v1\n      - name: Set up JDK 11\n        uses: actions/setup-java@v2\n        with:\n          distribution: 'zulu'\n          java-version: '11'\n      - name: Run unit tests\n        shell: bash\n        run: ./gradlew --continue build testRelease\n      - name: Build & publish snapshot\n        run: ./gradlew publish --no-daemon --no-parallel --stacktrace\n        env:\n          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_REPOSITORY_USERNAME }}\n          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_REPOSITORY_PASSWORD }}\n          ORG_GRADLE_PROJECT_SIGNING_PRIVATE_KEY: ${{ secrets.GPG_SIGNING_PRIVATE_KEY }}\n          ORG_GRADLE_PROJECT_SIGNING_PASSWORD: ${{ secrets.GPG_SIGNING_PASSWORD }}\n      - name: Slack Notification\n        if: failure()\n        uses: homoluctus/slatify@master\n        with:\n          type: \"failure\"\n          job_name: '*Snapshot Publish*'\n          username: GitHub\n          channel: ${{env.SLACK_CHANNEL}}\n          url: ${{ secrets.SLACK_WEB_HOOK }}\n          commit: true\n          token: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/pull_request.yml",
    "content": "name: Check PR\non: [pull_request]\n\njobs:\n  pr:\n    name: PR check\n    runs-on: [ubuntu-latest]\n    env:\n      DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}\n    steps:\n      - uses: actions/checkout@v1\n      - uses: actions/setup-ruby@v1\n        with:\n          ruby-version: '2.6'\n      - name: Set up JDK 11\n        uses: actions/setup-java@v2\n        with:\n          distribution: 'zulu'\n          java-version: '11'\n      - name: Run LintCheck\n        shell: bash\n        run: ./gradlew detekt ktlintCheck lint assembleRelease\n      - name: Run unit tests\n        shell: bash\n        run: ./gradlew --continue testRelease\n      - name: Danger action\n        uses: MeilCli/danger-action@v2\n        continue-on-error: true\n        with:\n          plugins_file: 'Gemfile'\n          danger_file: 'Dangerfile'\n          danger_id: 'danger-pr'\n"
  },
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/*\n/buildSrc/build/*\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n"
  },
  {
    "path": "Dangerfile",
    "content": "is_pr_big = git.insertions > 500\nhas_correct_prefix = github.branch_for_head.match(/^(feature|hotfix|fix|release|housekeep)\\//)\n\nwarn(\"Branch name should have `release/`, `hotfix/`, `fix/`, `housekeep/` or `feature/` prefix.\") if !has_correct_prefix\nwarn(\"This pull request is too big.\") if is_pr_big\n\ncommit_lint.check warn: :all, disable: [:subject_length]\n\n# Utils\ndef report_checkstyle_for_directory(directory_name)\n  if Dir.exists?(directory_name)\n    Dir.glob(\"#{directory_name}/*.xml\").each {|f|\n      report_checkstyle(f)\n    }\n  end\nend\n\ndef report_checkstyle(file_name)\n  if File.file?(file_name)\n    checkstyle_format.report file_name\n  end\nend\n\n# Setup checkstyle\ncheckstyle_format.base_path = Dir.pwd\n\n# Detekt checkstyle\nreport_checkstyle 'build/reports/detekt/detekt.xml'\n\n# Ktlint checkstyle\nreport_checkstyle_for_directory 'library/build/reports/ktlint'\nreport_checkstyle_for_directory 'sample/build/reports/ktlint'\n"
  },
  {
    "path": "Gemfile",
    "content": "source 'https://rubygems.org'\n\ngem 'danger-commit_lint'\ngem 'danger-checkstyle_format'\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Futured apps s.r.o.\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 align=\"right\" src=\"images/Hauler.svg\">\n\n# Hauler\n\n[![Maven Central](https://img.shields.io/maven-central/v/app.futured.hauler/hauler)](https://search.maven.org/artifact/app.futured.hauler/hauler/)\n![minSdk:21](https://img.shields.io/badge/minSDK-21-brightgreen.svg)\n[![Android Arsenal]( https://img.shields.io/badge/Android%20Arsenal-Hauler-brightgreen.svg?style=flat )]( https://android-arsenal.com/details/1/7359 )\n![Publish Snapshot](https://github.com/futuredapp/hauler/actions/workflows/publish_snapshot.yml/badge.svg)\n![License](https://img.shields.io/github/license/futuredapp/hauler?color=black)\n\nHauler is an Android library containing custom layout which enables to easily create swipe to dismiss `Activity`.\nImplementation is based on code from project [Plaid](https://github.com/nickbutcher/plaid).\n\n![Alt text](https://github.com/thefuntasty/hauler/blob/master/images/example.gif)\n\n# Installation\n\n```groovy\ndependencies {\n    implementation(\"app.futured.hauler:hauler:latestVersion\")\n\n    // optional dependency with set of Data Binding adapters\n    implementation(\"app.futured.hauler:databinding:latestVersion\")\n}\n```\n\n### Snapshot installation\n\nAdd new maven repo to your top level gradle file.\n\n```groovy\nmaven { url \"https://oss.sonatype.org/content/repositories/snapshots\" }\n```\n\nSnapshots are grouped based on major version, so for version 5.x.x use:\n\n```groovy\nimplementation \"app.futured.hauler:hauler:5.X.X-SNAPSHOT\"\n```\n\n# Features\n\nHauler library comes with highly customizable `HaulerView` which provides swipe to dismiss functionality. \nIt also ships with `databinding` module which contains Binding Adapters for smoother experience with Android Data Binding implementation.\n\n# Usage\n \n Activity which is meant to be dismissed must contain `HaulerView` as a root view and `NestedScrollView` (or other `View` what supports nested scroll) \n as its child. Make sure your `NestedScrollview`'s attribute `android:fillViewport` is set to `true` otherwise it might not behave as\n expected:\n\n```xml\n<app.futured.hauler.HaulerView\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:id=\"@+id/haulerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n\n    <androidx.core.widget.NestedScrollView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:fillViewport=\"true\">\n            \n            <!-- your layout-->\n            \n    </androidx.core.widget.NestedScrollView>\n</app.futured.hauler.HaulerView>\n```\n\nSecondly, define translucent floating Theme and assign it to the Activity you want to give dismiss ability:\n\n ```xml\n<style name=\"AppTheme.Draggable\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <item name=\"android:colorBackgroundCacheHint\">@null</item>\n        <item name=\"android:windowContentOverlay\">@null</item>\n        <item name=\"android:windowIsFloating\">false</item>\n        <item name=\"android:windowIsTranslucent\">true</item>\n        <item name=\"android:windowNoTitle\">true</item>\n        <item name=\"android:windowBackground\">@color/dark_gray</item>\n</style>\n```\n\n```xml\n<activity\n        android:name=\".draggable.SimpleUsageActivity\"\n        android:theme=\"@style/AppTheme.Draggable\"/>\n```\nSet `onDragDismissListener` to react properly to user dismiss request. Example implementation might look like this:\n```kotlin\n    override fun onCreate(savedInstanceState: Bundle?) {\n        // ...\n\n        haulerView.setOnDragDismissedListener {\n            finish() // finish activity when dismissed\n        }\n    }\n```\n\n## Customization\n\nThere are few styleable attributes you might want to use to customize your `HaulerView`:\n\n ```xml\n<app.futured.hauler.HaulerView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:dragDismissDistance=\"112dp\"\n        app:dragDismissFraction=\"0.9\"\n        app:dragElasticity=\"0.7\"\n        app:dragDismissScale=\"0.95\"/>\n```\n\n| Attribute name | Type | Default value | Description|\n| -------------- | ---- | ------------- | ---------- |\n| `app:dragDismissDistance` | dimen | 100dp | Distance which should be `View` swiped to consider Activity as dismissed |\n| `app:dragDismissFraction` | float | unspecified | `<0;1>` - Fraction of `View`'s height we should reach swiping to consider Activity as dismissed |\n| `app:dragElasticity` | float | 0.8 | `<0;1>` - Toughness of swipe. Higher value indicates more rigid feeling  |\n| `app:dragDismissScale` | float | 0.95 | `<0;1>` - Scale factor of `View` while performing swipe action |\n| `app:dragUpEnabled` | boolean | false | Flag indicating if drag up dismiss gesture is enabled |\n| `app:fadeSystemBars` | boolean | true | Flag indicating if system bars (status & navigation) fades while dismiss is in progress |\n\nAttributes `dragDismissDistance` and `dragDismissFraction` are exclusive. Do not use them together.\n\n# License\n\nHauler is available under the MIT license. See the [LICENSE file](LICENCE) for more information.\n"
  },
  {
    "path": "build.gradle.kts",
    "content": "import org.jlleitschuh.gradle.ktlint.reporter.ReporterType\n\nbuildscript {\n    repositories {\n        google()\n        jcenter()\n    }\n    dependencies {\n        classpath(Deps.gradlePlugin)\n        classpath(kotlin(Deps.Kotlin.gradlePlugin, Versions.kotlin))\n        classpath(Deps.Plugins.mavenPublish)\n        classpath(Deps.Plugins.dokka)\n    }\n}\n\nplugins {\n    idea\n    id(Deps.Plugins.detekt) version Versions.detekt\n    id(Deps.Plugins.ktlint) version Versions.ktlint\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n        mavenCentral()\n    }\n}\n\ntasks {\n    register<app.futured.hauler.DependencyUpdates>(\"dependencyUpdates\")\n}\n\nsubprojects {\n    apply(plugin = Deps.Plugins.ktlint)\n    ktlint {\n        version.set(Versions.ktlintExtension)\n        ignoreFailures.set(true)\n        android.set(true)\n        outputToConsole.set(true)\n        reporters {\n            reporter(ReporterType.PLAIN)\n            reporter(ReporterType.CHECKSTYLE)\n        }\n    }\n\n    plugins.whenPluginAdded {\n        if (this is SigningPlugin) {\n            extensions.findByType<SigningExtension>()?.apply {\n                val hasKey = project.hasProperty(\"SIGNING_PRIVATE_KEY\")\n                val hasPassword = project.hasProperty(\"SIGNING_PASSWORD\")\n\n                if (hasKey && hasPassword) {\n                    useInMemoryPgpKeys(\n                        project.properties[\"SIGNING_PRIVATE_KEY\"].toString(),\n                        project.properties[\"SIGNING_PASSWORD\"].toString()\n                    )\n                }\n            }\n        }\n    }\n}\n\ndetekt {\n    autoCorrect = false\n    version = Versions.detekt\n    input = files(\"sample/src/main/kotlin\", \"library/src/main/kotlin\")\n    config = files(\"detekt.yml\")\n}\n"
  },
  {
    "path": "buildSrc/build.gradle.kts",
    "content": "plugins {\n    `kotlin-dsl`\n}\n\nrepositories {\n    jcenter()\n}\n\ndependencies {\n    implementation(\"com.github.ben-manes:gradle-versions-plugin:0.36.0\")\n}\n\ndependencies {\n    implementation(\"com.github.ben-manes:gradle-versions-plugin:0.33.0\")\n}\n"
  },
  {
    "path": "buildSrc/src/main/kotlin/Deps.kt",
    "content": "object Deps {\n    const val gradlePlugin = \"com.android.tools.build:gradle:${Versions.gradle}\"\n\n    object Plugins {\n        const val detekt = \"io.gitlab.arturbosch.detekt\"\n        const val ktlint = \"org.jlleitschuh.gradle.ktlint\"\n        const val mavenPublish = \"com.vanniktech:gradle-maven-publish-plugin:${Versions.mavenPublish}\"\n        const val dokka = \"org.jetbrains.dokka:dokka-gradle-plugin:${Versions.dokka}\"\n    }\n\n    object Kotlin {\n        const val gradlePlugin = \"gradle-plugin\"\n        const val stdlib = \"stdlib-jdk7\"\n    }\n\n    object AndroidX {\n        const val appcompat = \"androidx.appcompat:appcompat:${Versions.androidx}\"\n        const val palette = \"androidx.palette:palette:${Versions.palette}\"\n        const val ktx = \"androidx.core:core-ktx:${Versions.androidxKtx}\"\n    }\n}\n"
  },
  {
    "path": "buildSrc/src/main/kotlin/ProjectSettings.kt",
    "content": "object ProjectSettings {\n    const val applicationId = \"app.futured.hauler\"\n    const val targetSdk = 32\n    const val minSdk = 21\n}\n"
  },
  {
    "path": "buildSrc/src/main/kotlin/Versions.kt",
    "content": "object Versions {\n    // gradle\n    const val gradle = \"7.2.1\"\n\n    // plugins\n    const val detekt = \"1.20.0\"\n    const val ktlint = \"10.3.0\"\n    const val ktlintExtension = \"0.41.0\"\n    const val mavenPublish = \"0.21.0\"\n    const val dokka = \"1.7.0\"\n\n    // kotlin\n    const val kotlin = \"1.7.0\"\n\n    const val androidx = \"1.4.2\"\n    const val androidxKtx = \"1.8.0\"\n    const val palette = \"1.0.0\"\n}\n"
  },
  {
    "path": "buildSrc/src/main/kotlin/app/futured/hauler/DependencyUpdates.kt",
    "content": "package app.futured.hauler\n\nimport com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask\n\nabstract class DependencyUpdates : DependencyUpdatesTask() {\n\n    init {\n        group = \"futured\"\n\n        this.resolutionStrategy {\n            componentSelection {\n                all {\n                    val rejected = listOf(\"alpha\", \"beta\", \"rc\", \"cr\", \"m\", \"preview\", \"testing\")\n                        .map { qualifier -> Regex(\"(?i).*[.-]$qualifier[.\\\\d-]*\") }\n                        .any { it.matches(candidate.version) }\n                    if (rejected) {\n                        reject(\"Release candidate\")\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "core/build.gradle.kts",
    "content": "import org.jetbrains.kotlin.config.KotlinCompilerVersion\n\nplugins {\n    id(\"com.android.library\")\n    id(\"kotlin-android\")\n    id(\"com.vanniktech.maven.publish\")\n}\n\nandroid {\n\n    compileSdkVersion(ProjectSettings.targetSdk)\n\n    defaultConfig {\n        minSdkVersion(ProjectSettings.minSdk)\n        targetSdkVersion(ProjectSettings.targetSdk)\n    }\n\n    sourceSets {\n        getByName(\"main\").java.srcDir(\"src/main/kotlin\")\n    }\n\n    compileOptions {\n        sourceCompatibility = JavaVersion.VERSION_1_8\n        targetCompatibility = JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = JavaVersion.VERSION_1_8.toString()\n    }\n}\n\ndependencies {\n    implementation(kotlin(Deps.Kotlin.stdlib, KotlinCompilerVersion.VERSION))\n    implementation(Deps.AndroidX.appcompat)\n    implementation(Deps.AndroidX.palette)\n    implementation(Deps.AndroidX.ktx)\n}\n"
  },
  {
    "path": "core/gradle.properties",
    "content": "POM_NAME=Library containing custom layout which enables to easily create swipe to dismiss Activity\nPOM_ARTIFACT_ID=hauler\nPOM_PACKAGING=aar\n"
  },
  {
    "path": "core/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"app.futured.hauler\"/>\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/ColorUtils.kt",
    "content": "package app.futured.hauler\n\nimport androidx.annotation.CheckResult\nimport androidx.annotation.ColorInt\nimport androidx.annotation.IntRange\n\ninternal object ColorUtils {\n\n    @CheckResult\n    @ColorInt\n    fun modifyAlpha(@ColorInt color: Int, @IntRange(from = 0, to = 255) alpha: Int): Int =\n        color and 0x00ffffff or (alpha shl 24)\n}\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/DragDirection.kt",
    "content": "package app.futured.hauler\n\nenum class DragDirection {\n    UP, DOWN\n}\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/HaulerView.kt",
    "content": "package app.futured.hauler\n\nimport android.app.Activity\nimport android.content.Context\nimport android.util.AttributeSet\nimport android.view.MotionEvent\nimport android.view.View\nimport android.widget.FrameLayout\nimport androidx.core.content.withStyledAttributes\nimport androidx.core.view.animation.PathInterpolatorCompat\n\nclass HaulerView @JvmOverloads constructor(\n    context: Context,\n    attrs: AttributeSet? = null,\n    defStyleAttr: Int = 0\n) : FrameLayout(context, attrs, defStyleAttr) {\n\n    // configurable attributes\n    private var dragDismissDistance =\n        context.resources.getDimensionPixelSize(R.dimen.default_drag_dismiss_distance).toFloat()\n    private var dragDismissFraction = -1f\n    private var dragDismissScale = 0.95f\n    private var shouldScale = true\n    private var dragElasticity = 0.8f\n\n    // state\n    private var totalDrag: Float = 0.toFloat()\n    private var draggingDown = false\n    private var draggingUp = false\n    private var mLastActionEvent: Int = 0\n\n    private var onDragDismissedListener: OnDragDismissedListener? = null\n    private var onDragActivityListener: OnDragActivityListener? = null\n    private var systemBarsFader: SystemBarsFader? = null\n\n    private var isDragEnabled = true\n    private var dragUpEnabled = false\n    private var fadeSystemBars = true\n\n    init {\n        getContext().withStyledAttributes(set = attrs, attrs = R.styleable.HaulerView) {\n            val distanceAvailable = hasValue(R.styleable.HaulerView_dragDismissDistance)\n            val dismissFractionAvailable = hasValue(R.styleable.HaulerView_dragDismissFraction)\n\n            if (distanceAvailable && dismissFractionAvailable) {\n                throw IllegalStateException(\"Do not specify both dragDismissDistance and dragDismissFraction. Choose one.\")\n            } else if (distanceAvailable) {\n                dragDismissDistance = getDimensionPixelSize(R.styleable.HaulerView_dragDismissDistance, 0).toFloat()\n            } else if (dismissFractionAvailable) {\n                dragDismissFraction = getFloat(R.styleable.HaulerView_dragDismissFraction, dragDismissFraction)\n            }\n\n            dragDismissScale = getFloat(R.styleable.HaulerView_dragDismissScale, dragDismissScale)\n            dragUpEnabled = getBoolean(R.styleable.HaulerView_dragUpEnabled, dragUpEnabled)\n            dragElasticity = getFloat(R.styleable.HaulerView_dragElasticity, dragElasticity)\n            fadeSystemBars = getBoolean(R.styleable.HaulerView_fadeSystemBars, fadeSystemBars)\n        }\n\n        setFadeSystemBars(fadeSystemBars)\n        shouldScale = dragDismissScale != 1f\n    }\n\n    override fun onStartNestedScroll(child: View, target: View, nestedScrollAxes: Int): Boolean =\n        nestedScrollAxes and View.SCROLL_AXIS_VERTICAL != 0\n\n    override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray) {\n        if (isDragEnabled.not()) {\n            return super.onNestedPreScroll(target, dx, dy, consumed)\n        }\n        // if we're in a drag gesture and the user reverses up the we should take those events\n        val draggingDownInProgress = draggingDown && dy > 0\n        val draggingUpInProgress = draggingUp && dy < 0\n        if (draggingDownInProgress || draggingUpInProgress) {\n            dragScale(dy)\n            consumed[1] = dy\n        }\n    }\n\n    override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) {\n        if (isDragEnabled.not() || (dragUpEnabled.not() && dyUnconsumed > 0)) {\n            return super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed)\n        }\n        dragScale(dyUnconsumed)\n    }\n\n    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {\n        mLastActionEvent = ev.action\n        return super.onInterceptTouchEvent(ev)\n    }\n\n    override fun onStopNestedScroll(child: View) {\n        if (isDragEnabled.not()) {\n            return super.onStopNestedScroll(child)\n        }\n\n        val totalDragNormalized = if (dragUpEnabled) Math.abs(totalDrag) else -totalDrag\n        val dragDirection = if (totalDrag > 0) DragDirection.UP else DragDirection.DOWN\n\n        if (totalDragNormalized >= dragDismissDistance) {\n            dispatchDismissCallback(dragDirection)\n        } else { // settle back to natural position\n            if (mLastActionEvent == MotionEvent.ACTION_DOWN) {\n                // this is a 'defensive cleanup for new gestures',\n                // don't animate here\n                // see also https://github.com/nickbutcher/plaid/issues/185\n                translationY = 0f\n                scaleX = 1f\n                scaleY = 1f\n            } else {\n                animate()\n                    .translationY(0f)\n                    .scaleX(1f)\n                    .scaleY(1f)\n                    .setDuration(200L)\n                    .setInterpolator(PathInterpolatorCompat.create(0.4f, 0f, 0.2f, 1f))\n                    .setListener(null)\n                    .start()\n            }\n            totalDrag = 0f\n            draggingUp = false\n            draggingDown = draggingUp\n            dispatchDragCallback(0f, 0f)\n        }\n    }\n\n    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {\n        super.onSizeChanged(w, h, oldw, oldh)\n        if (dragDismissFraction > 0f) {\n            dragDismissDistance = h * dragDismissFraction\n        }\n    }\n\n    /**\n     * Set if drag/swipe up dismiss is enabled\n     */\n    fun setDragUpEnabled(dragUpEnabled: Boolean) {\n        this.dragUpEnabled = dragUpEnabled\n    }\n\n    /**\n     * Set lambda reference which is called when dismiss gesture has\n     * been performed\n     */\n    fun setOnDragDismissedListener(onDragDismissedListener: OnDragDismissedListener) {\n        this.onDragDismissedListener = onDragDismissedListener\n    }\n\n    /**\n     * Set lambda reference to listener which is called when drag is in\n     * progress\n     */\n    fun setOnDragActivityListener(onDragActivityListener: OnDragActivityListener) {\n        this.onDragActivityListener = onDragActivityListener\n    }\n\n    /**\n     * Set if drag gesture is enabled\n     */\n    fun setDragEnabled(isDragEnabled: Boolean) {\n        this.isDragEnabled = isDragEnabled\n    }\n\n    /**\n     * Set if system bars should fade when dismiss is in progress\n     */\n    fun setFadeSystemBars(fadeSystemBars: Boolean) {\n        this.fadeSystemBars = fadeSystemBars\n\n        if (fadeSystemBars) {\n            (context as? Activity)?.also {\n                systemBarsFader = SystemBarsFader(it)\n            }\n        } else {\n            systemBarsFader = null\n        }\n    }\n\n    private fun dragScale(scroll: Int) {\n        if (scroll == 0) return\n\n        totalDrag += scroll.toFloat()\n\n        // track the direction & set the pivot point for scaling\n        // don't double track i.e. if start dragging down and then reverse, keep tracking as\n        // dragging down until they reach the 'natural' position\n        if (scroll < 0 && !draggingUp && !draggingDown) {\n            draggingDown = true\n            if (shouldScale) pivotY = height.toFloat()\n        } else if (scroll > 0 && !draggingDown && !draggingUp) {\n            draggingUp = true\n            if (shouldScale) {\n                pivotY = 0f\n            }\n        }\n        // how far have we dragged relative to the distance to perform a dismiss\n        // (0–1 where 1 = dismiss distance). Decreasing logarithmically as we approach the limit\n        var dragFraction = Math.log10((1 + Math.abs(totalDrag) / dragDismissDistance).toDouble()).toFloat()\n\n        // calculate the desired translation given the drag fraction\n        var dragTo = dragFraction * dragDismissDistance * dragElasticity\n\n        if (draggingUp) {\n            // as we use the absolute magnitude when calculating the drag fraction, need to\n            // re-apply the drag direction\n            dragTo *= -1f\n        }\n        translationY = dragTo\n\n        if (shouldScale) {\n            val scale = 1 - (1 - dragDismissScale) * dragFraction\n            scaleX = scale\n            scaleY = scale\n        }\n\n        // if we've reversed direction and gone past the settle point then clear the flags to\n        // allow the list to get the scroll events & reset any transforms\n        val downSettlePointReached = draggingDown && totalDrag >= 0\n        val upSettlePointReached = draggingUp && totalDrag <= 0\n        if (downSettlePointReached || upSettlePointReached) {\n            dragFraction = 0f\n            dragTo = dragFraction\n            totalDrag = dragTo\n            draggingUp = false\n            draggingDown = draggingUp\n            translationY = 0f\n            scaleX = 1f\n            scaleY = 1f\n        }\n        dispatchDragCallback(dragTo, Math.min(1f, Math.abs(totalDrag) / dragDismissDistance))\n    }\n\n    private fun dispatchDragCallback(elasticOffsetPixels: Float, rawOffset: Float) {\n        systemBarsFader?.onDrag(elasticOffsetPixels, rawOffset)\n        onDragActivityListener?.onDrag(elasticOffsetPixels, rawOffset)\n    }\n\n    private fun dispatchDismissCallback(dragDirection: DragDirection) {\n        systemBarsFader?.onDismiss()\n        onDragDismissedListener?.onDismissed(dragDirection)\n    }\n}\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/HaulerViewExtensions.kt",
    "content": "package app.futured.hauler\n\nfun HaulerView.setOnDragDismissedListener(onDragDismissedListener: (DragDirection) -> Unit) {\n    this.setOnDragDismissedListener(object : OnDragDismissedListener {\n        override fun onDismissed(dragDirection: DragDirection) {\n            onDragDismissedListener.invoke(dragDirection)\n        }\n    })\n}\n\nfun HaulerView.setOnDragActivityListener(onDragActivityListener: (elasticOffsetPixels: Float, rawOffset: Float) -> Unit) {\n    this.setOnDragActivityListener(object : OnDragActivityListener {\n        override fun onDrag(elasticOffsetPixels: Float, rawOffset: Float) {\n            onDragActivityListener.invoke(elasticOffsetPixels, rawOffset)\n        }\n    })\n}\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/LockableNestedScrollView.kt",
    "content": "package app.futured.hauler\n\nimport android.content.Context\nimport android.util.AttributeSet\nimport android.view.MotionEvent\nimport androidx.core.widget.NestedScrollView\n\nclass LockableNestedScrollView @JvmOverloads constructor(\n    context: Context,\n    attrs: AttributeSet? = null,\n    defStyleAttr: Int = 0\n) : NestedScrollView(context, attrs, defStyleAttr) {\n\n    private var isScrollable = true\n\n    fun setScrollEnabled(isScrollEnabled: Boolean) {\n        isScrollable = isScrollEnabled\n    }\n\n    @Suppress(\"ClickableViewAccessibility\")\n    override fun onTouchEvent(ev: MotionEvent): Boolean = when (ev.action) {\n        MotionEvent.ACTION_DOWN ->\n            isScrollable && super.onTouchEvent(ev)\n        else ->\n            super.onTouchEvent(ev)\n    }\n\n    override fun onInterceptTouchEvent(ev: MotionEvent) = isScrollable && super.onInterceptTouchEvent(ev)\n}\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/OnDragActivityListener.kt",
    "content": "package app.futured.hauler\n\ninterface OnDragActivityListener {\n    fun onDrag(elasticOffsetPixels: Float, rawOffset: Float)\n}\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/OnDragDismissedListener.kt",
    "content": "package app.futured.hauler\n\ninterface OnDragDismissedListener {\n    fun onDismissed(dragDirection: DragDirection)\n}\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/SystemBarsFader.kt",
    "content": "package app.futured.hauler\n\nimport android.app.Activity\nimport android.graphics.Color\n\ninternal class SystemBarsFader(private val activity: Activity) {\n\n    private val statusBarAlpha: Int by lazy { Color.alpha(getStatusBarColor()) }\n\n    fun onDrag(elasticOffsetPixels: Float, rawOffset: Float) {\n        when {\n            elasticOffsetPixels != 0f -> // dragging downward or upward, fade the status bar in proportion\n                activity.window.statusBarColor = ColorUtils.modifyAlpha(getStatusBarColor(), getNewAlpha(rawOffset))\n            elasticOffsetPixels == 0f ->\n                activity.window.statusBarColor = ColorUtils.modifyAlpha(getStatusBarColor(), statusBarAlpha)\n        }\n    }\n\n    fun onDismiss() {\n        // set transparent window bg and transparent navigation bar\n        activity.window.decorView.setBackgroundColor(0)\n        activity.window.navigationBarColor = ColorUtils.modifyAlpha(activity.window.navigationBarColor, 0)\n    }\n\n    private fun getStatusBarColor() = activity.window.statusBarColor\n\n    private fun getNewAlpha(rawOffset: Float) = ((1f - rawOffset) * statusBarAlpha).toInt()\n}\n"
  },
  {
    "path": "core/src/main/res/values/attrs_hauler_view.xml",
    "content": "<resources>\n\n    <declare-styleable name=\"HaulerView\">\n        <attr name=\"dragDismissDistance\" format=\"dimension\"/>\n        <attr name=\"dragDismissFraction\" format=\"float\"/>\n        <attr name=\"dragDismissScale\" format=\"float\"/>\n        <attr name=\"dragElasticity\" format=\"float\"/>\n        <attr name=\"dragUpEnabled\" format=\"boolean\"/>\n        <attr name=\"fadeSystemBars\" format=\"boolean\" />\n    </declare-styleable>\n\n</resources>\n"
  },
  {
    "path": "core/src/main/res/values/dimens.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <dimen name=\"default_drag_dismiss_distance\">100dp</dimen>\n</resources>\n"
  },
  {
    "path": "databinding/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "databinding/build.gradle.kts",
    "content": "import org.jetbrains.kotlin.config.KotlinCompilerVersion\n\nplugins {\n    id(\"com.android.library\")\n    id(\"kotlin-android\")\n    id(\"kotlin-kapt\")\n    id(\"com.vanniktech.maven.publish\")\n}\n\nandroid {\n    compileSdkVersion(ProjectSettings.targetSdk)\n\n    defaultConfig {\n        minSdkVersion(ProjectSettings.minSdk)\n        targetSdkVersion(ProjectSettings.targetSdk)\n    }\n\n    sourceSets {\n        getByName(\"main\").java.srcDir(\"src/main/kotlin\")\n    }\n\n    buildFeatures {\n        dataBinding = true\n    }\n\n    compileOptions {\n        sourceCompatibility = JavaVersion.VERSION_1_8\n        targetCompatibility = JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = JavaVersion.VERSION_1_8.toString()\n    }\n}\n\ndependencies {\n    implementation(project(\":core\"))\n\n    implementation(kotlin(Deps.Kotlin.stdlib, KotlinCompilerVersion.VERSION))\n    implementation(Deps.AndroidX.appcompat)\n}\n"
  },
  {
    "path": "databinding/gradle.properties",
    "content": "POM_NAME=Databinding extensions for core library\nPOM_ARTIFACT_ID=databinding\nPOM_PACKAGING=aar\n"
  },
  {
    "path": "databinding/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"app.futured.hauler.databinding\"/>\n"
  },
  {
    "path": "databinding/src/main/kotlin/app/futured/hauler/databinding/IsDragEnabledAdapter.kt",
    "content": "package app.futured.hauler.databinding\n\nimport androidx.databinding.BindingAdapter\nimport app.futured.hauler.HaulerView\n\n@BindingAdapter(\"app:isDragEnabled\")\nfun HaulerView.isDragEnabled(isDragEnabled: Boolean) {\n    this.setDragEnabled(isDragEnabled)\n}\n"
  },
  {
    "path": "databinding/src/main/kotlin/app/futured/hauler/databinding/IsDragUpEnabledAdapter.kt",
    "content": "package app.futured.hauler.databinding\n\nimport androidx.databinding.BindingAdapter\nimport app.futured.hauler.HaulerView\n\n@BindingAdapter(\"app:isDragUpEnabled\")\nfun HaulerView.isDragUpEnabled(isDragUpEnabled: Boolean) {\n    this.setDragUpEnabled(isDragUpEnabled)\n}\n"
  },
  {
    "path": "databinding/src/main/kotlin/app/futured/hauler/databinding/IsScrollableAdapter.kt",
    "content": "package app.futured.hauler.databinding\n\nimport androidx.databinding.BindingAdapter\nimport app.futured.hauler.LockableNestedScrollView\n\n@BindingAdapter(\"app:isScrollable\")\nfun LockableNestedScrollView.isScrollable(isScrollable: Boolean) {\n    setScrollEnabled(isScrollable)\n}\n"
  },
  {
    "path": "databinding/src/main/kotlin/app/futured/hauler/databinding/OnDragDismissedListenerAdapter.kt",
    "content": "package app.futured.hauler.databinding\n\nimport androidx.databinding.BindingAdapter\nimport app.futured.hauler.HaulerView\nimport app.futured.hauler.OnDragDismissedListener\nimport app.futured.hauler.setOnDragDismissedListener\n\n@BindingAdapter(\"app:onDragDismissedListener\")\nfun HaulerView.setOnDragDismissedListener(listener: OnDragDismissedListener) {\n    this.setOnDragDismissedListener { listener.onDismissed(it) }\n}\n"
  },
  {
    "path": "detekt.yml",
    "content": "build:\n  maxIssues: 100\n\ncomplexity:\n  active: true\n  ComplexCondition:\n    active: true\n  ComplexMethod:\n    active: true\n    threshold: 20\n    ignoreSimpleWhenEntries: true\n  LargeClass:\n    threshold: 250\n    active: true\n  TooManyFunctions:\n    active: true\n    thresholdInFiles: 30\n    thresholdInClasses: 30\n    thresholdInInterfaces: 30\n    thresholdInObjects: 25\n  LongParameterList:\n    active: true\n  NestedBlockDepth:\n    active: true\n    threshold: 4\n  StringLiteralDuplication:\n    active: true\n\nempty-blocks:\n  active: true\n  EmptyCatchBlock:\n    active: true\n  EmptyClassBlock:\n    active: true\n  EmptyDefaultConstructor:\n    active: true\n  EmptyDoWhileBlock:\n    active: true\n  EmptyElseBlock:\n    active: true\n  EmptyFinallyBlock:\n    active: true\n  EmptyForBlock:\n    active: true\n  EmptyFunctionBlock:\n    active: true\n  EmptyIfBlock:\n    active: true\n  EmptyInitBlock:\n    active: true\n  EmptyKtFile:\n    active: true\n  EmptySecondaryConstructor:\n    active: true\n  EmptyWhenBlock:\n    active: true\n  EmptyWhileBlock:\n    active: true\n\nexceptions:\n  active: true\n  ExceptionRaisedInUnexpectedLocation:\n    active: true\n  InstanceOfCheckForException:\n    active: true\n  ReturnFromFinally:\n    active: true\n  TooGenericExceptionCaught:\n    active: false\n  SwallowedException:\n    active: true\n  ThrowingExceptionFromFinally:\n    active: true\n  ThrowingExceptionsWithoutMessageOrCause:\n    active: true\n  ThrowingNewInstanceOfSameException:\n    active: true\n  TooGenericExceptionThrown:\n    active: true\n\nnaming:\n  active: true\n  ClassNaming:\n    active: true\n  ConstructorParameterNaming:\n    active: true\n  EnumNaming:\n    active: true\n  ForbiddenClassName:\n    active: true\n  FunctionMaxLength:\n    active: true\n    maximumFunctionNameLength: 35\n  FunctionMinLength:\n    active: true\n  FunctionNaming:\n    active: true\n  FunctionParameterNaming:\n    active: true\n  MatchingDeclarationName:\n    active: true\n  MemberNameEqualsClassName:\n    active: true\n  ObjectPropertyNaming:\n    active: true\n  PackageNaming:\n    active: true\n  TopLevelPropertyNaming:\n    active: true\n  VariableMaxLength:\n    active: true\n    maximumVariableNameLength: 50\n  VariableMinLength:\n    active: true\n  VariableNaming:\n    active: true\n\nperformance:\n  ArrayPrimitive:\n    active: true\n  ForEachOnRange:\n    active: true\n  SpreadOperator:\n    active: true\n  UnnecessaryTemporaryInstantiation:\n    active: true\n\npotential-bugs:\n  active: true\n  DuplicateCaseInWhenExpression:\n    active: true\n  EqualsAlwaysReturnsTrueOrFalse:\n    active: true\n  EqualsWithHashCodeExist:\n    active: true\n  ExplicitGarbageCollectionCall:\n    active: true\n  InvalidRange:\n    active: true\n  IteratorHasNextCallsNextMethod:\n    active: true\n  IteratorNotThrowingNoSuchElementException:\n    active: true\n  UnconditionalJumpStatementInLoop:\n    active: true\n  UnreachableCode:\n    active: true\n  UnsafeCallOnNullableType:\n    active: true\n  UnsafeCast:\n    active: true\n  UselessPostfixExpression:\n    active: true\n  WrongEqualsTypeParameter:\n    active: true\n\nstyle:\n  active: true\n  MaxLineLength:\n    active: false\n  CollapsibleIfStatements:\n    active: true\n  DataClassContainsFunctions:\n    active: false\n  EqualsNullCall:\n    active: true\n  ExplicitItLambdaParameter:\n    active: true\n  ExpressionBodySyntax:\n    active: true\n  ForbiddenComment:\n    active: true\n  ForbiddenImport:\n    active: true\n  ForbiddenVoid:\n    active: true\n  FunctionOnlyReturningConstant:\n    active: true\n  LoopWithTooManyJumpStatements:\n    active: true\n  MagicNumber:\n    active: false\n  MandatoryBracesIfStatements:\n    active: true\n  MayBeConst:\n    active: true\n  ModifierOrder:\n    active: true\n  NestedClassesVisibility:\n    active: false\n  NewLineAtEndOfFile:\n    active: true\n  NoTabs:\n    active: true\n  OptionalAbstractKeyword:\n    active: true\n  OptionalUnit:\n    active: true\n  OptionalWhenBraces:\n    active: true\n  PreferToOverPairSyntax:\n    active: false\n  ProtectedMemberInFinalClass:\n    active: true\n  RedundantVisibilityModifierRule:\n    active: true\n  ReturnCount:\n    active: true\n    max: 4\n  SafeCast:\n    active: true\n  SerialVersionUIDInSerializableClass:\n    active: true\n  SpacingBetweenPackageAndImports:\n    active: true\n  ThrowsCount:\n    active: true\n  TrailingWhitespace:\n    active: true\n  UnnecessaryAbstractClass:\n    active: true\n    excludeAnnotatedClasses: \"dagger.Module,android.arch.persistence.room.Dao\"\n  UnnecessaryApply:\n    active: false # wait for fix\n  UnnecessaryInheritance:\n    active: true\n  UnnecessaryLet:\n    active: true\n  UnnecessaryParentheses:\n    active: true\n  UntilInsteadOfRangeTo:\n    active: true\n  UnusedImports:\n    active: false\n  UnusedPrivateMember:\n    active: true\n  UseDataClass:\n    active: true\n  UtilityClassWithPublicConstructor:\n    active: true\n  VarCouldBeVal:\n    active: true\n  WildcardImport:\n    active: true\n    excludeImports: 'kotlinx.android.synthetic.*'\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.4-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-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# Kotlin code style for this project: \"official\" or \"obsolete\":\nkotlin.code.style=official\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n\n### Maven publish configuration\nGROUP=app.futured.hauler\nVERSION_NAME=5.X.X-SNAPSHOT\nPOM_DESCRIPTION=Library with swipe to dismiss Activity gesture implementation.\nPOM_INCEPTION_YEAR=2018\nPOM_URL=https://github.com/futuredapp/hauler\nPOM_SCM_URL=https://github.com/futuredapp/hauler\nPOM_SCM_CONNECTION=scm:git:git://github.com/futuredapp/hauler.git\nPOM_SCM_DEV_CONNECTION=scm:git:ssh://github.com/futuredapp/hauler.git\nPOM_LICENCE_NAME=MIT\nPOM_LICENCE_URL=https://github.com/futuredapp/hauler/blob/master/LICENSE\nPOM_LICENCE_DIST=repo\nPOM_DEVELOPER_ID=futured\nPOM_DEVELOPER_NAME=Futured\nPOM_DEVELOPER_URL=https://futured.app\nSONATYPE_HOST=DEFAULT\nRELEASE_SIGNING_ENABLED=true\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windows variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "sample/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "sample/build.gradle.kts",
    "content": "import org.jetbrains.kotlin.config.KotlinCompilerVersion\n\nplugins {\n    id(\"com.android.application\")\n    id(\"kotlin-android\")\n    id(\"kotlin-android-extensions\")\n    id(\"kotlin-kapt\")\n}\n\nandroid {\n    compileSdkVersion(ProjectSettings.targetSdk)\n\n    defaultConfig {\n        applicationId = ProjectSettings.applicationId\n        minSdkVersion(ProjectSettings.minSdk)\n        targetSdkVersion(ProjectSettings.targetSdk)\n    }\n\n    sourceSets {\n        getByName(\"main\").java.srcDir(\"src/main/kotlin\")\n    }\n\n    dataBinding {\n        isEnabled = true\n    }\n\n    compileOptions {\n        sourceCompatibility = JavaVersion.VERSION_1_8\n        targetCompatibility = JavaVersion.VERSION_1_8\n    }\n\n    kotlinOptions {\n        jvmTarget = JavaVersion.VERSION_1_8.toString()\n    }\n}\n\ndependencies {\n    implementation(project(\":core\"))\n    implementation(project(\":databinding\"))\n\n    // Kotlin\n    implementation(kotlin(Deps.Kotlin.stdlib, KotlinCompilerVersion.VERSION))\n    implementation(Deps.AndroidX.appcompat)\n}\n"
  },
  {
    "path": "sample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"app.futured.haulersample\">\n\n    <application\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\n        <activity\n            android:name=\"app.futured.haulersample.MainActivity\"\n            android:exported=\"true\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n\n        <activity\n            android:name=\"app.futured.haulersample.draggable.SimpleActivity\"\n            android:theme=\"@style/AppTheme.Draggable\" />\n\n        <activity\n            android:name=\"app.futured.haulersample.draggable.advanced.AdvancedActivity\"\n            android:theme=\"@style/AppTheme.Draggable\" />\n\n        <activity\n            android:name=\"app.futured.haulersample.draggable.databinding.DatabindingActivity\"\n            android:theme=\"@style/AppTheme.Draggable\" />\n\n        <activity\n            android:name=\"app.futured.haulersample.draggable.SimpleJavaActivity\"\n            android:theme=\"@style/AppTheme.Draggable\" />\n\n    </application>\n</manifest>\n"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/MainActivity.kt",
    "content": "package app.futured.haulersample\n\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport app.futured.haulersample.draggable.SimpleActivity\nimport app.futured.haulersample.draggable.SimpleJavaActivity\nimport app.futured.haulersample.draggable.advanced.AdvancedActivity\nimport app.futured.haulersample.draggable.databinding.DatabindingActivity\nimport kotlinx.android.synthetic.main.activity_main.*\n\nclass MainActivity : AppCompatActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_main)\n\n        startCommonButton.setOnClickListener {\n            startActivity(SimpleActivity.getStartIntent(this))\n        }\n\n        startAdvancedButton.setOnClickListener {\n            startActivity(AdvancedActivity.getStartIntent(this))\n        }\n\n        startBindingButton.setOnClickListener {\n            startActivity(DatabindingActivity.getStartIntent(this))\n        }\n\n        startJavaCommonButton.setOnClickListener {\n            startActivity(SimpleJavaActivity.getStartIntent(this))\n        }\n    }\n}\n"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/SimpleActivity.kt",
    "content": "package app.futured.haulersample.draggable\n\nimport android.content.Context\nimport android.content.Intent\nimport android.os.Bundle\nimport android.util.Log\nimport androidx.appcompat.app.AppCompatActivity\nimport app.futured.hauler.setOnDragActivityListener\nimport app.futured.hauler.setOnDragDismissedListener\nimport app.futured.haulersample.R\nimport kotlinx.android.synthetic.main.activity_simple.*\n\nclass SimpleActivity : AppCompatActivity() {\n\n    companion object {\n        fun getStartIntent(context: Context): Intent = Intent(context, SimpleActivity::class.java)\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_simple)\n\n        commonHaulerView.setOnDragDismissedListener {\n            finish()\n        }\n\n        commonHaulerView.setOnDragActivityListener { elasticOffset, rawOffset ->\n            Log.d(\"SimpleActivity\", \"elasticOffset: $elasticOffset, rawOffset: $rawOffset\")\n        }\n    }\n}\n"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/SimpleJavaActivity.java",
    "content": "package app.futured.haulersample.draggable;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport androidx.annotation.Nullable;\nimport app.futured.hauler.DragDirection;\nimport app.futured.hauler.HaulerView;\nimport app.futured.hauler.OnDragDismissedListener;\nimport app.futured.haulersample.R;\n\npublic class SimpleJavaActivity extends Activity {\n\n    public static Intent getStartIntent(Context context) {\n        return new Intent(context, SimpleJavaActivity.class);\n    }\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_simple);\n\n        HaulerView hv = findViewById(R.id.commonHaulerView);\n        hv.setOnDragDismissedListener(new OnDragDismissedListener() {\n            @Override\n            public void onDismissed(@NotNull DragDirection dragDirection) {\n                finish();\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/advanced/AdvancedActivity.kt",
    "content": "package app.futured.haulersample.draggable.advanced\n\nimport android.content.Context\nimport android.content.Intent\nimport android.os.Bundle\nimport android.widget.Toast\nimport androidx.appcompat.app.AppCompatActivity\nimport app.futured.hauler.DragDirection\nimport app.futured.hauler.setOnDragDismissedListener\nimport app.futured.haulersample.R\nimport kotlinx.android.synthetic.main.activity_advanced.*\n\nclass AdvancedActivity : AppCompatActivity() {\n\n    companion object {\n        fun getStartIntent(context: Context): Intent = Intent(context, AdvancedActivity::class.java)\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_advanced)\n\n        advancedHaulerView.setOnDragDismissedListener { dragDirection ->\n            Toast.makeText(this, \"Dismissed in direction: $dragDirection\", Toast.LENGTH_SHORT).show()\n            when (dragDirection) {\n                DragDirection.DOWN -> {\n                    finish()\n                    overridePendingTransition(0, R.anim.anim_slide_down)\n                }\n                DragDirection.UP -> {\n                    finish()\n                    overridePendingTransition(0, R.anim.anim_slide_up)\n                }\n            }\n        }\n        ignoredAreaView.setScrollViewParent(scrollViewParent)\n    }\n}\n"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/advanced/IgnoredAreaView.kt",
    "content": "package app.futured.haulersample.draggable.advanced\n\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport android.util.AttributeSet\nimport android.view.MotionEvent\nimport androidx.appcompat.widget.AppCompatTextView\nimport app.futured.hauler.LockableNestedScrollView\n\nclass IgnoredAreaView @kotlin.jvm.JvmOverloads constructor(\n    context: Context,\n    attrs: AttributeSet? = null,\n    defStyleAttr: Int = 0\n) : AppCompatTextView(context, attrs, defStyleAttr) {\n\n    private var parentScrollView: LockableNestedScrollView? = null\n\n    fun setScrollViewParent(parentScrollView: LockableNestedScrollView) {\n        this.parentScrollView = parentScrollView\n    }\n\n    @SuppressLint(\"ClickableViewAccessibility\")\n    override fun onTouchEvent(event: MotionEvent): Boolean {\n        return when (event.action) {\n            MotionEvent.ACTION_DOWN -> {\n                parentScrollView?.setScrollEnabled(false)\n                true\n            }\n\n            MotionEvent.ACTION_UP -> {\n                parentScrollView?.setScrollEnabled(true)\n                true\n            }\n            else -> false\n        }\n    }\n}\n"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/databinding/DatabindingActivity.kt",
    "content": "package app.futured.haulersample.draggable.databinding\n\nimport android.content.Context\nimport android.content.Intent\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.databinding.DataBindingUtil\nimport app.futured.hauler.DragDirection\nimport app.futured.haulersample.R\nimport app.futured.haulersample.databinding.ActivityDatabindingBinding\nimport kotlinx.android.synthetic.main.activity_databinding.*\n\nclass DatabindingActivity : AppCompatActivity(), DatabindingActivityView {\n    companion object {\n        fun getStartIntent(context: Context): Intent = Intent(context, DatabindingActivity::class.java)\n    }\n\n    lateinit var binding: ActivityDatabindingBinding\n\n    private var state = DatabindingActivityState(true)\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        binding = DataBindingUtil.setContentView(this, R.layout.activity_databinding)\n        refreshBinding()\n\n        dragEnabledCheck.setOnCheckedChangeListener { _, isChecked ->\n            state = state.copy(isDragEnabled = isChecked)\n            refreshBinding()\n        }\n    }\n\n    private fun refreshBinding() {\n        binding.viewState = state\n        binding.view = this\n        binding.executePendingBindings()\n    }\n\n    override fun onDragDismissed(dragDirection: DragDirection) {\n        finish()\n    }\n}\n"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/databinding/DatabindingActivityState.kt",
    "content": "package app.futured.haulersample.draggable.databinding\n\ndata class DatabindingActivityState(\n    val isDragEnabled: Boolean\n)\n"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/databinding/DatabindingActivityView.kt",
    "content": "package app.futured.haulersample.draggable.databinding\n\nimport app.futured.hauler.DragDirection\n\ninterface DatabindingActivityView {\n    fun onDragDismissed(dragDirection: DragDirection)\n}\n"
  },
  {
    "path": "sample/src/main/res/anim/anim_slide_down.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <translate\n            android:duration=\"@android:integer/config_mediumAnimTime\"\n            android:fromYDelta=\"0\"\n            android:toYDelta=\"100%p\"/>\n</set>\n"
  },
  {
    "path": "sample/src/main/res/anim/anim_slide_up.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <translate\n            android:duration=\"@android:integer/config_mediumAnimTime\"\n            android:fromYDelta=\"0\"\n            android:toYDelta=\"-100%p\"/>\n</set>\n"
  },
  {
    "path": "sample/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:height=\"108dp\"\n        android:width=\"108dp\"\n        android:viewportHeight=\"108\"\n        android:viewportWidth=\"108\">\n    <path android:fillColor=\"#008577\"\n          android:pathData=\"M0,0h108v108h-108z\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M9,0L9,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,0L19,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M29,0L29,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M39,0L39,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M49,0L49,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M59,0L59,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M69,0L69,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M79,0L79,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M89,0L89,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M99,0L99,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,9L108,9\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,19L108,19\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,29L108,29\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,39L108,39\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,49L108,49\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,59L108,59\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,69L108,69\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,79L108,79\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,89L108,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,99L108,99\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,29L89,29\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,39L89,39\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,49L89,49\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,59L89,59\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,69L89,69\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,79L89,79\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M29,19L29,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M39,19L39,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M49,19L49,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M59,19L59,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M69,19L69,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M79,19L79,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n</vector>\n"
  },
  {
    "path": "sample/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:aapt=\"http://schemas.android.com/aapt\"\n        android:width=\"108dp\"\n        android:height=\"108dp\"\n        android:viewportHeight=\"108\"\n        android:viewportWidth=\"108\">\n    <path\n            android:fillType=\"evenOdd\"\n            android:pathData=\"M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z\"\n            android:strokeColor=\"#00000000\"\n            android:strokeWidth=\"1\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                    android:endX=\"78.5885\"\n                    android:endY=\"90.9159\"\n                    android:startX=\"48.7653\"\n                    android:startY=\"61.0927\"\n                    android:type=\"linear\">\n                <item\n                        android:color=\"#44000000\"\n                        android:offset=\"0.0\"/>\n                <item\n                        android:color=\"#00000000\"\n                        android:offset=\"1.0\"/>\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n            android:fillColor=\"#FFFFFF\"\n            android:fillType=\"nonZero\"\n            android:pathData=\"M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z\"\n            android:strokeColor=\"#00000000\"\n            android:strokeWidth=\"1\"/>\n</vector>\n"
  },
  {
    "path": "sample/src/main/res/layout/activity_advanced.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<app.futured.hauler.HaulerView\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        tools:context=\"app.futured.haulersample.draggable.advanced.AdvancedActivity\"\n        android:id=\"@+id/advancedHaulerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@android:color/white\"\n        app:dragUpEnabled=\"true\"\n        app:dragElasticity=\"0.4\"\n        app:dragDismissScale=\"0.6\"\n        app:fadeSystemBars=\"false\"\n        app:dragDismissDistance=\"200dp\">\n\n    <app.futured.hauler.LockableNestedScrollView\n            android:id=\"@+id/scrollViewParent\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:fillViewport=\"true\">\n\n        <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:orientation=\"vertical\"\n                android:gravity=\"center\">\n\n            <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_gravity=\"center\"\n                    android:text=\"@string/swipe_to_dismiss\"/>\n\n            <app.futured.haulersample.draggable.advanced.IgnoredAreaView\n                    android:id=\"@+id/ignoredAreaView\"\n                    android:layout_width=\"200dp\"\n                    android:layout_marginTop=\"20dp\"\n                    android:layout_height=\"200dp\"\n                    android:background=\"@color/colorPrimary\"\n                    android:text=\"@string/ignored_area_text\"\n                    android:gravity=\"center\"\n                    android:textColor=\"@android:color/white\"/>\n\n        </LinearLayout>\n\n    </app.futured.hauler.LockableNestedScrollView>\n\n</app.futured.hauler.HaulerView>\n\n"
  },
  {
    "path": "sample/src/main/res/layout/activity_databinding.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <data>\n        <variable\n                name=\"viewState\"\n                type=\"app.futured.haulersample.draggable.databinding.DatabindingActivityState\"/>\n\n        <variable\n                name=\"view\"\n                type=\"app.futured.haulersample.draggable.databinding.DatabindingActivityView\"/>\n    </data>\n\n    <app.futured.hauler.HaulerView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:gravity=\"center\"\n            android:orientation=\"vertical\"\n            android:background=\"@android:color/white\"\n            app:isDragEnabled=\"@{viewState.dragEnabled}\"\n            app:isDragUpEnabled=\"@{true}\"\n            app:onDragDismissedListener=\"@{(dragDirection) -> view.onDragDismissed(dragDirection)}\">\n\n        <app.futured.hauler.LockableNestedScrollView\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:fillViewport=\"true\"\n                app:isScrollable=\"@{true}\">\n\n            <FrameLayout\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:padding=\"20dp\">\n\n                <CheckBox\n                        android:id=\"@+id/dragEnabledCheck\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/drag_enabled\"\n                        android:checked=\"true\"/>\n\n                <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_gravity=\"center\"\n                        android:text=\"@string/swipe_to_dismiss\"/>\n\n            </FrameLayout>\n\n        </app.futured.hauler.LockableNestedScrollView>\n\n    </app.futured.hauler.HaulerView>\n\n</layout>\n"
  },
  {
    "path": "sample/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:gravity=\"center\"\n        android:orientation=\"vertical\"\n        tools:context=\"app.futured.haulersample.MainActivity\">\n\n    <Button\n            android:id=\"@+id/startCommonButton\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/start_simple\"\n            android:layout_gravity=\"center\"/>\n\n    <Button\n            android:id=\"@+id/startAdvancedButton\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/start_advanced\"\n            android:layout_gravity=\"center\" />\n\n    <Button\n            android:id=\"@+id/startBindingButton\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/start_binding\"\n            android:layout_gravity=\"center\" />\n\n    <Button\n            android:id=\"@+id/startJavaCommonButton\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/start_simple_java\"\n            android:layout_gravity=\"center\" />\n\n</LinearLayout>\n"
  },
  {
    "path": "sample/src/main/res/layout/activity_simple.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<app.futured.hauler.HaulerView\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        tools:context=\"app.futured.haulersample.draggable.SimpleActivity\"\n        android:id=\"@+id/commonHaulerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@android:color/white\">\n\n    <androidx.core.widget.NestedScrollView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:fillViewport=\"true\">\n\n        <FrameLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\">\n\n            <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_gravity=\"center\"\n                    android:text=\"@string/swipe_to_dismiss\"/>\n\n        </FrameLayout>\n\n    </androidx.core.widget.NestedScrollView>\n\n</app.futured.hauler.HaulerView>\n\n"
  },
  {
    "path": "sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n</adaptive-icon>\n"
  },
  {
    "path": "sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n</adaptive-icon>\n"
  },
  {
    "path": "sample/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#008577</color>\n    <color name=\"colorPrimaryDark\">#00574B</color>\n    <color name=\"colorAccent\">#D81B60</color>\n    <color name=\"dark_gray\">#99323232</color>\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Hauler</string>\n    <string name=\"start_simple\">Start Simple Activity</string>\n    <string name=\"start_simple_java\">Start Simple Java Activity</string>\n    <string name=\"start_advanced\">Start Advanced Activity</string>\n    <string name=\"start_binding\">Start Binding Activity</string>\n    <string name=\"swipe_to_dismiss\">Swipe down to dismiss</string>\n    <string name=\"ignored_area_text\">Ignored area</string>\n    <string name=\"drag_enabled\">Drag Enabled</string>\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n    <style name=\"AppTheme.Draggable\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <item name=\"android:colorBackgroundCacheHint\">@null</item>\n        <item name=\"android:windowContentOverlay\">@null</item>\n        <item name=\"android:windowIsFloating\">false</item>\n        <item name=\"android:windowIsTranslucent\">true</item>\n        <item name=\"android:windowNoTitle\">true</item>\n        <item name=\"android:windowBackground\">@color/dark_gray</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "settings.gradle.kts",
    "content": "rootProject.buildFileName = \"build.gradle.kts\"\n\ninclude(\":core\", \":databinding\", \":sample\")\n"
  }
]