{"id":20823211,"url":"https://github.com/pink-room/peanuts","last_synced_at":"2025-05-07T16:46:04.407Z","repository":{"id":65508436,"uuid":"569370207","full_name":"pink-room/peanuts","owner":"pink-room","description":"Updating your UI state is now peanuts!","archived":false,"fork":false,"pushed_at":"2023-01-06T15:58:34.000Z","size":115,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-31T12:02:04.285Z","etag":null,"topics":["android","jetpack-compose","kotlin","state-flow"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pink-room.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-11-22T17:10:58.000Z","updated_at":"2022-12-19T09:25:40.000Z","dependencies_parsed_at":"2023-02-06T06:17:32.183Z","dependency_job_id":null,"html_url":"https://github.com/pink-room/peanuts","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pink-room%2Fpeanuts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pink-room%2Fpeanuts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pink-room%2Fpeanuts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pink-room%2Fpeanuts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pink-room","download_url":"https://codeload.github.com/pink-room/peanuts/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252917214,"owners_count":21824903,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","jetpack-compose","kotlin","state-flow"],"created_at":"2024-11-17T22:17:40.362Z","updated_at":"2025-05-07T16:46:04.379Z","avatar_url":"https://github.com/pink-room.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Peanuts\n\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.pinkroom/peanuts/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.pinkroom/peanuts)\n\nIf you use Kotlin flows to manage your Jetpack Compose UI states, chances are that this code is\nfamiliar to you on a daily basis.\n\nYou have a state:\n\n```kotlin\ndata class MyScreenState(\n    val isLoading: Boolean = false,\n    // ...\n)\n```\n\nAnd, in your ViewModel, you init and expose that state:\n\n```kotlin\nclass MyScreenViewModel : ViewModel() {\n    private val _state = MutableStateFlow(MyScreenState())\n    val state = _state.asStateFlow()\n}\n```\n\nThen, whenever you want to update the screen state, you need to do something like:\n\n```kotlin\n_state.update { currentState -\u003e currentState.copy(isLoading = true) }\n```\n\n-------\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"#why-peanuts\"\u003eWhy\u003c/a\u003e \u0026bull;\n    \u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e \u0026bull;\n    \u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e\n\u003c/p\u003e\n\n-------\n\n## Why Peanuts?\n\nEven tho the code above is simple, it has 2 main flaws:\n\n1. You always need to remember to copy the current state to create a new state;\n2. Due to that, you need to write the same code over and over again.\n\nPeanuts is a very simple library that uses KSP and KotlinPoet to simplify the screen state updates.\nIt will automatically generate an extension function for you, like this one:\n\n````kotlin\nfun MutableStateFlow\u003cMyScreenState\u003e.update(isLoading: Boolean = value.isLoading, ...) =\n    update { it.copy(isLoading = isLoading, ...) }\n````\n\nAllowing you to update your screen state simply with:\n\n````kotlin\n_state.update(isLoading = true)\n````\n\n## Installation\n\n1. Add KSP plugin:\n\nIn your project build gradle:\n\n``` groovy\nplugins {\n    //...\n    id 'com.google.devtools.ksp' version '1.7.20-1.0.7' // Depends on your kotlin version\n}\n```\n\nIn your app build gradle:\n\n```groovy\nplugins {\n    // ...\n    id 'com.google.devtools.ksp'\n}\n```\n\n2. Add dependency:\n\n``` groovy\ndependencies {\n    implementation 'dev.pinkroom:peanuts:\u003clatest_version\u003e'\n    ksp 'dev.pinkroom:peanuts:\u003clatest_version\u003e'\n}\n```\n\n3. Add KSP generated folders as source directories:\n\n``` groovy\nandroid {\n    // ...\n    applicationVariants.all { variant -\u003e\n        kotlin.sourceSets {\n            getByName(variant.name) {\n                kotlin.srcDir(\"build/generated/ksp/${variant.name}/kotlin\")\n            }\n        }\n    }\n}\n```\n\n**Note:** This is only needed due to [this](https://github.com/google/ksp/issues/37) issue.\n\n## Usage\n\nFirst, you need to annotate your screen states with `@PeanutState`:\n\n```kotlin\n@PeanutState\ndata class MyScreenState(\n    val isLoading: Boolean = false,\n    // ...\n)\n```\n\nAfter your code compiles, updating your screen state is peanuts:\n\n````kotlin\n_state.update(isLoading = true)\n````\n\n## License\n\n    Copyright 2022 Pink Room, Lda\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.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpink-room%2Fpeanuts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpink-room%2Fpeanuts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpink-room%2Fpeanuts/lists"}