Skip to content

Commit

Permalink
Merge pull request #42 from Jacob3075/WTA-20/clean-up-previews
Browse files Browse the repository at this point in the history
Added previews to different screens.
  • Loading branch information
Jacob3075 authored Oct 17, 2022
2 parents 0273bd1 + 179853c commit 3cf2828
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@ package com.jacob.wakatimeapp.navigation

import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import com.jacob.wakatimeapp.home.ui.HomePageContent
import com.jacob.wakatimeapp.home.ui.HomePageNavigator
import com.jacob.wakatimeapp.login.ui.LoginPageContent
import com.jacob.wakatimeapp.home.ui.HomePageScreen
import com.jacob.wakatimeapp.login.ui.LoginPageNavigator
import com.jacob.wakatimeapp.login.ui.LoginPageScreen
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph

@RootNavGraph(start = true)
@Destination
@Composable
fun LoginPage(loginPageNavigator: LoginPageNavigator, scaffoldState: SnackbarHostState) =
LoginPageContent(loginPageNavigator = loginPageNavigator, snackbarHostState = scaffoldState)
LoginPageScreen(loginPageNavigator = loginPageNavigator, snackbarHostState = scaffoldState)

@Composable
@Destination
fun HomePage(
homePageNavigator: HomePageNavigator,
scaffoldState: SnackbarHostState,
) = HomePageContent(
) = HomePageScreen(
navigator = homePageNavigator,
snackbarHostState = scaffoldState
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.jacob.wakatimeapp.home.domain.models

import com.jacob.wakatimeapp.core.models.Project
import com.jacob.wakatimeapp.core.models.Time
import com.jacob.wakatimeapp.core.models.UserDetails
import com.jacob.wakatimeapp.core.models.WeeklyStats
import kotlinx.datetime.LocalDate
import kotlinx.serialization.Serializable
Expand All @@ -14,13 +15,17 @@ data class HomePageUiData(
val mostUsedLanguage: String,
val mostUsedEditor: String,
val mostUsedOs: String,
val photoUrl: String,
val fullName: String,
)

fun WeeklyStats.toLoadedStateData() = HomePageUiData(
fun WeeklyStats.toLoadedStateData(userDetails: UserDetails) = HomePageUiData(
timeSpentToday = todaysStats.timeSpent,
projectsWorkedOn = todaysStats.projectsWorkedOn,
weeklyTimeSpent = dailyStats.associate { it.date to it.timeSpent },
mostUsedLanguage = todaysStats.mostUsedLanguage,
mostUsedEditor = todaysStats.mostUsedEditor,
mostUsedOs = todaysStats.mostUsedOs,
photoUrl = userDetails.photoUrl,
fullName = userDetails.fullName,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.jacob.wakatimeapp.home.domain.usecases

import arrow.core.left
import com.jacob.wakatimeapp.core.models.Error
import com.jacob.wakatimeapp.core.models.WeeklyStats
import com.jacob.wakatimeapp.core.models.UserDetails
import com.jacob.wakatimeapp.home.data.local.HomePageCache
import com.jacob.wakatimeapp.home.data.network.HomePageNetworkData
import com.jacob.wakatimeapp.home.domain.InstantProvider
Expand Down Expand Up @@ -31,19 +31,22 @@ class GetLast7DaysStatsUC @Inject constructor(
) {
private val ioScope = CoroutineScope(dispatcher)

operator fun invoke(cacheValidity: CacheValidity = INVALID) = channelFlow {
val lastRequestTime = homePageCache.getLastRequestTime()
operator fun invoke(userDetails: UserDetails, cacheValidity: CacheValidity = INVALID) =
channelFlow {
val lastRequestTime = homePageCache.getLastRequestTime()

when {
firstRequestOfDay(lastRequestTime) -> makeRequestAndUpdateCache()?.let { send(it) }
!validDataInCache(
lastRequestTime,
cacheValidity
) -> launch { makeRequestAndUpdateCache()?.let { send(it) } }
}
when {
firstRequestOfDay(lastRequestTime) ->
makeRequestAndUpdateCache(userDetails)?.let { send(it) }

dataFromCache().collect { send(it) }
}
!validDataInCache(
lastRequestTime,
cacheValidity
) -> launch { makeRequestAndUpdateCache(userDetails)?.let { send(it) } }
}

dataFromCache().collect { send(it) }
}

private fun dataFromCache() = homePageCache.getCachedData()
.catch { throwable ->
Expand All @@ -57,10 +60,11 @@ class GetLast7DaysStatsUC @Inject constructor(
*
* Returns an [Either.Left<Error>] if any errors happened.
*/
private suspend fun makeRequestAndUpdateCache() = homePageNetworkData.getLast7DaysStats()
.map(WeeklyStats::toLoadedStateData)
.tap { it.updateCaches() }
.fold(ifLeft = Error::left, ifRight = { null })
private suspend fun makeRequestAndUpdateCache(userDetails: UserDetails) =
homePageNetworkData.getLast7DaysStats()
.map { it.toLoadedStateData(userDetails) }
.tap { it.updateCaches() }
.fold(ifLeft = Error::left, ifRight = { null })

private suspend fun HomePageUiData.updateCaches() {
listOf(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.jacob.wakatimeapp.home.ui

import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
Expand All @@ -16,21 +17,27 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import androidx.hilt.navigation.compose.hiltViewModel
import com.jacob.wakatimeapp.core.models.Error
import com.jacob.wakatimeapp.core.models.Time
import com.jacob.wakatimeapp.core.ui.components.WtaAnimation
import com.jacob.wakatimeapp.core.ui.components.cards.TimeSpentCard
import com.jacob.wakatimeapp.core.ui.theme.WakaTimeAppTheme
import com.jacob.wakatimeapp.core.ui.theme.assets
import com.jacob.wakatimeapp.core.ui.theme.gradients
import com.jacob.wakatimeapp.core.ui.theme.spacing
import com.jacob.wakatimeapp.home.domain.models.HomePageUiData
import com.jacob.wakatimeapp.home.ui.components.OtherDailyStatsSection
import com.jacob.wakatimeapp.home.ui.components.RecentProjects
import com.jacob.wakatimeapp.home.ui.components.UserDetailsSection
import com.jacob.wakatimeapp.home.ui.components.WeeklyReport
import kotlinx.coroutines.launch
import timber.log.Timber

@Composable
fun HomePageContent(
fun HomePageScreen(
navigator: HomePageNavigator,
snackbarHostState: SnackbarHostState,
modifier: Modifier = Modifier,
Expand All @@ -40,13 +47,9 @@ fun HomePageContent(
val viewState by viewModel.homePageState.collectAsState()

LaunchedEffect(viewState) {
Timber.d(viewState.toString())
if (viewState !is HomePageViewState.Error) return@LaunchedEffect
val viewStateError = viewState as HomePageViewState.Error

Timber.e(viewStateError.error.message)
Timber.e(viewStateError.error.exception)

snackBarCoroutineScope.launch {
snackbarHostState.showSnackbar(
message = viewStateError.error.message,
Expand All @@ -55,23 +58,36 @@ fun HomePageContent(
}
}

HomePageContent(
viewState = viewState,
toDetailsPage = navigator::toDetailsPage,
modifier = modifier
)
}

@Composable
private fun HomePageContent(
viewState: HomePageViewState,
toDetailsPage: () -> Unit,
modifier: Modifier = Modifier,
) {
Column(modifier = modifier.statusBarsPadding()) {
when (val viewSateInstance = viewState) {
when (viewState) {
is HomePageViewState.Loading -> HomePageLoading()
is HomePageViewState.Loaded -> HomePageLoaded(
homePageViewState = viewSateInstance,
navigator = navigator
homePageViewState = viewState,
toDetailsPage = toDetailsPage,
)

is HomePageViewState.Error -> HomePageError(viewSateInstance)
is HomePageViewState.Error -> HomePageError(viewState)
}
}
}

@Composable
private fun HomePageLoaded(
homePageViewState: HomePageViewState.Loaded,
navigator: HomePageNavigator,
toDetailsPage: () -> Unit,
) {
val scrollState = rememberScrollState()
val spacing = MaterialTheme.spacing
Expand All @@ -81,15 +97,18 @@ private fun HomePageLoaded(
.padding(horizontal = spacing.medium)
.verticalScroll(scrollState)
) {
UserDetailsSection(homePageViewState.userDetails)
UserDetailsSection(
fullName = homePageViewState.contentData.photoUrl,
photoUrl = homePageViewState.contentData.fullName
)

TimeSpentCard(
gradient = MaterialTheme.gradients.primary,
roundedCornerPercent = 25,
iconId = icons.time,
mainText = "Total Time Spent Today",
time = homePageViewState.contentData.timeSpentToday,
onClick = navigator::toDetailsPage
onClick = toDetailsPage
)
Spacer(modifier = Modifier.height(spacing.small))

Expand Down Expand Up @@ -122,3 +141,41 @@ private fun HomePageLoading() = WtaAnimation(
text = "Loading..",
animationTestTag = HomePageTestTags.LOADING_ANIMATION_ILLUSTRATION
)

@Preview(
apiLevel = 31,
showSystemUi = true,
showBackground = true,
uiMode = Configuration.UI_MODE_NIGHT_NO or Configuration.UI_MODE_TYPE_NORMAL,
)
@Preview(
apiLevel = 31,
showSystemUi = true,
showBackground = true,
uiMode = Configuration.UI_MODE_NIGHT_YES
)
@Composable
fun HomePagePreview(
@PreviewParameter(HomePagePreviewProvider::class) viewState: HomePageViewState,
) = WakaTimeAppTheme {
HomePageContent(viewState = viewState, toDetailsPage = { })
}

class HomePagePreviewProvider : CollectionPreviewParameterProvider<HomePageViewState>(
listOf(
HomePageViewState.Loading,
HomePageViewState.Error(Error.UnknownError("Something went wrong")),
HomePageViewState.Loaded(
contentData = HomePageUiData(
timeSpentToday = Time.ZERO,
projectsWorkedOn = listOf(),
weeklyTimeSpent = mapOf(),
mostUsedLanguage = "",
mostUsedEditor = "",
mostUsedOs = "",
photoUrl = "",
fullName = "",
)
),
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch

@HiltViewModel
Expand All @@ -32,18 +32,14 @@ class HomePageViewModel @Inject constructor(

init {
viewModelScope.launch(ioDispatcher) {
combine(
getLast7DaysStatsUC(),
userDetailsFlow,
) { either, userDetails ->
when (either) {
is Left -> HomePageViewState.Error(either.value)
getLast7DaysStatsUC(userDetailsFlow.first()).collect {
_homePageState.value = when (it) {
is Left -> HomePageViewState.Error(it.value)
is Right -> HomePageViewState.Loaded(
contentData = either.value,
userDetails = userDetails
contentData = it.value,
)
}
}.collect { _homePageState.value = it }
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package com.jacob.wakatimeapp.home.ui

import com.jacob.wakatimeapp.core.models.Error as CoreModelsError
import com.jacob.wakatimeapp.core.models.UserDetails
import com.jacob.wakatimeapp.home.domain.models.HomePageUiData

sealed class HomePageViewState {
data class Loaded(
val contentData: HomePageUiData,
val userDetails: UserDetails?,
) : HomePageViewState()

data class Error(val error: CoreModelsError) : HomePageViewState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ import androidx.compose.ui.unit.sp
import coil.compose.rememberAsyncImagePainter
import coil.request.ImageRequest.Builder
import coil.transform.CircleCropTransformation
import com.jacob.wakatimeapp.core.models.UserDetails
import com.jacob.wakatimeapp.core.ui.theme.WakaTimeAppTheme
import com.jacob.wakatimeapp.core.ui.theme.assets
import com.jacob.wakatimeapp.core.ui.theme.pageTitle
import com.jacob.wakatimeapp.core.ui.theme.spacing

@Composable
fun UserDetailsSection(
userDetails: UserDetails?,
fullName: String,
photoUrl: String,
modifier: Modifier = Modifier,
) = Row(
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.medium),
Expand All @@ -37,7 +37,7 @@ fun UserDetailsSection(
) {
Image(
painter = rememberAsyncImagePainter(
Builder(LocalContext.current).data(data = userDetails?.photoUrl)
Builder(LocalContext.current).data(data = photoUrl)
.apply {
val icons = MaterialTheme.assets.icons
transformations(CircleCropTransformation())
Expand All @@ -50,7 +50,7 @@ fun UserDetailsSection(
modifier = Modifier.size(58.dp)
)
Text(
text = userDetails?.fullName.orEmpty(),
text = fullName,
style = MaterialTheme.typography.pageTitle.copy(
fontSize = 50.sp,
baselineShift = BaselineShift(multiplier = 0.3f),
Expand All @@ -64,20 +64,7 @@ fun UserDetailsSection(
@Composable
private fun UserDetailsPreview() = WakaTimeAppTheme {
UserDetailsSection(
UserDetails(
bio = "",
email = "",
id = "",
timeout = 0,
timezone = "",
username = "",
displayName = "",
lastProject = "",
fullName = "Jacob Bosco",
durationsSliceBy = "",
createdAt = "",
dateFormat = "",
photoUrl = ""
)
fullName = "",
photoUrl = "",
)
}
Loading

0 comments on commit 3cf2828

Please sign in to comment.