merge dev

This commit is contained in:
Rune Dyselinck 2023-04-28 15:50:44 +02:00
commit 94336348c5
24 changed files with 377 additions and 166 deletions

View file

@ -11,6 +11,7 @@ import androidx.compose.material.Surface
import androidx.compose.material.rememberScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
@ -21,9 +22,14 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.common.composable.drawer.DrawerViewModel
import be.ugent.sel.studeez.common.composable.drawer.getDrawerActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel
import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions
import be.ugent.sel.studeez.common.snackbar.SnackbarManager
import be.ugent.sel.studeez.navigation.StudeezDestinations
import be.ugent.sel.studeez.screens.home.HomeRoute
@ -31,6 +37,7 @@ import be.ugent.sel.studeez.screens.log_in.LoginRoute
import be.ugent.sel.studeez.screens.profile.EditProfileRoute
import be.ugent.sel.studeez.screens.profile.ProfileRoute
import be.ugent.sel.studeez.screens.session.SessionRoute
import be.ugent.sel.studeez.screens.session_recap.SessionRecapRoute
import be.ugent.sel.studeez.screens.sign_up.SignUpRoute
import be.ugent.sel.studeez.screens.splash.SplashRoute
import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewRoute
@ -89,43 +96,52 @@ fun StudeezNavGraph(
val drawerViewModel: DrawerViewModel = hiltViewModel()
val navBarViewModel: NavigationBarViewModel = hiltViewModel()
val backStackEntry by appState.navController.currentBackStackEntryAsState()
val getCurrentScreen: () -> String? = { backStackEntry?.destination?.route }
val goBack: () -> Unit = { appState.popUp() }
val open: (String) -> Unit = { appState.navigate(it) }
val openAndPopUp: (String, String) -> Unit =
{ route, popUp -> appState.navigateAndPopUp(route, popUp) }
val drawerActions: DrawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp)
val navigationBarActions: NavigationBarActions =
getNavigationBarActions(navBarViewModel, open, getCurrentScreen)
NavHost(
navController = appState.navController,
startDestination = StudeezDestinations.SPLASH_SCREEN,
modifier = modifier,
) {
val goBack: () -> Unit = {
appState.popUp()
}
val open: (String) -> Unit = { route ->
appState.navigate(route)
}
val openAndPopUp: (String, String) -> Unit = { route, popUp ->
appState.navigateAndPopUp(route, popUp)
}
composable(StudeezDestinations.SPLASH_SCREEN) {
SplashRoute(openAndPopUp, viewModel = hiltViewModel())
SplashRoute(
openAndPopUp,
viewModel = hiltViewModel(),
)
}
composable(StudeezDestinations.LOGIN_SCREEN) {
LoginRoute(openAndPopUp, viewModel = hiltViewModel())
LoginRoute(
openAndPopUp,
viewModel = hiltViewModel(),
)
}
composable(StudeezDestinations.SIGN_UP_SCREEN) {
SignUpRoute(openAndPopUp, viewModel = hiltViewModel())
SignUpRoute(
openAndPopUp,
viewModel = hiltViewModel(),
)
}
composable(StudeezDestinations.HOME_SCREEN) {
HomeRoute(
open,
openAndPopUp,
viewModel = hiltViewModel(),
drawerViewModel = drawerViewModel,
navBarViewModel = navBarViewModel,
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
)
}
@ -133,21 +149,27 @@ fun StudeezNavGraph(
// TODO Sessions screen
composable(StudeezDestinations.PROFILE_SCREEN) {
ProfileRoute(open, openAndPopUp, viewModel = hiltViewModel())
ProfileRoute(
open,
viewModel = hiltViewModel(),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
)
}
composable(StudeezDestinations.TIMER_OVERVIEW_SCREEN) {
TimerOverviewRoute(
open,
openAndPopUp,
viewModel = hiltViewModel(),
drawerViewModel = drawerViewModel,
navBarViewModel = navBarViewModel,
drawerActions = drawerActions,
)
}
composable(StudeezDestinations.SESSION_SCREEN) {
SessionRoute(open, viewModel = hiltViewModel())
SessionRoute(
open,
openAndPopUp,
viewModel = hiltViewModel()
)
}
// TODO Timers screen
@ -155,16 +177,25 @@ fun StudeezNavGraph(
// Edit screens
composable(StudeezDestinations.EDIT_PROFILE_SCREEN) {
EditProfileRoute(goBack, openAndPopUp, viewModel = hiltViewModel())
EditProfileRoute(
goBack,
openAndPopUp,
viewModel = hiltViewModel(),
)
}
composable(StudeezDestinations.TIMER_SELECTION_SCREEN) {
TimerSelectionRoute(
open,
openAndPopUp,
goBack,
viewModel = hiltViewModel(),
drawerViewModel = drawerViewModel,
navBarViewModel = navBarViewModel,
)
}
composable(StudeezDestinations.SESSION_RECAP) {
SessionRecapRoute(
openAndPopUp = openAndPopUp,
viewModel = hiltViewModel()
)
}
}

View file

@ -3,15 +3,9 @@ package be.ugent.sel.studeez.common.composable
import androidx.annotation.StringRes
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.ButtonColors
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@ -21,7 +15,6 @@ import be.ugent.sel.studeez.common.ext.basicButton
import be.ugent.sel.studeez.common.ext.card
@Composable
fun BasicTextButton(@StringRes text: Int, modifier: Modifier, action: () -> Unit) {
TextButton(onClick = action, modifier = modifier) { Text(text = stringResource(text)) }
}
@ -64,10 +57,10 @@ fun StealthButton(
onClick = onClick,
modifier = Modifier.card(),
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Transparent,
contentColor = Color.DarkGray,
backgroundColor = MaterialTheme.colors.surface,
contentColor = MaterialTheme.colors.onSurface
),
border = BorderStroke(3.dp, Color.DarkGray),
border = BorderStroke(1.dp, MaterialTheme.colors.onSurface)
)
}

View file

@ -0,0 +1,64 @@
package be.ugent.sel.studeez.common.composable
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.tooling.preview.Preview
import be.ugent.sel.studeez.common.composable.drawer.Drawer
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.ui.theme.StudeezTheme
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import be.ugent.sel.studeez.R.string as AppText
@Composable
fun DrawerScreenTemplate(
title: String,
drawerActions: DrawerActions,
barAction: @Composable RowScope.() -> Unit = {},
content: @Composable (PaddingValues) -> Unit
) {
val scaffoldState: ScaffoldState = rememberScaffoldState()
val coroutineScope: CoroutineScope = rememberCoroutineScope()
Scaffold(
scaffoldState = scaffoldState,
topBar = { TopAppBar(
title = { Text(text = title) },
navigationIcon = {
IconButton(onClick = {
coroutineScope.launch { scaffoldState.drawerState.open() }
}) {
Icon(
imageVector = Icons.Default.Menu,
contentDescription = resources().getString(AppText.menu)
)
}
},
actions = barAction
)},
drawerContent = {
Drawer(drawerActions)
}
) {
content(it)
}
}
@Preview
@Composable
fun DrawerScreenPreview() {
StudeezTheme { DrawerScreenTemplate(
title = "Drawer screen preview",
drawerActions =DrawerActions({}, {}, {}, {}, {})
) {
Text(text = "Preview content")
} }
}

View file

@ -2,26 +2,19 @@ package be.ugent.sel.studeez.common.composable
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope
import androidx.compose.material.FabPosition
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Scaffold
import androidx.compose.material.ScaffoldState
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.rememberScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.tooling.preview.Preview
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.common.composable.drawer.Drawer
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBar
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.ui.theme.StudeezTheme
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ -31,7 +24,7 @@ fun PrimaryScreenTemplate(
title: String,
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions,
action: @Composable RowScope.() -> Unit = {},
barAction: @Composable RowScope.() -> Unit = {},
content: @Composable (PaddingValues) -> Unit
) {
val scaffoldState: ScaffoldState = rememberScaffoldState()
@ -53,7 +46,7 @@ fun PrimaryScreenTemplate(
)
}
},
actions = action
actions = barAction
)
},
@ -77,7 +70,7 @@ fun PrimaryScreenPreview() {
PrimaryScreenTemplate(
"Preview screen",
DrawerActions({}, {}, {}, {}, {}),
NavigationBarActions({}, {}, {}, {}),
NavigationBarActions({ false }, {}, {}, {}, {}),
{
IconButton(onClick = { /*TODO*/ }) {
Icon(

View file

@ -1,6 +1,7 @@
package be.ugent.sel.studeez.common.composable
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
@ -10,13 +11,12 @@ import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.ui.theme.StudeezTheme
// TODO Add option for button in top right corner as extra button
@Composable
// Does not contain floatingActionButton and bottom bar, used in all the other screens
fun SecondaryScreenTemplate(
title: String,
popUp: () -> Unit,
barAction: @Composable RowScope.() -> Unit = {},
content: @Composable (PaddingValues) -> Unit
) {
Scaffold(
@ -30,7 +30,8 @@ fun SecondaryScreenTemplate(
contentDescription = resources().getString(R.string.go_back)
)
}
}
},
actions = barAction
) },
) { paddingValues ->
content(paddingValues)

View file

@ -1,10 +1,6 @@
package be.ugent.sel.studeez.common.composable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@ -20,24 +16,39 @@ import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
@Composable
fun TimerEntry(
timerInfo: TimerInfo,
button: @Composable () -> Unit,
rightButton: @Composable () -> Unit = {},
leftButton: @Composable () -> Unit = {}
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
modifier = Modifier.fillMaxWidth()
) {
Column(
Modifier.padding(horizontal = 10.dp)
Row(
modifier = Modifier.weight(1f)
) {
Text(
text = timerInfo.name, fontWeight = FontWeight.Bold, fontSize = 20.sp
)
Text(
text = timerInfo.description, fontWeight = FontWeight.Light, fontSize = 15.sp
)
Box(modifier = Modifier.align(alignment = Alignment.CenterVertically)) {
leftButton()
}
Column(
Modifier.padding(
horizontal = 20.dp,
vertical = 11.dp
)
) {
Text(
text = timerInfo.name,
fontWeight = FontWeight.Medium,
fontSize = 20.sp
)
Text(
text = timerInfo.description, fontWeight = FontWeight.Light, fontSize = 14.sp
)
}
}
Box(modifier = Modifier.align(alignment = Alignment.CenterVertically)) {
rightButton()
}
button()
}
}

View file

@ -12,11 +12,14 @@ import androidx.compose.material.icons.outlined.DateRange
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import be.ugent.sel.studeez.navigation.StudeezDestinations.HOME_SCREEN
import be.ugent.sel.studeez.navigation.StudeezDestinations.PROFILE_SCREEN
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.ui.theme.StudeezTheme
import be.ugent.sel.studeez.R.string as AppText
data class NavigationBarActions(
val isSelectedTab: (String) -> Boolean,
val onHomeClick: () -> Unit,
val onTasksClick: () -> Unit,
val onSessionsClick: () -> Unit,
@ -26,29 +29,38 @@ data class NavigationBarActions(
fun getNavigationBarActions(
navigationBarViewModel: NavigationBarViewModel,
open: (String) -> Unit,
getCurrentScreen: () -> String?
): NavigationBarActions {
return NavigationBarActions(
onHomeClick = { navigationBarViewModel.onHomeClick(open) },
onTasksClick = { navigationBarViewModel.onTasksClick(open) },
onSessionsClick = { navigationBarViewModel.onSessionsClick(open) },
onProfileClick = { navigationBarViewModel.onProfileClick(open) },
isSelectedTab = { screen ->
screen == getCurrentScreen()
},
onHomeClick = {
navigationBarViewModel.onHomeClick(open)
},
onTasksClick = {
navigationBarViewModel.onTasksClick(open)
},
onSessionsClick = {
navigationBarViewModel.onSessionsClick(open)
},
onProfileClick = {
navigationBarViewModel.onProfileClick(open)
},
)
}
@Composable
fun NavigationBar(
navigationBarActions: NavigationBarActions,
navigationBarActions: NavigationBarActions
) {
// TODO Pass functions and new screens.
// TODO Pass which screen is selected.
// TODO Disabled -> HIGH/MEDIUM_EMPHASIS if the page is implemented
BottomNavigation(
elevation = 10.dp
) {
BottomNavigationItem(
icon = { Icon(imageVector = Icons.Default.List, resources().getString(AppText.home)) },
label = { Text(text = resources().getString(AppText.home)) },
selected = false, // TODO
selected = navigationBarActions.isSelectedTab(HOME_SCREEN),
onClick = navigationBarActions.onHomeClick
)
@ -59,7 +71,8 @@ fun NavigationBar(
)
},
label = { Text(text = resources().getString(AppText.tasks)) },
selected = false, // TODO
// TODO selected = navigationBarActions.isSelectedTab(TASKS_SCREEN),
selected = false,
onClick = navigationBarActions.onTasksClick
)
@ -73,7 +86,8 @@ fun NavigationBar(
)
},
label = { Text(text = resources().getString(AppText.sessions)) },
selected = false, // TODO
// TODO selected = navigationBarActions.isSelectedTab(SESSIONS_SCREEN),
selected = false,
onClick = navigationBarActions.onSessionsClick
)
@ -84,7 +98,7 @@ fun NavigationBar(
)
},
label = { Text(text = resources().getString(AppText.profile)) },
selected = false, // TODO
selected = navigationBarActions.isSelectedTab(PROFILE_SCREEN),
onClick = navigationBarActions.onProfileClick
)
@ -95,6 +109,8 @@ fun NavigationBar(
@Composable
fun NavigationBarPreview() {
StudeezTheme {
NavigationBar(NavigationBarActions({}, {}, {}, {}))
NavigationBar(
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}),
)
}
}

View file

@ -0,0 +1,14 @@
package be.ugent.sel.studeez.data
import be.ugent.sel.studeez.data.local.models.SessionReport
import javax.inject.Inject
import javax.inject.Singleton
/**
* Used to communicate the SelectedTimer from the selection screen to the session screen.
* Because this is a singleton-class the view-models of both screens observe the same data.
*/
@Singleton
class SessionReportState @Inject constructor(){
var sessionReport: SessionReport? = null
}

View file

@ -5,6 +5,7 @@ class FunctionalCustomTimer(studyTime: Int) : FunctionalTimer(studyTime) {
override fun tick() {
if (!hasEnded()) {
time.minOne()
totalStudyTime++
}
}

View file

@ -12,6 +12,7 @@ class FunctionalEndlessTimer : FunctionalTimer(0) {
override fun tick() {
time.plusOne()
totalStudyTime++
}
override fun <T> accept(visitor: FunctionalTimerVisitor<T>): T {

View file

@ -23,6 +23,10 @@ class FunctionalPomodoroTimer(
isInBreak = !isInBreak
}
time.minOne()
if (!isInBreak) {
totalStudyTime++
}
}
override fun hasEnded(): Boolean {

View file

@ -1,7 +1,11 @@
package be.ugent.sel.studeez.data.local.models.timer_functional
import be.ugent.sel.studeez.data.local.models.SessionReport
import com.google.firebase.Timestamp
abstract class FunctionalTimer(initialValue: Int) {
val time: Time = Time(initialValue)
var totalStudyTime: Int = 0
fun getHoursMinutesSeconds(): HoursMinutesSeconds {
return time.getAsHMS()
@ -13,5 +17,12 @@ abstract class FunctionalTimer(initialValue: Int) {
abstract fun hasCurrentCountdownEnded(): Boolean
fun getSessionReport(): SessionReport {
return SessionReport(
studyTime = totalStudyTime,
endTime = Timestamp.now()
)
}
abstract fun <T> accept(visitor: FunctionalTimerVisitor<T>): T
}

View file

@ -9,6 +9,7 @@ object StudeezDestinations {
const val TIMER_OVERVIEW_SCREEN = "timer_overview"
const val TIMER_SELECTION_SCREEN = "timer_selection"
const val SESSION_SCREEN = "session"
const val SESSION_RECAP = "session_recap"
// const val TASKS_SCREEN = "tasks"
// const val SESSIONS_SCREEN = "sessions"
const val PROFILE_SCREEN = "profile"

View file

@ -11,26 +11,21 @@ import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.BasicButton
import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.common.composable.drawer.DrawerViewModel
import be.ugent.sel.studeez.common.composable.drawer.getDrawerActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel
import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions
import be.ugent.sel.studeez.common.ext.basicButton
import be.ugent.sel.studeez.resources
@Composable
fun HomeRoute(
open: (String) -> Unit,
openAndPopUp: (String, String) -> Unit,
viewModel: HomeViewModel,
drawerViewModel: DrawerViewModel,
navBarViewModel: NavigationBarViewModel,
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions,
) {
HomeScreen(
onStartSessionClick = { viewModel.onStartSessionClick(open) },
drawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp),
navigationBarActions = getNavigationBarActions(navBarViewModel, open),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
)
}
@ -40,12 +35,11 @@ fun HomeScreen(
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions,
) {
PrimaryScreenTemplate(
title = resources().getString(R.string.home),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
action = { FriendsAction() }
barAction = { FriendsAction() }
) {
BasicButton(R.string.start_session, Modifier.basicButton()) {
onStartSessionClick()
@ -69,6 +63,6 @@ fun HomeScreenPreview() {
HomeScreen(
onStartSessionClick = {},
drawerActions = DrawerActions({}, {}, {}, {}, {}),
navigationBarActions = NavigationBarActions({}, {}, {}, {})
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {})
)
}

View file

@ -11,15 +11,12 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.Headline
import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.common.composable.drawer.getDrawerActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions
import be.ugent.sel.studeez.resources
import kotlinx.coroutines.CoroutineScope
import be.ugent.sel.studeez.R.string as AppText
@ -41,13 +38,14 @@ fun getProfileActions(
@Composable
fun ProfileRoute(
open: (String) -> Unit,
openAndPopUp: (String, String) -> Unit,
viewModel: ProfileViewModel,
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions,
) {
ProfileScreen(
profileActions = getProfileActions(viewModel, open),
drawerActions = getDrawerActions(hiltViewModel(), open, openAndPopUp),
navigationBarActions = getNavigationBarActions(hiltViewModel(), open),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
)
}
@ -65,7 +63,7 @@ fun ProfileScreen(
title = resources().getString(AppText.profile),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
action = { EditAction(onClick = profileActions.onEditProfileClick) }
barAction = { EditAction(onClick = profileActions.onEditProfileClick) }
) {
Headline(text = (username ?: resources().getString(R.string.no_username)))
}
@ -90,6 +88,6 @@ fun ProfileScreenPreview() {
ProfileScreen(
profileActions = ProfileActions({ null }, {}),
drawerActions = DrawerActions({}, {}, {}, {}, {}),
navigationBarActions = NavigationBarActions({}, {}, {}, {})
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {})
)
}

View file

@ -14,15 +14,18 @@ data class SessionActions(
val getTask: () -> String,
val startMediaPlayer: () -> Unit,
val releaseMediaPlayer: () -> Unit,
val endSession: () -> Unit
)
private fun getSessionActions(
viewModel: SessionViewModel,
openAndPopUp: (String, String) -> Unit,
mediaplayer: MediaPlayer,
): SessionActions {
return SessionActions(
getTimer = viewModel::getTimer,
getTask = viewModel::getTask,
endSession = { viewModel.endSession(openAndPopUp) },
startMediaPlayer = mediaplayer::start,
releaseMediaPlayer = mediaplayer::release,
)
@ -31,6 +34,7 @@ private fun getSessionActions(
@Composable
fun SessionRoute(
open: (String) -> Unit,
openAndPopUp: (String, String) -> Unit,
viewModel: SessionViewModel,
) {
val context = LocalContext.current
@ -47,6 +51,6 @@ fun SessionRoute(
sessionScreen(
open = open,
sessionActions = getSessionActions(viewModel, mediaplayer)
sessionActions = getSessionActions(viewModel, openAndPopUp, mediaplayer)
)
}

View file

@ -1,20 +1,21 @@
package be.ugent.sel.studeez.screens.session
import be.ugent.sel.studeez.data.SelectedTimerState
import be.ugent.sel.studeez.data.SessionReportState
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.navigation.StudeezDestinations
import be.ugent.sel.studeez.screens.StudeezViewModel
import be.ugent.sel.studeez.data.SelectedTimerState
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class SessionViewModel @Inject constructor(
private val selectedTimerState: SelectedTimerState,
private val sessionReportState: SessionReportState,
logService: LogService
) : StudeezViewModel(logService) {
private val timer: FunctionalTimer = FunctionalPomodoroTimer(15, 5, 3)
private val task : String = "No task selected" // placeholder for tasks implementation
fun getTimer() : FunctionalTimer {
@ -24,4 +25,9 @@ class SessionViewModel @Inject constructor(
fun getTask(): String {
return task
}
fun endSession(openAndPopUp: (String, String) -> Unit) {
sessionReportState.sessionReport = getTimer().getSessionReport()
openAndPopUp(StudeezDestinations.SESSION_RECAP, StudeezDestinations.SESSION_SCREEN)
}
}

View file

@ -19,7 +19,6 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalEndlessTimer
import be.ugent.sel.studeez.navigation.StudeezDestinations
import be.ugent.sel.studeez.screens.session.SessionActions
import kotlinx.coroutines.delay
import kotlin.time.Duration.Companion.seconds
@ -45,8 +44,7 @@ abstract class AbstractSessionScreen {
TextButton(
onClick = {
sessionActions.releaseMediaPlayer
open(StudeezDestinations.HOME_SCREEN)
// Vanaf hier ook naar report gaan als "end session" knop word ingedrukt
sessionActions.endSession()
},
modifier = Modifier
.padding(horizontal = 20.dp)
@ -136,5 +134,5 @@ fun TimerPreview() {
override fun callMediaPlayer() {}
}
sessionScreen.Timer(sessionActions = SessionActions({ FunctionalEndlessTimer() }, { "Preview" }, {}, {}))
sessionScreen.Timer(sessionActions = SessionActions({ FunctionalEndlessTimer() }, { "Preview" }, {}, {}, {}))
}

View file

@ -0,0 +1,65 @@
package be.ugent.sel.studeez.screens.session_recap
import androidx.compose.foundation.layout.Column
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.BasicButton
import be.ugent.sel.studeez.common.ext.basicButton
import be.ugent.sel.studeez.data.local.models.SessionReport
import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds
import be.ugent.sel.studeez.data.local.models.timer_functional.Time
data class SessionRecapActions(
val getSessionReport: () -> SessionReport,
val saveSession: () -> Unit,
val discardSession: () -> Unit
)
fun getSessionRecapActions(
viewModel: SessionRecapViewModel,
openAndPopUp: (String, String) -> Unit,
): SessionRecapActions {
return SessionRecapActions(
viewModel::getSessionReport,
{viewModel.saveSession(openAndPopUp)},
{viewModel.discardSession(openAndPopUp)}
)
}
@Composable
fun SessionRecapRoute(
openAndPopUp: (String, String) -> Unit,
modifier: Modifier = Modifier,
viewModel: SessionRecapViewModel,
) {
SessionRecapScreen(
modifier = modifier,
getSessionRecapActions(viewModel, openAndPopUp)
)
}
@Composable
fun SessionRecapScreen(modifier: Modifier, sessionRecapActions: SessionRecapActions) {
val sessionReport: SessionReport = sessionRecapActions.getSessionReport()
val studyTime: Int = sessionReport.studyTime
val hms: HoursMinutesSeconds = Time(studyTime).getAsHMS()
Column {
Text(text = "You studied: ${hms.hours} : ${hms.minutes} : ${hms.seconds}")
BasicButton(
R.string.save, Modifier.basicButton()
) {
sessionRecapActions.saveSession()
}
BasicButton(
R.string.discard, Modifier.basicButton(),
colors = ButtonDefaults.buttonColors(backgroundColor = Color.Red)
) {
sessionRecapActions.discardSession()
}
}
}

View file

@ -0,0 +1,33 @@
package be.ugent.sel.studeez.screens.session_recap
import be.ugent.sel.studeez.data.SessionReportState
import be.ugent.sel.studeez.data.local.models.SessionReport
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.domain.SessionDAO
import be.ugent.sel.studeez.navigation.StudeezDestinations
import be.ugent.sel.studeez.screens.StudeezViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class SessionRecapViewModel @Inject constructor(
private val sessionReportState: SessionReportState,
private val sessionDAO: SessionDAO,
logService: LogService
) : StudeezViewModel(logService) {
private val report: SessionReport = sessionReportState.sessionReport!!
fun getSessionReport(): SessionReport {
return report
}
fun saveSession(open: (String, String) -> Unit) {
sessionDAO.saveSession(getSessionReport())
open(StudeezDestinations.HOME_SCREEN, StudeezDestinations.SESSION_RECAP)
}
fun discardSession(open: (String, String) -> Unit) {
open(StudeezDestinations.HOME_SCREEN, StudeezDestinations.SESSION_RECAP)
}
}

View file

@ -1,6 +1,5 @@
package be.ugent.sel.studeez.screens.timer_overview
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
@ -8,18 +7,12 @@ 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.BasicButton
import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate
import be.ugent.sel.studeez.common.composable.DrawerScreenTemplate
import be.ugent.sel.studeez.common.composable.StealthButton
import be.ugent.sel.studeez.common.composable.TimerEntry
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.common.composable.drawer.DrawerViewModel
import be.ugent.sel.studeez.common.composable.drawer.getDrawerActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel
import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions
import be.ugent.sel.studeez.common.ext.basicButton
import be.ugent.sel.studeez.data.local.models.timer_info.CustomTimerInfo
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
@ -45,38 +38,29 @@ fun getTimerOverviewActions(
@Composable
fun TimerOverviewRoute(
open: (String) -> Unit,
openAndPopUp: (String, String) -> Unit,
viewModel: TimerOverviewViewModel,
drawerViewModel: DrawerViewModel,
navBarViewModel: NavigationBarViewModel,
drawerActions: DrawerActions,
) {
TimerOverviewScreen(
timerOverviewActions = getTimerOverviewActions(viewModel),
drawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp),
navigationBarActions = getNavigationBarActions(navBarViewModel, open),
drawerActions = drawerActions,
)
}
@Composable
fun TimerOverviewScreen(
timerOverviewActions: TimerOverviewActions,
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions,
drawerActions: DrawerActions
) {
val timers = timerOverviewActions.getUserTimers().collectAsState(initial = emptyList())
// TODO moet geen primary screen zijn: geen navbar nodig
PrimaryScreenTemplate(
DrawerScreenTemplate(
title = resources().getString(R.string.timers),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
drawerActions = drawerActions
) {
Column {
LazyColumn(
verticalArrangement = Arrangement.spacedBy(7.dp)
) {
LazyColumn {
// Default Timers, cannot be edited
items(timerOverviewActions.getDefaultTimers()) {
TimerEntry(timerInfo = it) {}
@ -112,7 +96,6 @@ fun TimerOverviewPreview() {
{ flowOf() },
{ listOf(customTimer, customTimer) },
{}),
drawerActions = DrawerActions({}, {}, {}, {}, {}),
navigationBarActions = NavigationBarActions({}, {}, {}, {})
drawerActions = DrawerActions({}, {}, {}, {}, {})
)
}

View file

@ -1,22 +1,14 @@
package be.ugent.sel.studeez.screens.timer_selection
import androidx.compose.foundation.layout.Arrangement
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.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
import be.ugent.sel.studeez.common.composable.StealthButton
import be.ugent.sel.studeez.common.composable.TimerEntry
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.common.composable.drawer.DrawerViewModel
import be.ugent.sel.studeez.common.composable.drawer.getDrawerActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel
import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
import be.ugent.sel.studeez.resources
import kotlinx.coroutines.flow.Flow
@ -40,41 +32,37 @@ fun getTimerSelectionActions(
@Composable
fun TimerSelectionRoute(
open: (String) -> Unit,
openAndPopUp: (String, String) -> Unit,
popUp: () -> Unit,
viewModel: TimerSelectionViewModel,
drawerViewModel: DrawerViewModel,
navBarViewModel: NavigationBarViewModel,
) {
TimerSelectionScreen(
timerSelectionActions = getTimerSelectionActions(viewModel, open),
drawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp),
navigationBarActions = getNavigationBarActions(navBarViewModel, open),
popUp = popUp
)
}
@Composable
fun TimerSelectionScreen(
timerSelectionActions: TimerSelectionActions,
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions,
popUp: () -> Unit
) {
val timers = timerSelectionActions.getAllTimers().collectAsState(initial = emptyList())
PrimaryScreenTemplate(
SecondaryScreenTemplate(
title = resources().getString(R.string.timers),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
popUp = popUp
) {
LazyColumn(verticalArrangement = Arrangement.spacedBy(7.dp)) {
LazyColumn {
// All timers
items(timers.value) { timerInfo ->
TimerEntry(
timerInfo = timerInfo,
) {
StealthButton(
text = R.string.start,
onClick = { timerSelectionActions.startSession(timerInfo) }
)
}
leftButton = {
StealthButton(
text = R.string.start,
onClick = { timerSelectionActions.startSession(timerInfo) }
)
}
)
}
}
}
@ -85,7 +73,6 @@ fun TimerSelectionScreen(
fun TimerSelectionPreview() {
TimerSelectionScreen(
timerSelectionActions = TimerSelectionActions({ flowOf() }, {}),
drawerActions = DrawerActions({}, {}, {}, {}, {}),
navigationBarActions = NavigationBarActions({}, {}, {}, {}),
popUp = {}
)
}

View file

@ -10,6 +10,7 @@
<!-- Actions -->
<string name="confirm">Confirm</string>
<string name="save">Save</string>
<string name="discard">Discard</string>
<string name="cancel">Cancel</string>
<string name="go_back">Go back</string>
<string name="next">Next</string>