Full Code of thefuntasty/hauler for AI

master 2c7cf8eaeb34 cached
68 files
69.6 KB
20.1k tokens
3 symbols
1 requests
Download .txt
Repository: thefuntasty/hauler
Branch: master
Commit: 2c7cf8eaeb34
Files: 68
Total size: 69.6 KB

Directory structure:
gitextract_1jcvn5xr/

├── .editorconfig
├── .github/
│   └── workflows/
│       ├── publish_release.yml
│       ├── publish_snapshot.yml
│       └── pull_request.yml
├── .gitignore
├── Dangerfile
├── Gemfile
├── LICENSE
├── README.md
├── build.gradle.kts
├── buildSrc/
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           └── kotlin/
│               ├── Deps.kt
│               ├── ProjectSettings.kt
│               ├── Versions.kt
│               └── app/
│                   └── futured/
│                       └── hauler/
│                           └── DependencyUpdates.kt
├── core/
│   ├── .gitignore
│   ├── build.gradle.kts
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── kotlin/
│           │   └── app/
│           │       └── futured/
│           │           └── hauler/
│           │               ├── ColorUtils.kt
│           │               ├── DragDirection.kt
│           │               ├── HaulerView.kt
│           │               ├── HaulerViewExtensions.kt
│           │               ├── LockableNestedScrollView.kt
│           │               ├── OnDragActivityListener.kt
│           │               ├── OnDragDismissedListener.kt
│           │               └── SystemBarsFader.kt
│           └── res/
│               └── values/
│                   ├── attrs_hauler_view.xml
│                   └── dimens.xml
├── databinding/
│   ├── .gitignore
│   ├── build.gradle.kts
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── kotlin/
│               └── app/
│                   └── futured/
│                       └── hauler/
│                           └── databinding/
│                               ├── IsDragEnabledAdapter.kt
│                               ├── IsDragUpEnabledAdapter.kt
│                               ├── IsScrollableAdapter.kt
│                               └── OnDragDismissedListenerAdapter.kt
├── detekt.yml
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── sample/
│   ├── .gitignore
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── kotlin/
│           │   └── app/
│           │       └── futured/
│           │           └── haulersample/
│           │               ├── MainActivity.kt
│           │               └── draggable/
│           │                   ├── SimpleActivity.kt
│           │                   ├── SimpleJavaActivity.java
│           │                   ├── advanced/
│           │                   │   ├── AdvancedActivity.kt
│           │                   │   └── IgnoredAreaView.kt
│           │                   └── databinding/
│           │                       ├── DatabindingActivity.kt
│           │                       ├── DatabindingActivityState.kt
│           │                       └── DatabindingActivityView.kt
│           └── res/
│               ├── anim/
│               │   ├── anim_slide_down.xml
│               │   └── anim_slide_up.xml
│               ├── drawable/
│               │   └── ic_launcher_background.xml
│               ├── drawable-v24/
│               │   └── ic_launcher_foreground.xml
│               ├── layout/
│               │   ├── activity_advanced.xml
│               │   ├── activity_databinding.xml
│               │   ├── activity_main.xml
│               │   └── activity_simple.xml
│               ├── mipmap-anydpi-v26/
│               │   ├── ic_launcher.xml
│               │   └── ic_launcher_round.xml
│               └── values/
│                   ├── colors.xml
│                   ├── strings.xml
│                   └── styles.xml
└── settings.gradle.kts

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
[*.{kt,kts}]

max_line_length=130



================================================
FILE: .github/workflows/publish_release.yml
================================================
name: Publish Release

on:
  release:
    types: [published]

jobs:
  release:
    name: Release Publish
    runs-on: [ubuntu-latest]
    steps:
      - uses: actions/checkout@v1
      - name: Set up JDK 11
        uses: actions/setup-java@v2
        with:
          distribution: 'zulu'
          java-version: '11'
      - name: Build & run unit tests
        shell: bash
        run: ./gradlew --continue build testRelease
      - name: Publish release
        run: ./gradlew publish --no-daemon --no-parallel --stacktrace -PVERSION_NAME=${{github.event.release.name}}
        env:
          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_REPOSITORY_USERNAME }}
          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_REPOSITORY_PASSWORD }}
          ORG_GRADLE_PROJECT_SIGNING_PRIVATE_KEY: ${{ secrets.GPG_SIGNING_PRIVATE_KEY }}
          ORG_GRADLE_PROJECT_SIGNING_PASSWORD: ${{ secrets.GPG_SIGNING_PASSWORD }}


================================================
FILE: .github/workflows/publish_snapshot.yml
================================================
name: Publish Snapshot
on:
  push:
    branches:
      master

jobs:
  master:
    name: Snapshot Publish
    runs-on: [ ubuntu-latest ]
    env:
      SLACK_CHANNEL: android
    steps:
      - uses: actions/checkout@v1
      - name: Set up JDK 11
        uses: actions/setup-java@v2
        with:
          distribution: 'zulu'
          java-version: '11'
      - name: Run unit tests
        shell: bash
        run: ./gradlew --continue build testRelease
      - name: Build & publish snapshot
        run: ./gradlew publish --no-daemon --no-parallel --stacktrace
        env:
          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_REPOSITORY_USERNAME }}
          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_REPOSITORY_PASSWORD }}
          ORG_GRADLE_PROJECT_SIGNING_PRIVATE_KEY: ${{ secrets.GPG_SIGNING_PRIVATE_KEY }}
          ORG_GRADLE_PROJECT_SIGNING_PASSWORD: ${{ secrets.GPG_SIGNING_PASSWORD }}
      - name: Slack Notification
        if: failure()
        uses: homoluctus/slatify@master
        with:
          type: "failure"
          job_name: '*Snapshot Publish*'
          username: GitHub
          channel: ${{env.SLACK_CHANNEL}}
          url: ${{ secrets.SLACK_WEB_HOOK }}
          commit: true
          token: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/pull_request.yml
================================================
name: Check PR
on: [pull_request]

jobs:
  pr:
    name: PR check
    runs-on: [ubuntu-latest]
    env:
      DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
    steps:
      - uses: actions/checkout@v1
      - uses: actions/setup-ruby@v1
        with:
          ruby-version: '2.6'
      - name: Set up JDK 11
        uses: actions/setup-java@v2
        with:
          distribution: 'zulu'
          java-version: '11'
      - name: Run LintCheck
        shell: bash
        run: ./gradlew detekt ktlintCheck lint assembleRelease
      - name: Run unit tests
        shell: bash
        run: ./gradlew --continue testRelease
      - name: Danger action
        uses: MeilCli/danger-action@v2
        continue-on-error: true
        with:
          plugins_file: 'Gemfile'
          danger_file: 'Dangerfile'
          danger_id: 'danger-pr'


================================================
FILE: .gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/*
/buildSrc/build/*
.DS_Store
/build
/captures
.externalNativeBuild


================================================
FILE: Dangerfile
================================================
is_pr_big = git.insertions > 500
has_correct_prefix = github.branch_for_head.match(/^(feature|hotfix|fix|release|housekeep)\//)

warn("Branch name should have `release/`, `hotfix/`, `fix/`, `housekeep/` or `feature/` prefix.") if !has_correct_prefix
warn("This pull request is too big.") if is_pr_big

commit_lint.check warn: :all, disable: [:subject_length]

# Utils
def report_checkstyle_for_directory(directory_name)
  if Dir.exists?(directory_name)
    Dir.glob("#{directory_name}/*.xml").each {|f|
      report_checkstyle(f)
    }
  end
end

def report_checkstyle(file_name)
  if File.file?(file_name)
    checkstyle_format.report file_name
  end
end

# Setup checkstyle
checkstyle_format.base_path = Dir.pwd

# Detekt checkstyle
report_checkstyle 'build/reports/detekt/detekt.xml'

# Ktlint checkstyle
report_checkstyle_for_directory 'library/build/reports/ktlint'
report_checkstyle_for_directory 'sample/build/reports/ktlint'


================================================
FILE: Gemfile
================================================
source 'https://rubygems.org'

gem 'danger-commit_lint'
gem 'danger-checkstyle_format'


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 Futured apps s.r.o.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<img align="right" src="images/Hauler.svg">

# Hauler

[![Maven Central](https://img.shields.io/maven-central/v/app.futured.hauler/hauler)](https://search.maven.org/artifact/app.futured.hauler/hauler/)
![minSdk:21](https://img.shields.io/badge/minSDK-21-brightgreen.svg)
[![Android Arsenal]( https://img.shields.io/badge/Android%20Arsenal-Hauler-brightgreen.svg?style=flat )]( https://android-arsenal.com/details/1/7359 )
![Publish Snapshot](https://github.com/futuredapp/hauler/actions/workflows/publish_snapshot.yml/badge.svg)
![License](https://img.shields.io/github/license/futuredapp/hauler?color=black)

Hauler is an Android library containing custom layout which enables to easily create swipe to dismiss `Activity`.
Implementation is based on code from project [Plaid](https://github.com/nickbutcher/plaid).

![Alt text](https://github.com/thefuntasty/hauler/blob/master/images/example.gif)

# Installation

```groovy
dependencies {
    implementation("app.futured.hauler:hauler:latestVersion")

    // optional dependency with set of Data Binding adapters
    implementation("app.futured.hauler:databinding:latestVersion")
}
```

### Snapshot installation

Add new maven repo to your top level gradle file.

```groovy
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
```

Snapshots are grouped based on major version, so for version 5.x.x use:

```groovy
implementation "app.futured.hauler:hauler:5.X.X-SNAPSHOT"
```

# Features

Hauler library comes with highly customizable `HaulerView` which provides swipe to dismiss functionality. 
It also ships with `databinding` module which contains Binding Adapters for smoother experience with Android Data Binding implementation.

# Usage
 
 Activity which is meant to be dismissed must contain `HaulerView` as a root view and `NestedScrollView` (or other `View` what supports nested scroll) 
 as its child. Make sure your `NestedScrollview`'s attribute `android:fillViewport` is set to `true` otherwise it might not behave as
 expected:

```xml
<app.futured.hauler.HaulerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/haulerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true">
            
            <!-- your layout-->
            
    </androidx.core.widget.NestedScrollView>
</app.futured.hauler.HaulerView>
```

Secondly, define translucent floating Theme and assign it to the Activity you want to give dismiss ability:

 ```xml
<style name="AppTheme.Draggable" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@color/dark_gray</item>
</style>
```

```xml
<activity
        android:name=".draggable.SimpleUsageActivity"
        android:theme="@style/AppTheme.Draggable"/>
```
Set `onDragDismissListener` to react properly to user dismiss request. Example implementation might look like this:
```kotlin
    override fun onCreate(savedInstanceState: Bundle?) {
        // ...

        haulerView.setOnDragDismissedListener {
            finish() // finish activity when dismissed
        }
    }
```

## Customization

There are few styleable attributes you might want to use to customize your `HaulerView`:

 ```xml
<app.futured.hauler.HaulerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:dragDismissDistance="112dp"
        app:dragDismissFraction="0.9"
        app:dragElasticity="0.7"
        app:dragDismissScale="0.95"/>
```

| Attribute name | Type | Default value | Description|
| -------------- | ---- | ------------- | ---------- |
| `app:dragDismissDistance` | dimen | 100dp | Distance which should be `View` swiped to consider Activity as dismissed |
| `app:dragDismissFraction` | float | unspecified | `<0;1>` - Fraction of `View`'s height we should reach swiping to consider Activity as dismissed |
| `app:dragElasticity` | float | 0.8 | `<0;1>` - Toughness of swipe. Higher value indicates more rigid feeling  |
| `app:dragDismissScale` | float | 0.95 | `<0;1>` - Scale factor of `View` while performing swipe action |
| `app:dragUpEnabled` | boolean | false | Flag indicating if drag up dismiss gesture is enabled |
| `app:fadeSystemBars` | boolean | true | Flag indicating if system bars (status & navigation) fades while dismiss is in progress |

Attributes `dragDismissDistance` and `dragDismissFraction` are exclusive. Do not use them together.

# License

Hauler is available under the MIT license. See the [LICENSE file](LICENCE) for more information.


================================================
FILE: build.gradle.kts
================================================
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath(Deps.gradlePlugin)
        classpath(kotlin(Deps.Kotlin.gradlePlugin, Versions.kotlin))
        classpath(Deps.Plugins.mavenPublish)
        classpath(Deps.Plugins.dokka)
    }
}

plugins {
    idea
    id(Deps.Plugins.detekt) version Versions.detekt
    id(Deps.Plugins.ktlint) version Versions.ktlint
}

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
    }
}

tasks {
    register<app.futured.hauler.DependencyUpdates>("dependencyUpdates")
}

subprojects {
    apply(plugin = Deps.Plugins.ktlint)
    ktlint {
        version.set(Versions.ktlintExtension)
        ignoreFailures.set(true)
        android.set(true)
        outputToConsole.set(true)
        reporters {
            reporter(ReporterType.PLAIN)
            reporter(ReporterType.CHECKSTYLE)
        }
    }

    plugins.whenPluginAdded {
        if (this is SigningPlugin) {
            extensions.findByType<SigningExtension>()?.apply {
                val hasKey = project.hasProperty("SIGNING_PRIVATE_KEY")
                val hasPassword = project.hasProperty("SIGNING_PASSWORD")

                if (hasKey && hasPassword) {
                    useInMemoryPgpKeys(
                        project.properties["SIGNING_PRIVATE_KEY"].toString(),
                        project.properties["SIGNING_PASSWORD"].toString()
                    )
                }
            }
        }
    }
}

detekt {
    autoCorrect = false
    version = Versions.detekt
    input = files("sample/src/main/kotlin", "library/src/main/kotlin")
    config = files("detekt.yml")
}


================================================
FILE: buildSrc/build.gradle.kts
================================================
plugins {
    `kotlin-dsl`
}

repositories {
    jcenter()
}

dependencies {
    implementation("com.github.ben-manes:gradle-versions-plugin:0.36.0")
}

dependencies {
    implementation("com.github.ben-manes:gradle-versions-plugin:0.33.0")
}


================================================
FILE: buildSrc/src/main/kotlin/Deps.kt
================================================
object Deps {
    const val gradlePlugin = "com.android.tools.build:gradle:${Versions.gradle}"

    object Plugins {
        const val detekt = "io.gitlab.arturbosch.detekt"
        const val ktlint = "org.jlleitschuh.gradle.ktlint"
        const val mavenPublish = "com.vanniktech:gradle-maven-publish-plugin:${Versions.mavenPublish}"
        const val dokka = "org.jetbrains.dokka:dokka-gradle-plugin:${Versions.dokka}"
    }

    object Kotlin {
        const val gradlePlugin = "gradle-plugin"
        const val stdlib = "stdlib-jdk7"
    }

    object AndroidX {
        const val appcompat = "androidx.appcompat:appcompat:${Versions.androidx}"
        const val palette = "androidx.palette:palette:${Versions.palette}"
        const val ktx = "androidx.core:core-ktx:${Versions.androidxKtx}"
    }
}


================================================
FILE: buildSrc/src/main/kotlin/ProjectSettings.kt
================================================
object ProjectSettings {
    const val applicationId = "app.futured.hauler"
    const val targetSdk = 32
    const val minSdk = 21
}


================================================
FILE: buildSrc/src/main/kotlin/Versions.kt
================================================
object Versions {
    // gradle
    const val gradle = "7.2.1"

    // plugins
    const val detekt = "1.20.0"
    const val ktlint = "10.3.0"
    const val ktlintExtension = "0.41.0"
    const val mavenPublish = "0.21.0"
    const val dokka = "1.7.0"

    // kotlin
    const val kotlin = "1.7.0"

    const val androidx = "1.4.2"
    const val androidxKtx = "1.8.0"
    const val palette = "1.0.0"
}


================================================
FILE: buildSrc/src/main/kotlin/app/futured/hauler/DependencyUpdates.kt
================================================
package app.futured.hauler

import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask

abstract class DependencyUpdates : DependencyUpdatesTask() {

    init {
        group = "futured"

        this.resolutionStrategy {
            componentSelection {
                all {
                    val rejected = listOf("alpha", "beta", "rc", "cr", "m", "preview", "testing")
                        .map { qualifier -> Regex("(?i).*[.-]$qualifier[.\\d-]*") }
                        .any { it.matches(candidate.version) }
                    if (rejected) {
                        reject("Release candidate")
                    }
                }
            }
        }
    }
}


================================================
FILE: core/.gitignore
================================================
/build


================================================
FILE: core/build.gradle.kts
================================================
import org.jetbrains.kotlin.config.KotlinCompilerVersion

plugins {
    id("com.android.library")
    id("kotlin-android")
    id("com.vanniktech.maven.publish")
}

android {

    compileSdkVersion(ProjectSettings.targetSdk)

    defaultConfig {
        minSdkVersion(ProjectSettings.minSdk)
        targetSdkVersion(ProjectSettings.targetSdk)
    }

    sourceSets {
        getByName("main").java.srcDir("src/main/kotlin")
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }
}

dependencies {
    implementation(kotlin(Deps.Kotlin.stdlib, KotlinCompilerVersion.VERSION))
    implementation(Deps.AndroidX.appcompat)
    implementation(Deps.AndroidX.palette)
    implementation(Deps.AndroidX.ktx)
}


================================================
FILE: core/gradle.properties
================================================
POM_NAME=Library containing custom layout which enables to easily create swipe to dismiss Activity
POM_ARTIFACT_ID=hauler
POM_PACKAGING=aar


================================================
FILE: core/src/main/AndroidManifest.xml
================================================
<manifest package="app.futured.hauler"/>


================================================
FILE: core/src/main/kotlin/app/futured/hauler/ColorUtils.kt
================================================
package app.futured.hauler

import androidx.annotation.CheckResult
import androidx.annotation.ColorInt
import androidx.annotation.IntRange

internal object ColorUtils {

    @CheckResult
    @ColorInt
    fun modifyAlpha(@ColorInt color: Int, @IntRange(from = 0, to = 255) alpha: Int): Int =
        color and 0x00ffffff or (alpha shl 24)
}


================================================
FILE: core/src/main/kotlin/app/futured/hauler/DragDirection.kt
================================================
package app.futured.hauler

enum class DragDirection {
    UP, DOWN
}


================================================
FILE: core/src/main/kotlin/app/futured/hauler/HaulerView.kt
================================================
package app.futured.hauler

import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import androidx.core.content.withStyledAttributes
import androidx.core.view.animation.PathInterpolatorCompat

class HaulerView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    // configurable attributes
    private var dragDismissDistance =
        context.resources.getDimensionPixelSize(R.dimen.default_drag_dismiss_distance).toFloat()
    private var dragDismissFraction = -1f
    private var dragDismissScale = 0.95f
    private var shouldScale = true
    private var dragElasticity = 0.8f

    // state
    private var totalDrag: Float = 0.toFloat()
    private var draggingDown = false
    private var draggingUp = false
    private var mLastActionEvent: Int = 0

    private var onDragDismissedListener: OnDragDismissedListener? = null
    private var onDragActivityListener: OnDragActivityListener? = null
    private var systemBarsFader: SystemBarsFader? = null

    private var isDragEnabled = true
    private var dragUpEnabled = false
    private var fadeSystemBars = true

    init {
        getContext().withStyledAttributes(set = attrs, attrs = R.styleable.HaulerView) {
            val distanceAvailable = hasValue(R.styleable.HaulerView_dragDismissDistance)
            val dismissFractionAvailable = hasValue(R.styleable.HaulerView_dragDismissFraction)

            if (distanceAvailable && dismissFractionAvailable) {
                throw IllegalStateException("Do not specify both dragDismissDistance and dragDismissFraction. Choose one.")
            } else if (distanceAvailable) {
                dragDismissDistance = getDimensionPixelSize(R.styleable.HaulerView_dragDismissDistance, 0).toFloat()
            } else if (dismissFractionAvailable) {
                dragDismissFraction = getFloat(R.styleable.HaulerView_dragDismissFraction, dragDismissFraction)
            }

            dragDismissScale = getFloat(R.styleable.HaulerView_dragDismissScale, dragDismissScale)
            dragUpEnabled = getBoolean(R.styleable.HaulerView_dragUpEnabled, dragUpEnabled)
            dragElasticity = getFloat(R.styleable.HaulerView_dragElasticity, dragElasticity)
            fadeSystemBars = getBoolean(R.styleable.HaulerView_fadeSystemBars, fadeSystemBars)
        }

        setFadeSystemBars(fadeSystemBars)
        shouldScale = dragDismissScale != 1f
    }

    override fun onStartNestedScroll(child: View, target: View, nestedScrollAxes: Int): Boolean =
        nestedScrollAxes and View.SCROLL_AXIS_VERTICAL != 0

    override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray) {
        if (isDragEnabled.not()) {
            return super.onNestedPreScroll(target, dx, dy, consumed)
        }
        // if we're in a drag gesture and the user reverses up the we should take those events
        val draggingDownInProgress = draggingDown && dy > 0
        val draggingUpInProgress = draggingUp && dy < 0
        if (draggingDownInProgress || draggingUpInProgress) {
            dragScale(dy)
            consumed[1] = dy
        }
    }

    override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) {
        if (isDragEnabled.not() || (dragUpEnabled.not() && dyUnconsumed > 0)) {
            return super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed)
        }
        dragScale(dyUnconsumed)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        mLastActionEvent = ev.action
        return super.onInterceptTouchEvent(ev)
    }

    override fun onStopNestedScroll(child: View) {
        if (isDragEnabled.not()) {
            return super.onStopNestedScroll(child)
        }

        val totalDragNormalized = if (dragUpEnabled) Math.abs(totalDrag) else -totalDrag
        val dragDirection = if (totalDrag > 0) DragDirection.UP else DragDirection.DOWN

        if (totalDragNormalized >= dragDismissDistance) {
            dispatchDismissCallback(dragDirection)
        } else { // settle back to natural position
            if (mLastActionEvent == MotionEvent.ACTION_DOWN) {
                // this is a 'defensive cleanup for new gestures',
                // don't animate here
                // see also https://github.com/nickbutcher/plaid/issues/185
                translationY = 0f
                scaleX = 1f
                scaleY = 1f
            } else {
                animate()
                    .translationY(0f)
                    .scaleX(1f)
                    .scaleY(1f)
                    .setDuration(200L)
                    .setInterpolator(PathInterpolatorCompat.create(0.4f, 0f, 0.2f, 1f))
                    .setListener(null)
                    .start()
            }
            totalDrag = 0f
            draggingUp = false
            draggingDown = draggingUp
            dispatchDragCallback(0f, 0f)
        }
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        if (dragDismissFraction > 0f) {
            dragDismissDistance = h * dragDismissFraction
        }
    }

    /**
     * Set if drag/swipe up dismiss is enabled
     */
    fun setDragUpEnabled(dragUpEnabled: Boolean) {
        this.dragUpEnabled = dragUpEnabled
    }

    /**
     * Set lambda reference which is called when dismiss gesture has
     * been performed
     */
    fun setOnDragDismissedListener(onDragDismissedListener: OnDragDismissedListener) {
        this.onDragDismissedListener = onDragDismissedListener
    }

    /**
     * Set lambda reference to listener which is called when drag is in
     * progress
     */
    fun setOnDragActivityListener(onDragActivityListener: OnDragActivityListener) {
        this.onDragActivityListener = onDragActivityListener
    }

    /**
     * Set if drag gesture is enabled
     */
    fun setDragEnabled(isDragEnabled: Boolean) {
        this.isDragEnabled = isDragEnabled
    }

    /**
     * Set if system bars should fade when dismiss is in progress
     */
    fun setFadeSystemBars(fadeSystemBars: Boolean) {
        this.fadeSystemBars = fadeSystemBars

        if (fadeSystemBars) {
            (context as? Activity)?.also {
                systemBarsFader = SystemBarsFader(it)
            }
        } else {
            systemBarsFader = null
        }
    }

    private fun dragScale(scroll: Int) {
        if (scroll == 0) return

        totalDrag += scroll.toFloat()

        // track the direction & set the pivot point for scaling
        // don't double track i.e. if start dragging down and then reverse, keep tracking as
        // dragging down until they reach the 'natural' position
        if (scroll < 0 && !draggingUp && !draggingDown) {
            draggingDown = true
            if (shouldScale) pivotY = height.toFloat()
        } else if (scroll > 0 && !draggingDown && !draggingUp) {
            draggingUp = true
            if (shouldScale) {
                pivotY = 0f
            }
        }
        // how far have we dragged relative to the distance to perform a dismiss
        // (0–1 where 1 = dismiss distance). Decreasing logarithmically as we approach the limit
        var dragFraction = Math.log10((1 + Math.abs(totalDrag) / dragDismissDistance).toDouble()).toFloat()

        // calculate the desired translation given the drag fraction
        var dragTo = dragFraction * dragDismissDistance * dragElasticity

        if (draggingUp) {
            // as we use the absolute magnitude when calculating the drag fraction, need to
            // re-apply the drag direction
            dragTo *= -1f
        }
        translationY = dragTo

        if (shouldScale) {
            val scale = 1 - (1 - dragDismissScale) * dragFraction
            scaleX = scale
            scaleY = scale
        }

        // if we've reversed direction and gone past the settle point then clear the flags to
        // allow the list to get the scroll events & reset any transforms
        val downSettlePointReached = draggingDown && totalDrag >= 0
        val upSettlePointReached = draggingUp && totalDrag <= 0
        if (downSettlePointReached || upSettlePointReached) {
            dragFraction = 0f
            dragTo = dragFraction
            totalDrag = dragTo
            draggingUp = false
            draggingDown = draggingUp
            translationY = 0f
            scaleX = 1f
            scaleY = 1f
        }
        dispatchDragCallback(dragTo, Math.min(1f, Math.abs(totalDrag) / dragDismissDistance))
    }

    private fun dispatchDragCallback(elasticOffsetPixels: Float, rawOffset: Float) {
        systemBarsFader?.onDrag(elasticOffsetPixels, rawOffset)
        onDragActivityListener?.onDrag(elasticOffsetPixels, rawOffset)
    }

    private fun dispatchDismissCallback(dragDirection: DragDirection) {
        systemBarsFader?.onDismiss()
        onDragDismissedListener?.onDismissed(dragDirection)
    }
}


================================================
FILE: core/src/main/kotlin/app/futured/hauler/HaulerViewExtensions.kt
================================================
package app.futured.hauler

fun HaulerView.setOnDragDismissedListener(onDragDismissedListener: (DragDirection) -> Unit) {
    this.setOnDragDismissedListener(object : OnDragDismissedListener {
        override fun onDismissed(dragDirection: DragDirection) {
            onDragDismissedListener.invoke(dragDirection)
        }
    })
}

fun HaulerView.setOnDragActivityListener(onDragActivityListener: (elasticOffsetPixels: Float, rawOffset: Float) -> Unit) {
    this.setOnDragActivityListener(object : OnDragActivityListener {
        override fun onDrag(elasticOffsetPixels: Float, rawOffset: Float) {
            onDragActivityListener.invoke(elasticOffsetPixels, rawOffset)
        }
    })
}


================================================
FILE: core/src/main/kotlin/app/futured/hauler/LockableNestedScrollView.kt
================================================
package app.futured.hauler

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.core.widget.NestedScrollView

class LockableNestedScrollView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : NestedScrollView(context, attrs, defStyleAttr) {

    private var isScrollable = true

    fun setScrollEnabled(isScrollEnabled: Boolean) {
        isScrollable = isScrollEnabled
    }

    @Suppress("ClickableViewAccessibility")
    override fun onTouchEvent(ev: MotionEvent): Boolean = when (ev.action) {
        MotionEvent.ACTION_DOWN ->
            isScrollable && super.onTouchEvent(ev)
        else ->
            super.onTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent) = isScrollable && super.onInterceptTouchEvent(ev)
}


================================================
FILE: core/src/main/kotlin/app/futured/hauler/OnDragActivityListener.kt
================================================
package app.futured.hauler

interface OnDragActivityListener {
    fun onDrag(elasticOffsetPixels: Float, rawOffset: Float)
}


================================================
FILE: core/src/main/kotlin/app/futured/hauler/OnDragDismissedListener.kt
================================================
package app.futured.hauler

interface OnDragDismissedListener {
    fun onDismissed(dragDirection: DragDirection)
}


================================================
FILE: core/src/main/kotlin/app/futured/hauler/SystemBarsFader.kt
================================================
package app.futured.hauler

import android.app.Activity
import android.graphics.Color

internal class SystemBarsFader(private val activity: Activity) {

    private val statusBarAlpha: Int by lazy { Color.alpha(getStatusBarColor()) }

    fun onDrag(elasticOffsetPixels: Float, rawOffset: Float) {
        when {
            elasticOffsetPixels != 0f -> // dragging downward or upward, fade the status bar in proportion
                activity.window.statusBarColor = ColorUtils.modifyAlpha(getStatusBarColor(), getNewAlpha(rawOffset))
            elasticOffsetPixels == 0f ->
                activity.window.statusBarColor = ColorUtils.modifyAlpha(getStatusBarColor(), statusBarAlpha)
        }
    }

    fun onDismiss() {
        // set transparent window bg and transparent navigation bar
        activity.window.decorView.setBackgroundColor(0)
        activity.window.navigationBarColor = ColorUtils.modifyAlpha(activity.window.navigationBarColor, 0)
    }

    private fun getStatusBarColor() = activity.window.statusBarColor

    private fun getNewAlpha(rawOffset: Float) = ((1f - rawOffset) * statusBarAlpha).toInt()
}


================================================
FILE: core/src/main/res/values/attrs_hauler_view.xml
================================================
<resources>

    <declare-styleable name="HaulerView">
        <attr name="dragDismissDistance" format="dimension"/>
        <attr name="dragDismissFraction" format="float"/>
        <attr name="dragDismissScale" format="float"/>
        <attr name="dragElasticity" format="float"/>
        <attr name="dragUpEnabled" format="boolean"/>
        <attr name="fadeSystemBars" format="boolean" />
    </declare-styleable>

</resources>


================================================
FILE: core/src/main/res/values/dimens.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="default_drag_dismiss_distance">100dp</dimen>
</resources>


================================================
FILE: databinding/.gitignore
================================================
/build


================================================
FILE: databinding/build.gradle.kts
================================================
import org.jetbrains.kotlin.config.KotlinCompilerVersion

plugins {
    id("com.android.library")
    id("kotlin-android")
    id("kotlin-kapt")
    id("com.vanniktech.maven.publish")
}

android {
    compileSdkVersion(ProjectSettings.targetSdk)

    defaultConfig {
        minSdkVersion(ProjectSettings.minSdk)
        targetSdkVersion(ProjectSettings.targetSdk)
    }

    sourceSets {
        getByName("main").java.srcDir("src/main/kotlin")
    }

    buildFeatures {
        dataBinding = true
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }
}

dependencies {
    implementation(project(":core"))

    implementation(kotlin(Deps.Kotlin.stdlib, KotlinCompilerVersion.VERSION))
    implementation(Deps.AndroidX.appcompat)
}


================================================
FILE: databinding/gradle.properties
================================================
POM_NAME=Databinding extensions for core library
POM_ARTIFACT_ID=databinding
POM_PACKAGING=aar


================================================
FILE: databinding/src/main/AndroidManifest.xml
================================================
<manifest package="app.futured.hauler.databinding"/>


================================================
FILE: databinding/src/main/kotlin/app/futured/hauler/databinding/IsDragEnabledAdapter.kt
================================================
package app.futured.hauler.databinding

import androidx.databinding.BindingAdapter
import app.futured.hauler.HaulerView

@BindingAdapter("app:isDragEnabled")
fun HaulerView.isDragEnabled(isDragEnabled: Boolean) {
    this.setDragEnabled(isDragEnabled)
}


================================================
FILE: databinding/src/main/kotlin/app/futured/hauler/databinding/IsDragUpEnabledAdapter.kt
================================================
package app.futured.hauler.databinding

import androidx.databinding.BindingAdapter
import app.futured.hauler.HaulerView

@BindingAdapter("app:isDragUpEnabled")
fun HaulerView.isDragUpEnabled(isDragUpEnabled: Boolean) {
    this.setDragUpEnabled(isDragUpEnabled)
}


================================================
FILE: databinding/src/main/kotlin/app/futured/hauler/databinding/IsScrollableAdapter.kt
================================================
package app.futured.hauler.databinding

import androidx.databinding.BindingAdapter
import app.futured.hauler.LockableNestedScrollView

@BindingAdapter("app:isScrollable")
fun LockableNestedScrollView.isScrollable(isScrollable: Boolean) {
    setScrollEnabled(isScrollable)
}


================================================
FILE: databinding/src/main/kotlin/app/futured/hauler/databinding/OnDragDismissedListenerAdapter.kt
================================================
package app.futured.hauler.databinding

import androidx.databinding.BindingAdapter
import app.futured.hauler.HaulerView
import app.futured.hauler.OnDragDismissedListener
import app.futured.hauler.setOnDragDismissedListener

@BindingAdapter("app:onDragDismissedListener")
fun HaulerView.setOnDragDismissedListener(listener: OnDragDismissedListener) {
    this.setOnDragDismissedListener { listener.onDismissed(it) }
}


================================================
FILE: detekt.yml
================================================
build:
  maxIssues: 100

complexity:
  active: true
  ComplexCondition:
    active: true
  ComplexMethod:
    active: true
    threshold: 20
    ignoreSimpleWhenEntries: true
  LargeClass:
    threshold: 250
    active: true
  TooManyFunctions:
    active: true
    thresholdInFiles: 30
    thresholdInClasses: 30
    thresholdInInterfaces: 30
    thresholdInObjects: 25
  LongParameterList:
    active: true
  NestedBlockDepth:
    active: true
    threshold: 4
  StringLiteralDuplication:
    active: true

empty-blocks:
  active: true
  EmptyCatchBlock:
    active: true
  EmptyClassBlock:
    active: true
  EmptyDefaultConstructor:
    active: true
  EmptyDoWhileBlock:
    active: true
  EmptyElseBlock:
    active: true
  EmptyFinallyBlock:
    active: true
  EmptyForBlock:
    active: true
  EmptyFunctionBlock:
    active: true
  EmptyIfBlock:
    active: true
  EmptyInitBlock:
    active: true
  EmptyKtFile:
    active: true
  EmptySecondaryConstructor:
    active: true
  EmptyWhenBlock:
    active: true
  EmptyWhileBlock:
    active: true

exceptions:
  active: true
  ExceptionRaisedInUnexpectedLocation:
    active: true
  InstanceOfCheckForException:
    active: true
  ReturnFromFinally:
    active: true
  TooGenericExceptionCaught:
    active: false
  SwallowedException:
    active: true
  ThrowingExceptionFromFinally:
    active: true
  ThrowingExceptionsWithoutMessageOrCause:
    active: true
  ThrowingNewInstanceOfSameException:
    active: true
  TooGenericExceptionThrown:
    active: true

naming:
  active: true
  ClassNaming:
    active: true
  ConstructorParameterNaming:
    active: true
  EnumNaming:
    active: true
  ForbiddenClassName:
    active: true
  FunctionMaxLength:
    active: true
    maximumFunctionNameLength: 35
  FunctionMinLength:
    active: true
  FunctionNaming:
    active: true
  FunctionParameterNaming:
    active: true
  MatchingDeclarationName:
    active: true
  MemberNameEqualsClassName:
    active: true
  ObjectPropertyNaming:
    active: true
  PackageNaming:
    active: true
  TopLevelPropertyNaming:
    active: true
  VariableMaxLength:
    active: true
    maximumVariableNameLength: 50
  VariableMinLength:
    active: true
  VariableNaming:
    active: true

performance:
  ArrayPrimitive:
    active: true
  ForEachOnRange:
    active: true
  SpreadOperator:
    active: true
  UnnecessaryTemporaryInstantiation:
    active: true

potential-bugs:
  active: true
  DuplicateCaseInWhenExpression:
    active: true
  EqualsAlwaysReturnsTrueOrFalse:
    active: true
  EqualsWithHashCodeExist:
    active: true
  ExplicitGarbageCollectionCall:
    active: true
  InvalidRange:
    active: true
  IteratorHasNextCallsNextMethod:
    active: true
  IteratorNotThrowingNoSuchElementException:
    active: true
  UnconditionalJumpStatementInLoop:
    active: true
  UnreachableCode:
    active: true
  UnsafeCallOnNullableType:
    active: true
  UnsafeCast:
    active: true
  UselessPostfixExpression:
    active: true
  WrongEqualsTypeParameter:
    active: true

style:
  active: true
  MaxLineLength:
    active: false
  CollapsibleIfStatements:
    active: true
  DataClassContainsFunctions:
    active: false
  EqualsNullCall:
    active: true
  ExplicitItLambdaParameter:
    active: true
  ExpressionBodySyntax:
    active: true
  ForbiddenComment:
    active: true
  ForbiddenImport:
    active: true
  ForbiddenVoid:
    active: true
  FunctionOnlyReturningConstant:
    active: true
  LoopWithTooManyJumpStatements:
    active: true
  MagicNumber:
    active: false
  MandatoryBracesIfStatements:
    active: true
  MayBeConst:
    active: true
  ModifierOrder:
    active: true
  NestedClassesVisibility:
    active: false
  NewLineAtEndOfFile:
    active: true
  NoTabs:
    active: true
  OptionalAbstractKeyword:
    active: true
  OptionalUnit:
    active: true
  OptionalWhenBraces:
    active: true
  PreferToOverPairSyntax:
    active: false
  ProtectedMemberInFinalClass:
    active: true
  RedundantVisibilityModifierRule:
    active: true
  ReturnCount:
    active: true
    max: 4
  SafeCast:
    active: true
  SerialVersionUIDInSerializableClass:
    active: true
  SpacingBetweenPackageAndImports:
    active: true
  ThrowsCount:
    active: true
  TrailingWhitespace:
    active: true
  UnnecessaryAbstractClass:
    active: true
    excludeAnnotatedClasses: "dagger.Module,android.arch.persistence.room.Dao"
  UnnecessaryApply:
    active: false # wait for fix
  UnnecessaryInheritance:
    active: true
  UnnecessaryLet:
    active: true
  UnnecessaryParentheses:
    active: true
  UntilInsteadOfRangeTo:
    active: true
  UnusedImports:
    active: false
  UnusedPrivateMember:
    active: true
  UseDataClass:
    active: true
  UtilityClassWithPublicConstructor:
    active: true
  VarCouldBeVal:
    active: true
  WildcardImport:
    active: true
    excludeImports: 'kotlinx.android.synthetic.*'


================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists


================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.useAndroidX=true
android.enableJetifier=true

### Maven publish configuration
GROUP=app.futured.hauler
VERSION_NAME=5.X.X-SNAPSHOT
POM_DESCRIPTION=Library with swipe to dismiss Activity gesture implementation.
POM_INCEPTION_YEAR=2018
POM_URL=https://github.com/futuredapp/hauler
POM_SCM_URL=https://github.com/futuredapp/hauler
POM_SCM_CONNECTION=scm:git:git://github.com/futuredapp/hauler.git
POM_SCM_DEV_CONNECTION=scm:git:ssh://github.com/futuredapp/hauler.git
POM_LICENCE_NAME=MIT
POM_LICENCE_URL=https://github.com/futuredapp/hauler/blob/master/LICENSE
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=futured
POM_DEVELOPER_NAME=Futured
POM_DEVELOPER_URL=https://futured.app
SONATYPE_HOST=DEFAULT
RELEASE_SIGNING_ENABLED=true


================================================
FILE: gradlew
================================================
#!/usr/bin/env sh

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn () {
    echo "$*"
}

die () {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
  NONSTOP* )
    nonstop=true
    ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
    JAVACMD=`cygpath --unix "$JAVACMD"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Escape application args
save () {
    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
    echo " "
}
APP_ARGS=$(save "$@")

# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
  cd "$(dirname "$0")"
fi

exec "$JAVACMD" "$@"


================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: sample/.gitignore
================================================
/build


================================================
FILE: sample/build.gradle.kts
================================================
import org.jetbrains.kotlin.config.KotlinCompilerVersion

plugins {
    id("com.android.application")
    id("kotlin-android")
    id("kotlin-android-extensions")
    id("kotlin-kapt")
}

android {
    compileSdkVersion(ProjectSettings.targetSdk)

    defaultConfig {
        applicationId = ProjectSettings.applicationId
        minSdkVersion(ProjectSettings.minSdk)
        targetSdkVersion(ProjectSettings.targetSdk)
    }

    sourceSets {
        getByName("main").java.srcDir("src/main/kotlin")
    }

    dataBinding {
        isEnabled = true
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }
}

dependencies {
    implementation(project(":core"))
    implementation(project(":databinding"))

    // Kotlin
    implementation(kotlin(Deps.Kotlin.stdlib, KotlinCompilerVersion.VERSION))
    implementation(Deps.AndroidX.appcompat)
}


================================================
FILE: sample/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="app.futured.haulersample">

    <application
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:name="app.futured.haulersample.MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name="app.futured.haulersample.draggable.SimpleActivity"
            android:theme="@style/AppTheme.Draggable" />

        <activity
            android:name="app.futured.haulersample.draggable.advanced.AdvancedActivity"
            android:theme="@style/AppTheme.Draggable" />

        <activity
            android:name="app.futured.haulersample.draggable.databinding.DatabindingActivity"
            android:theme="@style/AppTheme.Draggable" />

        <activity
            android:name="app.futured.haulersample.draggable.SimpleJavaActivity"
            android:theme="@style/AppTheme.Draggable" />

    </application>
</manifest>


================================================
FILE: sample/src/main/kotlin/app/futured/haulersample/MainActivity.kt
================================================
package app.futured.haulersample

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import app.futured.haulersample.draggable.SimpleActivity
import app.futured.haulersample.draggable.SimpleJavaActivity
import app.futured.haulersample.draggable.advanced.AdvancedActivity
import app.futured.haulersample.draggable.databinding.DatabindingActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        startCommonButton.setOnClickListener {
            startActivity(SimpleActivity.getStartIntent(this))
        }

        startAdvancedButton.setOnClickListener {
            startActivity(AdvancedActivity.getStartIntent(this))
        }

        startBindingButton.setOnClickListener {
            startActivity(DatabindingActivity.getStartIntent(this))
        }

        startJavaCommonButton.setOnClickListener {
            startActivity(SimpleJavaActivity.getStartIntent(this))
        }
    }
}


================================================
FILE: sample/src/main/kotlin/app/futured/haulersample/draggable/SimpleActivity.kt
================================================
package app.futured.haulersample.draggable

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import app.futured.hauler.setOnDragActivityListener
import app.futured.hauler.setOnDragDismissedListener
import app.futured.haulersample.R
import kotlinx.android.synthetic.main.activity_simple.*

class SimpleActivity : AppCompatActivity() {

    companion object {
        fun getStartIntent(context: Context): Intent = Intent(context, SimpleActivity::class.java)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_simple)

        commonHaulerView.setOnDragDismissedListener {
            finish()
        }

        commonHaulerView.setOnDragActivityListener { elasticOffset, rawOffset ->
            Log.d("SimpleActivity", "elasticOffset: $elasticOffset, rawOffset: $rawOffset")
        }
    }
}


================================================
FILE: sample/src/main/kotlin/app/futured/haulersample/draggable/SimpleJavaActivity.java
================================================
package app.futured.haulersample.draggable;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import org.jetbrains.annotations.NotNull;

import androidx.annotation.Nullable;
import app.futured.hauler.DragDirection;
import app.futured.hauler.HaulerView;
import app.futured.hauler.OnDragDismissedListener;
import app.futured.haulersample.R;

public class SimpleJavaActivity extends Activity {

    public static Intent getStartIntent(Context context) {
        return new Intent(context, SimpleJavaActivity.class);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);

        HaulerView hv = findViewById(R.id.commonHaulerView);
        hv.setOnDragDismissedListener(new OnDragDismissedListener() {
            @Override
            public void onDismissed(@NotNull DragDirection dragDirection) {
                finish();
            }
        });
    }
}


================================================
FILE: sample/src/main/kotlin/app/futured/haulersample/draggable/advanced/AdvancedActivity.kt
================================================
package app.futured.haulersample.draggable.advanced

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import app.futured.hauler.DragDirection
import app.futured.hauler.setOnDragDismissedListener
import app.futured.haulersample.R
import kotlinx.android.synthetic.main.activity_advanced.*

class AdvancedActivity : AppCompatActivity() {

    companion object {
        fun getStartIntent(context: Context): Intent = Intent(context, AdvancedActivity::class.java)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_advanced)

        advancedHaulerView.setOnDragDismissedListener { dragDirection ->
            Toast.makeText(this, "Dismissed in direction: $dragDirection", Toast.LENGTH_SHORT).show()
            when (dragDirection) {
                DragDirection.DOWN -> {
                    finish()
                    overridePendingTransition(0, R.anim.anim_slide_down)
                }
                DragDirection.UP -> {
                    finish()
                    overridePendingTransition(0, R.anim.anim_slide_up)
                }
            }
        }
        ignoredAreaView.setScrollViewParent(scrollViewParent)
    }
}


================================================
FILE: sample/src/main/kotlin/app/futured/haulersample/draggable/advanced/IgnoredAreaView.kt
================================================
package app.futured.haulersample.draggable.advanced

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.appcompat.widget.AppCompatTextView
import app.futured.hauler.LockableNestedScrollView

class IgnoredAreaView @kotlin.jvm.JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatTextView(context, attrs, defStyleAttr) {

    private var parentScrollView: LockableNestedScrollView? = null

    fun setScrollViewParent(parentScrollView: LockableNestedScrollView) {
        this.parentScrollView = parentScrollView
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        return when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                parentScrollView?.setScrollEnabled(false)
                true
            }

            MotionEvent.ACTION_UP -> {
                parentScrollView?.setScrollEnabled(true)
                true
            }
            else -> false
        }
    }
}


================================================
FILE: sample/src/main/kotlin/app/futured/haulersample/draggable/databinding/DatabindingActivity.kt
================================================
package app.futured.haulersample.draggable.databinding

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import app.futured.hauler.DragDirection
import app.futured.haulersample.R
import app.futured.haulersample.databinding.ActivityDatabindingBinding
import kotlinx.android.synthetic.main.activity_databinding.*

class DatabindingActivity : AppCompatActivity(), DatabindingActivityView {
    companion object {
        fun getStartIntent(context: Context): Intent = Intent(context, DatabindingActivity::class.java)
    }

    lateinit var binding: ActivityDatabindingBinding

    private var state = DatabindingActivityState(true)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_databinding)
        refreshBinding()

        dragEnabledCheck.setOnCheckedChangeListener { _, isChecked ->
            state = state.copy(isDragEnabled = isChecked)
            refreshBinding()
        }
    }

    private fun refreshBinding() {
        binding.viewState = state
        binding.view = this
        binding.executePendingBindings()
    }

    override fun onDragDismissed(dragDirection: DragDirection) {
        finish()
    }
}


================================================
FILE: sample/src/main/kotlin/app/futured/haulersample/draggable/databinding/DatabindingActivityState.kt
================================================
package app.futured.haulersample.draggable.databinding

data class DatabindingActivityState(
    val isDragEnabled: Boolean
)


================================================
FILE: sample/src/main/kotlin/app/futured/haulersample/draggable/databinding/DatabindingActivityView.kt
================================================
package app.futured.haulersample.draggable.databinding

import app.futured.hauler.DragDirection

interface DatabindingActivityView {
    fun onDragDismissed(dragDirection: DragDirection)
}


================================================
FILE: sample/src/main/res/anim/anim_slide_down.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromYDelta="0"
            android:toYDelta="100%p"/>
</set>


================================================
FILE: sample/src/main/res/anim/anim_slide_up.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromYDelta="0"
            android:toYDelta="-100%p"/>
</set>


================================================
FILE: sample/src/main/res/drawable/ic_launcher_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<vector
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:height="108dp"
        android:width="108dp"
        android:viewportHeight="108"
        android:viewportWidth="108">
    <path android:fillColor="#008577"
          android:pathData="M0,0h108v108h-108z"/>
    <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,29L89,29"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,39L89,39"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,49L89,49"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,59L89,59"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,69L89,69"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M19,79L89,79"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M29,19L29,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M39,19L39,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M49,19L49,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M59,19L59,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M69,19L69,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
    <path android:fillColor="#00000000" android:pathData="M79,19L79,89"
          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>


================================================
FILE: sample/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:aapt="http://schemas.android.com/aapt"
        android:width="108dp"
        android:height="108dp"
        android:viewportHeight="108"
        android:viewportWidth="108">
    <path
            android:fillType="evenOdd"
            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"
            android:strokeColor="#00000000"
            android:strokeWidth="1">
        <aapt:attr name="android:fillColor">
            <gradient
                    android:endX="78.5885"
                    android:endY="90.9159"
                    android:startX="48.7653"
                    android:startY="61.0927"
                    android:type="linear">
                <item
                        android:color="#44000000"
                        android:offset="0.0"/>
                <item
                        android:color="#00000000"
                        android:offset="1.0"/>
            </gradient>
        </aapt:attr>
    </path>
    <path
            android:fillColor="#FFFFFF"
            android:fillType="nonZero"
            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"
            android:strokeColor="#00000000"
            android:strokeWidth="1"/>
</vector>


================================================
FILE: sample/src/main/res/layout/activity_advanced.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<app.futured.hauler.HaulerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        tools:context="app.futured.haulersample.draggable.advanced.AdvancedActivity"
        android:id="@+id/advancedHaulerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        app:dragUpEnabled="true"
        app:dragElasticity="0.4"
        app:dragDismissScale="0.6"
        app:fadeSystemBars="false"
        app:dragDismissDistance="200dp">

    <app.futured.hauler.LockableNestedScrollView
            android:id="@+id/scrollViewParent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true">

        <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:gravity="center">

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:text="@string/swipe_to_dismiss"/>

            <app.futured.haulersample.draggable.advanced.IgnoredAreaView
                    android:id="@+id/ignoredAreaView"
                    android:layout_width="200dp"
                    android:layout_marginTop="20dp"
                    android:layout_height="200dp"
                    android:background="@color/colorPrimary"
                    android:text="@string/ignored_area_text"
                    android:gravity="center"
                    android:textColor="@android:color/white"/>

        </LinearLayout>

    </app.futured.hauler.LockableNestedScrollView>

</app.futured.hauler.HaulerView>



================================================
FILE: sample/src/main/res/layout/activity_databinding.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
                name="viewState"
                type="app.futured.haulersample.draggable.databinding.DatabindingActivityState"/>

        <variable
                name="view"
                type="app.futured.haulersample.draggable.databinding.DatabindingActivityView"/>
    </data>

    <app.futured.hauler.HaulerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:orientation="vertical"
            android:background="@android:color/white"
            app:isDragEnabled="@{viewState.dragEnabled}"
            app:isDragUpEnabled="@{true}"
            app:onDragDismissedListener="@{(dragDirection) -> view.onDragDismissed(dragDirection)}">

        <app.futured.hauler.LockableNestedScrollView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fillViewport="true"
                app:isScrollable="@{true}">

            <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="20dp">

                <CheckBox
                        android:id="@+id/dragEnabledCheck"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/drag_enabled"
                        android:checked="true"/>

                <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="@string/swipe_to_dismiss"/>

            </FrameLayout>

        </app.futured.hauler.LockableNestedScrollView>

    </app.futured.hauler.HaulerView>

</layout>


================================================
FILE: sample/src/main/res/layout/activity_main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        tools:context="app.futured.haulersample.MainActivity">

    <Button
            android:id="@+id/startCommonButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/start_simple"
            android:layout_gravity="center"/>

    <Button
            android:id="@+id/startAdvancedButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/start_advanced"
            android:layout_gravity="center" />

    <Button
            android:id="@+id/startBindingButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/start_binding"
            android:layout_gravity="center" />

    <Button
            android:id="@+id/startJavaCommonButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/start_simple_java"
            android:layout_gravity="center" />

</LinearLayout>


================================================
FILE: sample/src/main/res/layout/activity_simple.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<app.futured.hauler.HaulerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        tools:context="app.futured.haulersample.draggable.SimpleActivity"
        android:id="@+id/commonHaulerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white">

    <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true">

        <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:text="@string/swipe_to_dismiss"/>

        </FrameLayout>

    </androidx.core.widget.NestedScrollView>

</app.futured.hauler.HaulerView>



================================================
FILE: sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>


================================================
FILE: sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>


================================================
FILE: sample/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="dark_gray">#99323232</color>
</resources>


================================================
FILE: sample/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">Hauler</string>
    <string name="start_simple">Start Simple Activity</string>
    <string name="start_simple_java">Start Simple Java Activity</string>
    <string name="start_advanced">Start Advanced Activity</string>
    <string name="start_binding">Start Binding Activity</string>
    <string name="swipe_to_dismiss">Swipe down to dismiss</string>
    <string name="ignored_area_text">Ignored area</string>
    <string name="drag_enabled">Drag Enabled</string>
</resources>


================================================
FILE: sample/src/main/res/values/styles.xml
================================================
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.Draggable" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@color/dark_gray</item>
    </style>

</resources>


================================================
FILE: settings.gradle.kts
================================================
rootProject.buildFileName = "build.gradle.kts"

include(":core", ":databinding", ":sample")
Download .txt
gitextract_1jcvn5xr/

├── .editorconfig
├── .github/
│   └── workflows/
│       ├── publish_release.yml
│       ├── publish_snapshot.yml
│       └── pull_request.yml
├── .gitignore
├── Dangerfile
├── Gemfile
├── LICENSE
├── README.md
├── build.gradle.kts
├── buildSrc/
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           └── kotlin/
│               ├── Deps.kt
│               ├── ProjectSettings.kt
│               ├── Versions.kt
│               └── app/
│                   └── futured/
│                       └── hauler/
│                           └── DependencyUpdates.kt
├── core/
│   ├── .gitignore
│   ├── build.gradle.kts
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── kotlin/
│           │   └── app/
│           │       └── futured/
│           │           └── hauler/
│           │               ├── ColorUtils.kt
│           │               ├── DragDirection.kt
│           │               ├── HaulerView.kt
│           │               ├── HaulerViewExtensions.kt
│           │               ├── LockableNestedScrollView.kt
│           │               ├── OnDragActivityListener.kt
│           │               ├── OnDragDismissedListener.kt
│           │               └── SystemBarsFader.kt
│           └── res/
│               └── values/
│                   ├── attrs_hauler_view.xml
│                   └── dimens.xml
├── databinding/
│   ├── .gitignore
│   ├── build.gradle.kts
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── kotlin/
│               └── app/
│                   └── futured/
│                       └── hauler/
│                           └── databinding/
│                               ├── IsDragEnabledAdapter.kt
│                               ├── IsDragUpEnabledAdapter.kt
│                               ├── IsScrollableAdapter.kt
│                               └── OnDragDismissedListenerAdapter.kt
├── detekt.yml
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── sample/
│   ├── .gitignore
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── kotlin/
│           │   └── app/
│           │       └── futured/
│           │           └── haulersample/
│           │               ├── MainActivity.kt
│           │               └── draggable/
│           │                   ├── SimpleActivity.kt
│           │                   ├── SimpleJavaActivity.java
│           │                   ├── advanced/
│           │                   │   ├── AdvancedActivity.kt
│           │                   │   └── IgnoredAreaView.kt
│           │                   └── databinding/
│           │                       ├── DatabindingActivity.kt
│           │                       ├── DatabindingActivityState.kt
│           │                       └── DatabindingActivityView.kt
│           └── res/
│               ├── anim/
│               │   ├── anim_slide_down.xml
│               │   └── anim_slide_up.xml
│               ├── drawable/
│               │   └── ic_launcher_background.xml
│               ├── drawable-v24/
│               │   └── ic_launcher_foreground.xml
│               ├── layout/
│               │   ├── activity_advanced.xml
│               │   ├── activity_databinding.xml
│               │   ├── activity_main.xml
│               │   └── activity_simple.xml
│               ├── mipmap-anydpi-v26/
│               │   ├── ic_launcher.xml
│               │   └── ic_launcher_round.xml
│               └── values/
│                   ├── colors.xml
│                   ├── strings.xml
│                   └── styles.xml
└── settings.gradle.kts
Download .txt
SYMBOL INDEX (3 symbols across 1 files)

FILE: sample/src/main/kotlin/app/futured/haulersample/draggable/SimpleJavaActivity.java
  class SimpleJavaActivity (line 16) | public class SimpleJavaActivity extends Activity {
    method getStartIntent (line 18) | public static Intent getStartIntent(Context context) {
    method onCreate (line 22) | @Override
Condensed preview — 68 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (80K chars).
[
  {
    "path": ".editorconfig",
    "chars": 35,
    "preview": "[*.{kt,kts}]\n\nmax_line_length=130\n\n"
  },
  {
    "path": ".github/workflows/publish_release.yml",
    "chars": 957,
    "preview": "name: Publish Release\n\non:\n  release:\n    types: [published]\n\njobs:\n  release:\n    name: Release Publish\n    runs-on: [u"
  },
  {
    "path": ".github/workflows/publish_snapshot.yml",
    "chars": 1311,
    "preview": "name: Publish Snapshot\non:\n  push:\n    branches:\n      master\n\njobs:\n  master:\n    name: Snapshot Publish\n    runs-on: ["
  },
  {
    "path": ".github/workflows/pull_request.yml",
    "chars": 859,
    "preview": "name: Check PR\non: [pull_request]\n\njobs:\n  pr:\n    name: PR check\n    runs-on: [ubuntu-latest]\n    env:\n      DANGER_GIT"
  },
  {
    "path": ".gitignore",
    "chars": 107,
    "preview": "*.iml\n.gradle\n/local.properties\n/.idea/*\n/buildSrc/build/*\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n"
  },
  {
    "path": "Dangerfile",
    "chars": 933,
    "preview": "is_pr_big = git.insertions > 500\nhas_correct_prefix = github.branch_for_head.match(/^(feature|hotfix|fix|release|houseke"
  },
  {
    "path": "Gemfile",
    "chars": 87,
    "preview": "source 'https://rubygems.org'\n\ngem 'danger-commit_lint'\ngem 'danger-checkstyle_format'\n"
  },
  {
    "path": "LICENSE",
    "chars": 1076,
    "preview": "MIT License\n\nCopyright (c) 2020 Futured apps s.r.o.\n\nPermission is hereby granted, free of charge, to any person obtaini"
  },
  {
    "path": "README.md",
    "chars": 5036,
    "preview": "<img align=\"right\" src=\"images/Hauler.svg\">\n\n# Hauler\n\n[![Maven Central](https://img.shields.io/maven-central/v/app.futu"
  },
  {
    "path": "build.gradle.kts",
    "chars": 1746,
    "preview": "import org.jlleitschuh.gradle.ktlint.reporter.ReporterType\n\nbuildscript {\n    repositories {\n        google()\n        jc"
  },
  {
    "path": "buildSrc/build.gradle.kts",
    "chars": 243,
    "preview": "plugins {\n    `kotlin-dsl`\n}\n\nrepositories {\n    jcenter()\n}\n\ndependencies {\n    implementation(\"com.github.ben-manes:gr"
  },
  {
    "path": "buildSrc/src/main/kotlin/Deps.kt",
    "chars": 806,
    "preview": "object Deps {\n    const val gradlePlugin = \"com.android.tools.build:gradle:${Versions.gradle}\"\n\n    object Plugins {\n   "
  },
  {
    "path": "buildSrc/src/main/kotlin/ProjectSettings.kt",
    "chars": 133,
    "preview": "object ProjectSettings {\n    const val applicationId = \"app.futured.hauler\"\n    const val targetSdk = 32\n    const val m"
  },
  {
    "path": "buildSrc/src/main/kotlin/Versions.kt",
    "chars": 402,
    "preview": "object Versions {\n    // gradle\n    const val gradle = \"7.2.1\"\n\n    // plugins\n    const val detekt = \"1.20.0\"\n    const"
  },
  {
    "path": "buildSrc/src/main/kotlin/app/futured/hauler/DependencyUpdates.kt",
    "chars": 696,
    "preview": "package app.futured.hauler\n\nimport com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask\n\nabstract class Dep"
  },
  {
    "path": "core/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "core/build.gradle.kts",
    "chars": 871,
    "preview": "import org.jetbrains.kotlin.config.KotlinCompilerVersion\n\nplugins {\n    id(\"com.android.library\")\n    id(\"kotlin-android"
  },
  {
    "path": "core/gradle.properties",
    "chars": 140,
    "preview": "POM_NAME=Library containing custom layout which enables to easily create swipe to dismiss Activity\nPOM_ARTIFACT_ID=haule"
  },
  {
    "path": "core/src/main/AndroidManifest.xml",
    "chars": 41,
    "preview": "<manifest package=\"app.futured.hauler\"/>\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/ColorUtils.kt",
    "chars": 341,
    "preview": "package app.futured.hauler\n\nimport androidx.annotation.CheckResult\nimport androidx.annotation.ColorInt\nimport androidx.a"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/DragDirection.kt",
    "chars": 70,
    "preview": "package app.futured.hauler\n\nenum class DragDirection {\n    UP, DOWN\n}\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/HaulerView.kt",
    "chars": 9208,
    "preview": "package app.futured.hauler\n\nimport android.app.Activity\nimport android.content.Context\nimport android.util.AttributeSet\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/HaulerViewExtensions.kt",
    "chars": 697,
    "preview": "package app.futured.hauler\n\nfun HaulerView.setOnDragDismissedListener(onDragDismissedListener: (DragDirection) -> Unit) "
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/LockableNestedScrollView.kt",
    "chars": 872,
    "preview": "package app.futured.hauler\n\nimport android.content.Context\nimport android.util.AttributeSet\nimport android.view.MotionEv"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/OnDragActivityListener.kt",
    "chars": 126,
    "preview": "package app.futured.hauler\n\ninterface OnDragActivityListener {\n    fun onDrag(elasticOffsetPixels: Float, rawOffset: Flo"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/OnDragDismissedListener.kt",
    "chars": 116,
    "preview": "package app.futured.hauler\n\ninterface OnDragDismissedListener {\n    fun onDismissed(dragDirection: DragDirection)\n}\n"
  },
  {
    "path": "core/src/main/kotlin/app/futured/hauler/SystemBarsFader.kt",
    "chars": 1128,
    "preview": "package app.futured.hauler\n\nimport android.app.Activity\nimport android.graphics.Color\n\ninternal class SystemBarsFader(pr"
  },
  {
    "path": "core/src/main/res/values/attrs_hauler_view.xml",
    "chars": 432,
    "preview": "<resources>\n\n    <declare-styleable name=\"HaulerView\">\n        <attr name=\"dragDismissDistance\" format=\"dimension\"/>\n   "
  },
  {
    "path": "core/src/main/res/values/dimens.xml",
    "chars": 126,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <dimen name=\"default_drag_dismiss_distance\">100dp</dimen>\n</resou"
  },
  {
    "path": "databinding/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "databinding/build.gradle.kts",
    "chars": 904,
    "preview": "import org.jetbrains.kotlin.config.KotlinCompilerVersion\n\nplugins {\n    id(\"com.android.library\")\n    id(\"kotlin-android"
  },
  {
    "path": "databinding/gradle.properties",
    "chars": 95,
    "preview": "POM_NAME=Databinding extensions for core library\nPOM_ARTIFACT_ID=databinding\nPOM_PACKAGING=aar\n"
  },
  {
    "path": "databinding/src/main/AndroidManifest.xml",
    "chars": 53,
    "preview": "<manifest package=\"app.futured.hauler.databinding\"/>\n"
  },
  {
    "path": "databinding/src/main/kotlin/app/futured/hauler/databinding/IsDragEnabledAdapter.kt",
    "chars": 254,
    "preview": "package app.futured.hauler.databinding\n\nimport androidx.databinding.BindingAdapter\nimport app.futured.hauler.HaulerView\n"
  },
  {
    "path": "databinding/src/main/kotlin/app/futured/hauler/databinding/IsDragUpEnabledAdapter.kt",
    "chars": 264,
    "preview": "package app.futured.hauler.databinding\n\nimport androidx.databinding.BindingAdapter\nimport app.futured.hauler.HaulerView\n"
  },
  {
    "path": "databinding/src/main/kotlin/app/futured/hauler/databinding/IsScrollableAdapter.kt",
    "chars": 275,
    "preview": "package app.futured.hauler.databinding\n\nimport androidx.databinding.BindingAdapter\nimport app.futured.hauler.LockableNes"
  },
  {
    "path": "databinding/src/main/kotlin/app/futured/hauler/databinding/OnDragDismissedListenerAdapter.kt",
    "chars": 417,
    "preview": "package app.futured.hauler.databinding\n\nimport androidx.databinding.BindingAdapter\nimport app.futured.hauler.HaulerView\n"
  },
  {
    "path": "detekt.yml",
    "chars": 4905,
    "preview": "build:\n  maxIssues: 100\n\ncomplexity:\n  active: true\n  ComplexCondition:\n    active: true\n  ComplexMethod:\n    active: tr"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 200,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
  },
  {
    "path": "gradle.properties",
    "chars": 1546,
    "preview": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will ov"
  },
  {
    "path": "gradlew",
    "chars": 5296,
    "preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up"
  },
  {
    "path": "gradlew.bat",
    "chars": 2260,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "sample/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "sample/build.gradle.kts",
    "chars": 1013,
    "preview": "import org.jetbrains.kotlin.config.KotlinCompilerVersion\n\nplugins {\n    id(\"com.android.application\")\n    id(\"kotlin-and"
  },
  {
    "path": "sample/src/main/AndroidManifest.xml",
    "chars": 1436,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/MainActivity.kt",
    "chars": 1123,
    "preview": "package app.futured.haulersample\n\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport app.fu"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/SimpleActivity.kt",
    "chars": 1000,
    "preview": "package app.futured.haulersample.draggable\n\nimport android.content.Context\nimport android.content.Intent\nimport android."
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/SimpleJavaActivity.java",
    "chars": 1055,
    "preview": "package app.futured.haulersample.draggable;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/advanced/AdvancedActivity.kt",
    "chars": 1352,
    "preview": "package app.futured.haulersample.draggable.advanced\n\nimport android.content.Context\nimport android.content.Intent\nimport"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/advanced/IgnoredAreaView.kt",
    "chars": 1141,
    "preview": "package app.futured.haulersample.draggable.advanced\n\nimport android.annotation.SuppressLint\nimport android.content.Conte"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/databinding/DatabindingActivity.kt",
    "chars": 1381,
    "preview": "package app.futured.haulersample.draggable.databinding\n\nimport android.content.Context\nimport android.content.Intent\nimp"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/databinding/DatabindingActivityState.kt",
    "chars": 126,
    "preview": "package app.futured.haulersample.draggable.databinding\n\ndata class DatabindingActivityState(\n    val isDragEnabled: Bool"
  },
  {
    "path": "sample/src/main/kotlin/app/futured/haulersample/draggable/databinding/DatabindingActivityView.kt",
    "chars": 189,
    "preview": "package app.futured.haulersample.draggable.databinding\n\nimport app.futured.hauler.DragDirection\n\ninterface DatabindingAc"
  },
  {
    "path": "sample/src/main/res/anim/anim_slide_down.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <translate\n "
  },
  {
    "path": "sample/src/main/res/anim/anim_slide_up.xml",
    "chars": 271,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <translate\n "
  },
  {
    "path": "sample/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 4887,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      "
  },
  {
    "path": "sample/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1969,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:aapt=\"http://schemas.android.com/aapt\"\n"
  },
  {
    "path": "sample/src/main/res/layout/activity_advanced.xml",
    "chars": 2021,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<app.futured.hauler.HaulerView\n        xmlns:android=\"http://schemas.android.com/"
  },
  {
    "path": "sample/src/main/res/layout/activity_databinding.xml",
    "chars": 2098,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:"
  },
  {
    "path": "sample/src/main/res/layout/activity_main.xml",
    "chars": 1442,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
  },
  {
    "path": "sample/src/main/res/layout/activity_simple.xml",
    "chars": 1114,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<app.futured.hauler.HaulerView\n        xmlns:android=\"http://schemas.android.com/"
  },
  {
    "path": "sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 271,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 271,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "sample/src/main/res/values/colors.xml",
    "chars": 254,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#008577</color>\n    <color name=\"color"
  },
  {
    "path": "sample/src/main/res/values/strings.xml",
    "chars": 517,
    "preview": "<resources>\n    <string name=\"app_name\">Hauler</string>\n    <string name=\"start_simple\">Start Simple Activity</string>\n "
  },
  {
    "path": "sample/src/main/res/values/styles.xml",
    "chars": 853,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
  },
  {
    "path": "settings.gradle.kts",
    "chars": 92,
    "preview": "rootProject.buildFileName = \"build.gradle.kts\"\n\ninclude(\":core\", \":databinding\", \":sample\")\n"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the thefuntasty/hauler GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 68 files (69.6 KB), approximately 20.1k tokens, and a symbol index with 3 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!