Full Code of Crdzbird/floaty_chathead for AI

master 28dfa9c02145 cached
96 files
200.6 KB
52.9k tokens
59 symbols
1 requests
Download .txt
Showing preview only (226K chars total). Download the full file or copy to clipboard to get everything.
Repository: Crdzbird/floaty_chathead
Branch: master
Commit: 28dfa9c02145
Files: 96
Total size: 200.6 KB

Directory structure:
gitextract_z7wqmmkf/

├── .gitignore
├── .idea/
│   ├── codeStyles/
│   │   └── Project.xml
│   ├── kotlinc.xml
│   ├── libraries/
│   │   ├── Dart_SDK.xml
│   │   ├── Flutter_Plugins.xml
│   │   └── KotlinJavaRuntime.xml
│   ├── modules.xml
│   ├── runConfigurations/
│   │   └── example_lib_main_dart.xml
│   └── workspace.xml
├── .metadata
├── .vscode/
│   └── launch.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── android/
│   ├── .gitignore
│   ├── .idea/
│   │   ├── .name
│   │   ├── assetWizardSettings.xml
│   │   ├── caches/
│   │   │   └── build_file_checksums.ser
│   │   ├── codeStyles/
│   │   │   └── Project.xml
│   │   ├── gradle.xml
│   │   ├── jarRepositories.xml
│   │   ├── misc.xml
│   │   ├── modules.xml
│   │   ├── runConfigurations.xml
│   │   └── vcs.xml
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       ├── gradle-wrapper.jar
│   │       └── gradle-wrapper.properties
│   ├── gradle.properties
│   ├── gradlew
│   ├── gradlew.bat
│   ├── settings.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── ni/
│           │       └── devotion/
│           │           └── floaty_head/
│           │               └── FloatFragment.kt
│           ├── kotlin/
│           │   └── ni/
│           │       └── devotion/
│           │           └── floaty_head/
│           │               ├── FloatyHeadPlugin.kt
│           │               ├── MainActivity.kt
│           │               ├── floating_chathead/
│           │               │   ├── ChatHead.kt
│           │               │   ├── ChatHeads.kt
│           │               │   ├── Close.kt
│           │               │   ├── SpringConfig.kt
│           │               │   └── WindowManagerHelper.kt
│           │               ├── models/
│           │               │   ├── Decoration.kt
│           │               │   ├── Margin.kt
│           │               │   └── Padding.kt
│           │               ├── services/
│           │               │   ├── FloatyContentJobService.kt
│           │               │   └── FloatyIconService.kt
│           │               ├── utils/
│           │               │   ├── Commons.kt
│           │               │   ├── Constants.kt
│           │               │   ├── ImageHelper.kt
│           │               │   ├── Managment.kt
│           │               │   ├── NumberUtils.kt
│           │               │   └── UiBuilder.kt
│           │               └── views/
│           │                   ├── BodyView.kt
│           │                   ├── FooterView.kt
│           │                   ├── HeaderView.kt
│           │                   └── RowView.kt
│           └── res/
│               ├── drawable/
│               │   ├── gradient_bg.xml
│               │   └── ic_chathead.xml
│               ├── layout/
│               │   └── fragment_float.xml
│               └── values/
│                   ├── colors.xml
│                   ├── strings.xml
│                   └── styles.xml
├── example/
│   ├── .gitignore
│   ├── .metadata
│   ├── README.md
│   ├── android/
│   │   ├── .gitignore
│   │   ├── app/
│   │   │   ├── build.gradle
│   │   │   └── src/
│   │   │       ├── debug/
│   │   │       │   └── AndroidManifest.xml
│   │   │       ├── main/
│   │   │       │   ├── AndroidManifest.xml
│   │   │       │   ├── kotlin/
│   │   │       │   │   └── ni/
│   │   │       │   │       └── devotion/
│   │   │       │   │           └── floaty_head_example/
│   │   │       │   │               ├── Application.kt
│   │   │       │   │               └── MainActivity.kt
│   │   │       │   └── res/
│   │   │       │       ├── drawable/
│   │   │       │       │   └── launch_background.xml
│   │   │       │       └── values/
│   │   │       │           └── styles.xml
│   │   │       └── profile/
│   │   │           └── AndroidManifest.xml
│   │   ├── build.gradle
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       └── gradle-wrapper.properties
│   │   ├── gradle.properties
│   │   ├── settings.gradle
│   │   └── settings_aar.gradle
│   ├── lib/
│   │   └── main.dart
│   ├── pubspec.yaml
│   └── test/
│       └── widget_test.dart
├── floaty_head.iml
├── lib/
│   ├── floaty_head.dart
│   ├── models/
│   │   ├── floaty_head_body.dart
│   │   ├── floaty_head_button.dart
│   │   ├── floaty_head_decoration.dart
│   │   ├── floaty_head_footer.dart
│   │   ├── floaty_head_header.dart
│   │   ├── floaty_head_margin.dart
│   │   ├── floaty_head_padding.dart
│   │   └── floaty_head_text.dart
│   └── utils/
│       └── commons.dart
├── pubspec.yaml
└── test/
    └── floaty_head_test.dart

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

================================================
FILE: .gitignore
================================================
.DS_Store
.dart_tool/

.packages
.pub/

build/


================================================
FILE: .idea/codeStyles/Project.xml
================================================
<component name="ProjectCodeStyleConfiguration">
  <code_scheme name="Project" version="173">
    <codeStyleSettings language="XML">
      <indentOptions>
        <option name="CONTINUATION_INDENT_SIZE" value="4" />
      </indentOptions>
      <arrangement>
        <rules>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>xmlns:android</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>xmlns:.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
              <order>BY_NAME</order>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*:id</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*:name</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>name</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>style</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
              <order>BY_NAME</order>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
                </AND>
              </match>
              <order>ANDROID_ATTRIBUTE_ORDER</order>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>.*</XML_NAMESPACE>
                </AND>
              </match>
              <order>BY_NAME</order>
            </rule>
          </section>
        </rules>
      </arrangement>
    </codeStyleSettings>
  </code_scheme>
</component>

================================================
FILE: .idea/kotlinc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="Kotlin2JvmCompilerArguments">
    <option name="jvmTarget" value="1.8" />
  </component>
</project>

================================================
FILE: .idea/libraries/Dart_SDK.xml
================================================
<component name="libraryTable">
  <library name="Dart SDK">
    <CLASSES>
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/async" />
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/collection" />
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/convert" />
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/core" />
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/developer" />
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/html" />
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/io" />
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/isolate" />
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/math" />
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/mirrors" />
      <root url="file:///usr/local/flutter/bin/cache/dart-sdk/lib/typed_data" />
    </CLASSES>
    <JAVADOC />
    <SOURCES />
  </library>
</component>

================================================
FILE: .idea/libraries/Flutter_Plugins.xml
================================================
<component name="libraryTable">
  <library name="Flutter Plugins" type="FlutterPluginsLibraryType">
    <CLASSES>
      <root url="file://$PROJECT_DIR$" />
    </CLASSES>
    <JAVADOC />
    <SOURCES />
  </library>
</component>

================================================
FILE: .idea/libraries/KotlinJavaRuntime.xml
================================================
<component name="libraryTable">
  <library name="KotlinJavaRuntime">
    <CLASSES>
      <root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib.jar!/" />
      <root url="jar://$PROJECT_DIR$/lib/kotlin-reflect.jar!/" />
      <root url="jar://$PROJECT_DIR$/lib/kotlin-test.jar!/" />
      <root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-jdk7.jar!/" />
      <root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-jdk8.jar!/" />
    </CLASSES>
    <JAVADOC />
    <SOURCES>
      <root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-sources.jar!/" />
      <root url="jar://$PROJECT_DIR$/lib/kotlin-reflect-sources.jar!/" />
      <root url="jar://$PROJECT_DIR$/lib/kotlin-test-sources.jar!/" />
      <root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-jdk7-sources.jar!/" />
      <root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-jdk8-sources.jar!/" />
    </SOURCES>
  </library>
</component>

================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ProjectModuleManager">
    <modules>
      <module fileurl="file://$PROJECT_DIR$/floaty_head.iml" filepath="$PROJECT_DIR$/floaty_head.iml" />
      <module fileurl="file://$PROJECT_DIR$/android/floaty_head_android.iml" filepath="$PROJECT_DIR$/android/floaty_head_android.iml" />
      <module fileurl="file://$PROJECT_DIR$/example/android/floaty_head_example_android.iml" filepath="$PROJECT_DIR$/example/android/floaty_head_example_android.iml" />
    </modules>
  </component>
</project>


================================================
FILE: .idea/runConfigurations/example_lib_main_dart.xml
================================================
<component name="ProjectRunConfigurationManager">
  <configuration default="false" name="example/lib/main.dart" type="FlutterRunConfigurationType" factoryName="Flutter">
    <option name="filePath" value="$PROJECT_DIR$/example/lib/main.dart" />
    <method />
  </configuration>
</component>

================================================
FILE: .idea/workspace.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ChangeListManager">
    <list default="true" id="2dcf5f1d-20d8-41af-b667-14e6b22c5dda" name="Default Changelist" comment="" />
    <option name="SHOW_DIALOG" value="false" />
    <option name="HIGHLIGHT_CONFLICTS" value="true" />
    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
    <option name="LAST_RESOLUTION" value="IGNORE" />
  </component>
  <component name="ExecutionTargetManager" SELECTED_TARGET="27abde15dc217ece" />
  <component name="FileTemplateManagerImpl">
    <option name="RECENT_TEMPLATES">
      <list>
        <option value="Kotlin Class" />
      </list>
    </option>
  </component>
  <component name="ProjectId" id="1ghpx5JiqLL4CNwOkv4sxh7sTZq" />
  <component name="ProjectViewState">
    <option name="hideEmptyMiddlePackages" value="true" />
    <option name="showExcludedFiles" value="true" />
    <option name="showLibraryContents" value="true" />
  </component>
  <component name="PropertiesComponent">
    <property name="dart.analysis.tool.window.force.activate" value="false" />
    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
    <property name="show.migrate.to.gradle.popup" value="false" />
  </component>
  <component name="RecentsManager">
    <key name="CopyFile.RECENT_KEYS">
      <recent name="$PROJECT_DIR$/android/src/main/kotlin/ni/devotion/floaty_head" />
    </key>
  </component>
  <component name="SvnConfiguration">
    <configuration />
  </component>
  <component name="TaskManager">
    <task active="true" id="Default" summary="Default task">
      <changelist id="2dcf5f1d-20d8-41af-b667-14e6b22c5dda" name="Default Changelist" comment="" />
      <created>1598576921664</created>
      <option name="number" value="Default" />
      <option name="presentableId" value="Default" />
      <updated>1598576921664</updated>
    </task>
    <servers />
  </component>
  <component name="WindowStateProjectService">
    <state x="743" y="285" width="428" height="486" key="FileChooserDialogImpl" timestamp="1598579852080">
      <screen x="0" y="0" width="1920" height="1053" />
    </state>
    <state x="743" y="285" width="428" height="486" key="FileChooserDialogImpl/0.0.1920.1053@0.0.1920.1053" timestamp="1598579852080" />
  </component>
</project>

================================================
FILE: .metadata
================================================
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
  revision: 216dee60c0cc9449f0b29bcf922974d612263e24
  channel: stable

project_type: plugin


================================================
FILE: .vscode/launch.json
================================================
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Flutter",
            "program": "lib/main.dart",
            "request": "launch",
            "type": "dart"
        }
    ]
}

================================================
FILE: CHANGELOG.md
================================================
## [2.0.0-nullsafety.0] - 2021.03.06
* mirgrate to nullsafety
## [1.1.0] - 2020.09.19
* Added documentation.
* Refactored all the code.
* Added independent functionality chathead works even if the app is killed.
## [1.0.0] - 2020.09.05

* Initial Release


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Floaty_Chathead

:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:

The following is a set of guidelines for contributing to Floaty_Chathead. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.

## How Can I Contribute?

### Reporting Bugs

> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.

#### How Do I Submit A (Good) Bug Report?

Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](#atom-and-packages) your bug is related to, create an issue on that repository and provide the following information by filling in [the template](https://github.com/atom/.github/blob/master/.github/ISSUE_TEMPLATE/bug_report.md).

Explain the problem and include additional details to help maintainers reproduce the problem:

* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how the plugin was intended to work on your app, e.g. which command exactly you used in the terminal. When listing steps, **don't just say what you did, but explain how you did it**.
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.**
* **Include screenshots and animated GIFs** which show you following the described steps and clearly demonstrate the problem. If you use the keyboard while following the steps, **record the GIF with the [Keybinding Resolver](https://github.com/atom/keybinding-resolver) shown**. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
* **If you're reporting that Floaty_Chathead crashed**, include a crash report with a stack trace from the project console. Include the crash report in the issue in a [code block](https://help.github.com/articles/markdown-basics/#multiple-lines), a [file attachment](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests/), or put it in a [gist](https://gist.github.com/) and provide link to that gist.
* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below.

### Suggesting Enhancements

This section guides you through submitting an enhancement suggestion for Floaty_Chathead, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the flutter community understand your suggestion :pencil: and find related suggestions :mag_right:.

Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](https://github.com/atom/.github/blob/master/.github/ISSUE_TEMPLATE/feature_request.md), including the steps that you imagine you would take if the feature you're requesting existed.

#### How Do I Submit A (Good) Enhancement Suggestion?

Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](#atom-and-packages) your enhancement suggestion is related to, create an issue on that repository and provide the following information:

* **Use a clear and descriptive title** for the issue to identify the suggestion.
* **Provide a step-by-step description of the suggested enhancement** in as many details as possible.
* **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
* **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of Atom which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
* **Explain why this enhancement would be useful** to most Flutter users.

### Pull Requests

The process described here has several goals:

- Fix problems that are important to user

[search-atom-repo-label-enhancement]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aenhancement
[search-atom-org-label-enhancement]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aenhancement
[search-atom-repo-label-bug]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Abug
[search-atom-org-label-bug]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Abug
[search-atom-repo-label-question]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aquestion
[search-atom-org-label-question]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aquestion
[search-atom-repo-label-feedback]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Afeedback
[search-atom-org-label-feedback]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Afeedback
[search-atom-repo-label-help-wanted]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Ahelp-wanted
[search-atom-org-label-help-wanted]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Ahelp-wanted
[search-atom-repo-label-beginner]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Abeginner
[search-atom-org-label-beginner]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Abeginner
[search-atom-repo-label-more-information-needed]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Amore-information-needed
[search-atom-org-label-more-information-needed]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Amore-information-needed
[search-atom-repo-label-needs-reproduction]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aneeds-reproduction
[search-atom-org-label-needs-reproduction]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aneeds-reproduction
[search-atom-repo-label-triage-help-needed]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Atriage-help-needed
[search-atom-org-label-triage-help-needed]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Atriage-help-needed
[search-atom-repo-label-windows]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Awindows
[search-atom-org-label-windows]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Awindows
[search-atom-repo-label-linux]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Alinux
[search-atom-org-label-linux]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Alinux
[search-atom-repo-label-mac]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Amac
[search-atom-org-label-mac]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Amac
[search-atom-repo-label-documentation]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Adocumentation
[search-atom-org-label-documentation]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Adocumentation
[search-atom-repo-label-performance]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aperformance
[search-atom-org-label-performance]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aperformance
[search-atom-repo-label-security]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Asecurity
[search-atom-org-label-security]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Asecurity
[search-atom-repo-label-ui]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aui
[search-atom-org-label-ui]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aui
[search-atom-repo-label-api]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aapi
[search-atom-org-label-api]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aapi
[search-atom-repo-label-crash]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Acrash
[search-atom-org-label-crash]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Acrash
[search-atom-repo-label-auto-indent]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aauto-indent
[search-atom-org-label-auto-indent]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aauto-indent
[search-atom-repo-label-encoding]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aencoding
[search-atom-org-label-encoding]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aencoding
[search-atom-repo-label-network]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Anetwork
[search-atom-org-label-network]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Anetwork
[search-atom-repo-label-uncaught-exception]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Auncaught-exception
[search-atom-org-label-uncaught-exception]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Auncaught-exception
[search-atom-repo-label-git]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Agit
[search-atom-org-label-git]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Agit
[search-atom-repo-label-blocked]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Ablocked
[search-atom-org-label-blocked]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Ablocked
[search-atom-repo-label-duplicate]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aduplicate
[search-atom-org-label-duplicate]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aduplicate
[search-atom-repo-label-wontfix]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Awontfix
[search-atom-org-label-wontfix]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Awontfix
[search-atom-repo-label-invalid]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Ainvalid
[search-atom-org-label-invalid]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Ainvalid
[search-atom-repo-label-package-idea]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Apackage-idea
[search-atom-org-label-package-idea]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Apackage-idea
[search-atom-repo-label-wrong-repo]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Awrong-repo
[search-atom-org-label-wrong-repo]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Awrong-repo
[search-atom-repo-label-editor-rendering]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aeditor-rendering
[search-atom-org-label-editor-rendering]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aeditor-rendering
[search-atom-repo-label-build-error]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Abuild-error
[search-atom-org-label-build-error]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Abuild-error
[search-atom-repo-label-error-from-pathwatcher]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aerror-from-pathwatcher
[search-atom-org-label-error-from-pathwatcher]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aerror-from-pathwatcher
[search-atom-repo-label-error-from-save]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aerror-from-save
[search-atom-org-label-error-from-save]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aerror-from-save
[search-atom-repo-label-error-from-open]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aerror-from-open
[search-atom-org-label-error-from-open]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aerror-from-open
[search-atom-repo-label-installer]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Ainstaller
[search-atom-org-label-installer]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Ainstaller
[search-atom-repo-label-auto-updater]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Aauto-updater
[search-atom-org-label-auto-updater]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aauto-updater
[search-atom-repo-label-deprecation-help]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3Aatom%2Fatom+label%3Adeprecation-help
[search-atom-org-label-deprecation-help]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Adeprecation-help
[search-atom-repo-label-electron]: https://github.com/search?q=is%3Aissue+repo%3Aatom%2Fatom+is%3Aopen+label%3Aelectron
[search-atom-org-label-electron]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3Aatom+label%3Aelectron
[search-atom-repo-label-work-in-progress]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3Aatom%2Fatom+label%3Awork-in-progress
[search-atom-org-label-work-in-progress]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3Aatom+label%3Awork-in-progress
[search-atom-repo-label-needs-review]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3Aatom%2Fatom+label%3Aneeds-review
[search-atom-org-label-needs-review]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3Aatom+label%3Aneeds-review
[search-atom-repo-label-under-review]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3Aatom%2Fatom+label%3Aunder-review
[search-atom-org-label-under-review]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3Aatom+label%3Aunder-review
[search-atom-repo-label-requires-changes]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3Aatom%2Fatom+label%3Arequires-changes
[search-atom-org-label-requires-changes]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3Aatom+label%3Arequires-changes
[search-atom-repo-label-needs-testing]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3Aatom%2Fatom+label%3Aneeds-testing
[search-atom-org-label-needs-testing]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3Aatom+label%3Aneeds-testing

[beginner]:https://github.com/search?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+label%3Abeginner+label%3Ahelp-wanted+user%3Aatom+sort%3Acomments-desc
[help-wanted]:https://github.com/search?q=is%3Aopen+is%3Aissue+label%3Ahelp-wanted+user%3Aatom+sort%3Acomments-desc+-label%3Abeginner
[contributing-to-official-atom-packages]:https://flight-manual.atom.io/hacking-atom/sections/contributing-to-official-atom-packages/
[hacking-on-atom-core]: https://flight-manual.atom.io/hacking-atom/sections/hacking-on-atom-core/


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

Copyright (c) 2020 Luis Cardoza Bird

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
================================================
# Floaty Chathead (Deprecated)

[![Deprecated](https://img.shields.io/badge/status-deprecated-red.svg)](https://pub.dev/packages/floaty_chatheads)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)

> **This package has been deprecated.** Please use [`floaty_chatheads`](https://pub.dev/packages/floaty_chatheads) instead.

---

## Migration

Replace your dependency:

```yaml
# Before
dependencies:
  floaty_chathead: ^3.0.0

# After
dependencies:
  floaty_chatheads: ^1.0.0
```

Then run:

```bash
flutter pub get
```

## What changed?

`floaty_chatheads` is a full rewrite of `floaty_chathead` using a **federated plugin architecture**, bringing:

- **iOS support** alongside Android
- **Type-safe platform channels** via Pigeon (no more manual `MethodChannel` strings)
- **Typed messaging** with `FloatyMessenger<T>` for serialized communication between main app and overlay
- **Lifecycle-aware controller** (`FloatyController`) with `ChangeNotifier` integration
- **Widget-level integration** via `FloatyScope` (InheritedWidget) and `FloatyPermissionGate`
- **Multi-chathead management** (`addChatHead`, `removeChatHead`, `expandChatHead`, `collapseChatHead`)
- **Built-in UI components** (`FloatyMiniPlayer`, `FloatyNotificationCard`)
- **100% test coverage** on handwritten code with 132 tests
- **Testing utilities** (`FakeFloatyPlatform`, `FakeOverlayDataSource`) for easy widget testing

## Links

- [`floaty_chatheads` on pub.dev](https://pub.dev/packages/floaty_chatheads)
- [`floaty_chatheads` repository](https://github.com/Crdzbird/floaty_chatheads)

---

## License

This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.


================================================
FILE: android/.gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures


================================================
FILE: android/.idea/.name
================================================
floaty_head

================================================
FILE: android/.idea/assetWizardSettings.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="WizardSettings">
    <option name="children">
      <map>
        <entry key="vectorWizard">
          <value>
            <PersistentState>
              <option name="children">
                <map>
                  <entry key="vectorAssetStep">
                    <value>
                      <PersistentState>
                        <option name="values">
                          <map>
                            <entry key="assetSourceType" value="FILE" />
                            <entry key="outputName" value="ic_chathead" />
                            <entry key="sourceFile" value="$USER_HOME$/Pictures/burbuja-de-dialogo.svg" />
                          </map>
                        </option>
                      </PersistentState>
                    </value>
                  </entry>
                </map>
              </option>
            </PersistentState>
          </value>
        </entry>
      </map>
    </option>
  </component>
</project>

================================================
FILE: android/.idea/codeStyles/Project.xml
================================================
<component name="ProjectCodeStyleConfiguration">
  <code_scheme name="Project" version="173">
    <JetCodeStyleSettings>
      <option name="PACKAGES_TO_USE_STAR_IMPORTS">
        <value>
          <package name="java.util" alias="false" withSubpackages="false" />
          <package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
          <package name="io.ktor" alias="false" withSubpackages="true" />
        </value>
      </option>
      <option name="PACKAGES_IMPORT_LAYOUT">
        <value>
          <package name="" alias="false" withSubpackages="true" />
          <package name="java" alias="false" withSubpackages="true" />
          <package name="javax" alias="false" withSubpackages="true" />
          <package name="kotlin" alias="false" withSubpackages="true" />
          <package name="" alias="true" withSubpackages="true" />
        </value>
      </option>
    </JetCodeStyleSettings>
    <codeStyleSettings language="XML">
      <indentOptions>
        <option name="CONTINUATION_INDENT_SIZE" value="4" />
      </indentOptions>
      <arrangement>
        <rules>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>xmlns:android</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>xmlns:.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
              <order>BY_NAME</order>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*:id</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*:name</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>name</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>style</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>^$</XML_NAMESPACE>
                </AND>
              </match>
              <order>BY_NAME</order>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
                </AND>
              </match>
              <order>ANDROID_ATTRIBUTE_ORDER</order>
            </rule>
          </section>
          <section>
            <rule>
              <match>
                <AND>
                  <NAME>.*</NAME>
                  <XML_ATTRIBUTE />
                  <XML_NAMESPACE>.*</XML_NAMESPACE>
                </AND>
              </match>
              <order>BY_NAME</order>
            </rule>
          </section>
        </rules>
      </arrangement>
    </codeStyleSettings>
  </code_scheme>
</component>

================================================
FILE: android/.idea/gradle.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="GradleMigrationSettings" migrationVersion="1" />
  <component name="GradleSettings">
    <option name="linkedExternalProjectsSettings">
      <GradleProjectSettings>
        <option name="testRunner" value="PLATFORM" />
        <option name="distributionType" value="DEFAULT_WRAPPED" />
        <option name="externalProjectPath" value="$PROJECT_DIR$" />
        <option name="gradleJvm" value="1.8" />
        <option name="modules">
          <set>
            <option value="$PROJECT_DIR$" />
          </set>
        </option>
        <option name="resolveModulePerSourceSet" value="false" />
      </GradleProjectSettings>
    </option>
  </component>
</project>

================================================
FILE: android/.idea/jarRepositories.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="RemoteRepositoriesConfiguration">
    <remote-repository>
      <option name="id" value="central" />
      <option name="name" value="Maven Central repository" />
      <option name="url" value="https://repo1.maven.org/maven2" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="jboss.community" />
      <option name="name" value="JBoss Community repository" />
      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="BintrayJCenter" />
      <option name="name" value="BintrayJCenter" />
      <option name="url" value="https://jcenter.bintray.com/" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="Google" />
      <option name="name" value="Google" />
      <option name="url" value="https://dl.google.com/dl/android/maven2/" />
    </remote-repository>
  </component>
</project>

================================================
FILE: android/.idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
    <output url="file://$PROJECT_DIR$/build/classes" />
  </component>
  <component name="ProjectType">
    <option name="id" value="Android" />
  </component>
</project>

================================================
FILE: android/.idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ProjectModuleManager">
    <modules>
      <module fileurl="file://$PROJECT_DIR$/.idea/modules/floaty_head.iml" filepath="$PROJECT_DIR$/.idea/modules/floaty_head.iml" group="floaty_head" />
    </modules>
  </component>
</project>

================================================
FILE: android/.idea/runConfigurations.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="RunConfigurationProducerService">
    <option name="ignoredProducers">
      <set>
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
      </set>
    </option>
  </component>
</project>

================================================
FILE: android/.idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="VcsDirectoryMappings">
    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
  </component>
</project>

================================================
FILE: android/build.gradle
================================================
group 'ni.devotion.floaty_head'
version '1.0-SNAPSHOT'

buildscript {
    ext.kotlin_version = '1.4.0'
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:4.0.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

rootProject.allprojects {
    repositories {
        google()
        jcenter()
    }
}

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion 30
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 30
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    lintOptions {
        disable 'InvalidPackage'
    }
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    implementation 'com.google.android.material:material:1.2.0'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.facebook.rebound:rebound:0.3.8'
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
}


================================================
FILE: android/gradle/wrapper/gradle-wrapper.properties
================================================
#Thu Aug 27 19:59:47 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip


================================================
FILE: android/gradle.properties
================================================
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
android.enableR8=true


================================================
FILE: android/gradlew
================================================
#!/usr/bin/env bash

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

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

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

# 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
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
esac

# 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

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" ] ; 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

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
    JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"


================================================
FILE: android/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

@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=

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

@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 Windowz variants

if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_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=%*
goto execute

:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
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: android/settings.gradle
================================================
rootProject.name = 'floaty_head'


================================================
FILE: android/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
  package="ni.devotion.floaty_head">

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <application>
        <activity
            android:name=".MainActivity"
            android:allowEmbedded="true"
            android:documentLaunchMode="always"
            android:label="floaty_head"
            android:resizeableActivity="true"
            android:showOnLockScreen="true"
            android:theme="@style/AppTheme.NoActionBar"
            tools:targetApi="n" />
        <service
            android:name=".services.FloatyIconService"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.FOREGROUND_SERVICE"/>
        <service
            android:name=".services.FloatyContentJobService"
            android:enabled="true"
            android:exported="false"
            android:permission="android.permission.BIND_JOB_SERVICE"/>
    </application>

</manifest>


================================================
FILE: android/src/main/java/ni/devotion/floaty_head/FloatFragment.kt
================================================
package ni.devotion.floaty_head

import android.content.Context
import android.view.View
import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import android.widget.FrameLayout
import android.widget.LinearLayout
import com.facebook.rebound.SimpleSpringListener
import com.facebook.rebound.Spring
import com.facebook.rebound.SpringSystem
import ni.devotion.floaty_head.floating_chathead.SpringConfigs
import ni.devotion.floaty_head.R
import ni.devotion.floaty_head.utils.Managment.bodyView
import ni.devotion.floaty_head.utils.Managment.footerView
import ni.devotion.floaty_head.utils.Managment.headerView


class FloatFragment(context: Context) : LinearLayout(context) {
    private val springSystem = SpringSystem.create()
    private val scaleSpring = springSystem.createSpring()
    private lateinit var content: LinearLayout

    init {
        setupView()
    }

    private fun setupView() {
        context.setTheme(R.style.Theme_MaterialComponents_Light)
        inflate(context, R.layout.fragment_float, this)
        scaleSpring.addListener(object : SimpleSpringListener() {
            override fun onSpringUpdate(spring: Spring) {
                scaleX = spring.currentValue.toFloat()
                scaleY = spring.currentValue.toFloat()
            }
        })
        scaleSpring.springConfig = SpringConfigs.CONTENT_SCALE
        scaleSpring.currentValue = 0.0
        content = findViewById<LinearLayout>(R.id.contentLayout)
        headerView?.let {
            content.addView(it)
        }
        bodyView?.let {
            content.addView(it)
        }
        footerView?.let {
            content.addView(it)
        }
    }

    override fun onViewRemoved(child: View?) {
        super.onViewRemoved(child)
        content.removeAllViews()
    }

    fun hideContent() {
        scaleSpring.endValue = 0.0
        val anim = AlphaAnimation(1.0f, 0.0f)
        anim.duration = 200
        anim.repeatMode = Animation.RELATIVE_TO_SELF
        startAnimation(anim)
    }

    fun showContent() {
        scaleSpring.endValue = 1.0
        val anim = AlphaAnimation(0.0f, 1.0f)
        anim.duration = 100
        anim.repeatMode = Animation.RELATIVE_TO_SELF
        startAnimation(anim)
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/FloatyHeadPlugin.kt
================================================
package ni.devotion.floaty_head

import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.IBinder
import android.provider.Settings
import android.util.Log
import android.widget.FrameLayout
import androidx.annotation.NonNull
import io.flutter.embedding.engine.loader.FlutterLoader
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.Registrar
import io.flutter.view.FlutterCallbackInformation
import io.flutter.view.FlutterMain
import io.flutter.view.FlutterNativeView
import io.flutter.view.FlutterRunArguments
import ni.devotion.floaty_head.services.FloatyContentJobService.Companion.INTENT_EXTRA_IS_UPDATE_WINDOW
import ni.devotion.floaty_head.services.FloatyIconService
import ni.devotion.floaty_head.services.FloatyContentJobService
import ni.devotion.floaty_head.utils.Commons.getMapFromObject
import ni.devotion.floaty_head.utils.Constants.SHARED_PREF_FLOATY_HEAD
import ni.devotion.floaty_head.utils.Constants.CALLBACK_HANDLE_KEY
import ni.devotion.floaty_head.utils.Constants.CODE_CALLBACK_HANDLE_KEY
import ni.devotion.floaty_head.utils.Constants.BACKGROUND_CHANNEL
import ni.devotion.floaty_head.utils.Constants.INTENT_EXTRA_PARAMS_MAP
import ni.devotion.floaty_head.utils.Constants.METHOD_CHANNEL
import ni.devotion.floaty_head.utils.Constants.KEY_BODY
import ni.devotion.floaty_head.utils.Constants.KEY_FOOTER
import ni.devotion.floaty_head.utils.Constants.KEY_HEADER
import ni.devotion.floaty_head.utils.Managment
import ni.devotion.floaty_head.utils.Managment.bodyMap
import ni.devotion.floaty_head.utils.Managment.bodyView
import ni.devotion.floaty_head.utils.Managment.footerMap
import ni.devotion.floaty_head.utils.Managment.footerView
import ni.devotion.floaty_head.utils.Managment.headerView
import ni.devotion.floaty_head.utils.Managment.headersMap
import ni.devotion.floaty_head.utils.Managment.layoutParams
import ni.devotion.floaty_head.utils.Managment.sIsIsolateRunning
import ni.devotion.floaty_head.views.BodyView
import ni.devotion.floaty_head.views.FooterView
import ni.devotion.floaty_head.views.HeaderView
import java.io.IOException
import java.util.ArrayList
import java.util.HashMap
import kotlin.collections.List
import kotlin.collections.Map

class FloatyHeadPlugin : ActivityAware, FlutterPlugin, MethodChannel.MethodCallHandler {
    companion object {
        var mBound: Boolean = false
        lateinit var instance: FloatyHeadPlugin
        var activity: Activity? = null
        var context: Context? = null
        var sBackgroundFlutterView: FlutterNativeView? = null
        private var channel: MethodChannel? = null
        private var backgroundChannel: MethodChannel? = null
    }
    var sPluginRegistrantCallback: PluginRegistry.PluginRegistrantCallback? = null
    private val CODE_DRAW_OVER_OTHER_APP_PERMISSION = 2084

    fun setPluginRegistrant(callback: PluginRegistry.PluginRegistrantCallback) {
        Managment.pluginRegistrantC = callback
        sPluginRegistrantCallback = callback
    }

    fun registerWith(pluginRegistrar: Registrar) {
        context = pluginRegistrar.context()
        channel = MethodChannel(pluginRegistrar.messenger(), METHOD_CHANNEL)
        channel?.setMethodCallHandler(FloatyHeadPlugin())
    }

    fun startCallBackHandler(context: Context) {
        var preferences = context.getSharedPreferences(SHARED_PREF_FLOATY_HEAD, 0)
        val callBackHandle: Long = preferences.getLong(CALLBACK_HANDLE_KEY, -1)
        if (callBackHandle != -1L) {
            FlutterMain.ensureInitializationComplete(context, null)
            val mAppBundlePath: String = FlutterMain.findAppBundlePath()
            val flutterCallback: FlutterCallbackInformation = FlutterCallbackInformation.lookupCallbackInformation(callBackHandle)
            sBackgroundFlutterView?.let { sbfv ->
                backgroundChannel ?: run {
                    backgroundChannel = MethodChannel(sbfv, BACKGROUND_CHANNEL)
                }
                Managment.sIsIsolateRunning.set(true)
            } ?: run {
                sBackgroundFlutterView = FlutterNativeView(context, true)
                if(mAppBundlePath != null && !Managment.sIsIsolateRunning.get()) {
                    Managment.pluginRegistrantC ?: run {
                        Log.i("TAG", "Unable to start callBackHandle... as plugin is not registered")
                        return
                    }
                    val args = FlutterRunArguments()
                    args.bundlePath = mAppBundlePath
                    args.entrypoint = flutterCallback.callbackName
                    args.libraryPath = flutterCallback.callbackLibraryPath
                    sBackgroundFlutterView!!.runFromBundle(args)
                    Managment.pluginRegistrantC?.registerWith(sBackgroundFlutterView!!.getPluginRegistry())
                    backgroundChannel = MethodChannel(sBackgroundFlutterView!!, BACKGROUND_CHANNEL)
                    Managment.sIsIsolateRunning.set(true)
                }
                Managment.sIsIsolateRunning.set(true)
            }
        }
    }

    fun invokeCallBack(context: Context, type: String, params: Any) {
        val argumentsList: MutableList<Any> = ArrayList()
        val preferences = activity!!.applicationContext.getSharedPreferences(SHARED_PREF_FLOATY_HEAD, 0)
        val codeCallBackHandle = preferences.getLong(CODE_CALLBACK_HANDLE_KEY, -1)
        if (codeCallBackHandle == -1L) {
            Log.e("TAG", "Back failed, as codeCallBackHandle is null")
        } else {
            argumentsList.clear()
            argumentsList.add(codeCallBackHandle)
            argumentsList.add(type)
            argumentsList.add(params)
            if(Managment.sIsIsolateRunning.get()) {
                backgroundChannel ?: run{
                    backgroundChannel = MethodChannel(sBackgroundFlutterView, BACKGROUND_CHANNEL)
                }
                try {
                    val retries = intArrayOf(2)
                    invokeCallBackToFlutter(backgroundChannel!!, "callBack", argumentsList, retries)
                    //channel!!.invokeMethod("callBack", argumentsList);
                }catch (ex: Exception) {
                    Log.e("TAG", "Exception in invoking callback $ex")
                }
            } else {
                Log.e("TAG", "invokeCallBack failed, as isolate is not running")
            }
        }
    }

    private fun invokeCallBackToFlutter(channel: MethodChannel, method: String, arguments: List<Any>, retries: IntArray) {
        channel.invokeMethod(method, arguments, object : MethodChannel.Result {
            override fun success(o: Any?) {
                Log.i("TAG", "Invoke call back success")
            }

            override fun error(s: String?, s1: String?, o: Any?) {
                Log.e("TAG", "Error $s$s1")
            }

            override fun notImplemented() {
                if (retries[0] > 0) {
                    Log.d("TAG", "Not Implemented method $method. Trying again to check if it works")
                    invokeCallBackToFlutter(channel, method, arguments, retries)
                } else {
                    Log.e("TAG", "Not Implemented method $method")
                }
                retries[0]--
            }
        })
    }

    private fun FloatyHeadPlugin(_context: Context, _activity: Activity, _methodChannel: MethodChannel) {
        activity = _activity
        context = _context
        channel = _methodChannel
        channel?.let { it.setMethodCallHandler(this) }
    }

    override fun onMethodCall(call: MethodCall, @NonNull result: Result) {
        when (call.method) {
            "start" -> {
                Managment.globalContext = activity?.applicationContext
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(activity)) {
                    val packageName = activity?.packageName
                    activity?.startActivityForResult(
                            Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName")),
                            CODE_DRAW_OVER_OTHER_APP_PERMISSION)
                } else {
                    if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
                        val subIntent = Intent(activity?.applicationContext, FloatyContentJobService::class.java)
                        subIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                        subIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
                        subIntent.putExtra(INTENT_EXTRA_IS_UPDATE_WINDOW, true)
                        activity?.startService(subIntent)
                        mBound = true
                    } else {
                        val subIntent = Intent(activity?.applicationContext, FloatyContentJobService::class.java)
                        activity?.startForegroundService(subIntent)
                        mBound = true
                    }
                }
            }
            "isOpen" -> result.success(mBound)
            "close" -> {
                if(mBound){
                    FloatyContentJobService.instance!!.closeWindow(true)
                    if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q){
                        activity?.stopService(Intent(activity?.applicationContext, FloatyContentJobService::class.java))
                    }else{
                        activity?.startForegroundService(Intent(activity?.applicationContext, FloatyContentJobService::class.java))
                    }
                    mBound = false
                }
            }
            "setIcon" -> result.success(setIconFromAsset(call.arguments as String))
            "setBackgroundCloseIcon" -> result.success(setBackgroundCloseIconFromAsset(call.arguments as String))
            "setCloseIcon" -> result.success(setCloseIconFromAsset(call.arguments as String))
            "setNotificationTitle" -> result.success(setNotificationTitle(call.arguments as String))
            "setNotificationIcon" -> result.success(setNotificationIcon(call.arguments as String))
            "setFloatyHeadContent" -> {
                assert((call.arguments != null))
                val updateParams = call.arguments as HashMap<String, Any>
                headersMap = getMapFromObject(updateParams, KEY_HEADER)
                bodyMap = getMapFromObject(updateParams, KEY_BODY)
                footerMap = getMapFromObject(updateParams, KEY_FOOTER)
                layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)
                try {
                    headersMap?.let {
                        headerView = HeaderView(activity!!.applicationContext, it).view
                    }
                    bodyMap?.let {
                        bodyView = BodyView(activity!!.applicationContext, it).view
                    }
                    footerMap?.let {
                        footerView = FooterView(activity!!.applicationContext, it).view
                    }
                } catch (except: Exception) {
                    except.printStackTrace()
                }
                result.success(true)
            }
            "registerCallBackHandler" -> {
                try {
                    val arguments = call.arguments as List<*>
                    arguments ?: result.success(false)
                    arguments?.let {
                        val callBackHandle = (it[0]).toString().toLong()
                        val onClickHandle = (it[1]).toString().toLong()
                        val preferences = activity?.applicationContext!!.getSharedPreferences(SHARED_PREF_FLOATY_HEAD, 0)
                        preferences?.edit()?.putLong(CALLBACK_HANDLE_KEY, callBackHandle)!!.commit()
                        preferences?.edit()?.putLong(CODE_CALLBACK_HANDLE_KEY, onClickHandle)!!.commit()
                        startCallBackHandler(activity!!.applicationContext)
                        result.success(true)
                    }
                } catch (ex: Exception) {
                    Log.e("TAG", "Exception in registerOnClickHandler " + ex.toString())
                    result.success(false)
                }
            }
            else -> result.notImplemented()
        }
    }

    private fun setNotificationTitle(title: String):Int {
        var result = -1
        try {
            Managment.notificationTitle = title
            result = 1
        }catch (e: IOException) {
            e.printStackTrace()
        }
        return result
    }

    private fun setNotificationIcon(assetPath: String):Int {
        var result = -1
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                val inputStream = activity!!.applicationContext.assets.open("flutter_assets/" + assetPath)
                val bitmap = BitmapFactory.decodeStream(inputStream)
                Managment.notificationIcon = bitmap
                result = 1
            } else {
                val assetLookupKey = FlutterLoader.getInstance().getLookupKeyForAsset(assetPath)
                val assetManager = activity!!.applicationContext.assets
                val assetFileDescriptor = assetManager.openFd(assetLookupKey)
                val inputStream = assetFileDescriptor.createInputStream()
                Managment.notificationIcon = BitmapFactory.decodeStream(inputStream)
                result = 1
            }
        }catch (e: IOException) {
            e.printStackTrace()
        }
        return result
    }

    private fun setBackgroundCloseIconFromAsset(assetPath: String):Int {
        var result = -1
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                val inputStream = activity!!.applicationContext.assets.open("flutter_assets/" + assetPath)
                val bitmap = BitmapFactory.decodeStream(inputStream)
                Managment.backgroundCloseIcon = bitmap
                result = 1
            }
            else {
                val assetLookupKey = FlutterLoader.getInstance().getLookupKeyForAsset(assetPath)
                val assetManager = activity!!.applicationContext.assets
                val assetFileDescriptor = assetManager.openFd(assetLookupKey)
                val inputStream = assetFileDescriptor.createInputStream()
                Managment.backgroundCloseIcon = BitmapFactory.decodeStream(inputStream)
                result = 1
            }
        }catch (e: IOException) {
            e.printStackTrace()
        }
        return result
    }

    private fun setCloseIconFromAsset(assetPath: String):Int {
        var result = -1
        try {
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
                val inputStream = activity!!.applicationContext.assets.open("flutter_assets/" + assetPath)
                val bitmap = BitmapFactory.decodeStream(inputStream)
                Managment.closeIcon = bitmap
                result = 1
            }
            else {
                val assetLookupKey = FlutterLoader.getInstance().getLookupKeyForAsset(assetPath)
                val assetManager = activity!!.applicationContext.assets
                val assetFileDescriptor = assetManager.openFd(assetLookupKey)
                val inputStream = assetFileDescriptor.createInputStream()
                Managment.closeIcon = BitmapFactory.decodeStream(inputStream)
                result = 1
            }
        }catch (e: IOException) {
            e.printStackTrace()
        }
        return result
    }

    private fun setIconFromAsset(assetPath: String):Int {
        var result = -1
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                val inputStream = activity!!.applicationContext.assets.open("flutter_assets/" + assetPath)
                val bitmap = BitmapFactory.decodeStream(inputStream)
                Managment.floatingIcon = bitmap
                result = 1
            }
            else {
                val assetLookupKey = FlutterLoader.getInstance().getLookupKeyForAsset(assetPath)
                val assetManager = activity!!.applicationContext.assets
                val assetFileDescriptor = assetManager.openFd(assetLookupKey)
                val inputStream = assetFileDescriptor.createInputStream()
                Managment.floatingIcon = BitmapFactory.decodeStream(inputStream)
                result = 1
            }
        }catch (e: IOException) {
            e.printStackTrace()
        }
        return result
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel?.setMethodCallHandler(null)
        //release()
    }

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
      channel = MethodChannel(flutterPluginBinding.binaryMessenger, METHOD_CHANNEL)
      channel?.setMethodCallHandler(this)
  }

  override fun onAttachedToActivity(binding: ActivityPluginBinding) {
      activity = binding.activity
      Managment.activity = binding.activity
      instance = this@FloatyHeadPlugin
  }

  override fun onDetachedFromActivity() {
      //release()
  }

  override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
      activity = binding.activity
      Managment.activity = binding.activity
      instance = this@FloatyHeadPlugin
  }

  override fun onDetachedFromActivityForConfigChanges() {
      //release()
  }
}


================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/MainActivity.kt
================================================
package ni.devotion.floaty_head

import android.content.Context
import android.graphics.Color
import android.os.Bundle
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import ni.devotion.floaty_head.utils.Commons.getMapFromObject
import ni.devotion.floaty_head.utils.Constants.INTENT_EXTRA_PARAMS_MAP
import ni.devotion.floaty_head.utils.Constants.KEY_BODY
import ni.devotion.floaty_head.utils.Constants.KEY_FOOTER
import ni.devotion.floaty_head.utils.Constants.KEY_HEADER
import ni.devotion.floaty_head.utils.Managment.bodyMap
import ni.devotion.floaty_head.utils.Managment.footerMap
import ni.devotion.floaty_head.utils.Managment.headerView
import ni.devotion.floaty_head.utils.Managment.headersMap
import ni.devotion.floaty_head.utils.Managment.layoutParams
import ni.devotion.floaty_head.utils.Managment.paramsMap
import ni.devotion.floaty_head.views.HeaderView
import java.util.*

class MainActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
  }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/floating_chathead/ChatHead.kt
================================================
package ni.devotion.floaty_head.floating_chathead

import android.graphics.*
import android.graphics.BitmapFactory.*
import android.view.*
import com.facebook.rebound.*
import ni.devotion.floaty_head.R
import ni.devotion.floaty_head.services.FloatyIconService
import ni.devotion.floaty_head.utils.ImageHelper
import ni.devotion.floaty_head.utils.Managment
import kotlin.math.hypot
import kotlin.math.pow

class ChatHead(var chatHeads: ChatHeads): View(chatHeads.context), View.OnTouchListener, SpringListener {
    var isTop: Boolean = false
    var isActive: Boolean = false

    var params: WindowManager.LayoutParams = WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT,
        WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManagerHelper.getLayoutFlag(),
        0,
        PixelFormat.TRANSLUCENT
    )
    var springSystem = SpringSystem.create()
    var springX = springSystem.createSpring()
    var springY = springSystem.createSpring()
    val paint = Paint()
    private var initialX = 0.0f
    private var initialY = 0.0f
    private var initialTouchX = 0.0f
    private var initialTouchY = 0.0f
    private var moving = false
    override fun onSpringEndStateChange(spring: Spring?) {}

    override fun onSpringAtRest(spring: Spring?) {}

    override fun onSpringActivate(spring: Spring?) {}

    init {
        params.gravity = Gravity.TOP or Gravity.START
        params.x = 0
        params.y = 0
        params.width = ChatHeads.CHAT_HEAD_SIZE + 15
        params.height = ChatHeads.CHAT_HEAD_SIZE + 30
        springX.addListener(object : SimpleSpringListener() {
            override fun onSpringUpdate(spring: Spring) {
                x = spring.currentValue.toFloat()
            }
        })
        springX.springConfig = SpringConfigs.NOT_DRAGGING
        springX.addListener(this)
        springY.addListener(object : SimpleSpringListener() {
            override fun onSpringUpdate(spring: Spring) {
                y = spring.currentValue.toFloat()
            }
        })
        springY.springConfig = SpringConfigs.NOT_DRAGGING
        springY.addListener(this)
        this.setLayerType(LAYER_TYPE_HARDWARE, paint)
        chatHeads.addView(this, params)
        this.setOnTouchListener(this)
    }

    override fun onSpringUpdate(spring: Spring) {
        if (spring !== this.springX && spring !== this.springY) return
        val totalVelocity = hypot(springX.velocity, springY.velocity).toInt()
        chatHeads.onSpringUpdate(this, spring, totalVelocity)
    }

    override fun onDraw(canvas: Canvas?) {
        Managment.floatingIcon ?: canvas?.drawBitmap(ImageHelper.addShadow((ImageHelper.getCircularBitmap(decodeResource(Managment.globalContext!!.resources, R.drawable.bot)))), 0f, 0f, paint)
        Managment.floatingIcon?.let {
            canvas?.drawBitmap(ImageHelper.addShadow(ImageHelper.getCircularBitmap(it)), 0f, 0f, paint)
        }
    }

    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
        val currentChatHead = chatHeads.chatHeads.find { it == v }!!
        val metrics = WindowManagerHelper.getScreenSize()
        when (event!!.action) {
            MotionEvent.ACTION_DOWN -> {
                initialX = x
                initialY = y
                initialTouchX = event.rawX
                initialTouchY = event.rawY
                scaleX = 0.9f
                scaleY = 0.9f
            }
            MotionEvent.ACTION_UP -> {
                if (!moving) {
                    if (currentChatHead.isActive) {
                        chatHeads.collapse()
                    } else {
                        val selectedChatHead = chatHeads.chatHeads.find { it.isActive }
                        selectedChatHead?.isActive = false
                        currentChatHead.isActive = true
                        chatHeads.changeContent()
                    }
                } else {
                    springX.endValue = metrics.widthPixels - width - (chatHeads.chatHeads.size - 1 - chatHeads.chatHeads.indexOf(this)) * (width + ChatHeads.CHAT_HEAD_EXPANDED_PADDING).toDouble()
                    springY.endValue = ChatHeads.CHAT_HEAD_EXPANDED_MARGIN_TOP.toDouble()
                    if (isActive) {
                        chatHeads.content.showContent()
                    }
                }
                scaleX = 1f
                scaleY = 1f
                moving = false
            }
            MotionEvent.ACTION_MOVE -> {
                if (ChatHeads.distance(initialTouchX, event.rawX, initialTouchY, event.rawY) > ChatHeads.CHAT_HEAD_DRAG_TOLERANCE.pow(2) && !moving) {
                    moving = true
                    if (isActive) {
                        chatHeads.content.hideContent()
                    }
                }
                if (moving) {
                    springX.currentValue = initialX + (event.rawX - initialTouchX).toDouble()
                    springY.currentValue = initialY + (event.rawY - initialTouchY).toDouble()
                }
            }
        }
        return true
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/floating_chathead/ChatHeads.kt
================================================
package ni.devotion.floaty_head.floating_chathead

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.PixelFormat
import android.view.*
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.view.VelocityTracker
import com.facebook.rebound.Spring
import com.facebook.rebound.SimpleSpringListener
import com.facebook.rebound.SpringChain
import java.util.*
import kotlin.math.*
import android.app.ActivityManager
import ni.devotion.floaty_head.FloatFragment
import ni.devotion.floaty_head.R
import ni.devotion.floaty_head.services.FloatyContentJobService
import ni.devotion.floaty_head.services.FloatyIconService
import ni.devotion.floaty_head.utils.Managment


class ChatHeads(context: Context) : View.OnTouchListener, FrameLayout(context) {
    companion object {
        val CHAT_HEAD_OUT_OF_SCREEN_X: Int = WindowManagerHelper.dpToPx(10f)
        val CHAT_HEAD_SIZE: Int = WindowManagerHelper.dpToPx(64f)
        val CHAT_HEAD_PADDING: Int = WindowManagerHelper.dpToPx(6f)
        val CHAT_HEAD_EXPANDED_PADDING: Int = WindowManagerHelper.dpToPx(4f)
        val CHAT_HEAD_EXPANDED_MARGIN_TOP: Float = WindowManagerHelper.dpToPx(4f).toFloat()
        val CLOSE_SIZE = WindowManagerHelper.dpToPx(64f)
        val CLOSE_CAPTURE_DISTANCE = WindowManagerHelper.dpToPx(100f)
        val CLOSE_ADDITIONAL_SIZE = WindowManagerHelper.dpToPx(24f)
        const val CHAT_HEAD_DRAG_TOLERANCE: Float = 20f
        fun distance(x1: Float, x2: Float, y1: Float, y2: Float): Float {
            return ((x1 - x2).pow(2) + (y1-y2).pow(2))
        }
    }
    var wasMoving = false
    var captured = false
    var movingOutOfClose = false
    private var initialX = 0.0f
    private var initialY = 0.0f
    private var initialTouchX = 0.0f
    private var initialTouchY = 0.0f
    private var initialVelocityX = 0.0
    private var initialVelocityY = 0.0
    private var lastY = 0.0
    private var moving = false
    private var toggled = false
    private var motionTrackerUpdated = false
    private var collapsing = false
    private var blockAnim = false
    private var horizontalSpringChain: SpringChain? = null
    private var verticalSpringChain: SpringChain? = null
    private var isOnRight = false
    private var velocityTracker: VelocityTracker? = null
    private var motionTracker = LinearLayout(context)
    var topChatHead: ChatHead? = null
    var content = FloatFragment(context)
    private var close = Close(this)
    var chatHeads = ArrayList<ChatHead>()

    private var motionTrackerParams = WindowManager.LayoutParams(
        CHAT_HEAD_SIZE,
        CHAT_HEAD_SIZE + 16,
            WindowManagerHelper.getLayoutFlag(),
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
        PixelFormat.TRANSLUCENT
    )

    private var params = WindowManager.LayoutParams(
        WindowManager.LayoutParams.MATCH_PARENT,
        WindowManager.LayoutParams.MATCH_PARENT,
            WindowManagerHelper.getLayoutFlag(),
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
        PixelFormat.TRANSLUCENT
    )

    init {
        context.setTheme(R.style.Theme_MaterialComponents_Light)
        params.gravity = Gravity.START or Gravity.TOP
        params.dimAmount = 0.7f
        motionTrackerParams.gravity = Gravity.START or Gravity.TOP
        FloatyContentJobService.instance?.windowManager?.addView(motionTracker, motionTrackerParams)
        FloatyContentJobService.instance?.windowManager?.addView(this, params)
        this.addView(content)
        motionTracker.setOnTouchListener(this)
        this.setOnTouchListener{ v, event ->
            v.performClick()
            when (event.action) {
                MotionEvent.ACTION_UP -> {
                    if (v == this) {
                        collapse()
                    }
                }

            }
            return@setOnTouchListener false
        }
    }

    fun setTop(chatHead: ChatHead) {
        topChatHead?.isTop = false
        chatHead.isTop = true
        topChatHead = chatHead
    }

    fun fixPositions(animation: Boolean = true) {
        if (topChatHead == null) return
        val metrics = WindowManagerHelper.getScreenSize()
        val newX =  if (isOnRight) metrics.widthPixels - topChatHead!!.width + CHAT_HEAD_OUT_OF_SCREEN_X.toDouble() else -CHAT_HEAD_OUT_OF_SCREEN_X.toDouble()
        val newY = initialY.toDouble()
        if (animation) {
            topChatHead!!.springX.endValue = newX
            topChatHead!!.springY.endValue = newY
        } else {
            topChatHead!!.springX.currentValue = newX
            topChatHead!!.springY.currentValue = newY
        }
    }

    private fun destroySpringChains() {
        horizontalSpringChain?.let {
            for (spring in it.allSprings) {
                spring.destroy()
            }
        }
        verticalSpringChain?.let {
            for (spring in it.allSprings) {
                spring.destroy()
            }
        }
        verticalSpringChain = null
        horizontalSpringChain = null
    }

    @SuppressLint("NewApi")
    private fun resetSpringChains() {
       destroySpringChains()
        horizontalSpringChain = SpringChain.create(0, 0, 200, 15)
        verticalSpringChain = SpringChain.create(0, 0, 200, 15)
        chatHeads.forEachIndexed { index, element ->
            element.z = index.toFloat()
            if (element.isTop) {
                horizontalSpringChain!!.addSpring(object : SimpleSpringListener() { })
                verticalSpringChain!!.addSpring(object : SimpleSpringListener() { })

                element.z = chatHeads.size.toFloat()
                horizontalSpringChain!!.setControlSpringIndex(index)
                verticalSpringChain!!.setControlSpringIndex(index)
            } else {
                horizontalSpringChain!!.addSpring(object : SimpleSpringListener() {
                    override fun onSpringUpdate(spring: Spring?) {
                        if (!toggled && !blockAnim) {
                            if (collapsing) {
                                element.springX.endValue = spring!!.endValue + (chatHeads.size - 1 - index) * CHAT_HEAD_PADDING * if (isOnRight) 1 else -1
                            } else {
                                element.springX.currentValue = spring!!.currentValue + (chatHeads.size - 1 - index) * CHAT_HEAD_PADDING * if (isOnRight) 1 else -1
                            }
                        }
                    }
                })
                verticalSpringChain!!.addSpring(object : SimpleSpringListener() {
                    override fun onSpringUpdate(spring: Spring?) {
                        if (!toggled && !blockAnim) {
                            element.springY.currentValue = spring!!.currentValue
                        }
                    }
                })
            }
        }
    }

    fun add(): ChatHead {
        chatHeads.forEach {
            it.visibility = View.VISIBLE
        }
        val chatHead = ChatHead(this)
        chatHeads.add(chatHead)
        var lx = -CHAT_HEAD_OUT_OF_SCREEN_X.toDouble()
        var ly = 0.0
        if (topChatHead != null) {
            lx = topChatHead!!.springX.currentValue
            ly = topChatHead!!.springY.currentValue
        }

        setTop(chatHead)
        destroySpringChains()
        resetSpringChains()

        blockAnim = true

        chatHeads.forEachIndexed { index, element ->
            element.springX.currentValue = lx + (chatHeads.size - 1 - index) * CHAT_HEAD_PADDING * if (isOnRight) 1 else -1
            element.springY.currentValue = ly
        }

        motionTrackerParams.x = chatHead.springX.currentValue.toInt()
        motionTrackerParams.y = chatHead.springY.currentValue.toInt()
        motionTrackerParams.flags = motionTrackerParams.flags and WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE.inv()

        FloatyContentJobService.instance?.windowManager?.updateViewLayout(motionTracker, motionTrackerParams)

        return chatHead
    }

    fun collapse() {
        toggled = false
        collapsing = true

        fixPositions()

        chatHeads.forEach {
            it.isActive = false
        }
        content.hideContent()
        motionTrackerParams.flags = motionTrackerParams.flags and WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE.inv()
        FloatyContentJobService.instance?.windowManager?.updateViewLayout(motionTracker, motionTrackerParams)

        params.flags = ((params.flags or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) and WindowManager.LayoutParams.FLAG_DIM_BEHIND.inv()) and WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL.inv() or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        FloatyContentJobService.instance?.windowManager?.updateViewLayout(this, params)
    }

    fun changeContent() {
        val chatHead = chatHeads.find { it.isActive }!!

        //content.messagesView.removeAllViews()

//        for (message in chatHead.messages) {
//            content.addMessage(message)
//        }
    }

    fun getRunningServiceInfo(serviceClass: Class<*>, context: Context): ActivityManager.RunningServiceInfo? {
        val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.name == service.service.className) {
                return service
            }
        }
        return null
    }

    fun hideChatHeads(isClosed:Boolean = false) {
        if(isClosed){
            close.hide()
            postDelayed({
                topChatHead?.let {
                    it.springY.currentValue = 0.0
                    it.springX.currentValue = 0.0
                }
                FloatyContentJobService.instance!!.closeWindow(true)
            }, 300)
        }else{
            close.hide()
            postDelayed({
                topChatHead?.let {
                    it.springY.currentValue = 0.0
                    it.springX.currentValue = 0.0
                }
            }, 300)
        }
    }

    fun onSpringUpdate(chatHead: ChatHead, spring: Spring, totalVelocity: Int) {
        val metrics = WindowManagerHelper.getScreenSize()
        if (topChatHead != null && chatHead == topChatHead!!) {
            if (horizontalSpringChain != null && spring == chatHead.springX) {
                horizontalSpringChain!!.controlSpring.currentValue = spring.currentValue
            }
            if (verticalSpringChain != null && spring == chatHead.springY) {
                verticalSpringChain!!.controlSpring.currentValue = spring.currentValue
            }
        }
        var tmpChatHead: ChatHead? = null
        if (collapsing) tmpChatHead = topChatHead!!
        else if (chatHead.isActive) tmpChatHead = chatHead
        if (tmpChatHead != null) {
            content.x = tmpChatHead.springX.currentValue.toFloat() - metrics.widthPixels.toFloat() + ((chatHeads.size - 1 - chatHeads.indexOf(tmpChatHead)) * (tmpChatHead.width + CHAT_HEAD_EXPANDED_PADDING)) + tmpChatHead.width
            content.y = tmpChatHead.springY.currentValue.toFloat() - CHAT_HEAD_EXPANDED_MARGIN_TOP
            content.pivotX = metrics.widthPixels.toFloat() - chatHead.width / 2 - ((chatHeads.size - 1 - chatHeads.indexOf(tmpChatHead)) * (tmpChatHead.width + CHAT_HEAD_EXPANDED_PADDING))
        }
        content.pivotY = chatHead.height.toFloat()
        if (!moving && distance(close.x, topChatHead!!.springX.currentValue.toFloat(), close.y, topChatHead!!.springY.currentValue.toFloat()) < CLOSE_CAPTURE_DISTANCE * CLOSE_CAPTURE_DISTANCE && !captured && close.visibility == View.VISIBLE) {
            topChatHead!!.springX.springConfig = SpringConfigs.CAPTURING
            topChatHead!!.springY.springConfig = SpringConfigs.CAPTURING
            topChatHead!!.springX.endValue = close.springX.endValue
            topChatHead!!.springY.endValue = close.springY.endValue
            postDelayed({
                hideChatHeads(false)
            }, 300)
            captured = true
        }
        if (wasMoving) {
            motionTrackerParams.x = if (isOnRight) metrics.widthPixels - chatHead.width else 0
            lastY = chatHead.springY.currentValue
            if (abs(chatHead.springY.velocity) > 3000 && (chatHead.springX.currentValue > metrics.widthPixels - chatHead.width + CHAT_HEAD_OUT_OF_SCREEN_X / 2 || chatHead.springX.currentValue < -CHAT_HEAD_OUT_OF_SCREEN_X / 2) && abs(initialVelocityX) > 3000) {
                chatHead.springY.velocity = 3000.0 * if (initialVelocityY < 0) -1 else 1
            }
            if ((chatHead.springX.currentValue < -CHAT_HEAD_OUT_OF_SCREEN_X / 2 && initialVelocityX < -3000 || chatHead.springX.currentValue > metrics.widthPixels - chatHead.width  + CHAT_HEAD_OUT_OF_SCREEN_X / 2) && abs(initialVelocityY) < abs(initialVelocityX)) {
                chatHead.springY.velocity = 0.0
            }
            if (abs(chatHead.springY.velocity) > 500) {
                if (chatHead.springY.currentValue < 0) {
                    chatHead.springY.velocity = -500.0
                } else if (chatHead.springY.currentValue > metrics.heightPixels) {
                    chatHead.springY.velocity = 500.0
                }
            }

            if (!moving) {
                if (spring === chatHead.springX) {
                    val xPosition = chatHead.springX.currentValue
                    if (xPosition + chatHead.width > metrics.widthPixels && chatHead.springX.velocity > 0) {
                        val newPos = metrics.widthPixels - chatHead.width + CHAT_HEAD_OUT_OF_SCREEN_X
                        chatHead.springX.springConfig = SpringConfigs.NOT_DRAGGING
                        chatHead.springX.endValue = newPos.toDouble()
                        isOnRight = true
                    } else if (xPosition < 0 && chatHead.springX.velocity < 0) {
                        chatHead.springX.springConfig = SpringConfigs.NOT_DRAGGING
                        chatHead.springX.endValue = -CHAT_HEAD_OUT_OF_SCREEN_X.toDouble()
                        isOnRight = false
                    }
                } else if (spring === chatHead.springY) {
                    val yPosition = chatHead.springY.currentValue
                    if (yPosition + chatHead.height > metrics.heightPixels && chatHead.springY.velocity > 0) {
                        chatHead.springY.springConfig = SpringConfigs.NOT_DRAGGING
                        chatHead.springY.endValue = metrics.heightPixels - chatHead.height.toDouble() -
                                WindowManagerHelper.dpToPx(25f)
                    } else if (yPosition < 0 && chatHead.springY.velocity < 0) {
                        chatHead.springY.springConfig = SpringConfigs.NOT_DRAGGING
                        chatHead.springY.endValue = 0.0
                    }
                }
            }

            if (abs(totalVelocity) % 10 == 0 && !moving) {
                motionTrackerParams.y = topChatHead!!.springY.currentValue.toInt()
                FloatyContentJobService.instance?.windowManager?.updateViewLayout(motionTracker, motionTrackerParams)
            }
        }
    }

    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
        val metrics = WindowManagerHelper.getScreenSize()
        if (topChatHead == null) return true
        when (event!!.action) {
            MotionEvent.ACTION_DOWN -> {
                topChatHead?.let {
                    initialX = it.springX.currentValue.toFloat()
                    initialY = it.springY.currentValue.toFloat()
                    initialTouchX = event.rawX
                    initialTouchY = event.rawY
                    wasMoving = false
                    collapsing = false
                    blockAnim = false
                    close.show()
                    it.scaleX = 0.9f
                    it.scaleY = 0.9f
                    it.springX.springConfig = SpringConfigs.DRAGGING
                    it.springY.springConfig = SpringConfigs.DRAGGING
                    it.springX.setAtRest()
                    it.springY.setAtRest()
                }
                motionTrackerUpdated = false
                when (velocityTracker) {
                    null -> velocityTracker = VelocityTracker.obtain()
                    else -> velocityTracker?.clear()
                }
                velocityTracker?.addMovement(event)
            }
            MotionEvent.ACTION_UP -> {
                if (moving) wasMoving = true
                postDelayed({
                    close.hide()
                    if (captured) {
                        content.removeAllViews()
                        hideChatHeads(true)
                    }
                }, 200)
                if (captured) return true
                if (!moving) {
                    if (!toggled) {
                        toggled = true
                        chatHeads.forEachIndexed { index, it ->
                            it.springX.springConfig = SpringConfigs.NOT_DRAGGING
                            it.springY.springConfig = SpringConfigs.NOT_DRAGGING
                            it.springY.endValue = CHAT_HEAD_EXPANDED_MARGIN_TOP.toDouble()
                            it.springX.endValue = metrics.widthPixels - topChatHead!!.width.toDouble() - (chatHeads.size - 1 - index) * (it.width + CHAT_HEAD_EXPANDED_PADDING).toDouble()
                        }
                        motionTrackerParams.flags = motionTrackerParams.flags or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                        FloatyContentJobService.instance?.windowManager?.updateViewLayout(motionTracker, motionTrackerParams)
                        params.flags = (params.flags and WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE.inv()) or WindowManager.LayoutParams.FLAG_DIM_BEHIND or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL and WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE.inv()
                        FloatyContentJobService.instance?.windowManager?.updateViewLayout(this, params)
                        topChatHead!!.isActive = true
                        changeContent()
                        android.os.Handler().postDelayed(
                            {
                                content.showContent()
                            }, 200
                        )
                    }
                } else if (!toggled) {
                    moving = false
                    var xVelocity = velocityTracker!!.xVelocity.toDouble()
                    val yVelocity = velocityTracker!!.yVelocity.toDouble()
                    var maxVelocityX = 0.0
                    velocityTracker?.recycle()
                    velocityTracker = null
                    if (xVelocity < -3500) {
                        val newVelocity = ((-topChatHead!!.springX.currentValue -  CHAT_HEAD_OUT_OF_SCREEN_X) * SpringConfigs.DRAGGING.friction)
                        maxVelocityX = newVelocity - 5000
                        if (xVelocity > maxVelocityX)
                            xVelocity = newVelocity - 500
                    } else if (xVelocity > 3500) {
                        val newVelocity = ((metrics.widthPixels - topChatHead!!.springX.currentValue - topChatHead!!.width + CHAT_HEAD_OUT_OF_SCREEN_X) * SpringConfigs.DRAGGING.friction)
                        maxVelocityX = newVelocity + 5000
                        if (maxVelocityX > xVelocity)
                            xVelocity = newVelocity + 500
                    } else if (yVelocity > 20 || yVelocity < -20) {
                        topChatHead!!.springX.springConfig = SpringConfigs.NOT_DRAGGING
                        if (topChatHead!!.x >= metrics.widthPixels / 2) {
                            topChatHead!!.springX.endValue = metrics.widthPixels - topChatHead!!.width + CHAT_HEAD_OUT_OF_SCREEN_X.toDouble()
                            isOnRight = true
                        } else {
                            topChatHead!!.springX.endValue = -CHAT_HEAD_OUT_OF_SCREEN_X.toDouble()
                            isOnRight = false
                        }
                    } else {
                        topChatHead!!.springX.springConfig = SpringConfigs.NOT_DRAGGING
                        topChatHead!!.springY.springConfig = SpringConfigs.NOT_DRAGGING
                        if (topChatHead!!.x >= metrics.widthPixels / 2) {
                            topChatHead!!.springX.endValue = metrics.widthPixels - topChatHead!!.width +
                                    CHAT_HEAD_OUT_OF_SCREEN_X.toDouble()
                            topChatHead!!.springY.endValue = topChatHead!!.y.toDouble()
                            isOnRight = true
                        } else {
                            topChatHead!!.springX.endValue = -CHAT_HEAD_OUT_OF_SCREEN_X.toDouble()
                            topChatHead!!.springY.endValue = topChatHead!!.y.toDouble()
                            isOnRight = false
                        }
                    }
                    if (xVelocity < 0) {
                        topChatHead!!.springX.velocity = max(xVelocity, maxVelocityX)
                    } else {
                        topChatHead!!.springX.velocity = min(xVelocity, maxVelocityX)
                    }
                    initialVelocityX = topChatHead!!.springX.velocity
                    initialVelocityY = topChatHead!!.springY.velocity
                    topChatHead!!.springY.velocity = yVelocity
                }
                topChatHead!!.scaleX = 1f
                topChatHead!!.scaleY = 1f
            }
            MotionEvent.ACTION_MOVE -> {
                if (distance(initialTouchX, event.rawX, initialTouchY, event.rawY) > CHAT_HEAD_DRAG_TOLERANCE.pow(2)) {
                    moving = true
                }
                velocityTracker?.addMovement(event)
                if (moving) {
                    close.springX.endValue = (metrics.widthPixels / 2) + (((event.rawX + topChatHead!!.width / 2) / 7) - metrics.widthPixels / 2 / 7) - close.width.toDouble() / 2
                    close.springY.endValue = (metrics.heightPixels - CLOSE_SIZE) + max(((event.rawY + close.height / 2) / 10) - metrics.heightPixels / 10, -WindowManagerHelper.dpToPx(30f).toFloat()) - WindowManagerHelper.dpToPx(60f).toDouble()
                    if (distance(close.x + close.width / 2, event.rawX, close.y + close.height / 2, event.rawY) < CLOSE_CAPTURE_DISTANCE * CLOSE_CAPTURE_DISTANCE) {
                        topChatHead!!.springX.springConfig = SpringConfigs.CAPTURING
                        topChatHead!!.springY.springConfig = SpringConfigs.CAPTURING
                        close.springScale.endValue = CLOSE_ADDITIONAL_SIZE.toDouble()
                        captured = true
                    } else if (captured) {
                        topChatHead!!.springX.springConfig = SpringConfigs.CAPTURING
                        topChatHead!!.springY.springConfig = SpringConfigs.CAPTURING
                        close.springScale.endValue = 0.0
                        topChatHead!!.springX.endValue = initialX + (event.rawX - initialTouchX).toDouble()
                        topChatHead!!.springY.endValue = initialY + (event.rawY - initialTouchY).toDouble()
                        captured = false
                        movingOutOfClose = true
                        postDelayed({ movingOutOfClose = false }, 100)
                    } else if (!movingOutOfClose) {
                        topChatHead!!.springX.springConfig = SpringConfigs.DRAGGING
                        topChatHead!!.springY.springConfig = SpringConfigs.DRAGGING
                        topChatHead!!.springX.currentValue = initialX + (event.rawX - initialTouchX).toDouble()
                        topChatHead!!.springY.currentValue = initialY + (event.rawY - initialTouchY).toDouble()
                        velocityTracker?.computeCurrentVelocity(2000)
                    }
                }
            }
        }
        return true
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/floating_chathead/Close.kt
================================================
package ni.devotion.floaty_head.floating_chathead

import android.graphics.*
import android.os.Build
import android.view.*
import android.widget.FrameLayout
import android.widget.RelativeLayout
import androidx.core.content.ContextCompat
import com.facebook.rebound.*
import ni.devotion.floaty_head.R
import ni.devotion.floaty_head.services.FloatyIconService
import ni.devotion.floaty_head.utils.Managment

class Close(var chatHeads: ChatHeads): View(chatHeads.context) {
    private var params = WindowManager.LayoutParams(
        ChatHeads.CLOSE_SIZE + ChatHeads.CLOSE_ADDITIONAL_SIZE,
        ChatHeads.CLOSE_SIZE + ChatHeads.CLOSE_ADDITIONAL_SIZE,
            WindowManagerHelper.getLayoutFlag(),
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
        PixelFormat.TRANSLUCENT
    )

    private var gradientParams = FrameLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, WindowManagerHelper.dpToPx(150f))
    var springSystem = SpringSystem.create()
    var springY = springSystem.createSpring()
    var springX = springSystem.createSpring()
    var springAlpha = springSystem.createSpring()
    var springScale = springSystem.createSpring()
    val paint = Paint()
    val gradient = FrameLayout(context)
    private var bitmapBg: Bitmap? = null
    private var bitmapClose: Bitmap? = null

    fun hide() {
        val metrics = WindowManagerHelper.getScreenSize()
        springY.endValue = metrics.heightPixels.toDouble() + height
        springX.endValue = metrics.widthPixels.toDouble() / 2 - width / 2
        springAlpha.endValue = 0.0
    }

    fun show() {
        visibility = View.VISIBLE
        springAlpha.endValue = 1.0
    }

    private fun onPositionUpdate() {
        if (chatHeads.captured) {
            chatHeads.topChatHead!!.springX.endValue = springX.currentValue + width / 2 - chatHeads.topChatHead!!.width / 2 + 2
            chatHeads.topChatHead!!.springY.endValue = springY.currentValue + height / 2 - chatHeads.topChatHead!!.height / 2 + 2
        }
    }

    init {
        bitmapBg = Managment.backgroundCloseIcon ?: Bitmap.createScaledBitmap(BitmapFactory.decodeResource(Managment.globalContext!!.resources, R.drawable.close_bg), ChatHeads.CLOSE_SIZE, ChatHeads.CLOSE_SIZE, false)
        Managment.backgroundCloseIcon?.let {
            bitmapBg = Bitmap.createScaledBitmap(it, ChatHeads.CLOSE_SIZE, ChatHeads.CLOSE_SIZE, false)
        }
        bitmapClose = Managment.closeIcon ?: Bitmap.createScaledBitmap(BitmapFactory.decodeResource(Managment.globalContext!!.resources, R.drawable.close), WindowManagerHelper.dpToPx(28f), WindowManagerHelper.dpToPx(28f), false)
        Managment.closeIcon?.let {
            bitmapClose = Bitmap.createScaledBitmap(it, WindowManagerHelper.dpToPx(28f), WindowManagerHelper.dpToPx(28f), false)
        }
        this.setLayerType(View.LAYER_TYPE_HARDWARE, paint)
        visibility = View.INVISIBLE
        hide()
        springY.addListener(object : SimpleSpringListener() {
            override fun onSpringUpdate(spring: Spring) {
                y = spring.currentValue.toFloat()
                if (chatHeads.captured && chatHeads.wasMoving) {
                    chatHeads.topChatHead!!.springY.currentValue = spring.currentValue
                }
                onPositionUpdate()
            }
        })
        springX.addListener(object : SimpleSpringListener() {
            override fun onSpringUpdate(spring: Spring) {
                x = spring.currentValue.toFloat()
                onPositionUpdate()
            }
        })
        springScale.addListener(object : SimpleSpringListener() {
            override fun onSpringUpdate(spring: Spring) {
                bitmapBg = Managment.backgroundCloseIcon ?: Bitmap.createScaledBitmap(BitmapFactory.decodeResource(Managment.globalContext!!.resources, R.drawable.close_bg), (spring.currentValue + ChatHeads.CLOSE_SIZE).toInt(), (spring.currentValue + ChatHeads.CLOSE_SIZE).toInt(), false)
                Managment.backgroundCloseIcon?.let {
                    bitmapBg = Bitmap.createScaledBitmap(it, (spring.currentValue + ChatHeads.CLOSE_SIZE).toInt(), (spring.currentValue + ChatHeads.CLOSE_SIZE).toInt(), false)
                }
                invalidate()
            }
        })
        springAlpha.addListener(object : SimpleSpringListener() {
            override fun onSpringUpdate(spring: Spring) {
                gradient.alpha = spring.currentValue.toFloat()
            }
        })
        springScale.springConfig = SpringConfigs.CLOSE_SCALE
        springY.springConfig = SpringConfigs.CLOSE_Y
        params.gravity = Gravity.START or Gravity.TOP
        gradientParams.gravity = Gravity.BOTTOM
        gradient.background = ContextCompat.getDrawable(context, R.drawable.gradient_bg)
        springAlpha.currentValue = 0.0
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) z = 100f
        chatHeads.addView(this, params)
        chatHeads.addView(gradient, gradientParams)
    }

    override fun onDraw(canvas: Canvas?) {
        bitmapBg?.let {
            canvas?.drawBitmap(it, width / 2 - it.width.toFloat() / 2, height / 2 - it.height.toFloat() / 2, paint)
        }
        bitmapClose?.let {
            canvas?.drawBitmap(it, width / 2 - it.width.toFloat() / 2, height / 2 - it.height.toFloat() / 2, paint)
        }
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/floating_chathead/SpringConfig.kt
================================================
package ni.devotion.floaty_head.floating_chathead

import com.facebook.rebound.SpringConfig

object SpringConfigs {
    val NOT_DRAGGING = SpringConfig.fromOrigamiTensionAndFriction(60.0, 7.5)
    val CAPTURING = SpringConfig.fromBouncinessAndSpeed(8.0, 40.0)
    val CLOSE_SCALE = SpringConfig.fromBouncinessAndSpeed(7.0, 25.0)
    val CLOSE_Y = SpringConfig.fromBouncinessAndSpeed(3.0, 3.0)
    val DRAGGING = SpringConfig.fromOrigamiTensionAndFriction(0.0, 5.0)
    val CONTENT_SCALE = SpringConfig.fromBouncinessAndSpeed(5.0, 40.0)
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/floating_chathead/WindowManagerHelper.kt
================================================
package ni.devotion.floaty_head.floating_chathead

import android.content.res.Resources
import android.os.Build
import android.view.WindowManager
import android.util.TypedValue

class WindowManagerHelper {
    companion object {
        fun getLayoutFlag(): Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        } else {
            WindowManager.LayoutParams.TYPE_PHONE
        }

        fun getScreenSize() = Resources.getSystem().displayMetrics
        fun dpToPx(dp: Float) = (dp * Resources.getSystem().displayMetrics.density).toInt()
        fun spToPx(sp: Float) = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, Resources.getSystem().displayMetrics)
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/models/Decoration.kt
================================================
package ni.devotion.floaty_head.models

import android.content.Context
import ni.devotion.floaty_head.utils.Commons
import ni.devotion.floaty_head.utils.NumberUtils

class Decoration(startColor: Any?, endColor: Any?, borderWidth: Any?, borderRadius: Any?, borderColor: Any?, context: Context?) {
    val startColor: Int
    var endColor = 0
    val borderWidth: Int
    val borderRadius: Float
    val borderColor: Int
    var isGradient = false

    init {
        this.startColor = NumberUtils.getInt(startColor)
        if (endColor != null) {
            this.endColor = NumberUtils.getInt(endColor)
            isGradient = true
        } else {
            isGradient = false
        }
        this.borderWidth = Commons.getPixelsFromDp(context!!, NumberUtils.getInt(borderWidth))
        this.borderRadius = Commons.getPixelsFromDp(context, NumberUtils.getFloat(borderRadius))
        this.borderColor = NumberUtils.getInt(borderColor)
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/models/Margin.kt
================================================
package ni.devotion.floaty_head.models

import ni.devotion.floaty_head.utils.NumberUtils
import android.content.Context
import ni.devotion.floaty_head.utils.Commons

class Margin(left: Any?, top: Any?, right: Any?, bottom: Any?, context: Context?) {
    val left: Int
    val top: Int
    val right: Int
    val bottom: Int

    init {
        this.left = Commons.getPixelsFromDp(context!!, NumberUtils.getInt(left))
        this.top = Commons.getPixelsFromDp(context, NumberUtils.getInt(top))
        this.right = Commons.getPixelsFromDp(context, NumberUtils.getInt(right))
        this.bottom = Commons.getPixelsFromDp(context, NumberUtils.getInt(bottom))
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/models/Padding.kt
================================================
package ni.devotion.floaty_head.models

import ni.devotion.floaty_head.utils.NumberUtils
import android.content.Context
import ni.devotion.floaty_head.utils.Commons

class Padding(left: Any?, top: Any?, right: Any?, bottom: Any?, context: Context?) {
    val left: Int
    val top: Int
    val right: Int
    val bottom: Int

    init {
        this.left = Commons.getPixelsFromDp(context!!, NumberUtils.getInt(left))
        this.top = Commons.getPixelsFromDp(context, NumberUtils.getInt(top))
        this.right = Commons.getPixelsFromDp(context, NumberUtils.getInt(right))
        this.bottom = Commons.getPixelsFromDp(context, NumberUtils.getInt(bottom))
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/services/FloatyContentJobService.kt
================================================
package ni.devotion.floaty_head.services

import android.app.*
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.util.Log
import android.view.WindowManager
import androidx.core.app.NotificationCompat
import android.graphics.PixelFormat
import android.view.WindowManager.LayoutParams
import ni.devotion.floaty_head.FloatyHeadPlugin
import ni.devotion.floaty_head.R
import ni.devotion.floaty_head.floating_chathead.ChatHeads
import ni.devotion.floaty_head.utils.Constants.INTENT_EXTRA_PARAMS_MAP
import ni.devotion.floaty_head.utils.Managment
import java.lang.Exception
import java.util.*


class FloatyContentJobService : Service() {
    companion object {
        var instance: FloatyContentJobService?= null
        val CHANNEL_ID = "ForegroundServiceChannel"
        val NOTIFICATION_ID = 1
        val INTENT_EXTRA_IS_UPDATE_WINDOW = "IsUpdateWindow"
        val INTENT_EXTRA_IS_CLOSE_WINDOW = "IsCloseWindow"
    }
    var windowManager: WindowManager? = null
    var context: Context? = null
    var notification: Notification? = null
    var chatHeads: ChatHeads? = null

    override fun onCreate() {
        instance = this
        createNotificationChannel()
        showNotificationManager()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if(null != intent && intent.extras != null) {
            val paramsMap = (intent.getSerializableExtra(INTENT_EXTRA_PARAMS_MAP) as HashMap<String, Any>?)
            assert(paramsMap != null)
            context = this
            val isCloseWindow = intent.getBooleanExtra(INTENT_EXTRA_IS_CLOSE_WINDOW, false)

            //createWindow()
            if(!isCloseWindow){
                val isUpdateWindow = intent.getBooleanExtra(INTENT_EXTRA_IS_CLOSE_WINDOW, false)
                if(isUpdateWindow){
                    //updateWindow()
                }else{
                    createWindow()
                }
            }else{
                closeWindow(true)
            }
        }
        return START_STICKY
    }

    fun closeWindow(isEverythingDone: Boolean){
        try {
            windowManager?.let { wm ->
                chatHeads?.let { ch ->
                    ch.removeAllViews()
                    wm.removeView(ch)
                    chatHeads = null
                }
            }
            windowManager = null
            if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q){
                Managment.activity?.stopService(Intent(Managment.activity?.applicationContext, this@FloatyContentJobService::class.java))
            }else{
                Managment.activity?.startForegroundService(Intent(Managment.activity?.applicationContext, this@FloatyContentJobService::class.java))
            }
        }catch(ex: Exception){
            Log.e("TAG", "View not found")
        }
        if(isEverythingDone) stopSelf()
    }

    fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val serviceChannel = NotificationChannel(
                    CHANNEL_ID,
                    "Foreground Service Channel",
                    NotificationManager.IMPORTANCE_DEFAULT
            )
            val manager = getSystemService(NotificationManager::class.java)
            assert(manager != null)
            manager.createNotificationChannel(serviceChannel)
        }
    }

    fun createWindow() {
        setWindowManager()
        val params:WindowManager.LayoutParams
        params = LayoutParams()
        params.width = LayoutParams.MATCH_PARENT
        params.height = LayoutParams.WRAP_CONTENT
        params.format = PixelFormat.TRANSLUCENT
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
        params.type = LayoutParams.TYPE_APPLICATION_OVERLAY
        params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL or LayoutParams.FLAG_SHOW_WHEN_LOCKED or LayoutParams.FLAG_NOT_FOCUSABLE
        }
        else
        {
        params.type = LayoutParams.TYPE_SYSTEM_ALERT or LayoutParams.TYPE_SYSTEM_OVERLAY
        params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL or LayoutParams.FLAG_NOT_FOCUSABLE
        }
        chatHeads = ChatHeads(this)
        chatHeads?.add()
    }

    fun showNotificationManager() {
        val notificationIntent = Intent(this, FloatyHeadPlugin::class.java)
        val pendingIntent = PendingIntent.getActivity(this,
                0, notificationIntent, 0)
        notification = if(Managment.notificationIcon == null) {
            NotificationCompat.Builder(this, "ForegroundServiceChannel")
                    .setContentTitle("${Managment.notificationTitle} is Currently Running")
                    .setSmallIcon(R.drawable.ic_chathead)
                    .setContentIntent(pendingIntent)
                    .build()
        }else{
            NotificationCompat.Builder(this, "ForegroundServiceChannel")
                    .setContentTitle("${Managment.notificationTitle} is Currently Running")
                    .setLargeIcon(Managment.notificationIcon)
                    .setContentIntent(pendingIntent)
                    .build()
        }
        startForeground(NOTIFICATION_ID, notification)
    }

    override fun onBind(p0: Intent?): IBinder? {
        return null
    }

    override fun onDestroy() {
        val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        assert(notificationManager != null)
        notificationManager.cancel(NOTIFICATION_ID)
        super.onDestroy()
    }

    private fun setWindowManager() = windowManager ?: run { windowManager = getSystemService(WINDOW_SERVICE) as WindowManager }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/services/FloatyIconService.kt
================================================
package ni.devotion.floaty_head.services

import android.annotation.SuppressLint
import android.app.*
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import ni.devotion.floaty_head.FloatyHeadPlugin
import ni.devotion.floaty_head.FloatyHeadPlugin.Companion.context
import ni.devotion.floaty_head.MainActivity
import ni.devotion.floaty_head.R
import ni.devotion.floaty_head.utils.Managment

class FloatyIconService: Service() {
    companion object {
        lateinit var instance: FloatyIconService
        var notificationManager: NotificationManager? = null
        var notification: Notification? = null
    }
    val channel_id = "2208"
    val floaty_notification_id = 2208

    override fun onCreate() {
        instance = this
        super.onCreate()
    }

    @SuppressLint("NewApi")
    private fun initNotificationManager() {
        notificationManager ?: run {
            context?.let {
                notificationManager = it.getSystemService(NotificationManager::class.java)
            } ?: run {
                Log.e("TAG", "Context is null. Can't show the FloatyNotification")
                return
            }
        }
    }

    fun createNotificationChannel() {
        initNotificationManager()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val serviceChannel = NotificationChannel(
                    channel_id,
                    "Foreground Service Channel",
                    NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager?.createNotificationChannel(serviceChannel)
        }
    }

    fun showNotificationManager() {
        val notificationIntent = Intent(this, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(this,
                0, notificationIntent, 0)
        notification = if(Managment.notificationIcon == null) {
            NotificationCompat.Builder(this, "ForegroundServiceChannel")
                    .setContentTitle("${Managment.notificationTitle} is Currently Running")
                    .setSmallIcon(R.drawable.ic_chathead)
                    .setContentIntent(pendingIntent)
                    .build()
        }else{
            NotificationCompat.Builder(this, "ForegroundServiceChannel")
                    .setContentTitle("${Managment.notificationTitle} is Currently Running")
                    .setLargeIcon(Managment.notificationIcon)
                    .setContentIntent(pendingIntent)
                    .build()
        }
        startForeground(floaty_notification_id, notification)
    }

    override fun onDestroy() {
        super.onDestroy()
    }

    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        createNotificationChannel()
        showNotificationManager()
        return START_NOT_STICKY
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/utils/Commons.kt
================================================
package ni.devotion.floaty_head.utils

import android.content.Context
import android.graphics.Typeface
import android.util.TypedValue
import android.view.Gravity
import android.widget.LinearLayout
import androidx.annotation.Nullable
import ni.devotion.floaty_head.models.Margin
import ni.devotion.floaty_head.utils.Constants.KEY_MARGIN


object Commons {
    fun getMapFromObject(map: Map<String, Any>, key: String?): Map<String, Any>? {
        return map[key] as Map<String, Any>?
    }

    fun getMapListFromObject(map: Map<String, Any>, key: String?): List<Map<String, Any>>? {
        return map[key] as List<Map<String, Any>>?
    }

    fun getSpFromPixels(context: Context, px: Float): Float {
        val scaledDensity = context.resources.displayMetrics.scaledDensity
        return px / scaledDensity
    }

    fun getPixelsFromDp(context: Context, dp: Int): Int {
        return if (dp == -1) -1 else TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, dp.toFloat(), context.resources.displayMetrics).toInt()
    }

    fun getPixelsFromDp(context: Context, dp: Float): Float {
        return if (dp == -1f) (-1).toFloat() else TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, dp, context.resources.displayMetrics)
    }

    fun getGravity(@Nullable gravityStr: String?, defVal: Int): Int {
        var gravity = defVal
        if (gravityStr != null) {
            when (gravityStr) {
                "top" -> gravity = Gravity.TOP
                "center" -> gravity = Gravity.CENTER
                "bottom" -> gravity = Gravity.BOTTOM
                "leading" -> gravity = Gravity.START
                "trailing" -> gravity = Gravity.END
            }
        }
        return gravity
    }

    fun getFontWeight(@Nullable fontWeightStr: String?, defVal: Int): Int {
        var fontWeight = defVal
        if (fontWeightStr != null) {
            fontWeight = when (fontWeightStr) {
                "normal" -> Typeface.NORMAL
                "bold" -> Typeface.BOLD
                "italic" -> Typeface.ITALIC
                "bold_italic" -> Typeface.BOLD_ITALIC
                else -> Typeface.NORMAL
            }
        }
        return fontWeight
    }

    fun setMargin(context: Context?, params: LinearLayout.LayoutParams, map: Map<String, Any?>) {
        val margin: Margin = UiBuilder.getMargin(context, map[KEY_MARGIN])
        params.setMargins(margin.left, margin.top, margin.right, margin.bottom)
    }
}


================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/utils/Constants.kt
================================================
package ni.devotion.floaty_head.utils

object Constants {

    val CHANNEL = "ni.devotion.floaty_head"
    val METHOD_CHANNEL = "ni.devotion/floaty_head"
    val BACKGROUND_CHANNEL = "ni.devotion.floaty_head/background"

    val SHARED_PREF_FLOATY_HEAD = "ni.devotion.floaty_head"
    val CALLBACK_HANDLE_KEY = "callback_handler"
    val CODE_CALLBACK_HANDLE_KEY = "code_callback_handler"

    val INTENT_EXTRA_PARAMS_MAP = "intent_params_map"

    val CALLBACK_TYPE_ONCLICK = "onClick"

    //Internal plugin param map keys
    val KEY_HEADER = "header"
    val KEY_BODY = "body"
    val KEY_FOOTER = "footer"
    val KEY_IS_SHOW_FOOTER = "isShowFooter"
    val KEY_TITLE = "title"
    val KEY_SUBTITLE = "subTitle"
    val KEY_TAG = "tag"
    val KEY_TEXT = "text"
    val KEY_FONT_SIZE = "fontSize"
    val KEY_FONT_WEIGHT = "fontWeight"
    val KEY_TEXT_COLOR = "textColor"
    val KEY_BUTTON = "button"
    val KEY_BUTTONS_LIST = "buttons"
    val KEY_BUTTON_POSITION = "buttonPosition"
    val KEY_BUTTONS_LIST_POSITION = "buttonsPosition"
    val KEY_DECORATION = "decoration"
    val KEY_START_COLOR = "startColor"
    val KEY_END_COLOR = "endColor"
    val KEY_BORDER_WIDTH = "borderWidth"
    val KEY_BORDER_COLOR = "borderColor"
    val KEY_BORDER_RADIUS = "borderRadius"
    val KEY_GRAVITY = "gravity"
    val KEY_PADDING = "padding"
    val KEY_MARGIN = "margin"
    val KEY_LEFT = "left"
    val KEY_TOP = "top"
    val KEY_RIGHT = "right"
    val KEY_BOTTOM = "bottom"
    val KEY_WIDTH = "width"
    val KEY_HEIGHT = "height"
    val KEY_ROWS = "rows"
    val KEY_COLUMNS = "columns"
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/utils/ImageHelper.kt
================================================
package ni.devotion.floaty_head.utils

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.os.Build
import androidx.core.content.ContextCompat
import ni.devotion.floaty_head.floating_chathead.ChatHeads

class ImageHelper {
    companion object {
        fun getCircularBitmap(bitmap: Bitmap): Bitmap {
            val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
            val canvas = Canvas(output)
            val paint = Paint()
            val rect = Rect(0, 0, bitmap.width, bitmap.height)
            paint.isAntiAlias = true
            canvas.drawARGB(0, 0, 0, 0)
            paint.color = -0xbdbdbe
            canvas.drawCircle(output.width.toFloat() / 2, output.height.toFloat() / 2, output.width.toFloat() / 2, paint)
            paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
            canvas.drawBitmap(bitmap, rect, rect, paint)
            return Bitmap.createScaledBitmap(output, ChatHeads.CHAT_HEAD_SIZE, ChatHeads.CHAT_HEAD_SIZE, true)
        }

        fun addShadow(src: Bitmap): Bitmap {
            val bmOut = Bitmap.createBitmap(src.width + 10, src.height + 20, Bitmap.Config.ARGB_8888)
            val centerX = (bmOut.width / 2 - src.width / 2).toFloat()
            val centerY = (bmOut.height / 2 - src.height / 2).toFloat()
            val canvas = Canvas(bmOut)
            canvas.drawColor(0, PorterDuff.Mode.CLEAR)
            val ptBlur = Paint()
            ptBlur.maskFilter = BlurMaskFilter(6f, BlurMaskFilter.Blur.NORMAL)
            val offsetXY = IntArray(2)
            val bmAlpha = src.extractAlpha(ptBlur, offsetXY)
            val ptAlphaColor = Paint()
            ptAlphaColor.color = Color.argb(80, 0, 0, 0)
            canvas.drawBitmap(bmAlpha, centerX + offsetXY[0], centerY  + offsetXY[1] + 4f, ptAlphaColor)
            bmAlpha.recycle()
            canvas.drawBitmap(src, centerX, centerY,null)
            return bmOut
        }
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    fun drawableFromVector(context: Context, drawableId: Int): Drawable {
        val drawable = when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> context.getDrawable(drawableId)
            else -> ContextCompat.getDrawable(context, drawableId)
        }
        val bitmap = Bitmap.createBitmap(drawable!!.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        drawable.setBounds(0, 0, canvas.width, canvas.height)
        drawable.draw(canvas)
        return BitmapDrawable(context.resources, Bitmap.createScaledBitmap(bitmap, drawable.intrinsicWidth, drawable.intrinsicHeight, false))
    }
}


================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/utils/Managment.kt
================================================
package ni.devotion.floaty_head.utils

import android.app.ActionBar
import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.view.View
import android.widget.FrameLayout
import java.util.HashMap
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.Registrar
import ni.devotion.floaty_head.services.FloatyIconService
import java.util.concurrent.atomic.AtomicBoolean

/**
 * Handle all the states of the project, and all the custom icons including the body that is gonna be displayed inside the chathead.
 */
object Managment {
    var floatingIcon: Bitmap? = null
    var closeIcon: Bitmap? = null
    var backgroundCloseIcon: Bitmap? = null
    var notificationTitle: String = "Floaty_head"
    var notificationIcon: Bitmap? = null
    var paramsMap: HashMap<String, Any>? = null
    var headersMap: Map<String, Any>? = null
    var bodyMap: Map<String, Any>? = null
    var footerMap: Map<String, Any>? = null
    var headerView: View? = null
    var bodyView: View? = null
    var footerView: View? = null
    var layoutParams: FrameLayout.LayoutParams? = null
    var pluginRegistrantC: PluginRegistry.PluginRegistrantCallback? = null
    var floatyIconService: FloatyIconService? = null
    var globalContext: Context? = null
    var activity: Activity? = null
    var sIsIsolateRunning = AtomicBoolean(false)
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/utils/NumberUtils.kt
================================================
package ni.devotion.floaty_head.utils

import android.util.Log

/**
 * Class used for convert any number to [float] or [int] and retrieve any number from an [any] object.
 */
object NumberUtils {
    private const val TAG = "NumberUtils"
    fun getFloat(`object`: Any?) = getNumber(`object`).toFloat()
    fun getInt(`object`: Any?) = getNumber(`object`).toInt()
    private fun getNumber(`object`: Any?): Number {
        var `val`: Number = 0
        if (`object` != null) {
            try {
                `val` = `object` as Number
            } catch (ex: Exception) {
                Log.d(TAG, ex.toString())
            }
        }
        return `val`
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/utils/UiBuilder.kt
================================================
package ni.devotion.floaty_head.utils

import android.content.Context
import android.graphics.Typeface
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.util.TypedValue
import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import ni.devotion.floaty_head.FloatyHeadPlugin
import ni.devotion.floaty_head.models.Decoration
import ni.devotion.floaty_head.models.Margin
import ni.devotion.floaty_head.models.Padding
import ni.devotion.floaty_head.utils.Constants.CALLBACK_TYPE_ONCLICK
import ni.devotion.floaty_head.utils.Constants.KEY_BORDER_COLOR
import ni.devotion.floaty_head.utils.Constants.KEY_BORDER_RADIUS
import ni.devotion.floaty_head.utils.Constants.KEY_BORDER_WIDTH
import ni.devotion.floaty_head.utils.Constants.KEY_BOTTOM
import ni.devotion.floaty_head.utils.Constants.KEY_DECORATION
import ni.devotion.floaty_head.utils.Constants.KEY_END_COLOR
import ni.devotion.floaty_head.utils.Constants.KEY_FONT_SIZE
import ni.devotion.floaty_head.utils.Constants.KEY_FONT_WEIGHT
import ni.devotion.floaty_head.utils.Constants.KEY_HEIGHT
import ni.devotion.floaty_head.utils.Constants.KEY_LEFT
import ni.devotion.floaty_head.utils.Constants.KEY_MARGIN
import ni.devotion.floaty_head.utils.Constants.KEY_PADDING
import ni.devotion.floaty_head.utils.Constants.KEY_RIGHT
import ni.devotion.floaty_head.utils.Constants.KEY_START_COLOR
import ni.devotion.floaty_head.utils.Constants.KEY_TAG
import ni.devotion.floaty_head.utils.Constants.KEY_TEXT
import ni.devotion.floaty_head.utils.Constants.KEY_TEXT_COLOR
import ni.devotion.floaty_head.utils.Constants.KEY_TOP
import ni.devotion.floaty_head.utils.Constants.KEY_WIDTH


/**
 * This class is responsible to create all the content that is displayed inside the chathead.
 * if you wanna add your own widget, please be sure to create your [function], also remember to
 * create your class with the styles and components needed for that widget to be displayed.
 */
object UiBuilder {
    fun getTextView(context: Context?, textMap: Map<String, Any>?): TextView? {
        if (textMap == null) return null
        val textView = TextView(context)
        textView.text = textMap[KEY_TEXT] as String?
        textView.setTypeface(textView.typeface, Commons.getFontWeight(textMap[KEY_FONT_WEIGHT] as String?, Typeface.NORMAL))
        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, NumberUtils.getFloat(textMap[KEY_FONT_SIZE]))
        textView.setTextColor(NumberUtils.getInt(textMap[KEY_TEXT_COLOR]))
        val padding: Padding = getPadding(context, textMap[KEY_PADDING])
        textView.setPadding(padding.left, padding.top, padding.right, padding.bottom)
        return textView
    }

    fun getPadding(context: Context?, `object`: Any?): Padding {
        val paddingMap = `object` as Map<String, Any>?
                ?: return Padding(0, 0, 0, 0, context)
        return Padding(paddingMap[KEY_LEFT], paddingMap[KEY_TOP], paddingMap[KEY_RIGHT], paddingMap[KEY_BOTTOM], context)
    }

    fun getMargin(context: Context?, `object`: Any?): Margin {
        val marginMap = `object` as Map<String, Any>?
                ?: return Margin(0, 0, 0, 0, context)
        return Margin(marginMap[KEY_LEFT], marginMap[KEY_TOP], marginMap[KEY_RIGHT], marginMap[KEY_BOTTOM], context)
    }

    fun getDecoration(context: Context?, `object`: Any?): Decoration? {
        val decorationMap = `object` as Map<String, Any>? ?: return null
        return Decoration(decorationMap[KEY_START_COLOR], decorationMap[KEY_END_COLOR],
                decorationMap[KEY_BORDER_WIDTH], decorationMap[KEY_BORDER_RADIUS],
                decorationMap[KEY_BORDER_COLOR], context)
    }

    fun getButtonView(context: Context?, buttonMap: Map<String, Any>?): Button? {
        buttonMap ?: return null
        val button = Button(context)
        val buttonText = getTextView(context, Commons.getMapFromObject(buttonMap, KEY_TEXT))!!
        button.text = buttonText.text
        val tag = buttonMap[KEY_TAG]
        button.tag = tag
        button.textSize = Commons.getSpFromPixels(context!!, buttonText.textSize)
        button.setTextColor(buttonText.textColors)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) button.elevation = 10f
        val params = LinearLayout.LayoutParams(
                Commons.getPixelsFromDp(context, buttonMap[KEY_WIDTH] as Int),
                Commons.getPixelsFromDp(context, buttonMap[KEY_HEIGHT] as Int),
                1.0f)
        val buttonMargin: Margin = getMargin(context, buttonMap[KEY_MARGIN])
        params.setMargins(buttonMargin.left, buttonMargin.top, buttonMargin.right, buttonMargin.bottom.coerceAtMost(4))
        button.layoutParams = params
        val padding: Padding = getPadding(context, buttonMap[KEY_PADDING])
        button.setPadding(padding.left, padding.top, padding.right, padding.bottom)
        val decoration: Decoration? = getDecoration(context, buttonMap[KEY_DECORATION])
        decoration?.let{
            val gd = getGradientDrawable(it)
            button.background = gd
        }
        button.setOnClickListener {
            if(!Managment.sIsIsolateRunning.get()){
                FloatyHeadPlugin.instance.startCallBackHandler(context)
            }
            FloatyHeadPlugin.instance.invokeCallBack(context, CALLBACK_TYPE_ONCLICK, tag!!)
        }
        return button
    }

    fun getGradientDrawable(decoration: Decoration?): GradientDrawable {
        val gd = GradientDrawable()
        if (decoration!!.isGradient) {
            val colors = intArrayOf(decoration.startColor, decoration.endColor)
            gd.colors = colors
            gd.orientation = GradientDrawable.Orientation.LEFT_RIGHT
        } else {
            gd.setColor(decoration.startColor)
        }
        gd.cornerRadius = decoration.borderRadius
        gd.setStroke(decoration.borderWidth, decoration.borderColor)
        return gd
    }
}

================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/views/BodyView.kt
================================================
package ni.devotion.floaty_head.views

import android.content.Context
import android.graphics.Color
import android.view.Gravity
import android.view.View
import android.widget.LinearLayout
import ni.devotion.floaty_head.utils.Commons.getGravity
import ni.devotion.floaty_head.utils.Commons.getMapFromObject
import ni.devotion.floaty_head.utils.Commons.setMargin
import ni.devotion.floaty_head.utils.Constants.KEY_COLUMNS
import ni.devotion.floaty_head.utils.Constants.KEY_DECORATION
import ni.devotion.floaty_head.utils.Constants.KEY_GRAVITY
import ni.devotion.floaty_head.utils.Constants.KEY_PADDING
import ni.devotion.floaty_head.utils.Constants.KEY_ROWS
import ni.devotion.floaty_head.utils.Constants.KEY_TEXT
import ni.devotion.floaty_head.utils.UiBuilder.getDecoration
import ni.devotion.floaty_head.utils.UiBuilder.getGradientDrawable
import ni.devotion.floaty_head.utils.UiBuilder.getPadding
import ni.devotion.floaty_head.utils.UiBuilder.getTextView


class BodyView(private val context: Context, private val bodyMap: Map<String, Any>) {
    val view: LinearLayout
        get() {
            val linearLayout = LinearLayout(context)
            linearLayout.orientation = LinearLayout.VERTICAL
            val decoration = getDecoration(context, bodyMap[KEY_DECORATION])
            if (decoration != null) {
                val gd = getGradientDrawable(decoration)
                linearLayout.background = gd
            } else {
                linearLayout.setBackgroundColor(Color.WHITE)
            }
            val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT)
            setMargin(context, params, bodyMap)
            linearLayout.layoutParams = params
            val padding = getPadding(context, bodyMap[KEY_PADDING])
            linearLayout.setPadding(padding.left, padding.top, padding.right, padding.bottom)
            val rowsMap = bodyMap[KEY_ROWS] as List<Map<String, Any>>?
            if (rowsMap != null) {
                for (i in rowsMap.indices) {
                    val row = rowsMap[i]
                    linearLayout.addView(createRow(row))
                }
            }
            return linearLayout
        }

    private fun createRow(rowMap: Map<String, Any>): View {
        val linearLayout = LinearLayout(context)
        linearLayout.orientation = LinearLayout.HORIZONTAL
        val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT)
        setMargin(context, params, rowMap)
        linearLayout.layoutParams = params
        linearLayout.gravity = getGravity(rowMap[KEY_GRAVITY] as String?, Gravity.START)
        val padding = getPadding(context, rowMap[KEY_PADDING])
        linearLayout.setPadding(padding.left, padding.top, padding.right, padding.bottom)
        val decoration = getDecoration(context, rowMap[KEY_DECORATION])
        if (decoration != null) {
            val gd = getGradientDrawable(decoration)
            linearLayout.background = gd
        }
        val columnsMap = rowMap[KEY_COLUMNS] as List<Map<String, Any>>?
        if (columnsMap != null) {
            for (j in columnsMap.indices) {
                val column = columnsMap[j]
                linearLayout.addView(createColumn(column))
            }
        }
        return linearLayout
    }

    private fun createColumn(columnMap: Map<String, Any>): View {
        val columnLayout = LinearLayout(context)
        columnLayout.orientation = LinearLayout.HORIZONTAL
        val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT)
        setMargin(context, params, columnMap)
        columnLayout.layoutParams = params
        val padding = getPadding(context, columnMap[KEY_PADDING])
        columnLayout.setPadding(padding.left, padding.top, padding.right, padding.bottom)
        val decoration = getDecoration(context, columnMap[KEY_DECORATION])
        if (decoration != null) {
            val gd = getGradientDrawable(decoration)
            columnLayout.background = gd
        }
        val textView = getTextView(context, getMapFromObject(columnMap, KEY_TEXT))
        columnLayout.addView(textView)
        return columnLayout
    }
}


================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/views/FooterView.kt
================================================
package ni.devotion.floaty_head.views

import android.content.Context
import android.view.Gravity
import android.view.ViewGroup
import android.widget.Button
import android.widget.LinearLayout
import ni.devotion.floaty_head.utils.Commons.getGravity
import ni.devotion.floaty_head.utils.Commons.getMapFromObject
import ni.devotion.floaty_head.utils.Commons.getMapListFromObject
import ni.devotion.floaty_head.utils.Constants.KEY_BUTTONS_LIST
import ni.devotion.floaty_head.utils.Constants.KEY_BUTTONS_LIST_POSITION
import ni.devotion.floaty_head.utils.Constants.KEY_DECORATION
import ni.devotion.floaty_head.utils.Constants.KEY_IS_SHOW_FOOTER
import ni.devotion.floaty_head.utils.Constants.KEY_PADDING
import ni.devotion.floaty_head.utils.Constants.KEY_TEXT
import ni.devotion.floaty_head.utils.UiBuilder.getButtonView
import ni.devotion.floaty_head.utils.UiBuilder.getDecoration
import ni.devotion.floaty_head.utils.UiBuilder.getGradientDrawable
import ni.devotion.floaty_head.utils.UiBuilder.getPadding
import ni.devotion.floaty_head.utils.UiBuilder.getTextView


class FooterView(private val context: Context, private val footerMap: Map<String, Any>) {
    val view: LinearLayout
        get() {
            val linearLayout = LinearLayout(context)
            linearLayout.orientation = LinearLayout.HORIZONTAL
            val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT)
            val footerPadding = getPadding(context, footerMap[KEY_PADDING])
            linearLayout.setPadding(footerPadding.left, footerPadding.top, footerPadding.right, footerPadding.bottom)
            linearLayout.layoutParams = params
            val decoration = getDecoration(context, footerMap[KEY_DECORATION])
            if (decoration != null) {
                val gd = getGradientDrawable(decoration)
                linearLayout.background = gd
            }
            if (footerMap[KEY_IS_SHOW_FOOTER] as Boolean) {
                val textMap = getMapFromObject(footerMap, KEY_TEXT)
                val buttonsMap: List<Map<String, Any>>? = getMapListFromObject(footerMap, KEY_BUTTONS_LIST)
                val textView = getTextView(context, textMap)
                val buttonsView: MutableList<Button?> = ArrayList()
                for (buttonMap in buttonsMap!!) {
                    buttonsView.add(getButtonView(context, buttonMap))
                }
                val buttonsPosition = footerMap[KEY_BUTTONS_LIST_POSITION] as String?
                if (textView != null) {
                    if (buttonsView.size > 0) {
                        if ("leading" == buttonsPosition) {
                            for (buttonView in buttonsView) {
                                linearLayout.addView(buttonView)
                            }
                            linearLayout.addView(textView)
                        } else {
                            val param = LinearLayout.LayoutParams(
                                    ViewGroup.LayoutParams.WRAP_CONTENT,
                                    ViewGroup.LayoutParams.WRAP_CONTENT,
                                    1.0f
                            )
                            textView.layoutParams = param
                            linearLayout.addView(textView)
                            for (buttonView in buttonsView) {
                                linearLayout.addView(buttonView)
                            }
                        }
                    } else {
                        linearLayout.addView(textView)
                    }
                } else {
                    for (buttonView in buttonsView) {
                        linearLayout.addView(buttonView)
                    }
                    linearLayout.gravity = getGravity(buttonsPosition, Gravity.FILL)
                }
            }
            return linearLayout
        }

}


================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/views/HeaderView.kt
================================================
package ni.devotion.floaty_head.views

import android.content.Context
import android.graphics.Color
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.RelativeLayout
import ni.devotion.floaty_head.utils.Commons.getMapFromObject
import ni.devotion.floaty_head.utils.Constants.KEY_BUTTON
import ni.devotion.floaty_head.utils.Constants.KEY_BUTTON_POSITION
import ni.devotion.floaty_head.utils.Constants.KEY_DECORATION
import ni.devotion.floaty_head.utils.Constants.KEY_PADDING
import ni.devotion.floaty_head.utils.Constants.KEY_SUBTITLE
import ni.devotion.floaty_head.utils.Constants.KEY_TITLE
import ni.devotion.floaty_head.utils.UiBuilder.getButtonView
import ni.devotion.floaty_head.utils.UiBuilder.getDecoration
import ni.devotion.floaty_head.utils.UiBuilder.getGradientDrawable
import ni.devotion.floaty_head.utils.UiBuilder.getPadding
import ni.devotion.floaty_head.utils.UiBuilder.getTextView


class HeaderView(private val context: Context, private val headerMap: Map<String, Any>) {
    val relativeView: RelativeLayout
        get() {
            val relativeLayout = RelativeLayout(context)
            relativeLayout.layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT)
            val decoration = getDecoration(context, headerMap[KEY_DECORATION])
            if (decoration != null) {
                val gd = getGradientDrawable(decoration)
                relativeLayout.background = gd
            } else {
                relativeLayout.setBackgroundColor(Color.WHITE)
            }
            val titleMap = getMapFromObject(headerMap, KEY_TITLE)
            val subTitleMap = getMapFromObject(headerMap, KEY_SUBTITLE)
            val buttonMap = getMapFromObject(headerMap, KEY_BUTTON)
            val padding = getPadding(context, headerMap[KEY_PADDING])
            relativeLayout.setPadding(padding.left, padding.top, padding.right, padding.bottom)
            val isShowButton = buttonMap != null
            assert(titleMap != null)
            val textColumn = createTextColumn(titleMap, subTitleMap)
            if (isShowButton) {
                val buttonPosition = headerMap[KEY_BUTTON_POSITION] as String?
                val button = getButtonView(context, buttonMap)
                if ("leading" == buttonPosition) {
                    relativeLayout.addView(button)
                    relativeLayout.addView(textColumn)
                } else {
                    relativeLayout.addView(textColumn)
                    relativeLayout.addView(button)
                }
            } else {
                relativeLayout.addView(textColumn)
            }
            return relativeLayout
        }

    //assert titleMap != null;
    val view: LinearLayout
        get() {
            val linearLayout = LinearLayout(context)
            linearLayout.orientation = LinearLayout.HORIZONTAL
            val decoration = getDecoration(context, headerMap[KEY_DECORATION])
            if (decoration != null) {
                val gd = getGradientDrawable(decoration)
                linearLayout.background = gd
            } else {
                linearLayout.setBackgroundColor(Color.WHITE)
            }
            linearLayout.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
            val titleMap = getMapFromObject(headerMap, KEY_TITLE)
            val subTitleMap = getMapFromObject(headerMap, KEY_SUBTITLE)
            val buttonMap = getMapFromObject(headerMap, KEY_BUTTON)
            val padding = getPadding(context, headerMap[KEY_PADDING])
            linearLayout.setPadding(padding.left, padding.top, padding.right, padding.bottom)
            val isShowButton = buttonMap != null
            assert(titleMap != null)
            val textColumn = createTextColumn(titleMap, subTitleMap)
            if (isShowButton) {
                val buttonPosition = headerMap[KEY_BUTTON_POSITION] as String?
                val button = getButtonView(context, buttonMap)
                if ("leading" == buttonPosition) {
                    linearLayout.addView(button)
                    textColumn?.let{
                        linearLayout.addView(it)
                    }
                } else {
                    textColumn?.let{
                        val param = LinearLayout.LayoutParams(
                                ViewGroup.LayoutParams.WRAP_CONTENT,
                                ViewGroup.LayoutParams.WRAP_CONTENT,
                                1.0f
                        )
                        it.layoutParams = param
                        linearLayout.addView(it)
                    }
                    linearLayout.addView(button)
                }
            } else {
                linearLayout.addView(textColumn)
            }
            return linearLayout
        }


    fun createTextColumn(titleMap: Map<String, Any>?, subTitleMap: Map<String, Any>?): View? {
        val titleView = getTextView(context, titleMap)
        if (subTitleMap != null) {
            val linearLayout = LinearLayout(context)
            linearLayout.orientation = LinearLayout.VERTICAL
            linearLayout.addView(titleView)
            linearLayout.addView(getTextView(context, subTitleMap))
            return linearLayout
        }
        return titleView
    }
}


================================================
FILE: android/src/main/kotlin/ni/devotion/floaty_head/views/RowView.kt
================================================
package ni.devotion.floaty_head.views

import android.content.Context
import android.widget.LinearLayout
import ni.devotion.floaty_head.utils.Commons.getMapFromObject
import ni.devotion.floaty_head.utils.UiBuilder.getPadding
import ni.devotion.floaty_head.utils.UiBuilder.getTextView

class RowView(private val context: Context, private val rowMap: Map<String, Any>) {
    val view: LinearLayout
        get() {
            val linearLayout = LinearLayout(context)
            linearLayout.orientation = LinearLayout.HORIZONTAL
            linearLayout.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
            val columnsMap = rowMap["columns"] as List<Map<String, Any>>?
            val padding = getPadding(context, getMapFromObject(rowMap, "padding"))
            linearLayout.setPadding(padding.left, padding.top, padding.right, padding.bottom)
            if (columnsMap != null) {
                for (i in columnsMap.indices) {
                    val eachColumn = columnsMap[i]
                    val textView = getTextView(context, getMapFromObject(eachColumn, "text"))
                    linearLayout.addView(textView)
                }
            }
            return linearLayout
        }

}

================================================
FILE: android/src/main/res/drawable/gradient_bg.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
            android:startColor="#59000000"
            android:endColor="#00ffffff"
            android:angle="90"
    />
</shape>

================================================
FILE: android/src/main/res/drawable/ic_chathead.xml
================================================
<vector android:height="64dp" android:viewportHeight="512"
    android:viewportWidth="512" android:width="64dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#64B5F6" android:pathData="M448,170.85v0.5c0,99 -80,179.4 -178.2,179.4h-24.3l-34,45.6c-9.1,12.2 -23.6,19.6 -38.9,19.6c-4.2,0 -8.4,-0.6 -12.6,-1.7c20.3,20.8 48.7,33.7 80,33.7h40l43.2,57.6c3.1,4.1 7.9,6.4 12.8,6.4c1.7,0 3.4,-0.3 5.1,-0.8c6.5,-2.2 10.9,-8.3 10.9,-15.2v-48h48c61.8,0 112,-50.2 112,-112v-64C512,227.45 485.8,188.85 448,170.85z"/>
    <path android:fillColor="#2196F3" android:pathData="M272,0.05H144c-79.4,0 -144,64.6 -144,144v32c0,79.4 64.6,144 144,144h16v48c0,6.9 4.4,13 10.9,15.2c1.7,0.5 3.4,0.8 5.1,0.8c4.9,0 9.7,-2.3 12.8,-6.4l43.2,-57.6h40c79.4,0 144,-64.6 144,-144v-32C416,64.65 351.4,0.05 272,0.05z"/>
</vector>


================================================
FILE: android/src/main/res/layout/fragment_float.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/contentLayout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_marginTop="80dp"
    android:orientation="vertical"
    android:clickable="true">
</LinearLayout>

================================================
FILE: android/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#71b5bd</color>
    <color name="colorPrimaryDark">#4A777C</color>
    <color name="colorAccent">#2e4f61</color>

    <color name="colorPrimaryDarkMode">#8e4a42</color>
    <color name="colorPrimarySubDarkMode">#b58883</color>
    <color name="colorAccentDarkMode">#d1b09e</color>

    <color name="transparent">#00ffffff</color>
    <color name="md_semitrans_blue">#47d500f9</color>
    <color name="md_semitran_green">#6A2ACADF</color>
    <color name="md_semitrans_green">#6B8BC34A</color>
    <color name="colorDivider">#1f000000</color>

    <!--reds-->
    <color name="md_red_50">#FFEBEE</color>
    <color name="md_red_100">#FFCDD2</color>
    <color name="md_red_200">#EF9A9A</color>
    <color name="md_red_300">#E57373</color>
    <color name="md_red_400">#EF5350</color>
    <color name="md_red_500">#F44336</color>
    <color name="md_red_600">#E53935</color>
    <color name="md_red_700">#D32F2F</color>
    <color name="md_red_800">#C62828</color>
    <color name="md_red_900">#B71C1C</color>
    <color name="md_red_A100">#FF8A80</color>
    <color name="md_red_A200">#FF5252</color>
    <color name="md_red_A400">#FF1744</color>
    <color name="md_red_A700">#D50000</color>

    <!-- pinks -->
    <color name="md_pink_50">#FCE4EC</color>
    <color name="md_pink_100">#F8BBD0</color>
    <color name="md_pink_200">#F48FB1</color>
    <color name="md_pink_300">#F06292</color>
    <color name="md_pink_400">#EC407A</color>
    <color name="md_pink_500">#E91E63</color>
    <color name="md_pink_600">#D81B60</color>
    <color name="md_pink_700">#C2185B</color>
    <color name="md_pink_800">#AD1457</color>
    <color name="md_pink_900">#880E4F</color>
    <color name="md_pink_A100">#FF80AB</color>
    <color name="md_pink_A200">#FF4081</color>
    <color name="md_pink_A400">#F50057</color>
    <color name="md_pink_A700">#C51162</color>

    <!-- purples -->
    <color name="md_purple_50">#F3E5F5</color>
    <color name="md_purple_100">#E1BEE7</color>
    <color name="md_purple_200">#CE93D8</color>
    <color name="md_purple_300">#BA68C8</color>
    <color name="md_purple_400">#AB47BC</color>
    <color name="md_purple_500">#9C27B0</color>
    <color name="md_purple_600">#8E24AA</color>
    <color name="md_purple_700">#7B1FA2</color>
    <color name="md_purple_800">#6A1B9A</color>
    <color name="md_purple_900">#4A148C</color>
    <color name="md_purple_A100">#EA80FC</color>
    <color name="md_purple_A200">#E040FB</color>
    <color name="md_purple_A400">#D500F9</color>
    <color name="md_purple_A700">#AA00FF</color>

    <!-- deep purples -->
    <color name="md_deep_purple_50">#EDE7F6</color>
    <color name="md_deep_purple_100">#D1C4E9</color>
    <color name="md_deep_purple_200">#B39DDB</color>
    <color name="md_deep_purple_300">#9575CD</color>
    <color name="md_deep_purple_400">#7E57C2</color>
    <color name="md_deep_purple_500">#673AB7</color>
    <color name="md_deep_purple_600">#5E35B1</color>
    <color name="md_deep_purple_700">#512DA8</color>
    <color name="md_deep_purple_800">#4527A0</color>
    <color name="md_deep_purple_900">#311B92</color>
    <color name="md_deep_purple_A100">#B388FF</color>
    <color name="md_deep_purple_A200">#7C4DFF</color>
    <color name="md_deep_purple_A400">#651FFF</color>
    <color name="md_deep_purple_A700">#6200EA</color>

    <!-- indigo -->
    <color name="md_indigo_50">#E8EAF6</color>
    <color name="md_indigo_100">#C5CAE9</color>
    <color name="md_indigo_200">#9FA8DA</color>
    <color name="md_indigo_300">#7986CB</color>
    <color name="md_indigo_400">#5C6BC0</color>
    <color name="md_indigo_500">#3F51B5</color>
    <color name="md_indigo_600">#3949AB</color>
    <color name="md_indigo_700">#303F9F</color>
    <color name="md_indigo_800">#283593</color>
    <color name="md_indigo_900">#1A237E</color>
    <color name="md_indigo_A100">#8C9EFF</color>
    <color name="md_indigo_A200">#536DFE</color>
    <color name="md_indigo_A400">#3D5AFE</color>
    <color name="md_indigo_A700">#304FFE</color>

    <!--blue-->
    <color name="md_blue_50">#E3F2FD</color>
    <color name="md_blue_100">#BBDEFB</color>
    <color name="md_blue_200">#90CAF9</color>
    <color name="md_blue_300">#64B5F6</color>
    <color name="md_blue_400">#42A5F5</color>
    <color name="md_blue_500">#2196F3</color>
    <color name="md_blue_600">#1E88E5</color>
    <color name="md_blue_700">#1976D2</color>
    <color name="md_blue_800">#1565C0</color>
    <color name="md_blue_900">#0D47A1</color>
    <color name="md_blue_A100">#82B1FF</color>
    <color name="md_blue_A200">#448AFF</color>
    <color name="md_blue_A400">#2979FF</color>
    <color name="md_blue_A700">#2962FF</color>

    <!-- light blue-->
    <color name="md_light_blue_50">#E1F5FE</color>
    <color name="md_light_blue_100">#B3E5FC</color>
    <color name="md_light_blue_200">#81D4fA</color>
    <color name="md_light_blue_300">#4fC3F7</color>
    <color name="md_light_blue_400">#29B6FC</color>
    <color name="md_light_blue_500">#03A9F4</color>
    <color name="md_light_blue_600">#039BE5</color>
    <color name="md_light_blue_700">#0288D1</color>
    <color name="md_light_blue_800">#0277BD</color>
    <color name="md_light_blue_900">#01579B</color>
    <color name="md_light_blue_A100">#80D8FF</color>
    <color name="md_light_blue_A200">#40C4FF</color>
    <color name="md_light_blue_A400">#00B0FF</color>
    <color name="md_light_blue_A700">#0091EA</color>

    <!-- cyan -->
    <color name="md_cyan_50">#E0F7FA</color>
    <color name="md_cyan_100">#B2EBF2</color>
    <color name="md_cyan_200">#80DEEA</color>
    <color name="md_cyan_300">#4DD0E1</color>
    <color name="md_cyan_400">#26C6DA</color>
    <color name="md_cyan_500">#00BCD4</color>
    <color name="md_cyan_600">#00ACC1</color>
    <color name="md_cyan_700">#0097A7</color>
    <color name="md_cyan_800">#00838F</color>
    <color name="md_cyan_900">#006064</color>
    <color name="md_cyan_A100">#84FFFF</color>
    <color name="md_cyan_A200">#18FFFF</color>
    <color name="md_cyan_A400">#00E5FF</color>
    <color name="md_cyan_A700">#00B8D4</color>

    <!-- teal -->
    <color name="md_teal_50">#E0F2F1</color>
    <color name="md_teal_100">#B2DFDB</color>
    <color name="md_teal_200">#80CBC4</color>
    <color name="md_teal_300">#4DB6AC</color>
    <color name="md_teal_400">#26A69A</color>
    <color name="md_teal_500">#009688</color>
    <color name="md_teal_600">#00897B</color>
    <color name="md_teal_700">#00796B</color>
    <color name="md_teal_800">#00695C</color>
    <color name="md_teal_900">#004D40</color>
    <color name="md_teal_A100">#A7FFEB</color>
    <color name="md_teal_A200">#64FFDA</color>
    <color name="md_teal_A400">#1DE9B6</color>
    <color name="md_teal_A700">#00BFA5</color>

    <!-- green -->
    <color name="md_green_50">#E8F5E9</color>
    <color name="md_green_100">#C8E6C9</color>
    <color name="md_green_200">#A5D6A7</color>
    <color name="md_green_300">#81C784</color>
    <color name="md_green_400">#66BB6A</color>
    <color name="md_green_500">#4CAF50</color>
    <color name="md_green_600">#43A047</color>
    <color name="md_green_700">#388E3C</color>
    <color name="md_green_800">#2E7D32</color>
    <color name="md_green_900">#1B5E20</color>
    <color name="md_green_A100">#B9F6CA</color>
    <color name="md_green_A200">#69F0AE</color>
    <color name="md_green_A400">#00E676</color>
    <color name="md_green_A700">#00C853</color>

    <!--light green-->
    <color name="md_light_green_50">#F1F8E9</color>
    <color name="md_light_green_100">#DCEDC8</color>
    <color name="md_light_green_200">#C5E1A5</color>
    <color name="md_light_green_300">#AED581</color>
    <color name="md_light_green_400">#9CCC65</color>
    <color name="md_light_green_500">#8BC34A</color>
    <color name="md_light_green_600">#7CB342</color>
    <color name="md_light_green_700">#689F38</color>
    <color name="md_light_green_800">#558B2F</color>
    <color name="md_light_green_900">#33691E</color>
    <color name="md_light_green_A100">#CCFF90</color>
    <color name="md_light_green_A200">#B2FF59</color>
    <color name="md_light_green_A400">#76FF03</color>
    <color name="md_light_green_A700">#64DD17</color>

    <!-- lime-->
    <color name="md_lime_50">#F9FBE7</color>
    <color name="md_lime_100">#F0F4C3</color>
    <color name="md_lime_200">#E6EE9C</color>
    <color name="md_lime_300">#DCE775</color>
    <color name="md_lime_400">#D4E157</color>
    <color name="md_lime_500">#CDDC39</color>
    <color name="md_lime_600">#C0CA33</color>
    <color name="md_lime_700">#A4B42B</color>
    <color name="md_lime_800">#9E9D24</color>
    <color name="md_lime_900">#827717</color>
    <color name="md_lime_A100">#F4FF81</color>
    <color name="md_lime_A200">#EEFF41</color>
    <color name="md_lime_A400">#C6FF00</color>
    <color name="md_lime_A700">#AEEA00</color>

    <!--yellow -->
    <color name="md_yellow_50">#FFFDE7</color>
    <color name="md_yellow_100">#FFF9C4</color>
    <color name="md_yellow_200">#FFF590</color>
    <color name="md_yellow_300">#FFF176</color>
    <color name="md_yellow_400">#FFEE58</color>
    <color name="md_yellow_500">#FFEB3B</color>
    <color name="md_yellow_600">#FDD835</color>
    <color name="md_yellow_700">#FBC02D</color>
    <color name="md_yellow_800">#F9A825</color>
    <color name="md_yellow_900">#F57F17</color>
    <color name="md_yellow_A100">#FFFF82</color>
    <color name="md_yellow_A200">#FFFF00</color>
    <color name="md_yellow_A400">#FFEA00</color>
    <color name="md_yellow_A700">#FFD600</color>

    <!--amber-->
    <color name="md_amber_50">#FFF8E1</color>
    <color name="md_amber_100">#FFECB3</color>
    <color name="md_amber_200">#FFE082</color>
    <color name="md_amber_300">#FFD54F</color>
    <color name="md_amber_400">#FFCA28</color>
    <color name="md_amber_500">#FFC107</color>
    <color name="md_amber_600">#FFB300</color>
    <color name="md_amber_700">#FFA000</color>
    <color name="md_amber_800">#FF8F00</color>
    <color name="md_amber_900">#FF6F00</color>
    <color name="md_amber_A100">#FFE57F</color>
    <color name="md_amber_A200">#FFD740</color>
    <color name="md_amber_A400">#FFC400</color>
    <color name="md_amber_A700">#FFAB00</color>

    <!--orange-->
    <color name="md_orange_50">#FFF3E0</color>
    <color name="md_orange_100">#FFE0B2</color>
    <color name="md_orange_200">#FFCC80</color>
    <color name="md_orange_300">#FFB74D</color>
    <color name="md_orange_400">#FFA726</color>
    <color name="md_orange_500">#FF9800</color>
    <color name="md_orange_600">#FB8C00</color>
    <color name="md_orange_700">#F57C00</color>
    <color name="md_orange_800">#EF6C00</color>
    <color name="md_orange_900">#E65100</color>
    <color name="md_orange_A100">#FFD180</color>
    <color name="md_orange_A200">#FFAB40</color>
    <color name="md_orange_A400">#FF9100</color>
    <color name="md_orange_A700">#FF6D00</color>

    <!--deep orange-->
    <color name="md_deep_orange_50">#FBE9A7</color>
    <color name="md_deep_orange_100">#FFCCBC</color>
    <color name="md_deep_orange_200">#FFAB91</color>
    <color name="md_deep_orange_300">#FF8A65</color>
    <color name="md_deep_orange_400">#FF7043</color>
    <color name="md_deep_orange_500">#FF5722</color>
    <color name="md_deep_orange_600">#F4511E</color>
    <color name="md_deep_orange_700">#E64A19</color>
    <color name="md_deep_orange_800">#D84315</color>
    <color name="md_deep_orange_900">#BF360C</color>
    <color name="md_deep_orange_A100">#FF9E80</color>
    <color name="md_deep_orange_A200">#FF6E40</color>
    <color name="md_deep_orange_A400">#FF3D00</color>
    <color name="md_deep_orange_A700">#DD2600</color>

    <!--brown -->
    <color name="md_brown_50">#EFEBE9</color>
    <color name="md_brown_100">#D7CCC8</color>
    <color name="md_brown_200">#BCAAA4</color>
    <color name="md_brown_300">#A1887F</color>
    <color name="md_brown_400">#8D6E63</color>
    <color name="md_brown_500">#795548</color>
    <color name="md_brown_600">#6D4C41</color>
    <color name="md_brown_700">#5D4037</color>
    <color name="md_brown_800">#4E342E</color>
    <color name="md_brown_900">#3E2723</color>

    <!--grey-->
    <color name="md_grey_50">#FAFAFA</color>
    <color name="md_grey_100">#F5F5F5</color>
    <color name="md_grey_200">#EEEEEE</color>
    <color name="md_grey_300">#E0E0E0</color>
    <color name="md_grey_400">#BDBDBD</color>
    <color name="md_grey_500">#9E9E9E</color>
    <color name="md_grey_600">#757575</color>
    <color name="md_grey_700">#616161</color>
    <color name="md_grey_800">#424242</color>
    <color name="md_grey_900">#212121</color>
    <color name="md_black_1000">#000000</color>
    <color name="md_white_1000">#ffffff</color>
    <color name="md_white_900">#F8F3F3</color>

    <!--blue grey-->
    <color name="md_blue_grey_50">#ECEFF1</color>
    <color name="md_blue_grey_100">#CFD8DC</color>
    <color name="md_blue_grey_200">#B0BBC5</color>
    <color name="md_blue_grey_300">#90A4AE</color>
    <color name="md_blue_grey_400">#78909C</color>
    <color name="md_blue_grey_500">#607D8B</color>
    <color name="md_blue_grey_600">#546E7A</color>
    <color name="md_blue_grey_700">#455A64</color>
    <color name="md_blue_grey_800">#37474F</color>
    <color name="md_blue_grey_900">#263238</color>

    <color name="material_petal">#F98866</color>
    <color name="material_poppy">#FF420E</color>
    <color name="material_stem">#80BD9E</color>
    <color name="material_spring_green">#89DA59</color>

    <color name="black_overlay">#66000000</color>
</resources>


================================================
FILE: android/src/main/res/values/strings.xml
================================================
<resources>
    <!-- TODO: Remove or change this placeholder text -->
    <string name="hello_blank_fragment">Hello blank fragment</string>
</resources>

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

    <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.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

</resources>


================================================
FILE: example/.gitignore
================================================
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/

# Web related
lib/generated_plugin_registrant.dart

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json


================================================
FILE: example/.metadata
================================================
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
  revision: 216dee60c0cc9449f0b29bcf922974d612263e24
  channel: stable

project_type: app


================================================
FILE: example/README.md
================================================
# floaty_head_example

Demonstrates how to use the floaty_head plugin.

## Getting Started

This project is a starting point for a Flutter application.

A few resources to get you started if this is your first Flutter project:

- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)

For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.


================================================
FILE: example/android/.gitignore
================================================
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties


================================================
FILE: example/android/app/build.gradle
================================================
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
    compileSdkVersion 29

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    lintOptions {
        disable 'InvalidPackage'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "ni.devotion.floaty_head_example"
        minSdkVersion 16
        targetSdkVersion 29
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }
}

flutter {
    source '../..'
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}


================================================
FILE: example/android/app/src/debug/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ni.devotion.floaty_head_example">
    <!-- Flutter needs it to communicate with the running application
         to allow setting breakpoints, to provide hot reload, etc.
    -->
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>


================================================
FILE: example/android/app/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ni.devotion.floaty_head_example">
    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
         calls FlutterMain.startInitialization(this); in its onCreate method.
         In most cases you can leave this as-is, but you if you want to provide
         additional functionality it is fine to subclass or reimplement
         FlutterApplication and put your custom class here. -->
    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="floaty_head_example"
        android:hardwareAccelerated="false"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <!-- Displays an Android View that continues showing the launch screen
                 Drawable until Flutter paints its first frame, then this splash
                 screen fades out. A splash screen is useful to avoid any visual
                 gap between the end of Android's launch screen and the painting of
                 Flutter's first frame. -->
            <meta-data
              android:name="io.flutter.embedding.android.SplashScreenDrawable"
              android:resource="@drawable/launch_background"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>


================================================
FILE: example/android/app/src/main/kotlin/ni/devotion/floaty_head_example/Application.kt
================================================
package ni.devotion.floaty_head_example;

import androidx.annotation.NonNull
import ni.devotion.floaty_head.FloatyHeadPlugin
import ni.devotion.floaty_head.utils.Managment
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.embedding.engine.FlutterEngine

/**
 * For the [Application] class also use the
 * ```kotlin
 * Managment.pluginRegistrantC = this
 * ```
 * to set the callback between Kotlin/Dart.
 */
class Application : FlutterApplication(), PluginRegistry.PluginRegistrantCallback {
      override fun onCreate() {
          super.onCreate()
          FloatyHeadPlugin().setPluginRegistrant(this)
          Managment.pluginRegistrantC = this
      }

     override fun registerWith(registry: PluginRegistry) {
        FloatyHeadPlugin().registerWith(registry.registrarFor(this.packageName))
     }
     
  }

================================================
FILE: example/android/app/src/main/kotlin/ni/devotion/floaty_head_example/MainActivity.kt
================================================
package ni.devotion.floaty_head_example;

import android.os.Bundle;
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterActivity() {

    /**
     * When using this plugin please set the [Application().onCreate()]
     * if this isn't setted the chathead cannot communicate with the dart-client code
     */
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
        Application().onCreate()
    }
}

================================================
FILE: example/android/app/src/main/res/drawable/launch_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/white" />

    <!-- You can insert your own image assets here -->
    <!-- <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/launch_image" />
    </item> -->
</layer-list>


================================================
FILE: example/android/app/src/main/res/values/styles.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Theme applied to the Android Window while the process is starting -->
    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
        <!-- Show a splash screen on the activity. Automatically removed when
             Flutter draws its first frame -->
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>
    <!-- Theme applied to the Android Window as soon as the process has started.
         This theme determines the color of the Android Window while your
         Flutter UI initializes, as well as behind your Flutter UI while its
         running.
         
         This Theme is only used starting with V2 of Flutter's Android embedding. -->
    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
        <item name="android:windowBackground">@android:color/white</item>
    </style>
</resources>


================================================
FILE: example/android/app/src/profile/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ni.devotion.floaty_head_example">
    <!-- Flutter needs it to communicate with the running application
         to allow setting breakpoints, to provide hot reload, etc.
    -->
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>


================================================
FILE: example/android/build.gradle
================================================
buildscript {
    ext.kotlin_version = '1.3.50'
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

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

rootProject.buildDir = '../build'
subprojects {
    project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
    project.evaluationDependsOn(':app')
}

task clean(type: Delete) {
    delete rootProject.buildDir
}


================================================
FILE: example/android/gradle/wrapper/gradle-wrapper.properties
================================================
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip


================================================
FILE: example/android/gradle.properties
================================================
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
android.enableR8=true


================================================
FILE: example/android/settings.gradle
================================================
include ':app'

def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()

def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}

plugins.each { name, path ->
    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
    include ":$name"
    project(":$name").projectDir = pluginDirectory
}


================================================
FILE: example/android/settings_aar.gradle
================================================
include ':app'


================================================
FILE: example/lib/main.dart
================================================
import 'dart:async';

import 'package:floaty_head/floaty_head.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

Future<void> main() async {
  runApp(MaterialApp(home: Home()));
}

class Home extends StatefulWidget {
  _Home createState() => _Home();
}

class _Home extends State<Home> {
  final FloatyHead floatyHead = FloatyHead();

  final header = FloatyHeadHeader(
    title: FloatyHeadText(
      text: "Outgoing Call",
      fontSize: 10,
      textColor: Colors.black45,
      fontWeight: FontWeight.normal,
      padding: FloatyHeadPadding(
        bottom: 4,
        left: 5,
        right: 5,
        top: 5,
      ),
    ),
    padding: FloatyHeadPadding.setSymmetricPadding(12, 12),
    subTitle: FloatyHeadText(
      text: "8989898989",
      fontSize: 14,
      fontWeight: FontWeight.bold,
      padding: FloatyHeadPadding(
        bottom: 4,
        left: 5,
        right: 5,
        top: 5,
      ),
      textColor: Colors.black87,
    ),
    decoration: FloatyHeadDecoration(startColor: Colors.grey[100]),
    button: FloatyHeadButton(
        text: FloatyHeadText(
          fontWeight: FontWeight.bold,
          text: "Personal",
          fontSize: 10,
          textColor: Colors.black45,
          padding: FloatyHeadPadding(
            bottom: 4,
            left: 5,
            right: 5,
            top: 5,
          ),
        ),
        tag: "personal_btn"),
  );

  final body = FloatyHeadBody(
    rows: [
      EachRow(
        columns: [
          EachColumn(
            text: FloatyHeadText(
              fontWeight: FontWeight.bold,
              text: "Updated body",
              fontSize: 12,
              textColor: Colors.black45,
              padding: FloatyHeadPadding(
                bottom: 4,
                left: 5,
                right: 5,
                top: 5,
              ),
            ),
          ),
        ],
        gravity: ContentGravity.center,
      ),
      EachRow(columns: [
        EachColumn(
          text: FloatyHeadText(
            text: "Updated long data of the body",
            fontSize: 12,
            textColor: Colors.black87,
            fontWeight: FontWeight.bold,
            padding: FloatyHeadPadding(
              bottom: 4,
              left: 5,
              right: 5,
              top: 5,
            ),
          ),
          padding: FloatyHeadPadding.setSymmetricPadding(6, 8),
          decoration: FloatyHeadDecoration(
              startColor: Colors.black12, borderRadius: 25.0),
          margin: FloatyHeadMargin(top: 4),
        ),
      ], gravity: ContentGravity.center),
      EachRow(
        columns: [
          EachColumn(
            text: FloatyHeadText(
              text: "Notes",
              fontSize: 10,
              textColor: Colors.black45,
              fontWeight: FontWeight.normal,
              padding: FloatyHeadPadding(
                bottom: 4,
                left: 5,
                right: 5,
                top: 5,
              ),
            ),
          ),
        ],
        gravity: ContentGravity.left,
        margin: FloatyHeadMargin(top: 8),
      ),
      EachRow(
        columns: [
          EachColumn(
            text: FloatyHeadText(
              text: "Updated random notes.",
              fontSize: 13,
              textColor: Colors.black54,
              fontWeight: FontWeight.bold,
              padding: FloatyHeadPadding(
                bottom: 4,
                left: 5,
                right: 5,
                top: 5,
              ),
            ),
          ),
        ],
        gravity: ContentGravity.left,
      ),
    ],
    padding: FloatyHeadPadding(left: 16, right: 16, bottom: 12, top: 12),
  );

  final footer = FloatyHeadFooter(
    buttons: [
      FloatyHeadButton(
        text: FloatyHeadText(
          text: "Simple button",
          fontSize: 12,
          textColor: Color.fromRGBO(250, 139, 97, 1),
          padding: FloatyHeadPadding(
            bottom: 4,
            left: 5,
            right: 5,
            top: 5,
          ),
          fontWeight: FontWeight.normal,
        ),
        tag: "simple_button",
        padding: FloatyHeadPadding(left: 10, right: 10, bottom: 10, top: 10),
        width: 0,
        height: FloatyHeadButton.WRAP_CONTENT,
        decoration: FloatyHeadDecoration(
            startColor: Colors.white,
            endColor: Colors.white,
            borderWidth: 0,
            borderRadius: 0.0),
      ),
      FloatyHeadButton(
        text: FloatyHeadText(
          fontWeight: FontWeight.normal,
          padding: FloatyHeadPadding(
            bottom: 4,
            left: 5,
            right: 5,
            top: 5,
          ),
          text: "Focus button",
          fontSize: 12,
          textColor: Colors.white,
        ),
        tag: "focus_button",
        width: 0,
        padding: FloatyHeadPadding(left: 10, right: 10, bottom: 10, top: 10),
        height: FloatyHeadButton.WRAP_CONTENT,
        decoration: FloatyHeadDecoration(
            startColor: Color.fromRGBO(250, 139, 97, 1),
            endColor: Color.fromRGBO(247, 28, 88, 1),
            borderWidth: 0,
            borderRadius: 30.0),
      )
    ],
    padding: FloatyHeadPadding(left: 16, right: 16, bottom: 12),
    decoration: FloatyHeadDecoration(startColor: Colors.white),
    buttonsPosition: ButtonPosition.center,
  );

  bool alternateColor = false;

  @override
  void initState() {
    super.initState();
    FloatyHead.registerOnClickListener(callBack);
  }

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(title: Text('Floaty Chathead')),
        body: SingleChildScrollView(
          padding: EdgeInsets.all(50),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              ElevatedButton(
                  child: Text('Open Floaty Chathead'),
                  onPressed: () => floatyHead.openBubble()),
              ElevatedButton(
                  child: Text('Close Floaty Chathead'),
                  onPressed: () => closeFloatyHead()),
              ElevatedButton(
                  child: Text('Set icon Floaty Chathead'),
                  onPressed: () => setIcon()),
              ElevatedButton(
                  child: Text('Set close icon Floaty Chathead'),
                  onPressed: () => setCloseIcon()),
              ElevatedButton(
                  child: Text('Set close background Icon Floaty Chathead'),
                  onPressed: () => setCloseIconBackground()),
              ElevatedButton(
                  child: Text(
                      'Set notification title to: OH MY GOD! THEY KILL KENNY!!! Floaty Chathead'),
                  onPressed: () => setNotificationTitle()),
              ElevatedButton(
                  child: Text('Set notification Icon Floaty Chathead'),
                  onPressed: () => setNotificationIcon()),
              ElevatedButton(
                  child: Text('Set Custom Header into Floaty Chathead'),
                  onPressed: () => setCustomHeader()),
            ],
          ),
        ),
      );

  void setCustomHeader() {
    floatyHead.updateFloatyHeadContent(
      header: header,
      body: body,
      footer: footer,
    );
  }

  void closeFloatyHead() {
    if (floatyHead.isOpen) {
      floatyHead.closeHead();
    }
  }

  Future<void> setNotificationTitle() async {
    String result;
    try {
      result = await floatyHead
          .setNotificationTitle("OH MY GOD! THEY KILL KENNY!!!");
    } on PlatformException {
      result = 'Failed to get icon.';
    }
    print('result: $result');
    if (!mounted) return;
  }

  Future<void> setNotificationIcon() async {
    String result;
    String assetPath = "assets/notificationIcon.png";
    try {
      result = await floatyHead.setNotificationIcon(assetPath);
      print(result);
    } on PlatformException {
      result = 'Failed to get icon.';
      print("failed: $result");
    }
    if (!mounted) return;
  }

  Future<void> setIcon() async {
    String result;
    String assetPath = "assets/chatheadIcon.png";
    try {
      result = await floatyHead.setIcon(assetPath);
      print('result: $result');
    } on PlatformException {
      result = 'Failed to get icon.';
    }
    if (!mounted) return;
  }

  Future<void> setCloseIcon() async {
    String assetPath = "assets/close.png";
    try {
      await floatyHead.setCloseIcon(assetPath);
    } on PlatformException {
      return;
    }
    if (!mounted) return;
  }

  Future<void> setCloseIconBackground() async {
    String assetPath = "assets/closeBg.png";
    try {
      await floatyHead.setCloseBackgroundIcon(assetPath);
    } on PlatformException {
      return;
    }
    if (!mounted) return;
  }
}

void callBack(String tag) {
  print('CALLBACK FROM FRAGMENT BUILDED: $tag');
  switch (tag) {
    case "simple_button":
    case "updated_simple_button":
      break;
    case "focus_button":
      print("Focus button has been called");
      break;
    default:
      print("OnClick event of $tag");
  }
}


================================================
FILE: example/pubspec.yaml
================================================
name: floaty_head_example
description: Demonstrates how to use the floaty_head plugin.

# The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.3

dev_dependencies:
  flutter_test:
    sdk: flutter
  floaty_head:
    path: ../

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  # assets:
  #   - images/a_dot_burr.jpeg
  #   - images/a_dot_ham.jpeg
  assets:
    - assets/chatheadIcon.png
    - assets/close.png
    - assets/closeBg.png
    - assets/notificationIcon.png
  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware.

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages


================================================
FILE: example/test/widget_test.dart
================================================
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:floaty_head_example/main.dart';

void main() {
  testWidgets('Verify Platform version', (WidgetTester tester) async {
    // Build our app and trigger a frame.
    await tester.pumpWidget(Home());

    // Verify that platform version is retrieved.
    expect(
      find.byWidgetPredicate(
        (Widget widget) =>
            widget is Text && widget.data.startsWith('Running on:'),
      ),
      findsOneWidget,
    );
  });
}


================================================
FILE: floaty_head.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
      <excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
      <excludeFolder url="file://$MODULE_DIR$/.idea" />
      <excludeFolder url="file://$MODULE_DIR$/.pub" />
      <excludeFolder url="file://$MODULE_DIR$/build" />
      <excludeFolder url="file://$MODULE_DIR$/example/.dart_tool" />
      <excludeFolder url="file://$MODULE_DIR$/example/.pub" />
      <excludeFolder url="file://$MODULE_DIR$/example/build" />
    </content>
    <orderEntry type="sourceFolder" forTests="false" />
    <orderEntry type="library" name="Dart SDK" level="project" />
    <orderEntry type="library" name="Flutter Plugins" level="project" />
  </component>
</module>

================================================
FILE: lib/floaty_head.dart
================================================
import 'dart:async';
import 'dart:io';
import 'dart:ui';

export 'models/floaty_head_body.dart';
export 'models/floaty_head_button.dart';
export 'models/floaty_head_decoration.dart';
export 'models/floaty_head_footer.dart';
export 'models/floaty_head_header.dart';
export 'models/floaty_head_margin.dart';
export 'models/floaty_head_padding.dart';
export 'models/floaty_head_text.dart';
export 'utils/commons.dart';

import 'package:floaty_head/models/floaty_head_body.dart';
import 'package:floaty_head/models/floaty_head_footer.dart';
import 'package:floaty_head/models/floaty_head_header.dart';
import 'package:floaty_head/models/floaty_head_margin.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';

/// Set the [gravity
Download .txt
gitextract_z7wqmmkf/

├── .gitignore
├── .idea/
│   ├── codeStyles/
│   │   └── Project.xml
│   ├── kotlinc.xml
│   ├── libraries/
│   │   ├── Dart_SDK.xml
│   │   ├── Flutter_Plugins.xml
│   │   └── KotlinJavaRuntime.xml
│   ├── modules.xml
│   ├── runConfigurations/
│   │   └── example_lib_main_dart.xml
│   └── workspace.xml
├── .metadata
├── .vscode/
│   └── launch.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── android/
│   ├── .gitignore
│   ├── .idea/
│   │   ├── .name
│   │   ├── assetWizardSettings.xml
│   │   ├── caches/
│   │   │   └── build_file_checksums.ser
│   │   ├── codeStyles/
│   │   │   └── Project.xml
│   │   ├── gradle.xml
│   │   ├── jarRepositories.xml
│   │   ├── misc.xml
│   │   ├── modules.xml
│   │   ├── runConfigurations.xml
│   │   └── vcs.xml
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       ├── gradle-wrapper.jar
│   │       └── gradle-wrapper.properties
│   ├── gradle.properties
│   ├── gradlew
│   ├── gradlew.bat
│   ├── settings.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── ni/
│           │       └── devotion/
│           │           └── floaty_head/
│           │               └── FloatFragment.kt
│           ├── kotlin/
│           │   └── ni/
│           │       └── devotion/
│           │           └── floaty_head/
│           │               ├── FloatyHeadPlugin.kt
│           │               ├── MainActivity.kt
│           │               ├── floating_chathead/
│           │               │   ├── ChatHead.kt
│           │               │   ├── ChatHeads.kt
│           │               │   ├── Close.kt
│           │               │   ├── SpringConfig.kt
│           │               │   └── WindowManagerHelper.kt
│           │               ├── models/
│           │               │   ├── Decoration.kt
│           │               │   ├── Margin.kt
│           │               │   └── Padding.kt
│           │               ├── services/
│           │               │   ├── FloatyContentJobService.kt
│           │               │   └── FloatyIconService.kt
│           │               ├── utils/
│           │               │   ├── Commons.kt
│           │               │   ├── Constants.kt
│           │               │   ├── ImageHelper.kt
│           │               │   ├── Managment.kt
│           │               │   ├── NumberUtils.kt
│           │               │   └── UiBuilder.kt
│           │               └── views/
│           │                   ├── BodyView.kt
│           │                   ├── FooterView.kt
│           │                   ├── HeaderView.kt
│           │                   └── RowView.kt
│           └── res/
│               ├── drawable/
│               │   ├── gradient_bg.xml
│               │   └── ic_chathead.xml
│               ├── layout/
│               │   └── fragment_float.xml
│               └── values/
│                   ├── colors.xml
│                   ├── strings.xml
│                   └── styles.xml
├── example/
│   ├── .gitignore
│   ├── .metadata
│   ├── README.md
│   ├── android/
│   │   ├── .gitignore
│   │   ├── app/
│   │   │   ├── build.gradle
│   │   │   └── src/
│   │   │       ├── debug/
│   │   │       │   └── AndroidManifest.xml
│   │   │       ├── main/
│   │   │       │   ├── AndroidManifest.xml
│   │   │       │   ├── kotlin/
│   │   │       │   │   └── ni/
│   │   │       │   │       └── devotion/
│   │   │       │   │           └── floaty_head_example/
│   │   │       │   │               ├── Application.kt
│   │   │       │   │               └── MainActivity.kt
│   │   │       │   └── res/
│   │   │       │       ├── drawable/
│   │   │       │       │   └── launch_background.xml
│   │   │       │       └── values/
│   │   │       │           └── styles.xml
│   │   │       └── profile/
│   │   │           └── AndroidManifest.xml
│   │   ├── build.gradle
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       └── gradle-wrapper.properties
│   │   ├── gradle.properties
│   │   ├── settings.gradle
│   │   └── settings_aar.gradle
│   ├── lib/
│   │   └── main.dart
│   ├── pubspec.yaml
│   └── test/
│       └── widget_test.dart
├── floaty_head.iml
├── lib/
│   ├── floaty_head.dart
│   ├── models/
│   │   ├── floaty_head_body.dart
│   │   ├── floaty_head_button.dart
│   │   ├── floaty_head_decoration.dart
│   │   ├── floaty_head_footer.dart
│   │   ├── floaty_head_header.dart
│   │   ├── floaty_head_margin.dart
│   │   ├── floaty_head_padding.dart
│   │   └── floaty_head_text.dart
│   └── utils/
│       └── commons.dart
├── pubspec.yaml
└── test/
    └── floaty_head_test.dart
Download .txt
SYMBOL INDEX (59 symbols across 13 files)

FILE: example/lib/main.dart
  function main (line 7) | Future<void> main()
  class Home (line 11) | class Home extends StatefulWidget {
    method createState (line 12) | _Home createState()
  class _Home (line 15) | class _Home extends State<Home> {
    method initState (line 202) | void initState()
    method build (line 208) | Widget build(BuildContext context)
    method setCustomHeader (line 246) | void setCustomHeader()
    method closeFloatyHead (line 254) | void closeFloatyHead()
    method setNotificationTitle (line 260) | Future<void> setNotificationTitle()
    method setNotificationIcon (line 272) | Future<void> setNotificationIcon()
    method setIcon (line 285) | Future<void> setIcon()
    method setCloseIcon (line 297) | Future<void> setCloseIcon()
    method setCloseIconBackground (line 307) | Future<void> setCloseIconBackground()
  function callBack (line 318) | void callBack(String tag)

FILE: example/test/widget_test.dart
  function main (line 13) | void main()

FILE: lib/floaty_head.dart
  type FloatyHeadGravity (line 32) | enum FloatyHeadGravity {
  type ContentGravity (line 48) | enum ContentGravity {
  type ButtonPosition (line 64) | enum ButtonPosition {
  type FontWeight (line 79) | enum FontWeight {
  type OnClickListener (line 90) | typedef void OnClickListener(String tag);
  class FloatyHead (line 92) | class FloatyHead {
    method openBubble (line 116) | void openBubble()
    method registerOnClickListener (line 129) | Future<bool> registerOnClickListener(
    method setIcon (line 154) | Future<String> setIcon(String assetPath)
    method setNotificationTitle (line 161) | Future<String> setNotificationTitle(String title)
    method setNotificationIcon (line 170) | Future<String> setNotificationIcon(String assetPath)
    method setCloseIcon (line 177) | Future<String> setCloseIcon(String assetPath)
    method setCloseBackgroundIcon (line 184) | Future<String> setCloseBackgroundIcon(String assetPath)
    method closeHead (line 191) | void closeHead()
    method updateFloatyHeadContent (line 202) | Future<bool?> updateFloatyHeadContent({
  function callbackDispatcher (line 224) | void callbackDispatcher()

FILE: lib/models/floaty_head_body.dart
  class FloatyHeadBody (line 5) | class FloatyHeadBody {
    method getMap (line 22) | Map<String, dynamic> getMap()
  class EachRow (line 36) | class EachRow {
    method getMap (line 51) | Map<String, dynamic> getMap()
  class EachColumn (line 67) | class EachColumn {
    method getMap (line 80) | Map<String, dynamic> getMap()

FILE: lib/models/floaty_head_button.dart
  class FloatyHeadButton (line 5) | class FloatyHeadButton {
    method getMap (line 26) | Map<String, dynamic> getMap()

FILE: lib/models/floaty_head_decoration.dart
  class FloatyHeadDecoration (line 5) | class FloatyHeadDecoration {
    method getMap (line 20) | Map<String, dynamic> getMap()

FILE: lib/models/floaty_head_footer.dart
  class FloatyHeadFooter (line 5) | class FloatyHeadFooter {
    method getMap (line 20) | Map<String, dynamic> getMap()

FILE: lib/models/floaty_head_header.dart
  class FloatyHeadHeader (line 6) | class FloatyHeadHeader {
    method getMap (line 24) | Map<String, dynamic> getMap()

FILE: lib/models/floaty_head_margin.dart
  class FloatyHeadMargin (line 3) | class FloatyHeadMargin {
    method getMap (line 11) | Map<String, int> getMap()
    method setSymmetricMargin (line 21) | FloatyHeadMargin setSymmetricMargin(int vertical, int horizontal)

FILE: lib/models/floaty_head_padding.dart
  class FloatyHeadPadding (line 3) | class FloatyHeadPadding {
    method getMap (line 11) | Map<String, int> getMap()
    method setSymmetricPadding (line 21) | FloatyHeadPadding setSymmetricPadding(int vertical, int horizontal)

FILE: lib/models/floaty_head_text.dart
  class FloatyHeadText (line 6) | class FloatyHeadText {
    method getMap (line 20) | Map<String, dynamic> getMap()

FILE: lib/utils/commons.dart
  class Commons (line 3) | class Commons {
    method getWindowGravity (line 5) | String getWindowGravity(FloatyHeadGravity? gravity)
    method getContentGravity (line 19) | String getContentGravity(ContentGravity? gravity)
    method getPosition (line 33) | String getPosition(ButtonPosition? buttonPosition)
    method getFontWeight (line 47) | String getFontWeight(FontWeight? fontWeight)

FILE: test/floaty_head_test.dart
  function main (line 4) | void main()
Condensed preview — 96 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (219K chars).
[
  {
    "path": ".gitignore",
    "chars": 47,
    "preview": ".DS_Store\n.dart_tool/\n\n.packages\n.pub/\n\nbuild/\n"
  },
  {
    "path": ".idea/codeStyles/Project.xml",
    "chars": 3309,
    "preview": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <codeStyleSettings lan"
  },
  {
    "path": ".idea/kotlinc.xml",
    "chars": 179,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Kotlin2JvmCompilerArguments\">\n    <optio"
  },
  {
    "path": ".idea/libraries/Dart_SDK.xml",
    "chars": 996,
    "preview": "<component name=\"libraryTable\">\n  <library name=\"Dart SDK\">\n    <CLASSES>\n      <root url=\"file:///usr/local/flutter/bin"
  },
  {
    "path": ".idea/libraries/Flutter_Plugins.xml",
    "chars": 228,
    "preview": "<component name=\"libraryTable\">\n  <library name=\"Flutter Plugins\" type=\"FlutterPluginsLibraryType\">\n    <CLASSES>\n      "
  },
  {
    "path": ".idea/libraries/KotlinJavaRuntime.xml",
    "chars": 876,
    "preview": "<component name=\"libraryTable\">\n  <library name=\"KotlinJavaRuntime\">\n    <CLASSES>\n      <root url=\"jar://$PROJECT_DIR$/"
  },
  {
    "path": ".idea/modules.xml",
    "chars": 569,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n   "
  },
  {
    "path": ".idea/runConfigurations/example_lib_main_dart.xml",
    "chars": 291,
    "preview": "<component name=\"ProjectRunConfigurationManager\">\n  <configuration default=\"false\" name=\"example/lib/main.dart\" type=\"Fl"
  },
  {
    "path": ".idea/workspace.xml",
    "chars": 2323,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ChangeListManager\">\n    <list default=\"t"
  },
  {
    "path": ".metadata",
    "chars": 308,
    "preview": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrade"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 409,
    "preview": "{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 255,
    "preview": "## [2.0.0-nullsafety.0] - 2021.03.06\n* mirgrate to nullsafety\n## [1.1.0] - 2020.09.19\n* Added documentation.\n* Refactore"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 16183,
    "preview": "# Contributing to Floaty_Chathead\n\n:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:\n\nThe follo"
  },
  {
    "path": "LICENSE",
    "chars": 1073,
    "preview": "MIT License\n\nCopyright (c) 2020 Luis Cardoza Bird\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "README.md",
    "chars": 1722,
    "preview": "# Floaty Chathead (Deprecated)\n\n[![Deprecated](https://img.shields.io/badge/status-deprecated-red.svg)](https://pub.dev/"
  },
  {
    "path": "android/.gitignore",
    "chars": 97,
    "preview": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n"
  },
  {
    "path": "android/.idea/.name",
    "chars": 11,
    "preview": "floaty_head"
  },
  {
    "path": "android/.idea/assetWizardSettings.xml",
    "chars": 1062,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"WizardSettings\">\n    <option name=\"child"
  },
  {
    "path": "android/.idea/codeStyles/Project.xml",
    "chars": 4150,
    "preview": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <JetCodeStyleSettings>"
  },
  {
    "path": "android/.idea/gradle.xml",
    "chars": 747,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleMigrationSettings\" migrationVersio"
  },
  {
    "path": "android/.idea/jarRepositories.xml",
    "chars": 1052,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RemoteRepositoriesConfiguration\">\n    <r"
  },
  {
    "path": "android/.idea/misc.xml",
    "chars": 357,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectRootManager\" version=\"2\" language"
  },
  {
    "path": "android/.idea/modules.xml",
    "chars": 310,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n   "
  },
  {
    "path": "android/.idea/runConfigurations.xml",
    "chars": 564,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <o"
  },
  {
    "path": "android/.idea/vcs.xml",
    "chars": 183,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping dire"
  },
  {
    "path": "android/build.gradle",
    "chars": 1240,
    "preview": "group 'ni.devotion.floaty_head'\nversion '1.0-SNAPSHOT'\n\nbuildscript {\n    ext.kotlin_version = '1.4.0'\n    repositories "
  },
  {
    "path": "android/gradle/wrapper/gradle-wrapper.properties",
    "chars": 232,
    "preview": "#Thu Aug 27 19:59:47 CST 2020\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "android/gradle.properties",
    "chars": 104,
    "preview": "org.gradle.jvmargs=-Xmx1536M\nandroid.useAndroidX=true\nandroid.enableJetifier=true\nandroid.enableR8=true\n"
  },
  {
    "path": "android/gradlew",
    "chars": 4971,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "android/gradlew.bat",
    "chars": 2404,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "android/settings.gradle",
    "chars": 33,
    "preview": "rootProject.name = 'floaty_head'\n"
  },
  {
    "path": "android/src/main/AndroidManifest.xml",
    "chars": 1238,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n"
  },
  {
    "path": "android/src/main/java/ni/devotion/floaty_head/FloatFragment.kt",
    "chars": 2251,
    "preview": "package ni.devotion.floaty_head\n\nimport android.content.Context\nimport android.view.View\nimport android.view.animation.A"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/FloatyHeadPlugin.kt",
    "chars": 18132,
    "preview": "package ni.devotion.floaty_head\n\nimport android.app.Activity\nimport android.content.ComponentName\nimport android.content"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/MainActivity.kt",
    "chars": 1098,
    "preview": "package ni.devotion.floaty_head\n\nimport android.content.Context\nimport android.graphics.Color\nimport android.os.Bundle\ni"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/floating_chathead/ChatHead.kt",
    "chars": 5080,
    "preview": "package ni.devotion.floaty_head.floating_chathead\n\nimport android.graphics.*\nimport android.graphics.BitmapFactory.*\nimp"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/floating_chathead/ChatHeads.kt",
    "chars": 24362,
    "preview": "package ni.devotion.floaty_head.floating_chathead\n\nimport android.annotation.SuppressLint\nimport android.content.Context"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/floating_chathead/Close.kt",
    "chars": 5499,
    "preview": "package ni.devotion.floaty_head.floating_chathead\n\nimport android.graphics.*\nimport android.os.Build\nimport android.view"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/floating_chathead/SpringConfig.kt",
    "chars": 537,
    "preview": "package ni.devotion.floaty_head.floating_chathead\n\nimport com.facebook.rebound.SpringConfig\n\nobject SpringConfigs {\n    "
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/floating_chathead/WindowManagerHelper.kt",
    "chars": 754,
    "preview": "package ni.devotion.floaty_head.floating_chathead\n\nimport android.content.res.Resources\nimport android.os.Build\nimport a"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/models/Decoration.kt",
    "chars": 950,
    "preview": "package ni.devotion.floaty_head.models\n\nimport android.content.Context\nimport ni.devotion.floaty_head.utils.Commons\nimpo"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/models/Margin.kt",
    "chars": 665,
    "preview": "package ni.devotion.floaty_head.models\n\nimport ni.devotion.floaty_head.utils.NumberUtils\nimport android.content.Context\n"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/models/Padding.kt",
    "chars": 666,
    "preview": "package ni.devotion.floaty_head.models\n\nimport ni.devotion.floaty_head.utils.NumberUtils\nimport android.content.Context\n"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/services/FloatyContentJobService.kt",
    "chars": 5737,
    "preview": "package ni.devotion.floaty_head.services\n\nimport android.app.*\nimport android.content.Context\nimport android.content.Int"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/services/FloatyIconService.kt",
    "chars": 3002,
    "preview": "package ni.devotion.floaty_head.services\n\nimport android.annotation.SuppressLint\nimport android.app.*\nimport android.con"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/utils/Commons.kt",
    "chars": 2488,
    "preview": "package ni.devotion.floaty_head.utils\n\nimport android.content.Context\nimport android.graphics.Typeface\nimport android.ut"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/utils/Constants.kt",
    "chars": 1602,
    "preview": "package ni.devotion.floaty_head.utils\n\nobject Constants {\n\n    val CHANNEL = \"ni.devotion.floaty_head\"\n    val METHOD_CH"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/utils/ImageHelper.kt",
    "chars": 2826,
    "preview": "package ni.devotion.floaty_head.utils\n\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport andr"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/utils/Managment.kt",
    "chars": 1403,
    "preview": "package ni.devotion.floaty_head.utils\n\nimport android.app.ActionBar\nimport android.app.Activity\nimport android.content.C"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/utils/NumberUtils.kt",
    "chars": 671,
    "preview": "package ni.devotion.floaty_head.utils\n\nimport android.util.Log\n\n/**\n * Class used for convert any number to [float] or ["
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/utils/UiBuilder.kt",
    "chars": 5964,
    "preview": "package ni.devotion.floaty_head.utils\n\nimport android.content.Context\nimport android.graphics.Typeface\nimport android.gr"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/views/BodyView.kt",
    "chars": 4340,
    "preview": "package ni.devotion.floaty_head.views\n\nimport android.content.Context\nimport android.graphics.Color\nimport android.view."
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/views/FooterView.kt",
    "chars": 3935,
    "preview": "package ni.devotion.floaty_head.views\n\nimport android.content.Context\nimport android.view.Gravity\nimport android.view.Vi"
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/views/HeaderView.kt",
    "chars": 5455,
    "preview": "package ni.devotion.floaty_head.views\n\nimport android.content.Context\nimport android.graphics.Color\nimport android.view."
  },
  {
    "path": "android/src/main/kotlin/ni/devotion/floaty_head/views/RowView.kt",
    "chars": 1283,
    "preview": "package ni.devotion.floaty_head.views\n\nimport android.content.Context\nimport android.widget.LinearLayout\nimport ni.devot"
  },
  {
    "path": "android/src/main/res/drawable/gradient_bg.xml",
    "chars": 250,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <gradient\n"
  },
  {
    "path": "android/src/main/res/drawable/ic_chathead.xml",
    "chars": 833,
    "preview": "<vector android:height=\"64dp\" android:viewportHeight=\"512\"\n    android:viewportWidth=\"512\" android:width=\"64dp\" xmlns:an"
  },
  {
    "path": "android/src/main/res/layout/fragment_float.xml",
    "chars": 405,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    android:id=\"@+id/contentLayout\"\n    xmlns:android=\"http://schem"
  },
  {
    "path": "android/src/main/res/values/colors.xml",
    "chars": 13714,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#71b5bd</color>\n    <color name=\"color"
  },
  {
    "path": "android/src/main/res/values/strings.xml",
    "chars": 152,
    "preview": "<resources>\n    <!-- TODO: Remove or change this placeholder text -->\n    <string name=\"hello_blank_fragment\">Hello blan"
  },
  {
    "path": "android/src/main/res/values/styles.xml",
    "chars": 671,
    "preview": "<resources>\n\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme "
  },
  {
    "path": "example/.gitignore",
    "chars": 621,
    "preview": "# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.buildlog/\n.history\n.svn/\n\n# IntelliJ related\n*.iml\n*.ipr\n*.i"
  },
  {
    "path": "example/.metadata",
    "chars": 305,
    "preview": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrade"
  },
  {
    "path": "example/README.md",
    "chars": 574,
    "preview": "# floaty_head_example\n\nDemonstrates how to use the floaty_head plugin.\n\n## Getting Started\n\nThis project is a starting p"
  },
  {
    "path": "example/android/.gitignore",
    "chars": 262,
    "preview": "gradle-wrapper.jar\n/.gradle\n/captures/\n/gradlew\n/gradlew.bat\n/local.properties\nGeneratedPluginRegistrant.java\n\n# Remembe"
  },
  {
    "path": "example/android/app/build.gradle",
    "chars": 1778,
    "preview": "def localProperties = new Properties()\ndef localPropertiesFile = rootProject.file('local.properties')\nif (localPropertie"
  },
  {
    "path": "example/android/app/src/debug/AndroidManifest.xml",
    "chars": 339,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"ni.devotion.floaty_head_example\">\n    "
  },
  {
    "path": "example/android/app/src/main/AndroidManifest.xml",
    "chars": 2640,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"ni.devotion.floaty_head_example\">\n    "
  },
  {
    "path": "example/android/app/src/main/kotlin/ni/devotion/floaty_head_example/Application.kt",
    "chars": 1048,
    "preview": "package ni.devotion.floaty_head_example;\n\nimport androidx.annotation.NonNull\nimport ni.devotion.floaty_head.FloatyHeadPl"
  },
  {
    "path": "example/android/app/src/main/kotlin/ni/devotion/floaty_head_example/MainActivity.kt",
    "chars": 656,
    "preview": "package ni.devotion.floaty_head_example;\n\nimport android.os.Bundle;\nimport androidx.annotation.NonNull\nimport io.flutter"
  },
  {
    "path": "example/android/app/src/main/res/drawable/launch_background.xml",
    "chars": 434,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmln"
  },
  {
    "path": "example/android/app/src/main/res/values/styles.xml",
    "chars": 951,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <!-- Theme applied to the Android Window while the process is sta"
  },
  {
    "path": "example/android/app/src/profile/AndroidManifest.xml",
    "chars": 339,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"ni.devotion.floaty_head_example\">\n    "
  },
  {
    "path": "example/android/build.gradle",
    "chars": 582,
    "preview": "buildscript {\n    ext.kotlin_version = '1.3.50'\n    repositories {\n        google()\n        jcenter()\n    }\n\n    depende"
  },
  {
    "path": "example/android/gradle/wrapper/gradle-wrapper.properties",
    "chars": 231,
    "preview": "#Fri Jun 23 08:50:38 CEST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER"
  },
  {
    "path": "example/android/gradle.properties",
    "chars": 104,
    "preview": "org.gradle.jvmargs=-Xmx1536M\nandroid.useAndroidX=true\nandroid.enableJetifier=true\nandroid.enableR8=true\n"
  },
  {
    "path": "example/android/settings.gradle",
    "chars": 484,
    "preview": "include ':app'\n\ndef flutterProjectRoot = rootProject.projectDir.parentFile.toPath()\n\ndef plugins = new Properties()\ndef "
  },
  {
    "path": "example/android/settings_aar.gradle",
    "chars": 15,
    "preview": "include ':app'\n"
  },
  {
    "path": "example/lib/main.dart",
    "chars": 9202,
    "preview": "import 'dart:async';\n\nimport 'package:floaty_head/floaty_head.dart';\nimport 'package:flutter/material.dart';\nimport 'pac"
  },
  {
    "path": "example/pubspec.yaml",
    "chars": 2257,
    "preview": "name: floaty_head_example\ndescription: Demonstrates how to use the floaty_head plugin.\n\n# The following line prevents th"
  },
  {
    "path": "example/test/widget_test.dart",
    "chars": 895,
    "preview": "// This is a basic Flutter widget test.\n//\n// To perform an interaction with a widget in your test, use the WidgetTester"
  },
  {
    "path": "floaty_head.iml",
    "chars": 947,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"JAVA_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\" "
  },
  {
    "path": "lib/floaty_head.dart",
    "chars": 7546,
    "preview": "import 'dart:async';\nimport 'dart:io';\nimport 'dart:ui';\n\nexport 'models/floaty_head_body.dart';\nexport 'models/floaty_h"
  },
  {
    "path": "lib/models/floaty_head_body.dart",
    "chars": 2301,
    "preview": "import 'package:floaty_head/floaty_head.dart';\n\n/// This class is used to build the [Body] that is gonna be displayed\n//"
  },
  {
    "path": "lib/models/floaty_head_button.dart",
    "chars": 953,
    "preview": "import 'package:floaty_head/floaty_head.dart';\n\n/// This class is used to build the [Buttons] inside the [Body] that is "
  },
  {
    "path": "lib/models/floaty_head_decoration.dart",
    "chars": 802,
    "preview": "import 'package:flutter/material.dart';\n\n/// This class is used to build the [Decoration] inside the [Body] that is gonn"
  },
  {
    "path": "lib/models/floaty_head_footer.dart",
    "chars": 1017,
    "preview": "import 'package:floaty_head/floaty_head.dart';\n\n/// This class is used to build the [Footer Content] inside the [Body] t"
  },
  {
    "path": "lib/models/floaty_head_header.dart",
    "chars": 946,
    "preview": "import 'package:floaty_head/floaty_head.dart';\nimport 'package:flutter/material.dart';\n\n/// This class is used to build "
  },
  {
    "path": "lib/models/floaty_head_margin.dart",
    "chars": 695,
    "preview": "/// This class is used to build the [Margin] inside the [Body] that is gonna be displayed\n/// when the chathead is tappe"
  },
  {
    "path": "lib/models/floaty_head_padding.dart",
    "chars": 701,
    "preview": "/// This class is used to build the [Padding] inside the [Body] that is gonna be displayed\n/// when the chathead is tapp"
  },
  {
    "path": "lib/models/floaty_head_text.dart",
    "chars": 855,
    "preview": "import 'package:floaty_head/floaty_head.dart';\nimport 'package:flutter/material.dart';\n\n/// This class is used to build "
  },
  {
    "path": "lib/utils/commons.dart",
    "chars": 1760,
    "preview": "import 'package:floaty_head/floaty_head.dart';\n\nclass Commons {\n  /// Replace the [windowGravity] setted in dart-client "
  },
  {
    "path": "pubspec.yaml",
    "chars": 544,
    "preview": "name: floaty_head\ndescription: A flutter plugin to create custom chatheads with hidden content displayed on tap, like Me"
  },
  {
    "path": "test/floaty_head_test.dart",
    "chars": 401,
    "preview": "import 'package:flutter/services.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\nvoid main() {\n  const MethodCh"
  }
]

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

About this extraction

This page contains the full source code of the Crdzbird/floaty_chathead GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 96 files (200.6 KB), approximately 52.9k tokens, and a symbol index with 59 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!