merged with current dev
This commit is contained in:
commit
b30edf6538
22 changed files with 849 additions and 373 deletions
|
@ -2,7 +2,13 @@ package be.ugent.sel.studeez
|
|||
|
||||
import android.content.res.Resources
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.ScaffoldState
|
||||
import androidx.compose.material.Snackbar
|
||||
import androidx.compose.material.SnackbarHost
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.rememberScaffoldState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.remember
|
||||
|
@ -11,22 +17,24 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import be.ugent.sel.studeez.common.composable.drawer.DrawerViewModel
|
||||
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel
|
||||
import be.ugent.sel.studeez.common.snackbar.SnackbarManager
|
||||
import be.ugent.sel.studeez.navigation.StudeezDestinations
|
||||
import be.ugent.sel.studeez.screens.home.HomeScreen
|
||||
import be.ugent.sel.studeez.screens.log_in.LoginScreen
|
||||
import be.ugent.sel.studeez.screens.session.SessionScreen
|
||||
import be.ugent.sel.studeez.screens.profile.EditProfileScreen
|
||||
import be.ugent.sel.studeez.screens.profile.ProfileScreen
|
||||
import be.ugent.sel.studeez.screens.sign_up.SignUpScreen
|
||||
import be.ugent.sel.studeez.screens.splash.SplashScreen
|
||||
import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewScreen
|
||||
import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionScreen
|
||||
import be.ugent.sel.studeez.screens.home.HomeRoute
|
||||
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.sign_up.SignUpRoute
|
||||
import be.ugent.sel.studeez.screens.splash.SplashRoute
|
||||
import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewRoute
|
||||
import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionRoute
|
||||
import be.ugent.sel.studeez.ui.theme.StudeezTheme
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
|
@ -48,13 +56,7 @@ fun StudeezApp() {
|
|||
},
|
||||
scaffoldState = appState.scaffoldState
|
||||
) { innerPaddingModifier ->
|
||||
NavHost(
|
||||
navController = appState.navController,
|
||||
startDestination = StudeezDestinations.SPLASH_SCREEN,
|
||||
modifier = Modifier.padding(innerPaddingModifier)
|
||||
) {
|
||||
studeezGraph(appState)
|
||||
}
|
||||
StudeezNavGraph(appState, Modifier.padding(innerPaddingModifier))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,60 +81,91 @@ fun resources(): Resources {
|
|||
return LocalContext.current.resources
|
||||
}
|
||||
|
||||
fun NavGraphBuilder.studeezGraph(appState: StudeezAppstate) {
|
||||
@Composable
|
||||
fun StudeezNavGraph(
|
||||
appState: StudeezAppstate,
|
||||
modifier: Modifier,
|
||||
) {
|
||||
val drawerViewModel: DrawerViewModel = hiltViewModel()
|
||||
val navBarViewModel: NavigationBarViewModel = hiltViewModel()
|
||||
|
||||
val goBack: () -> Unit = {
|
||||
appState.popUp()
|
||||
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())
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.LOGIN_SCREEN) {
|
||||
LoginRoute(openAndPopUp, viewModel = hiltViewModel())
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.SIGN_UP_SCREEN) {
|
||||
SignUpRoute(openAndPopUp, viewModel = hiltViewModel())
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.HOME_SCREEN) {
|
||||
HomeRoute(
|
||||
open,
|
||||
openAndPopUp,
|
||||
viewModel = hiltViewModel(),
|
||||
drawerViewModel = drawerViewModel,
|
||||
navBarViewModel = navBarViewModel,
|
||||
)
|
||||
}
|
||||
|
||||
// TODO Tasks screen
|
||||
// TODO Sessions screen
|
||||
|
||||
composable(StudeezDestinations.PROFILE_SCREEN) {
|
||||
ProfileRoute(open, openAndPopUp, viewModel = hiltViewModel())
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.TIMER_OVERVIEW_SCREEN) {
|
||||
TimerOverviewRoute(
|
||||
open,
|
||||
openAndPopUp,
|
||||
viewModel = hiltViewModel(),
|
||||
drawerViewModel = drawerViewModel,
|
||||
navBarViewModel = navBarViewModel,
|
||||
)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.SESSION_SCREEN) {
|
||||
SessionRoute(open, viewModel = hiltViewModel())
|
||||
}
|
||||
|
||||
// TODO Timers screen
|
||||
// TODO Settings screen
|
||||
|
||||
// Edit screens
|
||||
composable(StudeezDestinations.EDIT_PROFILE_SCREEN) {
|
||||
EditProfileRoute(goBack, openAndPopUp, viewModel = hiltViewModel())
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.TIMER_SELECTION_SCREEN) {
|
||||
TimerSelectionRoute(
|
||||
open,
|
||||
openAndPopUp,
|
||||
viewModel = hiltViewModel(),
|
||||
drawerViewModel = drawerViewModel,
|
||||
navBarViewModel = navBarViewModel,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val open: (String) -> Unit = {
|
||||
route -> appState.navigate(route)
|
||||
}
|
||||
|
||||
val openAndPopUp: (String, String) -> Unit = {
|
||||
route, popUp -> appState.navigateAndPopUp(route, popUp)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.SPLASH_SCREEN) {
|
||||
SplashScreen(openAndPopUp)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.LOGIN_SCREEN) {
|
||||
LoginScreen(openAndPopUp)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.SIGN_UP_SCREEN) {
|
||||
SignUpScreen(openAndPopUp)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.HOME_SCREEN) {
|
||||
HomeScreen(open, openAndPopUp)
|
||||
}
|
||||
|
||||
// TODO Tasks screen
|
||||
// TODO Sessions screen
|
||||
|
||||
composable(StudeezDestinations.PROFILE_SCREEN) {
|
||||
ProfileScreen(open, openAndPopUp)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.TIMER_OVERVIEW_SCREEN) {
|
||||
TimerOverviewScreen(open, openAndPopUp)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.SESSION_SCREEN) {
|
||||
SessionScreen(open, openAndPopUp)
|
||||
}
|
||||
|
||||
// TODO Timers screen
|
||||
// TODO Settings screen
|
||||
|
||||
// Edit screens
|
||||
composable(StudeezDestinations.EDIT_PROFILE_SCREEN) {
|
||||
EditProfileScreen(goBack, openAndPopUp)
|
||||
}
|
||||
|
||||
composable(StudeezDestinations.TIMER_SELECTION_SCREEN) {
|
||||
TimerSelectionScreen(open, openAndPopUp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package be.ugent.sel.studeez.activities
|
||||
|
||||
import android.media.MediaPlayer
|
||||
import android.media.RingtoneManager
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
|
@ -25,13 +22,7 @@ var onTimerInvisible: Job? = null
|
|||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
private var mediaPlayer: MediaPlayer? = null
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
|
||||
mediaPlayer = MediaPlayer.create(this, uri)
|
||||
mediaPlayer?.isLooping = false
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
StudeezTheme {
|
||||
|
@ -54,16 +45,9 @@ class MainActivity : ComponentActivity() {
|
|||
}
|
||||
|
||||
override fun onStart() {
|
||||
mediaPlayer?.stop()
|
||||
onTimerInvisible?.cancel()
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
mediaPlayer?.stop()
|
||||
mediaPlayer?.release()
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -2,17 +2,26 @@ 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.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.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.screens.drawer.Drawer
|
||||
import be.ugent.sel.studeez.screens.navbar.NavigationBar
|
||||
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.ui.theme.StudeezTheme
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -20,8 +29,8 @@ import kotlinx.coroutines.launch
|
|||
@Composable
|
||||
fun PrimaryScreenTemplate(
|
||||
title: String,
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
drawerActions: DrawerActions,
|
||||
navigationBarActions: NavigationBarActions,
|
||||
action: @Composable RowScope.() -> Unit = {},
|
||||
content: @Composable (PaddingValues) -> Unit
|
||||
) {
|
||||
|
@ -31,26 +40,28 @@ fun PrimaryScreenTemplate(
|
|||
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(R.string.menu)
|
||||
)
|
||||
}
|
||||
},
|
||||
actions = action
|
||||
) },
|
||||
|
||||
drawerContent = {
|
||||
Drawer(open, openAndPopUp)
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text(text = title) },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = {
|
||||
coroutineScope.launch { scaffoldState.drawerState.open() }
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Menu,
|
||||
contentDescription = resources().getString(R.string.menu)
|
||||
)
|
||||
}
|
||||
},
|
||||
actions = action
|
||||
)
|
||||
},
|
||||
|
||||
bottomBar = { NavigationBar(open) },
|
||||
drawerContent = {
|
||||
Drawer(drawerActions)
|
||||
},
|
||||
|
||||
bottomBar = { NavigationBar(navigationBarActions) },
|
||||
floatingActionButtonPosition = FabPosition.Center,
|
||||
isFloatingActionButtonDocked = true,
|
||||
floatingActionButton = { CollapsedAddButton() }
|
||||
|
@ -65,14 +76,16 @@ fun PrimaryScreenPreview() {
|
|||
StudeezTheme {
|
||||
PrimaryScreenTemplate(
|
||||
"Preview screen",
|
||||
{ _ -> {}},
|
||||
{ _, _ -> {}},
|
||||
{ IconButton(onClick = { /*TODO*/ }) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Edit,
|
||||
contentDescription = "Edit"
|
||||
)
|
||||
}}
|
||||
DrawerActions({}, {}, {}, {}, {}),
|
||||
NavigationBarActions({}, {}, {}, {}),
|
||||
{
|
||||
IconButton(onClick = { /*TODO*/ }) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Edit,
|
||||
contentDescription = "Edit"
|
||||
)
|
||||
}
|
||||
},
|
||||
) {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
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.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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.R
|
||||
import be.ugent.sel.studeez.data.local.models.timer_info.CustomTimerInfo
|
||||
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
|
||||
|
||||
@Composable
|
||||
fun TimerEntry(
|
||||
timerInfo: TimerInfo,
|
||||
button: @Composable () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Column(
|
||||
Modifier.padding(horizontal = 10.dp)
|
||||
) {
|
||||
Text(
|
||||
text = timerInfo.name, fontWeight = FontWeight.Bold, fontSize = 20.sp
|
||||
)
|
||||
Text(
|
||||
text = timerInfo.description, fontWeight = FontWeight.Light, fontSize = 15.sp
|
||||
)
|
||||
}
|
||||
button()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TimerEntryPreview() {
|
||||
val timerInfo = CustomTimerInfo(
|
||||
"my preview timer", "This is the description of the timer", 60
|
||||
)
|
||||
TimerEntry(timerInfo = timerInfo) {
|
||||
StealthButton(text = R.string.edit) {}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TimerDefaultEntryPreview() {
|
||||
val timerInfo = CustomTimerInfo(
|
||||
"Default preview timer", "This is the description of the timer", 60
|
||||
)
|
||||
TimerEntry(timerInfo = timerInfo) {}
|
||||
}
|
|
@ -1,7 +1,12 @@
|
|||
package be.ugent.sel.studeez.screens.drawer
|
||||
package be.ugent.sel.studeez.common.composable.drawer
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
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.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
@ -14,57 +19,71 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import be.ugent.sel.studeez.R
|
||||
import be.ugent.sel.studeez.resources
|
||||
import be.ugent.sel.studeez.ui.theme.StudeezTheme
|
||||
|
||||
data class DrawerActions(
|
||||
val onHomeButtonClick: () -> Unit,
|
||||
val onTimersClick: () -> Unit,
|
||||
val onSettingsClick: () -> Unit,
|
||||
val onLogoutClick: () -> Unit,
|
||||
val onAboutClick: () -> Unit,
|
||||
)
|
||||
|
||||
fun getDrawerActions(
|
||||
drawerViewModel: DrawerViewModel,
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
): DrawerActions {
|
||||
return DrawerActions(
|
||||
onHomeButtonClick = { drawerViewModel.onHomeButtonClick(open) },
|
||||
onTimersClick = { drawerViewModel.onTimersClick(open) },
|
||||
onSettingsClick = { drawerViewModel.onSettingsClick(open) },
|
||||
onLogoutClick = { drawerViewModel.onLogoutClick(openAndPopUp) },
|
||||
onAboutClick = { drawerViewModel.onAboutClick(open) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Drawer(
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: DrawerViewModel = hiltViewModel()
|
||||
drawerActions: DrawerActions,
|
||||
) {
|
||||
Column (
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Column (
|
||||
modifier = Modifier.fillMaxWidth().weight(1f)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f)
|
||||
) {
|
||||
DrawerEntry(
|
||||
icon = Icons.Default.Home,
|
||||
text = resources().getString(R.string.home)
|
||||
) {
|
||||
viewModel.onHomeButtonClick(open)
|
||||
}
|
||||
text = resources().getString(R.string.home),
|
||||
onClick = drawerActions.onHomeButtonClick,
|
||||
)
|
||||
DrawerEntry(
|
||||
icon = ImageVector.vectorResource(id = R.drawable.ic_timer),
|
||||
text = resources().getString(R.string.timers)
|
||||
) {
|
||||
viewModel.onTimersClick(open)
|
||||
}
|
||||
text = resources().getString(R.string.timers),
|
||||
onClick = drawerActions.onTimersClick,
|
||||
)
|
||||
DrawerEntry(
|
||||
icon = Icons.Default.Settings,
|
||||
text = resources().getString(R.string.settings)
|
||||
) {
|
||||
viewModel.onSettingsClick(open)
|
||||
}
|
||||
text = resources().getString(R.string.settings),
|
||||
onClick = drawerActions.onSettingsClick,
|
||||
)
|
||||
DrawerEntry(
|
||||
icon = ImageVector.vectorResource(id = R.drawable.ic_logout),
|
||||
text = resources().getString(R.string.log_out)
|
||||
) {
|
||||
viewModel.onLogoutClick(openAndPopUp)
|
||||
}
|
||||
text = resources().getString(R.string.log_out),
|
||||
onClick = drawerActions.onLogoutClick,
|
||||
)
|
||||
}
|
||||
|
||||
DrawerEntry(
|
||||
icon = Icons.Outlined.Info,
|
||||
text = resources().getString(R.string.about)
|
||||
) {
|
||||
viewModel.onAboutClick(open)
|
||||
}
|
||||
text = resources().getString(R.string.about),
|
||||
onClick = drawerActions.onAboutClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,11 +119,8 @@ fun DrawerEntry(
|
|||
@Preview
|
||||
@Composable
|
||||
fun DrawerPreview() {
|
||||
val drawerActions = DrawerActions({}, {}, {}, {}, {})
|
||||
StudeezTheme {
|
||||
Drawer(
|
||||
{ _, -> {} },
|
||||
{ _, _ -> {} },
|
||||
hiltViewModel()
|
||||
)
|
||||
Drawer(drawerActions)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package be.ugent.sel.studeez.screens.drawer
|
||||
package be.ugent.sel.studeez.common.composable.drawer
|
||||
|
||||
import be.ugent.sel.studeez.domain.AccountDAO
|
||||
import be.ugent.sel.studeez.domain.LogService
|
|
@ -1,4 +1,4 @@
|
|||
package be.ugent.sel.studeez.screens.navbar
|
||||
package be.ugent.sel.studeez.common.composable.navbar
|
||||
|
||||
import androidx.compose.material.BottomNavigation
|
||||
import androidx.compose.material.BottomNavigationItem
|
||||
|
@ -12,16 +12,32 @@ 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 androidx.hilt.navigation.compose.hiltViewModel
|
||||
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 onHomeClick: () -> Unit,
|
||||
val onTasksClick: () -> Unit,
|
||||
val onSessionsClick: () -> Unit,
|
||||
val onProfileClick: () -> Unit,
|
||||
)
|
||||
|
||||
fun getNavigationBarActions(
|
||||
navigationBarViewModel: NavigationBarViewModel,
|
||||
open: (String) -> Unit,
|
||||
): NavigationBarActions {
|
||||
return NavigationBarActions(
|
||||
onHomeClick = { navigationBarViewModel.onHomeClick(open) },
|
||||
onTasksClick = { navigationBarViewModel.onTasksClick(open) },
|
||||
onSessionsClick = { navigationBarViewModel.onSessionsClick(open) },
|
||||
onProfileClick = { navigationBarViewModel.onProfileClick(open) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NavigationBar(
|
||||
open: (String) -> Unit,
|
||||
viewModel: NavigationBarViewModel = hiltViewModel()
|
||||
navigationBarActions: NavigationBarActions,
|
||||
) {
|
||||
// TODO Pass functions and new screens.
|
||||
// TODO Pass which screen is selected.
|
||||
|
@ -33,31 +49,43 @@ fun NavigationBar(
|
|||
icon = { Icon(imageVector = Icons.Default.List, resources().getString(AppText.home)) },
|
||||
label = { Text(text = resources().getString(AppText.home)) },
|
||||
selected = false, // TODO
|
||||
onClick = { viewModel.onHomeClick(open) }
|
||||
onClick = navigationBarActions.onHomeClick
|
||||
)
|
||||
|
||||
BottomNavigationItem(
|
||||
icon = { Icon(imageVector = Icons.Default.Check, resources().getString(AppText.tasks)) },
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check, resources().getString(AppText.tasks)
|
||||
)
|
||||
},
|
||||
label = { Text(text = resources().getString(AppText.tasks)) },
|
||||
selected = false, // TODO
|
||||
onClick = { viewModel.onTasksClick(open) }
|
||||
onClick = navigationBarActions.onTasksClick
|
||||
)
|
||||
|
||||
// Hack to space the entries in the navigation bar, make space for fab
|
||||
BottomNavigationItem(icon = {}, onClick = {}, selected = false)
|
||||
|
||||
BottomNavigationItem(
|
||||
icon = { Icon(imageVector = Icons.Outlined.DateRange, resources().getString(AppText.sessions)) },
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.DateRange, resources().getString(AppText.sessions)
|
||||
)
|
||||
},
|
||||
label = { Text(text = resources().getString(AppText.sessions)) },
|
||||
selected = false, // TODO
|
||||
onClick = { viewModel.onSessionsClick(open) }
|
||||
onClick = navigationBarActions.onSessionsClick
|
||||
)
|
||||
|
||||
BottomNavigationItem(
|
||||
icon = { Icon(imageVector = Icons.Default.Person, resources().getString(AppText.profile)) },
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Person, resources().getString(AppText.profile)
|
||||
)
|
||||
},
|
||||
label = { Text(text = resources().getString(AppText.profile)) },
|
||||
selected = false, // TODO
|
||||
onClick = { viewModel.onProfileClick(open) }
|
||||
onClick = navigationBarActions.onProfileClick
|
||||
)
|
||||
|
||||
}
|
||||
|
@ -67,9 +95,6 @@ fun NavigationBar(
|
|||
@Composable
|
||||
fun NavigationBarPreview() {
|
||||
StudeezTheme {
|
||||
NavigationBar(
|
||||
{ _ -> {} },
|
||||
hiltViewModel()
|
||||
)
|
||||
NavigationBar(NavigationBarActions({}, {}, {}, {}))
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package be.ugent.sel.studeez.screens.navbar
|
||||
package be.ugent.sel.studeez.common.composable.navbar
|
||||
|
||||
import be.ugent.sel.studeez.domain.AccountDAO
|
||||
import be.ugent.sel.studeez.domain.LogService
|
|
@ -6,37 +6,69 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
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 HomeScreen(
|
||||
fun HomeRoute(
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: HomeViewModel = hiltViewModel()
|
||||
viewModel: HomeViewModel,
|
||||
drawerViewModel: DrawerViewModel,
|
||||
navBarViewModel: NavigationBarViewModel,
|
||||
) {
|
||||
HomeScreen(
|
||||
onStartSessionClick = { viewModel.onStartSessionClick(open) },
|
||||
drawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp),
|
||||
navigationBarActions = getNavigationBarActions(navBarViewModel, open),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HomeScreen(
|
||||
onStartSessionClick: () -> Unit,
|
||||
drawerActions: DrawerActions,
|
||||
navigationBarActions: NavigationBarActions,
|
||||
) {
|
||||
|
||||
PrimaryScreenTemplate(
|
||||
title = resources().getString(R.string.home),
|
||||
open = open,
|
||||
openAndPopUp = openAndPopUp,
|
||||
drawerActions = drawerActions,
|
||||
navigationBarActions = navigationBarActions,
|
||||
action = { FriendsAction() }
|
||||
) {
|
||||
BasicButton(R.string.start_session, Modifier.basicButton()) {
|
||||
viewModel.onStartSessionClick(open)
|
||||
onStartSessionClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FriendsAction () {
|
||||
fun FriendsAction() {
|
||||
IconButton(onClick = { /*TODO*/ }) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Person,
|
||||
contentDescription = resources().getString(R.string.friends)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun HomeScreenPreview() {
|
||||
HomeScreen(
|
||||
onStartSessionClick = {},
|
||||
drawerActions = DrawerActions({}, {}, {}, {}, {}),
|
||||
navigationBarActions = NavigationBarActions({}, {}, {}, {})
|
||||
)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import be.ugent.sel.studeez.common.composable.*
|
||||
import be.ugent.sel.studeez.common.ext.basicButton
|
||||
import be.ugent.sel.studeez.common.ext.fieldModifier
|
||||
|
@ -18,14 +18,48 @@ import be.ugent.sel.studeez.common.ext.textButton
|
|||
import be.ugent.sel.studeez.resources
|
||||
import be.ugent.sel.studeez.R.string as AppText
|
||||
|
||||
data class LoginScreenActions(
|
||||
val onEmailChange: (String) -> Unit,
|
||||
val onPasswordChange: (String) -> Unit,
|
||||
val onSignUpClick: () -> Unit,
|
||||
val onSignInClick: () -> Unit,
|
||||
val onForgotPasswordClick: () -> Unit,
|
||||
)
|
||||
|
||||
fun getLoginScreenActions(
|
||||
viewModel: LoginViewModel,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
): LoginScreenActions {
|
||||
return LoginScreenActions(
|
||||
onEmailChange = { viewModel.onEmailChange(it) },
|
||||
onPasswordChange = { viewModel.onPasswordChange(it) },
|
||||
onSignUpClick = { viewModel.onSignUpClick(openAndPopUp) },
|
||||
onSignInClick = { viewModel.onSignInClick(openAndPopUp) },
|
||||
onForgotPasswordClick = { viewModel.onForgotPasswordClick() }
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LoginScreen(
|
||||
fun LoginRoute(
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: LoginViewModel = hiltViewModel()
|
||||
viewModel: LoginViewModel,
|
||||
) {
|
||||
val uiState by viewModel.uiState
|
||||
|
||||
LoginScreen(
|
||||
modifier = modifier,
|
||||
uiState = uiState,
|
||||
loginScreenActions = getLoginScreenActions(viewModel = viewModel, openAndPopUp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LoginScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
uiState: LoginUiState,
|
||||
loginScreenActions: LoginScreenActions,
|
||||
) {
|
||||
SimpleScreenTemplate(title = resources().getString(AppText.sign_in)) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
|
@ -35,18 +69,42 @@ fun LoginScreen(
|
|||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
EmailField(uiState.email, viewModel::onEmailChange, Modifier.fieldModifier())
|
||||
PasswordField(uiState.password, viewModel::onPasswordChange, Modifier.fieldModifier())
|
||||
EmailField(
|
||||
uiState.email,
|
||||
loginScreenActions.onEmailChange,
|
||||
Modifier.fieldModifier()
|
||||
)
|
||||
PasswordField(
|
||||
uiState.password,
|
||||
loginScreenActions.onPasswordChange,
|
||||
Modifier.fieldModifier()
|
||||
)
|
||||
BasicButton(
|
||||
AppText.sign_in,
|
||||
Modifier.basicButton(),
|
||||
onClick = loginScreenActions.onSignInClick,
|
||||
)
|
||||
|
||||
BasicButton(AppText.sign_in, Modifier.basicButton()) { viewModel.onSignInClick(openAndPopUp) }
|
||||
BasicTextButton(
|
||||
AppText.not_already_user,
|
||||
Modifier.textButton(),
|
||||
action = loginScreenActions.onSignUpClick,
|
||||
)
|
||||
|
||||
BasicTextButton(AppText.not_already_user, Modifier.textButton()) {
|
||||
viewModel.onNotAlreadyUser(openAndPopUp)
|
||||
}
|
||||
|
||||
BasicTextButton(AppText.forgot_password, Modifier.textButton()) {
|
||||
viewModel.onForgotPasswordClick()
|
||||
}
|
||||
BasicTextButton(
|
||||
AppText.forgot_password,
|
||||
Modifier.textButton(),
|
||||
action = loginScreenActions.onForgotPasswordClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun LoginScreenPreview() {
|
||||
LoginScreen(
|
||||
uiState = LoginUiState(),
|
||||
loginScreenActions = LoginScreenActions({}, {}, {}, {}, {})
|
||||
)
|
||||
}
|
|
@ -63,7 +63,7 @@ class LoginViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun onNotAlreadyUser(openAndPopUp: (String, String) -> Unit) {
|
||||
fun onSignUpClick(openAndPopUp: (String, String) -> Unit) {
|
||||
openAndPopUp(SIGN_UP_SCREEN, LOGIN_SCREEN)
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
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.BasicTextButton
|
||||
import be.ugent.sel.studeez.common.composable.LabelledInputField
|
||||
|
@ -14,14 +13,43 @@ import be.ugent.sel.studeez.common.ext.textButton
|
|||
import be.ugent.sel.studeez.resources
|
||||
import be.ugent.sel.studeez.ui.theme.StudeezTheme
|
||||
|
||||
data class EditProfileActions(
|
||||
val onUserNameChange: (String) -> Unit,
|
||||
val onSaveClick: () -> Unit,
|
||||
val onDeleteClick: () -> Unit
|
||||
)
|
||||
|
||||
fun getEditProfileActions(
|
||||
viewModel: ProfileEditViewModel,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
): EditProfileActions {
|
||||
return EditProfileActions(
|
||||
onUserNameChange = { viewModel.onUsernameChange(it) },
|
||||
onSaveClick = { viewModel.onSaveClick() },
|
||||
onDeleteClick = { viewModel.onDeleteClick(openAndPopUp) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EditProfileRoute(
|
||||
goBack: () -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: ProfileEditViewModel,
|
||||
) {
|
||||
val uiState by viewModel.uiState
|
||||
EditProfileScreen(
|
||||
goBack = goBack,
|
||||
uiState = uiState,
|
||||
editProfileActions = getEditProfileActions(viewModel, openAndPopUp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EditProfileScreen(
|
||||
goBack: () -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: ProfileEditViewModel = hiltViewModel()
|
||||
uiState: ProfileEditUiState,
|
||||
editProfileActions: EditProfileActions,
|
||||
) {
|
||||
val uiState by viewModel.uiState
|
||||
|
||||
SecondaryScreenTemplate(
|
||||
title = resources().getString(R.string.editing_profile),
|
||||
popUp = goBack
|
||||
|
@ -29,16 +57,19 @@ fun EditProfileScreen(
|
|||
Column {
|
||||
LabelledInputField(
|
||||
value = uiState.username,
|
||||
onNewValue = viewModel::onUsernameChange,
|
||||
onNewValue = editProfileActions.onUserNameChange,
|
||||
label = R.string.username
|
||||
)
|
||||
|
||||
BasicTextButton(text = R.string.save, Modifier.textButton()) {
|
||||
viewModel.onSaveClick()
|
||||
}
|
||||
BasicTextButton(text = R.string.delete_profile, Modifier.textButton()) {
|
||||
viewModel.onDeleteClick(openAndPopUp)
|
||||
}
|
||||
BasicTextButton(
|
||||
text = R.string.save,
|
||||
Modifier.textButton(),
|
||||
action = editProfileActions.onSaveClick
|
||||
)
|
||||
BasicTextButton(
|
||||
text = R.string.delete_profile,
|
||||
Modifier.textButton(),
|
||||
action = editProfileActions.onDeleteClick
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,9 +78,6 @@ fun EditProfileScreen(
|
|||
@Composable
|
||||
fun EditProfileScreenComposable() {
|
||||
StudeezTheme {
|
||||
EditProfileScreen (
|
||||
{},
|
||||
{_, _ -> {}}
|
||||
)
|
||||
EditProfileScreen({}, ProfileEditUiState(), EditProfileActions({}, {}, {}))
|
||||
}
|
||||
}
|
|
@ -4,30 +4,68 @@ import androidx.compose.material.Icon
|
|||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
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 kotlinx.coroutines.CoroutineScope
|
||||
import be.ugent.sel.studeez.R.string as AppText
|
||||
|
||||
data class ProfileActions(
|
||||
val getUsername: suspend CoroutineScope.() -> String?,
|
||||
val onEditProfileClick: () -> Unit,
|
||||
)
|
||||
|
||||
fun getProfileActions(
|
||||
viewModel: ProfileViewModel,
|
||||
open: (String) -> Unit,
|
||||
): ProfileActions {
|
||||
return ProfileActions(
|
||||
getUsername = { viewModel.getUsername() },
|
||||
onEditProfileClick = { viewModel.onEditProfileClick(open) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ProfileRoute(
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: ProfileViewModel,
|
||||
) {
|
||||
ProfileScreen(
|
||||
profileActions = getProfileActions(viewModel, open),
|
||||
drawerActions = getDrawerActions(hiltViewModel(), open, openAndPopUp),
|
||||
navigationBarActions = getNavigationBarActions(hiltViewModel(), open),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ProfileScreen(
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: ProfileViewModel = hiltViewModel()
|
||||
profileActions: ProfileActions,
|
||||
drawerActions: DrawerActions,
|
||||
navigationBarActions: NavigationBarActions,
|
||||
) {
|
||||
var username: String? by remember { mutableStateOf("") }
|
||||
LaunchedEffect(key1 = Unit) {
|
||||
username = viewModel.getUsername()
|
||||
username = profileActions.getUsername(this)
|
||||
}
|
||||
|
||||
PrimaryScreenTemplate(
|
||||
title = resources().getString(AppText.profile),
|
||||
open = open,
|
||||
openAndPopUp = openAndPopUp,
|
||||
action = { EditAction { viewModel.onEditProfileClick(open) } }
|
||||
drawerActions = drawerActions,
|
||||
navigationBarActions = navigationBarActions,
|
||||
action = { EditAction(onClick = profileActions.onEditProfileClick) }
|
||||
) {
|
||||
Headline(text = (username ?: resources().getString(R.string.no_username)))
|
||||
}
|
||||
|
@ -44,4 +82,14 @@ fun EditAction(
|
|||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ProfileScreenPreview() {
|
||||
ProfileScreen(
|
||||
profileActions = ProfileActions({ null }, {}),
|
||||
drawerActions = DrawerActions({}, {}, {}, {}, {}),
|
||||
navigationBarActions = NavigationBarActions({}, {}, {}, {})
|
||||
)
|
||||
}
|
|
@ -24,34 +24,71 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import be.ugent.sel.studeez.navigation.StudeezDestinations
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import be.ugent.sel.studeez.R
|
||||
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalEndlessTimer
|
||||
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer
|
||||
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer
|
||||
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer.StudyState
|
||||
import be.ugent.sel.studeez.resources
|
||||
import kotlinx.coroutines.delay
|
||||
import javax.inject.Singleton
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
data class SessionActions(
|
||||
val getTimer: () -> FunctionalTimer,
|
||||
val getTask: () -> String,
|
||||
val releaseMediaPlayer: () -> Unit,
|
||||
val startMediaPlayer: () -> Unit,
|
||||
)
|
||||
|
||||
fun getSessionActions(
|
||||
viewModel: SessionViewModel,
|
||||
mediaplayer: MediaPlayer,
|
||||
): SessionActions {
|
||||
return SessionActions(
|
||||
getTimer = viewModel::getTimer,
|
||||
getTask = viewModel::getTask,
|
||||
releaseMediaPlayer = mediaplayer::release,
|
||||
startMediaPlayer = mediaplayer::start,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SessionScreen(
|
||||
fun SessionRoute(
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: SessionViewModel = hiltViewModel()
|
||||
viewModel: SessionViewModel,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
|
||||
val mediaplayer = MediaPlayer.create(context, uri)
|
||||
mediaplayer.isLooping = false
|
||||
|
||||
InvisibleSessionManager.setParameters(viewModel = viewModel, mediaplayer = mediaplayer)
|
||||
InvisibleSessionManager.setParameters(
|
||||
viewModel = viewModel,
|
||||
mediaplayer = mediaplayer
|
||||
)
|
||||
|
||||
SessionScreen(
|
||||
open = open,
|
||||
sessionActions = getSessionActions(viewModel, mediaplayer)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SessionScreen(
|
||||
open: (String) -> Unit,
|
||||
sessionActions: SessionActions
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(10.dp)
|
||||
) {
|
||||
Timer(viewModel, mediaplayer)
|
||||
modifier = Modifier.padding(10.dp)
|
||||
) {
|
||||
Timer(
|
||||
sessionActions = sessionActions
|
||||
)
|
||||
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
|
@ -61,12 +98,11 @@ fun SessionScreen(
|
|||
) {
|
||||
TextButton(
|
||||
onClick = {
|
||||
mediaplayer.stop()
|
||||
mediaplayer.release()
|
||||
sessionActions.releaseMediaPlayer
|
||||
|
||||
open(StudeezDestinations.HOME_SCREEN)
|
||||
InvisibleSessionManager.isSession = false
|
||||
// Vanaf hier ook naar report gaan als "end session" knop word ingedrukt
|
||||
},
|
||||
},
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 20.dp)
|
||||
.border(1.dp, Color.Red, RoundedCornerShape(32.dp))
|
||||
|
@ -77,7 +113,8 @@ fun SessionScreen(
|
|||
color = Color.Red,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 18.sp,
|
||||
modifier = Modifier.padding(1.dp)
|
||||
modifier = Modifier
|
||||
.padding(1.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -85,19 +122,21 @@ fun SessionScreen(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun Timer(viewModel: SessionViewModel = hiltViewModel(), mediaplayer: MediaPlayer) {
|
||||
private fun Timer(
|
||||
sessionActions: SessionActions
|
||||
) {
|
||||
var tikker by remember { mutableStateOf(false) }
|
||||
LaunchedEffect(tikker) {
|
||||
delay(1.seconds)
|
||||
viewModel.getTimer().tick()
|
||||
sessionActions.getTimer().tick()
|
||||
tikker = !tikker
|
||||
}
|
||||
|
||||
if (viewModel.getTimer().hasCurrentCountdownEnded() && !viewModel.getTimer().hasEnded()) {
|
||||
mediaplayer.start()
|
||||
if (sessionActions.getTimer().hasCurrentCountdownEnded() && !sessionActions.getTimer().hasEnded()) {
|
||||
sessionActions.startMediaPlayer
|
||||
}
|
||||
|
||||
val hms = viewModel.getTimer().getHoursMinutesSeconds()
|
||||
val hms = sessionActions.getTimer().getHoursMinutesSeconds()
|
||||
Column {
|
||||
Text(
|
||||
text = "${hms.hours} : ${hms.minutes} : ${hms.seconds}",
|
||||
|
@ -108,14 +147,14 @@ private fun Timer(viewModel: SessionViewModel = hiltViewModel(), mediaplayer: Me
|
|||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 40.sp,
|
||||
)
|
||||
val stateString: String = when (viewModel.getTimer().view) {
|
||||
val stateString: String = when (sessionActions.getTimer().view) {
|
||||
StudyState.DONE -> resources().getString(R.string.state_done)
|
||||
StudyState.FOCUS -> resources().getString(R.string.state_focus)
|
||||
StudyState.BREAK -> resources().getString(R.string.state_take_a_break)
|
||||
StudyState.FOCUS_REMAINING ->
|
||||
(viewModel.getTimer() as FunctionalPomodoroTimer?)?.breaksRemaining?.let {
|
||||
(sessionActions.getTimer() as FunctionalPomodoroTimer?)?.breaksRemaining?.let {
|
||||
resources().getQuantityString(R.plurals.state_focus_remaining, it, it)
|
||||
}.toString()
|
||||
}.toString()
|
||||
}
|
||||
|
||||
Text(
|
||||
|
@ -139,7 +178,7 @@ private fun Timer(viewModel: SessionViewModel = hiltViewModel(), mediaplayer: Me
|
|||
.background(Color.Blue, RoundedCornerShape(32.dp))
|
||||
) {
|
||||
Text(
|
||||
text = viewModel.getTask(),
|
||||
text = sessionActions.getTask(),
|
||||
color = Color.White,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
|
@ -151,6 +190,8 @@ private fun Timer(viewModel: SessionViewModel = hiltViewModel(), mediaplayer: Me
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Singleton
|
||||
object InvisibleSessionManager {
|
||||
private lateinit var viewModel: SessionViewModel
|
||||
private lateinit var mediaplayer: MediaPlayer
|
||||
|
@ -174,3 +215,19 @@ object InvisibleSessionManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TimerPreview() {
|
||||
Timer(sessionActions = SessionActions({ FunctionalEndlessTimer() }, { "Preview" }, {}, {}))
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SessionPreview() {
|
||||
SessionScreen(
|
||||
open = {},
|
||||
sessionActions = SessionActions({ FunctionalEndlessTimer() }, { "Preview" }, {}, {})
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -10,23 +10,64 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import be.ugent.sel.studeez.common.composable.*
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import be.ugent.sel.studeez.common.composable.BasicButton
|
||||
import be.ugent.sel.studeez.common.composable.BasicTextButton
|
||||
import be.ugent.sel.studeez.common.composable.EmailField
|
||||
import be.ugent.sel.studeez.common.composable.PasswordField
|
||||
import be.ugent.sel.studeez.common.composable.RepeatPasswordField
|
||||
import be.ugent.sel.studeez.common.composable.SimpleScreenTemplate
|
||||
import be.ugent.sel.studeez.common.composable.UsernameField
|
||||
import be.ugent.sel.studeez.common.ext.basicButton
|
||||
import be.ugent.sel.studeez.common.ext.fieldModifier
|
||||
import be.ugent.sel.studeez.common.ext.textButton
|
||||
import be.ugent.sel.studeez.resources
|
||||
import be.ugent.sel.studeez.R.string as AppText
|
||||
|
||||
data class SignUpActions(
|
||||
val onUserNameChange: (String) -> Unit,
|
||||
val onEmailChange: (String) -> Unit,
|
||||
val onPasswordChange: (String) -> Unit,
|
||||
val onRepeatPasswordChange: (String) -> Unit,
|
||||
val onSignUpClick: () -> Unit,
|
||||
val onLoginClick: () -> Unit,
|
||||
)
|
||||
|
||||
fun getSignUpActions(
|
||||
viewModel: SignUpViewModel,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
): SignUpActions {
|
||||
return SignUpActions(
|
||||
onUserNameChange = { viewModel.onUsernameChange(it) },
|
||||
onEmailChange = { viewModel.onEmailChange(it) },
|
||||
onPasswordChange = { viewModel.onPasswordChange(it) },
|
||||
onRepeatPasswordChange = { viewModel.onRepeatPasswordChange(it) },
|
||||
onSignUpClick = { viewModel.onSignUpClick(openAndPopUp) },
|
||||
onLoginClick = { viewModel.onLoginClick(openAndPopUp) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SignUpScreen(
|
||||
fun SignUpRoute(
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: SignUpViewModel = hiltViewModel()
|
||||
viewModel: SignUpViewModel,
|
||||
) {
|
||||
val uiState by viewModel.uiState
|
||||
val fieldModifier = Modifier.fieldModifier()
|
||||
SignUpScreen(
|
||||
modifier = modifier,
|
||||
uiState,
|
||||
getSignUpActions(viewModel, openAndPopUp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SignUpScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
uiState: SignUpUiState,
|
||||
signUpActions: SignUpActions,
|
||||
) {
|
||||
val fieldModifier = Modifier.fieldModifier()
|
||||
SimpleScreenTemplate(title = resources().getString(AppText.create_account)) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
|
@ -36,40 +77,45 @@ fun SignUpScreen(
|
|||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
|
||||
UsernameField(
|
||||
uiState.username,
|
||||
viewModel::onUsernameChange,
|
||||
signUpActions.onUserNameChange,
|
||||
fieldModifier
|
||||
)
|
||||
|
||||
EmailField(
|
||||
uiState.email,
|
||||
viewModel::onEmailChange,
|
||||
signUpActions.onEmailChange,
|
||||
fieldModifier
|
||||
)
|
||||
|
||||
PasswordField(
|
||||
uiState.password,
|
||||
viewModel::onPasswordChange,
|
||||
signUpActions.onPasswordChange,
|
||||
fieldModifier
|
||||
)
|
||||
|
||||
RepeatPasswordField(
|
||||
uiState.repeatPassword,
|
||||
viewModel::onRepeatPasswordChange,
|
||||
signUpActions.onRepeatPasswordChange,
|
||||
fieldModifier
|
||||
)
|
||||
|
||||
BasicButton(AppText.create_account, Modifier.basicButton()) {
|
||||
viewModel.onSignUpClick(openAndPopUp)
|
||||
}
|
||||
|
||||
BasicTextButton(AppText.already_user, Modifier.textButton()) {
|
||||
viewModel.onLoginScreenClick(openAndPopUp)
|
||||
}
|
||||
BasicButton(
|
||||
AppText.create_account,
|
||||
Modifier.basicButton(),
|
||||
onClick = signUpActions.onSignUpClick
|
||||
)
|
||||
BasicTextButton(
|
||||
AppText.already_user,
|
||||
Modifier.textButton(),
|
||||
action = signUpActions.onLoginClick
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SignUpPreview() {
|
||||
SignUpScreen(
|
||||
uiState = SignUpUiState(),
|
||||
signUpActions = SignUpActions({}, {}, {}, {}, {}, {})
|
||||
)
|
||||
}
|
|
@ -71,7 +71,7 @@ class SignUpViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun onLoginScreenClick(openAndPopUp: (String, String) -> Unit) {
|
||||
fun onLoginClick(openAndPopUp: (String, String) -> Unit) {
|
||||
openAndPopUp(LOGIN_SCREEN, SIGN_UP_SCREEN)
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import be.ugent.sel.studeez.common.composable.BasicButton
|
||||
import be.ugent.sel.studeez.common.ext.basicButton
|
||||
import kotlinx.coroutines.delay
|
||||
|
@ -24,14 +24,26 @@ import be.ugent.sel.studeez.R.string as AppText
|
|||
private const val SPLASH_TIMEOUT = 500L
|
||||
|
||||
@Composable
|
||||
fun SplashScreen(
|
||||
fun SplashRoute(
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: SplashViewModel = hiltViewModel()
|
||||
viewModel: SplashViewModel,
|
||||
) {
|
||||
SplashScreen(
|
||||
modifier = modifier,
|
||||
onAppStart = { viewModel.onAppStart(openAndPopUp) },
|
||||
showError = viewModel.showError.value
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SplashScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
onAppStart: () -> Unit,
|
||||
showError: Boolean,
|
||||
) {
|
||||
Column(
|
||||
modifier =
|
||||
modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight()
|
||||
.background(color = MaterialTheme.colors.background)
|
||||
|
@ -39,17 +51,37 @@ fun SplashScreen(
|
|||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
if (viewModel.showError.value) {
|
||||
if (showError) {
|
||||
Text(text = stringResource(AppText.generic_error))
|
||||
|
||||
BasicButton(AppText.try_again, Modifier.basicButton()) { viewModel.onAppStart(openAndPopUp) }
|
||||
BasicButton(
|
||||
AppText.try_again,
|
||||
Modifier.basicButton(),
|
||||
onClick = onAppStart,
|
||||
)
|
||||
} else {
|
||||
CircularProgressIndicator(color = MaterialTheme.colors.onBackground)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(true) {
|
||||
delay(SPLASH_TIMEOUT)
|
||||
viewModel.onAppStart(openAndPopUp)
|
||||
onAppStart()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SplashPreview() {
|
||||
SplashScreen(
|
||||
onAppStart = {},
|
||||
showError = false,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SplashErrorPreview() {
|
||||
SplashScreen(
|
||||
onAppStart = {},
|
||||
showError = true,
|
||||
)
|
||||
}
|
|
@ -1,122 +1,118 @@
|
|||
package be.ugent.sel.studeez.screens.timer_overview
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.annotation.StringRes
|
||||
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.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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 androidx.hilt.navigation.compose.hiltViewModel
|
||||
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.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
|
||||
import be.ugent.sel.studeez.resources
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
data class TimerOverviewActions(
|
||||
val getUserTimers: () -> Flow<List<TimerInfo>>,
|
||||
val getDefaultTimers: () -> List<TimerInfo>,
|
||||
val onEditClick: (TimerInfo) -> Unit,
|
||||
)
|
||||
|
||||
fun getTimerOverviewActions(
|
||||
viewModel: TimerOverviewViewModel,
|
||||
): TimerOverviewActions {
|
||||
return TimerOverviewActions(
|
||||
getUserTimers = viewModel::getUserTimers,
|
||||
getDefaultTimers = viewModel::getDefaultTimers,
|
||||
onEditClick = { viewModel.update(it) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimerOverviewRoute(
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: TimerOverviewViewModel,
|
||||
drawerViewModel: DrawerViewModel,
|
||||
navBarViewModel: NavigationBarViewModel,
|
||||
) {
|
||||
TimerOverviewScreen(
|
||||
timerOverviewActions = getTimerOverviewActions(viewModel),
|
||||
drawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp),
|
||||
navigationBarActions = getNavigationBarActions(navBarViewModel, open),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimerOverviewScreen(
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: TimerOverviewViewModel = hiltViewModel()
|
||||
timerOverviewActions: TimerOverviewActions,
|
||||
drawerActions: DrawerActions,
|
||||
navigationBarActions: NavigationBarActions,
|
||||
) {
|
||||
|
||||
val timers = viewModel.getUserTimers().collectAsState(initial = emptyList())
|
||||
val timers = timerOverviewActions.getUserTimers().collectAsState(initial = emptyList())
|
||||
|
||||
// TODO moet geen primary screen zijn: geen navbar nodig
|
||||
PrimaryScreenTemplate(
|
||||
title = resources().getString(R.string.timers),
|
||||
open = open,
|
||||
openAndPopUp = openAndPopUp
|
||||
drawerActions = drawerActions,
|
||||
navigationBarActions = navigationBarActions,
|
||||
) {
|
||||
|
||||
Column {
|
||||
LazyColumn(
|
||||
verticalArrangement = Arrangement.spacedBy(7.dp)
|
||||
) {
|
||||
// Default Timers, cannot be edited
|
||||
items(viewModel.getDefaultTimers()) {
|
||||
TimerEntry(timerInfo = it, canDisplay = false)
|
||||
items(timerOverviewActions.getDefaultTimers()) {
|
||||
TimerEntry(timerInfo = it) {}
|
||||
}
|
||||
|
||||
// User timers, can be edited
|
||||
items(timers.value) {
|
||||
TimerEntry(timerInfo = it, true, R.string.edit) { timerInfo ->
|
||||
viewModel.update(timerInfo)
|
||||
items(timers.value) { timerInfo ->
|
||||
TimerEntry(
|
||||
timerInfo = timerInfo,
|
||||
) {
|
||||
StealthButton(
|
||||
text = R.string.edit,
|
||||
onClick = { timerOverviewActions.onEditClick(timerInfo) }
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
BasicButton(R.string.add_timer, Modifier.basicButton()) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimerEntry(
|
||||
timerInfo: TimerInfo,
|
||||
canDisplay: Boolean,
|
||||
@StringRes buttonName: Int = -1,
|
||||
buttonFunction: (TimerInfo) -> Unit = {}
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Column(
|
||||
Modifier.padding(horizontal = 10.dp)
|
||||
) {
|
||||
Text(
|
||||
text = timerInfo.name,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 20.sp
|
||||
)
|
||||
Text(
|
||||
text = timerInfo.description,
|
||||
fontWeight = FontWeight.Light,
|
||||
fontSize = 15.sp
|
||||
)
|
||||
}
|
||||
if (canDisplay) {
|
||||
StealthButton(buttonName) {
|
||||
buttonFunction(timerInfo)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
|
||||
@Preview
|
||||
@Composable
|
||||
fun TimerEntryPreview() {
|
||||
val timerInfo = CustomTimerInfo(
|
||||
"my preview timer",
|
||||
"This is the description of the timer",
|
||||
60
|
||||
fun TimerOverviewPreview() {
|
||||
val customTimer = CustomTimerInfo(
|
||||
"my preview timer", "This is the description of the timer", 60
|
||||
)
|
||||
Scaffold() {
|
||||
Column() {
|
||||
TimerEntry(timerInfo = timerInfo, true, buttonName = R.string.edit) { }
|
||||
TimerEntry(timerInfo = timerInfo, true, buttonName = R.string.edit) { }
|
||||
TimerEntry(timerInfo = timerInfo, true, buttonName = R.string.edit) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
TimerOverviewScreen(
|
||||
timerOverviewActions = TimerOverviewActions(
|
||||
{ flowOf() },
|
||||
{ listOf(customTimer, customTimer) },
|
||||
{}),
|
||||
drawerActions = DrawerActions({}, {}, {}, {}, {}),
|
||||
navigationBarActions = NavigationBarActions({}, {}, {}, {})
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,42 +3,89 @@ 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.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import be.ugent.sel.studeez.R
|
||||
import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate
|
||||
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 be.ugent.sel.studeez.screens.timer_overview.TimerEntry
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
data class TimerSelectionActions(
|
||||
val getAllTimers: () -> Flow<List<TimerInfo>>,
|
||||
val startSession: (TimerInfo) -> Unit,
|
||||
)
|
||||
|
||||
fun getTimerSelectionActions(
|
||||
viewModel: TimerSelectionViewModel,
|
||||
open: (String) -> Unit,
|
||||
): TimerSelectionActions {
|
||||
return TimerSelectionActions(
|
||||
getAllTimers = viewModel::getAllTimers,
|
||||
startSession = { viewModel.startSession(open, it) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimerSelectionRoute(
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: TimerSelectionViewModel,
|
||||
drawerViewModel: DrawerViewModel,
|
||||
navBarViewModel: NavigationBarViewModel,
|
||||
) {
|
||||
TimerSelectionScreen(
|
||||
timerSelectionActions = getTimerSelectionActions(viewModel, open),
|
||||
drawerActions = getDrawerActions(drawerViewModel, open, openAndPopUp),
|
||||
navigationBarActions = getNavigationBarActions(navBarViewModel, open),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TimerSelectionScreen(
|
||||
open: (String) -> Unit,
|
||||
openAndPopUp: (String, String) -> Unit,
|
||||
viewModel: TimerSelectionViewModel = hiltViewModel()
|
||||
timerSelectionActions: TimerSelectionActions,
|
||||
drawerActions: DrawerActions,
|
||||
navigationBarActions: NavigationBarActions,
|
||||
) {
|
||||
|
||||
val timers = viewModel.getAllTimers().collectAsState(initial = emptyList())
|
||||
|
||||
val timers = timerSelectionActions.getAllTimers().collectAsState(initial = emptyList())
|
||||
PrimaryScreenTemplate(
|
||||
title = resources().getString(R.string.timers),
|
||||
open = open,
|
||||
openAndPopUp = openAndPopUp,
|
||||
drawerActions = drawerActions,
|
||||
navigationBarActions = navigationBarActions,
|
||||
) {
|
||||
|
||||
LazyColumn(verticalArrangement = Arrangement.spacedBy(7.dp)) {
|
||||
|
||||
// All timers
|
||||
items(timers.value) {
|
||||
items(timers.value) { timerInfo ->
|
||||
TimerEntry(
|
||||
timerInfo = it,
|
||||
canDisplay = true,
|
||||
buttonName = R.string.start
|
||||
) { timerInfo ->
|
||||
viewModel.startSession(open, timerInfo)
|
||||
timerInfo = timerInfo,
|
||||
) {
|
||||
StealthButton(
|
||||
text = R.string.start,
|
||||
onClick = { timerSelectionActions.startSession(timerInfo) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TimerSelectionPreview() {
|
||||
TimerSelectionScreen(
|
||||
timerSelectionActions = TimerSelectionActions({ flowOf() }, {}),
|
||||
drawerActions = DrawerActions({}, {}, {}, {}, {}),
|
||||
navigationBarActions = NavigationBarActions({}, {}, {}, {}),
|
||||
)
|
||||
}
|
Reference in a new issue