[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ninsert_final_newline = true\n\n[{*.kt, *.kts}]\nmax_line_length = 140\nij_kotlin_packages_to_use_import_on_demand = ^\nij_continuation_indent_size = 4\nij_kotlin_align_in_columns_case_branch = false\nij_kotlin_align_multiline_binary_operation = false\nij_kotlin_align_multiline_extends_list = false\nij_kotlin_align_multiline_method_parentheses = false\nij_kotlin_align_multiline_parameters = true\nij_kotlin_align_multiline_parameters_in_calls = false\nij_kotlin_allow_trailing_comma = false\nij_kotlin_allow_trailing_comma_on_call_site = false\nij_kotlin_assignment_wrap = normal\nij_kotlin_blank_lines_after_class_header = 0\nij_kotlin_blank_lines_around_block_when_branches = 0\nij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1\nij_kotlin_block_comment_at_first_column = true\nij_kotlin_call_parameters_new_line_after_left_paren = true\nij_kotlin_call_parameters_right_paren_on_new_line = true\nij_kotlin_call_parameters_wrap = on_every_item\nij_kotlin_catch_on_new_line = false\nij_kotlin_class_annotation_wrap = split_into_lines\nij_kotlin_code_style_defaults = KOTLIN_OFFICIAL\nij_kotlin_continuation_indent_for_chained_calls = false\nij_kotlin_continuation_indent_for_expression_bodies = false\nij_kotlin_continuation_indent_in_argument_lists = false\nij_kotlin_continuation_indent_in_elvis = false\nij_kotlin_continuation_indent_in_if_conditions = false\nij_kotlin_continuation_indent_in_parameter_lists = false\nij_kotlin_continuation_indent_in_supertype_lists = false\nij_kotlin_else_on_new_line = false\nij_kotlin_enum_constants_wrap = off\nij_kotlin_extends_list_wrap = normal\nij_kotlin_field_annotation_wrap = split_into_lines\nij_kotlin_finally_on_new_line = false\nij_kotlin_if_rparen_on_new_line = true\nij_kotlin_import_nested_classes = false\nij_kotlin_imports_layout = *, java.**, javax.**, kotlin.**, ^\nij_kotlin_insert_whitespaces_in_simple_one_line_method = true\nij_kotlin_keep_blank_lines_before_right_brace = 2\nij_kotlin_keep_blank_lines_in_code = 2\nij_kotlin_keep_blank_lines_in_declarations = 2\nij_kotlin_keep_first_column_comment = true\nij_kotlin_keep_indents_on_empty_lines = false\nij_kotlin_keep_line_breaks = true\nij_kotlin_lbrace_on_next_line = false\nij_kotlin_line_comment_add_space = false\nij_kotlin_line_comment_at_first_column = true\nij_kotlin_method_annotation_wrap = split_into_lines\nij_kotlin_method_call_chain_wrap = normal\nij_kotlin_method_parameters_new_line_after_left_paren = true\nij_kotlin_method_parameters_right_paren_on_new_line = true\nij_kotlin_method_parameters_wrap = on_every_item\nij_kotlin_name_count_to_use_star_import = 2147483647\nij_kotlin_name_count_to_use_star_import_for_members = 2147483647\nij_kotlin_parameter_annotation_wrap = off\nij_kotlin_space_after_comma = true\nij_kotlin_space_after_extend_colon = true\nij_kotlin_space_after_type_colon = true\nij_kotlin_space_before_catch_parentheses = true\nij_kotlin_space_before_comma = false\nij_kotlin_space_before_extend_colon = true\nij_kotlin_space_before_for_parentheses = true\nij_kotlin_space_before_if_parentheses = true\nij_kotlin_space_before_lambda_arrow = true\nij_kotlin_space_before_type_colon = false\nij_kotlin_space_before_when_parentheses = true\nij_kotlin_space_before_while_parentheses = true\nij_kotlin_spaces_around_additive_operators = true\nij_kotlin_spaces_around_assignment_operators = true\nij_kotlin_spaces_around_equality_operators = true\nij_kotlin_spaces_around_function_type_arrow = true\nij_kotlin_spaces_around_logical_operators = true\nij_kotlin_spaces_around_multiplicative_operators = true\nij_kotlin_spaces_around_range = false\nij_kotlin_spaces_around_relational_operators = true\nij_kotlin_spaces_around_unary_operator = false\nij_kotlin_spaces_around_when_arrow = true\nij_kotlin_variable_annotation_wrap = off\nij_kotlin_while_on_new_line = false\nij_kotlin_wrap_elvis_expressions = 1\nij_kotlin_wrap_expression_body_functions = 1\nij_kotlin_wrap_first_method_in_call_chain = false\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: arkivanov\ncustom: [\"https://www.buymeacoffee.com/arkivanov\"]\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build\n\non:\n  pull_request:\n    paths-ignore:\n      - 'docs/**'\n\njobs:\n  linux-build:\n    name: Build on Linux\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n      - name: Install Java\n        uses: actions/setup-java@v3\n        with:\n          distribution: 'zulu'\n          java-version: 17\n      - name: Update dependencies\n        run: sudo apt-get update\n      - name: Install dependencies\n        run: sudo apt-get install nodejs chromium-browser\n      - name: Build\n        uses: gradle/gradle-build-action@v2\n        with:\n          arguments: build -Dsplit_targets\n  macos-build:\n    name: Build on macOS\n    runs-on: macos-14\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n      - name: Install Java\n        uses: actions/setup-java@v3\n        with:\n          distribution: 'zulu'\n          java-version: 17\n      - name: Build project\n        uses: gradle/gradle-build-action@v2\n        with:\n          arguments: build -Dsplit_targets\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish\n\non:\n  workflow_dispatch:\n\njobs:\n  create-staging-repository:\n    runs-on: ubuntu-latest\n    name: Create staging repository\n    outputs:\n      repository_id: ${{ steps.create.outputs.repository_id }}\n    steps:\n      - id: create\n        uses: nexus-actions/create-nexus-staging-repo@v1.3.0\n        with:\n          username: arkivanov\n          password: ${{ secrets.SONATYPE_PASSWORD }}\n          staging_profile_id: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }}\n          description: Created by GitHub Actions\n          base_url: https://s01.oss.sonatype.org/service/local/\n  publish:\n    name: Publish\n    runs-on: macos-14\n    needs: create-staging-repository\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n      - name: Install Java\n        uses: actions/setup-java@v3\n        with:\n          distribution: 'zulu'\n          java-version: 17\n      - name: Publish\n        env:\n          SONATYPE_REPOSITORY_ID: ${{ needs.create-staging-repository.outputs.repository_id }}\n          SONATYPE_USER_NAME: ${{ secrets.SONATYPE_USER_NAME }}\n          SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}\n          SIGNING_KEY: ${{ secrets.SIGNING_KEY }}\n          SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}\n        run: ./gradlew publish\n  close-staging-repository:\n    name: Close staging repository\n    runs-on: ubuntu-latest\n    needs: [ create-staging-repository, publish ]\n    steps:\n      - name: Close staging repository\n        uses: nexus-actions/release-nexus-staging-repo@v1.1\n        with:\n          username: arkivanov\n          password: ${{ secrets.SONATYPE_PASSWORD }}\n          staging_repository_id: ${{ needs.create-staging-repository.outputs.repository_id }}\n          base_url: https://s01.oss.sonatype.org/service/local/\n          close_only: 'true'\n  check-publication:\n    name: Check publication\n    runs-on: macos-14\n    needs: close-staging-repository\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v1\n      - name: Install Java\n        uses: actions/setup-java@v3\n        with:\n          distribution: 'zulu'\n          java-version: 17\n      - name: Check publication\n        run: ./gradlew kotlinUpgradeYarnLock :tools:check-publication:build -Pcheck_publication\n"
  },
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\nlocal.properties\n.idea\n/build\n.DS_Store\n.kotlin\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "[![Maven Central](https://img.shields.io/maven-central/v/com.arkivanov.essenty/lifecycle?color=blue)](https://search.maven.org/search?q=g:com.arkivanov.essenty)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n[![Twitter URL](https://img.shields.io/badge/Twitter-@arkann1985-blue.svg?style=social&logo=twitter)](https://twitter.com/arkann1985)\n\n# Essenty\n\nThe most essential libraries for Kotlin Multiplatform development.\n\nSupported targets:\n\n- `android`\n- `jvm`\n- `js`\n- `wasmJs`\n- `ios`\n- `watchos`\n- `tvos`\n- `macos`\n- `linuxX64`\n\n## Lifecycle\n\nWhen writing Kotlin Multiplatform (common) code we often need to handle lifecycle events of a screen. For example, to stop background operations when the screen is destroyed, or to reload some data when the screen is activated. Essenty provides the `Lifecycle` API to help with lifecycle handling in the common code. It is very similar to [Android Activity lifecycle](https://developer.android.com/guide/components/activities/activity-lifecycle).\n\n### Setup\n\nGroovy:\n```groovy\n// Add the dependency, typically under the commonMain source set\nimplementation \"com.arkivanov.essenty:lifecycle:<essenty_version>\"\n```\n\nKotlin:\n```kotlin\n// Add the dependency, typically under the commonMain source set\nimplementation(\"com.arkivanov.essenty:lifecycle:<essenty_version>\")\n```\n\n### Lifecycle state transitions\n\n<img src=\"docs/media/LifecycleStates.png\" width=\"512\">\n\n### Content\n\nThe main [Lifecycle](https://github.com/arkivanov/Essenty/blob/master/lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/Lifecycle.kt) interface provides ability to observe the lifecycle state changes. There are also handy [extension functions](https://github.com/arkivanov/Essenty/blob/master/lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/LifecycleExt.kt) for convenience.\n\nThe [LifecycleRegistry](https://github.com/arkivanov/Essenty/blob/master/lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/LifecycleRegistry.kt) interface extends both the `Lifecycle` and the `Lifecycle.Callbacks` at the same time. It can be used to manually control the lifecycle, for example in tests. You can also find some useful [extension functions](https://github.com/arkivanov/Essenty/blob/master/lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/LifecycleRegistryExt.kt).\n\nThe [LifecycleOwner](https://github.com/arkivanov/Essenty/blob/master/lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/LifecycleOwner.kt) just holds the `Lifecyle`. It may be implemented by an arbitrary class, to provide convenient API.\n\n#### Android extensions\n\nFrom Android, the `Lifecycle` can be obtained by using special functions, can be found [here](https://github.com/arkivanov/Essenty/blob/master/lifecycle/src/androidMain/kotlin/com/arkivanov/essenty/lifecycle/AndroidExt.kt).\n\n#### iOS and tvOS extensions\n\nThere is [ApplicationLifecycle](https://github.com/arkivanov/Essenty/blob/master/lifecycle/src/itvosMain/kotlin/com/arkivanov/essenty/lifecycle/ApplicationLifecycle.kt) available for `ios` and `tvos` targets. It follows the `UIApplication` lifecycle notifications.\n\n> ⚠️  Since this implementation subscribes to `UIApplication` global lifecycle events, the instance and all its registered callbacks (and whatever they capture) will stay in memory until the application is destroyed or until `ApplicationLifecycle#destroy` method is called. It's ok to use it in a global scope like `UIApplicationDelegate`, but it may cause memory leaks when used in a narrower scope like `UIViewController` if it gets destroyed earlier. Use the `destroy` method to destroy the lifecycle manually and prevent memory leaks.\n\n#### Reaktive extensions\n\nThere are some useful `Lifecycle` extensions for Reaktive.\n\n- Automatic management of `Disposable` and `DisposableScope` by `Lifecycle`, can be found [here](https://github.com/arkivanov/Essenty/blob/master/lifecycle-reaktive/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/reaktive/DisposableWithLifecycle.kt).\n\n#### Coroutines extensions\n\nThere are some useful `Lifecycle` extensions for Coroutines.\n\n- Automatic management of `CoroutineScope` by `Lifecycle`, can be found [here](https://github.com/arkivanov/Essenty/blob/master/lifecycle-coroutines/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/coroutines/CoroutineScopeWithLifecycle.kt)\n- `Flow.withLifecycle(Lifecycle): Flow` - can be found [here](https://github.com/arkivanov/Essenty/blob/master/lifecycle-coroutines/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/coroutines/FlowWithLifecycle.kt).\n- `Lifecycle.repeatOnLifecycle(block)` - can be found [here](https://github.com/arkivanov/Essenty/blob/master/lifecycle-coroutines/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/coroutines/RepeatOnLifecycle.kt).\n\n### Usage example\n\n#### Observing the Lifecyle\n\nThe lifecycle can be observed using its `subscribe`/`unsubscribe` methods:\n\n```kotlin\nimport com.arkivanov.essenty.lifecycle.Lifecycle\n\nclass SomeLogic(lifecycle: Lifecycle) {\n    init {\n        lifecycle.subscribe(\n            object : Lifecycle.Callbacks {\n                override fun onCreate() {\n                    // Handle lifecycle created\n                }\n\n                // onStart, onResume, onPause, onStop are also available\n\n                override fun onDestroy() {\n                    // Handle lifecycle destroyed\n                }\n            }\n        )\n    }\n}\n```\n\nOr using the extension functions:\n\n```kotlin\nimport com.arkivanov.essenty.lifecycle.Lifecycle\nimport com.arkivanov.essenty.lifecycle.doOnCreate\nimport com.arkivanov.essenty.lifecycle.doOnDestroy\nimport com.arkivanov.essenty.lifecycle.subscribe\n\nclass SomeLogic(lifecycle: Lifecycle) {\n    init {\n        lifecycle.subscribe(\n            onCreate = { /* Handle lifecycle created */ },\n            // onStart, onResume, onPause, onStop are also available\n            onDestroy = { /* Handle lifecycle destroyed */ }\n        )\n\n        lifecycle.doOnCreate {\n            // Handle lifecycle created\n        }\n\n        // doOnStart, doOnResume, doOnPause, doOnStop are also available\n\n        lifecycle.doOnDestroy {\n            // Handle lifecycle destroyed\n        }\n    }\n}\n```\n\n#### Using the LifecycleRegistry manually\n\nA default implementation of the `LifecycleRegisty` interface can be instantiated using the corresponding builder function:\n\n```kotlin\nimport com.arkivanov.essenty.lifecycle.LifecycleRegistry\nimport com.arkivanov.essenty.lifecycle.resume\nimport com.arkivanov.essenty.lifecycle.destroy\n\nval lifecycleRegistry = LifecycleRegistry()\nval someLogic = SomeLogic(lifecycleRegistry)\n\nlifecycleRegistry.resume()\n\n// At some point later\nlifecycleRegistry.destroy()\n```\n\n## StateKeeper\n\nWhen writing common code targeting Android, it might be required to preserve some data over process death or Android configuration changes. For this purpose, Essenty provides the `StateKeeper` API, which is inspired by the AndroidX [SavedStateHandle](https://developer.android.com/reference/androidx/lifecycle/SavedStateHandle).\n\n### Setup\n\nGroovy:\n```groovy\n// Add the dependency, typically under the commonMain source set\nimplementation \"com.arkivanov.essenty:state-keeper:<essenty_version>\"\n```\n\nKotlin:\n```kotlin\n// Add the dependency, typically under the commonMain source set\nimplementation(\"com.arkivanov.essenty:state-keeper:<essenty_version>\")\n```\n\n### Content\n\nThe main [StateKeeper](https://github.com/arkivanov/Essenty/blob/master/state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/StateKeeper.kt) interface provides ability to register/unregister state suppliers, and also to consume any previously saved state. You can also find some handy [extension functions](https://github.com/arkivanov/Essenty/blob/master/state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/StateKeeperExt.kt). You can also find some handy [extension functions](https://github.com/arkivanov/Essenty/blob/master/state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/StateKeeperExt.kt).\n\nThe [StateKeeperDispatcher](https://github.com/arkivanov/Essenty/blob/master/state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/StateKeeperDispatcher.kt) interface extends `StateKeeper` and  allows state saving, by calling all registered state providers.\n\nThe [StateKeeperOwner](https://github.com/arkivanov/Essenty/blob/master/state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/StateKeeperOwner.kt) interface is just a holder of `StateKeeper`. It may be implemented by an arbitrary class, to provide convenient API.\n\n#### Android extensions\n\nFrom Android side, `StateKeeper` can be obtained by using special functions, can be found [here](https://github.com/arkivanov/Essenty/blob/master/state-keeper/src/androidMain/kotlin/com/arkivanov/essenty/statekeeper/AndroidExt.kt).\n\nThere are also some handy [extension functions](https://github.com/arkivanov/Essenty/blob/master/state-keeper/src/androidMain/kotlin/com/arkivanov/essenty/statekeeper/BundleExt.kt) for serializing/deserializing `KSerializable` objects to/from [Bundle](https://developer.android.com/reference/android/os/Bundle):\n\n- `fun <T : Any> Bundle.putSerializable(key: String?, value: T?, strategy: SerializationStrategy<T>)`\n- `fun <T : Any> Bundle.getSerializable(key: String?, strategy: DeserializationStrategy<T>): T?`\n- `fun Bundle.putSerializableContainer(key: String?, value: SerializableContainer?)`\n- `fun Bundle.getSerializableContainer(key: String?): SerializableContainer?`\n\nSimilar extensions are also available for [PersistableBundle](https://developer.android.com/reference/android/os/PersistableBundle).\n\n### Usage example\n\n#### Using StateKeeper\n\n> ⚠️  Make sure you [setup](https://github.com/Kotlin/kotlinx.serialization#setup) `kotlinx-serialization` properly. \n\n```kotlin\nimport com.arkivanov.essenty.statekeeper.StateKeeper\nimport kotlinx.serialization.Serializable\n\nclass SomeLogic(stateKeeper: StateKeeper) {\n    // Use the saved State if any, otherwise create a new State\n    private var state: State = stateKeeper.consume(key = \"SAVED_STATE\", strategy = State.serializer()) ?: State()\n\n    init {\n        // Register the State supplier\n        stateKeeper.register(key = \"SAVED_STATE\", strategy = State.serializer()) { state }\n    }\n\n    @Serializable\n    private class State(\n        val someValue: Int = 0\n    )\n}\n```\n\n#### Saveable properties (experimental since version `2.2.0-alpha01`)\n\n```kotlin\nimport com.arkivanov.essenty.statekeeper.StateKeeper\nimport com.arkivanov.essenty.statekeeper.saveable\nimport kotlinx.serialization.Serializable\n\nclass SomeLogic(stateKeeper: StateKeeper) {\n    private var state: State by stateKeeper.saveable(serializer = State.serializer(), init = ::State)\n\n    @Serializable\n    private class State(val someValue: Int = 0)\n}\n```\n\n#### Saveable state holders (experimental since version `2.2.0-alpha01`)\n\n```kotlin\nimport com.arkivanov.essenty.statekeeper.StateKeeper\nimport com.arkivanov.essenty.statekeeper.saveable\nimport kotlinx.serialization.Serializable\n\nclass SomeLogic(stateKeeper: StateKeeper) {\n    private val viewModel by stateKeeper.saveable(serializer = State.serializer(), state = ViewModel::state) { savedState ->\n        ViewModel(state = savedState ?: State())\n    }\n\n    private class ViewModel(var state: State)\n\n    @Serializable\n    private class State(val someValue: Int = 0)\n}\n```\n\n##### Polymorphic serialization (experimental)\n\nSometimes it might be necessary to serialize an interface or an abstract class that you don't own but have implemented. For this purpose Essenty provides `polymorphicSerializer` function that can be used to create custom polymorphic serializers for unowned base types.\n\nFor example a third-party library may have the following interface.\n\n```kotlin\ninterface Filter {\n    // Omitted code\n}\n```\n\nThen we can have multiple implementations of `Filter`.\n\n```kotlin\n@Serializable\nclass TextFilter(val text: String) : Filter { /* Omitted code */ }\n\n@Serializable\nclass RatingFilter(val stars: Int) : Filter { /* Omitted code */ }\n```\n\nNow we can create a polymorphic serializer for `Filter` as follows. It can be used to save and restore `Filter` directly via StateKeeper, or to have `Filter` as part of another `Serializable` class.\n\n```kotlin\nimport com.arkivanov.essenty.statekeeper.polymorphicSerializer\nimport com.slack.circuit.runtime.screen.Screen\nimport kotlinx.serialization.KSerializer\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.modules.SerializersModule\nimport kotlinx.serialization.modules.polymorphic\n\nobject FilterSerializer : KSerializer<Filter> by polymorphicSerializer(\n    SerializersModule {\n        polymorphic(Filter::class) {\n            subclass(TextFilter::class, TextFilter.serializer())\n            subclass(RatingFilter::class, RatingFilter.serializer())\n        }\n    }\n)\n```\n\n#### Using the StateKeeperDispatcher manually\n\nOn Android, the `StateKeeper` obtained via one of the extensions described above automatically saves and restores the state. On other platforms (if needed) the state can be saved and restored manually. A default implementation of `StateKeeperDisptacher` interface can be instantiated using the corresponding builder function. The state can be encoded as a JSON string and saved using the corresponding platform-specific API.\n\n```kotlin\nimport com.arkivanov.essenty.statekeeper.SerializableContainer\nimport com.arkivanov.essenty.statekeeper.StateKeeper\nimport com.arkivanov.essenty.statekeeper.StateKeeperDispatcher\n\nval stateKeeperDispatcher = StateKeeperDispatcher(/*Previously saved state, or null*/)\nval someLogic = SomeLogic(stateKeeperDispatcher)\n\n// At some point later when it's time to save the state\nval savedState: SerializableContainer = stateKeeperDispatcher.save()\n\n// The returned SerializableContainer can now be saved using the corresponding platform-specific API\n```\n\n## InstanceKeeper\n\nWhen writing common code targetting Android, it might be required to retain objects over Android configuration changes. This use case is covered by the `InstanceKeeper` API, which is similar to the AndroidX [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel).\n\n### Setup\n\nGroovy:\n```groovy\n// Add the dependency, typically under the commonMain source set\nimplementation \"com.arkivanov.essenty:instance-keeper:<essenty_version>\"\n```\n\nKotlin:\n```kotlin\n// Add the dependency, typically under the commonMain source set\nimplementation(\"com.arkivanov.essenty:instance-keeper:<essenty_version>\")\n```\n\n### Content\n\nThe main [InstanceKeeper](https://github.com/arkivanov/Essenty/blob/master/instance-keeper/src/commonMain/kotlin/com/arkivanov/essenty/instancekeeper/InstanceKeeper.kt) interface is responsible for storing object instances, represented by the [InstanceKeeper.Instance] interface. Instances of the `InstanceKeeper.Instance` interface survive Android Configuration changes, the `InstanceKeeper.Instance.onDestroy()` method is called when `InstanceKeeper` goes out of scope (e.g. the screen is finished). You can also find some handy [extension functions](https://github.com/arkivanov/Essenty/blob/master/instance-keeper/src/commonMain/kotlin/com/arkivanov/essenty/instancekeeper/InstanceKeeperExt.kt).\n\nThe [InstanceKeeperDispatcher](https://github.com/arkivanov/Essenty/blob/master/instance-keeper/src/commonMain/kotlin/com/arkivanov/essenty/instancekeeper/InstanceKeeperDispatcher.kt) interface extends `InstanceKeeper` and adds ability to destroy all registered instances.\n\nThe [InstanceKeeperOwner](https://github.com/arkivanov/Essenty/blob/master/instance-keeper/src/commonMain/kotlin/com/arkivanov/essenty/instancekeeper/InstanceKeeperOwner.kt) interface is just a holder of `InstanceKeeper`. It may be implemented by an arbitrary class, to provide convenient API.\n\n#### Android extensions\n\nFrom Android side, `InstanceKeeper` can be obtained by using special functions, can be found [here](https://github.com/arkivanov/Essenty/blob/master/instance-keeper/src/androidMain/kotlin/com/arkivanov/essenty/instancekeeper/AndroidExt.kt).\n\n### Usage example\n\n#### Using the InstanceKeeper\n\n```kotlin\nimport com.arkivanov.essenty.instancekeeper.InstanceKeeper\nimport com.arkivanov.essenty.instancekeeper.getOrCreate\n\nclass SomeLogic(instanceKeeper: InstanceKeeper) {\n    // Get the existing instance or create a new one\n    private val viewModel = instanceKeeper.getOrCreate { ViewModel() }\n}\n\n/*\n * Survives Android configuration changes.\n * ⚠️ Pay attention to not leak any dependencies.\n */\nclass ViewModel : InstanceKeeper.Instance {\n    override fun onDestroy() {\n        // Called when the screen is finished\n    }\n}\n```\n\n##### Alternative way (experimental since version 2.2.0-alpha01, stable since 2.2.0)\n\n```kotlin\nclass SomeLogic(instanceKeeperOwner: InstanceKeeperOwner) : InstanceKeeperOwner by instanceKeeperOwner {\n    // Get the existing instance or create a new one\n    private val viewModel = retainedInstance { ViewModel() }\n}\n```\n\n#### Using the InstanceKeeperDispatcher manually\n\nA default implementation of the `InstanceKeeperDispatcher` interface can be instantiated using the corresponding builder function:\n\n```kotlin\nimport com.arkivanov.essenty.instancekeeper.InstanceKeeper\nimport com.arkivanov.essenty.instancekeeper.InstanceKeeperDispatcher\n\n// Create a new instance of InstanceKeeperDispatcher, or reuse an existing one\nval instanceKeeperDispatcher = InstanceKeeperDispatcher()\nval someLogic = SomeLogic(instanceKeeperDispatcher)\n\n// At some point later\ninstanceKeeperDispatcher.destroy()\n```\n\n## BackHandler\n\nThe `BackHandler` API provides ability to handle back button clicks (e.g. the Android device's back button), in common code. This API is similar to AndroidX [OnBackPressedDispatcher](https://developer.android.com/reference/androidx/activity/OnBackPressedDispatcher).\n\n### Setup\n\nGroovy:\n```groovy\n// Add the dependency, typically under the commonMain source set\nimplementation \"com.arkivanov.essenty:back-handler:<essenty_version>\"\n```\n\nKotlin:\n```kotlin\n// Add the dependency, typically under the commonMain source set\nimplementation(\"com.arkivanov.essenty:back-handler:<essenty_version>\")\n```\n\n### Content\n\nThe [BackHandler](https://github.com/arkivanov/Essenty/blob/master/back-handler/src/commonMain/kotlin/com/arkivanov/essenty/backhandler/BackHandler.kt) interface provides ability to register and unregister back button callbacks. When the device's back button is pressed, all registered callbacks are called in reverse order, the first enabled callback is called and the iteration finishes.\n\n> Starting from `v1.2.x`, when the device's back button is pressed, all registered callbacks are sorted in ascending order first by priority and then by index, the last enabled callback is called.\n\n[BackCallback](https://github.com/arkivanov/Essenty/blob/master/back-handler/src/commonMain/kotlin/com/arkivanov/essenty/backhandler/BackCallback.kt) allows handling back events, including predictive back gestures.\n\nThe [BackDispatcher](https://github.com/arkivanov/Essenty/blob/master/back-handler/src/commonMain/kotlin/com/arkivanov/essenty/backhandler/BackDispatcher.kt) interface extends `BackHandler` and is responsible for triggering the registered callbacks. The `BackDispatcher.back()` method triggers all registered callbacks in reverse order, and returns `true` if an enabled callback was called, and `false` if no enabled callback was found.\n\n#### Android extensions\n\nFrom Android side, `BackHandler` can be obtained by using special functions, can be found [here](https://github.com/arkivanov/Essenty/blob/master/back-handler/src/androidMain/kotlin/com/arkivanov/essenty/backhandler/AndroidBackHandler.kt).\n\n### Predictive Back Gesture\n\nBoth `BackHandler` and `BackDispatcher` bring the new [Android Predictive Back Gesture](https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture) to Kotlin Multiplatform. \n\n#### Predictive Back Gesture on Android\n\nOn Android, the predictive back gesture only works starting with Android T. On Android T, it works only between Activities, if enabled in the system settings. Starting with Android U, the predictive back gesture also works between application's screens inside an Activity. In the latter case, back gesture events can be handled using `BackCallback`.\n\n#### Predictive Back Gesture on other platforms\n\nOn all other platforms, predictive back gestures can be dispatched manually via `BackDispatcher`. This can be done e.g. by adding an overlay on top of the UI and handling touch events manually.\n\n### Usage example\n\n#### Using the BackHandler\n\n```kotlin\nimport com.arkivanov.essenty.backhandler.BackHandler\n\nclass SomeLogic(backHandler: BackHandler) {\n    private val callback = BackCallback {\n        // Called when the back button is pressed\n    }\n\n    init {\n        backHandler.register(callback)\n\n        // Disable the callback when needed\n        callback.isEnabled = false\n    }\n}\n```\n\n#### Using the BackDispatcher manually\n\nA default implementation of the `BackDispatcher` interface can be instantiated using the corresponding builder function:\n\n```kotlin\nimport com.arkivanov.essenty.backhandler.BackDispatcher\n\nval backDispatcher = BackDispatcher()\nval someLogic = SomeLogic(backDispatcher)\n\nif (!backDispatcher.back()) {\n    // The back pressed event was not handled\n}\n```\n\n## Author\n\nTwitter: [@arkann1985](https://twitter.com/arkann1985)\n\nIf you like this project you can always <a href=\"https://www.buymeacoffee.com/arkivanov\" target=\"_blank\"><img src=\"https://cdn.buymeacoffee.com/buttons/v2/default-blue.png\" alt=\"Buy Me A Coffee\" height=32></a> ;-)\n"
  },
  {
    "path": "back-handler/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "back-handler/api/android/back-handler.api",
    "content": "public final class com/arkivanov/essenty/backhandler/AndroidBackHandlerKt {\n\tpublic static final fun BackHandler (Landroidx/activity/OnBackPressedDispatcher;)Lcom/arkivanov/essenty/backhandler/BackHandler;\n\tpublic static final fun BackHandler (Landroidx/activity/OnBackPressedDispatcher;Landroidx/lifecycle/LifecycleOwner;)Lcom/arkivanov/essenty/backhandler/BackHandler;\n\tpublic static final fun backHandler (Landroidx/activity/OnBackPressedDispatcherOwner;)Lcom/arkivanov/essenty/backhandler/BackHandler;\n\tpublic static final fun connectOnBackPressedCallback (Lcom/arkivanov/essenty/backhandler/BackDispatcher;)Landroidx/activity/OnBackPressedCallback;\n}\n\npublic abstract class com/arkivanov/essenty/backhandler/BackCallback {\n\tpublic static final field Companion Lcom/arkivanov/essenty/backhandler/BackCallback$Companion;\n\tpublic static final field PRIORITY_DEFAULT I\n\tpublic static final field PRIORITY_MAX I\n\tpublic static final field PRIORITY_MIN I\n\tpublic fun <init> ()V\n\tpublic fun <init> (ZI)V\n\tpublic synthetic fun <init> (ZIILkotlin/jvm/internal/DefaultConstructorMarker;)V\n\tpublic final fun addEnabledChangedListener (Lkotlin/jvm/functions/Function1;)V\n\tpublic final fun getPriority ()I\n\tpublic final fun isEnabled ()Z\n\tpublic abstract fun onBack ()V\n\tpublic fun onBackCancelled ()V\n\tpublic fun onBackProgressed (Lcom/arkivanov/essenty/backhandler/BackEvent;)V\n\tpublic fun onBackStarted (Lcom/arkivanov/essenty/backhandler/BackEvent;)V\n\tpublic final fun removeEnabledChangedListener (Lkotlin/jvm/functions/Function1;)V\n\tpublic final fun setEnabled (Z)V\n\tpublic final fun setPriority (I)V\n}\n\npublic final class com/arkivanov/essenty/backhandler/BackCallback$Companion {\n}\n\npublic final class com/arkivanov/essenty/backhandler/BackCallbackKt {\n\tpublic static final fun BackCallback (ZILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/backhandler/BackCallback;\n\tpublic static synthetic fun BackCallback$default (ZILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/essenty/backhandler/BackCallback;\n}\n\npublic abstract interface class com/arkivanov/essenty/backhandler/BackDispatcher : com/arkivanov/essenty/backhandler/BackHandler {\n\tpublic abstract fun addEnabledChangedListener (Lkotlin/jvm/functions/Function1;)V\n\tpublic abstract fun back ()Z\n\tpublic abstract fun cancelPredictiveBack ()V\n\tpublic abstract fun isEnabled ()Z\n\tpublic abstract fun progressPredictiveBack (Lcom/arkivanov/essenty/backhandler/BackEvent;)V\n\tpublic abstract fun removeEnabledChangedListener (Lkotlin/jvm/functions/Function1;)V\n\tpublic abstract fun startPredictiveBack (Lcom/arkivanov/essenty/backhandler/BackEvent;)Z\n}\n\npublic final class com/arkivanov/essenty/backhandler/BackDispatcherKt {\n\tpublic static final fun BackDispatcher ()Lcom/arkivanov/essenty/backhandler/BackDispatcher;\n}\n\npublic final class com/arkivanov/essenty/backhandler/BackEvent {\n\tpublic fun <init> ()V\n\tpublic fun <init> (FLcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;FF)V\n\tpublic synthetic fun <init> (FLcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;FFILkotlin/jvm/internal/DefaultConstructorMarker;)V\n\tpublic final fun component1 ()F\n\tpublic final fun component2 ()Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic final fun component3 ()F\n\tpublic final fun component4 ()F\n\tpublic final fun copy (FLcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;FF)Lcom/arkivanov/essenty/backhandler/BackEvent;\n\tpublic static synthetic fun copy$default (Lcom/arkivanov/essenty/backhandler/BackEvent;FLcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;FFILjava/lang/Object;)Lcom/arkivanov/essenty/backhandler/BackEvent;\n\tpublic fun equals (Ljava/lang/Object;)Z\n\tpublic final fun getProgress ()F\n\tpublic final fun getSwipeEdge ()Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic final fun getTouchX ()F\n\tpublic final fun getTouchY ()F\n\tpublic fun hashCode ()I\n\tpublic fun toString ()Ljava/lang/String;\n}\n\npublic final class com/arkivanov/essenty/backhandler/BackEvent$SwipeEdge : java/lang/Enum {\n\tpublic static final field LEFT Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic static final field RIGHT Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic static final field UNKNOWN Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic static fun getEntries ()Lkotlin/enums/EnumEntries;\n\tpublic static fun valueOf (Ljava/lang/String;)Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic static fun values ()[Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n}\n\npublic abstract interface class com/arkivanov/essenty/backhandler/BackHandler {\n\tpublic abstract fun isRegistered (Lcom/arkivanov/essenty/backhandler/BackCallback;)Z\n\tpublic abstract fun register (Lcom/arkivanov/essenty/backhandler/BackCallback;)V\n\tpublic abstract fun unregister (Lcom/arkivanov/essenty/backhandler/BackCallback;)V\n}\n\npublic abstract interface class com/arkivanov/essenty/backhandler/BackHandlerOwner {\n\tpublic abstract fun getBackHandler ()Lcom/arkivanov/essenty/backhandler/BackHandler;\n}\n\n"
  },
  {
    "path": "back-handler/api/back-handler.klib.api",
    "content": "// Klib ABI Dump\n// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxX64, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, watchosArm32, watchosArm64, watchosSimulatorArm64, watchosX64]\n// Rendering settings:\n// - Signature version: 2\n// - Show manifest properties: true\n// - Show declarations: true\n\n// Library unique name: <com.arkivanov.essenty:back-handler>\nabstract interface com.arkivanov.essenty.backhandler/BackDispatcher : com.arkivanov.essenty.backhandler/BackHandler { // com.arkivanov.essenty.backhandler/BackDispatcher|null[0]\n    abstract val isEnabled // com.arkivanov.essenty.backhandler/BackDispatcher.isEnabled|{}isEnabled[0]\n        abstract fun <get-isEnabled>(): kotlin/Boolean // com.arkivanov.essenty.backhandler/BackDispatcher.isEnabled.<get-isEnabled>|<get-isEnabled>(){}[0]\n\n    abstract fun addEnabledChangedListener(kotlin/Function1<kotlin/Boolean, kotlin/Unit>) // com.arkivanov.essenty.backhandler/BackDispatcher.addEnabledChangedListener|addEnabledChangedListener(kotlin.Function1<kotlin.Boolean,kotlin.Unit>){}[0]\n    abstract fun back(): kotlin/Boolean // com.arkivanov.essenty.backhandler/BackDispatcher.back|back(){}[0]\n    abstract fun cancelPredictiveBack() // com.arkivanov.essenty.backhandler/BackDispatcher.cancelPredictiveBack|cancelPredictiveBack(){}[0]\n    abstract fun progressPredictiveBack(com.arkivanov.essenty.backhandler/BackEvent) // com.arkivanov.essenty.backhandler/BackDispatcher.progressPredictiveBack|progressPredictiveBack(com.arkivanov.essenty.backhandler.BackEvent){}[0]\n    abstract fun removeEnabledChangedListener(kotlin/Function1<kotlin/Boolean, kotlin/Unit>) // com.arkivanov.essenty.backhandler/BackDispatcher.removeEnabledChangedListener|removeEnabledChangedListener(kotlin.Function1<kotlin.Boolean,kotlin.Unit>){}[0]\n    abstract fun startPredictiveBack(com.arkivanov.essenty.backhandler/BackEvent): kotlin/Boolean // com.arkivanov.essenty.backhandler/BackDispatcher.startPredictiveBack|startPredictiveBack(com.arkivanov.essenty.backhandler.BackEvent){}[0]\n}\n\nabstract interface com.arkivanov.essenty.backhandler/BackHandler { // com.arkivanov.essenty.backhandler/BackHandler|null[0]\n    abstract fun isRegistered(com.arkivanov.essenty.backhandler/BackCallback): kotlin/Boolean // com.arkivanov.essenty.backhandler/BackHandler.isRegistered|isRegistered(com.arkivanov.essenty.backhandler.BackCallback){}[0]\n    abstract fun register(com.arkivanov.essenty.backhandler/BackCallback) // com.arkivanov.essenty.backhandler/BackHandler.register|register(com.arkivanov.essenty.backhandler.BackCallback){}[0]\n    abstract fun unregister(com.arkivanov.essenty.backhandler/BackCallback) // com.arkivanov.essenty.backhandler/BackHandler.unregister|unregister(com.arkivanov.essenty.backhandler.BackCallback){}[0]\n}\n\nabstract interface com.arkivanov.essenty.backhandler/BackHandlerOwner { // com.arkivanov.essenty.backhandler/BackHandlerOwner|null[0]\n    abstract val backHandler // com.arkivanov.essenty.backhandler/BackHandlerOwner.backHandler|{}backHandler[0]\n        abstract fun <get-backHandler>(): com.arkivanov.essenty.backhandler/BackHandler // com.arkivanov.essenty.backhandler/BackHandlerOwner.backHandler.<get-backHandler>|<get-backHandler>(){}[0]\n}\n\nabstract class com.arkivanov.essenty.backhandler/BackCallback { // com.arkivanov.essenty.backhandler/BackCallback|null[0]\n    constructor <init>(kotlin/Boolean = ..., kotlin/Int = ...) // com.arkivanov.essenty.backhandler/BackCallback.<init>|<init>(kotlin.Boolean;kotlin.Int){}[0]\n\n    final var isEnabled // com.arkivanov.essenty.backhandler/BackCallback.isEnabled|{}isEnabled[0]\n        final fun <get-isEnabled>(): kotlin/Boolean // com.arkivanov.essenty.backhandler/BackCallback.isEnabled.<get-isEnabled>|<get-isEnabled>(){}[0]\n        final fun <set-isEnabled>(kotlin/Boolean) // com.arkivanov.essenty.backhandler/BackCallback.isEnabled.<set-isEnabled>|<set-isEnabled>(kotlin.Boolean){}[0]\n    final var priority // com.arkivanov.essenty.backhandler/BackCallback.priority|{}priority[0]\n        final fun <get-priority>(): kotlin/Int // com.arkivanov.essenty.backhandler/BackCallback.priority.<get-priority>|<get-priority>(){}[0]\n        final fun <set-priority>(kotlin/Int) // com.arkivanov.essenty.backhandler/BackCallback.priority.<set-priority>|<set-priority>(kotlin.Int){}[0]\n\n    abstract fun onBack() // com.arkivanov.essenty.backhandler/BackCallback.onBack|onBack(){}[0]\n    final fun addEnabledChangedListener(kotlin/Function1<kotlin/Boolean, kotlin/Unit>) // com.arkivanov.essenty.backhandler/BackCallback.addEnabledChangedListener|addEnabledChangedListener(kotlin.Function1<kotlin.Boolean,kotlin.Unit>){}[0]\n    final fun removeEnabledChangedListener(kotlin/Function1<kotlin/Boolean, kotlin/Unit>) // com.arkivanov.essenty.backhandler/BackCallback.removeEnabledChangedListener|removeEnabledChangedListener(kotlin.Function1<kotlin.Boolean,kotlin.Unit>){}[0]\n    open fun onBackCancelled() // com.arkivanov.essenty.backhandler/BackCallback.onBackCancelled|onBackCancelled(){}[0]\n    open fun onBackProgressed(com.arkivanov.essenty.backhandler/BackEvent) // com.arkivanov.essenty.backhandler/BackCallback.onBackProgressed|onBackProgressed(com.arkivanov.essenty.backhandler.BackEvent){}[0]\n    open fun onBackStarted(com.arkivanov.essenty.backhandler/BackEvent) // com.arkivanov.essenty.backhandler/BackCallback.onBackStarted|onBackStarted(com.arkivanov.essenty.backhandler.BackEvent){}[0]\n\n    final object Companion { // com.arkivanov.essenty.backhandler/BackCallback.Companion|null[0]\n        final const val PRIORITY_DEFAULT // com.arkivanov.essenty.backhandler/BackCallback.Companion.PRIORITY_DEFAULT|{}PRIORITY_DEFAULT[0]\n            final fun <get-PRIORITY_DEFAULT>(): kotlin/Int // com.arkivanov.essenty.backhandler/BackCallback.Companion.PRIORITY_DEFAULT.<get-PRIORITY_DEFAULT>|<get-PRIORITY_DEFAULT>(){}[0]\n        final const val PRIORITY_MAX // com.arkivanov.essenty.backhandler/BackCallback.Companion.PRIORITY_MAX|{}PRIORITY_MAX[0]\n            final fun <get-PRIORITY_MAX>(): kotlin/Int // com.arkivanov.essenty.backhandler/BackCallback.Companion.PRIORITY_MAX.<get-PRIORITY_MAX>|<get-PRIORITY_MAX>(){}[0]\n        final const val PRIORITY_MIN // com.arkivanov.essenty.backhandler/BackCallback.Companion.PRIORITY_MIN|{}PRIORITY_MIN[0]\n            final fun <get-PRIORITY_MIN>(): kotlin/Int // com.arkivanov.essenty.backhandler/BackCallback.Companion.PRIORITY_MIN.<get-PRIORITY_MIN>|<get-PRIORITY_MIN>(){}[0]\n    }\n}\n\nfinal class com.arkivanov.essenty.backhandler/BackEvent { // com.arkivanov.essenty.backhandler/BackEvent|null[0]\n    constructor <init>(kotlin/Float = ..., com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge = ..., kotlin/Float = ..., kotlin/Float = ...) // com.arkivanov.essenty.backhandler/BackEvent.<init>|<init>(kotlin.Float;com.arkivanov.essenty.backhandler.BackEvent.SwipeEdge;kotlin.Float;kotlin.Float){}[0]\n\n    final val progress // com.arkivanov.essenty.backhandler/BackEvent.progress|{}progress[0]\n        final fun <get-progress>(): kotlin/Float // com.arkivanov.essenty.backhandler/BackEvent.progress.<get-progress>|<get-progress>(){}[0]\n    final val swipeEdge // com.arkivanov.essenty.backhandler/BackEvent.swipeEdge|{}swipeEdge[0]\n        final fun <get-swipeEdge>(): com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge // com.arkivanov.essenty.backhandler/BackEvent.swipeEdge.<get-swipeEdge>|<get-swipeEdge>(){}[0]\n    final val touchX // com.arkivanov.essenty.backhandler/BackEvent.touchX|{}touchX[0]\n        final fun <get-touchX>(): kotlin/Float // com.arkivanov.essenty.backhandler/BackEvent.touchX.<get-touchX>|<get-touchX>(){}[0]\n    final val touchY // com.arkivanov.essenty.backhandler/BackEvent.touchY|{}touchY[0]\n        final fun <get-touchY>(): kotlin/Float // com.arkivanov.essenty.backhandler/BackEvent.touchY.<get-touchY>|<get-touchY>(){}[0]\n\n    final fun component1(): kotlin/Float // com.arkivanov.essenty.backhandler/BackEvent.component1|component1(){}[0]\n    final fun component2(): com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge // com.arkivanov.essenty.backhandler/BackEvent.component2|component2(){}[0]\n    final fun component3(): kotlin/Float // com.arkivanov.essenty.backhandler/BackEvent.component3|component3(){}[0]\n    final fun component4(): kotlin/Float // com.arkivanov.essenty.backhandler/BackEvent.component4|component4(){}[0]\n    final fun copy(kotlin/Float = ..., com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge = ..., kotlin/Float = ..., kotlin/Float = ...): com.arkivanov.essenty.backhandler/BackEvent // com.arkivanov.essenty.backhandler/BackEvent.copy|copy(kotlin.Float;com.arkivanov.essenty.backhandler.BackEvent.SwipeEdge;kotlin.Float;kotlin.Float){}[0]\n    final fun equals(kotlin/Any?): kotlin/Boolean // com.arkivanov.essenty.backhandler/BackEvent.equals|equals(kotlin.Any?){}[0]\n    final fun hashCode(): kotlin/Int // com.arkivanov.essenty.backhandler/BackEvent.hashCode|hashCode(){}[0]\n    final fun toString(): kotlin/String // com.arkivanov.essenty.backhandler/BackEvent.toString|toString(){}[0]\n\n    final enum class SwipeEdge : kotlin/Enum<com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge> { // com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge|null[0]\n        enum entry LEFT // com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge.LEFT|null[0]\n        enum entry RIGHT // com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge.RIGHT|null[0]\n        enum entry UNKNOWN // com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge.UNKNOWN|null[0]\n\n        final val entries // com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge.entries|#static{}entries[0]\n            final fun <get-entries>(): kotlin.enums/EnumEntries<com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge> // com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge.entries.<get-entries>|<get-entries>#static(){}[0]\n\n        final fun valueOf(kotlin/String): com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge // com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge.valueOf|valueOf#static(kotlin.String){}[0]\n        final fun values(): kotlin/Array<com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge> // com.arkivanov.essenty.backhandler/BackEvent.SwipeEdge.values|values#static(){}[0]\n    }\n}\n\nfinal fun com.arkivanov.essenty.backhandler/BackCallback(kotlin/Boolean = ..., kotlin/Int = ..., kotlin/Function1<com.arkivanov.essenty.backhandler/BackEvent, kotlin/Unit>? = ..., kotlin/Function1<com.arkivanov.essenty.backhandler/BackEvent, kotlin/Unit>? = ..., kotlin/Function0<kotlin/Unit>? = ..., kotlin/Function0<kotlin/Unit>): com.arkivanov.essenty.backhandler/BackCallback // com.arkivanov.essenty.backhandler/BackCallback|BackCallback(kotlin.Boolean;kotlin.Int;kotlin.Function1<com.arkivanov.essenty.backhandler.BackEvent,kotlin.Unit>?;kotlin.Function1<com.arkivanov.essenty.backhandler.BackEvent,kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>){}[0]\nfinal fun com.arkivanov.essenty.backhandler/BackDispatcher(): com.arkivanov.essenty.backhandler/BackDispatcher // com.arkivanov.essenty.backhandler/BackDispatcher|BackDispatcher(){}[0]\n"
  },
  {
    "path": "back-handler/api/jvm/back-handler.api",
    "content": "public abstract class com/arkivanov/essenty/backhandler/BackCallback {\n\tpublic static final field Companion Lcom/arkivanov/essenty/backhandler/BackCallback$Companion;\n\tpublic static final field PRIORITY_DEFAULT I\n\tpublic static final field PRIORITY_MAX I\n\tpublic static final field PRIORITY_MIN I\n\tpublic fun <init> ()V\n\tpublic fun <init> (ZI)V\n\tpublic synthetic fun <init> (ZIILkotlin/jvm/internal/DefaultConstructorMarker;)V\n\tpublic final fun addEnabledChangedListener (Lkotlin/jvm/functions/Function1;)V\n\tpublic final fun getPriority ()I\n\tpublic final fun isEnabled ()Z\n\tpublic abstract fun onBack ()V\n\tpublic fun onBackCancelled ()V\n\tpublic fun onBackProgressed (Lcom/arkivanov/essenty/backhandler/BackEvent;)V\n\tpublic fun onBackStarted (Lcom/arkivanov/essenty/backhandler/BackEvent;)V\n\tpublic final fun removeEnabledChangedListener (Lkotlin/jvm/functions/Function1;)V\n\tpublic final fun setEnabled (Z)V\n\tpublic final fun setPriority (I)V\n}\n\npublic final class com/arkivanov/essenty/backhandler/BackCallback$Companion {\n}\n\npublic final class com/arkivanov/essenty/backhandler/BackCallbackKt {\n\tpublic static final fun BackCallback (ZILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/backhandler/BackCallback;\n\tpublic static synthetic fun BackCallback$default (ZILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/essenty/backhandler/BackCallback;\n}\n\npublic abstract interface class com/arkivanov/essenty/backhandler/BackDispatcher : com/arkivanov/essenty/backhandler/BackHandler {\n\tpublic abstract fun addEnabledChangedListener (Lkotlin/jvm/functions/Function1;)V\n\tpublic abstract fun back ()Z\n\tpublic abstract fun cancelPredictiveBack ()V\n\tpublic abstract fun isEnabled ()Z\n\tpublic abstract fun progressPredictiveBack (Lcom/arkivanov/essenty/backhandler/BackEvent;)V\n\tpublic abstract fun removeEnabledChangedListener (Lkotlin/jvm/functions/Function1;)V\n\tpublic abstract fun startPredictiveBack (Lcom/arkivanov/essenty/backhandler/BackEvent;)Z\n}\n\npublic final class com/arkivanov/essenty/backhandler/BackDispatcherKt {\n\tpublic static final fun BackDispatcher ()Lcom/arkivanov/essenty/backhandler/BackDispatcher;\n}\n\npublic final class com/arkivanov/essenty/backhandler/BackEvent {\n\tpublic fun <init> ()V\n\tpublic fun <init> (FLcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;FF)V\n\tpublic synthetic fun <init> (FLcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;FFILkotlin/jvm/internal/DefaultConstructorMarker;)V\n\tpublic final fun component1 ()F\n\tpublic final fun component2 ()Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic final fun component3 ()F\n\tpublic final fun component4 ()F\n\tpublic final fun copy (FLcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;FF)Lcom/arkivanov/essenty/backhandler/BackEvent;\n\tpublic static synthetic fun copy$default (Lcom/arkivanov/essenty/backhandler/BackEvent;FLcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;FFILjava/lang/Object;)Lcom/arkivanov/essenty/backhandler/BackEvent;\n\tpublic fun equals (Ljava/lang/Object;)Z\n\tpublic final fun getProgress ()F\n\tpublic final fun getSwipeEdge ()Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic final fun getTouchX ()F\n\tpublic final fun getTouchY ()F\n\tpublic fun hashCode ()I\n\tpublic fun toString ()Ljava/lang/String;\n}\n\npublic final class com/arkivanov/essenty/backhandler/BackEvent$SwipeEdge : java/lang/Enum {\n\tpublic static final field LEFT Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic static final field RIGHT Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic static final field UNKNOWN Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic static fun getEntries ()Lkotlin/enums/EnumEntries;\n\tpublic static fun valueOf (Ljava/lang/String;)Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n\tpublic static fun values ()[Lcom/arkivanov/essenty/backhandler/BackEvent$SwipeEdge;\n}\n\npublic abstract interface class com/arkivanov/essenty/backhandler/BackHandler {\n\tpublic abstract fun isRegistered (Lcom/arkivanov/essenty/backhandler/BackCallback;)Z\n\tpublic abstract fun register (Lcom/arkivanov/essenty/backhandler/BackCallback;)V\n\tpublic abstract fun unregister (Lcom/arkivanov/essenty/backhandler/BackCallback;)V\n}\n\npublic abstract interface class com/arkivanov/essenty/backhandler/BackHandlerOwner {\n\tpublic abstract fun getBackHandler ()Lcom/arkivanov/essenty/backhandler/BackHandler;\n}\n\n"
  },
  {
    "path": "back-handler/build.gradle.kts",
    "content": "import com.arkivanov.gradle.bundle\nimport com.arkivanov.gradle.setupBinaryCompatibilityValidator\nimport com.arkivanov.gradle.setupMultiplatform\nimport com.arkivanov.gradle.setupPublication\nimport com.arkivanov.gradle.setupSourceSets\n\nplugins {\n    id(\"kotlin-multiplatform\")\n    id(\"com.android.library\")\n    id(\"com.arkivanov.gradle.setup\")\n}\n\nsetupMultiplatform()\nsetupPublication()\nsetupBinaryCompatibilityValidator()\n\nandroid {\n    namespace = \"com.arkivanov.essenty.backhandler\"\n}\n\nkotlin {\n    setupSourceSets {\n        val android by bundle()\n\n        common.main.dependencies {\n            implementation(project(\":utils-internal\"))\n        }\n\n        android.main.dependencies {\n            implementation(deps.androidx.activity.activityKtx)\n        }\n    }\n}\n"
  },
  {
    "path": "back-handler/src/androidMain/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest/>\n"
  },
  {
    "path": "back-handler/src/androidMain/kotlin/com/arkivanov/essenty/backhandler/AndroidBackHandler.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\nimport androidx.activity.BackEventCompat\nimport androidx.activity.OnBackPressedCallback\nimport androidx.activity.OnBackPressedDispatcher\nimport androidx.activity.OnBackPressedDispatcherOwner\nimport androidx.lifecycle.LifecycleOwner\n\n/**\n * Creates a new instance of [BackHandler] and attaches it to the provided AndroidX [OnBackPressedDispatcher].\n */\nfun BackHandler(onBackPressedDispatcher: OnBackPressedDispatcher): BackHandler =\n    BackDispatcher().also { dispatcher ->\n        onBackPressedDispatcher.addCallback(dispatcher.connectOnBackPressedCallback())\n    }\n\n/**\n * Creates a new instance of [BackHandler] and attaches it to the provided AndroidX [OnBackPressedDispatcher]\n * only when the [LifecycleOwner]'s Lifecycle is [STARTED][androidx.lifecycle.Lifecycle.State.STARTED].\n */\nfun BackHandler(\n    onBackPressedDispatcher: OnBackPressedDispatcher,\n    lifecycleOwner: LifecycleOwner,\n): BackHandler =\n    BackDispatcher().also { dispatcher ->\n        onBackPressedDispatcher.addCallback(lifecycleOwner, dispatcher.connectOnBackPressedCallback())\n    }\n\n/**\n * Creates a new instance of [BackHandler] and attaches it to the AndroidX [OnBackPressedDispatcher].\n */\nfun OnBackPressedDispatcherOwner.backHandler(): BackHandler =\n    BackHandler(onBackPressedDispatcher = onBackPressedDispatcher)\n\n/**\n * Creates a new instance of [OnBackPressedCallback] and connects it with this [BackDispatcher].\n * All events from the returned [OnBackPressedCallback] are forwarded to this [BackDispatcher].\n * The enabled state from this [BackDispatcher] is forwarded to the returned [OnBackPressedCallback].\n */\nfun BackDispatcher.connectOnBackPressedCallback(): OnBackPressedCallback =\n    OnBackPressedCallbackAdapter(dispatcher = this)\n\nprivate class OnBackPressedCallbackAdapter(\n    private val dispatcher: BackDispatcher,\n) : OnBackPressedCallback(enabled = dispatcher.isEnabled) {\n\n    init {\n        dispatcher.addEnabledChangedListener { isEnabled = it }\n    }\n\n    override fun handleOnBackPressed() {\n        dispatcher.back()\n    }\n\n    override fun handleOnBackStarted(backEvent: BackEventCompat) {\n        dispatcher.startPredictiveBack(backEvent.toEssentyBackEvent())\n    }\n\n    override fun handleOnBackProgressed(backEvent: BackEventCompat) {\n        dispatcher.progressPredictiveBack(backEvent.toEssentyBackEvent())\n    }\n\n    override fun handleOnBackCancelled() {\n        dispatcher.cancelPredictiveBack()\n    }\n\n    private fun BackEventCompat.toEssentyBackEvent(): BackEvent =\n        BackEvent(\n            progress = progress,\n            swipeEdge = when (swipeEdge) {\n                BackEventCompat.EDGE_LEFT -> BackEvent.SwipeEdge.LEFT\n                BackEventCompat.EDGE_RIGHT -> BackEvent.SwipeEdge.RIGHT\n                else -> BackEvent.SwipeEdge.UNKNOWN\n            },\n            touchX = touchX,\n            touchY = touchY,\n        )\n}\n"
  },
  {
    "path": "back-handler/src/androidUnitTest/kotlin/com/arkivanov/essenty/backhandler/AndroidBackHandlerTest.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\nimport androidx.activity.BackEventCompat\nimport androidx.activity.BackEventCompat.Companion.EDGE_LEFT\nimport androidx.activity.BackEventCompat.Companion.EDGE_RIGHT\nimport androidx.activity.OnBackPressedDispatcher\nimport kotlin.test.Test\nimport kotlin.test.assertContentEquals\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass AndroidBackHandlerTest {\n\n    private val dispatcher = OnBackPressedDispatcher()\n    private val handler = BackHandler(onBackPressedDispatcher = dispatcher)\n\n    @Test\n    fun WHEN_created_THEN_hasEnabledCallbacks_false() {\n        assertFalse(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun WHEN_enabled_callback_registered_THEN_hasEnabledCallbacks_true() {\n        handler.register(callback(isEnabled = true))\n\n        assertTrue(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun WHEN_disabled_callback_registered_THEN_hasEnabledCallbacks_false() {\n        handler.register(callback(isEnabled = false))\n\n        assertFalse(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun WHEN_multiple_callbacks_registered_and_one_enabled_THEN_hasEnabledCallbacks_true() {\n        handler.register(callback(isEnabled = false))\n        handler.register(callback(isEnabled = true))\n        handler.register(callback(isEnabled = false))\n\n        assertTrue(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun GIVEN_multiple_disabled_callbacks_WHEN_one_callback_enabled_THEN_hasEnabledCallbacks_true() {\n        val callback2 = callback(isEnabled = false)\n        handler.register(callback(isEnabled = false))\n        handler.register(callback2)\n        handler.register(callback(isEnabled = false))\n\n        callback2.isEnabled = true\n\n        assertTrue(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun GIVEN_multiple_enabled_callbacks_WHEN_all_callbacks_disabled_except_one_THEN_hasEnabledCallbacks_true() {\n        val callbacks = listOf(callback(isEnabled = true), callback(isEnabled = true), callback(isEnabled = true))\n        callbacks.forEach(handler::register)\n\n        callbacks.drop(1).forEach { it.isEnabled = false }\n\n        assertTrue(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun GIVEN_multiple_enabled_callbacks_WHEN_all_callbacks_disabled_THEN_hasEnabledCallbacks_false() {\n        val callbacks = listOf(callback(isEnabled = true), callback(isEnabled = true), callback(isEnabled = true))\n        callbacks.forEach(handler::register)\n\n        callbacks.forEach { it.isEnabled = false }\n\n        assertFalse(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun GIVEN_multiple_enabled_callbacks_WHEN_all_callbacks_removed_THEN_hasEnabledCallbacks_false() {\n        val callbacks = listOf(callback(isEnabled = true), callback(isEnabled = true), callback(isEnabled = true))\n        callbacks.forEach(handler::register)\n\n        callbacks.forEach(handler::unregister)\n\n        assertFalse(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun GIVEN_multiple_enabled_callbacks_WHEN_all_callbacks_removed_except_one_THEN_hasEnabledCallbacks_true() {\n        val callbacks = listOf(callback(isEnabled = true), callback(isEnabled = true), callback(isEnabled = true))\n        callbacks.forEach(handler::register)\n\n        callbacks.drop(1).forEach(handler::unregister)\n\n        assertTrue(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun GIVEN_all_callbacks_disabled_WHEN_onBackPressed_THEN_callbacks_not_called() {\n        var isCalled = false\n        repeat(3) {\n            handler.register(callback(isEnabled = false) { isCalled = true })\n        }\n\n        dispatcher.onBackPressed()\n\n        assertFalse(isCalled)\n    }\n\n    @Test\n    fun GIVEN_all_callbacks_enabled_WHEN_onBackPressed_THEN_only_last_callback_called() {\n        val called = MutableList(3) { false }\n\n        repeat(called.size) { index ->\n            handler.register(callback(isEnabled = true) { called[index] = true })\n        }\n\n        dispatcher.onBackPressed()\n\n        assertContentEquals(listOf(false, false, true), called)\n    }\n\n    @Test\n    fun GIVEN_only_one_callback_enabled_WHEN_onBackPressed_THEN_only_enabled_callback_called() {\n        val called = MutableList(3) { false }\n\n        repeat(called.size) { index ->\n            handler.register(callback(isEnabled = index == 0) { called[index] = true })\n        }\n\n        dispatcher.onBackPressed()\n\n        assertContentEquals(listOf(true, false, false), called)\n    }\n\n    @Test\n    fun GIVEN_multiple_enabled_callbacks_registered_and_all_callbacks_removed_except_one_WHEN_onBackPressed_THEN_callback_called() {\n        val called = MutableList(3) { false }\n        val callbacks = List(called.size) { index -> callback(isEnabled = true) { called[index] = true } }\n        callbacks.forEach(handler::register)\n        callbacks.drop(1).forEach(handler::unregister)\n\n        dispatcher.onBackPressed()\n\n        assertContentEquals(listOf(true, false, false), called)\n    }\n\n    @Test\n    fun GIVEN_enabled_callbacks_registered_with_priorities_WHEN_onBackPressed_THEN_last_callback_with_higher_priority_called() {\n        val list = ArrayList<Int>()\n        handler.register(callback(isEnabled = true, priority = 0) { list += 1 })\n        handler.register(callback(isEnabled = true, priority = 1) { list += 2 })\n        handler.register(callback(isEnabled = true, priority = 2) { list += 3 })\n        handler.register(callback(isEnabled = true, priority = 1) { list += 4 })\n        handler.register(callback(isEnabled = true, priority = 2) { list += 5 })\n        handler.register(callback(isEnabled = true, priority = 0) { list += 6 })\n        handler.register(callback(isEnabled = true, priority = 1) { list += 7 })\n        handler.register(callback(isEnabled = true, priority = 0) { list += 8 })\n\n        dispatcher.onBackPressed()\n\n        assertContentEquals(listOf(5), list)\n    }\n\n    @Test\n    fun GIVEN_enabled_callbacks_registered_with_priorities_WHEN_priority_changed_and_onBackPressed_THEN_last_callback_with_higher_priority_called() {\n        val list = ArrayList<Int>()\n        handler.register(callback(isEnabled = true, priority = 0) { list += 1 })\n        val callback = callback(isEnabled = true, priority = 1) { list += 2 }\n        handler.register(callback)\n        handler.register(callback(isEnabled = true, priority = 2) { list += 3 })\n\n        callback.priority = 3\n        dispatcher.onBackPressed()\n\n        assertContentEquals(listOf(2), list)\n    }\n\n    @Test\n    fun WHEN_progress_with_back_THEN_callbacks_called() {\n        val receivedEvents = ArrayList<Any?>()\n\n        handler.register(\n            BackCallback(\n                onBackStarted = { receivedEvents += it },\n                onBackProgressed = { receivedEvents += it },\n                onBackCancelled = { receivedEvents += \"Cancel\" },\n                onBack = { receivedEvents += \"Back\" },\n            )\n        )\n\n        dispatcher.dispatchOnBackStarted(BackEventCompat(progress = 0.1F, swipeEdge = EDGE_LEFT, touchX = 1F, touchY = 2F))\n        dispatcher.dispatchOnBackProgressed(BackEventCompat(progress = 0.2F, swipeEdge = EDGE_RIGHT, touchX = 2F, touchY = 3F))\n        dispatcher.dispatchOnBackProgressed(BackEventCompat(progress = 0.3F, swipeEdge = EDGE_LEFT, touchX = 3F, touchY = 4F))\n        dispatcher.onBackPressed()\n\n        assertContentEquals(\n            listOf(\n                BackEvent(progress = 0.1F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 1F, touchY = 2F),\n                BackEvent(progress = 0.2F, swipeEdge = BackEvent.SwipeEdge.RIGHT, touchX = 2F, touchY = 3F),\n                BackEvent(progress = 0.3F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 3F, touchY = 4F),\n                \"Back\",\n            ),\n            receivedEvents,\n        )\n    }\n\n    @Test\n    fun WHEN_progress_with_cancel_THEN_callbacks_called() {\n        val receivedEvents = ArrayList<Any?>()\n\n        handler.register(\n            BackCallback(\n                onBackStarted = { receivedEvents += it },\n                onBackProgressed = { receivedEvents += it },\n                onBackCancelled = { receivedEvents += \"Cancel\" },\n                onBack = { receivedEvents += \"Back\" },\n            )\n        )\n\n        dispatcher.dispatchOnBackStarted(BackEventCompat(progress = 0.1F, swipeEdge = EDGE_LEFT, touchX = 1F, touchY = 2F))\n        dispatcher.dispatchOnBackProgressed(BackEventCompat(progress = 0.2F, swipeEdge = EDGE_RIGHT, touchX = 2F, touchY = 3F))\n        dispatcher.dispatchOnBackProgressed(BackEventCompat(progress = 0.3F, swipeEdge = EDGE_LEFT, touchX = 3F, touchY = 4F))\n        dispatcher.dispatchOnBackCancelled()\n\n        assertContentEquals(\n            listOf(\n                BackEvent(progress = 0.1F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 1F, touchY = 2F),\n                BackEvent(progress = 0.2F, swipeEdge = BackEvent.SwipeEdge.RIGHT, touchX = 2F, touchY = 3F),\n                BackEvent(progress = 0.3F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 3F, touchY = 4F),\n                \"Cancel\",\n            ),\n            receivedEvents,\n        )\n    }\n\n    private fun callback(\n        isEnabled: Boolean = true,\n        priority: Int = BackCallback.PRIORITY_DEFAULT,\n        onBack: () -> Unit = {},\n    ): BackCallback =\n        BackCallback(\n            isEnabled = isEnabled,\n            priority = priority,\n            onBack = onBack,\n        )\n}\n"
  },
  {
    "path": "back-handler/src/androidUnitTest/kotlin/com/arkivanov/essenty/backhandler/AndroidBackHandlerWithLifecycleTest.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\nimport androidx.activity.OnBackPressedDispatcher\nimport androidx.lifecycle.Lifecycle\nimport androidx.lifecycle.LifecycleOwner\nimport androidx.lifecycle.LifecycleRegistry\nimport kotlin.test.Test\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass AndroidBackHandlerWithLifecycleTest {\n\n    private val dispatcher = OnBackPressedDispatcher()\n    private val lifecycleOwner = LifecycleOwnerImpl()\n\n    @Test\n    fun GIVEN_lifecycle_created_WHEN_handler_created_THEN_hasEnabledCallbacks_returns_false() {\n        lifecycleOwner.lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)\n\n        val handler = handler()\n        handler.register(callback())\n\n        assertFalse(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun GIVEN_lifecycle_started_WHEN_handler_created_THEN_hasEnabledCallbacks_returns_true() {\n        lifecycleOwner.lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START)\n\n        val handler = handler()\n        handler.register(callback())\n\n        assertTrue(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun GIVEN_handler_created_WHEN_lifecycle_started_THEN_hasEnabledCallbacks_returns_true() {\n        val handler = handler()\n        handler.register(callback())\n\n        lifecycleOwner.lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START)\n\n        assertTrue(dispatcher.hasEnabledCallbacks())\n    }\n\n    @Test\n    fun GIVEN_lifecycle_started_WHEN_lifecycle_stopped_THEN_hasEnabledCallbacks_returns_false() {\n        lifecycleOwner.lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START)\n        val handler = handler()\n        handler.register(callback())\n\n        lifecycleOwner.lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP)\n\n        assertFalse(dispatcher.hasEnabledCallbacks())\n    }\n\n    private fun handler(): BackHandler =\n        BackHandler(\n            onBackPressedDispatcher = dispatcher,\n            lifecycleOwner = lifecycleOwner,\n        )\n\n    private fun callback(): BackCallback =\n        BackCallback(isEnabled = true, onBack = {})\n\n    private class LifecycleOwnerImpl : LifecycleOwner {\n        override val lifecycle: LifecycleRegistry = LifecycleRegistry.createUnsafe(this)\n    }\n}\n"
  },
  {
    "path": "back-handler/src/androidUnitTest/kotlin/com/arkivanov/essenty/backhandler/OnBackPressedCallbackAdapterTest.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\nimport androidx.activity.BackEventCompat\nimport kotlin.test.Test\nimport kotlin.test.assertContentEquals\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass OnBackPressedCallbackAdapterTest {\n\n    private val dispatcher = BackDispatcher()\n\n    @Test\n    fun WHEN_connected_with_empty_dispatcher_THEN_disabled() {\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        assertFalse(callback.isEnabled)\n    }\n\n    @Test\n    fun WHEN_connected_with_not_empty_disabled_dispatcher_THEN_disabled() {\n        dispatcher.register(BackCallback(isEnabled = false, onBack = {}))\n\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        assertFalse(callback.isEnabled)\n    }\n\n    @Test\n    fun WHEN_connected_with_not_empty_enabled_dispatcher_THEN_enabled() {\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        assertTrue(callback.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_connected_with_empty_dispatcher_WHEN_disabled_callback_registered_in_dispatcher_THEN_disabled() {\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        dispatcher.register(BackCallback(isEnabled = false, onBack = {}))\n\n        assertFalse(callback.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_connected_with_empty_dispatcher_WHEN_enabled_callback_registered_in_dispatcher_THEN_enabled() {\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n\n        assertTrue(callback.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_connected_with_not_empty_disabled_dispatcher_WHEN_disabled_callback_registered_in_dispatcher_THEN_disabled() {\n        dispatcher.register(BackCallback(isEnabled = false, onBack = {}))\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        dispatcher.register(BackCallback(isEnabled = false, onBack = {}))\n\n        assertFalse(callback.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_connected_with_not_empty_disabled_dispatcher_WHEN_enabled_callback_registered_in_dispatcher_THEN_enabled() {\n        dispatcher.register(BackCallback(isEnabled = false, onBack = {}))\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n\n        assertTrue(callback.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_connected_with_not_empty_enabled_dispatcher_WHEN_disabled_callback_registered_in_dispatcher_THEN_enabled() {\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        dispatcher.register(BackCallback(isEnabled = false, onBack = {}))\n\n        assertTrue(callback.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_connected_with_not_empty_enabled_dispatcher_WHEN_enabled_callback_registered_in_dispatcher_THEN_enabled() {\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n\n        assertTrue(callback.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_connected_with_not_empty_disabled_dispatcher_WHEN_all_callbacks_unregistered_from_dispatcher_THEN_disabled() {\n        val essentyCallback = BackCallback(isEnabled = false, onBack = {})\n        dispatcher.register(essentyCallback)\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        dispatcher.unregister(essentyCallback)\n\n        assertFalse(callback.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_connected_with_not_empty_enabled_dispatcher_WHEN_not_all_callbacks_unregistered_from_dispatcher_THEN_enabled() {\n        val essentyCallback = BackCallback(isEnabled = true, onBack = {})\n        dispatcher.register(essentyCallback)\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        dispatcher.unregister(essentyCallback)\n\n        assertTrue(callback.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_connected_with_not_empty_enabled_dispatcher_WHEN_all_callbacks_unregistered_from_dispatcher_THEN_disabled() {\n        val essentyCallback = BackCallback(isEnabled = true, onBack = {})\n        dispatcher.register(essentyCallback)\n        val callback = dispatcher.connectOnBackPressedCallback()\n\n        dispatcher.unregister(essentyCallback)\n\n        assertFalse(callback.isEnabled)\n    }\n\n    @Test\n    fun WHEN_progress_with_back_THEN_forwards() {\n        val callback = dispatcher.connectOnBackPressedCallback()\n        val receivedEvents = ArrayList<Any?>()\n        dispatcher.register(\n            BackCallback(\n                onBackStarted = { receivedEvents += it },\n                onBackProgressed = { receivedEvents += it },\n                onBackCancelled = { receivedEvents += \"Cancel\" },\n                onBack = { receivedEvents += \"Back\" },\n            )\n        )\n\n        callback.handleOnBackStarted(BackEventCompat(progress = 0.1F, swipeEdge = BackEventCompat.EDGE_LEFT, touchX = 1F, touchY = 2F))\n        callback.handleOnBackProgressed(BackEventCompat(progress = 0.2F, swipeEdge = BackEventCompat.EDGE_RIGHT, touchX = 2F, touchY = 3F))\n        callback.handleOnBackProgressed(BackEventCompat(progress = 0.3F, swipeEdge = BackEventCompat.EDGE_LEFT, touchX = 3F, touchY = 4F))\n        callback.handleOnBackPressed()\n\n        assertContentEquals(\n            listOf(\n                BackEvent(progress = 0.1F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 1F, touchY = 2F),\n                BackEvent(progress = 0.2F, swipeEdge = BackEvent.SwipeEdge.RIGHT, touchX = 2F, touchY = 3F),\n                BackEvent(progress = 0.3F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 3F, touchY = 4F),\n                \"Back\",\n            ),\n            receivedEvents,\n        )\n    }\n\n    @Test\n    fun WHEN_progress_with_cancel_THEN_forwards() {\n        val callback = dispatcher.connectOnBackPressedCallback()\n        val receivedEvents = ArrayList<Any?>()\n        dispatcher.register(\n            BackCallback(\n                onBackStarted = { receivedEvents += it },\n                onBackProgressed = { receivedEvents += it },\n                onBackCancelled = { receivedEvents += \"Cancel\" },\n                onBack = { receivedEvents += \"Back\" },\n            )\n        )\n\n        callback.handleOnBackStarted(BackEventCompat(progress = 0.1F, swipeEdge = BackEventCompat.EDGE_LEFT, touchX = 1F, touchY = 2F))\n        callback.handleOnBackProgressed(BackEventCompat(progress = 0.2F, swipeEdge = BackEventCompat.EDGE_RIGHT, touchX = 2F, touchY = 3F))\n        callback.handleOnBackProgressed(BackEventCompat(progress = 0.3F, swipeEdge = BackEventCompat.EDGE_LEFT, touchX = 3F, touchY = 4F))\n        callback.handleOnBackCancelled()\n\n        assertContentEquals(\n            listOf(\n                BackEvent(progress = 0.1F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 1F, touchY = 2F),\n                BackEvent(progress = 0.2F, swipeEdge = BackEvent.SwipeEdge.RIGHT, touchX = 2F, touchY = 3F),\n                BackEvent(progress = 0.3F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 3F, touchY = 4F),\n                \"Cancel\",\n            ),\n            receivedEvents,\n        )\n    }\n}\n"
  },
  {
    "path": "back-handler/src/commonMain/kotlin/com/arkivanov/essenty/backhandler/BackCallback.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\nimport kotlin.properties.Delegates\n\n/**\n * A callback for back button handling.\n *\n * @param isEnabled the initial enabled state of the callback.\n * @param priority determines the order of callback execution.\n * When calling, callbacks are sorted in ascending order first by priority and then by index,\n * the last enabled callback gets called.\n */\nabstract class BackCallback(\n    isEnabled: Boolean = true,\n    var priority: Int = PRIORITY_DEFAULT,\n) {\n    private var enabledListeners = emptySet<(Boolean) -> Unit>()\n\n    /**\n     * Controls the enabled state of the callback.\n     */\n    var isEnabled: Boolean by Delegates.observable(isEnabled) { _, _, newValue ->\n        enabledListeners.forEach { it(newValue) }\n    }\n\n    /**\n     * Registers the specified [listener] to be called when the enabled state of the callback changes.\n     */\n    fun addEnabledChangedListener(listener: (isEnabled: Boolean) -> Unit) {\n        this.enabledListeners += listener\n    }\n\n    /**\n     * Unregisters the specified [listener].\n     */\n    fun removeEnabledChangedListener(listener: (isEnabled: Boolean) -> Unit) {\n        this.enabledListeners -= listener\n    }\n\n    /**\n     * Called when the back button is pressed, or the predictive back gesture is finished.\n     */\n    abstract fun onBack()\n\n    /**\n     * Called when the predictive back gesture starts.\n     */\n    open fun onBackStarted(backEvent: BackEvent) {\n    }\n\n    /**\n     * Called on every progress of the predictive back gesture.\n     */\n    open fun onBackProgressed(backEvent: BackEvent) {\n    }\n\n    /**\n     * Called when the predictive back gesture is cancelled.\n     */\n    open fun onBackCancelled() {\n    }\n\n    companion object {\n        const val PRIORITY_DEFAULT: Int = 0\n        const val PRIORITY_MIN: Int = Int.MIN_VALUE\n        const val PRIORITY_MAX: Int = Int.MAX_VALUE\n    }\n}\n\nfun BackCallback(\n    isEnabled: Boolean = true,\n    priority: Int = 0,\n    onBackStarted: ((BackEvent) -> Unit)? = null,\n    onBackProgressed: ((BackEvent) -> Unit)? = null,\n    onBackCancelled: (() -> Unit)? = null,\n    onBack: () -> Unit,\n): BackCallback =\n    object : BackCallback(isEnabled = isEnabled, priority = priority) {\n        override fun onBackStarted(backEvent: BackEvent) {\n            onBackStarted?.invoke(backEvent)\n        }\n\n        override fun onBackProgressed(backEvent: BackEvent) {\n            onBackProgressed?.invoke(backEvent)\n        }\n\n        override fun onBackCancelled() {\n            onBackCancelled?.invoke()\n        }\n\n        override fun onBack() {\n            onBack.invoke()\n        }\n    }\n"
  },
  {
    "path": "back-handler/src/commonMain/kotlin/com/arkivanov/essenty/backhandler/BackDispatcher.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\nimport kotlin.js.JsName\n\n/**\n * Provides a way to manually trigger back button handlers.\n */\ninterface BackDispatcher : BackHandler {\n\n    /**\n     * Returns `true` if there is at least one enabled handler, `false` otherwise.\n     */\n    val isEnabled: Boolean\n\n    /**\n     * Adds the provided [listener], which will be called every time the enabled state of\n     * this [BackDispatcher] changes.\n     */\n    fun addEnabledChangedListener(listener: (isEnabled: Boolean) -> Unit)\n\n    /**\n     * Removes the provided enabled state changed [listener].\n     */\n    fun removeEnabledChangedListener(listener: (isEnabled: Boolean) -> Unit)\n\n    /**\n     * If no predictive back gesture is currently in progress, finds the last enabled\n     * callback with the highest priority and calls [BackCallback.onBack].\n     *\n     * If the predictive back gesture is currently in progress, calls [BackCallback.onBack] on\n     * the previously selected callback.\n     *\n     * @return `true` if any callback was triggered, `false` otherwise.\n     */\n    fun back(): Boolean\n\n    /**\n     * Starts handling the predictive back gesture. Picks one of the enabled callback (if any)\n     * that will be handling the gesture and calls [BackCallback.onBackStarted].\n     *\n     * @return `true` if any callback was triggered, `false` otherwise.\n     */\n    fun startPredictiveBack(backEvent: BackEvent): Boolean\n\n    /**\n     * Calls [BackCallback.onBackProgressed] on the previously selected callback.\n     */\n    fun progressPredictiveBack(backEvent: BackEvent)\n\n    /**\n     * Calls [BackCallback.onBackCancelled] on the previously selected callback.\n     */\n    fun cancelPredictiveBack()\n}\n\n/**\n * Creates and returns a default implementation of [BackDispatcher].\n */\n@JsName(\"backDispatcher\")\nfun BackDispatcher(): BackDispatcher =\n    DefaultBackDispatcher()\n"
  },
  {
    "path": "back-handler/src/commonMain/kotlin/com/arkivanov/essenty/backhandler/BackEvent.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\n/**\n * Represents an event of the predictive back gesture.\n *\n * @param progress progress factor of the back gesture, must be between 0 and 1.\n * @param swipeEdge Indicates which edge the gesture is being performed from.\n * @param touchX absolute X location of the touch point of this event.\n * @param touchY absolute Y location of the touch point of this event.\n */\ndata class BackEvent(\n    val progress: Float = 0F,\n    val swipeEdge: SwipeEdge = SwipeEdge.UNKNOWN,\n    val touchX: Float = 0F,\n    val touchY: Float = 0F,\n) {\n\n    init {\n        require(progress in 0F..1F) { \"The 'progress' argument must be between 0 and 1 (both inclusive)\" }\n    }\n\n    enum class SwipeEdge {\n        UNKNOWN,\n        LEFT,\n        RIGHT,\n    }\n}\n"
  },
  {
    "path": "back-handler/src/commonMain/kotlin/com/arkivanov/essenty/backhandler/BackHandler.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\n/**\n * A handler for back button presses.\n */\ninterface BackHandler {\n\n    /**\n     * Checks whether the provided [BackCallback] is registered or not.\n     */\n    fun isRegistered(callback: BackCallback): Boolean\n\n    /**\n     * Registers the specified [callback] to be called when the back button is invoked.\n     */\n    fun register(callback: BackCallback)\n\n    /**\n     * Unregisters the specified [callback].\n     */\n    fun unregister(callback: BackCallback)\n}\n"
  },
  {
    "path": "back-handler/src/commonMain/kotlin/com/arkivanov/essenty/backhandler/BackHandlerOwner.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\n/**\n * Represents a holder of [BackHandler]. It may be implemented by an arbitrary class, to provide convenient API.\n */\ninterface BackHandlerOwner {\n\n    val backHandler: BackHandler\n}\n"
  },
  {
    "path": "back-handler/src/commonMain/kotlin/com/arkivanov/essenty/backhandler/DefaultBackDispatcher.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\ninternal class DefaultBackDispatcher : BackDispatcher {\n\n    private var set = emptySet<BackCallback>()\n    private var progressData: ProgressData? = null\n    override val isEnabled: Boolean get() = set.any(BackCallback::isEnabled)\n    private var enabledChangedListeners = emptySet<(Boolean) -> Unit>()\n    private var hasEnabledCallback: Boolean = false\n    private val onCallbackEnabledChanged: (Boolean) -> Unit = { onCallbackEnabledChanged() }\n\n    private fun onCallbackEnabledChanged() {\n        val hasEnabledCallback = isEnabled\n        if (this.hasEnabledCallback != hasEnabledCallback) {\n            this.hasEnabledCallback = hasEnabledCallback\n            enabledChangedListeners.forEach { it.invoke(hasEnabledCallback) }\n        }\n    }\n\n    override fun isRegistered(callback: BackCallback): Boolean =\n        callback in set\n\n    override fun register(callback: BackCallback) {\n        check(callback !in set) { \"Callback is already registered\" }\n\n        this.set += callback\n        callback.addEnabledChangedListener(onCallbackEnabledChanged)\n        onCallbackEnabledChanged()\n    }\n\n    override fun unregister(callback: BackCallback) {\n        check(callback in set) { \"Callback is not registered\" }\n\n        this.set -= callback\n        callback.removeEnabledChangedListener(onCallbackEnabledChanged)\n\n        if (callback == progressData?.callback) {\n            progressData?.callback = null\n            callback.onBackCancelled()\n        }\n\n        onCallbackEnabledChanged()\n    }\n\n    override fun addEnabledChangedListener(listener: (isEnabled: Boolean) -> Unit) {\n        enabledChangedListeners += listener\n    }\n\n    override fun removeEnabledChangedListener(listener: (isEnabled: Boolean) -> Unit) {\n        enabledChangedListeners -= listener\n    }\n\n    override fun back(): Boolean {\n        val callback = progressData?.callback ?: set.findMostImportant()\n        progressData = null\n        callback?.onBack()\n\n        return callback != null\n    }\n\n    override fun startPredictiveBack(backEvent: BackEvent): Boolean {\n        val callback = set.findMostImportant() ?: return false\n        progressData = ProgressData(startEvent = backEvent, callback = callback)\n        callback.onBackStarted(backEvent)\n\n        return true\n    }\n\n    override fun progressPredictiveBack(backEvent: BackEvent) {\n        val progressData = progressData ?: return\n\n        if (progressData.callback == null) {\n            progressData.callback = set.findMostImportant()\n            progressData.callback?.onBackStarted(progressData.startEvent)\n        }\n\n        progressData.callback?.onBackProgressed(backEvent)\n    }\n\n    override fun cancelPredictiveBack() {\n        progressData?.callback?.onBackCancelled()\n        progressData = null\n    }\n\n    private class ProgressData(\n        val startEvent: BackEvent,\n        var callback: BackCallback?,\n    )\n}\n"
  },
  {
    "path": "back-handler/src/commonMain/kotlin/com/arkivanov/essenty/backhandler/Utils.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\ninternal fun Iterable<BackCallback>.findMostImportant(): BackCallback? =\n    sortedBy(BackCallback::priority).lastOrNull(BackCallback::isEnabled)\n"
  },
  {
    "path": "back-handler/src/commonTest/kotlin/com/arkivanov/essenty/backhandler/DefaultBackDispatcherTest.kt",
    "content": "package com.arkivanov.essenty.backhandler\n\nimport kotlin.test.Test\nimport kotlin.test.assertContentEquals\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass DefaultBackDispatcherTest {\n\n    private val dispatcher = DefaultBackDispatcher()\n\n    @Test\n    fun WHEN_created_THEN_disabled() {\n        assertFalse(dispatcher.isEnabled)\n    }\n\n    @Test\n    fun WHEN_enabled_callback_registered_THEN_enabled() {\n        dispatcher.register(callback(isEnabled = true))\n\n        assertTrue(dispatcher.isEnabled)\n    }\n\n    @Test\n    fun WHEN_two_enabled_callbacks_registered_THEN_enabled() {\n        dispatcher.register(callback(isEnabled = true))\n        dispatcher.register(callback(isEnabled = true))\n\n        assertTrue(dispatcher.isEnabled)\n    }\n\n    @Test\n    fun WHEN_two_callbacks_registered_one_disabled_THEN_enabled() {\n        dispatcher.register(callback(isEnabled = false))\n        dispatcher.register(callback(isEnabled = true))\n\n        assertTrue(dispatcher.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_two_enabled_callbacks_registered_WHEN_one_callback_disabled_THEN_enabled() {\n        val callback1 = callback(isEnabled = true)\n        dispatcher.register(callback1)\n        dispatcher.register(callback(isEnabled = true))\n\n        callback1.isEnabled = false\n\n        assertTrue(dispatcher.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_two_enabled_callbacks_registered_WHEN_all_callbacks_disabled_THEN_disabled() {\n        val callback1 = callback(isEnabled = true)\n        val callback2 = callback(isEnabled = true)\n        dispatcher.register(callback1)\n        dispatcher.register(callback2)\n\n        callback1.isEnabled = false\n        callback2.isEnabled = false\n\n        assertFalse(dispatcher.isEnabled)\n    }\n\n    @Test\n    fun WHEN_two_disabled_callbacks_registered_THEN_disabled() {\n        dispatcher.register(callback(isEnabled = false))\n        dispatcher.register(callback(isEnabled = false))\n\n        assertFalse(dispatcher.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_enabled_callback_registered_WHEN_callback_unregistered_THEN_disabled() {\n        val callback = callback(isEnabled = true)\n        dispatcher.register(callback)\n\n        dispatcher.unregister(callback)\n\n        assertFalse(dispatcher.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_two_enabled_callbacks_registered_WHEN_one_callback_unregistered_THEN_enabled() {\n        val callback1 = callback(isEnabled = true)\n        dispatcher.register(callback1)\n        dispatcher.register(callback(isEnabled = true))\n\n        dispatcher.unregister(callback1)\n\n        assertTrue(dispatcher.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_two_enabled_callbacks_registered_WHEN_all_callback_unregistered_THEN_disabled() {\n        val callback1 = callback(isEnabled = true)\n        val callback2 = callback(isEnabled = true)\n        dispatcher.register(callback1)\n        dispatcher.register(callback2)\n\n        dispatcher.unregister(callback1)\n        dispatcher.unregister(callback2)\n\n        assertFalse(dispatcher.isEnabled)\n    }\n\n    @Test\n    fun GIVEN_enabled_callbacks_registered_WHEN_back_THEN_last_callback_called() {\n        val list = ArrayList<Int>()\n        dispatcher.register(callback(isEnabled = true) { list += 1 })\n        dispatcher.register(callback(isEnabled = true) { list += 2 })\n\n        dispatcher.back()\n\n        assertContentEquals(listOf(2), list)\n    }\n\n    @Test\n    fun GIVEN_enabled_callbacks_registered_with_priorities_WHEN_back_THEN_last_callback_with_higher_priority_called() {\n        val list = ArrayList<Int>()\n        dispatcher.register(callback(isEnabled = true, priority = 0) { list += 1 })\n        dispatcher.register(callback(isEnabled = true, priority = 1) { list += 2 })\n        dispatcher.register(callback(isEnabled = true, priority = 2) { list += 3 })\n        dispatcher.register(callback(isEnabled = true, priority = 1) { list += 4 })\n        dispatcher.register(callback(isEnabled = true, priority = 2) { list += 5 })\n        dispatcher.register(callback(isEnabled = true, priority = 0) { list += 6 })\n        dispatcher.register(callback(isEnabled = true, priority = 1) { list += 7 })\n        dispatcher.register(callback(isEnabled = true, priority = 0) { list += 8 })\n\n        dispatcher.back()\n\n        assertContentEquals(listOf(5), list)\n    }\n\n    @Test\n    fun GIVEN_enabled_callbacks_registered_with_priorities_WHEN_priority_changed_and_back_THEN_last_callback_with_higher_priority_called() {\n        val list = ArrayList<Int>()\n        dispatcher.register(callback(isEnabled = true, priority = 0) { list += 1 })\n        val callback = callback(isEnabled = true, priority = 1) { list += 2 }\n        dispatcher.register(callback)\n        dispatcher.register(callback(isEnabled = true, priority = 2) { list += 3 })\n\n        callback.priority = 3\n        dispatcher.back()\n\n        assertContentEquals(listOf(2), list)\n    }\n\n    @Test\n    fun GIVEN_callbacks_not_registered_WHEN_back_THEN_returned_false() {\n        val result = dispatcher.back()\n\n        assertFalse(result)\n    }\n\n    @Test\n    fun GIVEN_enabled_callback_registered_WHEN_back_THEN_returned_true() {\n        dispatcher.register(callback(isEnabled = true))\n\n        val result = dispatcher.back()\n\n        assertTrue(result)\n    }\n\n    @Test\n    fun GIVEN_enabled_callbacks_registered_and_then_some_disabled_WHEN_back_THEN_last_enabled_callback_called() {\n        val list = ArrayList<Int>()\n        val callback2 = callback(isEnabled = true) { list += 2 }\n        val callback4 = callback(isEnabled = true) { list += 4 }\n        dispatcher.register(callback(isEnabled = true) { list += 1 })\n        dispatcher.register(callback2)\n        dispatcher.register(callback(isEnabled = true) { list += 3 })\n        dispatcher.register(callback4)\n        callback2.isEnabled = false\n        callback4.isEnabled = false\n\n        dispatcher.back()\n\n        assertContentEquals(listOf(3), list)\n    }\n\n    @Test\n    fun GIVEN_some_disabled_callbacks_registered_WHEN_back_THEN_returned_true() {\n        val callback2 = callback(isEnabled = true)\n        val callback4 = callback(isEnabled = true)\n        dispatcher.register(callback(isEnabled = true))\n        dispatcher.register(callback2)\n        dispatcher.register(callback(isEnabled = true))\n        dispatcher.register(callback4)\n        callback2.isEnabled = false\n        callback4.isEnabled = false\n\n        val result = dispatcher.back()\n\n        assertTrue(result)\n    }\n\n    @Test\n    fun GIVEN_some_disabled_callbacks_registered_WHEN_back_THEN_last_enabled_callback_called() {\n        val list = ArrayList<Int>()\n        dispatcher.register(callback(isEnabled = true) { list += 1 })\n        dispatcher.register(callback(isEnabled = false) { list += 2 })\n        dispatcher.register(callback(isEnabled = true) { list += 3 })\n        dispatcher.register(callback(isEnabled = false) { list += 4 })\n\n        dispatcher.back()\n\n        assertContentEquals(listOf(3), list)\n    }\n\n    @Test\n    fun GIVEN_callbacks_registered_and_some_disabled_WHEN_back_THEN_returned_true() {\n        dispatcher.register(callback(isEnabled = true))\n        dispatcher.register(callback(isEnabled = false))\n        dispatcher.register(callback(isEnabled = true))\n        dispatcher.register(callback(isEnabled = false))\n\n        val result = dispatcher.back()\n\n        assertTrue(result)\n    }\n\n    @Test\n    fun GIVEN_enabled_callbacks_registered_and_then_all_disabled_WHEN_back_THEN_returned_false() {\n        val callback1 = callback(isEnabled = true)\n        val callback2 = callback(isEnabled = true)\n        dispatcher.register(callback1)\n        dispatcher.register(callback2)\n        callback1.isEnabled = false\n        callback2.isEnabled = false\n\n        val result = dispatcher.back()\n\n        assertFalse(result)\n    }\n\n    @Test\n    fun GIVEN_disabled_callbacks_registered_WHEN_back_THEN_returned_false() {\n        dispatcher.register(callback = callback(isEnabled = false))\n        dispatcher.register(callback = callback(isEnabled = false))\n\n        val result = dispatcher.back()\n\n        assertFalse(result)\n    }\n\n    @Test\n    fun GIVEN_callback_not_registered_WHEN_startPredictiveBack_THEN_returns_false() {\n        val result = dispatcher.startPredictiveBack(BackEvent())\n\n        assertFalse(result)\n    }\n\n    @Test\n    fun GIVEN_disabled_callback_registered_WHEN_startPredictiveBack_THEN_returns_false() {\n        dispatcher.register(callback = callback(isEnabled = false))\n\n        val result = dispatcher.startPredictiveBack(BackEvent())\n\n        assertFalse(result)\n    }\n\n    @Test\n    fun GIVEN_enabled_callback_registered_WHEN_startPredictiveBack_THEN_returns_true() {\n        dispatcher.register(callback = callback(isEnabled = true))\n\n        val result = dispatcher.startPredictiveBack(BackEvent())\n\n        assertTrue(result)\n    }\n\n    @Test\n    fun WHEN_progress_with_back_THEN_callbacks_called() {\n        val startEvent = BackEvent(progress = 0.1F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 1F, touchY = 2F)\n        val progressEvent1 = BackEvent(progress = 0.2F, swipeEdge = BackEvent.SwipeEdge.RIGHT, touchX = 2F, touchY = 3F)\n        val progressEvent2 = BackEvent(progress = 0.3F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 3F, touchY = 4F)\n        val callback = LoggingCallback()\n        dispatcher.register(callback)\n\n        dispatcher.startPredictiveBack(startEvent)\n        dispatcher.progressPredictiveBack(progressEvent1)\n        dispatcher.progressPredictiveBack(progressEvent2)\n        dispatcher.back()\n\n        callback.assertEvents(\n            \"start\" to startEvent,\n            \"progress\" to progressEvent1,\n            \"progress\" to progressEvent2,\n            \"back\" to null,\n        )\n    }\n\n    @Test\n    fun WHEN_progress_with_cancel_THEN_callbacks_called() {\n        val startEvent = BackEvent(progress = 0.1F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 1F, touchY = 2F)\n        val progressEvent1 = BackEvent(progress = 0.2F, swipeEdge = BackEvent.SwipeEdge.RIGHT, touchX = 2F, touchY = 3F)\n        val progressEvent2 = BackEvent(progress = 0.3F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 3F, touchY = 4F)\n        val callback = LoggingCallback()\n        dispatcher.register(callback)\n\n        dispatcher.startPredictiveBack(startEvent)\n        dispatcher.progressPredictiveBack(progressEvent1)\n        dispatcher.progressPredictiveBack(progressEvent2)\n        dispatcher.cancelPredictiveBack()\n\n        callback.assertEvents(\n            \"start\" to startEvent,\n            \"progress\" to progressEvent1,\n            \"progress\" to progressEvent2,\n            \"cancel\" to null,\n        )\n    }\n\n    @Test\n    fun GIVEN_callback_registered_and_gesture_started_WHEN_unregister_THEN_callback_cancelled() {\n        val callback = LoggingCallback()\n        dispatcher.register(callback)\n        dispatcher.startPredictiveBack(BackEvent())\n        callback.clear()\n\n        dispatcher.unregister(callback)\n\n        callback.assertEvents(\"cancel\" to null)\n    }\n\n    @Test\n    fun GIVEN_two_callbacks_registered_and_gesture_started_and_progress_callback_unregistered_WHEN_progress_THEN_another_callback_started_and_progressed() {\n        val callback1 = LoggingCallback()\n        val callback2 = LoggingCallback()\n        dispatcher.register(callback1)\n        dispatcher.register(callback2)\n        dispatcher.startPredictiveBack(BackEvent(progress = 0F))\n        dispatcher.progressPredictiveBack(BackEvent(progress = 0.1F))\n        dispatcher.unregister(callback2)\n\n        dispatcher.progressPredictiveBack(BackEvent(progress = 0.2F))\n\n        callback1.assertEvents(\"start\" to BackEvent(progress = 0F), \"progress\" to BackEvent(progress = 0.2F))\n    }\n\n    @Test\n    fun GIVEN_two_callbacks_registered_and_gesture_started_and_progress_callback_unregistered_WHEN_back_THEN_another_callback_back() {\n        val callback1 = LoggingCallback()\n        val callback2 = LoggingCallback()\n        dispatcher.register(callback1)\n        dispatcher.register(callback2)\n        dispatcher.startPredictiveBack(BackEvent(progress = 0F))\n        dispatcher.progressPredictiveBack(BackEvent(progress = 0.1F))\n        dispatcher.unregister(callback2)\n\n        dispatcher.back()\n\n        callback1.assertEvents(\"back\" to null)\n    }\n\n    @Test\n    fun GIVEN_two_callbacks_registered_and_gesture_started_and_progress_callback_unregistered_WHEN_cancel_THEN_another_callback_not_called() {\n        val callback1 = LoggingCallback()\n        val callback2 = LoggingCallback()\n        dispatcher.register(callback1)\n        dispatcher.register(callback2)\n        dispatcher.startPredictiveBack(BackEvent(progress = 0F))\n        dispatcher.progressPredictiveBack(BackEvent(progress = 0.1F))\n        dispatcher.unregister(callback2)\n\n        dispatcher.cancelPredictiveBack()\n\n        callback1.assertEvents()\n    }\n\n    @Test\n    fun WHEN_another_callback_registered_while_in_progress_THEN_old_callback_called() {\n        val startEvent = BackEvent(progress = 0.1F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 1F, touchY = 2F)\n        val progressEvent1 = BackEvent(progress = 0.2F, swipeEdge = BackEvent.SwipeEdge.RIGHT, touchX = 2F, touchY = 3F)\n        val progressEvent2 = BackEvent(progress = 0.3F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 3F, touchY = 4F)\n        val callback = LoggingCallback()\n        dispatcher.register(callback)\n\n        dispatcher.startPredictiveBack(startEvent)\n        dispatcher.progressPredictiveBack(progressEvent1)\n        dispatcher.register(LoggingCallback())\n        dispatcher.progressPredictiveBack(progressEvent2)\n        dispatcher.cancelPredictiveBack()\n\n        callback.assertEvents(\n            \"start\" to startEvent,\n            \"progress\" to progressEvent1,\n            \"progress\" to progressEvent2,\n            \"cancel\" to null,\n        )\n    }\n\n    @Test\n    fun WHEN_another_callback_registered_while_in_progress_THEN_new_callback_not_called() {\n        val startEvent = BackEvent(progress = 0.1F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 1F, touchY = 2F)\n        val progressEvent1 = BackEvent(progress = 0.2F, swipeEdge = BackEvent.SwipeEdge.RIGHT, touchX = 2F, touchY = 3F)\n        val progressEvent2 = BackEvent(progress = 0.3F, swipeEdge = BackEvent.SwipeEdge.LEFT, touchX = 3F, touchY = 4F)\n        val callback = LoggingCallback()\n        dispatcher.register(LoggingCallback())\n\n        dispatcher.startPredictiveBack(startEvent)\n        dispatcher.progressPredictiveBack(progressEvent1)\n        dispatcher.register(callback)\n        dispatcher.progressPredictiveBack(progressEvent2)\n        dispatcher.cancelPredictiveBack()\n\n        callback.assertEvents()\n    }\n\n    @Test\n    fun GIVEN_EnabledChanged_listener_added_WHEN_enabled_callback_registered_THEN_listener_called_with_true() {\n        val events = ArrayList<Boolean>()\n        dispatcher.addEnabledChangedListener { events += it }\n\n        dispatcher.register(callback(isEnabled = true, onBack = {}))\n\n        assertContentEquals(listOf(true), events)\n    }\n\n    @Test\n    fun GIVEN_EnabledChanged_listener_added_WHEN_disabled_callback_registered_THEN_listener_not_called() {\n        val events = ArrayList<Boolean>()\n        dispatcher.addEnabledChangedListener { events += it }\n\n        dispatcher.register(callback(isEnabled = false, onBack = {}))\n\n        assertContentEquals(emptyList(), events)\n    }\n\n    @Test\n    fun GIVEN_enabled_callback_registered_and_EnabledChanged_listener_added_WHEN_callback_unregistered_THEN_listener_called_with_false() {\n        val events = ArrayList<Boolean>()\n        val callback = callback(isEnabled = true, onBack = {})\n        dispatcher.register(callback)\n        dispatcher.addEnabledChangedListener { events += it }\n\n        dispatcher.unregister(callback)\n\n        assertContentEquals(listOf(false), events)\n    }\n\n    @Test\n    fun GIVEN_disabled_callback_registered_and_EnabledChanged_listener_added_WHEN_callback_unregistered_THEN_listener_not_called() {\n        val events = ArrayList<Boolean>()\n        val callback = callback(isEnabled = false, onBack = {})\n        dispatcher.register(callback)\n        dispatcher.addEnabledChangedListener { events += it }\n\n        dispatcher.unregister(callback)\n\n        assertContentEquals(emptyList(), events)\n    }\n\n    @Test\n    fun GIVEN_disabled_callback_registered_and_EnabledChanged_listener_added_WHEN_callback_enabled_THEN_listener_called_with_true() {\n        val events = ArrayList<Boolean>()\n        val callback = callback(isEnabled = false, onBack = {})\n        dispatcher.register(callback)\n        dispatcher.addEnabledChangedListener { events += it }\n\n        callback.isEnabled = true\n\n        assertContentEquals(listOf(true), events)\n    }\n\n    @Test\n    fun GIVEN_enabled_callback_registered_and_EnabledChanged_listener_added_WHEN_callback_disabled_THEN_listener_called_with_false() {\n        val events = ArrayList<Boolean>()\n        val callback = callback(isEnabled = true, onBack = {})\n        dispatcher.register(callback)\n        dispatcher.addEnabledChangedListener { events += it }\n\n        callback.isEnabled = false\n\n        assertContentEquals(listOf(false), events)\n    }\n\n    @Test\n    fun GIVEN_two_disabled_callback_registered_and_EnabledChanged_listener_added_WHEN_one_callback_enabled_THEN_listener_called_with_true() {\n        val events = ArrayList<Boolean>()\n        val callback1 = callback(isEnabled = false, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(callback(isEnabled = false, onBack = {}))\n        dispatcher.addEnabledChangedListener { events += it }\n\n        callback1.isEnabled = true\n\n        assertContentEquals(listOf(true), events)\n    }\n\n    @Test\n    fun GIVEN_two_enabled_callback_registered_and_EnabledChanged_listener_added_WHEN_one_callback_disabled_THEN_listener_not_called() {\n        val events = ArrayList<Boolean>()\n        val callback1 = callback(isEnabled = true, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(callback(isEnabled = true, onBack = {}))\n        dispatcher.addEnabledChangedListener { events += it }\n\n        callback1.isEnabled = false\n\n        assertContentEquals(emptyList(), events)\n    }\n\n    @Test\n    fun GIVEN_one_disabled_and_one_enabled_callback_registered_and_EnabledChanged_listener_added_WHEN_callback_enabled_THEN_listener_not_called() {\n        val events = ArrayList<Boolean>()\n        val callback1 = callback(isEnabled = false, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n        dispatcher.addEnabledChangedListener { events += it }\n\n        callback1.isEnabled = true\n\n        assertContentEquals(emptyList(), events)\n    }\n\n    @Test\n    fun GIVEN_one_disabled_and_one_enabled_callback_registered_and_EnabledChanged_listener_added_WHEN_callback_disabled_THEN_listener_called_with_false() {\n        val events = ArrayList<Boolean>()\n        val callback1 = callback(isEnabled = true, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(BackCallback(isEnabled = false, onBack = {}))\n        dispatcher.addEnabledChangedListener { events += it }\n\n        callback1.isEnabled = false\n\n        assertContentEquals(listOf(false), events)\n    }\n\n    @Test\n    fun GIVEN_one_disabled_and_one_enabled_callback_registered_and_EnabledChanged_listener_added_WHEN_enabled_callback_unregistered_THEN_listener_called_with_false() {\n        val events = ArrayList<Boolean>()\n        val callback1 = callback(isEnabled = true, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(BackCallback(isEnabled = false, onBack = {}))\n        dispatcher.addEnabledChangedListener { events += it }\n\n        dispatcher.unregister(callback1)\n\n        assertContentEquals(listOf(false), events)\n    }\n\n    @Test\n    fun GIVEN_one_disabled_and_one_enabled_callback_registered_and_EnabledChanged_listener_added_WHEN_disabled_callback_unregistered_THEN_listener_not_called() {\n        val events = ArrayList<Boolean>()\n        val callback1 = callback(isEnabled = false, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n        dispatcher.addEnabledChangedListener { events += it }\n\n        dispatcher.unregister(callback1)\n\n        assertContentEquals(emptyList(), events)\n    }\n\n    @Test\n    fun GIVEN_EnabledChanged_listener_added_and_disabled_callback_registered_WHEN_callback_enabled_THEN_listener_called_with_true() {\n        val events = ArrayList<Boolean>()\n        dispatcher.addEnabledChangedListener { events += it }\n        val callback = callback(isEnabled = false, onBack = {})\n        dispatcher.register(callback)\n        events.clear()\n\n        callback.isEnabled = true\n\n        assertContentEquals(listOf(true), events)\n    }\n\n    @Test\n    fun GIVEN_EnabledChanged_listener_added_and_enabled_callback_registered_WHEN_callback_disabled_THEN_listener_called_with_false() {\n        val events = ArrayList<Boolean>()\n        dispatcher.addEnabledChangedListener { events += it }\n        val callback = callback(isEnabled = true, onBack = {})\n        dispatcher.register(callback)\n        events.clear()\n\n        callback.isEnabled = false\n\n        assertContentEquals(listOf(false), events)\n    }\n\n    @Test\n    fun GIVEN_EnabledChanged_listener_added_and_two_disabled_callback_registered_WHEN_one_callback_enabled_THEN_listener_called_with_true() {\n        val events = ArrayList<Boolean>()\n        dispatcher.addEnabledChangedListener { events += it }\n        val callback1 = callback(isEnabled = false, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(callback(isEnabled = false, onBack = {}))\n        events.clear()\n\n        callback1.isEnabled = true\n\n        assertContentEquals(listOf(true), events)\n    }\n\n    @Test\n    fun GIVEN_EnabledChanged_listener_added_and_two_enabled_callback_registered_WHEN_one_callback_disabled_THEN_listener_not_called() {\n        val events = ArrayList<Boolean>()\n        dispatcher.addEnabledChangedListener { events += it }\n        val callback1 = callback(isEnabled = true, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(callback(isEnabled = true, onBack = {}))\n        events.clear()\n\n        callback1.isEnabled = false\n\n        assertContentEquals(emptyList(), events)\n    }\n\n    @Test\n    fun GIVEN_EnabledChanged_listener_added_and_one_disabled_and_one_enabled_callback_registered_WHEN_callback_enabled_THEN_listener_not_called() {\n        val events = ArrayList<Boolean>()\n        dispatcher.addEnabledChangedListener { events += it }\n        val callback1 = callback(isEnabled = false, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n        events.clear()\n\n        callback1.isEnabled = true\n\n        assertContentEquals(emptyList(), events)\n    }\n\n    @Test\n    fun GIVEN_EnabledChanged_listener_added_and_one_disabled_and_one_enabled_callback_registered_WHEN_callback_disabled_THEN_listener_called_with_false() {\n        val events = ArrayList<Boolean>()\n        dispatcher.addEnabledChangedListener { events += it }\n        val callback1 = callback(isEnabled = true, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(BackCallback(isEnabled = false, onBack = {}))\n        events.clear()\n\n        callback1.isEnabled = false\n\n        assertContentEquals(listOf(false), events)\n    }\n\n    @Test\n    fun GIVEN_EnabledChanged_listener_added_and_one_disabled_and_one_enabled_callback_registered_WHEN_enabled_callback_unregistered_THEN_listener_called_with_false() {\n        val events = ArrayList<Boolean>()\n        dispatcher.addEnabledChangedListener { events += it }\n        val callback1 = callback(isEnabled = true, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(BackCallback(isEnabled = false, onBack = {}))\n        events.clear()\n\n        dispatcher.unregister(callback1)\n\n        assertContentEquals(listOf(false), events)\n    }\n\n    @Test\n    fun GIVEN_EnabledChanged_listener_added_and_one_disabled_and_one_enabled_callback_registered_WHEN_disabled_callback_unregistered_THEN_listener_not_called() {\n        val events = ArrayList<Boolean>()\n        dispatcher.addEnabledChangedListener { events += it }\n        val callback1 = callback(isEnabled = false, onBack = {})\n        dispatcher.register(callback1)\n        dispatcher.register(BackCallback(isEnabled = true, onBack = {}))\n        events.clear()\n\n        dispatcher.unregister(callback1)\n\n        assertContentEquals(emptyList(), events)\n    }\n\n    @Test\n    fun GIVEN_callback_not_registered_WHEN_isRegistered_THEN_returns_false() {\n        val isRegistered = dispatcher.isRegistered(callback())\n\n        assertFalse(isRegistered)\n    }\n\n    @Test\n    fun GIVEN_callback_registered_WHEN_isRegistered_for_another_callback_THEN_returns_false() {\n        dispatcher.register(callback())\n\n        val isRegistered = dispatcher.isRegistered(callback())\n\n        assertFalse(isRegistered)\n    }\n\n    @Test\n    fun GIVEN_callback_registered_WHEN_isRegistered_for_same_callback_THEN_returns_true() {\n        val callback = callback()\n        dispatcher.register(callback)\n\n        val isRegistered = dispatcher.isRegistered(callback)\n\n        assertTrue(isRegistered)\n    }\n\n    private fun callback(\n        isEnabled: Boolean = true,\n        priority: Int = 0,\n        onBack: () -> Unit = {},\n    ): BackCallback =\n        BackCallback(isEnabled = isEnabled, priority = priority, onBack = onBack)\n\n    private class LoggingCallback : BackCallback() {\n        private val events: MutableList<Pair<String, BackEvent?>> = ArrayList()\n\n        override fun onBackStarted(backEvent: BackEvent) {\n            events += \"start\" to backEvent\n        }\n\n        override fun onBackProgressed(backEvent: BackEvent) {\n            events += \"progress\" to backEvent\n        }\n\n        override fun onBack() {\n            events += \"back\" to null\n        }\n\n        override fun onBackCancelled() {\n            events += \"cancel\" to null\n        }\n\n        fun clear() {\n            events.clear()\n        }\n\n        fun assertEvents(vararg events: Pair<String, BackEvent?>) {\n            assertContentEquals(events.toList(), this.events)\n        }\n    }\n}\n"
  },
  {
    "path": "build.gradle.kts",
    "content": "import com.arkivanov.gradle.AndroidConfig\nimport com.arkivanov.gradle.BinaryCompatibilityValidatorConfig\nimport com.arkivanov.gradle.PublicationConfig\nimport com.arkivanov.gradle.ensureUnreachableTasksDisabled\nimport com.arkivanov.gradle.iosCompat\nimport com.arkivanov.gradle.macosCompat\nimport com.arkivanov.gradle.setupDefaults\nimport com.arkivanov.gradle.setupDetekt\nimport com.arkivanov.gradle.tvosCompat\nimport com.arkivanov.gradle.watchosCompat\nimport org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension\n\n// Top-level build file where you can add configuration options common to all sub-projects/modules.\nbuildscript {\n    repositories {\n        gradlePluginPortal()\n        mavenCentral()\n        google()\n        maven(\"https://maven.pkg.jetbrains.space/public/p/compose/dev\")\n    }\n\n    dependencies {\n        classpath(deps.kotlin.kotlinGradlePlug)\n        classpath(deps.android.gradle)\n        classpath(deps.kotlinx.binaryCompatibilityValidator)\n        classpath(deps.detekt.gradleDetektPlug)\n        classpath(deps.jetbrains.kotlin.serializationGradlePlug)\n    }\n}\n\nplugins {\n    id(\"com.arkivanov.gradle.setup\")\n}\n\nsetupDefaults(\n    multiplatformConfigurator = {\n        androidTarget()\n        jvm()\n        js {\n            browser()\n            nodejs()\n        }\n        wasmJs {\n            browser()\n        }\n        linuxX64()\n        iosCompat()\n        watchosCompat()\n        tvosCompat()\n        macosCompat()\n    },\n    androidConfig = AndroidConfig(\n        minSdkVersion = 15,\n        compileSdkVersion = 34,\n        targetSdkVersion = 34,\n    ),\n    publicationConfig = PublicationConfig(\n        group = \"com.arkivanov.essenty\",\n        version = deps.versions.essenty.get(),\n        projectName = \"Essenty\",\n        projectDescription = \"Essential libraries for Kotlin Multiplatform\",\n        projectUrl = \"https://github.com/arkivanov/Essenty\",\n        scmUrl = \"scm:git:git://github.com/arkivanov/Essenty.git\",\n        licenseName = \"The Apache License, Version 2.0\",\n        licenseUrl = \"http://www.apache.org/licenses/LICENSE-2.0.txt\",\n        developerId = \"arkivanov\",\n        developerName = \"Arkadii Ivanov\",\n        developerEmail = \"arkann1985@gmail.com\",\n        signingKey = System.getenv(\"SIGNING_KEY\"),\n        signingPassword = System.getenv(\"SIGNING_PASSWORD\"),\n        repositoryUrl = \"https://s01.oss.sonatype.org/service/local/staging/deployByRepositoryId/${System.getenv(\"SONATYPE_REPOSITORY_ID\")}\",\n        repositoryUserName = System.getenv(\"SONATYPE_USER_NAME\"),\n        repositoryPassword = System.getenv(\"SONATYPE_PASSWORD\"),\n    ),\n    binaryCompatibilityValidatorConfig = BinaryCompatibilityValidatorConfig(klib = true),\n)\n\nsetupDetekt()\nensureUnreachableTasksDisabled()\n\nallprojects {\n    repositories {\n        mavenCentral()\n        google()\n    }\n\n    afterEvaluate {\n        extensions.findByType<KotlinMultiplatformExtension>()?.apply {\n            sourceSets {\n                all {\n                    languageSettings.optIn(\"com.arkivanov.essenty.utils.internal.InternalEssentyApi\")\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "deps.versions.toml",
    "content": "[versions]\n\nessenty = \"2.5.0\"\nkotlin = \"2.1.0\"\nkotlinxBinaryCompatibilityValidator = \"0.16.3\"\nkotlinxCoroutines = \"1.9.0\"\ndetektGradlePlugin = \"1.23.6\"\njunit = \"4.13.2\"\nandroidGradle = \"8.0.2\"\nandroidxLifecycle = \"2.6.2\"\nandroidxSavedstate = \"1.2.1\"\nandroidxActivity = \"1.8.1\"\njetbrainsKotlinxSerialization = \"1.6.3\"\nrobolectric = \"4.9.1\"\nreaktive = \"2.1.0\"\n\n[libraries]\n\nkotlin-kotlinGradlePlug = { group = \"org.jetbrains.kotlin\", name = \"kotlin-gradle-plugin\", version.ref = \"kotlin\" }\nkotlinx-binaryCompatibilityValidator = { group = \"org.jetbrains.kotlinx\", name = \"binary-compatibility-validator\", version.ref = \"kotlinxBinaryCompatibilityValidator\" }\n\nkotlinx-coroutinesCore = { group = \"org.jetbrains.kotlinx\", name = \"kotlinx-coroutines-core\", version.ref = \"kotlinxCoroutines\" }\nkotlinx-coroutinesTest = { group = \"org.jetbrains.kotlinx\", name = \"kotlinx-coroutines-test\", version.ref = \"kotlinxCoroutines\" }\n\ndetekt-gradleDetektPlug = { group = \"io.gitlab.arturbosch.detekt\", name = \"detekt-gradle-plugin\", version.ref = \"detektGradlePlugin\" }\n\nandroid-gradle = { group = \"com.android.tools.build\", name = \"gradle\", version.ref = \"androidGradle\" }\n\nandroidx-lifecycle-lifecycleCommonJava8 = { group = \"androidx.lifecycle\", name = \"lifecycle-common-java8\", version.ref = \"androidxLifecycle\" }\nandroidx-lifecycle-lifecycleRuntime = { group = \"androidx.lifecycle\", name = \"lifecycle-runtime\", version.ref = \"androidxLifecycle\" }\nandroidx-lifecycle-lifecycleViewmodelKtx = { group = \"androidx.lifecycle\", name = \"lifecycle-viewmodel-ktx\", version.ref = \"androidxLifecycle\" }\nandroidx-savedstate-savedstateKtx = { group = \"androidx.savedstate\", name = \"savedstate-ktx\", version.ref = \"androidxSavedstate\" }\nandroidx-activity-activityKtx = { group = \"androidx.activity\", name = \"activity-ktx\", version.ref = \"androidxActivity\" }\n\njetbrains-kotlin-serializationGradlePlug = { group = \"org.jetbrains.kotlin\", name = \"kotlin-serialization\", version.ref = \"kotlin\" }\njetbrains-kotlinx-kotlinxSerializationCore = { group = \"org.jetbrains.kotlinx\", name = \"kotlinx-serialization-core\", version.ref = \"jetbrainsKotlinxSerialization\" }\njetbrains-kotlinx-kotlinxSerializationJson = { group = \"org.jetbrains.kotlinx\", name = \"kotlinx-serialization-json\", version.ref = \"jetbrainsKotlinxSerialization\" }\n\nrobolectric-robolectric = { group = \"org.robolectric\", name = \"robolectric\", version.ref = \"robolectric\" }\n\nreaktive-reaktive = { group = \"com.badoo.reaktive\", name = \"reaktive\", version.ref = \"reaktive\" }\n"
  },
  {
    "path": "detekt.yml",
    "content": "complexity:\n  CyclomaticComplexMethod:\n    threshold: 15\n    ignoreSingleWhenExpression: true\n    ignoreSimpleWhenEntries: true\n    ignoreNestingFunctions: false\n  CognitiveComplexMethod:\n    active: true\n    threshold: 15\n  LongParameterList:\n    active: false\n  TooManyFunctions:\n    active: false\n\nexceptions:\n  PrintStackTrace:\n    active: false\n  TooGenericExceptionCaught:\n    active: false\n\nnaming:\n  FunctionNaming:\n    excludes: ['**/test/**', '**/*Test/**']\n    ignoreAnnotated: [ 'Composable' ]\n  MemberNameEqualsClassName:\n    active: false\n\nstyle:\n  ForbiddenComment:\n    values: ['FIXME:', 'STOPSHIP:']\n  MagicNumber:\n    active: false\n  MaxLineLength:\n    maxLineLength: 140\n    excludes: ['**/test/**', '**/*Test/**']\n  ReturnCount:\n    active: false\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.0.2-all.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "kotlin.code.style=official\norg.gradle.jvmargs=-Xmx2g\norg.gradle.parallel=true\norg.gradle.caching=true\nsystemProp.org.gradle.internal.publish.checksums.insecure=true\nandroid.useAndroidX=true\nandroid.enableJetifier=true\nkotlin.mpp.androidSourceSetLayoutVersion=2\nkotlin.mpp.applyDefaultHierarchyTemplate=false\n\n# For compatibility with Kotlin 1.9.0\nandroid.experimental.lint.version=8.1.0\n"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\n@rem This is normally unused\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "instance-keeper/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "instance-keeper/api/android/instance-keeper.api",
    "content": "public final class com/arkivanov/essenty/instancekeeper/AndroidExtKt {\n\tpublic static final fun InstanceKeeper (Landroidx/lifecycle/ViewModelStore;Z)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;\n\tpublic static synthetic fun InstanceKeeper$default (Landroidx/lifecycle/ViewModelStore;ZILjava/lang/Object;)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;\n\tpublic static final fun instanceKeeper (Landroidx/lifecycle/ViewModelStoreOwner;Z)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;\n\tpublic static synthetic fun instanceKeeper$default (Landroidx/lifecycle/ViewModelStoreOwner;ZILjava/lang/Object;)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;\n}\n\npublic abstract interface annotation class com/arkivanov/essenty/instancekeeper/ExperimentalInstanceKeeperApi : java/lang/annotation/Annotation {\n}\n\npublic abstract interface class com/arkivanov/essenty/instancekeeper/InstanceKeeper {\n\tpublic abstract fun get (Ljava/lang/Object;)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;\n\tpublic abstract fun put (Ljava/lang/Object;Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;)V\n\tpublic abstract fun remove (Ljava/lang/Object;)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;\n}\n\npublic abstract interface class com/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance {\n\tpublic abstract fun onDestroy ()V\n}\n\npublic final class com/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance$DefaultImpls {\n\tpublic static fun onDestroy (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;)V\n}\n\npublic final class com/arkivanov/essenty/instancekeeper/InstanceKeeper$SimpleInstance : com/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance {\n\tpublic fun <init> (Ljava/lang/Object;)V\n\tpublic final fun getInstance ()Ljava/lang/Object;\n\tpublic fun onDestroy ()V\n}\n\npublic abstract interface class com/arkivanov/essenty/instancekeeper/InstanceKeeperDispatcher : com/arkivanov/essenty/instancekeeper/InstanceKeeper {\n\tpublic abstract fun destroy ()V\n}\n\npublic final class com/arkivanov/essenty/instancekeeper/InstanceKeeperDispatcherKt {\n\tpublic static final fun InstanceKeeperDispatcher ()Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperDispatcher;\n}\n\npublic final class com/arkivanov/essenty/instancekeeper/InstanceKeeperExtKt {\n\tpublic static final fun getOrCreate (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;\n\tpublic static final fun getOrCreateCloseable (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ljava/lang/AutoCloseable;\n\tpublic static final fun getOrCreateSimple (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;\n\tpublic static final fun retainedCloseable (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ljava/lang/AutoCloseable;\n\tpublic static final fun retainedInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;\n\tpublic static final fun retainedSimpleInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;\n\tpublic static final fun retainingCloseable (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun retainingCloseable (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingCloseable$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingCloseable$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun retainingInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun retainingInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingInstance$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingInstance$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun retainingSimpleInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun retainingSimpleInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingSimpleInstance$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingSimpleInstance$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n}\n\npublic abstract interface class com/arkivanov/essenty/instancekeeper/InstanceKeeperOwner {\n\tpublic abstract fun getInstanceKeeper ()Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;\n}\n\n"
  },
  {
    "path": "instance-keeper/api/instance-keeper.klib.api",
    "content": "// Klib ABI Dump\n// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxX64, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, watchosArm32, watchosArm64, watchosSimulatorArm64, watchosX64]\n// Rendering settings:\n// - Signature version: 2\n// - Show manifest properties: true\n// - Show declarations: true\n\n// Library unique name: <com.arkivanov.essenty:instance-keeper>\nopen annotation class com.arkivanov.essenty.instancekeeper/ExperimentalInstanceKeeperApi : kotlin/Annotation { // com.arkivanov.essenty.instancekeeper/ExperimentalInstanceKeeperApi|null[0]\n    constructor <init>() // com.arkivanov.essenty.instancekeeper/ExperimentalInstanceKeeperApi.<init>|<init>(){}[0]\n}\n\nabstract interface com.arkivanov.essenty.instancekeeper/InstanceKeeper { // com.arkivanov.essenty.instancekeeper/InstanceKeeper|null[0]\n    abstract fun get(kotlin/Any): com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance? // com.arkivanov.essenty.instancekeeper/InstanceKeeper.get|get(kotlin.Any){}[0]\n    abstract fun put(kotlin/Any, com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance) // com.arkivanov.essenty.instancekeeper/InstanceKeeper.put|put(kotlin.Any;com.arkivanov.essenty.instancekeeper.InstanceKeeper.Instance){}[0]\n    abstract fun remove(kotlin/Any): com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance? // com.arkivanov.essenty.instancekeeper/InstanceKeeper.remove|remove(kotlin.Any){}[0]\n\n    abstract interface Instance { // com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance|null[0]\n        open fun onDestroy() // com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance.onDestroy|onDestroy(){}[0]\n    }\n\n    final class <#A1: out kotlin/Any?> SimpleInstance : com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance { // com.arkivanov.essenty.instancekeeper/InstanceKeeper.SimpleInstance|null[0]\n        constructor <init>(#A1) // com.arkivanov.essenty.instancekeeper/InstanceKeeper.SimpleInstance.<init>|<init>(1:0){}[0]\n\n        final val instance // com.arkivanov.essenty.instancekeeper/InstanceKeeper.SimpleInstance.instance|{}instance[0]\n            final fun <get-instance>(): #A1 // com.arkivanov.essenty.instancekeeper/InstanceKeeper.SimpleInstance.instance.<get-instance>|<get-instance>(){}[0]\n    }\n}\n\nabstract interface com.arkivanov.essenty.instancekeeper/InstanceKeeperDispatcher : com.arkivanov.essenty.instancekeeper/InstanceKeeper { // com.arkivanov.essenty.instancekeeper/InstanceKeeperDispatcher|null[0]\n    abstract fun destroy() // com.arkivanov.essenty.instancekeeper/InstanceKeeperDispatcher.destroy|destroy(){}[0]\n}\n\nabstract interface com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner { // com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner|null[0]\n    abstract val instanceKeeper // com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner.instanceKeeper|{}instanceKeeper[0]\n        abstract fun <get-instanceKeeper>(): com.arkivanov.essenty.instancekeeper/InstanceKeeper // com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner.instanceKeeper.<get-instanceKeeper>|<get-instanceKeeper>(){}[0]\n}\n\nfinal fun com.arkivanov.essenty.instancekeeper/InstanceKeeperDispatcher(): com.arkivanov.essenty.instancekeeper/InstanceKeeperDispatcher // com.arkivanov.essenty.instancekeeper/InstanceKeeperDispatcher|InstanceKeeperDispatcher(){}[0]\nfinal inline fun <#A: com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance> (com.arkivanov.essenty.instancekeeper/InstanceKeeper).com.arkivanov.essenty.instancekeeper/getOrCreate(kotlin/Any, kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/getOrCreate|getOrCreate@com.arkivanov.essenty.instancekeeper.InstanceKeeper(kotlin.Any;kotlin.Function0<0:0>){0§<com.arkivanov.essenty.instancekeeper.InstanceKeeper.Instance>}[0]\nfinal inline fun <#A: com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance> (com.arkivanov.essenty.instancekeeper/InstanceKeeper).com.arkivanov.essenty.instancekeeper/retainingInstance(kotlin/Any? = ..., crossinline kotlin/Function0<#A>): kotlin.properties/PropertyDelegateProvider<kotlin/Any?, kotlin.properties/ReadOnlyProperty<kotlin/Any?, #A>> // com.arkivanov.essenty.instancekeeper/retainingInstance|retainingInstance@com.arkivanov.essenty.instancekeeper.InstanceKeeper(kotlin.Any?;kotlin.Function0<0:0>){0§<com.arkivanov.essenty.instancekeeper.InstanceKeeper.Instance>}[0]\nfinal inline fun <#A: com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance> (com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner).com.arkivanov.essenty.instancekeeper/retainedInstance(kotlin/Any, kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/retainedInstance|retainedInstance@com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner(kotlin.Any;kotlin.Function0<0:0>){0§<com.arkivanov.essenty.instancekeeper.InstanceKeeper.Instance>}[0]\nfinal inline fun <#A: com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance> (com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner).com.arkivanov.essenty.instancekeeper/retainingInstance(kotlin/Any? = ..., crossinline kotlin/Function0<#A>): kotlin.properties/PropertyDelegateProvider<kotlin/Any?, kotlin.properties/ReadOnlyProperty<kotlin/Any?, #A>> // com.arkivanov.essenty.instancekeeper/retainingInstance|retainingInstance@com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner(kotlin.Any?;kotlin.Function0<0:0>){0§<com.arkivanov.essenty.instancekeeper.InstanceKeeper.Instance>}[0]\nfinal inline fun <#A: kotlin/Any?> (com.arkivanov.essenty.instancekeeper/InstanceKeeper).com.arkivanov.essenty.instancekeeper/getOrCreateSimple(kotlin/Any, kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/getOrCreateSimple|getOrCreateSimple@com.arkivanov.essenty.instancekeeper.InstanceKeeper(kotlin.Any;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]\nfinal inline fun <#A: kotlin/Any?> (com.arkivanov.essenty.instancekeeper/InstanceKeeper).com.arkivanov.essenty.instancekeeper/retainingSimpleInstance(kotlin/Any? = ..., crossinline kotlin/Function0<#A>): kotlin.properties/PropertyDelegateProvider<kotlin/Any?, kotlin.properties/ReadOnlyProperty<kotlin/Any?, #A>> // com.arkivanov.essenty.instancekeeper/retainingSimpleInstance|retainingSimpleInstance@com.arkivanov.essenty.instancekeeper.InstanceKeeper(kotlin.Any?;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]\nfinal inline fun <#A: kotlin/Any?> (com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner).com.arkivanov.essenty.instancekeeper/retainedSimpleInstance(kotlin/Any, kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/retainedSimpleInstance|retainedSimpleInstance@com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner(kotlin.Any;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]\nfinal inline fun <#A: kotlin/Any?> (com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner).com.arkivanov.essenty.instancekeeper/retainingSimpleInstance(kotlin/Any? = ..., crossinline kotlin/Function0<#A>): kotlin.properties/PropertyDelegateProvider<kotlin/Any?, kotlin.properties/ReadOnlyProperty<kotlin/Any?, #A>> // com.arkivanov.essenty.instancekeeper/retainingSimpleInstance|retainingSimpleInstance@com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner(kotlin.Any?;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]\nfinal inline fun <#A: kotlin/AutoCloseable> (com.arkivanov.essenty.instancekeeper/InstanceKeeper).com.arkivanov.essenty.instancekeeper/getOrCreateCloseable(kotlin/Any, kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/getOrCreateCloseable|getOrCreateCloseable@com.arkivanov.essenty.instancekeeper.InstanceKeeper(kotlin.Any;kotlin.Function0<0:0>){0§<kotlin.AutoCloseable>}[0]\nfinal inline fun <#A: kotlin/AutoCloseable> (com.arkivanov.essenty.instancekeeper/InstanceKeeper).com.arkivanov.essenty.instancekeeper/retainingCloseable(kotlin/Any? = ..., crossinline kotlin/Function0<#A>): kotlin.properties/PropertyDelegateProvider<kotlin/Any?, kotlin.properties/ReadOnlyProperty<kotlin/Any?, #A>> // com.arkivanov.essenty.instancekeeper/retainingCloseable|retainingCloseable@com.arkivanov.essenty.instancekeeper.InstanceKeeper(kotlin.Any?;kotlin.Function0<0:0>){0§<kotlin.AutoCloseable>}[0]\nfinal inline fun <#A: kotlin/AutoCloseable> (com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner).com.arkivanov.essenty.instancekeeper/retainedCloseable(kotlin/Any, kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/retainedCloseable|retainedCloseable@com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner(kotlin.Any;kotlin.Function0<0:0>){0§<kotlin.AutoCloseable>}[0]\nfinal inline fun <#A: kotlin/AutoCloseable> (com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner).com.arkivanov.essenty.instancekeeper/retainingCloseable(kotlin/Any? = ..., crossinline kotlin/Function0<#A>): kotlin.properties/PropertyDelegateProvider<kotlin/Any?, kotlin.properties/ReadOnlyProperty<kotlin/Any?, #A>> // com.arkivanov.essenty.instancekeeper/retainingCloseable|retainingCloseable@com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner(kotlin.Any?;kotlin.Function0<0:0>){0§<kotlin.AutoCloseable>}[0]\nfinal inline fun <#A: reified com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance> (com.arkivanov.essenty.instancekeeper/InstanceKeeper).com.arkivanov.essenty.instancekeeper/getOrCreate(kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/getOrCreate|getOrCreate@com.arkivanov.essenty.instancekeeper.InstanceKeeper(kotlin.Function0<0:0>){0§<com.arkivanov.essenty.instancekeeper.InstanceKeeper.Instance>}[0]\nfinal inline fun <#A: reified com.arkivanov.essenty.instancekeeper/InstanceKeeper.Instance> (com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner).com.arkivanov.essenty.instancekeeper/retainedInstance(kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/retainedInstance|retainedInstance@com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner(kotlin.Function0<0:0>){0§<com.arkivanov.essenty.instancekeeper.InstanceKeeper.Instance>}[0]\nfinal inline fun <#A: reified kotlin/Any?> (com.arkivanov.essenty.instancekeeper/InstanceKeeper).com.arkivanov.essenty.instancekeeper/getOrCreateSimple(kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/getOrCreateSimple|getOrCreateSimple@com.arkivanov.essenty.instancekeeper.InstanceKeeper(kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]\nfinal inline fun <#A: reified kotlin/Any?> (com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner).com.arkivanov.essenty.instancekeeper/retainedSimpleInstance(kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/retainedSimpleInstance|retainedSimpleInstance@com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner(kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]\nfinal inline fun <#A: reified kotlin/AutoCloseable> (com.arkivanov.essenty.instancekeeper/InstanceKeeper).com.arkivanov.essenty.instancekeeper/getOrCreateCloseable(kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/getOrCreateCloseable|getOrCreateCloseable@com.arkivanov.essenty.instancekeeper.InstanceKeeper(kotlin.Function0<0:0>){0§<kotlin.AutoCloseable>}[0]\nfinal inline fun <#A: reified kotlin/AutoCloseable> (com.arkivanov.essenty.instancekeeper/InstanceKeeperOwner).com.arkivanov.essenty.instancekeeper/retainedCloseable(kotlin/Function0<#A>): #A // com.arkivanov.essenty.instancekeeper/retainedCloseable|retainedCloseable@com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner(kotlin.Function0<0:0>){0§<kotlin.AutoCloseable>}[0]\n"
  },
  {
    "path": "instance-keeper/api/jvm/instance-keeper.api",
    "content": "public abstract interface annotation class com/arkivanov/essenty/instancekeeper/ExperimentalInstanceKeeperApi : java/lang/annotation/Annotation {\n}\n\npublic abstract interface class com/arkivanov/essenty/instancekeeper/InstanceKeeper {\n\tpublic abstract fun get (Ljava/lang/Object;)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;\n\tpublic abstract fun put (Ljava/lang/Object;Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;)V\n\tpublic abstract fun remove (Ljava/lang/Object;)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;\n}\n\npublic abstract interface class com/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance {\n\tpublic abstract fun onDestroy ()V\n}\n\npublic final class com/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance$DefaultImpls {\n\tpublic static fun onDestroy (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;)V\n}\n\npublic final class com/arkivanov/essenty/instancekeeper/InstanceKeeper$SimpleInstance : com/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance {\n\tpublic fun <init> (Ljava/lang/Object;)V\n\tpublic final fun getInstance ()Ljava/lang/Object;\n\tpublic fun onDestroy ()V\n}\n\npublic abstract interface class com/arkivanov/essenty/instancekeeper/InstanceKeeperDispatcher : com/arkivanov/essenty/instancekeeper/InstanceKeeper {\n\tpublic abstract fun destroy ()V\n}\n\npublic final class com/arkivanov/essenty/instancekeeper/InstanceKeeperDispatcherKt {\n\tpublic static final fun InstanceKeeperDispatcher ()Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperDispatcher;\n}\n\npublic final class com/arkivanov/essenty/instancekeeper/InstanceKeeperExtKt {\n\tpublic static final fun getOrCreate (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;\n\tpublic static final fun getOrCreateCloseable (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ljava/lang/AutoCloseable;\n\tpublic static final fun getOrCreateSimple (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;\n\tpublic static final fun retainedCloseable (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ljava/lang/AutoCloseable;\n\tpublic static final fun retainedInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper$Instance;\n\tpublic static final fun retainedSimpleInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;\n\tpublic static final fun retainingCloseable (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun retainingCloseable (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingCloseable$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingCloseable$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun retainingInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun retainingInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingInstance$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingInstance$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun retainingSimpleInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun retainingSimpleInstance (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingSimpleInstance$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun retainingSimpleInstance$default (Lcom/arkivanov/essenty/instancekeeper/InstanceKeeperOwner;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n}\n\npublic abstract interface class com/arkivanov/essenty/instancekeeper/InstanceKeeperOwner {\n\tpublic abstract fun getInstanceKeeper ()Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;\n}\n\n"
  },
  {
    "path": "instance-keeper/build.gradle.kts",
    "content": "import com.arkivanov.gradle.bundle\nimport com.arkivanov.gradle.setupBinaryCompatibilityValidator\nimport com.arkivanov.gradle.setupMultiplatform\nimport com.arkivanov.gradle.setupPublication\nimport com.arkivanov.gradle.setupSourceSets\n\nplugins {\n    id(\"kotlin-multiplatform\")\n    id(\"com.android.library\")\n    id(\"com.arkivanov.gradle.setup\")\n}\n\nsetupMultiplatform()\nsetupPublication()\nsetupBinaryCompatibilityValidator()\n\nandroid {\n    namespace = \"com.arkivanov.essenty.instancekeeper\"\n}\n\nkotlin {\n    setupSourceSets {\n        val android by bundle()\n\n        common.main.dependencies {\n            implementation(project(\":utils-internal\"))\n        }\n\n        android.main.dependencies {\n            implementation(deps.androidx.lifecycle.lifecycleViewmodelKtx)\n        }\n    }\n}\n"
  },
  {
    "path": "instance-keeper/src/androidMain/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest/>\n"
  },
  {
    "path": "instance-keeper/src/androidMain/kotlin/com/arkivanov/essenty/instancekeeper/AndroidExt.kt",
    "content": "package com.arkivanov.essenty.instancekeeper\n\nimport androidx.lifecycle.ViewModel\nimport androidx.lifecycle.ViewModelProvider\nimport androidx.lifecycle.ViewModelStore\nimport androidx.lifecycle.ViewModelStoreOwner\nimport androidx.lifecycle.get\n\n/**\n * Creates a new instance of [InstanceKeeper] and attaches it to the provided AndroidX [ViewModelStore].\n *\n * @param discardRetainedInstances a flag indicating whether any previously retained instances should be\n * discarded and destroyed or not, default value is `false`.\n */\nfun InstanceKeeper(\n    viewModelStore: ViewModelStore,\n    discardRetainedInstances: Boolean = false,\n): InstanceKeeper =\n    ViewModelProvider(\n        viewModelStore,\n        object : ViewModelProvider.Factory {\n            @Suppress(\"UNCHECKED_CAST\")\n            override fun <T : ViewModel> create(modelClass: Class<T>): T = InstanceKeeperViewModel() as T\n        }\n    )\n        .get<InstanceKeeperViewModel>()\n        .apply {\n            if (discardRetainedInstances) {\n                recreate()\n            }\n        }\n        .instanceKeeperDispatcher\n\n/**\n * Creates a new instance of [InstanceKeeper] and attaches it to the AndroidX [ViewModelStore].\n *\n * @param discardRetainedInstances a flag indicating whether any previously retained instances should be\n * discarded and destroyed or not, default value is `false`.\n */\nfun ViewModelStoreOwner.instanceKeeper(discardRetainedInstances: Boolean = false): InstanceKeeper =\n    InstanceKeeper(viewModelStore = viewModelStore, discardRetainedInstances = discardRetainedInstances)\n\ninternal class InstanceKeeperViewModel : ViewModel() {\n    var instanceKeeperDispatcher: InstanceKeeperDispatcher = InstanceKeeperDispatcher()\n        private set\n\n    override fun onCleared() {\n        instanceKeeperDispatcher.destroy()\n    }\n\n    fun recreate() {\n        instanceKeeperDispatcher.destroy()\n        instanceKeeperDispatcher = InstanceKeeperDispatcher()\n    }\n}\n"
  },
  {
    "path": "instance-keeper/src/androidUnitTest/kotlin/com/arkivanov/essenty/instancekeeper/AndroidInstanceKeeperTest.kt",
    "content": "package com.arkivanov.essenty.instancekeeper\n\nimport androidx.lifecycle.ViewModelStore\nimport androidx.lifecycle.ViewModelStoreOwner\nimport kotlin.test.Test\nimport kotlin.test.assertNotSame\nimport kotlin.test.assertSame\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass AndroidInstanceKeeperTest {\n\n    @Test\n    fun retains_instances() {\n        val owner = TestOwner()\n        var instanceKeeper = owner.instanceKeeper()\n        val instance1 = instanceKeeper.getOrCreate(key = \"key\", factory = ::TestInstance)\n\n        instanceKeeper = owner.instanceKeeper()\n        val instance2 = instanceKeeper.getOrCreate(key = \"key\", factory = ::TestInstance)\n\n        assertSame(instance1, instance2)\n    }\n\n    @Test\n    fun GIVEN_discardRetainedInstances_is_true_on_restore_THEN_instances_not_retained() {\n        val owner = TestOwner()\n        var instanceKeeper = owner.instanceKeeper()\n        val instance1 = instanceKeeper.getOrCreate(key = \"key\", factory = ::TestInstance)\n\n        instanceKeeper = owner.instanceKeeper(discardRetainedInstances = true)\n        val instance2 = instanceKeeper.getOrCreate(key = \"key\", factory = ::TestInstance)\n\n        assertNotSame(instance1, instance2)\n    }\n\n    @Test\n    fun GIVEN_discardRetainedInstances_is_true_on_restore_THEN_old_instances_destroyed() {\n        val owner = TestOwner()\n        val instanceKeeper = owner.instanceKeeper()\n        val instance1 = instanceKeeper.getOrCreate(key = \"key\", factory = ::TestInstance)\n\n        owner.instanceKeeper(discardRetainedInstances = true)\n\n        assertTrue(instance1.isDestroyed)\n    }\n\n    private class TestOwner : ViewModelStoreOwner {\n        override val viewModelStore: ViewModelStore = ViewModelStore()\n    }\n\n    private class TestInstance : InstanceKeeper.Instance {\n        var isDestroyed: Boolean = false\n\n        override fun onDestroy() {\n            isDestroyed = true\n        }\n    }\n}\n"
  },
  {
    "path": "instance-keeper/src/commonMain/kotlin/com/arkivanov/essenty/instancekeeper/DefaultInstanceKeeperDispatcher.kt",
    "content": "package com.arkivanov.essenty.instancekeeper\n\nimport com.arkivanov.essenty.instancekeeper.InstanceKeeper.Instance\n\ninternal class DefaultInstanceKeeperDispatcher : InstanceKeeperDispatcher {\n\n    private val map = HashMap<Any, Instance>()\n    private var isDestroyed = false\n\n    override fun get(key: Any): Instance? =\n        map[key]\n\n    override fun put(key: Any, instance: Instance) {\n        check(key !in map) { \"Another instance is already associated with the key: $key\" }\n\n        map[key] = instance\n\n        if (isDestroyed) {\n            instance.onDestroy()\n        }\n    }\n\n    override fun remove(key: Any): Instance? =\n        map.remove(key)\n\n    override fun destroy() {\n        if (!isDestroyed) {\n            isDestroyed = true\n            map.values.toList().forEach(Instance::onDestroy)\n        }\n    }\n}\n"
  },
  {
    "path": "instance-keeper/src/commonMain/kotlin/com/arkivanov/essenty/instancekeeper/ExperimentalInstanceKeeperApi.kt",
    "content": "package com.arkivanov.essenty.instancekeeper\n\n/**\n * Marks experimental API in Essenty. An experimental API can be changed or removed at any time.\n */\n@RequiresOptIn(level = RequiresOptIn.Level.WARNING)\n@Retention(AnnotationRetention.BINARY)\n@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)\nannotation class ExperimentalInstanceKeeperApi\n"
  },
  {
    "path": "instance-keeper/src/commonMain/kotlin/com/arkivanov/essenty/instancekeeper/InstanceKeeper.kt",
    "content": "package com.arkivanov.essenty.instancekeeper\n\n/**\n * A generic keyed store of [Instance] objects. Instances are destroyed at the end of the\n * [InstanceKeeper]'s scope, which is typically tied to the scope of a back stack entry.\n * E.g. instances are retained over Android configuration changes, and destroyed when the\n * corresponding back stack entry is popped.\n */\ninterface InstanceKeeper {\n\n    /**\n     * Returns an instance with the given [key], or `null` if no instance with the given key exists.\n     */\n    fun get(key: Any): Instance?\n\n    /**\n     * Stores the given [instance] with the given [key]. Throws [IllegalStateException] if another\n     * instance is already registered with the given [key].\n     */\n    fun put(key: Any, instance: Instance)\n\n    /**\n     * Removes an instance with the given [key]. This does not destroy the instance.\n     */\n    fun remove(key: Any): Instance?\n\n    /**\n     * Represents a destroyable instance.\n     */\n    interface Instance {\n\n        /**\n         * Called at the end of the [InstanceKeeper]'s scope.\n         */\n        fun onDestroy() {}\n    }\n\n    /**\n     * Are simple [Instance] wrapper for cases when destroying is not required.\n     */\n    class SimpleInstance<out T>(val instance: T) : Instance\n}\n"
  },
  {
    "path": "instance-keeper/src/commonMain/kotlin/com/arkivanov/essenty/instancekeeper/InstanceKeeperDispatcher.kt",
    "content": "package com.arkivanov.essenty.instancekeeper\n\nimport kotlin.js.JsName\n\n/**\n * Represents a destroyable [InstanceKeeper].\n */\ninterface InstanceKeeperDispatcher : InstanceKeeper {\n\n    /**\n     * Destroys all existing instances. Instances are not cleared, so that they can be\n     * accessed later. Any new instances will be immediately destroyed.\n     */\n    fun destroy()\n}\n\n/**\n * Creates a default implementation of [InstanceKeeperDispatcher].\n */\n@JsName(\"instanceKeeperDispatcher\")\nfun InstanceKeeperDispatcher(): InstanceKeeperDispatcher = DefaultInstanceKeeperDispatcher()\n"
  },
  {
    "path": "instance-keeper/src/commonMain/kotlin/com/arkivanov/essenty/instancekeeper/InstanceKeeperExt.kt",
    "content": "package com.arkivanov.essenty.instancekeeper\n\nimport com.arkivanov.essenty.instancekeeper.InstanceKeeper.SimpleInstance\nimport kotlin.properties.PropertyDelegateProvider\nimport kotlin.properties.ReadOnlyProperty\nimport kotlin.reflect.typeOf\n\n/**\n * Returns a previously stored [InstanceKeeper.Instance] of type [T] with the given key,\n * or creates and stores a new one if it doesn't exist.\n */\ninline fun <T : InstanceKeeper.Instance> InstanceKeeper.getOrCreate(key: Any, factory: () -> T): T {\n    @Suppress(\"UNCHECKED_CAST\") // Assuming the type per key is always the same\n    var instance: T? = get(key) as T?\n    if (instance == null) {\n        instance = factory()\n        put(key, instance)\n    }\n\n    return instance\n}\n\n/**\n * Returns a previously stored [InstanceKeeper.Instance] of type [T],\n * or creates and stores a new one if it doesn't exist. Uses `typeOf<T>()` as key.\n *\n * Deprecated. Using `getOrCreate` without the `key` parameter may crash when [T]\n * refers to a type with type (generic) parameters (e.g. a `StateFlow>`) and R8 Full Mode enabled.\n * See [KT-42913](https://youtrack.jetbrains.com/issue/KT-42913) for more information.\n */\n@Deprecated(\n    message = \"Using getOrCreate without the key parameter is unsafe. Please use the other variant.\",\n    replaceWith = ReplaceWith(\n        expression = \"getOrCreate(key = , factory = factory)\",\n    )\n)\ninline fun <reified T : InstanceKeeper.Instance> InstanceKeeper.getOrCreate(factory: () -> T): T =\n    getOrCreate(key = typeOf<T>(), factory = factory)\n\n/**\n * Returns a previously stored [AutoCloseable] instance of type [T] with the given [key],\n * or creates and stores a new one if it doesn't exist.\n *\n * @param key a key to store and retrieve the instance.\n * @param factory a function creating a new instance of type [T].\n */\ninline fun <T : AutoCloseable> InstanceKeeper.getOrCreateCloseable(key: Any, factory: () -> T): T =\n    getOrCreate(key = key) {\n        val instance = factory()\n\n        object : InstanceKeeper.Instance {\n            val instance: T = instance\n\n            override fun onDestroy() {\n                instance.close()\n            }\n        }\n    }.instance\n\n/**\n * Returns a previously stored [AutoCloseable] instance of type [T],\n * or creates and stores a new one if it doesn't exist. Uses `typeOf<T>()` as key.\n *\n * Deprecated. Using `getOrCreateCloseable` without the `key` parameter may crash when [T]\n * refers to a type with type (generic) parameters (e.g. a `StateFlow>`) and R8 Full Mode enabled.\n * See [KT-42913](https://youtrack.jetbrains.com/issue/KT-42913) for more information.\n *\n * @param factory a function creating a new instance of type [T].\n */\n@Deprecated(\n    message = \"Using getOrCreateCloseable without the key parameter is unsafe. Please use the other variant.\",\n    replaceWith = ReplaceWith(\n        expression = \"getOrCreateCloseable(key = , factory = factory)\",\n    )\n)\ninline fun <reified T : AutoCloseable> InstanceKeeper.getOrCreateCloseable(factory: () -> T): T =\n    getOrCreateCloseable(key = typeOf<T>(), factory = factory)\n\n/**\n * A convenience function for [InstanceKeeper.getOrCreate].\n */\ninline fun <T : InstanceKeeper.Instance> InstanceKeeperOwner.retainedInstance(key: Any, factory: () -> T): T =\n    instanceKeeper.getOrCreate(key = key, factory = factory)\n\n/**\n * A convenience function for [InstanceKeeper.getOrCreate].\n *\n * Deprecated. Using `retainedInstance` without the `key` parameter may crash when [T]\n * refers to a type with type (generic) parameters (e.g. a `StateFlow>`) and R8 Full Mode enabled.\n * See [KT-42913](https://youtrack.jetbrains.com/issue/KT-42913) for more information.\n */\n@Deprecated(\n    message = \"Using retainedInstance without the key parameter is unsafe. Please use the other variant.\",\n    replaceWith = ReplaceWith(\n        expression = \"retainedInstance(key = , factory = factory)\",\n    )\n)\ninline fun <reified T : InstanceKeeper.Instance> InstanceKeeperOwner.retainedInstance(factory: () -> T): T =\n    instanceKeeper.getOrCreate(key = typeOf<T>(), factory = factory)\n\n/**\n * A convenience function for [InstanceKeeper.getOrCreateCloseable].\n */\ninline fun <T : AutoCloseable> InstanceKeeperOwner.retainedCloseable(key: Any, factory: () -> T): T =\n    instanceKeeper.getOrCreateCloseable(key = key, factory = factory)\n\n/**\n * A convenience function for [InstanceKeeper.getOrCreateCloseable].\n *\n * Deprecated. Using `retainedCloseable` without the `key` parameter may crash when [T]\n * refers to a type with type (generic) parameters (e.g. a `StateFlow>`) and R8 Full Mode enabled.\n * See [KT-42913](https://youtrack.jetbrains.com/issue/KT-42913) for more information.\n */\n@Deprecated(\n    message = \"Using retainedCloseable without the key parameter is unsafe. Please use the other variant.\",\n    replaceWith = ReplaceWith(\n        expression = \"retainedCloseable(key = , factory = factory)\",\n    )\n)\ninline fun <reified T : AutoCloseable> InstanceKeeperOwner.retainedCloseable(factory: () -> T): T =\n    instanceKeeper.getOrCreateCloseable(key = typeOf<T>(), factory = factory)\n\n/**\n * Returns a previously stored instance of type [T] with the given key,\n * or creates and stores a new one if it doesn't exist.\n *\n * This overload is for simple cases when instance destroying is not required.\n */\ninline fun <T> InstanceKeeper.getOrCreateSimple(key: Any, factory: () -> T): T =\n    getOrCreate(key = key) { SimpleInstance(factory()) }\n        .instance\n\n/**\n * Returns a previously stored instance of type [T],\n * or creates and stores a new one if it doesn't exist. Uses `typeOf<T>()` as key.\n *\n * This overload is for simple cases when instance destroying is not required.\n *\n * Deprecated. Using `getOrCreateSimple` without the `key` parameter may crash when [T]\n * refers to a type with type (generic) parameters (e.g. a `StateFlow>`) and R8 Full Mode enabled.\n * See [KT-42913](https://youtrack.jetbrains.com/issue/KT-42913) for more information.\n */\n@Deprecated(\n    message = \"Using getOrCreateSimple without the key parameter is unsafe. Please use the other variant.\",\n    replaceWith = ReplaceWith(\n        expression = \"getOrCreateSimple(key = , factory = factory)\",\n    )\n)\ninline fun <reified T> InstanceKeeper.getOrCreateSimple(factory: () -> T): T =\n    getOrCreateSimple(key = typeOf<T>(), factory = factory)\n\n/**\n * A convenience function for [InstanceKeeper.getOrCreateSimple].\n */\ninline fun <T> InstanceKeeperOwner.retainedSimpleInstance(key: Any, factory: () -> T): T =\n    instanceKeeper.getOrCreateSimple(key = key, factory = factory)\n\n/**\n * A convenience function for [InstanceKeeper.getOrCreateSimple].\n *\n * Deprecated. Using `retainedSimpleInstance` without the `key` parameter may crash when [T]\n * refers to a type with type (generic) parameters (e.g. a `StateFlow>`) and R8 Full Mode enabled.\n * See [KT-42913](https://youtrack.jetbrains.com/issue/KT-42913) for more information.\n */\n@Deprecated(\n    message = \"Using retainedSimpleInstance without the key parameter is unsafe. Please use the other variant.\",\n    replaceWith = ReplaceWith(\n        expression = \"retainedSimpleInstance(key = , factory = factory)\",\n    )\n)\ninline fun <reified T> InstanceKeeperOwner.retainedSimpleInstance(factory: () -> T): T =\n    instanceKeeper.getOrCreateSimple(key = typeOf<T>(), factory = factory)\n\n/**\n * Helper function for creating a\n * [delegated property]((https://kotlinlang.org/docs/delegated-properties.html)) whose value is\n * automatically retained using [InstanceKeeper].\n *\n * Example:\n *\n * ```\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeper\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner\n * import com.arkivanov.essenty.instancekeeper.retainingInstance\n *\n * class SomeLogic(override val instanceKeeper: InstanceKeeper) : InstanceKeeperOwner {\n *     private val viewModel by retainingInstance { RetainedViewModel() }\n *\n *     private class RetainedViewModel : InstanceKeeper.Instance {\n *         // ...\n *     }\n * }\n * ```\n *\n * @param key an optional key for storing and retrieving the instance. If not provided, then the\n * property name is used as a key.\n * @param factory a function creating a new instance of type [T].\n * @param T a type of the property, extends [InstanceKeeper.Instance].\n * @return [PropertyDelegateProvider] of type [T], typically used to define a delegated property.\n * @see getOrCreate\n */\n@ExperimentalInstanceKeeperApi\ninline fun <T : InstanceKeeper.Instance> InstanceKeeper.retainingInstance(\n    key: Any? = null,\n    crossinline factory: () -> T,\n): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>> =\n    PropertyDelegateProvider { _, property ->\n        val instance = getOrCreate(key = key ?: \"RETAINING_INSTANCE_${property.name}\", factory = factory)\n        ReadOnlyProperty { _, _ -> instance }\n    }\n\n/**\n * Helper function for creating a\n * [delegated property]((https://kotlinlang.org/docs/delegated-properties.html)) whose value is\n * automatically retained using [InstanceKeeper].\n *\n * Example:\n *\n * ```\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeper\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner\n * import com.arkivanov.essenty.instancekeeper.retainingInstance\n *\n * class SomeLogic(override val instanceKeeper: InstanceKeeper) : InstanceKeeperOwner {\n *     private val viewModel by retainingInstance { RetainedViewModel() }\n *\n *     private class RetainedViewModel : InstanceKeeper.Instance {\n *         // ...\n *     }\n * }\n * ```\n *\n * @param key an optional key for storing and retrieving the instance. If not provided, then the\n * property name is used as a key.\n * @param factory a function creating a new instance of type [T].\n * @param T a type of the property, extends [InstanceKeeper.Instance].\n * @return [PropertyDelegateProvider] of type [T], typically used to define a delegated property.\n * @see getOrCreate\n */\n@ExperimentalInstanceKeeperApi\ninline fun <T : InstanceKeeper.Instance> InstanceKeeperOwner.retainingInstance(\n    key: Any? = null,\n    crossinline factory: () -> T,\n): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>> =\n    instanceKeeper.retainingInstance(key = key, factory = factory)\n\n/**\n * Helper function for creating a\n * [delegated property]((https://kotlinlang.org/docs/delegated-properties.html)) whose value is\n * automatically retained using [InstanceKeeper].\n *\n * This overload is for simple cases when instance destroying is not required.\n *\n * Example:\n *\n * ```\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeper\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner\n * import com.arkivanov.essenty.instancekeeper.retainingSimpleInstance\n *\n * class SomeLogic(override val instanceKeeper: InstanceKeeper) : InstanceKeeperOwner {\n *     private val viewModel by retainingSimpleInstance { RetainedClass() }\n *\n *     private class RetainedClass {\n *         // ...\n *     }\n * }\n * ```\n *\n * @param key an optional key for storing and retrieving the instance. If not provided, then the\n * property name is used as a key.\n * @param factory a function creating a new instance of type [T].\n * @param T a type of the property.\n * @return [PropertyDelegateProvider] of type [T], typically used to define a delegated property.\n * @see getOrCreateSimple\n */\n@ExperimentalInstanceKeeperApi\ninline fun <T> InstanceKeeper.retainingSimpleInstance(\n    key: Any? = null,\n    crossinline factory: () -> T,\n): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>> =\n    PropertyDelegateProvider { _, property ->\n        val instance = getOrCreateSimple(key = key ?: \"RETAINING_SIMPLE_INSTANCE_${property.name}\", factory = factory)\n        ReadOnlyProperty { _, _ -> instance }\n    }\n\n/**\n * Helper function for creating a\n * [delegated property]((https://kotlinlang.org/docs/delegated-properties.html)) whose value is\n * automatically retained using [InstanceKeeper].\n *\n * This overload is for simple cases when instance destroying is not required.\n *\n * Example:\n *\n * ```\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeper\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner\n * import com.arkivanov.essenty.instancekeeper.retainingSimpleInstance\n *\n * class SomeLogic(override val instanceKeeper: InstanceKeeper) : InstanceKeeperOwner {\n *     private val viewModel by retainingSimpleInstance { RetainedClass() }\n *\n *     private class RetainedClass {\n *         // ...\n *     }\n * }\n * ```\n *\n * @param key an optional key for storing and retrieving the instance. If not provided, then the\n * property name is used as a key.\n * @param factory a function creating a new instance of type [T].\n * @param T a type of the property.\n * @return [PropertyDelegateProvider] of type [T], typically used to define a delegated property.\n * @see getOrCreateSimple\n */\n@ExperimentalInstanceKeeperApi\ninline fun <T> InstanceKeeperOwner.retainingSimpleInstance(\n    key: Any? = null,\n    crossinline factory: () -> T,\n): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>> =\n    instanceKeeper.retainingSimpleInstance(key = key, factory = factory)\n\n/**\n * Helper function for creating a\n * [delegated property]((https://kotlinlang.org/docs/delegated-properties.html)) whose value is\n * automatically retained using [InstanceKeeper].\n *\n * This overload is for simple cases when instance destroying is not required.\n *\n * Example:\n *\n * ```\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeper\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner\n * import com.arkivanov.essenty.instancekeeper.retainingSimpleInstance\n *\n * class SomeLogic(override val instanceKeeper: InstanceKeeper) : InstanceKeeperOwner {\n *     private val viewModel by retainingSimpleInstance { RetainedViewModel() }\n *\n *     private class RetainedViewModel : AutoCloseable {\n *         // ...\n *     }\n * }\n * ```\n *\n * @param key an optional key for storing and retrieving the instance. If not provided, then the\n * property name is used as a key.\n * @param factory a function creating a new instance of type [T].\n * @param T a type of the property, extends [AutoCloseable].\n * @return [PropertyDelegateProvider] of type [T], typically used to define a delegated property.\n * @see getOrCreateCloseable\n */\n@ExperimentalInstanceKeeperApi\ninline fun <T : AutoCloseable> InstanceKeeper.retainingCloseable(\n    key: Any? = null,\n    crossinline factory: () -> T,\n): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>> =\n    PropertyDelegateProvider { _, property ->\n        val instance = getOrCreateCloseable(key = key ?: \"RETAINING_CLOSEABLE_${property.name}\", factory = factory)\n        ReadOnlyProperty { _, _ -> instance }\n    }\n\n/**\n * Helper function for creating a\n * [delegated property]((https://kotlinlang.org/docs/delegated-properties.html)) whose value is\n * automatically retained using [InstanceKeeper].\n *\n * This overload is for simple cases when instance destroying is not required.\n *\n * Example:\n *\n * ```\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeper\n * import com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner\n * import com.arkivanov.essenty.instancekeeper.retainingSimpleInstance\n *\n * class SomeLogic(override val instanceKeeper: InstanceKeeper) : InstanceKeeperOwner {\n *     private val viewModel by retainingSimpleInstance { RetainedViewModel() }\n *\n *     private class RetainedViewModel : AutoCloseable {\n *         // ...\n *     }\n * }\n * ```\n *\n * @param key an optional key for storing and retrieving the instance. If not provided, then the\n * property name is used as a key.\n * @param factory a function creating a new instance of type [T].\n * @param T a type of the property, extends [AutoCloseable].\n * @return [PropertyDelegateProvider] of type [T], typically used to define a delegated property.\n * @see getOrCreateCloseable\n */\n@ExperimentalInstanceKeeperApi\ninline fun <T : AutoCloseable> InstanceKeeperOwner.retainingCloseable(\n    key: Any? = null,\n    crossinline factory: () -> T,\n): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>> =\n    instanceKeeper.retainingCloseable(key = key, factory = factory)\n"
  },
  {
    "path": "instance-keeper/src/commonMain/kotlin/com/arkivanov/essenty/instancekeeper/InstanceKeeperOwner.kt",
    "content": "package com.arkivanov.essenty.instancekeeper\n\n/**\n * Represents a holder of [InstanceKeeper].\n */\ninterface InstanceKeeperOwner {\n\n    val instanceKeeper: InstanceKeeper\n}\n"
  },
  {
    "path": "instance-keeper/src/commonTest/kotlin/com/arkivanov/essenty/instancekeeper/DefaultInstanceKeeperDispatcherTest.kt",
    "content": "package com.arkivanov.essenty.instancekeeper\n\nimport kotlin.test.Test\nimport kotlin.test.assertFails\nimport kotlin.test.assertFalse\nimport kotlin.test.assertNull\nimport kotlin.test.assertSame\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass DefaultInstanceKeeperDispatcherTest {\n\n    @Test\n    fun GIVEN_no_instance_put_WHEN_get_THEN_returns_null() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        dispatcher.put(key = \"key1\", instance = TestInstance())\n\n        val returnedInstance = dispatcher.get(key = \"key2\")\n\n        assertNull(returnedInstance)\n    }\n\n    @Test\n    fun GIVEN_instance_put_WHEN_get_THEN_returns_instance() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        val instance1 = TestInstance()\n        val instance2 = TestInstance()\n        dispatcher.put(key = \"key1\", instance = instance1)\n        dispatcher.put(key = \"key2\", instance = instance2)\n\n        val returnedInstance1 = dispatcher.get(key = \"key1\")\n        val returnedInstance2 = dispatcher.get(key = \"key2\")\n\n        assertSame(instance1, returnedInstance1)\n        assertSame(instance2, returnedInstance2)\n    }\n\n    @Test\n    fun GIVEN_instance_put_WHEN_put_with_same_key_THEN_throws_exception() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        dispatcher.put(key = \"key\", instance = TestInstance())\n\n        assertFails {\n            dispatcher.put(key = \"key\", instance = TestInstance())\n        }\n    }\n\n    @Test\n    fun GIVEN_instance_with_same_key_put_twice_WHEN_get_THEN_returns_original_instance() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        val instance = TestInstance()\n        dispatcher.put(key = \"key\", instance = instance)\n        try {\n            dispatcher.put(key = \"key\", instance = TestInstance())\n        } catch (ignored: Exception) {\n        }\n\n        val returnedInstance = dispatcher.get(key = \"key\")\n\n        assertSame(instance, returnedInstance)\n    }\n\n    @Test\n    fun GIVEN_instances_put_WHEN_destroy_THEN_instances_destroyed() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        val instance1 = TestInstance()\n        val instance2 = TestInstance()\n        dispatcher.put(key = \"key1\", instance = instance1)\n        dispatcher.put(key = \"key2\", instance = instance2)\n\n        dispatcher.destroy()\n\n        assertTrue(instance1.isDestroyed)\n        assertTrue(instance2.isDestroyed)\n    }\n\n    @Test\n    fun GIVEN_instance_put_and_destroyed_WHEN_get_THEN_returns_instance() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        val instance = TestInstance()\n        dispatcher.put(key = \"key\", instance = instance)\n        dispatcher.destroy()\n\n        val returnedInstance = dispatcher.get(key = \"key\")\n\n        assertSame(instance, returnedInstance)\n    }\n\n    @Test\n    fun GIVEN_destroyed_WHEN_put_THEN_does_not_throw() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        val instance = TestInstance()\n        dispatcher.destroy()\n\n        dispatcher.put(key = \"key\", instance = instance)\n    }\n\n    @Test\n    fun GIVEN_destroyed_and_put_WHEN_get_THEN_returns_instance() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        val instance = TestInstance()\n        dispatcher.destroy()\n        dispatcher.put(key = \"key\", instance = instance)\n\n        val returnedInstance = dispatcher.get(key = \"key\")\n\n        assertSame(instance, returnedInstance)\n    }\n\n    @Test\n    fun GIVEN_not_empty_and_destroyed_WHEN_destroy_THEN_instance_is_not_destroyed_second_time() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        val instance = TestInstance()\n        dispatcher.put(key = \"key\", instance = instance)\n        dispatcher.destroy()\n        instance.isDestroyed = false\n\n        dispatcher.destroy()\n\n        assertFalse(instance.isDestroyed)\n    }\n\n    @Test\n    fun GEVEN_instance_not_put_WHEN_remove_THEN_returns_null() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n\n        val returnedInstance = dispatcher.remove(key = \"key\")\n\n        assertNull(returnedInstance)\n    }\n\n    @Test\n    fun GEVEN_instance_put_WHEN_remove_THEN_returns_instance() {\n        val instance = TestInstance()\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        dispatcher.put(\"key\", instance)\n\n        val returnedInstance = dispatcher.remove(key = \"key\")\n\n        assertSame(instance, returnedInstance)\n    }\n\n    @Test\n    fun GEVEN_instance_removed_WHEN_remove_THEN_returns_null() {\n        val instance = TestInstance()\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        dispatcher.put(\"key\", instance)\n        dispatcher.remove(\"key\")\n\n        val returnedInstance = dispatcher.remove(key = \"key\")\n\n        assertNull(returnedInstance)\n    }\n\n    @Test\n    fun GIVEN_instance_put_and_destroyed_WHEN_remove_THEN_returns_instance() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        val instance = TestInstance()\n        dispatcher.put(key = \"key\", instance = instance)\n        dispatcher.destroy()\n\n        val returnedInstance = dispatcher.remove(key = \"key\")\n\n        assertSame(instance, returnedInstance)\n    }\n\n    @Test\n    fun GIVEN_instance_put_and_destroyed_and_removed_WHEN_remove_THEN_returns_null() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        val instance = TestInstance()\n        dispatcher.put(key = \"key\", instance = instance)\n        dispatcher.destroy()\n        dispatcher.remove(key = \"key\")\n\n        val returnedInstance = dispatcher.remove(key = \"key\")\n\n        assertNull(returnedInstance)\n    }\n\n    @Test\n    fun GIVEN_instance_put_WHEN_destroy_and_instance_calls_get_in_onDestroy_THEN_returns_null() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        var returnedInstance: Any? = Any()\n        dispatcher.put(key = \"key\", instance = TestInstance(onDestroy = { returnedInstance = null }))\n\n        dispatcher.destroy()\n\n        assertNull(returnedInstance)\n    }\n\n    @Test\n    fun GIVEN_instances_put_WHEN_destroy_and_instance_calls_remove_in_onDestroy_THEN_does_not_throw() {\n        val dispatcher = DefaultInstanceKeeperDispatcher()\n        dispatcher.put(key = \"key1\", instance = TestInstance(onDestroy = { dispatcher.remove(key = \"key1\") }))\n        dispatcher.put(key = \"key2\", instance = TestInstance(onDestroy = { dispatcher.remove(key = \"key2\") }))\n\n        dispatcher.destroy()\n    }\n\n    private class TestInstance(\n        private val onDestroy: () -> Unit = {},\n    ) : InstanceKeeper.Instance {\n        var isDestroyed: Boolean = false\n\n        override fun onDestroy() {\n            isDestroyed = true\n            onDestroy.invoke()\n        }\n    }\n}\n"
  },
  {
    "path": "instance-keeper/src/commonTest/kotlin/com/arkivanov/essenty/instancekeeper/InstanceKeeperExtTest.kt",
    "content": "package com.arkivanov.essenty.instancekeeper\n\nimport kotlin.test.Test\nimport kotlin.test.assertNotSame\nimport kotlin.test.assertSame\n\n@Suppress(\"TestFunctionName\", \"DEPRECATION\")\n@OptIn(ExperimentalInstanceKeeperApi::class)\nclass InstanceKeeperExtTest {\n\n    private val dispatcher = InstanceKeeperDispatcher()\n\n    @Test\n    fun WHEN_getOrCreate_with_same_key_called_second_time_THEN_returns_same_instance() {\n        val thing1 = dispatcher.getOrCreate(key = \"key\") { ThingInstance<Int>() }\n        val thing2 = dispatcher.getOrCreate(key = \"key\") { ThingInstance<Int>() }\n\n        assertSame(thing1, thing2)\n    }\n\n    @Test\n    fun WHEN_getOrCreate_with_different_key_called_second_time_THEN_returns_new_instance() {\n        val thing1 = dispatcher.getOrCreate(key = \"key1\") { ThingInstance<Int>() }\n        val thing2 = dispatcher.getOrCreate(key = \"key2\") { ThingInstance<Int>() }\n\n        assertNotSame(thing1, thing2)\n    }\n\n    @Test\n    fun WHEN_getOrCreate_with_same_type_called_second_time_THEN_returns_same_instance() {\n        val thing1 = dispatcher.getOrCreate { ThingInstance<Int>() }\n        val thing2 = dispatcher.getOrCreate { ThingInstance<Int>() }\n\n        assertSame(thing1, thing2)\n    }\n\n    @Test\n    fun WHEN_getOrCreate_with_different_type_called_second_time_THEN_returns_new_instance() {\n        val thing1 = dispatcher.getOrCreate { ThingInstance<Int>() }\n        val thing2 = dispatcher.getOrCreate { ThingInstance<Float>() }\n\n        assertNotSame<ThingInstance<*>>(thing1, thing2)\n    }\n\n    @Test\n    fun WHEN_getOrCreateSimple_with_same_key_called_second_time_THEN_returns_same_instance() {\n        val thing1 = dispatcher.getOrCreateSimple(key = \"key\") { Thing<Int>() }\n        val thing2 = dispatcher.getOrCreateSimple(key = \"key\") { Thing<Int>() }\n\n        assertSame(thing1, thing2)\n    }\n\n    @Test\n    fun WHEN_getOrCreateSimple_with_different_key_called_second_time_THEN_returns_new_instance() {\n        val thing1 = dispatcher.getOrCreateSimple(key = \"key1\") { Thing<Int>() }\n        val thing2 = dispatcher.getOrCreateSimple(key = \"key2\") { Thing<Int>() }\n\n        assertNotSame(thing1, thing2)\n    }\n\n    @Test\n    fun WHEN_getOrCreateSimple_with_same_type_called_second_time_THEN_returns_same_instance() {\n        val thing1 = dispatcher.getOrCreateSimple { Thing<Int>() }\n        val thing2 = dispatcher.getOrCreateSimple { Thing<Int>() }\n\n        assertSame(thing1, thing2)\n    }\n\n    @Test\n    fun WHEN_getOrCreateSimple_with_different_type_called_second_time_THEN_returns_new_instance() {\n        val thing1 = dispatcher.getOrCreateSimple { Thing<Int>() }\n        val thing2 = dispatcher.getOrCreateSimple { Thing<Float>() }\n\n        assertNotSame<Thing<*>>(thing1, thing2)\n    }\n\n    @Test\n    fun retainingInstance_retains_instance() {\n        val instanceKeeper = InstanceKeeperDispatcher()\n        val component1 = Component(instanceKeeper)\n\n        val component2 = Component(instanceKeeper)\n\n        assertSame(component1.instance, component2.instance)\n    }\n\n    @Test\n    fun retainingSimpleInstance_retains_instance() {\n        val instanceKeeper = InstanceKeeperDispatcher()\n        val component1 = Component(instanceKeeper)\n\n        val component2 = Component(instanceKeeper)\n\n        assertSame(component1.simpleInstance, component2.simpleInstance)\n    }\n\n    @Test\n    fun retainingClosable_retains_instance() {\n        val instanceKeeper = InstanceKeeperDispatcher()\n        val component1 = Component(instanceKeeper)\n\n        val component2 = Component(instanceKeeper)\n\n        assertSame(component1.closeable, component2.closeable)\n    }\n\n    @Suppress(\"unused\")\n    private class Thing<out T>\n\n    @Suppress(\"unused\")\n    private class ThingInstance<out T> : InstanceKeeper.Instance\n\n    @Suppress(\"unused\")\n    private class ThingCloseable<out T> : AutoCloseable {\n        override fun close() {\n            // no-op\n        }\n    }\n\n    private class Component(override val instanceKeeper: InstanceKeeper) : InstanceKeeperOwner {\n        val instance by retainingInstance { ThingInstance<Int>() }\n        val simpleInstance by retainingSimpleInstance { Thing<Int>() }\n        val closeable by retainingCloseable { ThingCloseable<Int>() }\n    }\n}\n"
  },
  {
    "path": "lifecycle/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "lifecycle/api/android/lifecycle.api",
    "content": "public final class com/arkivanov/essenty/lifecycle/AndroidExtKt {\n\tpublic static final fun asEssentyLifecycle (Landroidx/lifecycle/Lifecycle;)Lcom/arkivanov/essenty/lifecycle/Lifecycle;\n\tpublic static final fun essentyLifecycle (Landroidx/lifecycle/LifecycleOwner;)Lcom/arkivanov/essenty/lifecycle/Lifecycle;\n}\n\npublic abstract interface class com/arkivanov/essenty/lifecycle/Lifecycle {\n\tpublic abstract fun getState ()Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic abstract fun subscribe (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic abstract fun unsubscribe (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n}\n\npublic abstract interface class com/arkivanov/essenty/lifecycle/Lifecycle$Callbacks {\n\tpublic abstract fun onCreate ()V\n\tpublic abstract fun onDestroy ()V\n\tpublic abstract fun onPause ()V\n\tpublic abstract fun onResume ()V\n\tpublic abstract fun onStart ()V\n\tpublic abstract fun onStop ()V\n}\n\npublic final class com/arkivanov/essenty/lifecycle/Lifecycle$Callbacks$DefaultImpls {\n\tpublic static fun onCreate (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic static fun onDestroy (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic static fun onPause (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic static fun onResume (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic static fun onStart (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic static fun onStop (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n}\n\npublic final class com/arkivanov/essenty/lifecycle/Lifecycle$State : java/lang/Enum {\n\tpublic static final field CREATED Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static final field DESTROYED Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static final field INITIALIZED Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static final field RESUMED Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static final field STARTED Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static fun getEntries ()Lkotlin/enums/EnumEntries;\n\tpublic static fun valueOf (Ljava/lang/String;)Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static fun values ()[Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n}\n\npublic final class com/arkivanov/essenty/lifecycle/LifecycleExtKt {\n\tpublic static final fun doOnCreate (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnCreate (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnDestroy (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnDestroy (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnPause (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnPause (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static synthetic fun doOnPause$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static synthetic fun doOnPause$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static final fun doOnResume (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnResume (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static synthetic fun doOnResume$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static synthetic fun doOnResume$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static final fun doOnStart (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnStart (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static synthetic fun doOnStart$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static synthetic fun doOnStart$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static final fun doOnStop (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnStop (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static synthetic fun doOnStop$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static synthetic fun doOnStop$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static final fun subscribe (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;\n\tpublic static synthetic fun subscribe$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;\n}\n\npublic abstract interface class com/arkivanov/essenty/lifecycle/LifecycleOwner {\n\tpublic abstract fun getLifecycle ()Lcom/arkivanov/essenty/lifecycle/Lifecycle;\n}\n\npublic abstract interface class com/arkivanov/essenty/lifecycle/LifecycleRegistry : com/arkivanov/essenty/lifecycle/Lifecycle, com/arkivanov/essenty/lifecycle/Lifecycle$Callbacks {\n}\n\npublic final class com/arkivanov/essenty/lifecycle/LifecycleRegistry$DefaultImpls {\n\tpublic static fun onCreate (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static fun onDestroy (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static fun onPause (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static fun onResume (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static fun onStart (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static fun onStop (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n}\n\npublic final class com/arkivanov/essenty/lifecycle/LifecycleRegistryExtKt {\n\tpublic static final fun create (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static final fun destroy (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static final fun pause (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static final fun resume (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static final fun start (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static final fun stop (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n}\n\npublic final class com/arkivanov/essenty/lifecycle/LifecycleRegistryKt {\n\tpublic static final fun LifecycleRegistry ()Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;\n\tpublic static final fun LifecycleRegistry (Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;)Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;\n}\n\n"
  },
  {
    "path": "lifecycle/api/jvm/lifecycle.api",
    "content": "public abstract interface class com/arkivanov/essenty/lifecycle/Lifecycle {\n\tpublic abstract fun getState ()Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic abstract fun subscribe (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic abstract fun unsubscribe (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n}\n\npublic abstract interface class com/arkivanov/essenty/lifecycle/Lifecycle$Callbacks {\n\tpublic abstract fun onCreate ()V\n\tpublic abstract fun onDestroy ()V\n\tpublic abstract fun onPause ()V\n\tpublic abstract fun onResume ()V\n\tpublic abstract fun onStart ()V\n\tpublic abstract fun onStop ()V\n}\n\npublic final class com/arkivanov/essenty/lifecycle/Lifecycle$Callbacks$DefaultImpls {\n\tpublic static fun onCreate (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic static fun onDestroy (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic static fun onPause (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic static fun onResume (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic static fun onStart (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n\tpublic static fun onStop (Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;)V\n}\n\npublic final class com/arkivanov/essenty/lifecycle/Lifecycle$State : java/lang/Enum {\n\tpublic static final field CREATED Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static final field DESTROYED Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static final field INITIALIZED Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static final field RESUMED Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static final field STARTED Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static fun getEntries ()Lkotlin/enums/EnumEntries;\n\tpublic static fun valueOf (Ljava/lang/String;)Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n\tpublic static fun values ()[Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;\n}\n\npublic final class com/arkivanov/essenty/lifecycle/LifecycleExtKt {\n\tpublic static final fun doOnCreate (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnCreate (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnDestroy (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnDestroy (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnPause (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnPause (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static synthetic fun doOnPause$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static synthetic fun doOnPause$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static final fun doOnResume (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnResume (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static synthetic fun doOnResume$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static synthetic fun doOnResume$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static final fun doOnStart (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnStart (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static synthetic fun doOnStart$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static synthetic fun doOnStart$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static final fun doOnStop (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static final fun doOnStop (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;)V\n\tpublic static synthetic fun doOnStop$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static synthetic fun doOnStop$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V\n\tpublic static final fun subscribe (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;\n\tpublic static synthetic fun subscribe$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/essenty/lifecycle/Lifecycle$Callbacks;\n}\n\npublic abstract interface class com/arkivanov/essenty/lifecycle/LifecycleOwner {\n\tpublic abstract fun getLifecycle ()Lcom/arkivanov/essenty/lifecycle/Lifecycle;\n}\n\npublic abstract interface class com/arkivanov/essenty/lifecycle/LifecycleRegistry : com/arkivanov/essenty/lifecycle/Lifecycle, com/arkivanov/essenty/lifecycle/Lifecycle$Callbacks {\n}\n\npublic final class com/arkivanov/essenty/lifecycle/LifecycleRegistry$DefaultImpls {\n\tpublic static fun onCreate (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static fun onDestroy (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static fun onPause (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static fun onResume (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static fun onStart (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static fun onStop (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n}\n\npublic final class com/arkivanov/essenty/lifecycle/LifecycleRegistryExtKt {\n\tpublic static final fun create (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static final fun destroy (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static final fun pause (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static final fun resume (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static final fun start (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n\tpublic static final fun stop (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;)V\n}\n\npublic final class com/arkivanov/essenty/lifecycle/LifecycleRegistryKt {\n\tpublic static final fun LifecycleRegistry ()Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;\n\tpublic static final fun LifecycleRegistry (Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;)Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;\n}\n\n"
  },
  {
    "path": "lifecycle/api/lifecycle.klib.api",
    "content": "// Klib ABI Dump\n// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxX64, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, watchosArm32, watchosArm64, watchosSimulatorArm64, watchosX64]\n// Alias: ios => [iosArm64, iosSimulatorArm64, iosX64]\n// Alias: tvos => [tvosArm64, tvosSimulatorArm64, tvosX64]\n// Rendering settings:\n// - Signature version: 2\n// - Show manifest properties: true\n// - Show declarations: true\n\n// Library unique name: <com.arkivanov.essenty:lifecycle>\nabstract interface com.arkivanov.essenty.lifecycle/Lifecycle { // com.arkivanov.essenty.lifecycle/Lifecycle|null[0]\n    abstract val state // com.arkivanov.essenty.lifecycle/Lifecycle.state|{}state[0]\n        abstract fun <get-state>(): com.arkivanov.essenty.lifecycle/Lifecycle.State // com.arkivanov.essenty.lifecycle/Lifecycle.state.<get-state>|<get-state>(){}[0]\n\n    abstract fun subscribe(com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks) // com.arkivanov.essenty.lifecycle/Lifecycle.subscribe|subscribe(com.arkivanov.essenty.lifecycle.Lifecycle.Callbacks){}[0]\n    abstract fun unsubscribe(com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks) // com.arkivanov.essenty.lifecycle/Lifecycle.unsubscribe|unsubscribe(com.arkivanov.essenty.lifecycle.Lifecycle.Callbacks){}[0]\n\n    final enum class State : kotlin/Enum<com.arkivanov.essenty.lifecycle/Lifecycle.State> { // com.arkivanov.essenty.lifecycle/Lifecycle.State|null[0]\n        enum entry CREATED // com.arkivanov.essenty.lifecycle/Lifecycle.State.CREATED|null[0]\n        enum entry DESTROYED // com.arkivanov.essenty.lifecycle/Lifecycle.State.DESTROYED|null[0]\n        enum entry INITIALIZED // com.arkivanov.essenty.lifecycle/Lifecycle.State.INITIALIZED|null[0]\n        enum entry RESUMED // com.arkivanov.essenty.lifecycle/Lifecycle.State.RESUMED|null[0]\n        enum entry STARTED // com.arkivanov.essenty.lifecycle/Lifecycle.State.STARTED|null[0]\n\n        final val entries // com.arkivanov.essenty.lifecycle/Lifecycle.State.entries|#static{}entries[0]\n            final fun <get-entries>(): kotlin.enums/EnumEntries<com.arkivanov.essenty.lifecycle/Lifecycle.State> // com.arkivanov.essenty.lifecycle/Lifecycle.State.entries.<get-entries>|<get-entries>#static(){}[0]\n\n        final fun valueOf(kotlin/String): com.arkivanov.essenty.lifecycle/Lifecycle.State // com.arkivanov.essenty.lifecycle/Lifecycle.State.valueOf|valueOf#static(kotlin.String){}[0]\n        final fun values(): kotlin/Array<com.arkivanov.essenty.lifecycle/Lifecycle.State> // com.arkivanov.essenty.lifecycle/Lifecycle.State.values|values#static(){}[0]\n    }\n\n    abstract interface Callbacks { // com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks|null[0]\n        open fun onCreate() // com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks.onCreate|onCreate(){}[0]\n        open fun onDestroy() // com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks.onDestroy|onDestroy(){}[0]\n        open fun onPause() // com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks.onPause|onPause(){}[0]\n        open fun onResume() // com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks.onResume|onResume(){}[0]\n        open fun onStart() // com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks.onStart|onStart(){}[0]\n        open fun onStop() // com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks.onStop|onStop(){}[0]\n    }\n}\n\nabstract interface com.arkivanov.essenty.lifecycle/LifecycleOwner { // com.arkivanov.essenty.lifecycle/LifecycleOwner|null[0]\n    abstract val lifecycle // com.arkivanov.essenty.lifecycle/LifecycleOwner.lifecycle|{}lifecycle[0]\n        abstract fun <get-lifecycle>(): com.arkivanov.essenty.lifecycle/Lifecycle // com.arkivanov.essenty.lifecycle/LifecycleOwner.lifecycle.<get-lifecycle>|<get-lifecycle>(){}[0]\n}\n\nabstract interface com.arkivanov.essenty.lifecycle/LifecycleRegistry : com.arkivanov.essenty.lifecycle/Lifecycle, com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks // com.arkivanov.essenty.lifecycle/LifecycleRegistry|null[0]\n\nfinal fun (com.arkivanov.essenty.lifecycle/Lifecycle).com.arkivanov.essenty.lifecycle/subscribe(kotlin/Function0<kotlin/Unit>? = ..., kotlin/Function0<kotlin/Unit>? = ..., kotlin/Function0<kotlin/Unit>? = ..., kotlin/Function0<kotlin/Unit>? = ..., kotlin/Function0<kotlin/Unit>? = ..., kotlin/Function0<kotlin/Unit>? = ...): com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks // com.arkivanov.essenty.lifecycle/subscribe|subscribe@com.arkivanov.essenty.lifecycle.Lifecycle(kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?){}[0]\nfinal fun (com.arkivanov.essenty.lifecycle/LifecycleRegistry).com.arkivanov.essenty.lifecycle/create() // com.arkivanov.essenty.lifecycle/create|create@com.arkivanov.essenty.lifecycle.LifecycleRegistry(){}[0]\nfinal fun (com.arkivanov.essenty.lifecycle/LifecycleRegistry).com.arkivanov.essenty.lifecycle/destroy() // com.arkivanov.essenty.lifecycle/destroy|destroy@com.arkivanov.essenty.lifecycle.LifecycleRegistry(){}[0]\nfinal fun (com.arkivanov.essenty.lifecycle/LifecycleRegistry).com.arkivanov.essenty.lifecycle/pause() // com.arkivanov.essenty.lifecycle/pause|pause@com.arkivanov.essenty.lifecycle.LifecycleRegistry(){}[0]\nfinal fun (com.arkivanov.essenty.lifecycle/LifecycleRegistry).com.arkivanov.essenty.lifecycle/resume() // com.arkivanov.essenty.lifecycle/resume|resume@com.arkivanov.essenty.lifecycle.LifecycleRegistry(){}[0]\nfinal fun (com.arkivanov.essenty.lifecycle/LifecycleRegistry).com.arkivanov.essenty.lifecycle/start() // com.arkivanov.essenty.lifecycle/start|start@com.arkivanov.essenty.lifecycle.LifecycleRegistry(){}[0]\nfinal fun (com.arkivanov.essenty.lifecycle/LifecycleRegistry).com.arkivanov.essenty.lifecycle/stop() // com.arkivanov.essenty.lifecycle/stop|stop@com.arkivanov.essenty.lifecycle.LifecycleRegistry(){}[0]\nfinal fun com.arkivanov.essenty.lifecycle/LifecycleRegistry(): com.arkivanov.essenty.lifecycle/LifecycleRegistry // com.arkivanov.essenty.lifecycle/LifecycleRegistry|LifecycleRegistry(){}[0]\nfinal fun com.arkivanov.essenty.lifecycle/LifecycleRegistry(com.arkivanov.essenty.lifecycle/Lifecycle.State): com.arkivanov.essenty.lifecycle/LifecycleRegistry // com.arkivanov.essenty.lifecycle/LifecycleRegistry|LifecycleRegistry(com.arkivanov.essenty.lifecycle.Lifecycle.State){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/Lifecycle).com.arkivanov.essenty.lifecycle/doOnCreate(crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnCreate|doOnCreate@com.arkivanov.essenty.lifecycle.Lifecycle(kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/Lifecycle).com.arkivanov.essenty.lifecycle/doOnDestroy(crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnDestroy|doOnDestroy@com.arkivanov.essenty.lifecycle.Lifecycle(kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/Lifecycle).com.arkivanov.essenty.lifecycle/doOnPause(kotlin/Boolean = ..., crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnPause|doOnPause@com.arkivanov.essenty.lifecycle.Lifecycle(kotlin.Boolean;kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/Lifecycle).com.arkivanov.essenty.lifecycle/doOnResume(kotlin/Boolean = ..., crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnResume|doOnResume@com.arkivanov.essenty.lifecycle.Lifecycle(kotlin.Boolean;kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/Lifecycle).com.arkivanov.essenty.lifecycle/doOnStart(kotlin/Boolean = ..., crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnStart|doOnStart@com.arkivanov.essenty.lifecycle.Lifecycle(kotlin.Boolean;kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/Lifecycle).com.arkivanov.essenty.lifecycle/doOnStop(kotlin/Boolean = ..., crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnStop|doOnStop@com.arkivanov.essenty.lifecycle.Lifecycle(kotlin.Boolean;kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/LifecycleOwner).com.arkivanov.essenty.lifecycle/doOnCreate(crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnCreate|doOnCreate@com.arkivanov.essenty.lifecycle.LifecycleOwner(kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/LifecycleOwner).com.arkivanov.essenty.lifecycle/doOnDestroy(crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnDestroy|doOnDestroy@com.arkivanov.essenty.lifecycle.LifecycleOwner(kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/LifecycleOwner).com.arkivanov.essenty.lifecycle/doOnPause(kotlin/Boolean = ..., crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnPause|doOnPause@com.arkivanov.essenty.lifecycle.LifecycleOwner(kotlin.Boolean;kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/LifecycleOwner).com.arkivanov.essenty.lifecycle/doOnResume(kotlin/Boolean = ..., crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnResume|doOnResume@com.arkivanov.essenty.lifecycle.LifecycleOwner(kotlin.Boolean;kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/LifecycleOwner).com.arkivanov.essenty.lifecycle/doOnStart(kotlin/Boolean = ..., crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnStart|doOnStart@com.arkivanov.essenty.lifecycle.LifecycleOwner(kotlin.Boolean;kotlin.Function0<kotlin.Unit>){}[0]\nfinal inline fun (com.arkivanov.essenty.lifecycle/LifecycleOwner).com.arkivanov.essenty.lifecycle/doOnStop(kotlin/Boolean = ..., crossinline kotlin/Function0<kotlin/Unit>) // com.arkivanov.essenty.lifecycle/doOnStop|doOnStop@com.arkivanov.essenty.lifecycle.LifecycleOwner(kotlin.Boolean;kotlin.Function0<kotlin.Unit>){}[0]\n\n// Targets: [ios, tvos]\nfinal class com.arkivanov.essenty.lifecycle/ApplicationLifecycle : com.arkivanov.essenty.lifecycle/Lifecycle { // com.arkivanov.essenty.lifecycle/ApplicationLifecycle|null[0]\n    constructor <init>() // com.arkivanov.essenty.lifecycle/ApplicationLifecycle.<init>|<init>(){}[0]\n\n    final val state // com.arkivanov.essenty.lifecycle/ApplicationLifecycle.state|{}state[0]\n        final fun <get-state>(): com.arkivanov.essenty.lifecycle/Lifecycle.State // com.arkivanov.essenty.lifecycle/ApplicationLifecycle.state.<get-state>|<get-state>(){}[0]\n\n    final fun destroy() // com.arkivanov.essenty.lifecycle/ApplicationLifecycle.destroy|destroy(){}[0]\n    final fun subscribe(com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks) // com.arkivanov.essenty.lifecycle/ApplicationLifecycle.subscribe|subscribe(com.arkivanov.essenty.lifecycle.Lifecycle.Callbacks){}[0]\n    final fun unsubscribe(com.arkivanov.essenty.lifecycle/Lifecycle.Callbacks) // com.arkivanov.essenty.lifecycle/ApplicationLifecycle.unsubscribe|unsubscribe(com.arkivanov.essenty.lifecycle.Lifecycle.Callbacks){}[0]\n}\n"
  },
  {
    "path": "lifecycle/build.gradle.kts",
    "content": "import com.arkivanov.gradle.bundle\nimport com.arkivanov.gradle.dependsOn\nimport com.arkivanov.gradle.setupBinaryCompatibilityValidator\nimport com.arkivanov.gradle.setupMultiplatform\nimport com.arkivanov.gradle.setupPublication\nimport com.arkivanov.gradle.setupSourceSets\n\nplugins {\n    id(\"kotlin-multiplatform\")\n    id(\"com.android.library\")\n    id(\"com.arkivanov.gradle.setup\")\n}\n\nsetupMultiplatform()\nsetupPublication()\nsetupBinaryCompatibilityValidator()\n\nandroid {\n    namespace = \"com.arkivanov.essenty.lifecycle\"\n}\n\nkotlin {\n    setupSourceSets {\n        val android by bundle()\n        val itvos by bundle()\n\n        (iosSet + tvosSet) dependsOn itvos\n        itvos dependsOn common\n\n        common.main.dependencies {\n            implementation(project(\":utils-internal\"))\n        }\n\n        android.main.dependencies {\n            implementation(deps.androidx.lifecycle.lifecycleCommonJava8)\n            implementation(deps.androidx.lifecycle.lifecycleRuntime)\n        }\n    }\n}\n"
  },
  {
    "path": "lifecycle/src/androidMain/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest />\n"
  },
  {
    "path": "lifecycle/src/androidMain/kotlin/com/arkivanov/essenty/lifecycle/AndroidExt.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\nimport androidx.lifecycle.DefaultLifecycleObserver\nimport androidx.lifecycle.Lifecycle\nimport androidx.lifecycle.LifecycleObserver\nimport androidx.lifecycle.LifecycleOwner\nimport com.arkivanov.essenty.lifecycle.Lifecycle as EssentyLifecycle\n\n/**\n * Converts AndroidX [Lifecycle] to Essenty [Lifecycle][EssentyLifecycle]\n */\nfun Lifecycle.asEssentyLifecycle(): EssentyLifecycle = EssentyLifecycleInterop(this)\n\n/**\n * Converts AndroidX [Lifecycle] to Essenty [Lifecycle][EssentyLifecycle]\n */\nfun LifecycleOwner.essentyLifecycle(): EssentyLifecycle = lifecycle.asEssentyLifecycle()\n\nprivate class EssentyLifecycleInterop(\n    private val delegate: Lifecycle\n) : EssentyLifecycle {\n\n    private val observerMap = HashMap<EssentyLifecycle.Callbacks, LifecycleObserver>()\n\n    override val state: EssentyLifecycle.State get() = delegate.currentState.toEssentyLifecycleState()\n\n    override fun subscribe(callbacks: EssentyLifecycle.Callbacks) {\n        check(callbacks !in observerMap) { \"Already subscribed\" }\n\n        val observer = AndroidLifecycleObserver(delegate = callbacks, onDestroy = { observerMap -= callbacks })\n        observerMap[callbacks] = observer\n        delegate.addObserver(observer)\n    }\n\n    override fun unsubscribe(callbacks: EssentyLifecycle.Callbacks) {\n        observerMap.remove(callbacks)?.also {\n            delegate.removeObserver(it)\n        }\n    }\n}\n\nprivate fun Lifecycle.State.toEssentyLifecycleState(): EssentyLifecycle.State =\n    when (this) {\n        Lifecycle.State.DESTROYED -> EssentyLifecycle.State.DESTROYED\n        Lifecycle.State.INITIALIZED -> EssentyLifecycle.State.INITIALIZED\n        Lifecycle.State.CREATED -> EssentyLifecycle.State.CREATED\n        Lifecycle.State.STARTED -> EssentyLifecycle.State.STARTED\n        Lifecycle.State.RESUMED -> EssentyLifecycle.State.RESUMED\n    }\n\nprivate class AndroidLifecycleObserver(\n    private val delegate: EssentyLifecycle.Callbacks,\n    private val onDestroy: () -> Unit,\n) : DefaultLifecycleObserver {\n    override fun onCreate(owner: LifecycleOwner) {\n        delegate.onCreate()\n    }\n\n    override fun onStart(owner: LifecycleOwner) {\n        delegate.onStart()\n    }\n\n    override fun onResume(owner: LifecycleOwner) {\n        delegate.onResume()\n    }\n\n    override fun onPause(owner: LifecycleOwner) {\n        delegate.onPause()\n    }\n\n    override fun onStop(owner: LifecycleOwner) {\n        delegate.onStop()\n    }\n\n    override fun onDestroy(owner: LifecycleOwner) {\n        delegate.onDestroy()\n        onDestroy.invoke()\n    }\n}\n"
  },
  {
    "path": "lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/Lifecycle.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\n/**\n * A holder of [Lifecycle.State] that can be observed for changes.\n *\n * Possible transitions:\n *\n * ```\n * [INITIALIZED] ──┐\n *                 ↓\n *         ┌── [CREATED] ──┐\n *         ↓       ↑       ↓\n *    [DESTROYED]  └── [STARTED] ──┐\n *                         ↑       ↓\n *                         └── [RESUMED]\n * ```\n */\ninterface Lifecycle {\n\n    /**\n     * The current state of the [Lifecycle].\n     */\n    val state: State\n\n    /**\n     * Subscribes the given [callbacks] to state changes.\n     */\n    fun subscribe(callbacks: Callbacks)\n\n    /**\n     * Unsubscribes the given [callbacks] from state changes.\n     */\n    fun unsubscribe(callbacks: Callbacks)\n\n    /**\n     * Defines the possible states of the [Lifecycle].\n     */\n    enum class State {\n        DESTROYED,\n        INITIALIZED,\n        CREATED,\n        STARTED,\n        RESUMED\n    }\n\n    /**\n     * The callbacks of the [Lifecycle]. Each callback is called on the corresponding state change.\n     */\n    interface Callbacks {\n        fun onCreate() {\n        }\n\n        fun onStart() {\n        }\n\n        fun onResume() {\n        }\n\n        fun onPause() {\n        }\n\n        fun onStop() {\n        }\n\n        fun onDestroy() {\n        }\n    }\n}\n"
  },
  {
    "path": "lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/LifecycleExt.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\n/**\n * A convenience method for [Lifecycle.subscribe].\n */\nfun Lifecycle.subscribe(\n    onCreate: (() -> Unit)? = null,\n    onStart: (() -> Unit)? = null,\n    onResume: (() -> Unit)? = null,\n    onPause: (() -> Unit)? = null,\n    onStop: (() -> Unit)? = null,\n    onDestroy: (() -> Unit)? = null\n): Lifecycle.Callbacks =\n    object : Lifecycle.Callbacks {\n        override fun onCreate() {\n            onCreate?.invoke()\n        }\n\n        override fun onStart() {\n            onStart?.invoke()\n        }\n\n        override fun onResume() {\n            onResume?.invoke()\n        }\n\n        override fun onPause() {\n            onPause?.invoke()\n        }\n\n        override fun onStop() {\n            onStop?.invoke()\n        }\n\n        override fun onDestroy() {\n            onDestroy?.invoke()\n        }\n    }.also(::subscribe)\n\n/**\n * Registers the callback [block] to be called when this [Lifecycle] is created.\n */\ninline fun Lifecycle.doOnCreate(crossinline block: () -> Unit) {\n    subscribe(\n        object : Lifecycle.Callbacks {\n            override fun onCreate() {\n                unsubscribe(this)\n                block()\n            }\n        }\n    )\n}\n\n/**\n * Registers the callback [block] to be called when this [Lifecycle] is started.\n *\n * @param isOneTime if `true` then the callback is automatically unregistered right before\n * the first call, default value is `false`.\n */\ninline fun Lifecycle.doOnStart(isOneTime: Boolean = false, crossinline block: () -> Unit) {\n    subscribe(\n        object : Lifecycle.Callbacks {\n            override fun onStart() {\n                if (isOneTime) {\n                    unsubscribe(this)\n                }\n\n                block()\n            }\n        }\n    )\n}\n\n/**\n * Registers the callback [block] to be called when this [Lifecycle] is resumed.\n *\n * @param isOneTime if `true` then the callback is automatically unregistered right before\n * the first call, default value is `false`.\n */\ninline fun Lifecycle.doOnResume(isOneTime: Boolean = false, crossinline block: () -> Unit) {\n    subscribe(\n        object : Lifecycle.Callbacks {\n            override fun onResume() {\n                if (isOneTime) {\n                    unsubscribe(this)\n                }\n\n                block()\n            }\n        }\n    )\n}\n\n/**\n * Registers the callback [block] to be called when this [Lifecycle] is paused.\n *\n * @param isOneTime if `true` then the callback is automatically unregistered right before\n * the first call, default value is `false`.\n */\ninline fun Lifecycle.doOnPause(isOneTime: Boolean = false, crossinline block: () -> Unit) {\n    subscribe(\n        object : Lifecycle.Callbacks {\n            override fun onPause() {\n                if (isOneTime) {\n                    unsubscribe(this)\n                }\n\n                block()\n            }\n        }\n    )\n}\n\n/**\n * Registers the callback [block] to be called when this [Lifecycle] is stopped.\n *\n * @param isOneTime if `true` then the callback is automatically unregistered right before\n * the first call, default value is `false`.\n */\ninline fun Lifecycle.doOnStop(isOneTime: Boolean = false, crossinline block: () -> Unit) {\n    subscribe(\n        object : Lifecycle.Callbacks {\n            override fun onStop() {\n                if (isOneTime) {\n                    unsubscribe(this)\n                }\n\n                block()\n            }\n        }\n    )\n}\n\n/**\n * Registers the callback [block] to be called when this [Lifecycle] is destroyed.\n * Calls the [block] immediately if the [Lifecycle] is already destroyed.\n */\ninline fun Lifecycle.doOnDestroy(crossinline block: () -> Unit) {\n    if (state == Lifecycle.State.DESTROYED) {\n        block()\n    } else {\n        subscribe(\n            object : Lifecycle.Callbacks {\n                override fun onDestroy() {\n                    block()\n                }\n            }\n        )\n    }\n}\n\n/**\n * Convenience method for [Lifecycle.doOnCreate].\n */\ninline fun LifecycleOwner.doOnCreate(crossinline block: () -> Unit) {\n    lifecycle.doOnCreate(block)\n}\n\n/**\n * Convenience method for [Lifecycle.doOnStart].\n */\ninline fun LifecycleOwner.doOnStart(isOneTime: Boolean = false, crossinline block: () -> Unit) {\n    lifecycle.doOnStart(isOneTime = isOneTime, block = block)\n}\n\n/**\n * Convenience method for [Lifecycle.doOnResume].\n */\ninline fun LifecycleOwner.doOnResume(isOneTime: Boolean = false, crossinline block: () -> Unit) {\n    lifecycle.doOnResume(isOneTime = isOneTime, block = block)\n}\n\n/**\n * Convenience method for [Lifecycle.doOnPause].\n */\ninline fun LifecycleOwner.doOnPause(isOneTime: Boolean = false, crossinline block: () -> Unit) {\n    lifecycle.doOnPause(isOneTime = isOneTime, block = block)\n}\n\n/**\n * Convenience method for [Lifecycle.doOnStop].\n */\ninline fun LifecycleOwner.doOnStop(isOneTime: Boolean = false, crossinline block: () -> Unit) {\n    lifecycle.doOnStop(isOneTime = isOneTime, block = block)\n}\n\n/**\n * Convenience method for [Lifecycle.doOnDestroy].\n */\ninline fun LifecycleOwner.doOnDestroy(crossinline block: () -> Unit) {\n    lifecycle.doOnDestroy(block)\n}\n"
  },
  {
    "path": "lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/LifecycleOwner.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\n/**\n * Represents a holder of [Lifecycle].\n */\ninterface LifecycleOwner {\n\n    val lifecycle: Lifecycle\n}\n"
  },
  {
    "path": "lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/LifecycleRegistry.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\nimport kotlin.js.JsName\n\n/**\n * Represents [Lifecycle] and [Lifecycle.Callbacks] at the same time.\n * Can be used to manually control the [Lifecycle].\n */\ninterface LifecycleRegistry : Lifecycle, Lifecycle.Callbacks\n\n/**\n * Creates a default implementation of [LifecycleRegistry].\n */\n@JsName(\"lifecycleRegistry\")\nfun LifecycleRegistry(): LifecycleRegistry = LifecycleRegistry(initialState = Lifecycle.State.INITIALIZED)\n\n/**\n * Creates a default implementation of [LifecycleRegistry] with the specified [initialState].\n */\nfun LifecycleRegistry(\n    initialState: Lifecycle.State,\n): LifecycleRegistry =\n    LifecycleRegistryImpl(initialState)\n"
  },
  {
    "path": "lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/LifecycleRegistryExt.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\n/**\n * Drives the state of the [Lifecycle] forward to [Lifecycle.State.CREATED].\n * Does nothing if the state is already [Lifecycle.State.CREATED] or greater, or [Lifecycle.State.DESTROYED].\n */\nfun LifecycleRegistry.create() {\n    if (state == Lifecycle.State.INITIALIZED) {\n        onCreate()\n    }\n}\n\n/**\n * Drives the state of the [Lifecycle] forward  to [Lifecycle.State.STARTED].\n * Does nothing if the state is already [Lifecycle.State.STARTED] or greater, or [Lifecycle.State.DESTROYED].\n */\nfun LifecycleRegistry.start() {\n    create()\n\n    if (state == Lifecycle.State.CREATED) {\n        onStart()\n    }\n}\n\n/**\n * Drives the state of the [Lifecycle] forward  to [Lifecycle.State.RESUMED].\n * Does nothing if the state is already [Lifecycle.State.RESUMED] or greater, or [Lifecycle.State.DESTROYED].\n */\nfun LifecycleRegistry.resume() {\n    start()\n\n    if (state == Lifecycle.State.STARTED) {\n        onResume()\n    }\n}\n\n/**\n * Drives the state of the [Lifecycle] backward to [Lifecycle.State.STARTED].\n * Does nothing if the state is already [Lifecycle.State.STARTED] or lower.\n */\nfun LifecycleRegistry.pause() {\n    if (state == Lifecycle.State.RESUMED) {\n        onPause()\n    }\n}\n\n/**\n * Drives the state of the [Lifecycle] backward to [Lifecycle.State.CREATED].\n * Does nothing if the state is already [Lifecycle.State.CREATED] or lower.\n */\nfun LifecycleRegistry.stop() {\n    pause()\n\n    if (state == Lifecycle.State.STARTED) {\n        onStop()\n    }\n}\n\n/**\n * Drives the state of the [Lifecycle] backward to [Lifecycle.State.DESTROYED].\n * Does nothing if the state is already [Lifecycle.State.DESTROYED].\n */\nfun LifecycleRegistry.destroy() {\n    stop()\n\n    if (state == Lifecycle.State.CREATED) {\n        onDestroy()\n    }\n}\n"
  },
  {
    "path": "lifecycle/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/LifecycleRegistryImpl.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\nimport com.arkivanov.essenty.lifecycle.Lifecycle.Callbacks\nimport com.arkivanov.essenty.lifecycle.Lifecycle.State\n\ninternal class LifecycleRegistryImpl(initialState: State) : LifecycleRegistry {\n\n    private var callbacks = emptySet<Callbacks>()\n    private var _state = initialState\n    override val state: State get() = _state\n\n    override fun subscribe(callbacks: Callbacks) {\n        check(callbacks !in this.callbacks) { \"Already subscribed\" }\n\n        this.callbacks += callbacks\n\n        val state = _state\n        if (state >= State.CREATED) {\n            callbacks.onCreate()\n        }\n        if (state >= State.STARTED) {\n            callbacks.onStart()\n        }\n        if (state >= State.RESUMED) {\n            callbacks.onResume()\n        }\n    }\n\n    override fun unsubscribe(callbacks: Callbacks) {\n        this.callbacks -= callbacks\n    }\n\n    override fun onCreate() {\n        checkState(State.INITIALIZED)\n        _state = State.CREATED\n        callbacks.forEach(Callbacks::onCreate)\n    }\n\n    override fun onStart() {\n        checkState(State.CREATED)\n        _state = State.STARTED\n        callbacks.forEach(Callbacks::onStart)\n    }\n\n    override fun onResume() {\n        checkState(State.STARTED)\n        _state = State.RESUMED\n        callbacks.forEach(Callbacks::onResume)\n    }\n\n    override fun onPause() {\n        checkState(State.RESUMED)\n        _state = State.STARTED\n        callbacks.reversed().forEach(Callbacks::onPause)\n    }\n\n    override fun onStop() {\n        checkState(State.STARTED)\n        _state = State.CREATED\n        callbacks.reversed().forEach(Callbacks::onStop)\n    }\n\n    override fun onDestroy() {\n        checkState(State.CREATED)\n        _state = State.DESTROYED\n        callbacks.reversed().forEach(Callbacks::onDestroy)\n        callbacks = emptySet()\n    }\n\n    private fun checkState(required: State) {\n        check(_state == required) { \"Expected state $required but was $_state\" }\n    }\n}\n"
  },
  {
    "path": "lifecycle/src/commonTest/kotlin/com/arkivanov/essenty/lifecycle/LifecycleExtTest.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\nimport com.arkivanov.essenty.lifecycle.Lifecycle.Callbacks\nimport com.arkivanov.essenty.lifecycle.Lifecycle.State\nimport kotlin.test.Test\nimport kotlin.test.assertContentEquals\nimport kotlin.test.assertEquals\n\n@Suppress(\"TestFunctionName\")\nclass LifecycleExtTest {\n    private val owner = TestLifecycleOwner()\n    private val events = ArrayList<String>()\n\n    @Test\n    fun WHEN_doOnCreate_THEN_not_called() {\n        State.entries.forEach { state ->\n            owner.state = state\n            owner.doOnCreate(callback())\n        }\n\n        assertNoEvents()\n    }\n\n    @Test\n    fun WHEN_doOnCreate_and_onCreate_called_THEN_called() {\n        owner.doOnCreate(callback())\n        owner.call(Callbacks::onCreate)\n\n        assertOneEvent()\n    }\n\n    @Test\n    fun WHEN_doOnStart_THEN_not_called() {\n        State.entries.forEach { state ->\n            owner.state = state\n            owner.doOnStart(block = callback())\n        }\n\n        assertNoEvents()\n    }\n\n    @Test\n    fun WHEN_doOnStart_and_onStart_called_multiple_times_THEN_called_multiple_times() {\n        owner.doOnStart(block = callback())\n        owner.call(Callbacks::onStart)\n        owner.call(Callbacks::onStart)\n\n        assertEquals(2, events.size)\n    }\n\n    @Test\n    fun WHEN_doOnStart_isOneTime_true_and_onStart_called_multiple_times_THEN_called_once() {\n        owner.doOnStart(isOneTime = true, block = callback())\n        owner.call(Callbacks::onStart)\n        owner.call(Callbacks::onStart)\n\n        assertOneEvent()\n    }\n\n    @Test\n    fun WHEN_doOnResume_THEN_not_called() {\n        State.entries.forEach { state ->\n            owner.state = state\n            owner.doOnResume(block = callback())\n        }\n\n        assertNoEvents()\n    }\n\n    @Test\n    fun WHEN_doOnResume_and_onResume_called_multiple_times_THEN_called_multiple_times() {\n        owner.doOnResume(block = callback())\n        owner.call(Callbacks::onResume)\n        owner.call(Callbacks::onResume)\n\n        assertEquals(2, events.size)\n    }\n\n    @Test\n    fun WHEN_doOnResume_isOneTime_true_and_onResume_called_multiple_times_THEN_called_once() {\n        owner.doOnResume(isOneTime = true, block = callback())\n        owner.call(Callbacks::onResume)\n        owner.call(Callbacks::onResume)\n\n        assertOneEvent()\n    }\n\n    @Test\n    fun WHEN_doOnPause_THEN_not_called() {\n        State.entries.forEach { state ->\n            owner.state = state\n            owner.doOnPause(block = callback())\n        }\n\n        assertNoEvents()\n    }\n\n    @Test\n    fun WHEN_doOnPause_and_onPause_called_multiple_times_THEN_called_multiple_times() {\n        owner.doOnPause(block = callback())\n        owner.call(Callbacks::onPause)\n        owner.call(Callbacks::onPause)\n\n        assertEquals(2, events.size)\n    }\n\n    @Test\n    fun WHEN_doOnPause_isOneTime_true_and_onPause_called_multiple_times_THEN_called_once() {\n        owner.doOnPause(isOneTime = true, block = callback())\n        owner.call(Callbacks::onPause)\n        owner.call(Callbacks::onPause)\n\n        assertOneEvent()\n    }\n\n    @Test\n    fun WHEN_doOnStop_THEN_not_called() {\n        State.entries.forEach { state ->\n            owner.state = state\n            owner.doOnStop(block = callback())\n        }\n\n        assertNoEvents()\n    }\n\n    @Test\n    fun WHEN_doOnStop_and_onStop_called_multiple_times_THEN_called_multiple_times() {\n        owner.doOnStop(block = callback())\n        owner.call(Callbacks::onStop)\n        owner.call(Callbacks::onStop)\n\n        assertEquals(2, events.size)\n    }\n\n    @Test\n    fun WHEN_doOnStop_isOneTime_true_and_onStop_called_multiple_times_THEN_called_once() {\n        owner.doOnStop(isOneTime = true, block = callback())\n        owner.call(Callbacks::onStop)\n        owner.call(Callbacks::onStop)\n\n        assertOneEvent()\n    }\n\n    @Test\n    fun GIVEN_state_INITIALIZED_WHEN_doOnDestroy_THEN_not_called() {\n        owner.doOnDestroy(callback())\n\n        assertNoEvents()\n    }\n\n    @Test\n    fun GIVEN_state_CREATED_WHEN_doOnDestroy_THEN_not_called() {\n        owner.state = State.CREATED\n\n        owner.doOnDestroy(callback())\n\n        assertNoEvents()\n    }\n\n    @Test\n    fun GIVEN_state_CREATED_WHEN_doOnDestroy_and_onDestroy_called_THEN_called() {\n        owner.state = State.CREATED\n\n        owner.doOnDestroy(callback())\n        owner.call(Callbacks::onDestroy)\n\n        assertOneEvent()\n    }\n\n    @Test\n    fun GIVEN_state_DESTROYED_WHEN_doOnDestroy_THEN_called() {\n        owner.state = State.DESTROYED\n\n        owner.doOnDestroy(callback())\n\n        assertOneEvent()\n    }\n\n    private fun assertNoEvents() {\n        assertContentEquals(emptyList(), events)\n    }\n\n    private fun assertOneEvent() {\n        assertEquals(1, events.size)\n    }\n\n    private fun callback(name: String = \"event\"): () -> Unit =\n        { events += name }\n\n    private class TestLifecycleOwner : LifecycleOwner {\n        override val lifecycle: TestLifecycle = TestLifecycle()\n\n        var state: State by lifecycle::state\n\n        fun call(call: (Callbacks) -> Unit) {\n            lifecycle.callbacks.forEach(call)\n        }\n    }\n\n    private class TestLifecycle : Lifecycle {\n        override var state: State = State.INITIALIZED\n        var callbacks: MutableSet<Callbacks> = HashSet()\n\n        override fun subscribe(callbacks: Callbacks) {\n            this.callbacks += callbacks\n        }\n\n        override fun unsubscribe(callbacks: Callbacks) {\n            this.callbacks -= callbacks\n        }\n    }\n}\n"
  },
  {
    "path": "lifecycle/src/commonTest/kotlin/com/arkivanov/essenty/lifecycle/LifecycleRegistryTest.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\n@Suppress(\"TestFunctionName\")\nclass LifecycleRegistryTest {\n\n    private val registry = LifecycleRegistryImpl(initialState = Lifecycle.State.INITIALIZED)\n\n    @Test\n    fun WHEN_called_THEN_calls_subscribers_in_correct_order() {\n        val events = ArrayList<String>()\n\n        fun callbacks(name: String): Lifecycle.Callbacks =\n            object : Lifecycle.Callbacks {\n                override fun onCreate() {\n                    events += \"onCreate $name\"\n                }\n\n                override fun onStart() {\n                    events += \"onStart $name\"\n                }\n\n                override fun onResume() {\n                    events += \"onResume $name\"\n                }\n\n                override fun onPause() {\n                    events += \"onPause $name\"\n                }\n\n                override fun onStop() {\n                    events += \"onStop $name\"\n                }\n\n                override fun onDestroy() {\n                    events += \"onDestroy $name\"\n                }\n            }\n\n        registry.subscribe(callbacks(name = \"1\"))\n        registry.subscribe(callbacks(name = \"2\"))\n\n        registry.onCreate()\n        registry.onStart()\n        registry.onResume()\n        registry.onPause()\n        registry.onStop()\n        registry.onDestroy()\n\n        assertEquals(\n            listOf(\n                \"onCreate 1\",\n                \"onCreate 2\",\n                \"onStart 1\",\n                \"onStart 2\",\n                \"onResume 1\",\n                \"onResume 2\",\n                \"onPause 2\",\n                \"onPause 1\",\n                \"onStop 2\",\n                \"onStop 1\",\n                \"onDestroy 2\",\n                \"onDestroy 1\"\n            ),\n            events\n        )\n    }\n\n    @Test\n    fun WHEN_unsubscribed_and_called_THEN_callbacks_not_called() {\n        val events = ArrayList<String>()\n\n        val callbacks =\n            object : Lifecycle.Callbacks {\n                override fun onCreate() {\n                    events += \"onCreate\"\n                }\n            }\n\n        registry.subscribe(callbacks)\n        registry.unsubscribe(callbacks)\n        registry.onCreate()\n\n        assertEquals(emptyList(), events)\n    }\n\n    @Test\n    fun WHEN_unsubscribed_from_callback_and_called_THEN_callbacks_not_called() {\n        val events = ArrayList<String>()\n\n        val callbacks =\n            object : Lifecycle.Callbacks {\n                override fun onCreate() {\n                    registry.unsubscribe(this)\n                }\n\n                override fun onStart() {\n                    events += \"onStart\"\n                }\n            }\n\n        registry.subscribe(callbacks)\n        registry.onCreate()\n        registry.onStart()\n\n        assertEquals(emptyList(), events)\n    }\n\n    @Test\n    fun WHEN_created_with_initial_state_THEN_state_returns_that_state() {\n        val registry = LifecycleRegistryImpl(initialState = Lifecycle.State.RESUMED)\n\n        assertEquals(Lifecycle.State.RESUMED, registry.state)\n    }\n\n    @Test\n    fun GIVEN_created_with_initial_state_WHEN_subscribed_THEN_callbacks_called() {\n        val registry = LifecycleRegistryImpl(initialState = Lifecycle.State.RESUMED)\n        val events = ArrayList<String>()\n\n        val callbacks =\n            object : Lifecycle.Callbacks {\n                override fun onCreate() {\n                    events += \"onCreate\"\n                }\n\n                override fun onStart() {\n                    events += \"onStart\"\n                }\n\n                override fun onResume() {\n                    events += \"onResume\"\n                }\n            }\n\n        registry.subscribe(callbacks)\n\n        assertEquals(listOf(\"onCreate\", \"onStart\", \"onResume\"), events)\n    }\n}\n"
  },
  {
    "path": "lifecycle/src/itvosMain/kotlin/com/arkivanov/essenty/lifecycle/ApplicationLifecycle.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\nimport platform.Foundation.NSNotification\nimport platform.Foundation.NSNotificationCenter\nimport platform.Foundation.NSNotificationName\nimport platform.Foundation.NSOperationQueue\nimport platform.UIKit.UIApplication\nimport platform.UIKit.UIApplicationDidBecomeActiveNotification\nimport platform.UIKit.UIApplicationDidEnterBackgroundNotification\nimport platform.UIKit.UIApplicationState\nimport platform.UIKit.UIApplicationWillEnterForegroundNotification\nimport platform.UIKit.UIApplicationWillResignActiveNotification\nimport platform.UIKit.UIApplicationWillTerminateNotification\nimport platform.darwin.NSObjectProtocol\n\n/**\n * An implementation of [Lifecycle] that follows the [UIApplication] lifecycle notifications.\n *\n * Since this implementation subscribes to [UIApplication] global lifecycle events,\n * the instance and all its registered callbacks (and whatever they capture) will stay in\n * memory until the application is destroyed. It's ok to use it in a global scope like\n * `UIApplicationDelegate`, but it may cause memory leaks when used in a narrower scope like\n * `UIViewController` if it gets destroyed earlier.\n */\nclass ApplicationLifecycle internal constructor(\n    private val platform: Platform,\n    private val lifecycle: LifecycleRegistry = LifecycleRegistry(),\n) : Lifecycle by lifecycle {\n\n    constructor() : this(platform = DefaultPlatform)\n\n    private val willEnterForegroundObserver = platform.addObserver(UIApplicationWillEnterForegroundNotification) { lifecycle.start() }\n    private val didBecomeActiveObserver = platform.addObserver(UIApplicationDidBecomeActiveNotification) { lifecycle.resume() }\n    private val willResignActiveObserver = platform.addObserver(UIApplicationWillResignActiveNotification) { lifecycle.pause() }\n    private val didEnterBackgroundObserver = platform.addObserver(UIApplicationDidEnterBackgroundNotification) { lifecycle.stop() }\n    private val willTerminateObserver = platform.addObserver(UIApplicationWillTerminateNotification) { lifecycle.destroy() }\n\n    init {\n        platform.addOperationOnMainQueue {\n            if (lifecycle.state == Lifecycle.State.INITIALIZED) {\n                when (platform.applicationState) {\n                    UIApplicationState.UIApplicationStateActive -> lifecycle.resume()\n                    UIApplicationState.UIApplicationStateInactive -> lifecycle.start()\n                    UIApplicationState.UIApplicationStateBackground -> lifecycle.create()\n                    else -> lifecycle.create()\n                }\n            }\n        }\n\n        doOnDestroy {\n            platform.removeObserver(willEnterForegroundObserver)\n            platform.removeObserver(didBecomeActiveObserver)\n            platform.removeObserver(willResignActiveObserver)\n            platform.removeObserver(didEnterBackgroundObserver)\n            platform.removeObserver(willTerminateObserver)\n        }\n    }\n\n    /**\n     * Destroys this [ApplicationLifecycle] moving it to [Lifecycle.State.DESTROYED] state.\n     * Also unsubscribes from all [UIApplication] lifecycle notifications.\n     *\n     * If the current state is [Lifecycle.State.INITIALIZED], then the lifecycle is first\n     * moved to [Lifecycle.State.CREATED] state and then immediately to [Lifecycle.State.DESTROYED] state.\n     */\n    fun destroy() {\n        if (lifecycle.state == Lifecycle.State.INITIALIZED) {\n            lifecycle.create()\n        }\n\n        lifecycle.destroy()\n    }\n\n    internal interface Platform {\n        val applicationState: UIApplicationState\n\n        fun addObserver(name: NSNotificationName, block: (NSNotification?) -> Unit): NSObjectProtocol\n        fun removeObserver(observer: NSObjectProtocol)\n        fun addOperationOnMainQueue(block: () -> Unit)\n    }\n\n    internal object DefaultPlatform : Platform {\n        override val applicationState: UIApplicationState get() = UIApplication.sharedApplication.applicationState\n\n        override fun addObserver(name: NSNotificationName, block: (NSNotification?) -> Unit): NSObjectProtocol =\n            NSNotificationCenter.defaultCenter.addObserverForName(\n                name = name,\n                `object` = null,\n                queue = NSOperationQueue.mainQueue,\n                usingBlock = block,\n            )\n\n        override fun removeObserver(observer: NSObjectProtocol) {\n            NSNotificationCenter.defaultCenter.removeObserver(observer)\n        }\n\n        override fun addOperationOnMainQueue(block: () -> Unit) {\n            NSOperationQueue.mainQueue.addOperationWithBlock(block)\n        }\n    }\n}\n"
  },
  {
    "path": "lifecycle/src/itvosTest/kotlin/com/arkivanov/essenty/lifecycle/ApplicationLifecyclePlatformTest.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\nimport platform.Foundation.NSNotificationCenter\nimport platform.UIKit.UIApplicationWillEnterForegroundNotification\nimport kotlin.test.Test\nimport kotlin.test.assertContentEquals\nimport kotlin.test.assertEquals\n\n@Suppress(\"TestFunctionName\")\nclass ApplicationLifecyclePlatformTest {\n\n    private val notificationName = UIApplicationWillEnterForegroundNotification\n    private val platform = ApplicationLifecycle.DefaultPlatform\n\n    @Test\n    fun WHEN_addObserver_and_notification_posted_THEN_notification_received() {\n        val objects = ArrayList<Any?>()\n\n        platform.addObserver(notificationName) { objects += it?.`object` }\n        NSNotificationCenter.defaultCenter.postNotificationName(aName = notificationName, `object` = \"str\")\n\n        assertContentEquals(listOf(\"str\"), objects)\n    }\n\n    @Test\n    fun GIVEN_observer_added_WHEN_removeObserver_and_notification_posted_THEN_notification_not_received() {\n        val objects = ArrayList<Any?>()\n        val observer = platform.addObserver(notificationName) { objects += it?.`object` }\n\n        platform.removeObserver(observer)\n        NSNotificationCenter.defaultCenter.postNotificationName(aName = notificationName, `object` = \"str\")\n\n        assertEquals(emptyList(), objects)\n    }\n}\n"
  },
  {
    "path": "lifecycle/src/itvosTest/kotlin/com/arkivanov/essenty/lifecycle/ApplicationLifecycleTest.kt",
    "content": "package com.arkivanov.essenty.lifecycle\n\nimport platform.Foundation.NSNotification\nimport platform.Foundation.NSNotificationName\nimport platform.UIKit.UIApplicationDidBecomeActiveNotification\nimport platform.UIKit.UIApplicationDidEnterBackgroundNotification\nimport platform.UIKit.UIApplicationState\nimport platform.UIKit.UIApplicationState.UIApplicationStateActive\nimport platform.UIKit.UIApplicationState.UIApplicationStateBackground\nimport platform.UIKit.UIApplicationState.UIApplicationStateInactive\nimport platform.UIKit.UIApplicationWillEnterForegroundNotification\nimport platform.UIKit.UIApplicationWillResignActiveNotification\nimport platform.UIKit.UIApplicationWillTerminateNotification\nimport platform.darwin.NSObject\nimport platform.darwin.NSObjectProtocol\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass ApplicationLifecycleTest {\n\n    private val platform = TestPlatform()\n    private val lifecycle = ApplicationLifecycle(platform = platform)\n\n    @Test\n    fun WHEN_WillEnterForeground_notification_THEN_state_STARTED() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n\n        assertEquals(Lifecycle.State.STARTED, lifecycle.state)\n    }\n\n    @Test\n    fun WHEN_DidBecomeActive_notification_THEN_state_RESUMED() {\n        postNotification(UIApplicationDidBecomeActiveNotification)\n\n        assertEquals(Lifecycle.State.RESUMED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_RESUMED_WHEN_WillResignActive_notification_THEN_state_STARTED() {\n        postNotification(UIApplicationDidBecomeActiveNotification)\n\n        postNotification(UIApplicationWillResignActiveNotification)\n\n        assertEquals(Lifecycle.State.STARTED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_RESUMED_WHEN_DidEnterBackground_notification_THEN_state_CREATED() {\n        postNotification(UIApplicationDidBecomeActiveNotification)\n\n        postNotification(UIApplicationDidEnterBackgroundNotification)\n\n        assertEquals(Lifecycle.State.CREATED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_STARTED_WHEN_DidEnterBackground_notification_THEN_state_CREATED() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n\n        postNotification(UIApplicationDidEnterBackgroundNotification)\n\n        assertEquals(Lifecycle.State.CREATED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_RESUMED_WHEN_WillTerminate_notification_THEN_state_DESTROYED() {\n        postNotification(UIApplicationDidBecomeActiveNotification)\n\n        postNotification(UIApplicationWillTerminateNotification)\n\n        assertEquals(Lifecycle.State.DESTROYED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_RESUMED_WHEN_WillTerminate_notification_THEN_observers_removed() {\n        postNotification(UIApplicationDidBecomeActiveNotification)\n\n        postNotification(UIApplicationWillTerminateNotification)\n\n        platform.assertNotificationObserversEmpty()\n    }\n\n    @Test\n    fun GIVEN_state_STATED_WHEN_WillTerminate_notification_THEN_state_DESTROYED() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n\n        postNotification(UIApplicationWillTerminateNotification)\n\n        assertEquals(Lifecycle.State.DESTROYED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_STATED_WHEN_WillTerminate_notification_THEN_observers_removed() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n\n        postNotification(UIApplicationWillTerminateNotification)\n\n        platform.assertNotificationObserversEmpty()\n    }\n\n    @Test\n    fun GIVEN_state_CREATED_WHEN_WillTerminate_notification_THEN_state_DESTROYED() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n        postNotification(UIApplicationDidEnterBackgroundNotification)\n\n        postNotification(UIApplicationWillTerminateNotification)\n\n        assertEquals(Lifecycle.State.DESTROYED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_CREATED_WHEN_WillTerminate_notification_THEN_observers_removed() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n        postNotification(UIApplicationDidEnterBackgroundNotification)\n\n        postNotification(UIApplicationWillTerminateNotification)\n\n        platform.assertNotificationObserversEmpty()\n    }\n\n    @Test\n    fun GIVEN_state_INITIALIZED_WHEN_destroy_THEN_state_DESTROYED() {\n        lifecycle.destroy()\n\n        assertEquals(Lifecycle.State.DESTROYED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_INITIALIZED_WHEN_destroy_THEN_observers_removed() {\n        lifecycle.destroy()\n\n        platform.assertNotificationObserversEmpty()\n    }\n\n    @Test\n    fun GIVEN_state_RESUMED_WHEN_destroy_THEN_state_DESTROYED() {\n        postNotification(UIApplicationDidBecomeActiveNotification)\n\n        lifecycle.destroy()\n\n        assertEquals(Lifecycle.State.DESTROYED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_RESUMED_WHEN_destroy_THEN_observers_removed() {\n        postNotification(UIApplicationDidBecomeActiveNotification)\n\n        lifecycle.destroy()\n\n        platform.assertNotificationObserversEmpty()\n    }\n\n    @Test\n    fun GIVEN_state_STATED_WHEN_destroy_THEN_state_DESTROYED() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n\n        lifecycle.destroy()\n\n        assertEquals(Lifecycle.State.DESTROYED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_STATED_WHEN_destroy_THEN_observers_removed() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n\n        lifecycle.destroy()\n\n        platform.assertNotificationObserversEmpty()\n    }\n\n    @Test\n    fun GIVEN_state_CREATED_WHEN_destroy_THEN_state_DESTROYED() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n        postNotification(UIApplicationDidEnterBackgroundNotification)\n\n        lifecycle.destroy()\n\n        assertEquals(Lifecycle.State.DESTROYED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_CREATED_WHEN_destroy_THEN_observers_removed() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n        postNotification(UIApplicationDidEnterBackgroundNotification)\n\n        lifecycle.destroy()\n\n        platform.assertNotificationObserversEmpty()\n    }\n\n    @Test\n    fun GIVEN_state_INITIALIZED_and_applicationState_Active_WHEN_main_queue_processed_THEN_state_RESUMED() {\n        platform.applicationState = UIApplicationStateActive\n\n        platform.processMainQueue()\n\n        assertEquals(Lifecycle.State.RESUMED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_INITIALIZED_and_applicationState_Inactive_WHEN_main_queue_processed_THEN_state_STARTED() {\n        platform.applicationState = UIApplicationStateInactive\n\n        platform.processMainQueue()\n\n        assertEquals(Lifecycle.State.STARTED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_INITIALIZED_and_applicationState_Background_WHEN_main_queue_processed_THEN_state_CREATED() {\n        platform.applicationState = UIApplicationStateBackground\n\n        platform.processMainQueue()\n\n        assertEquals(Lifecycle.State.CREATED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_CREATED_and_applicationState_Active_WHEN_main_queue_processed_THEN_state_CREATED() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n        postNotification(UIApplicationDidEnterBackgroundNotification)\n        platform.applicationState = UIApplicationStateActive\n\n        platform.processMainQueue()\n\n        assertEquals(Lifecycle.State.CREATED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_CREATED_and_applicationState_Inactive_WHEN_main_queue_processed_THEN_state_CREATED() {\n        postNotification(UIApplicationWillEnterForegroundNotification)\n        postNotification(UIApplicationDidEnterBackgroundNotification)\n        platform.applicationState = UIApplicationStateInactive\n\n        platform.processMainQueue()\n\n        assertEquals(Lifecycle.State.CREATED, lifecycle.state)\n    }\n\n    @Test\n    fun GIVEN_state_RESUMED_and_applicationState_Background_WHEN_main_queue_processed_THEN_state_RESUMED() {\n        postNotification(UIApplicationDidBecomeActiveNotification)\n        platform.applicationState = UIApplicationStateBackground\n\n        platform.processMainQueue()\n\n        assertEquals(Lifecycle.State.RESUMED, lifecycle.state)\n    }\n\n    private fun postNotification(name: NSNotificationName) {\n        platform.postNotification(name = name)\n    }\n\n    private class TestPlatform : ApplicationLifecycle.Platform {\n        private val notificationObservers = HashMap<NSObjectProtocol, Pair<NSNotificationName, (NSNotification?) -> Unit>>()\n        private val mainQueue = ArrayList<() -> Unit>()\n        override var applicationState: UIApplicationState = UIApplicationStateActive\n\n        override fun addObserver(name: NSNotificationName, block: (NSNotification?) -> Unit): NSObjectProtocol {\n            val handle = NSObject()\n            notificationObservers += handle to (name to block)\n\n            return handle\n        }\n\n        override fun removeObserver(observer: NSObjectProtocol) {\n            notificationObservers -= observer\n        }\n\n        fun postNotification(name: NSNotificationName) {\n            notificationObservers.values\n                .firstOrNull { (observerName, _) -> observerName == name }\n                ?.second\n                ?.invoke(null)\n        }\n\n        fun assertNotificationObserversEmpty() {\n            assertTrue(notificationObservers.isEmpty())\n        }\n\n        override fun addOperationOnMainQueue(block: () -> Unit) {\n            mainQueue += block\n        }\n\n        fun processMainQueue() {\n            val blocks = mainQueue.toList()\n            mainQueue.clear()\n            blocks.forEach { it() }\n        }\n    }\n}\n"
  },
  {
    "path": "lifecycle-coroutines/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "lifecycle-coroutines/api/android/lifecycle-coroutines.api",
    "content": "public final class com/arkivanov/essenty/lifecycle/coroutines/CoroutineScopeWithLifecycleKt {\n\tpublic static final fun coroutineScope (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/CoroutineScope;\n\tpublic static synthetic fun coroutineScope$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lkotlin/coroutines/CoroutineContext;ILjava/lang/Object;)Lkotlinx/coroutines/CoroutineScope;\n\tpublic static final fun withLifecycle (Lkotlinx/coroutines/CoroutineScope;Lcom/arkivanov/essenty/lifecycle/Lifecycle;)Lkotlinx/coroutines/CoroutineScope;\n}\n\npublic final class com/arkivanov/essenty/lifecycle/coroutines/FlowWithLifecycleKt {\n\tpublic static final fun flowWithLifecycle (Lkotlinx/coroutines/flow/Flow;Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/flow/Flow;\n\tpublic static synthetic fun flowWithLifecycle$default (Lkotlinx/coroutines/flow/Flow;Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;\n\tpublic static final fun withLifecycle (Lkotlinx/coroutines/flow/Flow;Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/flow/Flow;\n\tpublic static synthetic fun withLifecycle$default (Lkotlinx/coroutines/flow/Flow;Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;\n}\n\npublic final class com/arkivanov/essenty/lifecycle/coroutines/RepeatOnLifecycleKt {\n\tpublic static final fun repeatOnLifecycle (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;\n\tpublic static final fun repeatOnLifecycle (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;\n\tpublic static synthetic fun repeatOnLifecycle$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;\n\tpublic static synthetic fun repeatOnLifecycle$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;\n}\n\n"
  },
  {
    "path": "lifecycle-coroutines/api/jvm/lifecycle-coroutines.api",
    "content": "public final class com/arkivanov/essenty/lifecycle/coroutines/CoroutineScopeWithLifecycleKt {\n\tpublic static final fun coroutineScope (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/CoroutineScope;\n\tpublic static synthetic fun coroutineScope$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lkotlin/coroutines/CoroutineContext;ILjava/lang/Object;)Lkotlinx/coroutines/CoroutineScope;\n\tpublic static final fun withLifecycle (Lkotlinx/coroutines/CoroutineScope;Lcom/arkivanov/essenty/lifecycle/Lifecycle;)Lkotlinx/coroutines/CoroutineScope;\n}\n\npublic final class com/arkivanov/essenty/lifecycle/coroutines/FlowWithLifecycleKt {\n\tpublic static final fun flowWithLifecycle (Lkotlinx/coroutines/flow/Flow;Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/flow/Flow;\n\tpublic static synthetic fun flowWithLifecycle$default (Lkotlinx/coroutines/flow/Flow;Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;\n\tpublic static final fun withLifecycle (Lkotlinx/coroutines/flow/Flow;Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/flow/Flow;\n\tpublic static synthetic fun withLifecycle$default (Lkotlinx/coroutines/flow/Flow;Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;\n}\n\npublic final class com/arkivanov/essenty/lifecycle/coroutines/RepeatOnLifecycleKt {\n\tpublic static final fun repeatOnLifecycle (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;\n\tpublic static final fun repeatOnLifecycle (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;\n\tpublic static synthetic fun repeatOnLifecycle$default (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;\n\tpublic static synthetic fun repeatOnLifecycle$default (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;Lcom/arkivanov/essenty/lifecycle/Lifecycle$State;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;\n}\n\n"
  },
  {
    "path": "lifecycle-coroutines/api/lifecycle-coroutines.klib.api",
    "content": "// Klib ABI Dump\n// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxX64, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, watchosArm32, watchosArm64, watchosSimulatorArm64, watchosX64]\n// Rendering settings:\n// - Signature version: 2\n// - Show manifest properties: true\n// - Show declarations: true\n\n// Library unique name: <com.arkivanov.essenty:lifecycle-coroutines>\nfinal fun (com.arkivanov.essenty.lifecycle/LifecycleOwner).com.arkivanov.essenty.lifecycle.coroutines/coroutineScope(kotlin.coroutines/CoroutineContext = ...): kotlinx.coroutines/CoroutineScope // com.arkivanov.essenty.lifecycle.coroutines/coroutineScope|coroutineScope@com.arkivanov.essenty.lifecycle.LifecycleOwner(kotlin.coroutines.CoroutineContext){}[0]\nfinal fun (kotlinx.coroutines/CoroutineScope).com.arkivanov.essenty.lifecycle.coroutines/withLifecycle(com.arkivanov.essenty.lifecycle/Lifecycle): kotlinx.coroutines/CoroutineScope // com.arkivanov.essenty.lifecycle.coroutines/withLifecycle|withLifecycle@kotlinx.coroutines.CoroutineScope(com.arkivanov.essenty.lifecycle.Lifecycle){}[0]\nfinal fun <#A: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.arkivanov.essenty.lifecycle.coroutines/flowWithLifecycle(com.arkivanov.essenty.lifecycle/Lifecycle, com.arkivanov.essenty.lifecycle/Lifecycle.State = ..., kotlin.coroutines/CoroutineContext = ...): kotlinx.coroutines.flow/Flow<#A> // com.arkivanov.essenty.lifecycle.coroutines/flowWithLifecycle|flowWithLifecycle@kotlinx.coroutines.flow.Flow<0:0>(com.arkivanov.essenty.lifecycle.Lifecycle;com.arkivanov.essenty.lifecycle.Lifecycle.State;kotlin.coroutines.CoroutineContext){0§<kotlin.Any?>}[0]\nfinal fun <#A: kotlin/Any?> (kotlinx.coroutines.flow/Flow<#A>).com.arkivanov.essenty.lifecycle.coroutines/withLifecycle(com.arkivanov.essenty.lifecycle/Lifecycle, com.arkivanov.essenty.lifecycle/Lifecycle.State = ..., kotlin.coroutines/CoroutineContext = ...): kotlinx.coroutines.flow/Flow<#A> // com.arkivanov.essenty.lifecycle.coroutines/withLifecycle|withLifecycle@kotlinx.coroutines.flow.Flow<0:0>(com.arkivanov.essenty.lifecycle.Lifecycle;com.arkivanov.essenty.lifecycle.Lifecycle.State;kotlin.coroutines.CoroutineContext){0§<kotlin.Any?>}[0]\nfinal suspend fun (com.arkivanov.essenty.lifecycle/Lifecycle).com.arkivanov.essenty.lifecycle.coroutines/repeatOnLifecycle(com.arkivanov.essenty.lifecycle/Lifecycle.State = ..., kotlin.coroutines/CoroutineContext = ..., kotlin.coroutines/SuspendFunction1<kotlinx.coroutines/CoroutineScope, kotlin/Unit>) // com.arkivanov.essenty.lifecycle.coroutines/repeatOnLifecycle|repeatOnLifecycle@com.arkivanov.essenty.lifecycle.Lifecycle(com.arkivanov.essenty.lifecycle.Lifecycle.State;kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,kotlin.Unit>){}[0]\nfinal suspend fun (com.arkivanov.essenty.lifecycle/LifecycleOwner).com.arkivanov.essenty.lifecycle.coroutines/repeatOnLifecycle(com.arkivanov.essenty.lifecycle/Lifecycle.State = ..., kotlin.coroutines/CoroutineContext = ..., kotlin.coroutines/SuspendFunction1<kotlinx.coroutines/CoroutineScope, kotlin/Unit>) // com.arkivanov.essenty.lifecycle.coroutines/repeatOnLifecycle|repeatOnLifecycle@com.arkivanov.essenty.lifecycle.LifecycleOwner(com.arkivanov.essenty.lifecycle.Lifecycle.State;kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,kotlin.Unit>){}[0]\n"
  },
  {
    "path": "lifecycle-coroutines/build.gradle.kts",
    "content": "import com.arkivanov.gradle.setupBinaryCompatibilityValidator\nimport com.arkivanov.gradle.setupMultiplatform\nimport com.arkivanov.gradle.setupPublication\nimport com.arkivanov.gradle.setupSourceSets\n\nplugins {\n    id(\"kotlin-multiplatform\")\n    id(\"com.android.library\")\n    id(\"com.arkivanov.gradle.setup\")\n}\n\nsetupMultiplatform()\nsetupPublication()\nsetupBinaryCompatibilityValidator()\n\nandroid {\n    namespace = \"com.arkivanov.essenty.lifecycle.coroutines\"\n}\n\nkotlin {\n    setupSourceSets {\n        common.main.dependencies {\n            implementation(project(\":lifecycle\"))\n            implementation(deps.kotlinx.coroutinesCore)\n        }\n\n        common.test.dependencies {\n            implementation(deps.kotlinx.coroutinesTest)\n        }\n    }\n}\n"
  },
  {
    "path": "lifecycle-coroutines/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/coroutines/CoroutineScopeWithLifecycle.kt",
    "content": "package com.arkivanov.essenty.lifecycle.coroutines\n\nimport com.arkivanov.essenty.lifecycle.Lifecycle\nimport com.arkivanov.essenty.lifecycle.LifecycleOwner\nimport com.arkivanov.essenty.lifecycle.doOnDestroy\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.cancel\nimport kotlin.coroutines.CoroutineContext\n\n/**\n * Creates and returns a new [CoroutineScope] with the specified [context].\n * The returned [CoroutineScope] is automatically cancelled when the [Lifecycle] is destroyed.\n *\n * @param context a [CoroutineContext] to be used for creating the [CoroutineScope], default\n * is [Dispatchers.Main.immediate][kotlinx.coroutines.MainCoroutineDispatcher.immediate]\n * if available on the current platform, or [Dispatchers.Main] otherwise.\n */\nfun LifecycleOwner.coroutineScope(\n    context: CoroutineContext = Dispatchers.Main.immediateOrFallback,\n): CoroutineScope =\n    CoroutineScope(context = context).withLifecycle(lifecycle)\n\n/**\n * Automatically cancels this [CoroutineScope] when the specified [lifecycle] is destroyed.\n *\n * @return the same (this) [CoroutineScope].\n */\nfun CoroutineScope.withLifecycle(lifecycle: Lifecycle): CoroutineScope {\n    lifecycle.doOnDestroy(::cancel)\n\n    return this\n}\n"
  },
  {
    "path": "lifecycle-coroutines/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/coroutines/DispatchersExt.kt",
    "content": "package com.arkivanov.essenty.lifecycle.coroutines\n\nimport kotlinx.coroutines.MainCoroutineDispatcher\nimport kotlin.concurrent.Volatile\n\n@Volatile\nprivate var isImmediateSupported: Boolean = true\n\ninternal val MainCoroutineDispatcher.immediateOrFallback: MainCoroutineDispatcher\n    get() {\n        if (isImmediateSupported) {\n            try {\n                return immediate\n            } catch (ignored: UnsupportedOperationException) {\n            } catch (ignored: NotImplementedError) {\n            }\n\n            isImmediateSupported = false\n        }\n\n        return this\n    }\n"
  },
  {
    "path": "lifecycle-coroutines/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/coroutines/FlowWithLifecycle.kt",
    "content": "package com.arkivanov.essenty.lifecycle.coroutines\n\nimport com.arkivanov.essenty.lifecycle.Lifecycle\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.flow.Flow\nimport kotlinx.coroutines.flow.callbackFlow\nimport kotlin.coroutines.CoroutineContext\n\n/**\n * [Flow] operator that emits values from this upstream [Flow] when the [lifecycle]\n * is at least at [minActiveState] state. The emissions will be stopped when the\n * [lifecycle] state falls below [minActiveState] state.\n *\n * The [Flow] is collected on the specified [context], which defaults to\n * [Dispatchers.Main.immediate][kotlinx.coroutines.MainCoroutineDispatcher.immediate]\n * if available on the current platform, or to [Dispatchers.Main] otherwise.\n *\n * See the [AndroidX documentation](https://developer.android.com/reference/kotlin/androidx/lifecycle/package-summary#(kotlinx.coroutines.flow.Flow).flowWithLifecycle(androidx.lifecycle.Lifecycle,androidx.lifecycle.Lifecycle.State))\n * for more information.\n */\nfun <T> Flow<T>.withLifecycle(\n    lifecycle: Lifecycle,\n    minActiveState: Lifecycle.State = Lifecycle.State.STARTED,\n    context: CoroutineContext = Dispatchers.Main.immediateOrFallback,\n): Flow<T> = callbackFlow {\n    lifecycle.repeatOnLifecycle(minActiveState, context) {\n        this@withLifecycle.collect {\n            send(it)\n        }\n    }\n    close()\n}\n\n@Deprecated(\n    message = \"Use 'withLifecycle' instead\",\n    replaceWith = ReplaceWith(\"withLifecycle(lifecycle, minActiveState)\"),\n    level = DeprecationLevel.ERROR\n)\nfun <T> Flow<T>.flowWithLifecycle(\n    lifecycle: Lifecycle,\n    minActiveState: Lifecycle.State = Lifecycle.State.STARTED,\n    context: CoroutineContext = Dispatchers.Main.immediateOrFallback,\n): Flow<T> {\n    return withLifecycle(lifecycle, minActiveState, context)\n}\n"
  },
  {
    "path": "lifecycle-coroutines/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/coroutines/RepeatOnLifecycle.kt",
    "content": "package com.arkivanov.essenty.lifecycle.coroutines\n\nimport com.arkivanov.essenty.lifecycle.Lifecycle\nimport com.arkivanov.essenty.lifecycle.LifecycleOwner\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.Job\nimport kotlinx.coroutines.coroutineScope\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.suspendCancellableCoroutine\nimport kotlinx.coroutines.sync.Mutex\nimport kotlinx.coroutines.sync.withLock\nimport kotlinx.coroutines.withContext\nimport kotlin.coroutines.CoroutineContext\nimport kotlin.coroutines.resume\n\n/**\n * Convenience method for [Lifecycle.repeatOnLifecycle].\n */\nsuspend fun LifecycleOwner.repeatOnLifecycle(\n    minActiveState: Lifecycle.State = Lifecycle.State.STARTED,\n    context: CoroutineContext = Dispatchers.Main.immediateOrFallback,\n    block: suspend CoroutineScope.() -> Unit,\n) {\n    lifecycle.repeatOnLifecycle(minActiveState = minActiveState, context = context, block = block)\n}\n\n/**\n * Runs the given [block] in a new coroutine when this [Lifecycle] is at least at [minActiveState] and suspends\n * the execution until this [Lifecycle] is [Lifecycle.State.DESTROYED].\n *\n * The [block] will cancel and re-launch as the [Lifecycle] moves in and out of the [minActiveState].\n *\n * The [block] is called on the specified [context], which defaults to\n * [Dispatchers.Main.immediate][kotlinx.coroutines.MainCoroutineDispatcher.immediate]\n * if available on the current platform, or to [Dispatchers.Main] otherwise.\n *\n * See the [AndroidX documentation](https://developer.android.com/reference/kotlin/androidx/lifecycle/package-summary#(androidx.lifecycle.Lifecycle).repeatOnLifecycle(androidx.lifecycle.Lifecycle.State,kotlin.coroutines.SuspendFunction1))\n * for more information.\n */\nsuspend fun Lifecycle.repeatOnLifecycle(\n    minActiveState: Lifecycle.State = Lifecycle.State.STARTED,\n    context: CoroutineContext = Dispatchers.Main.immediateOrFallback,\n    block: suspend CoroutineScope.() -> Unit\n) {\n    require(minActiveState != Lifecycle.State.INITIALIZED) {\n        \"repeatOnEssentyLifecycle cannot start work with the INITIALIZED lifecycle state.\"\n    }\n\n    if (this.state == Lifecycle.State.DESTROYED) {\n        return\n    }\n\n    coroutineScope {\n        withContext(context) {\n            if (this@repeatOnLifecycle.state == Lifecycle.State.DESTROYED) {\n                return@withContext\n            }\n\n            var callback: Lifecycle.Callbacks? = null\n            var job: Job? = null\n            val mutex = Mutex()\n\n            try {\n                suspendCancellableCoroutine { cont ->\n                    callback = createLifecycleAwareCallback(\n                        startState = minActiveState,\n                        onStateAppear = {\n                            job = launch {\n                                mutex.withLock {\n                                    block()\n                                }\n                            }\n                        },\n                        onStateDisappear = {\n                            job?.cancel()\n                            job = null\n                        },\n                        onDestroy = {\n                            cont.resume(Unit)\n                        },\n                    )\n\n                    this@repeatOnLifecycle.subscribe(requireNotNull(callback))\n                }\n            } finally {\n                job?.cancel()\n                job = null\n                callback?.let {\n                    this@repeatOnLifecycle.unsubscribe(it)\n                }\n                callback = null\n            }\n        }\n    }\n}\n\n/**\n * Creates lifecycle aware [Lifecycle.Callbacks] interface instance.\n *\n * @param startState [Lifecycle.State] that [onStateAppear] block must be called from\n * @param onStateAppear block of code that will be executed when the [Lifecycle.State] was equal [startState]\n * @param onStateDisappear block of code that will be executed when the [Lifecycle.State] was equal to opposite [startState]\n * @param onDestroy block of code that will be executed when the [Lifecycle.State] was equal [Lifecycle.State.DESTROYED]\n *\n * @return [Lifecycle.Callbacks]\n */\nprivate fun createLifecycleAwareCallback(\n    startState: Lifecycle.State,\n    onStateAppear: () -> Unit,\n    onStateDisappear: () -> Unit,\n    onDestroy: () -> Unit,\n): Lifecycle.Callbacks = object : Lifecycle.Callbacks {\n\n    override fun onCreate() {\n        launchIfState(Lifecycle.State.CREATED)\n    }\n\n    override fun onStart() {\n        launchIfState(Lifecycle.State.STARTED)\n    }\n\n    override fun onResume() {\n        launchIfState(Lifecycle.State.RESUMED)\n    }\n\n    override fun onPause() {\n        closeIfState(Lifecycle.State.RESUMED)\n    }\n\n    override fun onStop() {\n        closeIfState(Lifecycle.State.STARTED)\n    }\n\n    override fun onDestroy() {\n        closeIfState(Lifecycle.State.CREATED)\n        onDestroy()\n    }\n\n    private fun launchIfState(state: Lifecycle.State) {\n        if (startState == state) {\n            onStateAppear()\n        }\n    }\n\n    private fun closeIfState(state: Lifecycle.State) {\n        if (startState == state) {\n            onStateDisappear()\n        }\n    }\n}\n"
  },
  {
    "path": "lifecycle-coroutines/src/commonTest/kotlin/com/arkivanov/essenty/lifecycle/coroutines/CoroutineScopeWithLifecycleTest.kt",
    "content": "package com.arkivanov.essenty.lifecycle.coroutines\n\nimport com.arkivanov.essenty.lifecycle.LifecycleRegistry\nimport com.arkivanov.essenty.lifecycle.create\nimport com.arkivanov.essenty.lifecycle.destroy\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.isActive\nimport kotlinx.coroutines.test.StandardTestDispatcher\nimport kotlin.test.Test\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass CoroutineScopeWithLifecycleTest {\n\n    @Test\n    fun GIVEN_lifecycle_not_destroyed_WHEN_scope_created_THEN_scope_is_active() {\n        val lifecycle = LifecycleRegistry()\n\n        val scope = CoroutineScope(StandardTestDispatcher()).withLifecycle(lifecycle)\n\n        assertTrue(scope.isActive)\n    }\n\n    @Test\n    fun GIVEN_lifecycle_destroyed_WHEN_scope_created_THEN_scope_is_not_active() {\n        val lifecycle = LifecycleRegistry()\n        lifecycle.create()\n        lifecycle.destroy()\n\n        val scope = CoroutineScope(StandardTestDispatcher()).withLifecycle(lifecycle)\n\n        assertFalse(scope.isActive)\n    }\n\n    @Test\n    fun WHEN_lifecycle_destroyed_THEN_scope_is_not_active() {\n        val lifecycle = LifecycleRegistry()\n        val scope = CoroutineScope(StandardTestDispatcher()).withLifecycle(lifecycle)\n        lifecycle.create()\n\n        lifecycle.destroy()\n\n        assertFalse(scope.isActive)\n    }\n}\n"
  },
  {
    "path": "lifecycle-coroutines/src/commonTest/kotlin/com/arkivanov/essenty/lifecycle/coroutines/DispatchersExtTest.kt",
    "content": "package com.arkivanov.essenty.lifecycle.coroutines\n\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.test.StandardTestDispatcher\nimport kotlinx.coroutines.test.TestDispatcher\nimport kotlinx.coroutines.test.resetMain\nimport kotlinx.coroutines.test.setMain\nimport kotlin.test.*\n\n@OptIn(ExperimentalCoroutinesApi::class)\n@Suppress(\"TestFunctionName\")\nclass DispatchersExtTest {\n\n    @AfterTest\n    fun after() {\n        Dispatchers.resetMain()\n    }\n\n    @Test\n    fun WHEN_immediateOrDefault_called_multiple_times_THEN_returns_same_dispatcher() {\n        val dispatcher1 = Dispatchers.Main.immediateOrFallback\n        val dispatcher2 = Dispatchers.Main.immediateOrFallback\n\n        assertSame(dispatcher1, dispatcher2)\n    }\n\n    @Test\n    fun GIVEN_Main_dispatcher_changed_WHEN_immediateOrDefault_called_THEN_returns_updated_dispatcher() {\n        try {\n            Dispatchers.Main.immediate\n        } catch (e: NotImplementedError) {\n            return // Only test on platforms where Main dispatcher is supported\n        }\n\n        val oldDispatcher = Dispatchers.Main.immediateOrFallback\n        val testDispatcher = StandardTestDispatcher()\n        Dispatchers.setMain(testDispatcher)\n\n        val newDispatcher = Dispatchers.Main.immediateOrFallback\n\n        assertNotSame(oldDispatcher, newDispatcher)\n    }\n}\n"
  },
  {
    "path": "lifecycle-coroutines/src/commonTest/kotlin/com/arkivanov/essenty/lifecycle/coroutines/LifecycleCoroutinesExtTest.kt",
    "content": "package com.arkivanov.essenty.lifecycle.coroutines\n\nimport com.arkivanov.essenty.lifecycle.Lifecycle\nimport com.arkivanov.essenty.lifecycle.LifecycleRegistry\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.coroutineScope\nimport kotlinx.coroutines.flow.flow\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.test.StandardTestDispatcher\nimport kotlinx.coroutines.test.advanceUntilIdle\nimport kotlinx.coroutines.test.resetMain\nimport kotlinx.coroutines.test.runTest\nimport kotlinx.coroutines.test.setMain\nimport kotlinx.coroutines.yield\nimport kotlin.test.AfterTest\nimport kotlin.test.BeforeTest\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\n@OptIn(ExperimentalCoroutinesApi::class)\nclass LifecycleCoroutinesExtTest {\n\n    private val testDispatcher = StandardTestDispatcher()\n    private val registry = LifecycleRegistry(initialState = Lifecycle.State.INITIALIZED)\n\n    @BeforeTest\n    fun beforeTesting() {\n        Dispatchers.setMain(testDispatcher)\n    }\n\n    @AfterTest\n    fun afterTesting() {\n        Dispatchers.resetMain()\n    }\n\n    @Test\n    fun test_passed_state_CREATED_must_be_trigger_block_once() = runTest {\n        val state = Lifecycle.State.CREATED\n        val expected = listOf(state)\n\n        val actual = executeRepeatOnEssentyLifecycleTest(state)\n        advanceUntilIdle()\n\n        assertEquals(expected, actual)\n    }\n\n    @Test\n    fun test_passed_state_STARTED_must_be_trigger_block_twice() = runTest {\n        val state = Lifecycle.State.STARTED\n        val expected = listOf(state, state)\n\n        val actual = executeRepeatOnEssentyLifecycleTest(state)\n        advanceUntilIdle()\n\n        assertEquals(expected, actual)\n    }\n\n    @Test\n    fun test_passed_state_RESUMED_must_be_trigger_block_twice() = runTest {\n        val state = Lifecycle.State.RESUMED\n        val expected = listOf(state, state)\n\n        val actual = executeRepeatOnEssentyLifecycleTest(state)\n        advanceUntilIdle()\n\n        assertEquals(expected, actual)\n    }\n\n    @Test\n    fun test_passed_state_DESTROYED_must_not_be_trigger_block() = runTest {\n        val state = Lifecycle.State.DESTROYED\n        val expected = emptyList<Lifecycle.State>()\n\n        val actual = executeRepeatOnEssentyLifecycleTest(state)\n        advanceUntilIdle()\n\n        assertEquals(expected, actual)\n    }\n\n    @Test\n    fun test_flow_passed_state_CREATED_must_be_trigger_block_once() = runTest {\n        val state = Lifecycle.State.CREATED\n        val expect = listOf(state, state)\n\n        val actual = executeFlowWithEssentyLifecycleTest(state)\n        advanceUntilIdle()\n\n        assertEquals(expect, actual)\n    }\n\n    @Test\n    fun test_flow_passed_state_STARTED_must_be_trigger_block_twice() = runTest {\n        val state = Lifecycle.State.STARTED\n        val expect = listOf(state, state, state, state)\n\n        val actual = executeFlowWithEssentyLifecycleTest(state)\n        advanceUntilIdle()\n\n        assertEquals(expect, actual)\n    }\n\n    @Test\n    fun test_flow_passed_state_RESUMED_must_be_trigger_block_twice() = runTest {\n        val state = Lifecycle.State.RESUMED\n        val expect = listOf(state, state, state, state)\n\n        val actual = executeFlowWithEssentyLifecycleTest(state)\n        advanceUntilIdle()\n\n        assertEquals(expect, actual)\n    }\n\n    @Test\n    fun test_flow_passed_state_DESTROYED_must_not_be_trigger_block() = runTest {\n        val state = Lifecycle.State.DESTROYED\n        val expect = emptyList<Lifecycle.State>()\n\n        val actual = executeFlowWithEssentyLifecycleTest(state)\n        advanceUntilIdle()\n\n        assertEquals(expect, actual)\n    }\n\n    private suspend fun executeRepeatOnEssentyLifecycleTest(\n        lifecycleState: Lifecycle.State\n    ): List<Lifecycle.State> = coroutineScope {\n        val events = ArrayList<Lifecycle.State>()\n\n        launch {\n            registry.repeatOnLifecycle(\n                minActiveState = lifecycleState,\n                context = testDispatcher\n            ) {\n                events.add(lifecycleState)\n            }\n        }\n\n        registry.onCreate()\n        yield()\n        registry.onStart()\n        yield()\n        registry.onResume()\n        yield()\n        registry.onPause()\n        yield()\n        registry.onStop()\n        yield()\n        registry.onStart()\n        yield()\n        registry.onResume()\n        yield()\n        registry.onPause()\n        yield()\n        registry.onStop()\n        yield()\n        registry.onDestroy()\n\n        return@coroutineScope events\n    }\n\n    private suspend fun executeFlowWithEssentyLifecycleTest(\n        lifecycleState: Lifecycle.State\n    ): List<Lifecycle.State> = coroutineScope {\n        val actual = ArrayList<Lifecycle.State>()\n\n        launch {\n            flow {\n                repeat(2) { emit(lifecycleState) }\n            }\n                .withLifecycle(registry, lifecycleState, testDispatcher)\n                .collect { actual.add(it) }\n        }\n\n\n        registry.onCreate()\n        yield()\n        registry.onStart()\n        yield()\n        registry.onResume()\n        yield()\n        yield()\n        registry.onPause()\n        yield()\n        registry.onStop()\n        yield()\n        registry.onStart()\n        yield()\n        registry.onResume()\n        yield()\n        registry.onPause()\n        yield()\n        registry.onStop()\n        yield()\n        registry.onDestroy()\n\n        return@coroutineScope actual\n    }\n}\n"
  },
  {
    "path": "lifecycle-reaktive/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "lifecycle-reaktive/api/android/lifecycle-reaktive.api",
    "content": "public final class com/arkivanov/essenty/lifecycle/reaktive/DisposableWithLifecycleKt {\n\tpublic static final fun disposableScope (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;)Lcom/badoo/reaktive/disposable/scope/DisposableScope;\n\tpublic static final fun withLifecycle (Lcom/badoo/reaktive/disposable/Disposable;Lcom/arkivanov/essenty/lifecycle/Lifecycle;)Lcom/badoo/reaktive/disposable/Disposable;\n}\n\n"
  },
  {
    "path": "lifecycle-reaktive/api/jvm/lifecycle-reaktive.api",
    "content": "public final class com/arkivanov/essenty/lifecycle/reaktive/DisposableWithLifecycleKt {\n\tpublic static final fun disposableScope (Lcom/arkivanov/essenty/lifecycle/LifecycleOwner;)Lcom/badoo/reaktive/disposable/scope/DisposableScope;\n\tpublic static final fun withLifecycle (Lcom/badoo/reaktive/disposable/Disposable;Lcom/arkivanov/essenty/lifecycle/Lifecycle;)Lcom/badoo/reaktive/disposable/Disposable;\n}\n\n"
  },
  {
    "path": "lifecycle-reaktive/api/lifecycle-reaktive.klib.api",
    "content": "// Klib ABI Dump\n// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxX64, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, watchosArm32, watchosArm64, watchosSimulatorArm64, watchosX64]\n// Rendering settings:\n// - Signature version: 2\n// - Show manifest properties: true\n// - Show declarations: true\n\n// Library unique name: <com.arkivanov.essenty:lifecycle-reaktive>\nfinal fun (com.arkivanov.essenty.lifecycle/LifecycleOwner).com.arkivanov.essenty.lifecycle.reaktive/disposableScope(): com.badoo.reaktive.disposable.scope/DisposableScope // com.arkivanov.essenty.lifecycle.reaktive/disposableScope|disposableScope@com.arkivanov.essenty.lifecycle.LifecycleOwner(){}[0]\nfinal fun <#A: com.badoo.reaktive.disposable/Disposable> (#A).com.arkivanov.essenty.lifecycle.reaktive/withLifecycle(com.arkivanov.essenty.lifecycle/Lifecycle): #A // com.arkivanov.essenty.lifecycle.reaktive/withLifecycle|withLifecycle@0:0(com.arkivanov.essenty.lifecycle.Lifecycle){0§<com.badoo.reaktive.disposable.Disposable>}[0]\n"
  },
  {
    "path": "lifecycle-reaktive/build.gradle.kts",
    "content": "import com.arkivanov.gradle.setupBinaryCompatibilityValidator\nimport com.arkivanov.gradle.setupMultiplatform\nimport com.arkivanov.gradle.setupPublication\nimport com.arkivanov.gradle.setupSourceSets\n\nplugins {\n    id(\"kotlin-multiplatform\")\n    id(\"com.android.library\")\n    id(\"com.arkivanov.gradle.setup\")\n}\n\nsetupMultiplatform()\nsetupPublication()\nsetupBinaryCompatibilityValidator()\n\nandroid {\n    namespace = \"com.arkivanov.essenty.lifecycle.reaktive\"\n}\n\nkotlin {\n    setupSourceSets {\n        common.main.dependencies {\n            implementation(project(\":lifecycle\"))\n            implementation(deps.reaktive.reaktive)\n        }\n    }\n}\n"
  },
  {
    "path": "lifecycle-reaktive/src/commonMain/kotlin/com/arkivanov/essenty/lifecycle/reaktive/DisposableWithLifecycle.kt",
    "content": "package com.arkivanov.essenty.lifecycle.reaktive\n\nimport com.arkivanov.essenty.lifecycle.Lifecycle\nimport com.arkivanov.essenty.lifecycle.LifecycleOwner\nimport com.arkivanov.essenty.lifecycle.doOnDestroy\nimport com.badoo.reaktive.disposable.Disposable\nimport com.badoo.reaktive.disposable.scope.DisposableScope\n\n/**\n * Creates and returns a new [DisposableScope], which is automatically\n * disposed when the [Lifecycle] is destroyed.\n */\nfun LifecycleOwner.disposableScope(): DisposableScope =\n    DisposableScope().withLifecycle(lifecycle)\n\n/**\n * Automatically disposes this [Disposable] when the specified [lifecycle] is destroyed.\n *\n * @return the same (this) [Disposable].\n */\nfun <T : Disposable> T.withLifecycle(lifecycle: Lifecycle): T {\n    lifecycle.doOnDestroy(::dispose)\n\n    return this\n}\n"
  },
  {
    "path": "lifecycle-reaktive/src/commonTest/kotlin/com/arkivanov/essenty/lifecycle/reaktive/DisposableWithLifecycleTest.kt",
    "content": "package com.arkivanov.essenty.lifecycle.reaktive\n\nimport com.arkivanov.essenty.lifecycle.LifecycleRegistry\nimport com.arkivanov.essenty.lifecycle.create\nimport com.arkivanov.essenty.lifecycle.destroy\nimport com.badoo.reaktive.disposable.Disposable\nimport kotlin.test.Test\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass DisposableWithLifecycleTest {\n\n    @Test\n    fun GIVEN_lifecycle_not_destroyed_WHEN_disposable_created_THEN_disposable_is_not_disposed() {\n        val lifecycle = LifecycleRegistry()\n\n        val disposable = Disposable().withLifecycle(lifecycle)\n\n        assertFalse(disposable.isDisposed)\n    }\n\n    @Test\n    fun GIVEN_lifecycle_destroyed_WHEN_disposable_created_THEN_disposable_is_disposed() {\n        val lifecycle = LifecycleRegistry()\n        lifecycle.create()\n        lifecycle.destroy()\n\n        val scope = Disposable().withLifecycle(lifecycle)\n\n        assertTrue(scope.isDisposed)\n    }\n\n    @Test\n    fun WHEN_lifecycle_destroyed_THEN_disposable_is_disposed() {\n        val lifecycle = LifecycleRegistry()\n        val scope = Disposable().withLifecycle(lifecycle)\n        lifecycle.create()\n\n        lifecycle.destroy()\n\n        assertTrue(scope.isDisposed)\n    }\n}\n"
  },
  {
    "path": "settings.gradle.kts",
    "content": "dependencyResolutionManagement {\n    versionCatalogs {\n        create(\"deps\") {\n            from(files(\"deps.versions.toml\"))\n        }\n    }\n}\n\npluginManagement {\n    repositories {\n        gradlePluginPortal()\n        maven(\"https://jitpack.io\")\n    }\n\n    resolutionStrategy {\n        eachPlugin {\n            if (requested.id.toString() == \"com.arkivanov.gradle.setup\") {\n                useModule(\"com.github.arkivanov:gradle-setup-plugin:4ae41e7b6a\")\n            }\n        }\n    }\n\n    plugins {\n        id(\"com.arkivanov.gradle.setup\")\n    }\n}\n\nif (!startParameter.projectProperties.containsKey(\"check_publication\")) {\n    include(\":utils-internal\")\n    include(\":lifecycle\")\n    include(\":lifecycle-coroutines\")\n    include(\":lifecycle-reaktive\")\n    include(\":state-keeper\")\n    include(\":state-keeper-benchmarks\")\n    include(\":instance-keeper\")\n    include(\":back-handler\")\n} else {\n    include(\":tools:check-publication\")\n}\n"
  },
  {
    "path": "state-keeper/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "state-keeper/api/android/state-keeper.api",
    "content": "public final class com/arkivanov/essenty/statekeeper/AndroidExtKt {\n\tpublic static final fun StateKeeper (Landroidx/savedstate/SavedStateRegistry;Ljava/lang/String;ZLkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/statekeeper/StateKeeper;\n\tpublic static final fun StateKeeper (Landroidx/savedstate/SavedStateRegistry;ZLkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/statekeeper/StateKeeper;\n\tpublic static synthetic fun StateKeeper$default (Landroidx/savedstate/SavedStateRegistry;Ljava/lang/String;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/essenty/statekeeper/StateKeeper;\n\tpublic static synthetic fun StateKeeper$default (Landroidx/savedstate/SavedStateRegistry;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/essenty/statekeeper/StateKeeper;\n\tpublic static final fun stateKeeper (Landroidx/savedstate/SavedStateRegistryOwner;Ljava/lang/String;ZLkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/statekeeper/StateKeeper;\n\tpublic static final fun stateKeeper (Landroidx/savedstate/SavedStateRegistryOwner;ZLkotlin/jvm/functions/Function0;)Lcom/arkivanov/essenty/statekeeper/StateKeeper;\n\tpublic static synthetic fun stateKeeper$default (Landroidx/savedstate/SavedStateRegistryOwner;Ljava/lang/String;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/essenty/statekeeper/StateKeeper;\n\tpublic static synthetic fun stateKeeper$default (Landroidx/savedstate/SavedStateRegistryOwner;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/arkivanov/essenty/statekeeper/StateKeeper;\n}\n\npublic final class com/arkivanov/essenty/statekeeper/BundleExtKt {\n\tpublic static final fun getSerializable (Landroid/os/Bundle;Ljava/lang/String;Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object;\n\tpublic static final fun getSerializableContainer (Landroid/os/Bundle;Ljava/lang/String;)Lcom/arkivanov/essenty/statekeeper/SerializableContainer;\n\tpublic static final fun putSerializable (Landroid/os/Bundle;Ljava/lang/String;Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)V\n\tpublic static final fun putSerializableContainer (Landroid/os/Bundle;Ljava/lang/String;Lcom/arkivanov/essenty/statekeeper/SerializableContainer;)V\n}\n\npublic abstract interface annotation class com/arkivanov/essenty/statekeeper/ExperimentalStateKeeperApi : java/lang/annotation/Annotation {\n}\n\npublic final class com/arkivanov/essenty/statekeeper/PersistableBundleExtKt {\n\tpublic static final fun getSerializable (Landroid/os/PersistableBundle;Ljava/lang/String;Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object;\n\tpublic static final fun getSerializableContainer (Landroid/os/PersistableBundle;Ljava/lang/String;)Lcom/arkivanov/essenty/statekeeper/SerializableContainer;\n\tpublic static final fun putSerializable (Landroid/os/PersistableBundle;Ljava/lang/String;Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)V\n\tpublic static final fun putSerializableContainer (Landroid/os/PersistableBundle;Ljava/lang/String;Lcom/arkivanov/essenty/statekeeper/SerializableContainer;)V\n}\n\npublic final class com/arkivanov/essenty/statekeeper/PolymorphicSerializerKt {\n\tpublic static final fun polymorphicSerializer (Lkotlin/reflect/KClass;Lkotlinx/serialization/modules/SerializersModule;)Lkotlinx/serialization/KSerializer;\n}\n\npublic final class com/arkivanov/essenty/statekeeper/SerializableContainer {\n\tpublic static final field Companion Lcom/arkivanov/essenty/statekeeper/SerializableContainer$Companion;\n\tpublic fun <init> ()V\n\tpublic synthetic fun <init> ([BLkotlin/jvm/internal/DefaultConstructorMarker;)V\n\tpublic final fun clear ()V\n\tpublic final fun consume (Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object;\n\tpublic final fun set (Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)V\n}\n\npublic final class com/arkivanov/essenty/statekeeper/SerializableContainer$Companion {\n\tpublic final fun serializer ()Lkotlinx/serialization/KSerializer;\n}\n\npublic final class com/arkivanov/essenty/statekeeper/SerializableContainerKt {\n\tpublic static final fun SerializableContainer (Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)Lcom/arkivanov/essenty/statekeeper/SerializableContainer;\n\tpublic static final fun consumeRequired (Lcom/arkivanov/essenty/statekeeper/SerializableContainer;Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object;\n}\n\npublic abstract interface class com/arkivanov/essenty/statekeeper/StateKeeper {\n\tpublic abstract fun consume (Ljava/lang/String;Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object;\n\tpublic abstract fun isRegistered (Ljava/lang/String;)Z\n\tpublic abstract fun register (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Lkotlin/jvm/functions/Function0;)V\n\tpublic abstract fun unregister (Ljava/lang/String;)V\n}\n\npublic abstract interface class com/arkivanov/essenty/statekeeper/StateKeeperDispatcher : com/arkivanov/essenty/statekeeper/StateKeeper {\n\tpublic abstract fun save ()Lcom/arkivanov/essenty/statekeeper/SerializableContainer;\n}\n\npublic final class com/arkivanov/essenty/statekeeper/StateKeeperDispatcherKt {\n\tpublic static final fun StateKeeperDispatcher (Lcom/arkivanov/essenty/statekeeper/SerializableContainer;)Lcom/arkivanov/essenty/statekeeper/StateKeeperDispatcher;\n\tpublic static synthetic fun StateKeeperDispatcher$default (Lcom/arkivanov/essenty/statekeeper/SerializableContainer;ILjava/lang/Object;)Lcom/arkivanov/essenty/statekeeper/StateKeeperDispatcher;\n}\n\npublic final class com/arkivanov/essenty/statekeeper/StateKeeperExtKt {\n\tpublic static final fun saveable (Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lkotlinx/serialization/KSerializer;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun saveable (Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun saveable (Lcom/arkivanov/essenty/statekeeper/StateKeeperOwner;Lkotlinx/serialization/KSerializer;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun saveable (Lcom/arkivanov/essenty/statekeeper/StateKeeperOwner;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun saveable$default (Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lkotlinx/serialization/KSerializer;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun saveable$default (Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun saveable$default (Lcom/arkivanov/essenty/statekeeper/StateKeeperOwner;Lkotlinx/serialization/KSerializer;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun saveable$default (Lcom/arkivanov/essenty/statekeeper/StateKeeperOwner;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n}\n\npublic abstract interface class com/arkivanov/essenty/statekeeper/StateKeeperOwner {\n\tpublic abstract fun getStateKeeper ()Lcom/arkivanov/essenty/statekeeper/StateKeeper;\n}\n\n"
  },
  {
    "path": "state-keeper/api/jvm/state-keeper.api",
    "content": "public abstract interface annotation class com/arkivanov/essenty/statekeeper/ExperimentalStateKeeperApi : java/lang/annotation/Annotation {\n}\n\npublic final class com/arkivanov/essenty/statekeeper/PolymorphicSerializerKt {\n\tpublic static final fun polymorphicSerializer (Lkotlin/reflect/KClass;Lkotlinx/serialization/modules/SerializersModule;)Lkotlinx/serialization/KSerializer;\n}\n\npublic final class com/arkivanov/essenty/statekeeper/SerializableContainer {\n\tpublic static final field Companion Lcom/arkivanov/essenty/statekeeper/SerializableContainer$Companion;\n\tpublic fun <init> ()V\n\tpublic synthetic fun <init> ([BLkotlin/jvm/internal/DefaultConstructorMarker;)V\n\tpublic final fun clear ()V\n\tpublic final fun consume (Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object;\n\tpublic final fun set (Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)V\n}\n\npublic final class com/arkivanov/essenty/statekeeper/SerializableContainer$Companion {\n\tpublic final fun serializer ()Lkotlinx/serialization/KSerializer;\n}\n\npublic final class com/arkivanov/essenty/statekeeper/SerializableContainerKt {\n\tpublic static final fun SerializableContainer (Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)Lcom/arkivanov/essenty/statekeeper/SerializableContainer;\n\tpublic static final fun consumeRequired (Lcom/arkivanov/essenty/statekeeper/SerializableContainer;Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object;\n}\n\npublic abstract interface class com/arkivanov/essenty/statekeeper/StateKeeper {\n\tpublic abstract fun consume (Ljava/lang/String;Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object;\n\tpublic abstract fun isRegistered (Ljava/lang/String;)Z\n\tpublic abstract fun register (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Lkotlin/jvm/functions/Function0;)V\n\tpublic abstract fun unregister (Ljava/lang/String;)V\n}\n\npublic abstract interface class com/arkivanov/essenty/statekeeper/StateKeeperDispatcher : com/arkivanov/essenty/statekeeper/StateKeeper {\n\tpublic abstract fun save ()Lcom/arkivanov/essenty/statekeeper/SerializableContainer;\n}\n\npublic final class com/arkivanov/essenty/statekeeper/StateKeeperDispatcherKt {\n\tpublic static final fun StateKeeperDispatcher (Lcom/arkivanov/essenty/statekeeper/SerializableContainer;)Lcom/arkivanov/essenty/statekeeper/StateKeeperDispatcher;\n\tpublic static synthetic fun StateKeeperDispatcher$default (Lcom/arkivanov/essenty/statekeeper/SerializableContainer;ILjava/lang/Object;)Lcom/arkivanov/essenty/statekeeper/StateKeeperDispatcher;\n}\n\npublic final class com/arkivanov/essenty/statekeeper/StateKeeperExtKt {\n\tpublic static final fun saveable (Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lkotlinx/serialization/KSerializer;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun saveable (Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun saveable (Lcom/arkivanov/essenty/statekeeper/StateKeeperOwner;Lkotlinx/serialization/KSerializer;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static final fun saveable (Lcom/arkivanov/essenty/statekeeper/StateKeeperOwner;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun saveable$default (Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lkotlinx/serialization/KSerializer;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun saveable$default (Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun saveable$default (Lcom/arkivanov/essenty/statekeeper/StateKeeperOwner;Lkotlinx/serialization/KSerializer;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n\tpublic static synthetic fun saveable$default (Lcom/arkivanov/essenty/statekeeper/StateKeeperOwner;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/PropertyDelegateProvider;\n}\n\npublic abstract interface class com/arkivanov/essenty/statekeeper/StateKeeperOwner {\n\tpublic abstract fun getStateKeeper ()Lcom/arkivanov/essenty/statekeeper/StateKeeper;\n}\n\n"
  },
  {
    "path": "state-keeper/api/state-keeper.klib.api",
    "content": "// Klib ABI Dump\n// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxX64, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, wasmJs, watchosArm32, watchosArm64, watchosSimulatorArm64, watchosX64]\n// Rendering settings:\n// - Signature version: 2\n// - Show manifest properties: true\n// - Show declarations: true\n\n// Library unique name: <com.arkivanov.essenty:state-keeper>\nopen annotation class com.arkivanov.essenty.statekeeper/ExperimentalStateKeeperApi : kotlin/Annotation { // com.arkivanov.essenty.statekeeper/ExperimentalStateKeeperApi|null[0]\n    constructor <init>() // com.arkivanov.essenty.statekeeper/ExperimentalStateKeeperApi.<init>|<init>(){}[0]\n}\n\nabstract interface com.arkivanov.essenty.statekeeper/StateKeeper { // com.arkivanov.essenty.statekeeper/StateKeeper|null[0]\n    abstract fun <#A1: kotlin/Any> consume(kotlin/String, kotlinx.serialization/DeserializationStrategy<#A1>): #A1? // com.arkivanov.essenty.statekeeper/StateKeeper.consume|consume(kotlin.String;kotlinx.serialization.DeserializationStrategy<0:0>){0§<kotlin.Any>}[0]\n    abstract fun <#A1: kotlin/Any> register(kotlin/String, kotlinx.serialization/SerializationStrategy<#A1>, kotlin/Function0<#A1?>) // com.arkivanov.essenty.statekeeper/StateKeeper.register|register(kotlin.String;kotlinx.serialization.SerializationStrategy<0:0>;kotlin.Function0<0:0?>){0§<kotlin.Any>}[0]\n    abstract fun isRegistered(kotlin/String): kotlin/Boolean // com.arkivanov.essenty.statekeeper/StateKeeper.isRegistered|isRegistered(kotlin.String){}[0]\n    abstract fun unregister(kotlin/String) // com.arkivanov.essenty.statekeeper/StateKeeper.unregister|unregister(kotlin.String){}[0]\n}\n\nabstract interface com.arkivanov.essenty.statekeeper/StateKeeperDispatcher : com.arkivanov.essenty.statekeeper/StateKeeper { // com.arkivanov.essenty.statekeeper/StateKeeperDispatcher|null[0]\n    abstract fun save(): com.arkivanov.essenty.statekeeper/SerializableContainer // com.arkivanov.essenty.statekeeper/StateKeeperDispatcher.save|save(){}[0]\n}\n\nabstract interface com.arkivanov.essenty.statekeeper/StateKeeperOwner { // com.arkivanov.essenty.statekeeper/StateKeeperOwner|null[0]\n    abstract val stateKeeper // com.arkivanov.essenty.statekeeper/StateKeeperOwner.stateKeeper|{}stateKeeper[0]\n        abstract fun <get-stateKeeper>(): com.arkivanov.essenty.statekeeper/StateKeeper // com.arkivanov.essenty.statekeeper/StateKeeperOwner.stateKeeper.<get-stateKeeper>|<get-stateKeeper>(){}[0]\n}\n\nfinal class com.arkivanov.essenty.statekeeper/SerializableContainer { // com.arkivanov.essenty.statekeeper/SerializableContainer|null[0]\n    constructor <init>() // com.arkivanov.essenty.statekeeper/SerializableContainer.<init>|<init>(){}[0]\n\n    final fun <#A1: kotlin/Any> consume(kotlinx.serialization/DeserializationStrategy<#A1>): #A1? // com.arkivanov.essenty.statekeeper/SerializableContainer.consume|consume(kotlinx.serialization.DeserializationStrategy<0:0>){0§<kotlin.Any>}[0]\n    final fun <#A1: kotlin/Any> set(#A1?, kotlinx.serialization/SerializationStrategy<#A1>) // com.arkivanov.essenty.statekeeper/SerializableContainer.set|set(0:0?;kotlinx.serialization.SerializationStrategy<0:0>){0§<kotlin.Any>}[0]\n    final fun clear() // com.arkivanov.essenty.statekeeper/SerializableContainer.clear|clear(){}[0]\n\n    final object Companion { // com.arkivanov.essenty.statekeeper/SerializableContainer.Companion|null[0]\n        final fun serializer(): kotlinx.serialization/KSerializer<com.arkivanov.essenty.statekeeper/SerializableContainer> // com.arkivanov.essenty.statekeeper/SerializableContainer.Companion.serializer|serializer(){}[0]\n    }\n}\n\nfinal fun <#A: kotlin/Any> (com.arkivanov.essenty.statekeeper/SerializableContainer).com.arkivanov.essenty.statekeeper/consumeRequired(kotlinx.serialization/DeserializationStrategy<#A>): #A // com.arkivanov.essenty.statekeeper/consumeRequired|consumeRequired@com.arkivanov.essenty.statekeeper.SerializableContainer(kotlinx.serialization.DeserializationStrategy<0:0>){0§<kotlin.Any>}[0]\nfinal fun <#A: kotlin/Any> com.arkivanov.essenty.statekeeper/SerializableContainer(#A?, kotlinx.serialization/SerializationStrategy<#A>): com.arkivanov.essenty.statekeeper/SerializableContainer // com.arkivanov.essenty.statekeeper/SerializableContainer|SerializableContainer(0:0?;kotlinx.serialization.SerializationStrategy<0:0>){0§<kotlin.Any>}[0]\nfinal fun <#A: kotlin/Any> com.arkivanov.essenty.statekeeper/polymorphicSerializer(kotlin.reflect/KClass<#A>, kotlinx.serialization.modules/SerializersModule): kotlinx.serialization/KSerializer<#A> // com.arkivanov.essenty.statekeeper/polymorphicSerializer|polymorphicSerializer(kotlin.reflect.KClass<0:0>;kotlinx.serialization.modules.SerializersModule){0§<kotlin.Any>}[0]\nfinal fun <#A: kotlin/Any?, #B: kotlin/Any?> (com.arkivanov.essenty.statekeeper/StateKeeper).com.arkivanov.essenty.statekeeper/saveable(kotlinx.serialization/KSerializer<#B>, kotlin/Function1<#A, #B>, kotlin/String? = ..., kotlin/Function1<#B?, #A>): kotlin.properties/PropertyDelegateProvider<kotlin/Any?, kotlin.properties/ReadOnlyProperty<kotlin/Any?, #A>> // com.arkivanov.essenty.statekeeper/saveable|saveable@com.arkivanov.essenty.statekeeper.StateKeeper(kotlinx.serialization.KSerializer<0:1>;kotlin.Function1<0:0,0:1>;kotlin.String?;kotlin.Function1<0:1?,0:0>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]\nfinal fun <#A: kotlin/Any?, #B: kotlin/Any?> (com.arkivanov.essenty.statekeeper/StateKeeperOwner).com.arkivanov.essenty.statekeeper/saveable(kotlinx.serialization/KSerializer<#B>, kotlin/Function1<#A, #B>, kotlin/String? = ..., kotlin/Function1<#B?, #A>): kotlin.properties/PropertyDelegateProvider<kotlin/Any?, kotlin.properties/ReadOnlyProperty<kotlin/Any?, #A>> // com.arkivanov.essenty.statekeeper/saveable|saveable@com.arkivanov.essenty.statekeeper.StateKeeperOwner(kotlinx.serialization.KSerializer<0:1>;kotlin.Function1<0:0,0:1>;kotlin.String?;kotlin.Function1<0:1?,0:0>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]\nfinal fun <#A: kotlin/Any?> (com.arkivanov.essenty.statekeeper/StateKeeper).com.arkivanov.essenty.statekeeper/saveable(kotlinx.serialization/KSerializer<#A>, kotlin/String? = ..., kotlin/Function0<#A>): kotlin.properties/PropertyDelegateProvider<kotlin/Any?, kotlin.properties/ReadWriteProperty<kotlin/Any?, #A>> // com.arkivanov.essenty.statekeeper/saveable|saveable@com.arkivanov.essenty.statekeeper.StateKeeper(kotlinx.serialization.KSerializer<0:0>;kotlin.String?;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]\nfinal fun <#A: kotlin/Any?> (com.arkivanov.essenty.statekeeper/StateKeeperOwner).com.arkivanov.essenty.statekeeper/saveable(kotlinx.serialization/KSerializer<#A>, kotlin/String? = ..., kotlin/Function0<#A>): kotlin.properties/PropertyDelegateProvider<kotlin/Any?, kotlin.properties/ReadWriteProperty<kotlin/Any?, #A>> // com.arkivanov.essenty.statekeeper/saveable|saveable@com.arkivanov.essenty.statekeeper.StateKeeperOwner(kotlinx.serialization.KSerializer<0:0>;kotlin.String?;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]\nfinal fun com.arkivanov.essenty.statekeeper/StateKeeperDispatcher(com.arkivanov.essenty.statekeeper/SerializableContainer? = ...): com.arkivanov.essenty.statekeeper/StateKeeperDispatcher // com.arkivanov.essenty.statekeeper/StateKeeperDispatcher|StateKeeperDispatcher(com.arkivanov.essenty.statekeeper.SerializableContainer?){}[0]\nfinal inline fun <#A: reified kotlin/Any> com.arkivanov.essenty.statekeeper/polymorphicSerializer(kotlinx.serialization.modules/SerializersModule): kotlinx.serialization/KSerializer<#A> // com.arkivanov.essenty.statekeeper/polymorphicSerializer|polymorphicSerializer(kotlinx.serialization.modules.SerializersModule){0§<kotlin.Any>}[0]\n"
  },
  {
    "path": "state-keeper/build.gradle.kts",
    "content": "import com.arkivanov.gradle.bundle\nimport com.arkivanov.gradle.dependsOn\nimport com.arkivanov.gradle.setupBinaryCompatibilityValidator\nimport com.arkivanov.gradle.setupMultiplatform\nimport com.arkivanov.gradle.setupPublication\nimport com.arkivanov.gradle.setupSourceSets\n\nplugins {\n    id(\"kotlin-multiplatform\")\n    id(\"com.android.library\")\n    id(\"kotlinx-serialization\")\n    id(\"com.arkivanov.gradle.setup\")\n}\n\nsetupMultiplatform()\nsetupPublication()\nsetupBinaryCompatibilityValidator()\n\nandroid {\n    namespace = \"com.arkivanov.essenty.statekeeper\"\n}\n\nkotlin {\n    setupSourceSets {\n        val java by bundle()\n        val nonJava by bundle()\n        val android by bundle()\n        val macosArm64 by bundle()\n\n        java dependsOn common\n        javaSet dependsOn java\n        nonJava dependsOn common\n        (allSet - javaSet) dependsOn nonJava\n\n        common.main.dependencies {\n            implementation(project(\":utils-internal\"))\n            api(deps.jetbrains.kotlinx.kotlinxSerializationCore)\n            implementation(deps.jetbrains.kotlinx.kotlinxSerializationJson)\n        }\n\n        android.main.dependencies {\n            implementation(deps.androidx.savedstate.savedstateKtx)\n            implementation(deps.androidx.lifecycle.lifecycleRuntime)\n        }\n\n        android.test.dependencies {\n            implementation(deps.robolectric.robolectric)\n        }\n    }\n}\n"
  },
  {
    "path": "state-keeper/src/androidMain/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest/>\n"
  },
  {
    "path": "state-keeper/src/androidMain/kotlin/com/arkivanov/essenty/statekeeper/AndroidExt.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport android.os.Bundle\nimport androidx.savedstate.SavedStateRegistry\nimport androidx.savedstate.SavedStateRegistryOwner\n\nprivate const val KEY_STATE = \"STATE_KEEPER_STATE\"\n\n/**\n * Creates a new instance of [StateKeeper] and attaches it to the provided AndroidX [SavedStateRegistry].\n *\n * @param savedStateRegistry a [SavedStateRegistry] to attach the returned [StateKeeper] to.\n * @param discardSavedState a flag indicating whether any previously saved state should be discarded or not,\n * default value is `false`.\n * @param isSavingAllowed called before saving the state.\n * When `true` then the state will be saved, otherwise it won't. Default value is `true`.\n */\nfun StateKeeper(\n    savedStateRegistry: SavedStateRegistry,\n    discardSavedState: Boolean = false,\n    isSavingAllowed: () -> Boolean = { true },\n): StateKeeper =\n    StateKeeper(\n        savedStateRegistry = savedStateRegistry,\n        key = KEY_STATE,\n        discardSavedState = discardSavedState,\n        isSavingAllowed = isSavingAllowed,\n    )\n\n/**\n * Creates a new instance of [StateKeeper] and attaches it to the provided AndroidX [SavedStateRegistry].\n *\n * @param savedStateRegistry a [SavedStateRegistry] to attach the returned [StateKeeper] to.\n * @param key a key to access the provided [SavedStateRegistry], to be used by the returned [StateKeeper].\n * @param discardSavedState a flag indicating whether any previously saved state should be discarded or not,\n * default value is `false`.\n * @param isSavingAllowed called before saving the state.\n * When `true` then the state will be saved, otherwise it won't. Default value is `true`.\n */\nfun StateKeeper(\n    savedStateRegistry: SavedStateRegistry,\n    key: String,\n    discardSavedState: Boolean = false,\n    isSavingAllowed: () -> Boolean = { true },\n): StateKeeper {\n    val dispatcher =\n        StateKeeperDispatcher(\n            savedState = savedStateRegistry\n                .consumeRestoredStateForKey(key = key)\n                ?.getSerializableContainer(key = KEY_STATE)\n                ?.takeUnless { discardSavedState },\n        )\n\n    savedStateRegistry.registerSavedStateProvider(key = key) {\n        Bundle().apply {\n            if (isSavingAllowed()) {\n                putSerializableContainer(key = KEY_STATE, value = dispatcher.save())\n            }\n        }\n    }\n\n    return dispatcher\n}\n\n/**\n * Creates a new instance of [StateKeeper] and attaches it to the AndroidX [SavedStateRegistry].\n *\n * @param discardSavedState a flag indicating whether any previously saved state should be discarded or not,\n * default value is `false`.\n * @param isSavingAllowed called before saving the state.\n * When `true` then the state will be saved, otherwise it won't. Default value is `true`.\n */\nfun SavedStateRegistryOwner.stateKeeper(\n    discardSavedState: Boolean = false,\n    isSavingAllowed: () -> Boolean = { true },\n): StateKeeper =\n    stateKeeper(\n        key = KEY_STATE,\n        discardSavedState = discardSavedState,\n        isSavingAllowed = isSavingAllowed,\n    )\n\n/**\n * Creates a new instance of [StateKeeper] and attaches it to the AndroidX [SavedStateRegistry].\n *\n * @param key a key to access this [SavedStateRegistry], to be used by the returned [StateKeeper].\n * @param discardSavedState a flag indicating whether any previously saved state should be discarded or not,\n * default value is `false`.\n * @param isSavingAllowed called before saving the state.\n * When `true` then the state will be saved, otherwise it won't. Default value is `true`.\n */\nfun SavedStateRegistryOwner.stateKeeper(\n    key: String,\n    discardSavedState: Boolean = false,\n    isSavingAllowed: () -> Boolean = { true },\n): StateKeeper =\n    StateKeeper(\n        savedStateRegistry = savedStateRegistry,\n        key = key,\n        discardSavedState = discardSavedState,\n        isSavingAllowed = isSavingAllowed\n    )\n"
  },
  {
    "path": "state-keeper/src/androidMain/kotlin/com/arkivanov/essenty/statekeeper/BundleExt.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport android.os.Bundle\nimport android.os.Parcel\nimport android.os.Parcelable\nimport kotlinx.serialization.DeserializationStrategy\nimport kotlinx.serialization.SerializationStrategy\n\n/**\n * Inserts the provided `kotlinx-serialization` [Serializable][kotlinx.serialization.Serializable] value\n * into this [Bundle], replacing any existing value for the given [key].\n * Either [key] or [value] may be `null`.\n */\nfun <T : Any> Bundle.putSerializable(key: String?, value: T?, strategy: SerializationStrategy<T>) {\n    putParcelable(key, ValueHolder(value = value, bytes = lazy { value?.serialize(strategy) }))\n}\n\n/**\n * Returns a `kotlinx-serialization` [Serializable][kotlinx.serialization.Serializable] associated with\n * the given [key], or `null` if no mapping exists for the given [key] or a `null` value is explicitly\n * associated with the [key].\n */\nfun <T : Any> Bundle.getSerializable(key: String?, strategy: DeserializationStrategy<T>): T? =\n    getParcelableCompat<ValueHolder<T>>(key)?.let { holder ->\n        holder.value ?: holder.bytes.value?.deserialize(strategy)\n    }\n\n@Suppress(\"DEPRECATION\")\nprivate inline fun <reified T : Parcelable> Bundle.getParcelableCompat(key: String?): T? =\n    classLoader.let { savedClassLoader ->\n        try {\n            classLoader = T::class.java.classLoader\n            getParcelable(key) as T?\n        } finally {\n            classLoader = savedClassLoader\n        }\n    }\n\n/**\n * Inserts the provided [SerializableContainer] into this [Bundle],\n * replacing any existing value for the given [key]. Either [key] or [value] may be `null`.\n */\nfun Bundle.putSerializableContainer(key: String?, value: SerializableContainer?) {\n    putSerializable(key = key, value = value, strategy = SerializableContainer.serializer())\n}\n\n/**\n * Returns a [SerializableContainer] associated with the given [key],\n * or `null` if no mapping exists for the given [key] or a `null` value\n * is explicitly associated with the [key].\n */\nfun Bundle.getSerializableContainer(key: String?): SerializableContainer? =\n    getSerializable(key = key, strategy = SerializableContainer.serializer())\n\nprivate class ValueHolder<out T : Any>(\n    val value: T?,\n    val bytes: Lazy<ByteArray?>,\n) : Parcelable {\n    override fun writeToParcel(dest: Parcel, flags: Int) {\n        dest.writeByteArray(bytes.value)\n    }\n\n    override fun describeContents(): Int = 0\n\n    companion object CREATOR : Parcelable.Creator<ValueHolder<Any>> {\n        override fun createFromParcel(parcel: Parcel): ValueHolder<Any> =\n            ValueHolder(value = null, bytes = lazyOf(parcel.createByteArray()))\n\n        override fun newArray(size: Int): Array<ValueHolder<Any>?> =\n            arrayOfNulls(size)\n    }\n}\n"
  },
  {
    "path": "state-keeper/src/androidMain/kotlin/com/arkivanov/essenty/statekeeper/PersistableBundleExt.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport android.os.Build\nimport android.os.Bundle\nimport android.os.PersistableBundle\nimport androidx.annotation.RequiresApi\nimport com.arkivanov.essenty.statekeeper.base64.base64ToByteArray\nimport com.arkivanov.essenty.statekeeper.base64.toBase64\nimport kotlinx.serialization.DeserializationStrategy\nimport kotlinx.serialization.SerializationStrategy\n\n/**\n * Inserts the provided `kotlinx-serialization` [Serializable][kotlinx.serialization.Serializable] value\n * into this [PersistableBundle], replacing any existing value for the given [key].\n * Either [key] or [value] may be `null`.\n *\n * **Note:** unlike [Bundle.putSerializable], due to the specifics of [PersistableBundle] this function\n * serializes the [value] eagerly, which may degrade the performance for large payloads.\n */\n@RequiresApi(Build.VERSION_CODES.LOLLIPOP)\nfun <T : Any> PersistableBundle.putSerializable(key: String?, value: T?, strategy: SerializationStrategy<T>) {\n    putString(key, value?.serialize(strategy)?.toBase64())\n}\n\n/**\n * Returns a `kotlinx-serialization` [Serializable][kotlinx.serialization.Serializable] associated with\n * the given [key], or `null` if no mapping exists for the given [key] or a `null` value is explicitly\n * associated with the [key].\n */\n@RequiresApi(Build.VERSION_CODES.LOLLIPOP)\nfun <T : Any> PersistableBundle.getSerializable(key: String?, strategy: DeserializationStrategy<T>): T? =\n    getString(key)?.base64ToByteArray()?.deserialize(strategy)\n\n/**\n * Inserts the provided [SerializableContainer] into this [Bundle],\n * replacing any existing value for the given [key]. Either [key] or [value] may be `null`.\n *\n * **Note:** unlike [Bundle.putSerializableContainer], due to the specifics of [PersistableBundle]\n * this function serializes the [value] eagerly, which may degrade the performance for large payloads.\n */\n@RequiresApi(Build.VERSION_CODES.LOLLIPOP)\nfun PersistableBundle.putSerializableContainer(key: String?, value: SerializableContainer?) {\n    putSerializable(key = key, value = value, strategy = SerializableContainer.serializer())\n}\n\n/**\n * Returns a [SerializableContainer] associated with the given [key],\n * or `null` if no mapping exists for the given [key] or a `null` value\n * is explicitly associated with the [key].\n */\n@RequiresApi(Build.VERSION_CODES.LOLLIPOP)\nfun PersistableBundle.getSerializableContainer(key: String?): SerializableContainer? =\n    getSerializable(key = key, strategy = SerializableContainer.serializer())\n"
  },
  {
    "path": "state-keeper/src/androidUnitTest/kotlin/com/arkivanov/essenty/statekeeper/AndroidStateKeeperTest.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport android.os.Bundle\nimport android.os.Parcel\nimport androidx.lifecycle.Lifecycle\nimport androidx.lifecycle.LifecycleRegistry\nimport androidx.savedstate.SavedStateRegistry\nimport androidx.savedstate.SavedStateRegistryController\nimport androidx.savedstate.SavedStateRegistryOwner\nimport kotlinx.serialization.builtins.serializer\nimport org.junit.runner.RunWith\nimport org.robolectric.RobolectricTestRunner\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertNull\n\n@Suppress(\"TestFunctionName\")\n@RunWith(RobolectricTestRunner::class)\nclass AndroidStateKeeperTest {\n\n    @Test\n    fun saves_and_restores_state_without_parcelling() {\n        var savedStateRegistryOwner = TestSavedStateRegistryOwner()\n        savedStateRegistryOwner.controller.performRestore(null)\n        var stateKeeper = savedStateRegistryOwner.stateKeeper()\n        stateKeeper.register(key = \"key\", strategy = String.serializer()) { \"data\" }\n        val bundle = Bundle()\n        savedStateRegistryOwner.controller.performSave(bundle)\n\n        savedStateRegistryOwner = TestSavedStateRegistryOwner()\n        savedStateRegistryOwner.controller.performRestore(bundle)\n        stateKeeper = StateKeeper(savedStateRegistry = savedStateRegistryOwner.savedStateRegistry)\n        val restoredData = stateKeeper.consume(key = \"key\", strategy = String.serializer())\n\n        assertEquals(\"data\", restoredData)\n    }\n\n    @Test\n    fun saves_and_restores_state_with_parcelling() {\n        var savedStateRegistryOwner = TestSavedStateRegistryOwner()\n        savedStateRegistryOwner.controller.performRestore(null)\n        var stateKeeper = savedStateRegistryOwner.stateKeeper()\n        stateKeeper.register(key = \"key\", strategy = String.serializer()) { \"data\" }\n        val bundle = Bundle()\n        savedStateRegistryOwner.controller.performSave(bundle)\n\n        savedStateRegistryOwner = TestSavedStateRegistryOwner()\n        savedStateRegistryOwner.controller.performRestore(bundle.parcelize().deparcelize())\n        stateKeeper = StateKeeper(savedStateRegistry = savedStateRegistryOwner.savedStateRegistry)\n        val restoredData = stateKeeper.consume(key = \"key\", strategy = String.serializer())\n\n        assertEquals(\"data\", restoredData)\n    }\n\n    @Test\n    fun GIVEN_isSavingAllowed_is_false_on_save_THEN_state_not_saved() {\n        val savedStateRegistryOwner = TestSavedStateRegistryOwner()\n        savedStateRegistryOwner.controller.performRestore(null)\n        val stateKeeper = savedStateRegistryOwner.stateKeeper(isSavingAllowed = { false })\n        stateKeeper.register(key = \"key\", strategy = String.serializer()) { throw IllegalStateException(\"Must not be called\") }\n        val bundle = Bundle()\n\n        savedStateRegistryOwner.controller.performSave(bundle)\n    }\n\n    @Test\n    fun GIVEN_discardSavedState_is_true_on_restore_THEN_discards_saved_state() {\n        var savedStateRegistryOwner = TestSavedStateRegistryOwner()\n        savedStateRegistryOwner.controller.performRestore(null)\n        var stateKeeper = savedStateRegistryOwner.stateKeeper()\n        stateKeeper.register(key = \"key\", strategy = String.serializer()) { \"data\" }\n        val bundle = Bundle()\n        savedStateRegistryOwner.controller.performSave(bundle)\n\n        savedStateRegistryOwner = TestSavedStateRegistryOwner()\n        savedStateRegistryOwner.controller.performRestore(bundle.parcelize().deparcelize())\n        stateKeeper = savedStateRegistryOwner.stateKeeper(discardSavedState = true)\n        val restoredData = stateKeeper.consume(key = \"key\", strategy = String.serializer())\n\n        assertNull(restoredData)\n    }\n\n    private class TestSavedStateRegistryOwner : SavedStateRegistryOwner {\n        val controller: SavedStateRegistryController = SavedStateRegistryController.create(this)\n\n        override val lifecycle: Lifecycle = LifecycleRegistry(this)\n        override val savedStateRegistry: SavedStateRegistry get() = controller.savedStateRegistry\n    }\n}\n"
  },
  {
    "path": "state-keeper/src/androidUnitTest/kotlin/com/arkivanov/essenty/statekeeper/BundleExtTest.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport android.os.Bundle\nimport kotlinx.serialization.Serializable\nimport org.junit.runner.RunWith\nimport org.robolectric.RobolectricTestRunner\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\n@RunWith(RobolectricTestRunner::class)\nclass BundleExtTest {\n\n    @Test\n    fun getSerializable_returns_same_value_after_putSerializable_without_serialization() {\n        val value = Value(value = \"123\")\n        val bundle = Bundle()\n        bundle.putSerializable(key = \"key\", value = value, strategy = Value.serializer())\n        val newValue = bundle.getSerializable(key = \"key\", strategy = Value.serializer())\n\n        assertEquals(value, newValue)\n    }\n\n    @Test\n    fun getSerializable_returns_same_value_after_putSerializable_with_serialization() {\n        val value = Value(value = \"123\")\n        val bundle = Bundle()\n        bundle.putSerializable(key = \"key\", value = value, strategy = Value.serializer())\n        val newValue = bundle.parcelize().deparcelize().getSerializable(key = \"key\", strategy = Value.serializer())\n\n        assertEquals(value, newValue)\n    }\n\n    @Test\n    fun getSerializable_returns_same_value_after_putSerializable_with_double_serialization() {\n        val value = Value(value = \"123\")\n        val bundle = Bundle()\n        bundle.putSerializable(key = \"key\", value = value, strategy = Value.serializer())\n        bundle.putInt(\"int\", 123)\n        val newBundle = bundle.parcelize().deparcelize()\n        newBundle.getInt(\"int\") // Force partial deserialization of the Bundle\n        val newValue = newBundle.parcelize().deparcelize().getSerializable(key = \"key\", strategy = Value.serializer())\n\n        assertEquals(value, newValue)\n    }\n\n    @Serializable\n    data class Value(val value: String)\n}\n"
  },
  {
    "path": "state-keeper/src/androidUnitTest/kotlin/com/arkivanov/essenty/statekeeper/TestUtils.android.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport android.os.Bundle\nimport android.os.Parcel\n\ninternal fun Bundle.parcelize(): ByteArray {\n    val parcel = Parcel.obtain()\n    parcel.writeBundle(this)\n    return parcel.marshall()\n}\n\ninternal fun ByteArray.deparcelize(): Bundle {\n    val parcel = Parcel.obtain()\n    parcel.unmarshall(this, 0, size)\n    parcel.setDataPosition(0)\n\n    return requireNotNull(parcel.readBundle())\n}\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/DefaultStateKeeperDispatcher.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.DeserializationStrategy\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.SerializationStrategy\n\ninternal class DefaultStateKeeperDispatcher(\n    savedState: SerializableContainer?,\n) : StateKeeperDispatcher {\n\n    private val savedState: MutableMap<String, SerializableContainer>? = savedState?.consume(strategy = SavedState.serializer())?.map\n    private val suppliers = HashMap<String, Supplier<*>>()\n\n    override fun save(): SerializableContainer {\n        val map = savedState?.toMutableMap() ?: HashMap()\n\n        suppliers.forEach { (key, supplier) ->\n            supplier.toSerializableContainer()?.also { container ->\n                map[key] = container\n            }\n        }\n\n        return SerializableContainer(value = SavedState(map), strategy = SavedState.serializer())\n    }\n\n    private fun <T : Any> Supplier<T>.toSerializableContainer(): SerializableContainer? =\n        supplier()?.let { value ->\n            SerializableContainer(value = value, strategy = strategy)\n        }\n\n    override fun <T : Any> consume(key: String, strategy: DeserializationStrategy<T>): T? =\n        savedState\n            ?.remove(key)\n            ?.consume(strategy = strategy)\n\n    override fun <T : Any> register(key: String, strategy: SerializationStrategy<T>, supplier: () -> T?) {\n        check(!isRegistered(key)) { \"Another supplier is already registered with the key: $key\" }\n        suppliers[key] = Supplier(strategy = strategy, supplier = supplier)\n    }\n\n    override fun unregister(key: String) {\n        check(isRegistered(key)) { \"No supplier is registered with the key: $key\" }\n        suppliers -= key\n    }\n\n    override fun isRegistered(key: String): Boolean = key in suppliers\n\n    private class Supplier<T : Any>(\n        val strategy: SerializationStrategy<T>,\n        val supplier: () -> T?,\n    )\n\n    @Serializable\n    private class SavedState(\n        val map: MutableMap<String, SerializableContainer>\n    )\n}\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/ExperimentalStateKeeperApi.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\n/**\n * Marks experimental API in Essenty. An experimental API can be changed or removed at any time.\n */\n@RequiresOptIn(level = RequiresOptIn.Level.WARNING)\n@Retention(AnnotationRetention.BINARY)\n@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)\nannotation class ExperimentalStateKeeperApi\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/PolymorphicSerializer.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.ExperimentalSerializationApi\nimport kotlinx.serialization.KSerializer\nimport kotlinx.serialization.descriptors.SerialDescriptor\nimport kotlinx.serialization.descriptors.SerialKind\nimport kotlinx.serialization.descriptors.buildClassSerialDescriptor\nimport kotlinx.serialization.descriptors.element\nimport kotlinx.serialization.encoding.CompositeDecoder\nimport kotlinx.serialization.encoding.Decoder\nimport kotlinx.serialization.encoding.Encoder\nimport kotlinx.serialization.encoding.decodeStructure\nimport kotlinx.serialization.encoding.encodeStructure\nimport kotlinx.serialization.modules.SerializersModule\nimport kotlin.reflect.KClass\n\n/**\n * Creates a polymorphic [KSerializer] for the specified class of type [T] using the specified [module].\n */\n@ExperimentalStateKeeperApi\n@ExperimentalSerializationApi\ninline fun <reified T : Any> polymorphicSerializer(module: SerializersModule): KSerializer<T> =\n    polymorphicSerializer(baseClass = T::class, module = module)\n\n/**\n * Creates a polymorphic [KSerializer] for the specified [baseClass] class using the specified [module].\n */\n@ExperimentalStateKeeperApi\n@ExperimentalSerializationApi\nfun <T : Any> polymorphicSerializer(baseClass: KClass<T>, module: SerializersModule): KSerializer<T> =\n    PolymorphicSerializer(baseClass = baseClass, module = module)\n\n@ExperimentalSerializationApi\nprivate class PolymorphicSerializer<T : Any>(\n    private val baseClass: KClass<T>,\n    private val module: SerializersModule,\n) : KSerializer<T> {\n    override val descriptor: SerialDescriptor =\n        buildClassSerialDescriptor(\"PolymorphicSerializer\") {\n            element<String>(\"type\")\n            element(\"value\", ContextualSerialDescriptor)\n        }\n\n    override fun serialize(encoder: Encoder, value: T) {\n        val serializer = requireNotNull(module.getPolymorphic(baseClass, value))\n        encoder.encodeStructure(descriptor) {\n            encodeStringElement(descriptor, 0, serializer.descriptor.serialName)\n            encodeSerializableElement(descriptor, 1, serializer, value)\n        }\n    }\n\n    override fun deserialize(decoder: Decoder): T =\n        decoder.decodeStructure(descriptor) {\n            var className: String? = null\n            var value: T? = null\n\n            while (true) {\n                when (val index = decodeElementIndex(descriptor)) {\n                    0 -> className = decodeStringElement(descriptor, index)\n\n                    1 -> {\n                        val actualClassName = requireNotNull(className)\n                        val serializer = requireNotNull(module.getPolymorphic(baseClass, actualClassName))\n                        value = decodeSerializableElement(descriptor, 1, serializer)\n                    }\n\n                    CompositeDecoder.DECODE_DONE -> break\n\n                    else -> error(\"Unsupported index: $index\")\n                }\n            }\n\n            requireNotNull(value)\n        }\n\n    private object ContextualSerialDescriptor : SerialDescriptor {\n        override val elementsCount: Int = 0\n        override val kind: SerialKind = SerialKind.CONTEXTUAL\n        override val serialName: String = \"Value\"\n\n        override fun getElementAnnotations(index: Int): List<Annotation> = elementNotFoundError(index)\n        override fun getElementDescriptor(index: Int): SerialDescriptor = elementNotFoundError(index)\n        override fun getElementIndex(name: String): Int = CompositeDecoder.UNKNOWN_NAME\n        override fun getElementName(index: Int): String = elementNotFoundError(index)\n        override fun isElementOptional(index: Int): Boolean = elementNotFoundError(index)\n\n        private fun elementNotFoundError(index: Int): Nothing {\n            throw IndexOutOfBoundsException(\"Element at index $index not found\")\n        }\n    }\n}\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/SerializableContainer.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport com.arkivanov.essenty.statekeeper.base64.base64ToByteArray\nimport com.arkivanov.essenty.statekeeper.base64.toBase64\nimport kotlinx.serialization.DeserializationStrategy\nimport kotlinx.serialization.KSerializer\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.SerializationStrategy\nimport kotlinx.serialization.descriptors.PrimitiveKind\nimport kotlinx.serialization.descriptors.PrimitiveSerialDescriptor\nimport kotlinx.serialization.descriptors.SerialDescriptor\nimport kotlinx.serialization.encoding.Decoder\nimport kotlinx.serialization.encoding.Encoder\n\n/**\n * Represents a lazy [Serializable][kotlinx.serialization.Serializable] container for a `Serializable` object.\n */\n@Serializable(with = SerializableContainer.Serializer::class)\nclass SerializableContainer private constructor(\n    private var data: ByteArray?,\n) {\n    constructor() : this(data = null)\n\n    private var holder: Holder<*>? = null\n\n    /**\n     * Deserializes and returns a previously stored [Serializable][kotlinx.serialization.Serializable] object.\n     *\n     * @param strategy a [DeserializationStrategy] for deserializing the object.\n     */\n    fun <T : Any> consume(strategy: DeserializationStrategy<T>): T? {\n        val consumedValue: Any? = holder?.value ?: data?.deserialize(strategy)\n        holder = null\n        data = null\n\n        @Suppress(\"UNCHECKED_CAST\")\n        return consumedValue as T?\n    }\n\n    /**\n     * Stores a [Serializable][kotlinx.serialization.Serializable] object, replacing any previously stored object.\n     *\n     * @param value an object to be stored and serialized later when needed.\n     * @param strategy a [SerializationStrategy] for serializing the value.\n     */\n    fun <T : Any> set(value: T?, strategy: SerializationStrategy<T>) {\n        holder = Holder(value = value, strategy = strategy)\n        data = null\n    }\n\n    /**\n     * Clears any previously stored object.\n     */\n    fun clear() {\n        holder = null\n        data = null\n    }\n\n    private class Holder<T : Any>(\n        val value: T?,\n        val strategy: SerializationStrategy<T>,\n    )\n\n    internal object Serializer : KSerializer<SerializableContainer> {\n        private const val NULL_MARKER = \".\"\n        override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(\"SerializableContainer\", PrimitiveKind.STRING)\n\n        override fun serialize(encoder: Encoder, value: SerializableContainer) {\n            val bytes = value.holder?.serialize() ?: value.data\n            encoder.encodeString(bytes?.toBase64() ?: NULL_MARKER)\n        }\n\n        private fun <T : Any> Holder<T>.serialize(): ByteArray? =\n            value?.serialize(strategy)\n\n        override fun deserialize(decoder: Decoder): SerializableContainer =\n            SerializableContainer(data = decoder.decodeString().takeUnless { it == NULL_MARKER }?.base64ToByteArray())\n    }\n}\n\n/**\n * Creates a new [SerializableContainer] and sets the provided [value] with the provided [strategy].\n */\nfun <T : Any> SerializableContainer(\n    value: T?,\n    strategy: SerializationStrategy<T>\n): SerializableContainer =\n    SerializableContainer().apply {\n        set(value = value, strategy = strategy)\n    }\n\n/**\n * A convenience method for [SerializableContainer.consume]. Throws [IllegalStateException]\n * if the [SerializableContainer] is empty.\n */\nfun <T : Any> SerializableContainer.consumeRequired(strategy: DeserializationStrategy<T>): T =\n    checkNotNull(consume(strategy))\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/StateKeeper.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.DeserializationStrategy\nimport kotlinx.serialization.SerializationStrategy\n\n/**\n * A key-value storage, typically used to persist data after process death or Android configuration changes.\n */\ninterface StateKeeper {\n\n    /**\n     * Removes and returns a previously saved value for the given [key].\n     *\n     * @param key a key to look up.\n     * @param strategy a [DeserializationStrategy] for deserializing the value.\n     * @return the value for the given [key] or `null` if no value is found.\n     */\n    fun <T : Any> consume(key: String, strategy: DeserializationStrategy<T>): T?\n\n    /**\n     * Registers the value [supplier] to be called when it's time to persist the data.\n     *\n     * @param key a key to be associated with the value.\n     * @param strategy a [SerializationStrategy] for serializing the value.\n     * @param supplier a supplier of the value.\n     */\n    fun <T : Any> register(key: String, strategy: SerializationStrategy<T>, supplier: () -> T?)\n\n    /**\n     * Unregisters a previously registered `supplier` for the given [key].\n     */\n    fun unregister(key: String)\n\n    /**\n     * Checks if a `supplier` is registered for the given [key].\n     */\n    fun isRegistered(key: String): Boolean\n}\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/StateKeeperDispatcher.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlin.js.JsName\n\n/**\n * Represents a savable [StateKeeper].\n */\ninterface StateKeeperDispatcher : StateKeeper {\n\n    /**\n     * Calls all registered `suppliers` and saves the data into a [SerializableContainer].\n     */\n    fun save(): SerializableContainer\n}\n\n/**\n * Creates a default implementation of [StateKeeperDispatcher] with the provided [savedState].\n */\n@JsName(\"stateKeeperDispatcher\")\nfun StateKeeperDispatcher(savedState: SerializableContainer? = null): StateKeeperDispatcher =\n    DefaultStateKeeperDispatcher(savedState)\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/StateKeeperExt.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.KSerializer\nimport kotlinx.serialization.Serializable\nimport kotlin.concurrent.Volatile\nimport kotlin.properties.PropertyDelegateProvider\nimport kotlin.properties.ReadOnlyProperty\nimport kotlin.properties.ReadWriteProperty\nimport kotlin.reflect.KProperty\n\n/**\n * Helper function for creating a\n * [delegated property](https://kotlinlang.org/docs/delegated-properties.html) holding an object\n * whose state is automatically saved and restored using [StateKeeper].\n *\n * Example:\n *\n * ```\n * import com.arkivanov.essenty.statekeeper.StateKeeper\n * import com.arkivanov.essenty.statekeeper.saveable\n * import kotlinx.serialization.Serializable\n *\n * private class SomeLogic(stateKeeper: StateKeeper) {\n *\n *     private val stateHolder by stateKeeper.saveable(\n *         serializer = State.serializer(),\n *         state = StateHolder::state,\n *     ) { savedState ->\n *         StateHolder(state = savedState ?: State())\n *     }\n *\n *     private class StateHolder(var state: State)\n *\n *     @Serializable\n *     private class State(val someValue: Int = 0)\n * }\n * ```\n *\n * @param serializer a [KSerializer] for serializing and deserializing the state.\n * @param state a function that selects a state [S] from the resulting\n * object [T] and returns it for saving.\n * @param key an optional key for saving and restoring the state. If not provided, then the\n * property name is used as a key.\n * @param init a function that accepts the previously saved state [S] (if any) and\n * returns an object of type [T].\n * @return [PropertyDelegateProvider] of type [T], typically used to define a delegated property.\n */\n@ExperimentalStateKeeperApi\nfun <T, S> StateKeeper.saveable(\n    serializer: KSerializer<S>,\n    state: (T) -> S,\n    key: String? = null,\n    init: (savedState: S?) -> T,\n): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>> =\n    PropertyDelegateProvider { _, property ->\n        val stateKey = key ?: \"SAVEABLE_HOLDER_${property.name}\"\n        val holderSerializer = Holder.serializer(serializer)\n        val result = init(consume(key = stateKey, strategy = holderSerializer)?.value)\n        register(key = stateKey, strategy = holderSerializer) { Holder(state(result)) }\n        ReadOnlyProperty { _, _ -> result }\n    }\n\n/**\n * Helper function for creating a\n * [delegated property](https://kotlinlang.org/docs/delegated-properties.html) holding an object\n * whose state is automatically saved and restored using [StateKeeper].\n *\n * Example:\n *\n * ```\n * import com.arkivanov.essenty.statekeeper.StateKeeper\n * import com.arkivanov.essenty.statekeeper.saveable\n * import kotlinx.serialization.Serializable\n *\n * private class SomeLogic(override val stateKeeper: StateKeeper) : StateKeeperOwner {\n *\n *     private val stateHolder by saveable(\n *         serializer = State.serializer(),\n *         state = StateHolder::state,\n *     ) { savedState ->\n *         StateHolder(state = savedState ?: State())\n *     }\n *\n *     private class StateHolder(var state: State)\n *\n *     @Serializable\n *     private class State(val someValue: Int = 0)\n * }\n * ```\n *\n * @param serializer a [KSerializer] for serializing and deserializing the state.\n * @param state a function that selects a state [S] from the resulting\n * object [T] and returns it for saving.\n * @param key an optional key for saving and restoring the state. If not provided, then the\n * property name is used as a key.\n * @param init a function that accepts the previously saved state [S] (if any) and\n * returns an object of type [T].\n * @return [PropertyDelegateProvider] of type [T], typically used to define a delegated property.\n */\n@ExperimentalStateKeeperApi\nfun <T, S> StateKeeperOwner.saveable(\n    serializer: KSerializer<S>,\n    state: (T) -> S,\n    key: String? = null,\n    init: (savedState: S?) -> T,\n): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>> =\n    stateKeeper.saveable(\n        serializer = serializer,\n        state = state,\n        key = key,\n        init = init,\n    )\n\n/**\n * Helper function for creating a mutable\n * [delegated property](https://kotlinlang.org/docs/delegated-properties.html) whose value is\n * automatically saved and restored using [StateKeeper].\n *\n * Example:\n *\n * ```\n * import com.arkivanov.essenty.statekeeper.StateKeeper\n * import com.arkivanov.essenty.statekeeper.saveable\n * import kotlinx.serialization.Serializable\n *\n * class SomeLogic(stateKeeper: StateKeeper) {\n *     private var state: State by stateKeeper.saveable(serializer = State.serializer(), init = ::State)\n *\n *     @Serializable\n *     private class State(val someValue: Int = 0)\n * }\n * ```\n *\n * @param serializer a [KSerializer] for serializing and deserializing values of type [T].\n * @param key an optional key for saving and restoring the value. If not provided, then the\n * property name is used as a key.\n * @param init a function returning the initial value of type [T].\n * @return [PropertyDelegateProvider] of type [T], typically used to define a delegated property.\n */\n@ExperimentalStateKeeperApi\nfun <T> StateKeeper.saveable(\n    serializer: KSerializer<T>,\n    key: String? = null,\n    init: () -> T,\n): PropertyDelegateProvider<Any?, ReadWriteProperty<Any?, T>> =\n    PropertyDelegateProvider { _, property ->\n        val stateKey = key ?: \"SAVEABLE_${property.name}\"\n        val holderSerializer = Holder.serializer(serializer)\n        val holder = consume(key = stateKey, strategy = holderSerializer) ?: Holder(init())\n        register(key = stateKey, strategy = holderSerializer) { Holder(holder.value) }\n        holder\n    }\n\n@Serializable\nprivate class Holder<T>(@Volatile var value: T) : ReadWriteProperty<Any?, T> {\n    override fun getValue(thisRef: Any?, property: KProperty<*>): T =\n        this.value\n\n    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {\n        this.value = value\n    }\n}\n\n/**\n * Helper function for creating a mutable\n * [delegated property]((https://kotlinlang.org/docs/delegated-properties.html)) whose value is\n * automatically saved and restored using [StateKeeper].\n *\n * Example:\n *\n * ```\n * import com.arkivanov.essenty.statekeeper.StateKeeper\n * import com.arkivanov.essenty.statekeeper.saveable\n * import kotlinx.serialization.Serializable\n *\n * class SomeLogic(override val stateKeeper: StateKeeper) : StateKeeperOwner {\n *     private var state: State by saveable(serializer = State.serializer(), init = ::State)\n *\n *     @Serializable\n *     private class State(val someValue: Int = 0)\n * }\n * ```\n *\n * @param serializer a [KSerializer] for serializing and deserializing values of type [T].\n * @param key an optional key for saving and restoring the value. If not provided, then the\n * property name is used as a key.\n * @param init a function returning the initial value of type [T].\n * @return [PropertyDelegateProvider] of type [T], typically used to define a delegated property.\n */\n@ExperimentalStateKeeperApi\nfun <T> StateKeeperOwner.saveable(\n    serializer: KSerializer<T>,\n    key: String? = null,\n    init: () -> T,\n): PropertyDelegateProvider<Any?, ReadWriteProperty<Any?, T>> =\n    stateKeeper.saveable(\n        serializer = serializer,\n        key = key,\n        init = init,\n    )\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/StateKeeperOwner.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\n/**\n * Represents a holder of [StateKeeper].\n */\ninterface StateKeeperOwner {\n\n    val stateKeeper: StateKeeper\n}\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/Utils.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.DeserializationStrategy\nimport kotlinx.serialization.SerializationStrategy\nimport kotlinx.serialization.json.Json\n\ninternal val essentyJson: Json =\n    Json {\n        allowStructuredMapKeys = true\n    }\n\ninternal expect fun <T> T.serialize(strategy: SerializationStrategy<T>): ByteArray\n\ninternal expect fun <T> ByteArray.deserialize(strategy: DeserializationStrategy<T>): T\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/base64/Decoder.kt",
    "content": "package com.arkivanov.essenty.statekeeper.base64\n\ninternal fun String.base64ToByteArray(): ByteArray =\n    decode(this)\n\n@Suppress(\"CognitiveComplexMethod\", \"LoopWithTooManyJumpStatements\") // Keep the original\ninternal fun decode(encoded: String): ByteArray {\n    if (encoded.isBlank()) return ByteArray(0)\n    val result = ByteArray(encoded.length)\n    var resultSize = 0\n\n    val backDictionary = backDictionary\n    var buffer = 0\n    var buffered = 0\n    var index = 0\n\n    while (index < encoded.length) {\n        val ch = encoded[index++]\n        if (ch <= ' ') continue\n        if (ch == '=') {\n            index--\n            break\n        }\n        val value = backDictionary.getOrElse(ch.code) { -1 }\n        if (value == -1) error(\"Unexpected character $ch (${ch.code})) in $encoded\")\n\n        buffer = buffer shl 6 or value\n        buffered++\n\n        if (buffered == 4) {\n            result[resultSize] = (buffer shr 16).toByte()\n            result[resultSize + 1] = (buffer shr 8 and 0xff).toByte()\n            result[resultSize + 2] = (buffer and 0xff).toByte()\n            resultSize += 3\n            buffered = 0\n            buffer = 0\n        }\n    }\n\n    var padding = 0\n    while (index < encoded.length) {\n        val ch = encoded[index++]\n        if (ch <= ' ') continue\n        check(ch == '=')\n        padding++\n        buffer = buffer shl 6\n        buffered++\n    }\n\n    if (buffered == 4) {\n        result[resultSize] = (buffer shr 16).toByte()\n        result[resultSize + 1] = (buffer shr 8 and 0xff).toByte()\n        result[resultSize + 2] = (buffer and 0xff).toByte()\n        resultSize += 3\n\n        resultSize -= padding\n        buffered = 0\n    }\n\n    check(buffered == 0) {\n        \"buffered: $buffered\"\n    }\n\n    return when {\n        resultSize < result.size -> result.copyOf(resultSize)\n        else -> result\n    }\n}\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/base64/Dictionaries.kt",
    "content": "package com.arkivanov.essenty.statekeeper.base64\n\ninternal val dictionary: CharArray = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\".toCharArray()\n\ninternal val backDictionary: IntArray = IntArray(0x80) { code ->\n    dictionary.indexOf(code.toChar())\n}\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/base64/Encoder.kt",
    "content": "package com.arkivanov.essenty.statekeeper.base64\n\ninternal fun ByteArray.toBase64(): String =\n    encode(this)\n\ninternal fun encode(array: ByteArray): String = buildString(capacity = (array.size / 3) * 4 + 1) {\n    var index = 0\n\n    while (index < array.size) {\n        if (index + 3 > array.size) break\n\n        val buffer = array[index].toInt() and 0xff shl 16 or\n            (array[index + 1].toInt() and 0xff shl 8) or\n            (array[index + 2].toInt() and 0xff shl 0)\n\n        append(dictionary[buffer shr 18])\n        append(dictionary[buffer shr 12 and 0x3f])\n        append(dictionary[buffer shr 6 and 0x3f])\n        append(dictionary[buffer and 0x3f])\n\n        index += 3\n    }\n\n    if (index < array.size) {\n        var buffer = 0\n        while (index < array.size) {\n            buffer = buffer shl 8 or (array[index].toInt() and 0xff)\n            index++\n        }\n        val padding = 3 - (index % 3)\n        buffer = buffer shl (padding * 8)\n\n        append(dictionary[buffer shr 18])\n        append(dictionary[buffer shr 12 and 0x3f])\n\n        val a = dictionary[buffer shr 6 and 0x3f]\n        val b = dictionary[buffer and 0x3f]\n\n        when (padding) {\n            0 -> {\n                append(a)\n                append(b)\n            }\n            1 -> {\n                append(a)\n                append('=')\n            }\n            2 -> {\n                append(\"==\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "state-keeper/src/commonMain/kotlin/com/arkivanov/essenty/statekeeper/base64/README.md",
    "content": "The content of this package was copied from https://github.com/cy6erGn0m/kotlinx.serialization/tree/cy/base64/formats/base64/commonMain/src/kotlinx.serialization.base64/impl.\n\nWaiting for https://github.com/Kotlin/kotlinx.serialization/issues/1633.\n"
  },
  {
    "path": "state-keeper/src/commonTest/kotlin/com/arkivanov/essenty/statekeeper/CodingTest.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass CodingTest {\n\n    @Test\n    fun serializes_and_deserializes() {\n        val data = SerializableData()\n\n        val newData = data.serialize(SerializableData.serializer()).deserialize(SerializableData.serializer())\n\n        assertEquals(data, newData)\n    }\n}\n"
  },
  {
    "path": "state-keeper/src/commonTest/kotlin/com/arkivanov/essenty/statekeeper/DefaultStateKeeperDispatcherTest.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.Serializable\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFalse\nimport kotlin.test.assertNull\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass DefaultStateKeeperDispatcherTest {\n\n    @Test\n    fun WHEN_save_recreate_consume_THEN_data_restored() {\n        val dispatcher1 = DefaultStateKeeperDispatcher(savedState = null)\n\n        val data1 = Data()\n        val data2 = Data()\n\n        dispatcher1.register(key = \"key1\", strategy = Data.serializer()) { data1 }\n        dispatcher1.register(key = \"key2\", strategy = Data.serializer()) { data2 }\n        dispatcher1.register(key = \"key3\", strategy = Data.serializer()) { null }\n\n        val savedState = dispatcher1.save().serializeAndDeserialize()\n\n        val dispatcher2 = DefaultStateKeeperDispatcher(savedState = savedState)\n\n        val restoredData1 = dispatcher2.consume(key = \"key1\", strategy = Data.serializer())\n        val restoredData2 = dispatcher2.consume(key = \"key2\", strategy = Data.serializer())\n        val restoredData3 = dispatcher2.consume(key = \"key3\", strategy = Data.serializer())\n\n        assertEquals(data1, restoredData1)\n        assertEquals(data2, restoredData2)\n        assertNull(restoredData3)\n    }\n\n    @Test\n    fun WHEN_save_recreate_twice_consume_THEN_data_restored() {\n        val dispatcher1 = DefaultStateKeeperDispatcher(savedState = null)\n\n        val data1 = Data(value = \"value1\")\n        val data2 = Data(value = \"value2\")\n        val data3 = Data(value = \"value3\")\n\n        dispatcher1.register(key = \"key1\", strategy = Data.serializer()) { data1 }\n        dispatcher1.register(key = \"key2\", strategy = Data.serializer()) { data2 }\n\n        val savedState1 = dispatcher1.save().serializeAndDeserialize()\n        val dispatcher2 = DefaultStateKeeperDispatcher(savedState = savedState1)\n        dispatcher2.register(key = \"key1\", strategy = Data.serializer()) { data3 }\n        val savedState2 = dispatcher2.save().serializeAndDeserialize()\n        val dispatcher3 = DefaultStateKeeperDispatcher(savedState = savedState2)\n\n        val restoredData1 = dispatcher3.consume(key = \"key1\", strategy = Data.serializer())\n        val restoredData2 = dispatcher3.consume(key = \"key2\", strategy = Data.serializer())\n\n        assertEquals(data3, restoredData1)\n        assertEquals(data2, restoredData2)\n    }\n\n    @Test\n    fun WHEN_consume_second_time_THEN_returns_null() {\n        val dispatcher1 = DefaultStateKeeperDispatcher(savedState = null)\n\n        dispatcher1.register(key = \"key\", strategy = Data.serializer()) { Data() }\n\n        val savedState = dispatcher1.save().serializeAndDeserialize()\n\n        val dispatcher2 = DefaultStateKeeperDispatcher(savedState = savedState)\n\n        dispatcher2.consume(key = \"key\", strategy = Data.serializer())\n\n        val restoredSerializable = dispatcher2.consume(key = \"key\", strategy = Data.serializer())\n\n        assertNull(restoredSerializable)\n    }\n\n    @Test\n    fun GIVEN_not_registered_WHEN_isRegistered_THEN_returns_false() {\n        val dispatcher = DefaultStateKeeperDispatcher(savedState = null)\n\n        val result = dispatcher.isRegistered(key = \"key\")\n\n        assertFalse(result)\n    }\n\n    @Test\n    fun GIVEN_registered_with_one_key_WHEN_isRegistered_with_another_key_THEN_returns_false() {\n        val dispatcher = DefaultStateKeeperDispatcher(savedState = null)\n        dispatcher.register(key = \"key1\", strategy = Data.serializer()) { Data() }\n\n        val result = dispatcher.isRegistered(key = \"key2\")\n\n        assertFalse(result)\n    }\n\n    @Test\n    fun GIVEN_registered_WHEN_isRegistered_with_same_key_THEN_returns_true() {\n        val dispatcher = DefaultStateKeeperDispatcher(savedState = null)\n        dispatcher.register(key = \"key\", strategy = Data.serializer()) { Data() }\n\n        val result = dispatcher.isRegistered(key = \"key\")\n\n        assertTrue(result)\n    }\n\n    @Serializable\n    private data class Data(\n        val value: String,\n    ) {\n        constructor() : this(value = \"value\") // To avoid default values in the primary constructor\n    }\n}\n"
  },
  {
    "path": "state-keeper/src/commonTest/kotlin/com/arkivanov/essenty/statekeeper/PolymorphicSerializerTest.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.ExperimentalSerializationApi\nimport kotlinx.serialization.KSerializer\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.builtins.ListSerializer\nimport kotlinx.serialization.modules.SerializersModule\nimport kotlinx.serialization.modules.polymorphic\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass PolymorphicSerializerTest {\n\n    @Test\n    fun serialize_and_deserialize() {\n        val someListSerializer = ListSerializer(SomeSerializer)\n        val originalSome = listOf(Some1(data = SerializableData()), Some2(data = SerializableData()))\n\n        val newSome = originalSome.serialize(someListSerializer).deserialize(someListSerializer)\n\n        assertEquals(originalSome, newSome)\n    }\n\n    private interface Some\n\n    @Serializable\n    private data class Some1(val data: SerializableData) : Some\n\n    @Serializable\n    private data class Some2(val data: SerializableData) : Some\n\n    @OptIn(ExperimentalStateKeeperApi::class, ExperimentalSerializationApi::class)\n    private object SomeSerializer : KSerializer<Some> by polymorphicSerializer(\n        SerializersModule {\n            polymorphic(Some::class) {\n                subclass(Some1::class, Some1.serializer())\n                subclass(Some2::class, Some2.serializer())\n            }\n        }\n    )\n}\n"
  },
  {
    "path": "state-keeper/src/commonTest/kotlin/com/arkivanov/essenty/statekeeper/SerializableContainerTest.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.Serializable\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertNotNull\nimport kotlin.test.assertNull\n\n@Suppress(\"TestFunctionName\")\nclass SerializableContainerTest {\n\n    @Test\n    fun GIVEN_value_not_set_WHEN_consume_THEN_returns_null() {\n        val container = SerializableContainer()\n\n        val data = container.consume(SerializableData.serializer())\n\n        assertNull(data)\n    }\n\n    @Test\n    fun GIVEN_value_set_WHEN_consume_THEN_returns_value() {\n        val data = SerializableData()\n        val container = SerializableContainer(value = data, strategy = SerializableData.serializer())\n\n        val newData = container.consume(SerializableData.serializer())\n\n        assertEquals(data, newData)\n    }\n\n    @Test\n    fun GIVEN_value_set_and_consumed_WHEN_consume_second_time_THEN_returns_null() {\n        val container = SerializableContainer(value = SerializableData(), strategy = SerializableData.serializer())\n        container.consume(SerializableData.serializer())\n\n        val newData = container.consume(SerializableData.serializer())\n\n        assertNull(newData)\n    }\n\n    @Test\n    fun serializes_and_deserializes_initial_data() {\n        val data = SerializableData()\n        val container = SerializableContainer(value = data, strategy = SerializableData.serializer())\n        val newContainer = container.serializeAndDeserialize()\n        val newData = newContainer.consume(strategy = SerializableData.serializer())\n\n        assertEquals(data, newData)\n    }\n\n    @Test\n    fun serializes_and_deserializes_set_data() {\n        val data = SerializableData()\n        val container = SerializableContainer()\n        container.set(value = data, strategy = SerializableData.serializer())\n        val newContainer = container.serializeAndDeserialize()\n        val newData = newContainer.consume(strategy = SerializableData.serializer())\n\n        assertEquals(data, newData)\n    }\n\n    @Test\n    fun serializes_and_deserializes_initial_data_twice() {\n        val data = SerializableData()\n        val container = SerializableContainer(value = data, strategy = SerializableData.serializer())\n        val newContainer = container.serializeAndDeserialize().serializeAndDeserialize()\n        val newData = newContainer.consume(strategy = SerializableData.serializer())\n\n        assertEquals(data, newData)\n    }\n\n    @Test\n    fun serializes_and_deserializes_set_data_twice() {\n        val data = SerializableData()\n        val container = SerializableContainer()\n        container.set(value = data, strategy = SerializableData.serializer())\n        val newContainer = container.serializeAndDeserialize().serializeAndDeserialize()\n        val newData = newContainer.consume(strategy = SerializableData.serializer())\n\n        assertEquals(data, newData)\n    }\n\n    @Test\n    fun serializes_and_deserializes_initial_null() {\n        val container = SerializableContainer()\n        val newContainer = container.serializeAndDeserialize()\n        val newData = newContainer.consume(strategy = SerializableData.serializer())\n\n        assertNull(newData)\n    }\n\n    @Test\n    fun serializes_and_deserializes_set_null() {\n        val container = SerializableContainer()\n        container.set(null, SerializableData.serializer())\n        val newContainer = container.serializeAndDeserialize()\n        val newData = newContainer.consume(strategy = SerializableData.serializer())\n\n        assertNull(newData)\n    }\n\n    @Test\n    fun serializes_and_deserializes_initial_null_twice() {\n        val container = SerializableContainer()\n        val newContainer = container.serializeAndDeserialize().serializeAndDeserialize()\n        val newData = newContainer.consume(strategy = SerializableData.serializer())\n\n        assertNull(newData)\n    }\n\n    @Test\n    fun serializes_and_deserializes_set_null_twice() {\n        val container = SerializableContainer()\n        container.set(null, SerializableData.serializer())\n        val newContainer = container.serializeAndDeserialize().serializeAndDeserialize()\n        val newData = newContainer.consume(strategy = SerializableData.serializer())\n\n        assertNull(newData)\n    }\n\n    @Test\n    fun serializes_and_deserializes_list() {\n        val data = SerializableData()\n\n        val containers =\n            Containers(\n                listOf(\n                    SerializableContainer(data, SerializableData.serializer()),\n                    SerializableContainer(),\n                    null,\n                )\n            )\n\n        val newContainers = containers.serializeAndDeserialize(Containers.serializer())\n\n        val (container1, container2, container3) = newContainers.list\n        assertNotNull(container1)\n        assertNotNull(container2)\n        assertNull(container3)\n        val newData1 = container1.consume(SerializableData.serializer())\n        val newData2 = container2.consume(SerializableData.serializer())\n        assertEquals(newData1, data)\n        assertNull(newData2)\n    }\n\n    @Test\n    fun serializes_and_deserializes_list_twice() {\n        val data = SerializableData()\n\n        val containers =\n            Containers(\n                listOf(\n                    SerializableContainer(data, SerializableData.serializer()),\n                    SerializableContainer(),\n                    null,\n                )\n            )\n\n        val newContainers = containers.serializeAndDeserialize(Containers.serializer()).serializeAndDeserialize(Containers.serializer())\n\n        val (container1, container2, container3) = newContainers.list\n        assertNotNull(container1)\n        assertNotNull(container2)\n        assertNull(container3)\n        val newData1 = container1.consume(SerializableData.serializer())\n        val newData2 = container2.consume(SerializableData.serializer())\n        assertEquals(newData1, data)\n        assertNull(newData2)\n    }\n\n    @Serializable\n    private class Containers(\n        val list: List<SerializableContainer?>,\n    )\n}\n"
  },
  {
    "path": "state-keeper/src/commonTest/kotlin/com/arkivanov/essenty/statekeeper/SerializableData.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.KSerializer\nimport kotlinx.serialization.Serializable\nimport kotlinx.serialization.builtins.serializer\nimport kotlinx.serialization.descriptors.SerialDescriptor\nimport kotlinx.serialization.encoding.Decoder\nimport kotlinx.serialization.encoding.Encoder\n\n@Suppress(\"DataClassPrivateConstructor\")\n@ConsistentCopyVisibility\n@Serializable\ndata class SerializableData private constructor(\n    private val i1: Int,\n    private val i2: Int?,\n    private val i3: Int?,\n    private val l1: Long,\n    private val l2: Long?,\n    private val l3: Long?,\n    private val f1: Float,\n    private val f2: Float?,\n    private val f3: Float?,\n    private val d1: Double,\n    private val d2: Double?,\n    private val d3: Double?,\n    private val h1: Short,\n    private val h2: Short?,\n    private val h3: Short?,\n    private val b1: Byte,\n    private val b2: Byte?,\n    private val b3: Byte?,\n    private val c1: Char,\n    private val c2: Char?,\n    private val c3: Char?,\n    private val z1: Boolean,\n    private val z2: Boolean?,\n    private val z3: Boolean?,\n    private val s1: String,\n    private val s2: String?,\n    private val s3: String?,\n    private val s4: String? = \"\",\n    private val other1: Other,\n    private val other2: Other?,\n    private val other3: Other?,\n    private val obj1: Obj,\n    private val obj2: Obj?,\n    private val obj3: Obj?,\n    private val enum1: SomeEnum,\n    private val enum2: SomeEnum?,\n    private val enum3: SomeEnum?,\n    @Serializable(with = NotSerializable1Serializer::class) private val notSerializable11: NotSerializable1,\n    @Serializable(with = NotSerializable1Serializer::class) private val notSerializable12: NotSerializable1?,\n    @Serializable(with = NotSerializable1Serializer::class) private val notSerializable13: NotSerializable1?,\n    @Serializable(with = NotSerializable2Serializer::class) private val notSerializable21: NotSerializable2,\n    @Serializable(with = NotSerializable2Serializer::class) private val notSerializable22: NotSerializable2?,\n    @Serializable(with = NotSerializable2Serializer::class) private val notSerializable23: NotSerializable2?,\n\n    private val intList1: List<Int>,\n    private val intList2: List<Int>?,\n    private val intList3: List<Int>?,\n    private val intList4: List<Int?>,\n    private val intList5: List<Int?>?,\n    private val intList6: List<Int?>?,\n\n    private val longList1: List<Long>,\n    private val longList2: List<Long>?,\n    private val longList3: List<Long>?,\n    private val longList4: List<Long?>,\n    private val longList5: List<Long?>?,\n    private val longList6: List<Long?>?,\n\n    private val shortList1: List<Short>,\n    private val shortList2: List<Short>?,\n    private val shortList3: List<Short>?,\n    private val shortList4: List<Short?>,\n    private val shortList5: List<Short?>?,\n    private val shortList6: List<Short?>?,\n\n    private val byteList1: List<Byte>,\n    private val byteList2: List<Byte>?,\n    private val byteList3: List<Byte>?,\n    private val byteList4: List<Byte?>,\n    private val byteList5: List<Byte?>?,\n    private val byteList6: List<Byte?>?,\n\n    private val charList1: List<Char>,\n    private val charList2: List<Char>?,\n    private val charList3: List<Char>?,\n    private val charList4: List<Char?>,\n    private val charList5: List<Char?>?,\n    private val charList6: List<Char?>?,\n\n    private val floatList1: List<Float>,\n    private val floatList2: List<Float>?,\n    private val floatList3: List<Float>?,\n    private val floatList4: List<Float?>,\n    private val floatList5: List<Float?>?,\n    private val floatList6: List<Float?>?,\n\n    private val doubleList1: List<Double>,\n    private val doubleList2: List<Double>?,\n    private val doubleList3: List<Double>?,\n    private val doubleList4: List<Double?>,\n    private val doubleList5: List<Double?>?,\n    private val doubleList6: List<Double?>?,\n\n    private val booleanList1: List<Boolean>,\n    private val booleanList2: List<Boolean>?,\n    private val booleanList3: List<Boolean>?,\n    private val booleanList4: List<Boolean?>,\n    private val booleanList5: List<Boolean?>?,\n    private val booleanList6: List<Boolean?>?,\n\n    private val stringList1: List<String>,\n    private val stringList2: List<String>?,\n    private val stringList3: List<String>?,\n    private val stringList4: List<String?>,\n    private val stringList5: List<String?>?,\n    private val stringList6: List<String?>?,\n\n    private val serialzableList1: List<Other>,\n    private val serialzableList2: List<Other>?,\n    private val serialzableList3: List<Other>?,\n    private val serialzableList4: List<Other?>,\n    private val serialzableList5: List<Other?>?,\n    private val serialzableList6: List<Other?>?,\n\n    private val intSet1: Set<Int>,\n    private val intSet2: Set<Int>?,\n    private val intSet3: Set<Int>?,\n    private val intSet4: Set<Int?>,\n    private val intSet5: Set<Int?>?,\n    private val intSet6: Set<Int?>?,\n\n    private val longSet1: Set<Long>,\n    private val longSet2: Set<Long>?,\n    private val longSet3: Set<Long>?,\n    private val longSet4: Set<Long?>,\n    private val longSet5: Set<Long?>?,\n    private val longSet6: Set<Long?>?,\n\n    private val shortSet1: Set<Short>,\n    private val shortSet2: Set<Short>?,\n    private val shortSet3: Set<Short>?,\n    private val shortSet4: Set<Short?>,\n    private val shortSet5: Set<Short?>?,\n    private val shortSet6: Set<Short?>?,\n\n    private val byteSet1: Set<Byte>,\n    private val byteSet2: Set<Byte>?,\n    private val byteSet3: Set<Byte>?,\n    private val byteSet4: Set<Byte?>,\n    private val byteSet5: Set<Byte?>?,\n    private val byteSet6: Set<Byte?>?,\n\n    private val charSet1: Set<Char>,\n    private val charSet2: Set<Char>?,\n    private val charSet3: Set<Char>?,\n    private val charSet4: Set<Char?>,\n    private val charSet5: Set<Char?>?,\n    private val charSet6: Set<Char?>?,\n\n    private val floatSet1: Set<Float>,\n    private val floatSet2: Set<Float>?,\n    private val floatSet3: Set<Float>?,\n    private val floatSet4: Set<Float?>,\n    private val floatSet5: Set<Float?>?,\n    private val floatSet6: Set<Float?>?,\n\n    private val doubleSet1: Set<Double>,\n    private val doubleSet2: Set<Double>?,\n    private val doubleSet3: Set<Double>?,\n    private val doubleSet4: Set<Double?>,\n    private val doubleSet5: Set<Double?>?,\n    private val doubleSet6: Set<Double?>?,\n\n    private val booleanSet1: Set<Boolean>,\n    private val booleanSet2: Set<Boolean>?,\n    private val booleanSet3: Set<Boolean>?,\n    private val booleanSet4: Set<Boolean?>,\n    private val booleanSet5: Set<Boolean?>?,\n    private val booleanSet6: Set<Boolean?>?,\n\n    private val stringSet1: Set<String>,\n    private val stringSet2: Set<String>?,\n    private val stringSet3: Set<String>?,\n    private val stringSet4: Set<String?>,\n    private val stringSet5: Set<String?>?,\n    private val stringSet6: Set<String?>?,\n\n    private val serialzableSet1: Set<Other>,\n    private val serialzableSet2: Set<Other>?,\n    private val serialzableSet3: Set<Other>?,\n    private val serialzableSet4: Set<Other?>,\n    private val serialzableSet5: Set<Other?>?,\n    private val serialzableSet6: Set<Other?>?,\n\n    private val intMap1: Map<Int, Int>,\n    private val intMap2: Map<Int, Int>?,\n    private val intMap3: Map<Int, Int>?,\n    private val intMap4: Map<Int?, Int?>,\n    private val intMap5: Map<Int?, Int?>?,\n    private val intMap6: Map<Int?, Int?>?,\n\n    private val longMap1: Map<Long, Long>,\n    private val longMap2: Map<Long, Long>?,\n    private val longMap3: Map<Long, Long>?,\n    private val longMap4: Map<Long?, Long?>,\n    private val longMap5: Map<Long?, Long?>?,\n    private val longMap6: Map<Long?, Long?>?,\n\n    private val shortMap1: Map<Short, Short>,\n    private val shortMap2: Map<Short, Short>?,\n    private val shortMap3: Map<Short, Short>?,\n    private val shortMap4: Map<Short?, Short?>,\n    private val shortMap5: Map<Short?, Short?>?,\n    private val shortMap6: Map<Short?, Short?>?,\n\n    private val byteMap1: Map<Byte, Byte>,\n    private val byteMap2: Map<Byte, Byte>?,\n    private val byteMap3: Map<Byte, Byte>?,\n    private val byteMap4: Map<Byte?, Byte?>,\n    private val byteMap5: Map<Byte?, Byte?>?,\n    private val byteMap6: Map<Byte?, Byte?>?,\n\n    private val charMap1: Map<Char, Char>,\n    private val charMap2: Map<Char, Char>?,\n    private val charMap3: Map<Char, Char>?,\n    private val charMap4: Map<Char?, Char?>,\n    private val charMap5: Map<Char?, Char?>?,\n    private val charMap6: Map<Char?, Char?>?,\n\n    private val floatMap1: Map<Float, Float>,\n    private val floatMap2: Map<Float, Float>?,\n    private val floatMap3: Map<Float, Float>?,\n    private val floatMap4: Map<Float?, Float?>,\n    private val floatMap5: Map<Float?, Float?>?,\n    private val floatMap6: Map<Float?, Float?>?,\n\n    private val doubleMap1: Map<Double, Double>,\n    private val doubleMap2: Map<Double, Double>?,\n    private val doubleMap3: Map<Double, Double>?,\n    private val doubleMap4: Map<Double?, Double?>,\n    private val doubleMap5: Map<Double?, Double?>?,\n    private val doubleMap6: Map<Double?, Double?>?,\n\n    private val booleanMap1: Map<Boolean, Boolean>,\n    private val booleanMap2: Map<Boolean, Boolean>?,\n    private val booleanMap3: Map<Boolean, Boolean>?,\n    private val booleanMap4: Map<Boolean?, Boolean?>,\n    private val booleanMap5: Map<Boolean?, Boolean?>?,\n    private val booleanMap6: Map<Boolean?, Boolean?>?,\n\n    private val stringMap1: Map<String, String>,\n    private val stringMap2: Map<String, String>?,\n    private val stringMap3: Map<String, String>?,\n    private val stringMap4: Map<String?, String?>,\n    private val stringMap5: Map<String?, String?>?,\n    private val stringMap6: Map<String?, String?>?,\n\n    private val serializableMap1: Map<Other, Other>,\n    private val serializableMap2: Map<Other, Other>?,\n    private val serializableMap3: Map<Other, Other>?,\n    private val serializableMap4: Map<Other?, Other?>,\n    private val serializableMap5: Map<Other?, Other?>?,\n    private val serializableMap6: Map<Other?, Other?>?,\n) {\n    constructor() : this(\n        i1 = 1,\n        i2 = 2,\n        i3 = null,\n        l1 = 1L,\n        l2 = 2L,\n        l3 = null,\n        f1 = 1F,\n        f2 = 2F,\n        f3 = null,\n        d1 = 1.0,\n        d2 = 2.0,\n        d3 = null,\n        h1 = 1,\n        h2 = 2,\n        h3 = null,\n        b1 = 1,\n        b2 = 2,\n        b3 = null,\n        c1 = 'a',\n        c2 = 'b',\n        c3 = null,\n        z1 = false,\n        z2 = true,\n        z3 = null,\n        s1 = \"str\",\n        s2 = \"str\",\n        s3 = null,\n        s4 = null,\n        other1 = Other(a = 1),\n        other2 = Other(a = 2),\n        other3 = null,\n        obj1 = Obj,\n        obj2 = Obj,\n        obj3 = null,\n        enum1 = SomeEnum.A,\n        enum2 = SomeEnum.B,\n        enum3 = null,\n        notSerializable11 = NotSerializable1(value = 1),\n        notSerializable12 = NotSerializable1(value = 2),\n        notSerializable13 = null,\n        notSerializable21 = NotSerializable2(value = 1),\n        notSerializable22 = NotSerializable2(value = 2),\n        notSerializable23 = null,\n\n        intList1 = listOf(1, 2),\n        intList2 = listOf(3, 4),\n        intList3 = null,\n        intList4 = listOf(5, null),\n        intList5 = listOf(6, null),\n        intList6 = null,\n\n        longList1 = listOf(1L, 2L),\n        longList2 = listOf(3L, 4L),\n        longList3 = null,\n        longList4 = listOf(5L, null),\n        longList5 = listOf(6L, null),\n        longList6 = null,\n\n        shortList1 = listOf(1.toShort(), 2.toShort()),\n        shortList2 = listOf(3.toShort(), 4.toShort()),\n        shortList3 = null,\n        shortList4 = listOf(5.toShort(), null),\n        shortList5 = listOf(6.toShort(), null),\n        shortList6 = null,\n\n        byteList1 = listOf(1.toByte(), 2.toByte()),\n        byteList2 = listOf(3.toByte(), 4.toByte()),\n        byteList3 = null,\n        byteList4 = listOf(5.toByte(), null),\n        byteList5 = listOf(6.toByte(), null),\n        byteList6 = null,\n\n        charList1 = listOf('a', 'b'),\n        charList2 = listOf('c', 'd'),\n        charList3 = null,\n        charList4 = listOf('e', null),\n        charList5 = listOf('f', null),\n        charList6 = null,\n\n        floatList1 = listOf(1F, 2F),\n        floatList2 = listOf(3F, 4F),\n        floatList3 = null,\n        floatList4 = listOf(5F, null),\n        floatList5 = listOf(6F, null),\n        floatList6 = null,\n\n        doubleList1 = listOf(1.0, 2.0),\n        doubleList2 = listOf(3.0, 4.0),\n        doubleList3 = null,\n        doubleList4 = listOf(5.0, null),\n        doubleList5 = listOf(6.0, null),\n        doubleList6 = null,\n\n        booleanList1 = listOf(false, true),\n        booleanList2 = listOf(true, false),\n        booleanList3 = null,\n        booleanList4 = listOf(false, null),\n        booleanList5 = listOf(true, null),\n        booleanList6 = null,\n\n        stringList1 = listOf(\"a\", \"b\"),\n        stringList2 = listOf(\"c\", \"d\"),\n        stringList3 = null,\n        stringList4 = listOf(\"e\", null),\n        stringList5 = listOf(\"f\", null),\n        stringList6 = null,\n\n        serialzableList1 = listOf(Other(a = 1), Other(a = 2)),\n        serialzableList2 = listOf(Other(a = 3), Other(a = 4)),\n        serialzableList3 = null,\n        serialzableList4 = listOf(Other(a = 5), null),\n        serialzableList5 = listOf(Other(a = 6), null),\n        serialzableList6 = null,\n\n        intSet1 = setOf(1, 2),\n        intSet2 = setOf(3, 4),\n        intSet3 = null,\n        intSet4 = setOf(5, null),\n        intSet5 = setOf(6, null),\n        intSet6 = null,\n\n        longSet1 = setOf(1L, 2L),\n        longSet2 = setOf(3L, 4L),\n        longSet3 = null,\n        longSet4 = setOf(5L, null),\n        longSet5 = setOf(6L, null),\n        longSet6 = null,\n\n        shortSet1 = setOf(1.toShort(), 2.toShort()),\n        shortSet2 = setOf(3.toShort(), 4.toShort()),\n        shortSet3 = null,\n        shortSet4 = setOf(5.toShort(), null),\n        shortSet5 = setOf(6.toShort(), null),\n        shortSet6 = null,\n\n        byteSet1 = setOf(1.toByte(), 2.toByte()),\n        byteSet2 = setOf(3.toByte(), 4.toByte()),\n        byteSet3 = null,\n        byteSet4 = setOf(5.toByte(), null),\n        byteSet5 = setOf(6.toByte(), null),\n        byteSet6 = null,\n\n        charSet1 = setOf('a', 'b'),\n        charSet2 = setOf('c', 'd'),\n        charSet3 = null,\n        charSet4 = setOf('e', null),\n        charSet5 = setOf('f', null),\n        charSet6 = null,\n\n        floatSet1 = setOf(1F, 2F),\n        floatSet2 = setOf(3F, 4F),\n        floatSet3 = null,\n        floatSet4 = setOf(5F, null),\n        floatSet5 = setOf(6F, null),\n        floatSet6 = null,\n\n        doubleSet1 = setOf(1.0, 2.0),\n        doubleSet2 = setOf(3.0, 4.0),\n        doubleSet3 = null,\n        doubleSet4 = setOf(5.0, null),\n        doubleSet5 = setOf(6.0, null),\n        doubleSet6 = null,\n\n        booleanSet1 = setOf(false, true),\n        booleanSet2 = setOf(true, false),\n        booleanSet3 = null,\n        booleanSet4 = setOf(false, null),\n        booleanSet5 = setOf(true, null),\n        booleanSet6 = null,\n\n        stringSet1 = setOf(\"a\", \"b\"),\n        stringSet2 = setOf(\"c\", \"d\"),\n        stringSet3 = null,\n        stringSet4 = setOf(\"e\", null),\n        stringSet5 = setOf(\"f\", null),\n        stringSet6 = null,\n\n        serialzableSet1 = setOf(Other(a = 1), Other(a = 2)),\n        serialzableSet2 = setOf(Other(a = 3), Other(a = 4)),\n        serialzableSet3 = null,\n        serialzableSet4 = setOf(Other(a = 5), null),\n        serialzableSet5 = setOf(Other(a = 6), null),\n        serialzableSet6 = null,\n\n        intMap1 = mapOf(1 to 11, 2 to 22),\n        intMap2 = mapOf(3 to 33, 4 to 44),\n        intMap3 = null,\n        intMap4 = mapOf(5 to 55, null to null),\n        intMap5 = mapOf(6 to 66, null to null),\n        intMap6 = null,\n\n        longMap1 = mapOf(1L to 11L, 2L to 22L),\n        longMap2 = mapOf(3L to 33L, 4L to 44L),\n        longMap3 = null,\n        longMap4 = mapOf(5L to 55L, null to null),\n        longMap5 = mapOf(6L to 66L, null to null),\n        longMap6 = null,\n\n        shortMap1 = mapOf(1.toShort() to 11.toShort(), 2.toShort() to 22.toShort()),\n        shortMap2 = mapOf(3.toShort() to 33.toShort(), 4.toShort() to 44.toShort()),\n        shortMap3 = null,\n        shortMap4 = mapOf(5.toShort() to 55.toShort(), null to null),\n        shortMap5 = mapOf(6.toShort() to 66.toShort(), null to null),\n        shortMap6 = null,\n\n        byteMap1 = mapOf(1.toByte() to 11.toByte(), 2.toByte() to 22.toByte()),\n        byteMap2 = mapOf(3.toByte() to 33.toByte(), 4.toByte() to 44.toByte()),\n        byteMap3 = null,\n        byteMap4 = mapOf(5.toByte() to 55.toByte(), null to null),\n        byteMap5 = mapOf(6.toByte() to 66.toByte(), null to null),\n        byteMap6 = null,\n\n        charMap1 = mapOf('a' to 'A', 'b' to 'B'),\n        charMap2 = mapOf('c' to 'C', 'd' to 'D'),\n        charMap3 = null,\n        charMap4 = mapOf('e' to 'E', null to null),\n        charMap5 = mapOf('f' to 'F', null to null),\n        charMap6 = null,\n\n        floatMap1 = mapOf(1F to 11F, 2F to 22F),\n        floatMap2 = mapOf(3F to 33F, 4F to 44F),\n        floatMap3 = null,\n        floatMap4 = mapOf(5F to 55F, null to null),\n        floatMap5 = mapOf(6F to 66F, null to null),\n        floatMap6 = null,\n\n        doubleMap1 = mapOf(1.0 to 11.0, 2.0 to 22.0),\n        doubleMap2 = mapOf(3.0 to 33.0, 4.0 to 44.0),\n        doubleMap3 = null,\n        doubleMap4 = mapOf(5.0 to 55.0, null to null),\n        doubleMap5 = mapOf(6.0 to 66.0, null to null),\n        doubleMap6 = null,\n\n        booleanMap1 = mapOf(false to true, true to false),\n        booleanMap2 = mapOf(true to false, false to true),\n        booleanMap3 = null,\n        booleanMap4 = mapOf(false to true, null to null),\n        booleanMap5 = mapOf(true to false, null to null),\n        booleanMap6 = null,\n\n        stringMap1 = mapOf(\"a\" to \"A\", \"b\" to \"B\"),\n        stringMap2 = mapOf(\"c\" to \"C\", \"d\" to \"D\"),\n        stringMap3 = null,\n        stringMap4 = mapOf(\"e\" to \"E\", null to null),\n        stringMap5 = mapOf(\"f\" to \"F\", null to null),\n        stringMap6 = null,\n\n        serializableMap1 = mapOf(Other(a = 1) to Other(a = 11), Other(a = 2) to Other(a = 22)),\n        serializableMap2 = mapOf(Other(a = 3) to Other(a = 33), Other(a = 4) to Other(a = 44)),\n        serializableMap3 = null,\n        serializableMap4 = mapOf(Other(a = 5) to Other(a = 55), null to null),\n        serializableMap5 = mapOf(Other(a = 6) to Other(a = 66), null to null),\n        serializableMap6 = null,\n    )\n}\n\n@Serializable\nprivate data class Other(\n    val a: Int\n) : SomeClass()\n\n@Serializable\nprivate data object Obj\n\nprivate enum class SomeEnum {\n    A, B\n}\n\nprivate interface SomeInterface\n\nprivate abstract class SomeClass\n\nprivate data class NotSerializable1(\n    val value: Int,\n)\n\nprivate object NotSerializable1Serializer : KSerializer<NotSerializable1> {\n    override val descriptor: SerialDescriptor = Int.serializer().descriptor\n\n    override fun serialize(encoder: Encoder, value: NotSerializable1) {\n        encoder.encodeInt(value.value)\n    }\n\n    override fun deserialize(decoder: Decoder): NotSerializable1 =\n        NotSerializable1(value = decoder.decodeInt())\n}\n\nprivate data class NotSerializable2(\n    val value: Int,\n)\n\nprivate object NotSerializable2Serializer : KSerializer<NotSerializable2> {\n    override val descriptor: SerialDescriptor = Int.serializer().descriptor\n\n    override fun serialize(encoder: Encoder, value: NotSerializable2) {\n        encoder.encodeInt(value.value)\n    }\n\n    override fun deserialize(decoder: Decoder): NotSerializable2 =\n        NotSerializable2(value = decoder.decodeInt())\n}\n"
  },
  {
    "path": "state-keeper/src/commonTest/kotlin/com/arkivanov/essenty/statekeeper/StateKeeperExtTest.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.builtins.nullable\nimport kotlinx.serialization.builtins.serializer\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertNull\n\n@OptIn(ExperimentalStateKeeperApi::class)\nclass StateKeeperExtTest {\n\n    @Test\n    fun saveable_holder_saves_and_restores_state() {\n        val oldStateKeeper = StateKeeperDispatcher()\n        val oldComponent = ComponentWithStateHolder(oldStateKeeper)\n\n        oldComponent.holder.state++\n\n        val savedState = oldStateKeeper.save().serializeAndDeserialize()\n        val newStateKeeper = StateKeeperDispatcher(savedState = savedState)\n        val newComponent = ComponentWithStateHolder(newStateKeeper)\n\n        assertEquals(1, newComponent.holder.state)\n    }\n\n    @Test\n    fun saveable_holder_saves_and_restores_nullable_state() {\n        val oldStateKeeper = StateKeeperDispatcher()\n        val oldComponent = ComponentWithStateHolder(oldStateKeeper)\n\n        oldComponent.nullableHolder.state = 1\n\n        val savedState = oldStateKeeper.save().serializeAndDeserialize()\n        val newStateKeeper = StateKeeperDispatcher(savedState = savedState)\n        val newComponent = ComponentWithStateHolder(newStateKeeper)\n\n        assertEquals(1, newComponent.nullableHolder.state)\n    }\n\n    @Test\n    fun saveable_property_saves_and_restores_state() {\n        val oldStateKeeper = StateKeeperDispatcher()\n        val oldComponent = ComponentWithState(oldStateKeeper)\n\n        oldComponent.state++\n\n        val savedState = oldStateKeeper.save().serializeAndDeserialize()\n        val newStateKeeper = StateKeeperDispatcher(savedState = savedState)\n        val newComponent = ComponentWithState(newStateKeeper)\n\n        assertEquals(1, newComponent.state)\n    }\n\n    @Test\n    fun saveable_property_saves_and_restores_nullable_state_1() {\n        val oldStateKeeper = StateKeeperDispatcher()\n        val oldComponent = ComponentWithState(oldStateKeeper)\n\n        oldComponent.nullableState1 = null\n\n        val savedState = oldStateKeeper.save().serializeAndDeserialize()\n        val newStateKeeper = StateKeeperDispatcher(savedState = savedState)\n        val newComponent = ComponentWithState(newStateKeeper)\n\n        assertNull(newComponent.nullableState1)\n    }\n\n    @Test\n    fun saveable_property_saves_and_restores_nullable_state_2() {\n        val oldStateKeeper = StateKeeperDispatcher()\n        val oldComponent = ComponentWithState(oldStateKeeper)\n\n        oldComponent.nullableState2 = 1\n\n        val savedState = oldStateKeeper.save().serializeAndDeserialize()\n        val newStateKeeper = StateKeeperDispatcher(savedState = savedState)\n        val newComponent = ComponentWithState(newStateKeeper)\n\n        assertEquals(1, newComponent.nullableState2)\n    }\n\n    private class ComponentWithStateHolder(override val stateKeeper: StateKeeper) : StateKeeperOwner {\n        val holder by saveable(serializer = Int.serializer(), state = Holder::state) {\n            Holder(state = it ?: 0)\n        }\n\n        val nullableHolder by saveable(serializer = Int.serializer().nullable, state = NullableHolder::state) {\n            NullableHolder(state = it)\n        }\n    }\n\n    private class ComponentWithState(override val stateKeeper: StateKeeper) : StateKeeperOwner {\n        var state: Int by saveable(serializer = Int.serializer()) { 0 }\n        var nullableState1: Int? by saveable(serializer = Int.serializer().nullable) { 0 }\n        var nullableState2: Int? by saveable(serializer = Int.serializer().nullable) { null }\n    }\n\n    private class Holder(var state: Int)\n    private class NullableHolder(var state: Int?)\n}\n"
  },
  {
    "path": "state-keeper/src/commonTest/kotlin/com/arkivanov/essenty/statekeeper/TestUtils.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.KSerializer\n\ninternal fun <T : Any> T.serializeAndDeserialize(serializer: KSerializer<T>): T =\n    serialize(strategy = serializer)\n        .deserialize(strategy = serializer)\n\ninternal fun SerializableContainer.serializeAndDeserialize(): SerializableContainer =\n    serializeAndDeserialize(SerializableContainer.serializer())\n"
  },
  {
    "path": "state-keeper/src/commonTest/kotlin/com/arkivanov/essenty/statekeeper/base64/Base64ImplTest.kt",
    "content": "package com.arkivanov.essenty.statekeeper.base64\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass Base64ImplTest {\n\n    @Test\n    fun encodeSmokeTests() {\n        testEncode(\"123\", \"MTIz\")\n        testEncode(\"abcdef\", \"YWJjZGVm\")\n\n        testEncode(\"1\", \"MQ==\")\n        testEncode(\"2\", \"Mg==\")\n        testEncode(\"12\", \"MTI=\")\n\n        testEncode(\"abcd\", \"YWJjZA==\")\n        testEncode(\"abcde\", \"YWJjZGU=\")\n\n        // RFC's testcases\n        testEncode(\"\", \"\")\n        testEncode(\"f\", \"Zg==\")\n        testEncode(\"fo\", \"Zm8=\")\n        testEncode(\"foo\", \"Zm9v\")\n        testEncode(\"foob\", \"Zm9vYg==\")\n        testEncode(\"fooba\", \"Zm9vYmE=\")\n        testEncode(\"foobar\", \"Zm9vYmFy\")\n    }\n\n    @Test\n    fun decodeSmokeTests() {\n        testDecode(\"123\", \"MTIz\")\n        testDecode(\"abcdef\", \"YWJjZGVm\")\n\n        testDecode(\"1\", \"MQ==\")\n        testDecode(\"2\", \"Mg==\")\n        testDecode(\"12\", \"MTI=\")\n\n        testDecode(\"abcd\", \"YWJjZA==\")\n        testDecode(\"abcde\", \"YWJjZGU=\")\n\n        // RFC\n        // RFC's testcases\n        testDecode(\"\", \"\")\n        testDecode(\"f\", \"Zg==\")\n        testDecode(\"fo\", \"Zm8=\")\n        testDecode(\"foo\", \"Zm9v\")\n        testDecode(\"foob\", \"Zm9vYg==\")\n        testDecode(\"fooba\", \"Zm9vYmE=\")\n        testDecode(\"foobar\", \"Zm9vYmFy\")\n    }\n\n    private fun testEncode(input: String, expected: String) {\n        val result = encode(input.encodeToByteArray())\n        assertEquals(expected, result)\n    }\n\n    private fun testDecode(expected: String, encoded: String) {\n        val result = decode(encoded).decodeToString()\n        assertEquals(expected, result)\n    }\n}\n"
  },
  {
    "path": "state-keeper/src/commonTest/kotlin/com/arkivanov/essenty/statekeeper/base64/README.md",
    "content": "The content of this package was copied from https://github.com/cy6erGn0m/kotlinx.serialization/tree/cy/base64/formats/base64/commonTest/src/kotlinx/serialization/base64.\n\nWaiting for https://github.com/Kotlin/kotlinx.serialization/issues/1633.\n"
  },
  {
    "path": "state-keeper/src/javaMain/kotlin/com/arkivanov/essenty/statekeeper/Utils.java.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.DeserializationStrategy\nimport kotlinx.serialization.ExperimentalSerializationApi\nimport kotlinx.serialization.SerializationStrategy\nimport kotlinx.serialization.json.decodeFromStream\nimport kotlinx.serialization.json.encodeToStream\nimport java.io.ByteArrayInputStream\nimport java.io.ByteArrayOutputStream\nimport java.util.zip.ZipEntry\nimport java.util.zip.ZipInputStream\nimport java.util.zip.ZipOutputStream\n\ninternal actual fun <T> T.serialize(strategy: SerializationStrategy<T>): ByteArray =\n    ByteArrayOutputStream().use { output ->\n        ZipOutputStream(output).use { zip ->\n            zip.setLevel(7)\n            zip.putNextEntry(ZipEntry(\"Entry\"))\n\n            zip.buffered().use { bufferedOutput ->\n                @OptIn(ExperimentalSerializationApi::class)\n                essentyJson.encodeToStream(serializer = strategy, value = this, stream = bufferedOutput)\n            }\n        }\n\n        output.toByteArray()\n    }\n\ninternal actual fun <T> ByteArray.deserialize(strategy: DeserializationStrategy<T>): T =\n    ZipInputStream(ByteArrayInputStream(this)).use { zip ->\n        zip.nextEntry\n\n        zip.buffered().use { bufferedInput ->\n            @OptIn(ExperimentalSerializationApi::class)\n            essentyJson.decodeFromStream(deserializer = strategy, stream = bufferedInput)\n        }\n    }\n"
  },
  {
    "path": "state-keeper/src/jsTest/kotlin/com/arkivanov/essenty/statekeeper/DefaultStateKeeperDispatcherJsTest.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlin.test.Test\nimport kotlin.test.assertTrue\n\n@Suppress(\"TestFunctionName\")\nclass DefaultStateKeeperDispatcherJsTest {\n\n    // Verifies the workaround for https://youtrack.jetbrains.com/issue/KT-49186\n    @Test\n    fun WHEN_save_THEN_returns_SerializableContainer() {\n        val stateKeeper = DefaultStateKeeperDispatcher(null)\n\n        val serializableContainer = stateKeeper.save()\n\n        @Suppress(\"USELESS_IS_CHECK\")\n        assertTrue(serializableContainer is SerializableContainer)\n    }\n}\n"
  },
  {
    "path": "state-keeper/src/nonJavaMain/kotlin/com/arkivanov/essenty/statekeeper/Utils.kt",
    "content": "package com.arkivanov.essenty.statekeeper\n\nimport kotlinx.serialization.DeserializationStrategy\nimport kotlinx.serialization.SerializationStrategy\n\ninternal actual fun <T> T.serialize(strategy: SerializationStrategy<T>): ByteArray =\n    essentyJson.encodeToString(serializer = strategy, value = this).encodeToByteArray()\n\ninternal actual fun <T> ByteArray.deserialize(strategy: DeserializationStrategy<T>): T =\n    essentyJson.decodeFromString(deserializer = strategy, string = decodeToString())\n"
  },
  {
    "path": "state-keeper-benchmarks/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "state-keeper-benchmarks/build.gradle.kts",
    "content": "import com.arkivanov.gradle.setupAndroidLibrary\n\nplugins {\n    id(\"kotlin-android\")\n    id(\"com.android.library\")\n    id(\"kotlinx-serialization\")\n    id(\"kotlin-parcelize\")\n    id(\"com.arkivanov.gradle.setup\")\n}\n\nsetupAndroidLibrary()\n\nandroid {\n    namespace = \"com.arkivanov.essenty.statekeeper.benchmarks\"\n    testOptions.unitTests.isIncludeAndroidResources = true\n}\n\ndependencies {\n    implementation(project(\":state-keeper\"))\n    implementation(deps.jetbrains.kotlinx.kotlinxSerializationJson)\n    testImplementation(kotlin(\"test\"))\n    testImplementation(deps.robolectric.robolectric)\n}\n"
  },
  {
    "path": "state-keeper-benchmarks/src/main/res/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest/>\n"
  },
  {
    "path": "state-keeper-benchmarks/src/test/kotlin/com/arkivanov/essenty/statekeeper/benchmarks/Benchmarks.kt",
    "content": "@file:Suppress(\"INVISIBLE_MEMBER\", \"INVISIBLE_REFERENCE\")\n\npackage com.arkivanov.essenty.statekeeper.benchmarks\n\nimport android.os.Build\nimport android.os.Bundle\nimport android.os.Parcel\nimport android.os.Parcelable\nimport com.arkivanov.essenty.statekeeper.deserialize\nimport com.arkivanov.essenty.statekeeper.serialize\nimport kotlinx.parcelize.Parcelize\nimport kotlinx.serialization.Serializable\nimport org.robolectric.annotation.Config\nimport kotlin.test.assertEquals\nimport kotlin.time.measureTime\n\n//@RunWith(RobolectricTestRunner::class)\n@Config(minSdk = Build.VERSION_CODES.TIRAMISU)\nclass Benchmarks {\n\n    // Manual run only\n//    @Test\n    fun size() {\n        val data = getData()\n        println(\"Parcelable size: ${data.getParcelizedSize()}\")\n        println(\"Serializable size: ${data.getSerializedSize()}\")\n\n        val newDataParcelable = data.parcelize().deparcelize()\n        val newDataSerializable = data.serialize(Data.serializer()).deserialize(Data.serializer())\n\n        assertEquals(data, newDataParcelable)\n        assertEquals(data, newDataSerializable)\n    }\n\n    // Manual run only\n//    @Test\n    fun performance() {\n        val data = getData()\n\n        repeat(100) {\n            data.parcelize().deparcelize()\n            data.serialize(Data.serializer()).deserialize(Data.serializer())\n        }\n\n        val t1 =\n            measureTime {\n                repeat(100) {\n                    data.parcelize().deparcelize()\n                }\n            }\n\n        val t2 =\n            measureTime {\n                repeat(100) {\n                    data.serialize(Data.serializer()).deserialize(Data.serializer())\n                }\n            }\n\n        println(\"Parcelize time: $t1\")\n        println(\"Serialize time: $t2\")\n    }\n\n    private fun Data.getParcelizedSize(): Int =\n        parcelize().size\n\n    private fun Data.parcelize(): ByteArray {\n        val bundle = Bundle()\n        bundle.putParcelable(\"key\", this)\n        val parcel = Parcel.obtain()\n        parcel.writeBundle(bundle)\n        return parcel.marshall()\n    }\n\n    private fun ByteArray.deparcelize(): Data {\n        val parcel = Parcel.obtain()\n        parcel.unmarshall(this, 0, size)\n        parcel.setDataPosition(0)\n\n        return requireNotNull(parcel.readBundle()).getParcelable(\"key\", Data::class.java)!!\n    }\n\n    private fun Data.getSerializedSize(): Int =\n        serialize(Data.serializer()).size\n\n    private fun getData(): Data =\n        getInnerData(\n            dataList = List(30) {\n                getInnerData(\n                    dataList = List(10) {\n                        getInnerData()\n                    },\n                )\n            },\n        )\n\n    private fun getInnerData(dataList: List<Data> = emptyList()): Data =\n        Data(\n            booleanValue = true,\n            byteValue = 64,\n            shortValue = 8192,\n            integerValue = 1234567,\n            longValue = 12345678912345,\n            floatValue = 100F,\n            doubleValue = 100.0,\n            charValue = 'a',\n            stringValue = \"Some string data goes here\",\n            intList = List(100) { it },\n            stringList = List(100) { \"Some string data goes here\" },\n            dataList = dataList,\n        )\n\n    @Serializable\n    @Parcelize\n    data class Data(\n        val booleanValue: Boolean,\n        val byteValue: Byte,\n        val shortValue: Short,\n        val integerValue: Int,\n        val longValue: Long,\n        val floatValue: Float,\n        val doubleValue: Double,\n        val charValue: Char,\n        val stringValue: String,\n        val intList: List<Int>,\n        val stringList: List<String>,\n        val dataList: List<Data>,\n    ) : Parcelable\n}\n"
  },
  {
    "path": "tools/check-publication/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n.idea\n/build\n"
  },
  {
    "path": "tools/check-publication/build.gradle.kts",
    "content": "import com.arkivanov.gradle.setupMultiplatform\nimport com.arkivanov.gradle.setupSourceSets\n\nplugins {\n    id(\"kotlin-multiplatform\")\n    id(\"com.android.library\")\n    id(\"com.arkivanov.gradle.setup\")\n}\n\nsetupMultiplatform()\n\nrepositories {\n    maven(\"https://s01.oss.sonatype.org/content/groups/staging/\") {\n        credentials {\n            username = \"arkivanov\"\n            password = System.getenv(\"SONATYPE_PASSWORD\")\n        }\n    }\n}\n\nandroid {\n    namespace = \"com.arkivanov.essenty.tools.checkpublication\"\n}\n\nkotlin {\n    setupSourceSets {\n        common.main.dependencies {\n            val version = deps.versions.essenty.get()\n            implementation(\"com.arkivanov.essenty:back-handler:$version\")\n            implementation(\"com.arkivanov.essenty:instance-keeper:$version\")\n            implementation(\"com.arkivanov.essenty:lifecycle:$version\")\n            implementation(\"com.arkivanov.essenty:lifecycle-coroutines:$version\")\n            implementation(\"com.arkivanov.essenty:lifecycle-reaktive:$version\")\n            implementation(\"com.arkivanov.essenty:state-keeper:$version\")\n        }\n    }\n}\n"
  },
  {
    "path": "tools/check-publication/src/androidMain/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest/>\n"
  },
  {
    "path": "tools/check-publication/src/commonMain/kotlin/com/arkivanov/essenty/tools/checkpublication/Dummy.kt",
    "content": "package com.arkivanov.essenty.tools.checkpublication\n\nfun dummy() {\n    // no-op\n}\n"
  },
  {
    "path": "utils-internal/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "utils-internal/build.gradle.kts",
    "content": "import com.arkivanov.gradle.setupMultiplatform\nimport com.arkivanov.gradle.setupPublication\n\nplugins {\n    id(\"kotlin-multiplatform\")\n    id(\"com.android.library\")\n    id(\"com.arkivanov.gradle.setup\")\n}\n\nsetupMultiplatform()\nsetupPublication()\n\nandroid {\n    namespace = \"com.arkivanov.essenty.utils.internal\"\n}\n"
  },
  {
    "path": "utils-internal/src/androidMain/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest/>\n"
  },
  {
    "path": "utils-internal/src/commonMain/kotlin/com/arkivanov/essenty/utils/internal/ExperimentalEssentyApi.kt",
    "content": "package com.arkivanov.essenty.utils.internal\n\n/**\n * Marks experimental API in Essenty. An experimental API can be changed or removed at any time.\n */\n@RequiresOptIn(level = RequiresOptIn.Level.WARNING)\n@Retention(AnnotationRetention.BINARY)\n@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)\nannotation class ExperimentalEssentyApi\n"
  },
  {
    "path": "utils-internal/src/commonMain/kotlin/com/arkivanov/essenty/utils/internal/InternalEssentyApi.kt",
    "content": "package com.arkivanov.essenty.utils.internal\n\n@RequiresOptIn(message = \"This API is internal, please don't use it.\", level = RequiresOptIn.Level.ERROR)\n@Retention(AnnotationRetention.BINARY)\n@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)\nannotation class InternalEssentyApi\n"
  }
]