Skip to content

Commit

Permalink
Merge pull request #482 from bounswe/development
Browse files Browse the repository at this point in the history
Development Main Merge
  • Loading branch information
Sefik-Palazoglu authored Nov 27, 2023
2 parents 1775b76 + c061f26 commit 5d3199b
Show file tree
Hide file tree
Showing 143 changed files with 9,223 additions and 1,115 deletions.
10 changes: 10 additions & 0 deletions prediction-polls/android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ android {
}
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
Expand All @@ -77,6 +78,8 @@ android {
dependencies {
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.2")

implementation("androidx.activity:activity-compose:1.8.0")
implementation(platform("androidx.compose:compose-bom:2023.10.00"))
implementation("androidx.compose.ui:ui")
Expand Down Expand Up @@ -134,4 +137,11 @@ dependencies {

// Easy Google Login
implementation("com.github.stevdza-san:OneTapCompose:1.0.9")

// Immutable Kotlin Collections
// Used for creating stable domain classes. Check stability meaning in terms of compose if you do not know what I mean.
implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.6")

// For date transformation
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ class NavigationDrawerTest {

composeTestRule.setContent {
titles = titleIds.map { stringResource(id = it) }
NavigationDrawer(
selectedNavItem = NavItem.FEED
) {
NavigationDrawer() {
Button(
onClick = {
it()
Expand Down Expand Up @@ -56,7 +54,6 @@ class NavigationDrawerTest {
composeTestRule.setContent {
clickedTitle = stringResource(id = NavItem.PROFILE.titleId)
NavigationDrawer(
selectedNavItem = selectedNavItem,
onButtonClick = {
selectedNavItem = it
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,110 @@
package com.bounswe.predictionpolls

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavOptions
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.bounswe.predictionpolls.data.remote.TokenManager
import com.bounswe.predictionpolls.ui.common.CommonAppbar
import com.bounswe.predictionpolls.ui.common.NavigationDrawer
import com.bounswe.predictionpolls.ui.create.createPollScreen
import com.bounswe.predictionpolls.ui.feed.feedScreen
import com.bounswe.predictionpolls.ui.leaderboard.leaderboardScreen
import com.bounswe.predictionpolls.ui.login.loginScreen
import com.bounswe.predictionpolls.ui.main.MAIN_ROUTE
import com.bounswe.predictionpolls.ui.main.mainScreen
import com.bounswe.predictionpolls.ui.main.navigateToMainScreen
import com.bounswe.predictionpolls.ui.profile.profileScreen
import com.bounswe.predictionpolls.ui.signup.signupScreen
import com.bounswe.predictionpolls.ui.theme.PredictionPollsTheme
import com.bounswe.predictionpolls.ui.vote.pollVoteScreen
import com.bounswe.predictionpolls.utils.NavItem
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject
lateinit var tokenManager: TokenManager

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
PredictionPollsTheme {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = MAIN_ROUTE) {
mainScreen(navController)
loginScreen(navController)
signupScreen(navController)
feedScreen(navController)
leaderboardScreen(navController)
val routesWithDrawer = remember { NavItem.entries.map { it.route }.toSet() }
val currentBackStack = navController.currentBackStackEntryAsState()
val currentRoute = rememberUpdatedState(currentBackStack.value?.destination?.route)
val isUserLoggedIn = tokenManager.isLoggedIn.collectAsState(initial = false)
val context = LocalContext.current
val loginRequiredText = stringResource(R.string.login_required_notification)
val logoutSuccessText = stringResource(R.string.logged_out_notification)

NavigationDrawer(
selectedRoute = currentRoute.value,
onButtonClick = {
if (it.requiresAuth && !isUserLoggedIn.value) {
Toast.makeText(context, loginRequiredText, Toast.LENGTH_SHORT).show()
navController.navigateToMainScreen(
navOptions = NavOptions.Builder().setPopUpTo(MAIN_ROUTE, true)
.build()
)
} else {
navController.navigate(it.route)
}
},
isSignedIn = isUserLoggedIn.value,
onAuthButtonClick = {
if (isUserLoggedIn.value) {
tokenManager.clear()
Toast.makeText(context, logoutSuccessText, Toast.LENGTH_SHORT).show()
navController.navigateToMainScreen(
navOptions = NavOptions.Builder().setPopUpTo(MAIN_ROUTE, true)
.build()
)
} else {
navController.navigateToMainScreen(
navOptions = NavOptions.Builder().setPopUpTo(MAIN_ROUTE, true)
.build()
)
}
}
) { toggleDrawerState ->
Column {
CommonAppbar(
isVisible = currentRoute.value in routesWithDrawer,
onMenuClick = { toggleDrawerState() },
onNotificationClick = { /*TODO implement notification */ }
)
NavHost(navController = navController, startDestination = MAIN_ROUTE) {
mainScreen(navController)
loginScreen(navController)
signupScreen(navController)
feedScreen(navController, isUserLoggedIn.value)
leaderboardScreen(navController)
createPollScreen()
profileScreen(navController)
pollVoteScreen(navController)

// TODO: Remove placeholders
composable("settings") { Text(text = "Settings Page WIP") }
composable("notifications") { Text(text = "Notifications Page WIP") }
composable("moderation") { Text(text = "Moderation Page WIP") }
}
}

}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.bounswe.predictionpolls.common

data class PredictionPollsError(val code: String, val message: String)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.bounswe.predictionpolls.common

/**
* A generic class that holds a value or an exception
*/
sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.bounswe.predictionpolls.data.feed

import com.bounswe.predictionpolls.data.feed.model.PollResponse
import retrofit2.http.GET

interface FeedApi {
/**
* Fetches the list of polls and returns the result.
*/
@GET("/polls")
suspend fun getPolls(): List<PollResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.bounswe.predictionpolls.data.feed

import com.bounswe.predictionpolls.common.Result
import com.bounswe.predictionpolls.data.feed.model.PollResponse
import com.bounswe.predictionpolls.domain.poll.Poll

interface FeedRemoteDataSource {
/**
* Fetches the list of polls and returns the result.
*/
suspend fun getPolls(page: Int): Result<List<PollResponse>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.bounswe.predictionpolls.data.feed

import com.bounswe.predictionpolls.common.Result
import com.bounswe.predictionpolls.data.feed.model.PollResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import javax.inject.Inject

class FeedRemoteDataSourceImpl @Inject constructor(
private val feedApi: FeedApi
) : FeedRemoteDataSource {
override suspend fun getPolls(page: Int): Result<List<PollResponse>> = withContext(Dispatchers.IO) {
try {
val response = feedApi.getPolls()
Result.Success(response)
} catch (e: Exception) {
Result.Error(e)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.bounswe.predictionpolls.data.feed

import android.util.Log
import com.bounswe.predictionpolls.common.Result
import com.bounswe.predictionpolls.domain.feed.FeedRepository
import com.bounswe.predictionpolls.domain.poll.Poll
import javax.inject.Inject

private const val TAG = "FeedRepositoryImpl"

class FeedRepositoryImpl @Inject constructor(
private val feedRemoteDataSource: FeedRemoteDataSource
) : FeedRepository {
override suspend fun getPolls(page: Int): Result<List<Poll>> =
when (val result = feedRemoteDataSource.getPolls(page)) {
is Result.Success -> {
val polls = result.data.mapNotNull {
try {
it.toPollDomainModel()
} catch (e: Exception) {
Log.e(TAG, "getPolls: $it cannot be converted to Poll")
null
}
}
Result.Success(polls)
}

is Result.Error -> {
Result.Error(result.exception)
}
}

}
Loading

0 comments on commit 5d3199b

Please sign in to comment.