Merge pull request #106 from SELab1/feed

Feed
This commit is contained in:
brreynie 2023-05-09 23:16:23 +02:00 committed by GitHub Enterprise
commit e8c073039e
12 changed files with 143 additions and 49 deletions

View file

@ -2,6 +2,7 @@ package be.ugent.sel.studeez.common.composable
import androidx.annotation.StringRes
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
@ -20,6 +21,7 @@ import androidx.compose.material.icons.filled.Add
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@ -48,6 +50,7 @@ fun BasicButton(
modifier: Modifier = Modifier,
colors: ButtonColors = ButtonDefaults.buttonColors(),
border: BorderStroke? = null,
enabled: Boolean = true,
onClick: () -> Unit,
) {
Button(
@ -56,6 +59,7 @@ fun BasicButton(
shape = defaultButtonShape(),
colors = colors,
border = border,
enabled = enabled,
) {
Text(
text = stringResource(text),
@ -74,17 +78,22 @@ fun BasicButtonPreview() {
fun StealthButton(
@StringRes text: Int,
modifier: Modifier = Modifier.card(),
enabled: Boolean = true,
onClick: () -> Unit,
) {
//val clickablemodifier = if (disabled) Modifier.clickable(indication = null) else modifier
val borderColor = if (enabled) MaterialTheme.colors.primary
else MaterialTheme.colors.onSurface.copy(alpha = 0.3f)
BasicButton(
text = text,
onClick = onClick,
modifier = modifier,
enabled = enabled,
colors = ButtonDefaults.buttonColors(
backgroundColor = MaterialTheme.colors.surface,
contentColor = MaterialTheme.colors.onSurface.copy(alpha = 0.4f)
contentColor = borderColor
),
border = BorderStroke(3.dp, MaterialTheme.colors.onSurface.copy(alpha = 0.4f))
border = BorderStroke(2.dp, borderColor)
)
}

View file

@ -9,58 +9,105 @@ import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import be.ugent.sel.studeez.common.composable.BasicTextButton
import be.ugent.sel.studeez.common.composable.DateText
import be.ugent.sel.studeez.common.composable.Headline
import be.ugent.sel.studeez.common.ext.textButton
import be.ugent.sel.studeez.data.local.models.FeedEntry
import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds
import be.ugent.sel.studeez.R.string as AppText
@Composable
fun Feed(
uiState: FeedUiState,
continueTask: (String, String) -> Unit,
onEmptyFeedHelp: () -> Unit
) {
when (uiState) {
FeedUiState.Loading -> {
Column(
FeedUiState.Loading -> LoadingFeed()
is FeedUiState.Succes -> LoadedFeed(
uiState = uiState,
continueTask = continueTask,
onEmptyFeedHelp = onEmptyFeedHelp
)
}
}
@Composable
fun LoadedFeed(
uiState: FeedUiState.Succes,
continueTask: (String, String) -> Unit,
onEmptyFeedHelp: () -> Unit,
) {
if (uiState.feedEntries.isEmpty()) EmptyFeed(onEmptyFeedHelp)
else FeedWithElements(uiState = uiState, continueTask = continueTask)
}
@Composable
fun LoadingFeed() {
Column(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
CircularProgressIndicator(color = MaterialTheme.colors.onBackground)
}
}
@Composable
fun FeedWithElements(
uiState: FeedUiState.Succes,
continueTask: (String, String) -> Unit,
) {
val feedEntries = uiState.feedEntries
LazyColumn {
items(feedEntries.toList()) { (date, feedEntries) ->
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
.padding(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
CircularProgressIndicator(color = MaterialTheme.colors.onBackground)
val totalDayStudyTime: Int = feedEntries.sumOf { it.totalStudyTime }
DateText(date = date)
Text(
text = "${HoursMinutesSeconds(totalDayStudyTime)}",
fontSize = 15.sp,
fontWeight = FontWeight.Bold
)
}
}
is FeedUiState.Succes -> {
val feedEntries = uiState.feedEntries
LazyColumn {
items(feedEntries.toList()) { (date, feedEntries) ->
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
val totalDayStudyTime: Int = feedEntries.sumOf { it.totalStudyTime }
DateText(date = date)
Text(
text = "${HoursMinutesSeconds(totalDayStudyTime)}",
fontSize = 15.sp,
fontWeight = FontWeight.Bold
)
}
feedEntries.forEach { feedEntry ->
FeedEntry(feedEntry = feedEntry) {
continueTask(feedEntry.subjectId, feedEntry.taskId)
}
}
Spacer(modifier = Modifier.height(20.dp))
feedEntries.forEach { feedEntry ->
FeedEntry(feedEntry = feedEntry) {
continueTask(feedEntry.subjectId, feedEntry.taskId)
}
}
Spacer(modifier = Modifier.height(20.dp))
}
}
}
@Composable
fun EmptyFeed(onEmptyFeedHelp: () -> Unit) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
) {
Headline(text = stringResource(id = AppText.your_feed))
BasicTextButton(
AppText.empty_feed_help_text,
Modifier.textButton(),
action = onEmptyFeedHelp,
)
}
}
}
@ -70,7 +117,7 @@ fun Feed(
fun FeedLoadingPreview() {
Feed(
uiState = FeedUiState.Loading,
continueTask = { _, _ -> run {} },
continueTask = { _, _ -> run {} }, {}
)
}
@ -108,6 +155,6 @@ fun FeedPreview() {
)
)
),
continueTask = { _, _ -> run {} },
continueTask = { _, _ -> run {} }, {}
)
}

View file

@ -18,6 +18,7 @@ import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.StealthButton
import be.ugent.sel.studeez.data.local.models.FeedEntry
import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds
import be.ugent.sel.studeez.R.string as AppText
@Composable
fun FeedEntry(
@ -69,14 +70,19 @@ fun FeedEntry(
Text(text = HoursMinutesSeconds(feedEntry.totalStudyTime).toString())
}
}
val buttonText: Int = if (feedEntry.isArchived) AppText.deleted else AppText.continue_task
StealthButton(
text = R.string.continue_task,
text = buttonText,
enabled = !feedEntry.isArchived,
modifier = Modifier
.padding(start = 10.dp, end = 5.dp)
.weight(6f)
) {
continueWithTask()
if (!feedEntry.isArchived) {
continueWithTask()
}
}
}
}
}

View file

@ -38,4 +38,8 @@ class FeedViewModel @Inject constructor(
open(StudeezDestinations.TIMER_SELECTION_SCREEN)
}
}
fun onEmptyFeedHelp(open: (String) -> Unit) {
open(StudeezDestinations.ADD_SUBJECT_FORM)
}
}

View file

@ -1,14 +1,25 @@
package be.ugent.sel.studeez.common.ext
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.unit.dp
fun Modifier.textButton(): Modifier {
return this.fillMaxWidth().padding(16.dp, 8.dp, 16.dp, 0.dp)
}
fun Modifier.noRippleClickable(onClick: () -> Unit): Modifier = composed {
clickable(indication = null,
interactionSource = remember { MutableInteractionSource() }) {
onClick()
}
}
fun Modifier.basicButton(): Modifier {
return this.fillMaxWidth().padding(16.dp, 8.dp)
}

View file

@ -9,5 +9,6 @@ data class FeedEntry(
val taskId: String = "", // Name of task is not unique
val subjectId: String = "",
val totalStudyTime: Int = 0,
val endTime: Timestamp = Timestamp(0, 0)
val endTime: Timestamp = Timestamp(0, 0),
val isArchived: Boolean = false
)

View file

@ -74,7 +74,8 @@ class FirebaseFeedDAO @Inject constructor(
taskId = task.id,
subjectId = subject.id,
totalStudyTime = sessionReport.studyTime,
endTime = sessionReport.endTime
endTime = sessionReport.endTime,
isArchived = task.archived || subject.archived
)
}
}

View file

@ -32,6 +32,7 @@ fun HomeRoute(
navigationBarActions = navigationBarActions,
feedUiState = feedUiState,
continueTask = { subjectId, taskId -> feedViewModel.continueTask(open, subjectId, taskId) },
onEmptyFeedHelp = { feedViewModel.onEmptyFeedHelp(open) }
)
}
@ -42,6 +43,7 @@ fun HomeScreen(
navigationBarActions: NavigationBarActions,
feedUiState: FeedUiState,
continueTask: (String, String) -> Unit,
onEmptyFeedHelp: () -> Unit,
) {
PrimaryScreenTemplate(
title = resources().getString(R.string.home),
@ -49,7 +51,7 @@ fun HomeScreen(
navigationBarActions = navigationBarActions,
// TODO barAction = { FriendsAction() }
) {
Feed(feedUiState, continueTask)
Feed(feedUiState, continueTask, onEmptyFeedHelp)
}
}
@ -101,5 +103,6 @@ fun HomeScreenPreview() {
)
),
continueTask = { _, _ -> run {} },
onEmptyFeedHelp = {}
)
}

View file

@ -82,12 +82,13 @@ fun TimerOverviewScreen(
items(timers.value) { timerInfo ->
TimerEntry(
timerInfo = timerInfo,
) {
StealthButton(
text = R.string.edit,
onClick = { timerOverviewActions.onEditClick(timerInfo) }
)
}
rightButton = {
StealthButton(
text = R.string.edit,
onClick = { timerOverviewActions.onEditClick(timerInfo) }
)
}
)
}

View file

@ -1,10 +1,13 @@
package be.ugent.sel.studeez.screens.timer_selection
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
import be.ugent.sel.studeez.common.composable.StealthButton
@ -99,7 +102,10 @@ fun CustomTimerEntry(
)
},
rightButton = {
TimePickerButton(initialSeconds = hms.getTotalSeconds()) { chosenTime ->
TimePickerButton(
initialSeconds = hms.getTotalSeconds(),
modifier = Modifier.padding(horizontal = 5.dp)
) { chosenTime ->
timerInfo.studyTime = chosenTime
}
}

View file

@ -5,6 +5,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import be.ugent.sel.studeez.data.SelectedTimerState
import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.domain.TimerDAO
@ -21,7 +22,9 @@ class TimerSelectionViewModel @Inject constructor(
logService: LogService
) : StudeezViewModel(logService) {
var customTimerStudyTime: MutableState<Int> = mutableStateOf(0)
var customTimerStudyTime: MutableState<Int> = mutableStateOf(
HoursMinutesSeconds(1, 0, 0).getTotalSeconds()
)
fun getAllTimers() : Flow<List<TimerInfo>> {
return timerDAO.getAllTimers()

View file

@ -31,6 +31,8 @@
<!-- Feed-->
<string name="continue_task">Continue</string>
<string name="your_feed">This is your feed</string>
<string name="empty_feed_help_text">Create you first subject and tasks to get started</string>
<!-- Tasks -->
<string name="tasks">Tasks</string>