{"id":22850533,"url":"https://github.com/iurysza/livematch","last_synced_at":"2026-04-30T00:02:50.200Z","repository":{"id":61855995,"uuid":"524116167","full_name":"iurysza/livematch","owner":"iurysza","description":"WIP: A /r/soccer client for android built with compose","archived":false,"fork":false,"pushed_at":"2024-01-07T18:39:39.000Z","size":10971,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-06T10:53:25.584Z","etag":null,"topics":["android","arrowkt","kotlin","reddit"],"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/iurysza.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-12T14:24:28.000Z","updated_at":"2024-05-28T07:40:15.000Z","dependencies_parsed_at":"2024-01-07T19:52:55.429Z","dependency_job_id":null,"html_url":"https://github.com/iurysza/livematch","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iurysza%2Flivematch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iurysza%2Flivematch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iurysza%2Flivematch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iurysza%2Flivematch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iurysza","download_url":"https://codeload.github.com/iurysza/livematch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246428991,"owners_count":20775802,"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","arrowkt","kotlin","reddit"],"created_at":"2024-12-13T05:08:00.875Z","updated_at":"2026-04-30T00:02:45.152Z","avatar_url":"https://github.com/iurysza.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"./assets/imgs/app_launcher_icon.png\" alt=\"Live Match\" width=\"80\"\u003e\u003c/img\u003e\n\n# Live Match\n\nThis is a POC of a client built specifically for Reddit's [/r/soccer](https://www.reddit.com/r/soccer/) community. The\nidea is that\nyou can use this app to follow any live match happening, besides you will be able to watch goals and other match related\nmedia as they're posted with a native video player (WIP).\n\n**LiveMatch** is a fully functional Android where I try to apply some ideas and best practices related to android\ndevelopment while also explore new ideas that only a side project would allow. In this small\nproject you can see How I approach: modularization, dependency injection, unit testing, architecture, UI/UX design, etc.\n\n# Features\n\nThe app has three main features:\n\n* The Match Day feature lists all the football matches happening today and their scores.\n\n* The Match Thread displays important information about a football match and the best comments from Reddit's `/r/soccer`\n  community. These comments are organized based on what was happening in the match at the time they were posted.\n\n- Match Highlights is a collection of all media related to the match thread that has been posted, displayed in a\n  carousel. When tapped, they can be viewed by opening an in-app browser tab. The plan is to have an in-app video\n  playback in the future.\n\n## App Screens\n\n| Feature      | Dark Theme                                                               | Light Theme                                                               |\n|--------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------|\n| Match Day    | \u003cimg src=\"./assets/imgs/match-day-dark.png\" width=\"200\" height=\"400\"\u003e    | \u003cimg src=\"./assets/imgs/match-day-light.png\" width=\"200\" height=\"400\"\u003e    |\n| Match Thread | \u003cimg src=\"./assets/imgs/match-thread-dark.png\" width=\"200\" height=\"400\"\u003e | \u003cimg src=\"./assets/imgs/match-thread-light.png\" width=\"200\" height=\"400\"\u003e |\n\n# Architecture\n\n**Important Note:** This example focuses on scalability and is suitable for large projects and teams. For smaller\nprojects and teams, a simpler approach and architecture may be more appropriate. The goal of this project is to\ndemonstrate how I would approach app architecture in big projects and teams to ensure scalability.\n\nThis architecture includes:\n\n- A layered architecture approach inspired by hexagonal/clean-arch.\n\n- Rail Oriented Programming across all layers.\n\n- MVVM like Arch for the presentation layer, featuring unidirectional data flow.\n\n# Modularization\n\nThis modularization approach is an example of how to scale a project for multiple developers. While it may have some\nsimplifications compared to what you might see in a larger project with over 50 developers, it still attempts to\nshowcases the key principles of what I consider `good` modularization. This approach strikes a balance between keeping\nthings straightforward and ensuring scalability, making it a smart choice for a small project.\n\n## Packaging approach\n\nThere is a debate about whether to package the code by feature or by layer. Both approaches have advantages and\ndisadvantages. Packaging by feature groups together all the code needed to implement a specific feature, which makes it\neasier to understand and maintain. However, it can lead to code duplication and make it difficult to reuse code across\nfeatures. Packaging by layer groups together code based on the function it performs, which makes it easier to reuse code\nand enforce consistency. However, it can make it harder to understand specific features and changes may affect multiple\nfeatures.\n\nHere, a hybrid approach was used.\nI packaged the UI logic by feature, so all the code related to a specific feature was kept in the same package. However,\nfor the services used in the project, we packaged them by layer, with data and domain kept in the same module. This\nenabled us to reuse the code across features, but without enforcing the creation of separate modules for each layer.\nInstead, we kept them as simple Java packages to keep the code base simpler. This approach allowed us to balance the\nadvantages of both packaging by feature and packaging by layer, and resulted in a codebase that was both modular and\neasy-er to maintain.\n\n## Module breakdown\n\n| Name                            | Responsibilities                                                                                                                    |\n|---------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|\n| `app:main`                      | Defines the Application and MainActivity as the main entry point of the application.                                                |\n| `app:playground`                | Enables testing of mocked screens, components, and navigation flows, making it easier to test and debug the application.            |\n| `feature:match-day`             | Contains UI components and UI logic related to the MatchDay feature.                                                                |\n| `feature:match-thread`          | Contains UI components and UI logic related to the MatchThread feature.                                                             |\n| `core:common`                   | Contains network components and other shared components.                                                                            |\n| `core:design-system`            | Contains shared UI elements used throughout the application.                                                                        |\n| `core:reddit`                   | Serves as a single source of truth for Reddit data and exposes repository abstractions and use cases related to Reddit.             |\n| `core:footballdata`             | Serves as a single source of truth for Footballdata data and exposes repository abstractions and use cases related to Footballdata. |\n| `core:webview-to-native-player` | Scrapes and plays web video content natively.                                                                                       |\n\n### Module Graph\n\n```mermaid\n%%{\n  init: {\n    'theme': 'base',\n\t'themeVariables': {\"primaryTextColor\":\"#fff\",\"primaryColor\":\"#5a4f7c\",\"primaryBorderColor\":\"#5a4f7c\",\"lineColor\":\"#f5a623\",\"tertiaryColor\":\"#40375c\",\"fontSize\":\"11px\"}\n  }\n}%%\n\ngraph LR\n  subgraph app\n    main\n    playground\n  end\n  subgraph core\n    common\n    design-system\n    footballinfo\n    reddit\n    webview-to-native-player\n  end\n  subgraph features\n    match-day\n    match-thread\n  end\n  footballinfo --\u003e common\n  match-day --\u003e common\n  match-day --\u003e footballinfo\n  match-day --\u003e design-system\n  match-day --\u003e reddit\n  match-thread --\u003e webview-to-native-player\n  match-thread --\u003e common\n  match-thread --\u003e footballinfo\n  match-thread --\u003e design-system\n  match-thread --\u003e reddit\n  playground --\u003e webview-to-native-player\n  playground --\u003e match-thread\n  playground --\u003e match-day\n  playground --\u003e design-system\n  reddit --\u003e common\n  webview-to-native-player --\u003e common\n  main --\u003e match-thread\n  main --\u003e match-day\n  main --\u003e design-system\n  main --\u003e common\n```\n# Testing with mock-web-server:\n\nYou can use mockwebserver `docker` image to run quickly run and test app in a controlled environment.\n\n- First, you'll need [docker](https://docs.docker.com/get-docker/) **installed** and **running**.\n- Then, open `./modules/gradle.properties` and change `USE_MOCK_URL` to `true`\n\nNow, when running `./gradlew :modules:app:main:installDebug` we will start mock-web-server and the app will redirect its\nrequest to hit the localhost endpoints instead.\n\n# Static Analysis\n\nYou can run `ktlintFormat` and `detektCheck` to check code style. CI is WIP.\n\n# Building\n\nYou'll need to provide some properties to via the `./modules/local.properties` file build it locally.\n\n```bash\nCLIENT_ID=# Your Reddit client id\nFOOTBALL_INFO_KEY=# Your API key for soccer-football-info.p.rapidapi.com\nFOOTBALL_KEY=# The API key for football-data.org\nkeyAlias=# The key alias\nkeyPassword=# The key password\nstoreFile=# The Path to your keystore\nstorePassword=# The keystore password\n```\n\n# Adding SVG icons\n\nAdd the desired svg icon file in `./assets/icons/svgs/` and then run:\n\n```bash\n$ kotlin svg-to-compose.main.kts\n```\n\nThis will generate a file to programatically create that icon using the compose API and then place it in\nthe `design-system` module, ready to be used.\n\n# Acknowledgements\n\nThe LiveMatch App icon was created using\n\u003ca href=\"https://www.flaticon.com/free-icons/football\" title=\"football icons\"\u003eFootball icons created by Freepik -\nFlaticon\u003c/a\u003e\n\n# TODO\n\n- [x] Use match score from dedicated API\n- [x] Native video player\n- [x] Match highlight comments\n- [x] Light Theme\n- [ ] Match Stats\n- [ ] Github actions CI\n- [ ] Better match events ticker\n- [ ] Reddit comment stream","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiurysza%2Flivematch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiurysza%2Flivematch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiurysza%2Flivematch/lists"}