Skip to content

Commit

Permalink
Merge pull request #64 from swapnil-musale/development
Browse files Browse the repository at this point in the history
Android App Release V1.0.5
  • Loading branch information
swapnil-musale committed Aug 28, 2023
2 parents 78a5658 + e23a0ab commit eb1d416
Show file tree
Hide file tree
Showing 21 changed files with 168 additions and 84 deletions.
48 changes: 41 additions & 7 deletions .github/workflows/android_cd.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
name: Android CD Pipeline
# write permission is required to create release through github action

# Grant write permission to create release through github action
permissions:
contents: write

Expand All @@ -9,13 +10,22 @@ on:
- v*

jobs:
validate:
name: Validate Branch
runs-on: ubuntu-latest
steps:
- name: Exit if not on production branch
if: endsWith(github.event.base_ref, 'master') == false
run: exit -1

build:
name: Deploy Android App
needs: validate
name: Build App Release
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')

steps:
- name: Checkout
- name: Checkout Repository
uses: actions/checkout@v3

- name: Set Up JDK 18
Expand All @@ -28,9 +38,13 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Build Release APK
id: buildReleaseApk
run: ./gradlew assembleRelease --stacktrace

- name: Build Release AAB
id: buildRelease
run: ./gradlew bundleRelease
id: buildReleaseAab
run: ./gradlew bundleRelease --stacktrace

- name: Generate Signed AAB
id: sign
Expand All @@ -42,6 +56,11 @@ jobs:
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}

deploy:
needs: build
name: Create release on PlayStore
runs-on: ubuntu-latest
steps:
- name: Deploy to Play Store
id: deploy
uses: r0adkll/upload-google-play@v1.1.1
Expand All @@ -52,16 +71,31 @@ jobs:
track: production
status: completed
inAppUpdatePriority: 2
whatsNewDirectory: distribution/whatsnew

upload:
needs: build
name: Upload Build Artifact on Github
runs-on: ubuntu-latest
steps:
- name: Upload Release Build
uses: actions/upload-artifact@v3
with:
name: release-artifacts
path: app/build/outputs/bundle/release/
path: |
app/build/outputs/apk/release/
app/build/outputs/bundle/release/
release:
needs: build
name: Prepare Github Release
runs-on: ubuntu-latest
steps:
- name: Create Github Release
uses: softprops/action-gh-release@v1
with:
generate_release_notes: true
prerelease: false
files: app/build/outputs/bundle/release/app-release.aab
files: |
app/build/outputs/apk/release/app-release.apk
app/build/outputs/bundle/release/app-release.aab
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
.externalNativeBuild
.cxx
local.properties
deploymentTargetDropDown.xml
34 changes: 21 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,27 @@ JetJoke project use [Joke API](https://sv443.net/jokeapi/v2/) to fetch and displ

## License :
```
Copyright 2023 Swapnil Musale
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
MIT License
Copyright (c) 2023 Swapnil Musale
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

</br>
6 changes: 2 additions & 4 deletions app/src/main/java/com/devx/jetjoke/ui/home/HomeScreen.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.devx.jetjoke.ui.home

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
Expand Down Expand Up @@ -41,10 +40,9 @@ import com.devx.jetjoke.ui.home.component.JokeCategoryTag
import com.devx.jetjoke.ui.home.component.TypewriterText
import com.devx.jetjoke.ui.shimmer.JokeShimmerItem

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun HomeScreen(
uiState: HomeScreenState,
uiState: HomeScreenUiState,
loadNextJoke: () -> Unit,
) {
var displayJoke by remember { mutableStateOf("") }
Expand Down Expand Up @@ -127,7 +125,7 @@ fun HomeScreen(
private fun HomeScreenPreview() {
JetJokeTheme {
HomeScreen(
uiState = HomeScreenState(
uiState = HomeScreenUiState(
isLoading = false,
jokeData = getFakeJokeData(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ package com.devx.jetjoke.ui.home

import com.devx.domain.model.JokeResponse

data class HomeScreenState(
data class HomeScreenUiState(
val isLoading: Boolean = false,
val jokeData: JokeResponse? = null,
val errorMessage: String? = null,
)
33 changes: 23 additions & 10 deletions app/src/main/java/com/devx/jetjoke/ui/home/HomeViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.devx.jetjoke.ui.home
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.devx.domain.useCase.GetJokeUseCase
import com.devx.domain.util.NetworkResponse
import com.devx.jetjoke.util.DispatchersProvider
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
Expand All @@ -18,9 +19,9 @@ class HomeViewModel @Inject constructor(
private val dispatchersProvider: DispatchersProvider,
) : ViewModel() {

private val _uiState: MutableStateFlow<HomeScreenState> =
MutableStateFlow(value = HomeScreenState())
val uiState: StateFlow<HomeScreenState> = _uiState.asStateFlow()
private val _uiState: MutableStateFlow<HomeScreenUiState> =
MutableStateFlow(value = HomeScreenUiState())
val uiState: StateFlow<HomeScreenUiState> = _uiState.asStateFlow()

init {
fetchJoke()
Expand All @@ -31,13 +32,25 @@ class HomeViewModel @Inject constructor(
_uiState.update {
it.copy(isLoading = true)
}
val response = getJokeUseCase()
if (response.error?.not() == true) {
_uiState.update {
it.copy(
isLoading = false,
jokeData = response,
)
when (val response = getJokeUseCase()) {
is NetworkResponse.Success -> {
_uiState.update {
it.copy(
isLoading = false,
jokeData = response.data,
)
}
}

is NetworkResponse.Error -> {
// TODO Show Snack bar
_uiState.update {
it.copy(isLoading = false, errorMessage = response.errorMessage)
}
}

is NetworkResponse.Exception -> {
// TODO Show Snack bar
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions data/src/main/java/com/devx/data/JokeApi.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.devx.data

import com.devx.data.model.JokeResponse
import com.devx.data.model.JokeResponseDto
import retrofit2.Response
import retrofit2.http.GET

interface JokeApi {

@GET("joke/Any")
suspend fun getJoke(): Response<JokeResponse>
suspend fun getJoke(): Response<JokeResponseDto>
}
15 changes: 0 additions & 15 deletions data/src/main/java/com/devx/data/mapper/JokeResponse.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.devx.data.model

import androidx.annotation.Keep
import com.devx.domain.model.JokeResponse
import com.devx.domain.util.Mapper
import com.squareup.moshi.Json

@Keep
data class JokeResponse(
data class JokeResponseDto(

@field:Json(name = "delivery")
val delivery: String? = null,
Expand Down Expand Up @@ -35,4 +37,16 @@ data class JokeResponse(

@field:Json(name = "message")
val message: String? = null,
)
) : Mapper<JokeResponse> {
override fun mapToDomain(): JokeResponse {
return JokeResponse(
error = error ?: false,
type = type.orEmpty(),
setUp = setup,
joke = joke,
delivery = delivery,
category = category.orEmpty(),
message = message,
)
}
}
24 changes: 6 additions & 18 deletions data/src/main/java/com/devx/data/repository/JokeRepositoryImpl.kt
Original file line number Diff line number Diff line change
@@ -1,32 +1,20 @@
package com.devx.data.repository

import com.devx.data.JokeApi
import com.devx.data.mapper.toDto
import com.devx.data.model.JokeCategoryData
import com.devx.data.util.safeApiCall
import com.devx.domain.model.JokeResponse
import com.devx.domain.repository.JokeRepository
import com.devx.domain.util.NetworkResponse
import javax.inject.Inject

class JokeRepositoryImpl @Inject constructor(private val jokeApi: JokeApi) : JokeRepository {

override suspend fun getJoke(): JokeResponse {
return try {
val response = jokeApi.getJoke()
response.body().toDto()
} catch (exception: Exception) {
JokeResponse(
joke = "",
setUp = "",
delivery = "",
category = "",
type = "",
error = true,
message = exception.message,
)
}
override suspend fun getJoke(): NetworkResponse<JokeResponse> {
return safeApiCall { jokeApi.getJoke() }
}

override fun getJokeCategories(): ArrayList<String> {
return JokeCategoryData.jokeCategories
override fun getJokeCategories(): NetworkResponse<List<String>> {
return NetworkResponse.Success(data = JokeCategoryData.jokeCategories)
}
}
22 changes: 22 additions & 0 deletions data/src/main/java/com/devx/data/util/NetworkUtil.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.devx.data.util

import com.devx.domain.util.Mapper
import com.devx.domain.util.NetworkResponse
import retrofit2.HttpException
import retrofit2.Response

suspend fun <R : Mapper<T>, T : Any> safeApiCall(execute: suspend () -> Response<R>): NetworkResponse<T> {
return try {
val response = execute()
val body = response.body()
if (response.isSuccessful && body != null) {
NetworkResponse.Success(data = body.mapToDomain())
} else {
NetworkResponse.Error(errorMessage = response.message())
}
} catch (exception: HttpException) {
NetworkResponse.Error(errorMessage = exception.localizedMessage)
} catch (throwable: Throwable) {
NetworkResponse.Exception(throwable = throwable)
}
}
3 changes: 0 additions & 3 deletions distribution/whatsnew-en-US

This file was deleted.

1 change: 1 addition & 0 deletions distribution/whatsnew/whatsnew-en-US
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
App Performance Improvement
2 changes: 1 addition & 1 deletion domain/src/main/java/com/devx/domain/model/JokeResponse.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ data class JokeResponse(
fun getFakeJokeData(): JokeResponse {
return JokeResponse(
error = false,
type = "twopart", // "single"
type = "twopart",
setUp = "So what's a set of predefined steps the government might take to preserve the environment?",
delivery = "An Al-Gore-ithm.",
category = "Programming",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.devx.domain.repository

import com.devx.domain.model.JokeResponse
import com.devx.domain.util.NetworkResponse

interface JokeRepository {
suspend fun getJoke(): JokeResponse
fun getJokeCategories(): ArrayList<String>
suspend fun getJoke(): NetworkResponse<JokeResponse>
fun getJokeCategories(): NetworkResponse<List<String>>
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.devx.domain.useCase

import com.devx.domain.repository.JokeRepository
import com.devx.domain.util.NetworkResponse
import javax.inject.Inject

class GetJokeCategoriesUseCase @Inject constructor(private val jokeRepository: JokeRepository) {
operator fun invoke(): ArrayList<String> {
operator fun invoke(): NetworkResponse<List<String>> {
return jokeRepository.getJokeCategories()
}
}
Loading

0 comments on commit eb1d416

Please sign in to comment.