{"id":13694453,"url":"https://github.com/joreilly/WordMasterKMP","last_synced_at":"2025-05-03T03:31:40.564Z","repository":{"id":40452060,"uuid":"445910666","full_name":"joreilly/WordMasterKMP","owner":"joreilly","description":"Kotlin Multiplatform sample with SwiftUI and Compose (Desktop and Android) clients. Heavily inspired by Wordle game.","archived":false,"fork":false,"pushed_at":"2024-09-22T17:00:40.000Z","size":334,"stargazers_count":66,"open_issues_count":1,"forks_count":9,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-19T22:20:40.888Z","etag":null,"topics":["android","compose","compose-desktop","ios","jetpac","jetpack-compose","kotlin","kotlin-multiplatform","kotlin-native","swift","swiftui"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joreilly.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-08T19:31:54.000Z","updated_at":"2025-02-24T23:45:37.000Z","dependencies_parsed_at":"2025-01-02T16:16:54.289Z","dependency_job_id":null,"html_url":"https://github.com/joreilly/WordMasterKMP","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joreilly%2FWordMasterKMP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joreilly%2FWordMasterKMP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joreilly%2FWordMasterKMP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joreilly%2FWordMasterKMP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joreilly","download_url":"https://codeload.github.com/joreilly/WordMasterKMP/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252137577,"owners_count":21700240,"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","compose","compose-desktop","ios","jetpac","jetpack-compose","kotlin","kotlin-multiplatform","kotlin-native","swift","swiftui"],"created_at":"2024-08-02T17:01:32.554Z","updated_at":"2025-05-03T03:31:39.745Z","avatar_url":"https://github.com/joreilly.png","language":"Kotlin","funding_links":[],"categories":["Misc"],"sub_categories":["SwiftUI","macOS"],"readme":"# WordMasterKMP\n\n![kotlin-version](https://img.shields.io/badge/kotlin-1.8.0-orange)\n\nKotlin Multiplatform sample heavily inspired by [Wordle](https://www.powerlanguage.co.uk/wordle/) game and also [Word Master](https://github.com/octokatherine/word-master) and [wordle-solver](https://github.com/dlew/wordle-solver) samples.  The main game logic/state is included in shared KMP code with basic UI then in following clients\n- iOS (SwiftUI)\n- Android (Jetpack Compose)\n- Desktop (Compose for Desktop)\n\n### Shared KMP game logic/state\n\nThe shared `WordMasterService` class includes following `StateFlow`s representing the current set of guesses and updated status info for each letter.\n\n```\nval boardGuesses = MutableStateFlow\u003cArrayList\u003cArrayList\u003cString\u003e\u003e\u003e(arrayListOf())\nval boardStatus = MutableStateFlow\u003cArrayList\u003cArrayList\u003cLetterStatus\u003e\u003e\u003e(arrayListOf())\n```\n\nThe various clients call `WordService.setGuess()` when a user enters a letter and then `WordService.checkGuess()` after row of letters\nare entered...UI then reflects any resulting updates to above `StateFlow`'s.  The Compose clients for example do that using following (with any updates to those `StateFlow's` triggering recomposition)\n\n```\nval boardGuesses by wordMasterService.boardGuesses.collectAsState()\nval boardStatus by wordMasterService.boardStatus.collectAsState()\n```\n\u003cbr\u003e\nOn iOS we're using [KMP-NativeCoroutines](https://github.com/rickclephas/KMP-NativeCoroutines) library to map the `StateFlow`s to Swift `AsyncStream`s.  So, for example, our Swift view model includes\n\n```\n@Published public var boardStatus: [[LetterStatus]] = []\n@Published public var boardGuesses: [[String]] = []\n```\n\nwhich are then updated using for example\n\n```\nlet stream = asyncStream(for: wordMasterService.boardStatusNative)\nfor try await data in stream {\n  self.boardStatus = data as! [[LetterStatus]]\n}\n\nlet stream = asyncStream(for: wordMasterService.boardGuessesNative)\nfor try await data in stream {\n    self.boardGuesses = data as! [[String]]\n}\n\n```\n\nAny updates to `boardStatus` or `boardGuesses` will trigger our SwiftUI UI to be recomposed again.\n\n\n### Remaining work includes\n\n- check if overall word is valid and show indication in UI if not (ideally with animations!)\n- better keyboard navigation\n- share Compose code between Android and Desktop\n- indicator in UI that correct guess entered (other than all letters being green)\n\n\n### Screenshots\n\u003cimg width=\"462\" alt=\"Screenshot 2022-01-08 at 22 40 36\" src=\"https://user-images.githubusercontent.com/6302/148663058-a725d403-b956-4c84-8635-fbb388fa63a8.png\"\u003e\n\n![Simulator Screen Shot - iPhone 13 Pro - 2022-01-08 at 22 38 11](https://user-images.githubusercontent.com/6302/148663064-3ed57b1f-c1a3-4e39-b2c2-2ddb3fb09ed9.png)\n\n![Screenshot_1641682073](https://user-images.githubusercontent.com/6302/148663060-c1047266-425c-4b14-bdaf-b7177a1fa332.png)\n\n## Full set of Kotlin Multiplatform/Compose/SwiftUI samples\n\n*  PeopleInSpace (https://github.com/joreilly/PeopleInSpace)\n*  GalwayBus (https://github.com/joreilly/GalwayBus)\n*  Confetti (https://github.com/joreilly/Confetti)\n*  BikeShare (https://github.com/joreilly/BikeShare)\n*  FantasyPremierLeague (https://github.com/joreilly/FantasyPremierLeague)\n*  ClimateTrace (https://github.com/joreilly/ClimateTraceKMP)\n*  GeminiKMP (https://github.com/joreilly/GeminiKMP)\n*  MortyComposeKMM (https://github.com/joreilly/MortyComposeKMM)\n*  StarWars (https://github.com/joreilly/StarWars)\n*  WordMasterKMP (https://github.com/joreilly/WordMasterKMP)\n*  Chip-8 (https://github.com/joreilly/chip-8)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoreilly%2FWordMasterKMP","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoreilly%2FWordMasterKMP","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoreilly%2FWordMasterKMP/lists"}