{"id":21275509,"url":"https://github.com/alinachroma/the-gallery-app","last_synced_at":"2025-08-20T06:13:35.107Z","repository":{"id":251972279,"uuid":"838900077","full_name":"alinachroma/The-Gallery-App","owner":"alinachroma","description":"An Android app that makes requests to a web service and displays the list of images from the placeholder API and gives a possibility to mark them as favourites. Built fully with Jetpack Compose.","archived":false,"fork":false,"pushed_at":"2024-08-06T19:29:57.000Z","size":232,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-15T13:13:19.888Z","etag":null,"topics":["android","compose","coroutines","jetpack-compose","rest-api","retrofit2","room"],"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/alinachroma.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":"2024-08-06T15:00:40.000Z","updated_at":"2024-08-06T19:30:00.000Z","dependencies_parsed_at":"2024-08-06T23:03:08.035Z","dependency_job_id":null,"html_url":"https://github.com/alinachroma/The-Gallery-App","commit_stats":null,"previous_names":["alinachroma/the-gallery-app"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/alinachroma/The-Gallery-App","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alinachroma%2FThe-Gallery-App","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alinachroma%2FThe-Gallery-App/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alinachroma%2FThe-Gallery-App/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alinachroma%2FThe-Gallery-App/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alinachroma","download_url":"https://codeload.github.com/alinachroma/The-Gallery-App/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alinachroma%2FThe-Gallery-App/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271274035,"owners_count":24730913,"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","status":"online","status_checked_at":"2025-08-20T02:00:09.606Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","coroutines","jetpack-compose","rest-api","retrofit2","room"],"created_at":"2024-11-21T09:32:44.095Z","updated_at":"2025-08-20T06:13:35.054Z","avatar_url":"https://github.com/alinachroma.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The Gallery App\n\nAn Android app that makes requests to a web service and displays a list of images from the placeholder API and gives a possibility to mark them as favourites.\nBuilt fully with Jetpack Compose.\n\n## Features\n\n* The app consists of two tabs (`Gallery` and `Favourites`), the first tab displays images from the placeholder API, the second tab displays a list of images that are marked as favourite and stored locally.\n* When the user clicks on an image (`Gallery` tab), the image opens in a bigger size and it is possible to dismiss it or mark it as favourite.\n* As soon as the image is marked as favourite, it is stored in the local database and displayed in the `Favourites` tab. It is also possible to view a favourite image in a bigger size (by clicking on it), and to dismiss or remove it from the list of favourites.\n* The app supports both Light and Dark themes.\n\n## Screenshots\n\u003cimg width=\"700\" alt=\"gallery\" src=\"https://github.com/user-attachments/assets/6d9f0287-967c-4c41-b7bf-75eca6ff533c\"\u003e\n\n## Demo\n| Features | Offline behavior |\n| ------------- | ------------- |\n| \u003cvideo src=\"https://github.com/user-attachments/assets/fc1f655b-dccb-4118-a6b3-75df00598642\"\u003e | \u003cvideo src=\"https://github.com/user-attachments/assets/14007349-b1b4-4429-940c-62393a72e83a\"\u003e| \n\n### UI State management\nThe [GalleryUiState](app/src/main/java/com/example/gallery/ui/GalleryViewModel.kt) defines the data to be displayed in the `Gallery` tab. \nThere are three possible states that the app can handle:\n* `Success` (images are fetched successfully) - UI is represented by the [ResultScreen.kt](app/src/main/java/com/example/gallery/ui/screens/ResultScreen.kt) Composable.\n* `Loading` (images are in progress) - UI is represented by the [LoadingScreen.kt](app/src/main/java/com/example/gallery/ui/screens/LoadingScreen.kt) Composable.\n* `Error` (images are failed to load, connection issues) - UI is represented by the [ErrorScreen.kt](app/src/main/java/com/example/gallery/ui/screens/ErrorScreen.kt) Composable.\nThe [GalleryScreen.kt](app/src/main/java/com/example/gallery/ui/screens/GalleryScreen.kt) Composable wraps the above-mentioned composables (for the `Success`, `Loading` or `Error` state) and displays the content accordingly.\n\n### Architecture Components\n* The `data` layer is represented by the repositories, data classes and services - [GalleryImagesRepository.kt](app/src/main/java/com/example/gallery/data/GalleryImagesRepository.kt), [GalleryApiService.kt](app/src/main/java/com/example/gallery/network/GalleryApiService.kt) - these are fetching the data from the placeholder API. The state of the request is being observed and displayed accordingly, which is defined in the [GalleryViewModel.kt](app/src/main/java/com/example/gallery/ui/GalleryViewModel.kt) with [GalleryUiState.kt](app/src/main/java/com/example/gallery/ui/GalleryViewModel.kt). [FavouriteImagesRepository](app/src/main/java/com/example/gallery/data/FavouriteImagesRepository.kt) and its implementation ([OfflineFavouriteImagesRepository.kt](app/src/main/java/com/example/gallery/data/OfflineFavouriteImagesRepository.kt)) are responsible for the interactions with the local database. The [GalleryImage.kt](app/src/main/java/com/example/gallery/model/GalleryImage.kt) represents the data that we receive from the network. The [FavouriteImage.kt](app/src/main/java/com/example/gallery/model/FavouriteImage.kt) represents a single row in the favourites image database.\n* The `UI` layer is represented by the composables and the state holders (`ViewModel` classes). All the Composables in the `buttons`, `items` and `screens` packages represent elements that are used across the app. For example, the [ImageItem.kt](app/src/main/java/com/example/gallery/ui/items/ImageItem.kt) is used to represent the gallery image as well as the favourite image. The [GalleryViewModel.kt](app/src/main/java/com/example/gallery/ui/GalleryViewModel.kt) exposes properties and commands that the [GalleryScreen.kt](app/src/main/java/com/example/gallery/ui/screens/GalleryScreen.kt)-related UI can bind to, and reacts to user actions and data changes. The [FavouritesViewModel.kt](app/src/main/java/com/example/gallery/ui/FavouritesViewModel.kt) does the same for the [FavouritesScreen.kt](app/src/main/java/com/example/gallery/ui/screens/FavouritesScreen.kt)-related UI.\n* The [GalleryApp.kt](app/src/main/java/com/example/gallery/ui/GalleryApp.kt) is the \"main\" composable that wraps the rest of composables and the only composable the `ViewModels` are called from.\n* The app uses repository pattern and manual dependency injection, this is how the [GalleryViewModel.kt](app/src/main/java/com/example/gallery/ui/GalleryViewModel.kt) and [FavouritesViewModel.kt](app/src/main/java/com/example/gallery/ui/FavouritesViewModel.kt) access [FavouriteImagesRepository.kt](app/src/main/java/com/example/gallery/data/FavouriteImagesRepository.kt) and [GalleryImagesRepository.kt](app/src/main/java/com/example/gallery/data/GalleryImagesRepository.kt) (the repositories are injected).\n\n### Saved state across configuration changes\nBoth [GalleryScreen.kt](app/src/main/java/com/example/gallery/ui/screens/GalleryScreen.kt) and [FavouritesScreen.kt](app/src/main/java/com/example/gallery/ui/screens/FavouritesScreen.kt) survive configuration changes (for example, screen orientation changes). \n\n### Data and persistence\nIf the user marks images as favourites, these will be stored in the [FavouriteImagesDatabase.kt](app/src/main/java/com/example/gallery/data/FavouriteImagesDatabase.kt), so if the user closes the app, the images still will be displayed in the `Favourites` tab after the restart. \n\n### Offline behavior\nIf the uses loses connection or turns on Airplane mode, the app will not be able to fetch the images from the API and the [ErrorScreen.kt](app/src/main/java/com/example/gallery/ui/screens/ErrorScreen.kt) will be shown instead of the [ResultScreen.kt](app/src/main/java/com/example/gallery/ui/screens/ResultScreen.kt). \nIf the uses presses the `Retry` button on the screen, the app will try to make an API call again and as soon as the user is back online, they will be shown the [LoadingScreen.kt](app/src/main/java/com/example/gallery/ui/screens/LoadingScreen.kt) and then the gallery.\n\n### Material Design theming\nThe Gallery App uses [Material Theme Builder](https://material-foundation.github.io/material-theme-builder/) and `MaterialTheme` composable. The app uses a custom, branded color scheme. \n\n## Libraries \u0026 dependencies used in the project:\n\n*   Jetpack Compose (for the UI).\n*   Kotlin coroutines (to load images asynchronously, handle asynchronous computations in general).\n*   Kotlin serialization - tools that are needed for decoding JSON objects, converting data used by an our app to a format that can be stored in the database.\n*   Retrofit (to make API calls).\n*   Room - for data persistence, for storing favourite images in the database.\n*   Coil (for faster image loading and improved overall performance).\n*   Manual Dependency Injection.\n\n## Credits \nThe `ic_connection_error`, `ic_broken_image`, `ic_progress_activity` icons are the icons that were provided by the [Android Codelabs](https://developer.android.com/get-started/codelabs).\n\n\u003ca href=\"https://www.vecteezy.com/free-png/gallery-logo\"\u003eGallery Logo PNGs by Vecteezy\u003c/a\u003e.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falinachroma%2Fthe-gallery-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falinachroma%2Fthe-gallery-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falinachroma%2Fthe-gallery-app/lists"}