Resolved merge conflicts (call with friends)

This commit is contained in:
lbarraga 2023-05-04 00:12:04 +02:00
commit 46109ac4ff
31 changed files with 1011 additions and 205 deletions

2
.idea/misc.xml generated
View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View file

@ -2,18 +2,8 @@ package be.ugent.sel.studeez
import android.content.res.Resources
import androidx.compose.foundation.layout.padding
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.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
@ -38,10 +28,13 @@ 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.sessions.SessionsRoute
import be.ugent.sel.studeez.screens.settings.SettingsRoute
import be.ugent.sel.studeez.screens.sign_up.SignUpRoute
import be.ugent.sel.studeez.screens.splash.SplashRoute
import be.ugent.sel.studeez.screens.timer_edit.TimerEditRoute
import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewRoute
import be.ugent.sel.studeez.screens.timer_overview.add_timer.AddTimerRoute
import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionRoute
import be.ugent.sel.studeez.ui.theme.StudeezTheme
import kotlinx.coroutines.CoroutineScope
@ -92,7 +85,7 @@ fun resources(): Resources {
@Composable
fun StudeezNavGraph(
appState: StudeezAppstate,
modifier: Modifier,
modifier: Modifier = Modifier,
) {
val drawerViewModel: DrawerViewModel = hiltViewModel()
val navBarViewModel: NavigationBarViewModel = hiltViewModel()
@ -114,8 +107,52 @@ fun StudeezNavGraph(
startDestination = StudeezDestinations.SPLASH_SCREEN,
modifier = modifier,
) {
// NavBar
composable(StudeezDestinations.HOME_SCREEN) {
HomeRoute(
open,
viewModel = hiltViewModel(),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions
)
}
composable(StudeezDestinations.TASKS_SCREEN) {
// TODO
}
composable(StudeezDestinations.SESSIONS_SCREEN) {
SessionsRoute(
drawerActions = drawerActions,
navigationBarActions = navigationBarActions
)
}
composable(StudeezDestinations.PROFILE_SCREEN) {
ProfileRoute(
open,
viewModel = hiltViewModel(),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions
)
}
// Drawer
composable(StudeezDestinations.TIMER_SCREEN) {
TimerOverviewRoute(
viewModel = hiltViewModel(),
drawerActions = drawerActions,
open = open
)
}
composable(StudeezDestinations.SETTINGS_SCREEN) {
SettingsRoute(
drawerActions = drawerActions
)
}
// Login flow
composable(StudeezDestinations.SPLASH_SCREEN) {
SplashRoute(
openAndPopUp,
@ -137,40 +174,12 @@ fun StudeezNavGraph(
)
}
composable(StudeezDestinations.HOME_SCREEN) {
HomeRoute(
// Studying flow
composable(StudeezDestinations.TIMER_SELECTION_SCREEN) {
TimerSelectionRoute(
open,
goBack,
viewModel = hiltViewModel(),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
)
}
// TODO Tasks screen
// TODO Sessions screen
composable(StudeezDestinations.PROFILE_SCREEN) {
ProfileRoute(
open,
viewModel = hiltViewModel(),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
)
}
composable(StudeezDestinations.TIMER_OVERVIEW_SCREEN) {
TimerOverviewRoute(
viewModel = hiltViewModel(),
drawerActions = drawerActions,
open = open
)
}
composable(StudeezDestinations.TIMER_EDIT_SCREEN) {
TimerEditRoute(
open = open,
popUp = goBack,
viewModel = hiltViewModel()
)
}
@ -182,10 +191,43 @@ fun StudeezNavGraph(
)
}
// TODO Timers screen
// TODO Settings screen
composable(StudeezDestinations.SESSION_RECAP) {
SessionRecapRoute(
openAndPopUp = openAndPopUp,
viewModel = hiltViewModel()
)
}
composable(StudeezDestinations.ADD_TIMER_SCREEN) {
AddTimerRoute(
open = open,
goBack = goBack,
viewModel = hiltViewModel()
)
}
composable(StudeezDestinations.TIMER_EDIT_SCREEN) {
TimerEditRoute(
open = open,
popUp = goBack,
viewModel = hiltViewModel()
)
}
// Friends flow
composable(StudeezDestinations.SEARCH_FRIENDS_SCREEN) {
// TODO
}
// Create & edit screens
composable(StudeezDestinations.CREATE_TASK_SCREEN) {
// TODO
}
composable(StudeezDestinations.CREATE_SESSION_SCREEN) {
// TODO
}
// Edit screens
composable(StudeezDestinations.EDIT_PROFILE_SCREEN) {
EditProfileRoute(
goBack,
@ -193,20 +235,5 @@ fun StudeezNavGraph(
viewModel = hiltViewModel(),
)
}
composable(StudeezDestinations.TIMER_SELECTION_SCREEN) {
TimerSelectionRoute(
open,
goBack,
viewModel = hiltViewModel(),
)
}
composable(StudeezDestinations.SESSION_RECAP) {
SessionRecapRoute(
openAndPopUp = openAndPopUp,
viewModel = hiltViewModel()
)
}
}
}

View file

@ -2,7 +2,6 @@ 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.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -13,10 +12,18 @@ import androidx.compose.ui.unit.sp
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.ext.basicButton
import be.ugent.sel.studeez.common.ext.card
import be.ugent.sel.studeez.common.ext.defaultButtonShape
@Composable
fun BasicTextButton(@StringRes text: Int, modifier: Modifier, action: () -> Unit) {
TextButton(onClick = action, modifier = modifier) { Text(text = stringResource(text)) }
TextButton(
onClick = action,
modifier = modifier
) {
Text(
text = stringResource(text)
)
}
}
@Composable
@ -30,7 +37,7 @@ fun BasicButton(
Button(
onClick = onClick,
modifier = modifier,
shape = RoundedCornerShape(20.dp),
shape = defaultButtonShape(),
colors = colors,
border = border,
) {
@ -47,6 +54,25 @@ fun BasicButtonPreview() {
BasicButton(text = R.string.add_timer, modifier = Modifier.basicButton()) {}
}
@Composable
fun NotInternationalisedButton(
text: String,
modifier: Modifier = Modifier,
colors: ButtonColors = ButtonDefaults.buttonColors(),
border: BorderStroke? = null,
onClick: () -> Unit
) {
Button(
onClick = onClick,
modifier = modifier,
shape = defaultButtonShape(),
colors = colors,
border = border
) {
Text(text = text)
}
}
@Composable
fun StealthButton(
@StringRes text: Int,

View file

@ -1,7 +1,9 @@
package be.ugent.sel.studeez.common.composable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.material.FloatingActionButton
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
@ -11,52 +13,134 @@ import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.DateRange
import androidx.compose.material.icons.filled.Person
import androidx.compose.runtime.Composable
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.ui.theme.StudeezTheme
import be.ugent.sel.studeez.R.string as AppText
const val TRANSITION = "transition"
val HEIGHT_DIFFERENCE = 30.dp
data class AddButtonActions(
val onTaskClick: () -> Unit,
val onFriendClick: () -> Unit,
val onSessionClick: () -> Unit
)
@Composable
fun CollapsedAddButton() {
FloatingActionButton(
onClick = { /* TODO popup add options */ }
fun AddButton(
addButtonActions: AddButtonActions
) {
var isExpanded by remember { mutableStateOf(false) }
// Rotate the button when expanded, normal when collapsed.
val transition = updateTransition(targetState = isExpanded, label = TRANSITION)
val rotate by transition.animateFloat(label = TRANSITION) { expanded -> if (expanded) 315f else 0f }
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top
) {
Icon(imageVector = Icons.Default.Add, contentDescription = "fab")
Box {
// Show minis when expanded.
if (isExpanded) {
ExpandedAddButton(
addButtonActions = addButtonActions
)
}
}
// The base add button
FloatingActionButton(
onClick = {
// Toggle expanded/collapsed.
isExpanded = !isExpanded
},
modifier = Modifier.padding(bottom = if (isExpanded) 78.dp else 0.dp)
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = "fab",
modifier = Modifier.rotate(rotate) // The rotation
)
}
}
}
@Composable
fun ExpandedAddButton() {
Row() {
IconButton(onClick = { /* TODO Go to next step */ }) {
Column (horizontalAlignment = Alignment.CenterHorizontally) {
Icon(imageVector = Icons.Default.Check, contentDescription = "Task")
Text(text = "Task")
}
}
IconButton(onClick = { /* TODO Go to next step */ }) {
Column (horizontalAlignment = Alignment.CenterHorizontally) {
Icon(imageVector = Icons.Default.Person, contentDescription = "Friend")
Text(text = "Friend")
}
}
IconButton(onClick = { /* TODO Go to next step */ }) {
Column (horizontalAlignment = Alignment.CenterHorizontally) {
Icon(imageVector = Icons.Default.DateRange, contentDescription = "Session")
Text(text = "Session")
}
}
fun ExpandedAddButton(
addButtonActions: AddButtonActions
) {
Row {
ExpandedEntry(
name = AppText.task,
imageVector = Icons.Default.Check,
onClick = addButtonActions.onTaskClick,
modifier = Modifier.padding(36.dp, HEIGHT_DIFFERENCE, 36.dp, 0.dp)
)
ExpandedEntry(
name = AppText.friend,
imageVector = Icons.Default.Person,
onClick = addButtonActions.onFriendClick
)
ExpandedEntry(
name = AppText.session,
imageVector = Icons.Default.DateRange,
onClick = addButtonActions.onSessionClick,
modifier = Modifier.padding(36.dp, HEIGHT_DIFFERENCE, 36.dp, 0.dp)
)
}
}
@Composable
fun ExpandedEntry(
name: Int,
imageVector: ImageVector,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
IconButton(
onClick = onClick,
modifier = modifier
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Icon(
imageVector = imageVector,
contentDescription = resources().getString(name),
// TODO Dark overlay
// tint = colors.surface
)
Text(
text = resources().getString(name),
// TODO Dark overlay
// color = colors.surface
)
}
}
}
@Preview
@Composable
fun CollapsedAddButtonPreview() {
StudeezTheme { CollapsedAddButton() }
fun AddButtonPreview() {
StudeezTheme { AddButton(
addButtonActions = AddButtonActions({}, {}, {})
)}
}
@Preview
@Composable
fun ExpandedAddButtonPreview() {
StudeezTheme { ExpandedAddButton() }
StudeezTheme { ExpandedAddButton (
addButtonActions = AddButtonActions({}, {}, {})
) }
}

View file

@ -57,7 +57,11 @@ fun PrimaryScreenTemplate(
bottomBar = { NavigationBar(navigationBarActions) },
floatingActionButtonPosition = FabPosition.Center,
isFloatingActionButtonDocked = true,
floatingActionButton = { CollapsedAddButton() }
floatingActionButton = { AddButton(AddButtonActions(
onTaskClick = navigationBarActions.onAddTaskClick,
onFriendClick = navigationBarActions.onAddFriendClick,
onSessionClick = navigationBarActions.onAddSessionClick
)) }
) {
content(it)
}
@ -70,7 +74,7 @@ fun PrimaryScreenPreview() {
PrimaryScreenTemplate(
"Preview screen",
DrawerActions({}, {}, {}, {}, {}),
NavigationBarActions({ false }, {}, {}, {}, {}),
NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}),
{
IconButton(onClick = { /*TODO*/ }) {
Icon(

View file

@ -1,5 +1,6 @@
package be.ugent.sel.studeez.common.composable.drawer
import android.content.Context
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@ -16,6 +17,7 @@ import androidx.compose.material.icons.outlined.Info
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@ -28,7 +30,7 @@ data class DrawerActions(
val onTimersClick: () -> Unit,
val onSettingsClick: () -> Unit,
val onLogoutClick: () -> Unit,
val onAboutClick: () -> Unit,
val onAboutClick: (Context) -> Unit,
)
fun getDrawerActions(
@ -41,7 +43,7 @@ fun getDrawerActions(
onTimersClick = { drawerViewModel.onTimersClick(open) },
onSettingsClick = { drawerViewModel.onSettingsClick(open) },
onLogoutClick = { drawerViewModel.onLogoutClick(openAndPopUp) },
onAboutClick = { drawerViewModel.onAboutClick(open) },
onAboutClick = { context -> drawerViewModel.onAboutClick(open, context = context) },
)
}
@ -79,10 +81,11 @@ fun Drawer(
)
}
val context = LocalContext.current
DrawerEntry(
icon = Icons.Outlined.Info,
text = resources().getString(R.string.about),
onClick = drawerActions.onAboutClick,
onClick = { drawerActions.onAboutClick(context) },
)
}
}
@ -96,7 +99,7 @@ fun DrawerEntry(
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier
.clickable(onClick = { onClick() })
.clickable(onClick = onClick)
.fillMaxWidth()
) {
Box(

View file

@ -1,5 +1,10 @@
package be.ugent.sel.studeez.common.composable.drawer
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import be.ugent.sel.studeez.domain.AccountDAO
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.navigation.StudeezDestinations
@ -9,6 +14,8 @@ import be.ugent.sel.studeez.screens.StudeezViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
const val REPO_URL: String = "https://github.ugent.be/SELab1/project2023-groep14/"
@HiltViewModel
class DrawerViewModel @Inject constructor(
private val accountDAO: AccountDAO,
@ -20,11 +27,11 @@ class DrawerViewModel @Inject constructor(
}
fun onTimersClick(openAndPopup: (String) -> Unit) {
openAndPopup(StudeezDestinations.TIMER_OVERVIEW_SCREEN)
openAndPopup(StudeezDestinations.TIMER_SCREEN)
}
fun onSettingsClick(open: (String) -> Unit) {
// TODO
open(StudeezDestinations.SETTINGS_SCREEN)
}
fun onLogoutClick(openAndPopUp: (String, String) -> Unit) {
@ -34,7 +41,8 @@ class DrawerViewModel @Inject constructor(
}
}
fun onAboutClick(open: (String) -> Unit) {
// TODO
fun onAboutClick(open: (String) -> Unit, context: Context) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(REPO_URL))
context.startActivity(intent)
}
}

View file

@ -14,16 +14,24 @@ 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.navigation.StudeezDestinations.SESSIONS_SCREEN
import be.ugent.sel.studeez.navigation.StudeezDestinations.TASKS_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,
val onProfileClick: () -> Unit,
// AddButton
val onAddTaskClick: () -> Unit,
val onAddFriendClick: () -> Unit,
val onAddSessionClick: () -> Unit
)
fun getNavigationBarActions(
@ -35,6 +43,7 @@ fun getNavigationBarActions(
isSelectedTab = { screen ->
screen == getCurrentScreen()
},
onHomeClick = {
navigationBarViewModel.onHomeClick(open)
},
@ -47,6 +56,16 @@ fun getNavigationBarActions(
onProfileClick = {
navigationBarViewModel.onProfileClick(open)
},
onAddTaskClick = {
navigationBarViewModel.onAddTaskClick(open)
},
onAddFriendClick = {
navigationBarViewModel.onAddFriendClick(open)
},
onAddSessionClick = {
navigationBarViewModel.onAddSessionClick(open)
}
)
}
@ -71,13 +90,12 @@ fun NavigationBar(
)
},
label = { Text(text = resources().getString(AppText.tasks)) },
// TODO selected = navigationBarActions.isSelectedTab(TASKS_SCREEN),
selected = false,
selected = navigationBarActions.isSelectedTab(TASKS_SCREEN),
onClick = navigationBarActions.onTasksClick
)
// Hack to space the entries in the navigation bar, make space for fab
BottomNavigationItem(icon = {}, onClick = {}, selected = false)
BottomNavigationItem(icon = {}, onClick = {}, selected = false, enabled = false)
BottomNavigationItem(
icon = {
@ -86,8 +104,7 @@ fun NavigationBar(
)
},
label = { Text(text = resources().getString(AppText.sessions)) },
// TODO selected = navigationBarActions.isSelectedTab(SESSIONS_SCREEN),
selected = false,
selected = navigationBarActions.isSelectedTab(SESSIONS_SCREEN),
onClick = navigationBarActions.onSessionsClick
)
@ -110,7 +127,7 @@ fun NavigationBar(
fun NavigationBarPreview() {
StudeezTheme {
NavigationBar(
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}),
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}),
)
}
}

View file

@ -1,12 +1,16 @@
package be.ugent.sel.studeez.common.composable.navbar
import be.ugent.sel.studeez.common.snackbar.SnackbarManager
import be.ugent.sel.studeez.domain.AccountDAO
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.navigation.StudeezDestinations.HOME_SCREEN
import be.ugent.sel.studeez.navigation.StudeezDestinations.PROFILE_SCREEN
import be.ugent.sel.studeez.navigation.StudeezDestinations.SESSIONS_SCREEN
import be.ugent.sel.studeez.navigation.StudeezDestinations.TASKS_SCREEN
import be.ugent.sel.studeez.screens.StudeezViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import be.ugent.sel.studeez.R.string as AppText
@HiltViewModel
class NavigationBarViewModel @Inject constructor(
@ -19,14 +23,29 @@ class NavigationBarViewModel @Inject constructor(
}
fun onTasksClick(open: (String) -> Unit) {
// TODO
open(TASKS_SCREEN)
}
fun onSessionsClick(open: (String) -> Unit) {
// TODO
open(SESSIONS_SCREEN)
}
fun onProfileClick(open: (String) -> Unit) {
open(PROFILE_SCREEN)
}
fun onAddTaskClick(open: (String) -> Unit) {
// TODO open(CREATE_TASK_SCREEN)
SnackbarManager.showMessage(AppText.create_task_not_possible_yet) // TODO Remove
}
fun onAddFriendClick(open: (String) -> Unit) {
// TODO open(SEARCH_FRIENDS_SCREEN)
SnackbarManager.showMessage(AppText.add_friend_not_possible_yet) // TODO Remove
}
fun onAddSessionClick(open: (String) -> Unit) {
// TODO open(CREATE_SESSION_SCREEN)
SnackbarManager.showMessage(AppText.create_session_not_possible_yet) // TODO Remove
}
}

View file

@ -0,0 +1,24 @@
package be.ugent.sel.studeez.common.composable.navbar
import android.app.TimePickerDialog
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
@Composable
fun BasicTimePicker(
onHoursChange: (Int) -> Unit,
onMinutesChange: (Int) -> Unit,
Hours: Int,
Minutes: Int,
): TimePickerDialog {
return TimePickerDialog(
LocalContext.current,
{ _, mHour: Int, mMinute: Int ->
onHoursChange(mHour)
onMinutesChange(mMinute)
},
Hours,
Minutes,
true
)
}

View file

@ -0,0 +1,8 @@
package be.ugent.sel.studeez.common.ext
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.unit.dp
fun defaultButtonShape(): RoundedCornerShape {
return RoundedCornerShape(20.dp)
}

View file

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

View file

@ -1,23 +1,34 @@
package be.ugent.sel.studeez.navigation
object StudeezDestinations {
const val SPLASH_SCREEN = "splash"
const val SIGN_UP_SCREEN = "signup"
const val LOGIN_SCREEN = "login"
// NavBar
const val HOME_SCREEN = "home"
const val TIMER_OVERVIEW_SCREEN = "timer_overview"
const val TASKS_SCREEN = "tasks"
const val SESSIONS_SCREEN = "sessions"
const val PROFILE_SCREEN = "profile"
// Drawer
const val TIMER_SCREEN = "timer_overview"
const val SETTINGS_SCREEN = "settings"
// Login flow
const val SPLASH_SCREEN = "splash"
const val LOGIN_SCREEN = "login"
const val SIGN_UP_SCREEN = "signup"
// Studying flow
const val TIMER_SELECTION_SCREEN = "timer_selection"
const val TIMER_EDIT_SCREEN = "timer_edit"
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"
// const val TIMERS_SCREEN = "timers"
// const val SETTINGS_SCREEN = "settings"
// Friends flow
const val SEARCH_FRIENDS_SCREEN = "search_friends"
// Edit screens
// Create & edit screens
const val CREATE_TASK_SCREEN = "create_task"
const val CREATE_SESSION_SCREEN = "create_session"
const val EDIT_PROFILE_SCREEN = "edit_profile"
const val ADD_TIMER_SCREEN = "add_timer"
}

View file

@ -33,13 +33,13 @@ fun HomeRoute(
fun HomeScreen(
onStartSessionClick: () -> Unit,
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions,
navigationBarActions: NavigationBarActions
) {
PrimaryScreenTemplate(
title = resources().getString(R.string.home),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
barAction = { FriendsAction() }
// TODO barAction = { FriendsAction() }
) {
BasicButton(R.string.start_session, Modifier.basicButton()) {
onStartSessionClick()
@ -63,6 +63,6 @@ fun HomeScreenPreview() {
HomeScreen(
onStartSessionClick = {},
drawerActions = DrawerActions({}, {}, {}, {}, {}),
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {})
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {})
)
}

View file

@ -63,7 +63,10 @@ fun EditProfileScreen(
BasicTextButton(
text = R.string.save,
Modifier.textButton(),
action = editProfileActions.onSaveClick
action = {
editProfileActions.onSaveClick()
goBack()
}
)
BasicTextButton(
text = R.string.delete_profile,

View file

@ -88,6 +88,6 @@ fun ProfileScreenPreview() {
ProfileScreen(
profileActions = ProfileActions({ null }, {}),
drawerActions = DrawerActions({}, {}, {}, {}, {}),
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {})
navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {})
)
}

View file

@ -47,8 +47,11 @@ fun SessionRecapScreen(modifier: Modifier, sessionRecapActions: SessionRecapActi
val sessionReport: SessionReport = sessionRecapActions.getSessionReport()
val studyTime: Int = sessionReport.studyTime
val hms: HoursMinutesSeconds = Time(studyTime).getAsHMS()
Column {
Column(
modifier = modifier
) {
Text(text = "You studied: $hms")
BasicButton(
R.string.save, Modifier.basicButton()
) {

View file

@ -11,7 +11,7 @@ import javax.inject.Inject
@HiltViewModel
class SessionRecapViewModel @Inject constructor(
private val sessionReportState: SessionReportState,
sessionReportState: SessionReportState,
private val sessionDAO: SessionDAO,
logService: LogService
) : StudeezViewModel(logService) {

View file

@ -0,0 +1,42 @@
package be.ugent.sel.studeez.screens.sessions
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.R.string as AppText
@Composable
fun SessionsRoute(
// viewModel: SessionsViewModel,
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions
) {
SessionsScreen(
drawerActions = drawerActions,
navigationBarActions = navigationBarActions
)
}
@Composable
fun SessionsScreen(
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions
) {
PrimaryScreenTemplate(
title = resources().getString(AppText.upcoming_sessions),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions
) {
Text(
text = resources().getString(AppText.sessions_temp_description),
modifier = Modifier.fillMaxSize(),
textAlign = TextAlign.Center
)
}
}

View file

@ -0,0 +1,37 @@
package be.ugent.sel.studeez.screens.settings
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import be.ugent.sel.studeez.common.composable.DrawerScreenTemplate
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.R.string as AppText
@Composable
fun SettingsRoute(
// viewModel: SettingsViewModel,
drawerActions: DrawerActions
) {
SettingsScreen(
drawerActions = drawerActions
)
}
@Composable
fun SettingsScreen(
drawerActions: DrawerActions
) {
DrawerScreenTemplate(
title = resources().getString(AppText.settings),
drawerActions = drawerActions
) {
Text(
text = resources().getString(AppText.settings_temp_description),
modifier = Modifier.fillMaxSize(),
textAlign = TextAlign.Center
)
}
}

View file

@ -42,12 +42,16 @@ abstract class AbstractTimerEditScreen(private val timerInfo: TimerInfo) {
onNewValue = { name = it },
label = R.string.name
)
LabelledInputField(
value = description,
onNewValue = { description = it },
label = R.string.description,
singleLine = false
)
repeat(20) {
LabelledInputField(
value = description,
onNewValue = { description = it },
label = R.string.description,
singleLine = false
)
}
ExtraFields()

View file

@ -16,6 +16,7 @@ import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
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.navigation.StudeezDestinations
import be.ugent.sel.studeez.resources
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
@ -24,6 +25,7 @@ data class TimerOverviewActions(
val getUserTimers: () -> Flow<List<TimerInfo>>,
val getDefaultTimers: () -> List<TimerInfo>,
val onEditClick: (TimerInfo) -> Unit,
val onAddClick: () -> Unit,
)
fun getTimerOverviewActions(
@ -34,6 +36,7 @@ fun getTimerOverviewActions(
getUserTimers = viewModel::getUserTimers,
getDefaultTimers = viewModel::getDefaultTimers,
onEditClick = { viewModel.update(it, open) },
onAddClick = { viewModel.create(open) }
)
}
@ -61,8 +64,16 @@ fun TimerOverviewScreen(
title = resources().getString(R.string.timers),
drawerActions = drawerActions
) {
Column {
Column { // TODO knop beneden
LazyColumn {
// Custom timer, select new duration each time
item {
TimerEntry(timerInfo = CustomTimerInfo(
name = resources().getString(R.string.custom_name),
description = resources().getString(R.string.custom_name),
studyTime = 0
))
}
// Default Timers, cannot be edited
items(timerOverviewActions.getDefaultTimers()) {
TimerEntry(timerInfo = it) {}
@ -79,9 +90,13 @@ fun TimerOverviewScreen(
}
}
}
BasicButton(R.string.add_timer, Modifier.basicButton()) {
// TODO
// TODO uit lazy column
item {
BasicButton(R.string.add_timer, Modifier.basicButton()) {
timerOverviewActions.onAddClick()
}
}
}
}
}
@ -97,7 +112,9 @@ fun TimerOverviewPreview() {
timerOverviewActions = TimerOverviewActions(
{ flowOf() },
{ listOf(customTimer, customTimer) },
{}),
{},
{}
),
drawerActions = DrawerActions({}, {}, {}, {}, {})
)
}

View file

@ -32,6 +32,10 @@ class TimerOverviewViewModel @Inject constructor(
open(StudeezDestinations.TIMER_EDIT_SCREEN)
}
fun create(open: (String) -> Unit) {
open(StudeezDestinations.ADD_TIMER_SCREEN)
}
fun delete(timerInfo: TimerInfo) =timerDAO.deleteTimer(timerInfo)
fun save(timerInfo: TimerInfo) = timerDAO.saveTimer(timerInfo)

View file

@ -0,0 +1,12 @@
package be.ugent.sel.studeez.screens.timer_overview.add_timer
data class AddTimerUiState(
val studyTimeHours: Int = 1,
val studyTimeMinutes: Int = 0,
val withBreaks: Boolean = false,
val breakTimeMinutes: Int = 5,
val breakTimeHours: Int = 0,
val repeats: Int = 1,
val name: String = "Timer",
val description: String = "Long study session",
)

View file

@ -0,0 +1,91 @@
package be.ugent.sel.studeez.screens.timer_overview.add_timer
import androidx.compose.runtime.mutableStateOf
import be.ugent.sel.studeez.data.local.models.timer_info.CustomTimerInfo
import be.ugent.sel.studeez.data.local.models.timer_info.PomodoroTimerInfo
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.domain.TimerDAO
import be.ugent.sel.studeez.screens.StudeezViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class AddTimerViewModel @Inject constructor(
logService: LogService,
private val timerDAO: TimerDAO,
): StudeezViewModel(logService) {
var uiState = mutableStateOf(AddTimerUiState())
private set
private val studyTimeHours
get() = uiState.value.studyTimeHours
private val studyTimeMinutes
get() = uiState.value.studyTimeMinutes
private val breakTimeHours
get() = uiState.value.breakTimeHours
private val breakTimeMinutes
get() = uiState.value.breakTimeMinutes
private val repeats
get() = uiState.value.repeats
private val name
get() = uiState.value.name
private val description
get() = uiState.value.description
fun onStudyTimeHoursChange(newValue: Int) {
uiState.value = uiState.value.copy(studyTimeHours = newValue)
}
fun onStudyTimeMinutesChange(newValue: Int) {
uiState.value = uiState.value.copy(studyTimeMinutes = newValue)
}
fun onWithBreaksChange() {
uiState.value = uiState.value.copy(withBreaks = !uiState.value.withBreaks)
}
fun onBreakTimeHourChange(newValue: Int) {
uiState.value = uiState.value.copy(breakTimeHours = newValue)
}
fun onBreakTimeMinutesChange(newValue: Int) {
uiState.value = uiState.value.copy(breakTimeMinutes = newValue)
}
fun onRepeatsChange(newValue: Int) {
uiState.value = uiState.value.copy(repeats = newValue)
}
fun addTimer() {
if (uiState.value.withBreaks) {
timerDAO.saveTimer(PomodoroTimerInfo(
name = uiState.value.name,
description = uiState.value.description,
studyTime = studyTimeHours * 60 * 60 + studyTimeMinutes * 60,
breakTime = breakTimeHours * 60 * 60 + breakTimeMinutes * 60,
repeats = repeats
))
} else {
timerDAO.saveTimer(CustomTimerInfo(
name = uiState.value.name,
description = uiState.value.description,
studyTime = studyTimeHours * 60 * 60 + studyTimeMinutes * 60
))
}
}
fun onNameChange(newValue: String) {
uiState.value = uiState.value.copy(name = newValue)
}
fun onDescriptionChange(newValue: String) {
uiState.value = uiState.value.copy(description = newValue)
}
}

View file

@ -0,0 +1,274 @@
package be.ugent.sel.studeez.screens.timer_overview.add_timer
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Button
import androidx.compose.material.Checkbox
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
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.R
import be.ugent.sel.studeez.common.composable.BasicButton
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
import be.ugent.sel.studeez.common.composable.navbar.BasicTimePicker
import be.ugent.sel.studeez.navigation.StudeezDestinations
import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.ui.theme.StudeezTheme
data class AddTimerActions(
val open: (String) -> Unit,
val goBack: () -> Unit,
val onStudyTimeHoursChange: (Int) -> Unit,
val onStudyTimeMinutesChange: (Int) -> Unit,
val onBreakTimeHourChange: (Int) -> Unit,
val onBreakTimeMinutesChange: (Int) -> Unit,
val onRepeatsChange: (Int) -> Unit,
val onWithBreaksChange: () -> Unit,
val addTimer: () -> Unit,
val onNameChange: (String) -> Unit,
val onDescriptionChange: (String) -> Unit,
)
fun getAddTimerActions(
open: (String) -> Unit,
goBack: () -> Unit,
viewModel: AddTimerViewModel,
): AddTimerActions {
return AddTimerActions(
open = open,
goBack = goBack,
onWithBreaksChange = viewModel::onWithBreaksChange,
onStudyTimeHoursChange = viewModel::onStudyTimeHoursChange,
onStudyTimeMinutesChange = viewModel::onStudyTimeMinutesChange,
onBreakTimeHourChange = viewModel::onBreakTimeHourChange,
onBreakTimeMinutesChange = viewModel::onBreakTimeMinutesChange,
onRepeatsChange = viewModel::onRepeatsChange,
addTimer = viewModel::addTimer,
onNameChange = viewModel::onNameChange,
onDescriptionChange = viewModel::onDescriptionChange
)
}
@Composable
fun AddTimerRoute(
open: (String) -> Unit,
goBack: () -> Unit,
viewModel: AddTimerViewModel,
) {
val uiState by viewModel.uiState
AddTimerScreen(
addTimerActions = getAddTimerActions(
open = open,
goBack = goBack,
viewModel = viewModel,
),
uiState = uiState
)
}
@Composable
fun AddTimerScreen(
addTimerActions: AddTimerActions,
uiState: AddTimerUiState,
) {
val mStudyTimePicker = BasicTimePicker(
onHoursChange = addTimerActions.onStudyTimeHoursChange,
onMinutesChange = addTimerActions.onStudyTimeMinutesChange,
Hours = uiState.studyTimeHours,
Minutes = uiState.studyTimeMinutes
)
val mBreakTimePicker = BasicTimePicker(
onHoursChange = addTimerActions.onBreakTimeHourChange,
onMinutesChange = addTimerActions.onBreakTimeMinutesChange,
Hours = uiState.breakTimeHours,
Minutes = uiState.breakTimeMinutes
)
SecondaryScreenTemplate(
title = resources().getString(R.string.add_timer),
popUp = addTimerActions.goBack
) {
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
item {
Row(
modifier = Modifier
.padding(16.dp)
) {
Text(
text = stringResource(R.string.addTimer_question),
textAlign = TextAlign.Center
)
}
}
item {
Text(
text = uiState.studyTimeHours.toString() + stringResource(R.string.addTimer_studytime_1) + uiState.studyTimeMinutes + stringResource(
R.string.addTimer_studytime_2)
)
}
item {
Button(
onClick = {
mStudyTimePicker.show()
},
) {
Text(
text = stringResource(R.string.addTimer_timepicker),
)
}
}
item {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Text(
text = stringResource(R.string.addTimer_break_question),
)
Checkbox(
checked = uiState.withBreaks,
onCheckedChange = { addTimerActions.onWithBreaksChange() }
)
}
}
if (uiState.withBreaks) {
item {
Text(
text = if (uiState.repeats == 1) uiState.repeats.toString() + stringResource(
R.string.addTimer_break_1)
else uiState.repeats.toString() + stringResource(
R.string.addTimer_break_s)
)
TextField(
value = uiState.repeats.toString(),
onValueChange = { it: String ->
it.toIntOrNull()?.let { it1 ->
addTimerActions.onRepeatsChange(
kotlin.math.abs(it1)
)
}
}
)
}
item {
Text(
text = uiState.breakTimeHours.toString() + stringResource(R.string.breakTime_1) + uiState.breakTimeMinutes + stringResource(
R.string.breakTime_2)
)
}
item {
Button(
onClick = {
mBreakTimePicker.show()
},
) {
Text(
text = stringResource(R.string.addTimer_timepicker),
)
}
}
}
item {
Text(
text = stringResource(R.string.addTimer_name)
)
}
item {
TextField(
value = uiState.name,
onValueChange = { addTimerActions.onNameChange(it) }
)
}
item {
if (uiState.name == "") {
Text(
text = stringResource(R.string.addTimer_name_error),
color = Color.Red
)
}
}
item {
Text(
text = stringResource(R.string.addTimer_description)
)
}
item {
TextField(
value = uiState.description,
onValueChange = { addTimerActions.onDescriptionChange(it) }
)
}
item {
if (uiState.description == "") {
Text(
text = stringResource(R.string.addTimer_description_error),
color = Color.Red
)
}
}
item {
Row(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.Center
) {
BasicButton(
text = R.string.add_timer,
modifier = Modifier,
onClick = {
if (uiState.description != "" && uiState.name != "") {
addTimerActions.addTimer()
addTimerActions.open(StudeezDestinations.TIMER_SCREEN)
}
}
)
}
}
}
}
}
@Preview
@Composable
fun AddTimerScreenPreview() { StudeezTheme {
AddTimerScreen(
addTimerActions = AddTimerActions({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}),
uiState = AddTimerUiState()
)
}
}

View file

@ -8,7 +8,11 @@ import androidx.compose.ui.tooling.preview.Preview
import be.ugent.sel.studeez.R
import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate
import be.ugent.sel.studeez.common.composable.StealthButton
import be.ugent.sel.studeez.common.composable.TimePickerButton
import be.ugent.sel.studeez.common.composable.TimerEntry
import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds
import be.ugent.sel.studeez.data.local.models.timer_functional.Time
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
@ -17,6 +21,7 @@ import kotlinx.coroutines.flow.flowOf
data class TimerSelectionActions(
val getAllTimers: () -> Flow<List<TimerInfo>>,
val startSession: (TimerInfo) -> Unit,
val customTimeStudyTime: Int
)
fun getTimerSelectionActions(
@ -26,6 +31,7 @@ fun getTimerSelectionActions(
return TimerSelectionActions(
getAllTimers = viewModel::getAllTimers,
startSession = { viewModel.startSession(open, it) },
customTimeStudyTime = viewModel.customTimerStudyTime.value
)
}
@ -52,6 +58,11 @@ fun TimerSelectionScreen(
popUp = popUp
) {
LazyColumn {
// Custom timer with duration selection button
item {
CustomTimerEntry(timerSelectionActions)
}
// All timers
items(timers.value) { timerInfo ->
TimerEntry(
@ -68,11 +79,38 @@ fun TimerSelectionScreen(
}
}
@Composable
fun CustomTimerEntry(
timerSelectionActions: TimerSelectionActions
) {
val timerInfo = CustomTimerInfo(
name = resources().getString(R.string.custom_name),
description = resources().getString(R.string.custom_description),
studyTime = timerSelectionActions.customTimeStudyTime
)
val hms: HoursMinutesSeconds = Time(timerInfo.studyTime).getAsHMS()
TimerEntry(
timerInfo = timerInfo,
leftButton = {
StealthButton(
text = R.string.start,
onClick = { timerSelectionActions.startSession(timerInfo) }
)
},
rightButton = {
TimePickerButton(initialSeconds = hms.getTotalSeconds()) { chosenTime ->
timerInfo.studyTime = chosenTime
}
}
)
}
@Preview
@Composable
fun TimerSelectionPreview() {
TimerSelectionScreen(
timerSelectionActions = TimerSelectionActions({ flowOf() }, {}),
timerSelectionActions = TimerSelectionActions({ flowOf() }, {}, 0),
popUp = {}
)
}

View file

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

View file

@ -12,7 +12,9 @@ import androidx.compose.ui.graphics.Color
private val DarkColorPalette = darkColors(
primary = Blue100,
primaryVariant = Blue120,
secondary = Yellow100
secondary = Yellow100,
onPrimary = Color.White
)
private val LightColorPalette = lightColors(

View file

@ -1,5 +1,6 @@
<resources>
<!-- Common -->
<!-- ========== Common ========== -->
<string name="app_name">Studeez</string>
<string name="username">Username</string>
<string name="email">Email</string>
@ -7,20 +8,75 @@
<string name="repeat_password">Repeat password</string>
<string name="menu">Menu</string>
<!-- 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>
<string name="start">Start</string>
<!-- 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>
<string name="start">Start</string>
<!-- Messages -->
<string name="success">Success!</string>
<string name="try_again">Try again</string>
<string name="generic_error">Something wrong happened. Please try again.</string>
<string name="email_error">Please insert a valid email.</string>
<!-- Messages -->
<string name="success">Success!</string>
<string name="try_again">Try again</string>
<string name="generic_error">Something wrong happened. Please try again.</string>
<string name="email_error">Please insert a valid email.</string>
<!-- ========== NavBar ========== -->
<!-- HomeScreen -->
<string name="home">Home</string>
<string name="start_session">Start session</string>
<!-- Tasks -->
<string name="tasks">Tasks</string>
<string name="task">Task</string>
<!-- Sessions -->
<string name="sessions_temp_description">Looks like you found the sessions screen! In here, your upcoming studying sessions with friends will be listed. You can accept invites or edit your own.</string> <!-- TODO Remove this description line once implemented. -->
<string name="sessions">Sessions</string>
<string name="session">Session</string>
<string name="end_session">End session</string>
<string name="upcoming_sessions">Upcoming sessions</string>
<!-- Profile -->
<string name="profile">Profile</string>
<string name="no_username">Unknown username</string>
<string name="edit_profile">Edit profile</string>
<string name="editing_profile">Editing profile</string>
<string name="delete_profile">Delete profile</string>
<!-- ========== Drawer ========== -->
<string name="log_out">Log out</string>
<string name="profile_picture_description">Profile Picture</string>
<string name="user_description">Normal user</string>
<!-- Timers -->
<string name="timers">Timers</string>
<string name="edit">Edit</string>
<string name="add_timer">Add timer</string>
<string name="pick_time">Select time</string>
<string name="state_focus">Focus!</string>
<plurals name="state_focus_remaining">
<item quantity="zero">Focus one more time!</item>
<item quantity="one">Focus! (%d break remaining)</item>
<item quantity="other">Focus! (%d breaks remaining)</item>
</plurals>
<string name="state_done">Done!</string>
<string name="state_take_a_break">Take a break!</string>
<string name="custom_name">Custom</string>
<string name="custom_description">Select how long you want to study</string>
<!-- Settings -->
<string name="settings_temp_description">Looks like you found the settings screen! In the future, this will enable you to edit your preferenes such as light/dark mode, end sessions automatically when we detect you are gone etc.</string> <!-- TODO Remove this description line once implemented. -->
<string name="settings">Settings</string>
<!-- About -->
<string name="about">About Studeez</string>
<!-- ========== Login flow ========== -->
<!-- SignUpScreen -->
<string name="create_account">Create account</string>
@ -36,57 +92,42 @@
<string name="recovery_email_sent">Check your inbox for the recovery email.</string>
<string name="empty_password_error">Password cannot be empty.</string>
<!-- HomeScreen -->
<string name="home">Home</string>
<string name="start_session">Start session</string>
<!-- ========== Studying flow ========== -->
<!-- Tasks -->
<string name="tasks">Tasks</string>
<!-- ========== Friends flow ========== -->
<!-- Sessions -->
<string name="sessions">Sessions</string>
<string name="end_session">End session</string>
<!-- Profile -->
<string name="profile">Profile</string>
<string name="no_username">Unknown username</string>
<string name="edit_profile">Edit profile</string>
<string name="editing_profile">Editing profile</string>
<string name="delete_profile">Delete profile</string>
<!-- Friends -->
<string name="friends">Friends</string>
<string name="friend">Friend</string>
<string name="add_friend_not_possible_yet">Adding friends still needs to be implemented. Hang on tight!</string> <!-- TODO Remove this description line once implemented. -->
<!-- Drawer / SideMenu -->
<string name="log_out">Log out</string>
<string name="profile_picture_description">Profile Picture</string>
<string name="user_description">Normal user</string>
<!-- ========== Create & edit screens ========== -->
<!-- Timers -->
<string name="timers">Timers</string>
<string name="edit">Edit</string>
<string name="add_timer">Add timer</string>
<string name="state_focus">Focus!</string>
<plurals name="state_focus_remaining">
<item quantity="zero">Focus one more time!</item>
<item quantity="one">Focus! (%d break remaining)</item>
<item quantity="other">Focus! (%d breaks remaining)</item>
</plurals>
<string name="state_done">Done!</string>
<string name="state_take_a_break">Take a break!</string>
<!-- Task -->
<string name="create_task_not_possible_yet">Creating tasks still needs to be implemented. Hang on tight!</string> <!-- TODO Remove this description line once implemented. -->
<!-- Edit Timer-->
<!-- Session -->
<string name="create_session_not_possible_yet">Creating sessions still needs to be implemented. Hang on tight!</string> <!-- TODO Remove this description line once implemented. -->
<!-- Add Timer -->
<string name="addTimer_description_error">Timer description cannot be empty!</string>
<string name="addTimer_description">Timer description</string>
<string name="addTimer_name_error">Timer name cannot be empty!</string>
<string name="addTimer_name">Timer name</string>
<string name="addTimer_timepicker">Open Time Picker</string>
<string name="breakTime_1">" hours and "</string>
<string name="breakTime_2">" minutes of breaktime"</string>
<string name="addTimer_break_1">" break"</string>
<string name="addTimer_break_s">" breaks"</string>
<string name="addTimer_break_question">With breaks?</string>
<string name="addTimer_studytime_1">" hours and "</string>
<string name="addTimer_studytime_2">" minutes of studytime"</string>
<string name="addTimer_question">How long do you want to study?</string>
<!-- Edit Timer-->
<string name="name">Name</string>
<string name="description">Description</string>
<string name="studyTime">Study Time</string>
<string name="breakTime">Break Time</string>
<string name="repeats">Number of Repeats</string>
<!-- Settings -->
<string name="settings">Settings</string>
<!-- About -->
<string name="about">About Studeez</string>
</resources>

View file

@ -2,6 +2,7 @@ package be.ugent.sel.studeez.timer_functional
import android.media.MediaPlayer
import be.ugent.sel.studeez.data.SelectedTimerState
import be.ugent.sel.studeez.data.SessionReportState
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalCustomTimer
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalEndlessTimer
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer
@ -24,7 +25,7 @@ class InvisibleSessionManagerTest {
@Test
fun InvisibleEndlessTimerTest() = runTest {
timerState.selectedTimer = FunctionalEndlessTimer()
viewModel = SessionViewModel(timerState, mock())
viewModel = SessionViewModel(timerState, SessionReportState(), mock())
InvisibleSessionManager.setParameters(viewModel, mediaPlayer)
val test = launch {
@ -46,7 +47,7 @@ class InvisibleSessionManagerTest {
val breakTime = 5
val repeats = 1
timerState.selectedTimer = FunctionalPomodoroTimer(studyTime, breakTime, repeats)
viewModel = SessionViewModel(timerState, mock())
viewModel = SessionViewModel(timerState, SessionReportState(), mock())
InvisibleSessionManager.setParameters(viewModel, mediaPlayer)
val test = launch {
@ -79,7 +80,7 @@ class InvisibleSessionManagerTest {
@Test
fun InvisibleCustomTimerTest() = runTest {
timerState.selectedTimer = FunctionalCustomTimer(5)
viewModel = SessionViewModel(timerState, mock())
viewModel = SessionViewModel(timerState, SessionReportState(), mock())
InvisibleSessionManager.setParameters(viewModel, mediaPlayer)
val test = launch {