optimize imports and format code for all files :)
This commit is contained in:
parent
cefa85ae22
commit
62bca72d0f
56 changed files with 310 additions and 239 deletions
|
@ -75,7 +75,7 @@ fun StealthButton(
|
||||||
) {
|
) {
|
||||||
//val clickablemodifier = if (disabled) Modifier.clickable(indication = null) else modifier
|
//val clickablemodifier = if (disabled) Modifier.clickable(indication = null) else modifier
|
||||||
val borderColor = if (enabled) MaterialTheme.colors.primary
|
val borderColor = if (enabled) MaterialTheme.colors.primary
|
||||||
else MaterialTheme.colors.onSurface.copy(alpha = 0.3f)
|
else MaterialTheme.colors.onSurface.copy(alpha = 0.3f)
|
||||||
BasicButton(
|
BasicButton(
|
||||||
text = text,
|
text = text,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
|
|
@ -29,20 +29,22 @@ fun DrawerScreenTemplate(
|
||||||
Scaffold(
|
Scaffold(
|
||||||
scaffoldState = scaffoldState,
|
scaffoldState = scaffoldState,
|
||||||
|
|
||||||
topBar = { TopAppBar(
|
topBar = {
|
||||||
title = { Text(text = title) },
|
TopAppBar(
|
||||||
navigationIcon = {
|
title = { Text(text = title) },
|
||||||
IconButton(onClick = {
|
navigationIcon = {
|
||||||
coroutineScope.launch { scaffoldState.drawerState.open() }
|
IconButton(onClick = {
|
||||||
}) {
|
coroutineScope.launch { scaffoldState.drawerState.open() }
|
||||||
Icon(
|
}) {
|
||||||
imageVector = Icons.Default.Menu,
|
Icon(
|
||||||
contentDescription = resources().getString(AppText.menu)
|
imageVector = Icons.Default.Menu,
|
||||||
)
|
contentDescription = resources().getString(AppText.menu)
|
||||||
}
|
)
|
||||||
},
|
}
|
||||||
actions = barAction
|
},
|
||||||
)},
|
actions = barAction
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
drawerContent = {
|
drawerContent = {
|
||||||
Drawer(drawerActions)
|
Drawer(drawerActions)
|
||||||
|
@ -55,10 +57,12 @@ fun DrawerScreenTemplate(
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun DrawerScreenPreview() {
|
fun DrawerScreenPreview() {
|
||||||
StudeezTheme { DrawerScreenTemplate(
|
StudeezTheme {
|
||||||
title = "Drawer screen preview",
|
DrawerScreenTemplate(
|
||||||
drawerActions =DrawerActions({}, {}, {}, {}, {})
|
title = "Drawer screen preview",
|
||||||
) {
|
drawerActions = DrawerActions({}, {}, {}, {}, {})
|
||||||
Text(text = "Preview content")
|
) {
|
||||||
} }
|
Text(text = "Preview content")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -131,15 +131,19 @@ fun ExpandedEntry(
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun AddButtonPreview() {
|
fun AddButtonPreview() {
|
||||||
StudeezTheme { AddButton(
|
StudeezTheme {
|
||||||
addButtonActions = AddButtonActions({}, {}, {})
|
AddButton(
|
||||||
)}
|
addButtonActions = AddButtonActions({}, {}, {})
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun ExpandedAddButtonPreview() {
|
fun ExpandedAddButtonPreview() {
|
||||||
StudeezTheme { ExpandedAddButton (
|
StudeezTheme {
|
||||||
addButtonActions = AddButtonActions({}, {}, {})
|
ExpandedAddButton(
|
||||||
) }
|
addButtonActions = AddButtonActions({}, {}, {})
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -57,11 +57,15 @@ fun PrimaryScreenTemplate(
|
||||||
bottomBar = { NavigationBar(navigationBarActions) },
|
bottomBar = { NavigationBar(navigationBarActions) },
|
||||||
floatingActionButtonPosition = FabPosition.Center,
|
floatingActionButtonPosition = FabPosition.Center,
|
||||||
isFloatingActionButtonDocked = true,
|
isFloatingActionButtonDocked = true,
|
||||||
floatingActionButton = { AddButton(AddButtonActions(
|
floatingActionButton = {
|
||||||
onTaskClick = navigationBarActions.onAddTaskClick,
|
AddButton(
|
||||||
onFriendClick = navigationBarActions.onAddFriendClick,
|
AddButtonActions(
|
||||||
onSessionClick = navigationBarActions.onAddSessionClick
|
onTaskClick = navigationBarActions.onAddTaskClick,
|
||||||
)) }
|
onFriendClick = navigationBarActions.onAddFriendClick,
|
||||||
|
onSessionClick = navigationBarActions.onAddSessionClick
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
content(it)
|
content(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,18 +21,20 @@ fun SecondaryScreenTemplate(
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
// Everything at the top of the screen
|
// Everything at the top of the screen
|
||||||
topBar = { TopAppBar(
|
topBar = {
|
||||||
title = { Text(text = title) },
|
TopAppBar(
|
||||||
navigationIcon = {
|
title = { Text(text = title) },
|
||||||
IconButton(onClick = { popUp() }) {
|
navigationIcon = {
|
||||||
Icon(
|
IconButton(onClick = { popUp() }) {
|
||||||
imageVector = Icons.Default.ArrowBack,
|
Icon(
|
||||||
contentDescription = resources().getString(R.string.go_back)
|
imageVector = Icons.Default.ArrowBack,
|
||||||
)
|
contentDescription = resources().getString(R.string.go_back)
|
||||||
}
|
)
|
||||||
},
|
}
|
||||||
actions = barAction
|
},
|
||||||
) },
|
actions = barAction
|
||||||
|
)
|
||||||
|
},
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
content(paddingValues)
|
content(paddingValues)
|
||||||
}
|
}
|
||||||
|
@ -41,8 +43,10 @@ fun SecondaryScreenTemplate(
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun SecondaryScreenToolbarPreview() {
|
fun SecondaryScreenToolbarPreview() {
|
||||||
StudeezTheme { SecondaryScreenTemplate(
|
StudeezTheme {
|
||||||
"Preview screen",
|
SecondaryScreenTemplate(
|
||||||
{}
|
"Preview screen",
|
||||||
) {} }
|
{}
|
||||||
|
) {}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -11,6 +11,6 @@ fun SimpleScreenTemplate(
|
||||||
title: String,
|
title: String,
|
||||||
content: @Composable (PaddingValues) -> Unit
|
content: @Composable (PaddingValues) -> Unit
|
||||||
) {
|
) {
|
||||||
Scaffold( topBar = { TopAppBar ( title = { Text(text = title) } ) }
|
Scaffold(topBar = { TopAppBar(title = { Text(text = title) }) }
|
||||||
) { paddingValues -> content(paddingValues) }
|
) { paddingValues -> content(paddingValues) }
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ import androidx.compose.ui.unit.sp
|
||||||
fun Headline(
|
fun Headline(
|
||||||
text: String
|
text: String
|
||||||
) {
|
) {
|
||||||
Row (
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.Center
|
horizontalArrangement = Arrangement.Center
|
||||||
|
|
|
@ -102,7 +102,7 @@ fun LabeledNumberInputField(
|
||||||
singleLine = singleLine,
|
singleLine = singleLine,
|
||||||
label = { Text(resources().getString(label)) },
|
label = { Text(resources().getString(label)) },
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
onValueChange = {typedInt ->
|
onValueChange = { typedInt ->
|
||||||
val isNumber = typedInt.matches(Regex("[1-9]+\\d*]"))
|
val isNumber = typedInt.matches(Regex("[1-9]+\\d*]"))
|
||||||
if (isNumber) {
|
if (isNumber) {
|
||||||
number = typedInt.toInt()
|
number = typedInt.toInt()
|
||||||
|
@ -161,12 +161,11 @@ fun LabeledErrorTextField(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
@Preview(showBackground = true)
|
@Composable
|
||||||
@Composable
|
fun IntInputPreview() {
|
||||||
fun IntInputPreview() {
|
LabeledNumberInputField(value = 1, onNewValue = {}, label = AppText.email)
|
||||||
LabeledNumberInputField(value = 1, onNewValue = {}, label = AppText.email)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PasswordField(
|
fun PasswordField(
|
||||||
|
|
|
@ -82,7 +82,11 @@ fun TimePickerButton(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pickDuration(context: Context, onTimeChosen: (Int) -> Unit, timeState: MutableState<Int>) {
|
private fun pickDuration(
|
||||||
|
context: Context,
|
||||||
|
onTimeChosen: (Int) -> Unit,
|
||||||
|
timeState: MutableState<Int>
|
||||||
|
) {
|
||||||
val listener = OnTimeSetListener { _, hour, minute ->
|
val listener = OnTimeSetListener { _, hour, minute ->
|
||||||
timeState.value = HoursMinutesSeconds(hour, minute, 0).getTotalSeconds()
|
timeState.value = HoursMinutesSeconds(hour, minute, 0).getTotalSeconds()
|
||||||
onTimeChosen(timeState.value)
|
onTimeChosen(timeState.value)
|
||||||
|
|
|
@ -2,12 +2,7 @@ package be.ugent.sel.studeez.common.composable.drawer
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.*
|
||||||
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.Icon
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
|
|
@ -3,8 +3,6 @@ package be.ugent.sel.studeez.common.composable.drawer
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
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.AccountDAO
|
||||||
import be.ugent.sel.studeez.domain.LogService
|
import be.ugent.sel.studeez.domain.LogService
|
||||||
import be.ugent.sel.studeez.navigation.StudeezDestinations
|
import be.ugent.sel.studeez.navigation.StudeezDestinations
|
||||||
|
|
|
@ -8,8 +8,6 @@ import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Check
|
import androidx.compose.material.icons.filled.Check
|
||||||
import androidx.compose.material.icons.filled.List
|
import androidx.compose.material.icons.filled.List
|
||||||
import androidx.compose.material.icons.filled.Person
|
import androidx.compose.material.icons.filled.Person
|
||||||
import androidx.compose.material.icons.outlined.Check
|
|
||||||
import androidx.compose.material.icons.outlined.DateRange
|
|
||||||
import androidx.compose.material.icons.outlined.Face
|
import androidx.compose.material.icons.outlined.Face
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
|
|
@ -6,11 +6,15 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
fun Modifier.textButton(): Modifier {
|
fun Modifier.textButton(): Modifier {
|
||||||
return this.fillMaxWidth().padding(16.dp, 8.dp, 16.dp, 0.dp)
|
return this
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp, 8.dp, 16.dp, 0.dp)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Modifier.basicButton(): Modifier {
|
fun Modifier.basicButton(): Modifier {
|
||||||
return this.fillMaxWidth().padding(16.dp, 8.dp)
|
return this
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp, 8.dp)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Modifier.card(): Modifier {
|
fun Modifier.card(): Modifier {
|
||||||
|
@ -26,7 +30,9 @@ fun Modifier.dropdownSelector(): Modifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Modifier.fieldModifier(): Modifier {
|
fun Modifier.fieldModifier(): Modifier {
|
||||||
return this.fillMaxWidth().padding(16.dp, 4.dp)
|
return this
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp, 4.dp)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Modifier.toolbarActions(): Modifier {
|
fun Modifier.toolbarActions(): Modifier {
|
||||||
|
@ -34,9 +40,13 @@ fun Modifier.toolbarActions(): Modifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Modifier.spacer(): Modifier {
|
fun Modifier.spacer(): Modifier {
|
||||||
return this.fillMaxWidth().padding(12.dp)
|
return this
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(12.dp)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Modifier.smallSpacer(): Modifier {
|
fun Modifier.smallSpacer(): Modifier {
|
||||||
return this.fillMaxWidth().height(8.dp)
|
return this
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(8.dp)
|
||||||
}
|
}
|
|
@ -48,6 +48,6 @@ class SelectedTimerInfo @Inject constructor() : SelectedState<TimerInfo>() {
|
||||||
@Singleton
|
@Singleton
|
||||||
class SelectedUserId @Inject constructor(
|
class SelectedUserId @Inject constructor(
|
||||||
userDAO: UserDAO
|
userDAO: UserDAO
|
||||||
): SelectedState<String>() {
|
) : SelectedState<String>() {
|
||||||
override var value: String = userDAO.getCurrentUserId()
|
override var value: String = userDAO.getCurrentUserId()
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ package be.ugent.sel.studeez.data.local.models.timer_functional
|
||||||
|
|
||||||
data class HoursMinutesSeconds(val hours: Int, val minutes: Int, val seconds: Int) {
|
data class HoursMinutesSeconds(val hours: Int, val minutes: Int, val seconds: Int) {
|
||||||
|
|
||||||
constructor(sec: Int): this(
|
constructor(sec: Int) : this(
|
||||||
hours = sec / (60 * 60),
|
hours = sec / (60 * 60),
|
||||||
minutes = (sec / (60)) % 60,
|
minutes = (sec / (60)) % 60,
|
||||||
seconds = sec % 60,
|
seconds = sec % 60,
|
||||||
|
|
|
@ -8,13 +8,13 @@ class CustomTimerInfo(
|
||||||
description: String,
|
description: String,
|
||||||
var studyTime: Int,
|
var studyTime: Int,
|
||||||
id: String = ""
|
id: String = ""
|
||||||
): TimerInfo(id, name, description) {
|
) : TimerInfo(id, name, description) {
|
||||||
|
|
||||||
override fun getFunctionalTimer(): FunctionalTimer {
|
override fun getFunctionalTimer(): FunctionalTimer {
|
||||||
return FunctionalCustomTimer(studyTime)
|
return FunctionalCustomTimer(studyTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun asJson() : Map<String, Any> {
|
override fun asJson(): Map<String, Any> {
|
||||||
return mapOf(
|
return mapOf(
|
||||||
"type" to "custom",
|
"type" to "custom",
|
||||||
"name" to name,
|
"name" to name,
|
||||||
|
|
|
@ -7,14 +7,14 @@ class EndlessTimerInfo(
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
id: String = ""
|
id: String = ""
|
||||||
): TimerInfo(id, name, description) {
|
) : TimerInfo(id, name, description) {
|
||||||
|
|
||||||
|
|
||||||
override fun getFunctionalTimer(): FunctionalTimer {
|
override fun getFunctionalTimer(): FunctionalTimer {
|
||||||
return FunctionalEndlessTimer()
|
return FunctionalEndlessTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun asJson() : Map<String, Any> {
|
override fun asJson(): Map<String, Any> {
|
||||||
return mapOf(
|
return mapOf(
|
||||||
"type" to "endless",
|
"type" to "endless",
|
||||||
"name" to name,
|
"name" to name,
|
||||||
|
|
|
@ -2,7 +2,6 @@ package be.ugent.sel.studeez.data.local.models.timer_info
|
||||||
|
|
||||||
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalPomodoroTimer
|
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
|
||||||
import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimerVisitor
|
|
||||||
|
|
||||||
class PomodoroTimerInfo(
|
class PomodoroTimerInfo(
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -11,14 +10,14 @@ class PomodoroTimerInfo(
|
||||||
var breakTime: Int,
|
var breakTime: Int,
|
||||||
var repeats: Int,
|
var repeats: Int,
|
||||||
id: String = ""
|
id: String = ""
|
||||||
): TimerInfo(id, name, description) {
|
) : TimerInfo(id, name, description) {
|
||||||
|
|
||||||
|
|
||||||
override fun getFunctionalTimer(): FunctionalTimer {
|
override fun getFunctionalTimer(): FunctionalTimer {
|
||||||
return FunctionalPomodoroTimer(studyTime, breakTime, repeats)
|
return FunctionalPomodoroTimer(studyTime, breakTime, repeats)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun asJson() : Map<String, Any> {
|
override fun asJson(): Map<String, Any> {
|
||||||
return mapOf(
|
return mapOf(
|
||||||
"type" to "break",
|
"type" to "break",
|
||||||
"name" to name,
|
"name" to name,
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package be.ugent.sel.studeez.domain
|
package be.ugent.sel.studeez.domain
|
||||||
|
|
||||||
import be.ugent.sel.studeez.data.local.models.FeedEntry
|
|
||||||
import be.ugent.sel.studeez.data.local.models.SessionReport
|
import be.ugent.sel.studeez.data.local.models.SessionReport
|
||||||
import be.ugent.sel.studeez.data.local.models.User
|
|
||||||
import be.ugent.sel.studeez.data.local.models.task.Task
|
|
||||||
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
|
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package be.ugent.sel.studeez.domain
|
package be.ugent.sel.studeez.domain
|
||||||
|
|
||||||
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
|
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
|
||||||
import be.ugent.sel.studeez.data.local.models.timer_info.TimerJson
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface TimerDAO {
|
interface TimerDAO {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package be.ugent.sel.studeez.domain.implementation
|
package be.ugent.sel.studeez.domain.implementation
|
||||||
|
|
||||||
import be.ugent.sel.studeez.data.local.models.timer_info.*
|
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
|
||||||
|
import be.ugent.sel.studeez.data.local.models.timer_info.TimerJson
|
||||||
import be.ugent.sel.studeez.domain.ConfigurationService
|
import be.ugent.sel.studeez.domain.ConfigurationService
|
||||||
import com.google.firebase.ktx.Firebase
|
import com.google.firebase.ktx.Firebase
|
||||||
import com.google.firebase.remoteconfig.ktx.get
|
import com.google.firebase.remoteconfig.ktx.get
|
||||||
import com.google.firebase.remoteconfig.ktx.remoteConfig
|
import com.google.firebase.remoteconfig.ktx.remoteConfig
|
||||||
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
|
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
|
||||||
import com.google.gson.Gson
|
|
||||||
import kotlinx.coroutines.tasks.await
|
import kotlinx.coroutines.tasks.await
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
|
@ -42,14 +42,14 @@ class FirebaseFeedDAO @Inject constructor(
|
||||||
*/
|
*/
|
||||||
override suspend fun getFeedEntriesFromUser(id: String): Map<String, List<FeedEntry>> {
|
override suspend fun getFeedEntriesFromUser(id: String): Map<String, List<FeedEntry>> {
|
||||||
return sessionDAO.getSessionsOfUser(id)
|
return sessionDAO.getSessionsOfUser(id)
|
||||||
.map { sessionReport -> sessionToFeedEntryFromUser(sessionReport, id) }
|
.map { sessionReport -> sessionToFeedEntryFromUser(sessionReport, id) }
|
||||||
.sortedByDescending { it.endTime }
|
.sortedByDescending { it.endTime }
|
||||||
.groupBy { getFormattedTime(it) }
|
.groupBy { getFormattedTime(it) }
|
||||||
.mapValues { (_, entries) ->
|
.mapValues { (_, entries) ->
|
||||||
entries
|
entries
|
||||||
.groupBy { it.taskId }
|
.groupBy { it.taskId }
|
||||||
.map { fuseFeedEntries(it.component2()) }
|
.map { fuseFeedEntries(it.component2()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFriendsSessions(): Flow<Map<String, List<Pair<String, FeedEntry>>>> {
|
override fun getFriendsSessions(): Flow<Map<String, List<Pair<String, FeedEntry>>>> {
|
||||||
|
@ -70,7 +70,7 @@ class FirebaseFeedDAO @Inject constructor(
|
||||||
val new: MutableMap<String, List<Pair<String, FeedEntry>>> = mutableMapOf()
|
val new: MutableMap<String, List<Pair<String, FeedEntry>>> = mutableMapOf()
|
||||||
for ((name, map) in l) {
|
for ((name, map) in l) {
|
||||||
for ((day, feedEntries: List<FeedEntry>) in map) {
|
for ((day, feedEntries: List<FeedEntry>) in map) {
|
||||||
new[day] = new.getOrDefault(day, listOf()) + feedEntries.map { Pair(name, it) }
|
new[day] = new.getOrDefault(day, listOf()) + feedEntries.map { Pair(name, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new
|
return new
|
||||||
|
@ -109,7 +109,11 @@ class FirebaseFeedDAO @Inject constructor(
|
||||||
return makeFeedEntry(sessionReport, subject, task)
|
return makeFeedEntry(sessionReport, subject, task)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makeFeedEntry(sessionReport: SessionReport, subject: Subject, task: Task): FeedEntry {
|
private fun makeFeedEntry(
|
||||||
|
sessionReport: SessionReport,
|
||||||
|
subject: Subject,
|
||||||
|
task: Task
|
||||||
|
): FeedEntry {
|
||||||
return FeedEntry(
|
return FeedEntry(
|
||||||
argb_color = subject.argb_color,
|
argb_color = subject.argb_color,
|
||||||
subJectName = subject.name,
|
subJectName = subject.name,
|
||||||
|
@ -125,7 +129,10 @@ class FirebaseFeedDAO @Inject constructor(
|
||||||
/**
|
/**
|
||||||
* Convert a sessionReport to a feedEntry. Fetch Task and Subject to get names
|
* Convert a sessionReport to a feedEntry. Fetch Task and Subject to get names
|
||||||
*/
|
*/
|
||||||
private suspend fun sessionToFeedEntryFromUser(sessionReport: SessionReport, id: String): FeedEntry {
|
private suspend fun sessionToFeedEntryFromUser(
|
||||||
|
sessionReport: SessionReport,
|
||||||
|
id: String
|
||||||
|
): FeedEntry {
|
||||||
val subjectId: String = sessionReport.subjectId
|
val subjectId: String = sessionReport.subjectId
|
||||||
val taskId: String = sessionReport.taskId
|
val taskId: String = sessionReport.taskId
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.tasks.await
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.resumeWithException
|
import kotlin.coroutines.resumeWithException
|
||||||
|
@ -27,7 +26,7 @@ import be.ugent.sel.studeez.R.string as AppText
|
||||||
class FirebaseFriendshipDAO @Inject constructor(
|
class FirebaseFriendshipDAO @Inject constructor(
|
||||||
private val firestore: FirebaseFirestore,
|
private val firestore: FirebaseFirestore,
|
||||||
private val auth: AccountDAO
|
private val auth: AccountDAO
|
||||||
): FriendshipDAO {
|
) : FriendshipDAO {
|
||||||
|
|
||||||
private fun currentUserDocument(): DocumentReference = firestore
|
private fun currentUserDocument(): DocumentReference = firestore
|
||||||
.collection(USER_COLLECTION)
|
.collection(USER_COLLECTION)
|
||||||
|
@ -89,21 +88,25 @@ class FirebaseFriendshipDAO @Inject constructor(
|
||||||
// Add entry to current user
|
// Add entry to current user
|
||||||
currentUserDocument()
|
currentUserDocument()
|
||||||
.collection(FRIENDS_COLLECTION)
|
.collection(FRIENDS_COLLECTION)
|
||||||
.add(mapOf(
|
.add(
|
||||||
FRIENDID to otherUserId,
|
mapOf(
|
||||||
ACCEPTED to true, // TODO Make it not automatically accepted.
|
FRIENDID to otherUserId,
|
||||||
FRIENDSSINCE to Timestamp.now()
|
ACCEPTED to true, // TODO Make it not automatically accepted.
|
||||||
))
|
FRIENDSSINCE to Timestamp.now()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
// Add entry to other user
|
// Add entry to other user
|
||||||
firestore.collection(USER_COLLECTION)
|
firestore.collection(USER_COLLECTION)
|
||||||
.document(otherUserId)
|
.document(otherUserId)
|
||||||
.collection(FRIENDS_COLLECTION)
|
.collection(FRIENDS_COLLECTION)
|
||||||
.add(mapOf(
|
.add(
|
||||||
FRIENDID to currentUserId,
|
mapOf(
|
||||||
ACCEPTED to true, // TODO Make it not automatically accepted.
|
FRIENDID to currentUserId,
|
||||||
FRIENDSSINCE to Timestamp.now()
|
ACCEPTED to true, // TODO Make it not automatically accepted.
|
||||||
))
|
FRIENDSSINCE to Timestamp.now()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}.addOnSuccessListener {
|
}.addOnSuccessListener {
|
||||||
val message = if (allowed) AppText.success else AppText.already_friend
|
val message = if (allowed) AppText.success else AppText.already_friend
|
||||||
|
|
|
@ -1,24 +1,15 @@
|
||||||
package be.ugent.sel.studeez.domain.implementation
|
package be.ugent.sel.studeez.domain.implementation
|
||||||
|
|
||||||
import be.ugent.sel.studeez.data.local.models.FeedEntry
|
|
||||||
import be.ugent.sel.studeez.data.local.models.SessionReport
|
import be.ugent.sel.studeez.data.local.models.SessionReport
|
||||||
import be.ugent.sel.studeez.data.local.models.User
|
|
||||||
import be.ugent.sel.studeez.data.local.models.task.Task
|
|
||||||
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
|
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
|
||||||
import be.ugent.sel.studeez.data.remote.FirebaseSessionReport
|
import be.ugent.sel.studeez.domain.AccountDAO
|
||||||
import be.ugent.sel.studeez.data.remote.FirebaseSessionReport.ENDTIME
|
import be.ugent.sel.studeez.domain.SessionDAO
|
||||||
import be.ugent.sel.studeez.data.remote.FirebaseSessionReport.STUDYTIME
|
|
||||||
import be.ugent.sel.studeez.domain.*
|
|
||||||
import be.ugent.sel.studeez.domain.implementation.FirebaseCollections.SESSION_COLLECTION
|
import be.ugent.sel.studeez.domain.implementation.FirebaseCollections.SESSION_COLLECTION
|
||||||
import be.ugent.sel.studeez.domain.implementation.FirebaseCollections.USER_COLLECTION
|
import be.ugent.sel.studeez.domain.implementation.FirebaseCollections.USER_COLLECTION
|
||||||
import com.google.firebase.Timestamp
|
|
||||||
import com.google.firebase.firestore.CollectionReference
|
import com.google.firebase.firestore.CollectionReference
|
||||||
import com.google.firebase.firestore.FirebaseFirestore
|
import com.google.firebase.firestore.FirebaseFirestore
|
||||||
import com.google.firebase.firestore.ktx.getField
|
|
||||||
import com.google.firebase.firestore.ktx.snapshots
|
import com.google.firebase.firestore.ktx.snapshots
|
||||||
import com.google.firebase.firestore.ktx.toObject
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.tasks.await
|
import kotlinx.coroutines.tasks.await
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
|
@ -82,7 +82,10 @@ class FirebaseSubjectDAO @Inject constructor(
|
||||||
.document(id)
|
.document(id)
|
||||||
.collection(FirebaseCollections.SUBJECT_COLLECTION)
|
.collection(FirebaseCollections.SUBJECT_COLLECTION)
|
||||||
|
|
||||||
private fun subjectTasksCollection(subject: Subject, id: String = auth.currentUserId): CollectionReference =
|
private fun subjectTasksCollection(
|
||||||
|
subject: Subject,
|
||||||
|
id: String = auth.currentUserId
|
||||||
|
): CollectionReference =
|
||||||
firestore.collection(FirebaseCollections.USER_COLLECTION)
|
firestore.collection(FirebaseCollections.USER_COLLECTION)
|
||||||
.document(id)
|
.document(id)
|
||||||
.collection(FirebaseCollections.SUBJECT_COLLECTION)
|
.collection(FirebaseCollections.SUBJECT_COLLECTION)
|
||||||
|
|
|
@ -51,7 +51,10 @@ class FirebaseTaskDAO @Inject constructor(
|
||||||
selectedSubjectTasksCollection(oldTask.subjectId).document(oldTask.id).delete()
|
selectedSubjectTasksCollection(oldTask.subjectId).document(oldTask.id).delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun selectedSubjectTasksCollection(subjectId: String, id: String = auth.currentUserId): CollectionReference =
|
private fun selectedSubjectTasksCollection(
|
||||||
|
subjectId: String,
|
||||||
|
id: String = auth.currentUserId
|
||||||
|
): CollectionReference =
|
||||||
firestore.collection(FirebaseCollections.USER_COLLECTION)
|
firestore.collection(FirebaseCollections.USER_COLLECTION)
|
||||||
.document(id)
|
.document(id)
|
||||||
.collection(FirebaseCollections.SUBJECT_COLLECTION)
|
.collection(FirebaseCollections.SUBJECT_COLLECTION)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package be.ugent.sel.studeez.domain.implementation
|
package be.ugent.sel.studeez.domain.implementation
|
||||||
|
|
||||||
import be.ugent.sel.studeez.data.local.models.timer_info.*
|
import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo
|
||||||
|
import be.ugent.sel.studeez.data.local.models.timer_info.TimerJson
|
||||||
import be.ugent.sel.studeez.domain.AccountDAO
|
import be.ugent.sel.studeez.domain.AccountDAO
|
||||||
import be.ugent.sel.studeez.domain.TimerDAO
|
import be.ugent.sel.studeez.domain.TimerDAO
|
||||||
import com.google.firebase.firestore.CollectionReference
|
import com.google.firebase.firestore.CollectionReference
|
||||||
|
@ -29,7 +30,7 @@ class FirebaseTimerDAO @Inject constructor(
|
||||||
// Wrap default timers in een flow en combineer met de userTimer flow.
|
// Wrap default timers in een flow en combineer met de userTimer flow.
|
||||||
val defaultTimers: List<TimerInfo> = configurationService.getDefaultTimers()
|
val defaultTimers: List<TimerInfo> = configurationService.getDefaultTimers()
|
||||||
val defaultTimersFlow: Flow<List<TimerInfo>> = flowOf(defaultTimers)
|
val defaultTimersFlow: Flow<List<TimerInfo>> = flowOf(defaultTimers)
|
||||||
val userTimersFlow: Flow<List<TimerInfo>> = getUserTimers()
|
val userTimersFlow: Flow<List<TimerInfo>> = getUserTimers()
|
||||||
return defaultTimersFlow.combine(userTimersFlow) { defaultTimersList, userTimersList ->
|
return defaultTimersFlow.combine(userTimersFlow) { defaultTimersList, userTimersList ->
|
||||||
defaultTimersList + userTimersList
|
defaultTimersList + userTimersList
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,10 +80,12 @@ class FirebaseUserDAO @Inject constructor(
|
||||||
newUsername: String,
|
newUsername: String,
|
||||||
newBiography: String
|
newBiography: String
|
||||||
) {
|
) {
|
||||||
currentUserDocument().set(mapOf(
|
currentUserDocument().set(
|
||||||
USERNAME to newUsername,
|
mapOf(
|
||||||
BIOGRAPHY to newBiography
|
USERNAME to newUsername,
|
||||||
))
|
BIOGRAPHY to newBiography
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteLoggedInUserReferences() {
|
override suspend fun deleteLoggedInUserReferences() {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package be.ugent.sel.studeez.domain.implementation
|
package be.ugent.sel.studeez.domain.implementation
|
||||||
|
|
||||||
import be.ugent.sel.studeez.data.local.models.timer_info.*
|
import be.ugent.sel.studeez.data.local.models.timer_info.*
|
||||||
|
import be.ugent.sel.studeez.domain.implementation.ToTimerConverter.TimerFactory
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
|
@ -15,32 +16,38 @@ import com.google.gson.reflect.TypeToken
|
||||||
class ToTimerConverter {
|
class ToTimerConverter {
|
||||||
|
|
||||||
fun interface TimerFactory {
|
fun interface TimerFactory {
|
||||||
fun makeTimer(map: TimerJson) : TimerInfo
|
fun makeTimer(map: TimerJson): TimerInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
private val timerInfoMap: Map<TimerType, TimerFactory> = mapOf(
|
private val timerInfoMap: Map<TimerType, TimerFactory> = mapOf(
|
||||||
TimerType.ENDLESS to TimerFactory { EndlessTimerInfo(
|
TimerType.ENDLESS to TimerFactory {
|
||||||
it.name,
|
EndlessTimerInfo(
|
||||||
it.description,
|
it.name,
|
||||||
it.id
|
it.description,
|
||||||
) },
|
it.id
|
||||||
TimerType.CUSTOM to TimerFactory { CustomTimerInfo(
|
)
|
||||||
it.name,
|
},
|
||||||
it.description,
|
TimerType.CUSTOM to TimerFactory {
|
||||||
it.studyTime,
|
CustomTimerInfo(
|
||||||
it.id
|
it.name,
|
||||||
) },
|
it.description,
|
||||||
TimerType.BREAK to TimerFactory { PomodoroTimerInfo(
|
it.studyTime,
|
||||||
it.name,
|
it.id
|
||||||
it.description,
|
)
|
||||||
it.studyTime,
|
},
|
||||||
it.breakTime,
|
TimerType.BREAK to TimerFactory {
|
||||||
it.repeats,
|
PomodoroTimerInfo(
|
||||||
it.id
|
it.name,
|
||||||
) }
|
it.description,
|
||||||
|
it.studyTime,
|
||||||
|
it.breakTime,
|
||||||
|
it.repeats,
|
||||||
|
it.id
|
||||||
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun getTimer(timerJson: TimerJson): TimerInfo{
|
private fun getTimer(timerJson: TimerJson): TimerInfo {
|
||||||
val type: TimerType = TimerType.valueOf(timerJson.type.uppercase())
|
val type: TimerType = TimerType.valueOf(timerJson.type.uppercase())
|
||||||
return timerInfoMap.getValue(type).makeTimer(timerJson)
|
return timerInfoMap.getValue(type).makeTimer(timerJson)
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,12 @@ fun StudeezNavGraph(
|
||||||
|
|
||||||
composable(StudeezDestinations.TASKS_SCREEN) {
|
composable(StudeezDestinations.TASKS_SCREEN) {
|
||||||
TaskRoute(
|
TaskRoute(
|
||||||
goBack = { openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.TASKS_SCREEN) },
|
goBack = {
|
||||||
|
openAndPopUp(
|
||||||
|
StudeezDestinations.SUBJECT_SCREEN,
|
||||||
|
StudeezDestinations.TASKS_SCREEN
|
||||||
|
)
|
||||||
|
},
|
||||||
open = open,
|
open = open,
|
||||||
viewModel = hiltViewModel(),
|
viewModel = hiltViewModel(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -95,24 +95,24 @@ fun FriendsOverviewScreen(
|
||||||
// label = AppText.search_friends,
|
// label = AppText.search_friends,
|
||||||
// enabled = false
|
// enabled = false
|
||||||
// )
|
// )
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = friendsOverviewActions.onSubmit,
|
onClick = friendsOverviewActions.onSubmit,
|
||||||
// modifier = Modifier.background(
|
// modifier = Modifier.background(
|
||||||
// color = MaterialTheme.colors.background
|
// color = MaterialTheme.colors.background
|
||||||
// ),
|
// ),
|
||||||
) {
|
) {
|
||||||
Row {
|
Row {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = AppText.click_search_friends),
|
text = stringResource(id = AppText.click_search_friends),
|
||||||
color = MaterialTheme.colors.onPrimary
|
color = MaterialTheme.colors.onPrimary
|
||||||
)
|
)
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.Search,
|
imageVector = Icons.Default.Search,
|
||||||
contentDescription = stringResource(AppText.search_friends),
|
contentDescription = stringResource(AppText.search_friends),
|
||||||
tint = MaterialTheme.colors.onPrimary
|
tint = MaterialTheme.colors.onPrimary
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = popUp) {
|
IconButton(onClick = popUp) {
|
||||||
|
@ -126,7 +126,7 @@ fun FriendsOverviewScreen(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
LazyColumn (
|
LazyColumn(
|
||||||
modifier = Modifier.padding(paddingValues)
|
modifier = Modifier.padding(paddingValues)
|
||||||
) {
|
) {
|
||||||
if (friends.value.isEmpty()) {
|
if (friends.value.isEmpty()) {
|
||||||
|
@ -180,7 +180,7 @@ fun FriendsEntry(
|
||||||
removeFriend: (Friendship) -> Unit
|
removeFriend: (Friendship) -> Unit
|
||||||
) {
|
) {
|
||||||
Card {
|
Card {
|
||||||
Row (
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 15.dp, vertical = 7.dp),
|
.padding(horizontal = 15.dp, vertical = 7.dp),
|
||||||
|
@ -193,11 +193,11 @@ fun FriendsEntry(
|
||||||
ProfilePicture()
|
ProfilePicture()
|
||||||
}
|
}
|
||||||
|
|
||||||
Box (
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Column (
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(vertical = 4.dp)
|
.padding(vertical = 4.dp)
|
||||||
) {
|
) {
|
||||||
|
@ -208,7 +208,11 @@ fun FriendsEntry(
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = "${resources().getString(AppText.app_name)} ${resources().getString(AppText.friend)}",
|
text = "${resources().getString(AppText.app_name)} ${
|
||||||
|
resources().getString(
|
||||||
|
AppText.friend
|
||||||
|
)
|
||||||
|
}",
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
|
|
|
@ -23,15 +23,17 @@ class FriendsOverviewViewModel @Inject constructor(
|
||||||
logService: LogService
|
logService: LogService
|
||||||
) : StudeezViewModel(logService) {
|
) : StudeezViewModel(logService) {
|
||||||
|
|
||||||
var uiState = mutableStateOf(FriendsOverviewUiState(
|
var uiState = mutableStateOf(
|
||||||
userId = selectedUserIdState.value
|
FriendsOverviewUiState(
|
||||||
))
|
userId = selectedUserIdState.value
|
||||||
|
)
|
||||||
|
)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun getAllFriends(): Flow<List<Pair<User, Friendship>>> {
|
fun getAllFriends(): Flow<List<Pair<User, Friendship>>> {
|
||||||
return friendshipDAO.getAllFriendships(
|
return friendshipDAO.getAllFriendships(
|
||||||
userId = uiState.value.userId
|
userId = uiState.value.userId
|
||||||
)
|
)
|
||||||
.flatMapConcat { friendships ->
|
.flatMapConcat { friendships ->
|
||||||
val userFlows = friendships.map { friendship ->
|
val userFlows = friendships.map { friendship ->
|
||||||
userDAO.getUserDetails(friendship.friendId)
|
userDAO.getUserDetails(friendship.friendId)
|
||||||
|
|
|
@ -105,7 +105,7 @@ fun SearchFriendsScreen(
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = Modifier.padding(paddingValues)
|
modifier = Modifier.padding(paddingValues)
|
||||||
) {
|
) {
|
||||||
items (searchResults.value) { user ->
|
items(searchResults.value) { user ->
|
||||||
UserEntry(
|
UserEntry(
|
||||||
user = user,
|
user = user,
|
||||||
goToProfile = searchFriendsActions.goToProfile
|
goToProfile = searchFriendsActions.goToProfile
|
||||||
|
@ -123,21 +123,29 @@ fun SearchFriendsPreview() {
|
||||||
popUp = {},
|
popUp = {},
|
||||||
uiState = SearchFriendUiState(
|
uiState = SearchFriendUiState(
|
||||||
queryString = "dit is een test",
|
queryString = "dit is een test",
|
||||||
searchResults = flowOf(listOf(User(
|
searchResults = flowOf(
|
||||||
id = "someid",
|
listOf(
|
||||||
username = "Eerste user",
|
User(
|
||||||
biography = "blah blah blah"
|
id = "someid",
|
||||||
)))
|
username = "Eerste user",
|
||||||
|
biography = "blah blah blah"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
searchFriendsActions = SearchFriendsActions(
|
searchFriendsActions = SearchFriendsActions(
|
||||||
onQueryStringChange = {},
|
onQueryStringChange = {},
|
||||||
getUsersWithUsername = {},
|
getUsersWithUsername = {},
|
||||||
getAllUsers = {
|
getAllUsers = {
|
||||||
flowOf(listOf(User(
|
flowOf(
|
||||||
id = "someid",
|
listOf(
|
||||||
username = "Eerste user",
|
User(
|
||||||
biography = "blah blah blah"
|
id = "someid",
|
||||||
)))
|
username = "Eerste user",
|
||||||
|
biography = "blah blah blah"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
},
|
},
|
||||||
goToProfile = { }
|
goToProfile = { }
|
||||||
)
|
)
|
||||||
|
@ -163,11 +171,11 @@ fun UserEntry(
|
||||||
ProfilePicture()
|
ProfilePicture()
|
||||||
}
|
}
|
||||||
|
|
||||||
Box (
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Column (
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(vertical = 4.dp)
|
.padding(vertical = 4.dp)
|
||||||
) {
|
) {
|
||||||
|
@ -178,7 +186,11 @@ fun UserEntry(
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = "${resources().getString(AppText.app_name)} ${resources().getString(AppText.friend)}",
|
text = "${resources().getString(AppText.app_name)} ${
|
||||||
|
resources().getString(
|
||||||
|
AppText.friend
|
||||||
|
)
|
||||||
|
}",
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis
|
overflow = TextOverflow.Ellipsis
|
||||||
|
|
|
@ -18,7 +18,7 @@ class SearchFriendsViewModel @Inject constructor(
|
||||||
private val userDAO: UserDAO,
|
private val userDAO: UserDAO,
|
||||||
private val selectedProfileState: SelectedUserId,
|
private val selectedProfileState: SelectedUserId,
|
||||||
logService: LogService
|
logService: LogService
|
||||||
): StudeezViewModel(logService) {
|
) : StudeezViewModel(logService) {
|
||||||
|
|
||||||
var uiState = mutableStateOf(SearchFriendUiState())
|
var uiState = mutableStateOf(SearchFriendUiState())
|
||||||
private set
|
private set
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
package be.ugent.sel.studeez.screens.home
|
package be.ugent.sel.studeez.screens.home
|
||||||
|
|
||||||
import be.ugent.sel.studeez.domain.LogService
|
import be.ugent.sel.studeez.domain.LogService
|
||||||
import be.ugent.sel.studeez.navigation.StudeezDestinations
|
import be.ugent.sel.studeez.navigation.StudeezDestinations
|
||||||
import be.ugent.sel.studeez.screens.StudeezViewModel
|
import be.ugent.sel.studeez.screens.StudeezViewModel
|
||||||
|
|
|
@ -92,7 +92,8 @@ fun ProfileScreen(
|
||||||
item {
|
item {
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(5.dp),
|
horizontalArrangement = Arrangement.spacedBy(5.dp),
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
.wrapContentWidth(align = Alignment.CenterHorizontally)
|
.wrapContentWidth(align = Alignment.CenterHorizontally)
|
||||||
) {
|
) {
|
||||||
AmountOfFriendsButton(
|
AmountOfFriendsButton(
|
||||||
|
@ -140,7 +141,7 @@ fun ProfileScreenPreview() {
|
||||||
fun AmountOfFriendsButton(
|
fun AmountOfFriendsButton(
|
||||||
amountOfFriends: Int,
|
amountOfFriends: Int,
|
||||||
onClick: () -> Unit
|
onClick: () -> Unit
|
||||||
){
|
) {
|
||||||
Button(
|
Button(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
shape = defaultButtonShape()
|
shape = defaultButtonShape()
|
||||||
|
|
|
@ -82,7 +82,7 @@ fun EditProfileScreen(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
BasicTextButton(
|
BasicTextButton(
|
||||||
text = AppText.delete_profile,
|
text = AppText.delete_profile,
|
||||||
Modifier.textButton(),
|
Modifier.textButton(),
|
||||||
action = editProfileActions.onDeleteClick
|
action = editProfileActions.onDeleteClick
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package be.ugent.sel.studeez.screens.profile.edit_profile
|
package be.ugent.sel.studeez.screens.profile.edit_profile
|
||||||
|
|
||||||
data class ProfileEditUiState (
|
data class ProfileEditUiState(
|
||||||
val username: String = "",
|
val username: String = "",
|
||||||
val biography: String = ""
|
val biography: String = ""
|
||||||
)
|
)
|
|
@ -39,9 +39,11 @@ fun getPublicProfileActions(
|
||||||
): PublicProfileActions {
|
): PublicProfileActions {
|
||||||
return PublicProfileActions(
|
return PublicProfileActions(
|
||||||
getUserDetails = { viewModel.getUserDetails(viewModel.uiState.value.userId) },
|
getUserDetails = { viewModel.getUserDetails(viewModel.uiState.value.userId) },
|
||||||
getAmountOfFriends = { viewModel.getAmountOfFriends(
|
getAmountOfFriends = {
|
||||||
userId = viewModel.uiState.value.userId
|
viewModel.getAmountOfFriends(
|
||||||
) },
|
userId = viewModel.uiState.value.userId
|
||||||
|
)
|
||||||
|
},
|
||||||
onViewFriendsClick = { viewModel.onViewFriendsClick(open) },
|
onViewFriendsClick = { viewModel.onViewFriendsClick(open) },
|
||||||
sendFriendRequest = {
|
sendFriendRequest = {
|
||||||
viewModel.sendFriendRequest(
|
viewModel.sendFriendRequest(
|
||||||
|
@ -123,11 +125,13 @@ fun PublicProfilePreview() {
|
||||||
PublicProfileScreen(
|
PublicProfileScreen(
|
||||||
publicProfileActions = PublicProfileActions(
|
publicProfileActions = PublicProfileActions(
|
||||||
getUserDetails = {
|
getUserDetails = {
|
||||||
flowOf(User(
|
flowOf(
|
||||||
id = "someid",
|
User(
|
||||||
username = "Maxime De Poorter",
|
id = "someid",
|
||||||
biography = "I am a different student and this is my public profile"
|
username = "Maxime De Poorter",
|
||||||
))
|
biography = "I am a different student and this is my public profile"
|
||||||
|
)
|
||||||
|
)
|
||||||
},
|
},
|
||||||
getAmountOfFriends = { flowOf(113) },
|
getAmountOfFriends = { flowOf(113) },
|
||||||
onViewFriendsClick = {},
|
onViewFriendsClick = {},
|
||||||
|
|
|
@ -18,7 +18,7 @@ class PublicProfileViewModel @Inject constructor(
|
||||||
private val friendshipDAO: FriendshipDAO,
|
private val friendshipDAO: FriendshipDAO,
|
||||||
selectedUserIdState: SelectedUserId,
|
selectedUserIdState: SelectedUserId,
|
||||||
logService: LogService
|
logService: LogService
|
||||||
): StudeezViewModel(logService) {
|
) : StudeezViewModel(logService) {
|
||||||
|
|
||||||
val uiState = mutableStateOf(
|
val uiState = mutableStateOf(
|
||||||
PublicProfileUiState(
|
PublicProfileUiState(
|
||||||
|
|
|
@ -39,7 +39,8 @@ fun SessionRoute(
|
||||||
|
|
||||||
val soundPlayer = SoundPlayer(LocalContext.current)
|
val soundPlayer = SoundPlayer(LocalContext.current)
|
||||||
val sessionActions = getSessionActions(viewModel, openAndPopUp)
|
val sessionActions = getSessionActions(viewModel, openAndPopUp)
|
||||||
val sessionScreen = viewModel.getTimer().accept(GetSessionScreenComposable(soundPlayer, open, sessionActions))
|
val sessionScreen =
|
||||||
|
viewModel.getTimer().accept(GetSessionScreenComposable(soundPlayer, open, sessionActions))
|
||||||
|
|
||||||
sessionScreen()
|
sessionScreen()
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class SoundPlayer(private val context: Context) {
|
||||||
|
|
||||||
|
|
||||||
private fun initPlayer(): MediaPlayer {
|
private fun initPlayer(): MediaPlayer {
|
||||||
return MediaPlayer.create(
|
return MediaPlayer.create(
|
||||||
context,
|
context,
|
||||||
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
|
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
|
||||||
)
|
)
|
||||||
|
|
|
@ -27,7 +27,7 @@ fun BreakSessionScreenComposable(
|
||||||
sessionActions = sessionActions,
|
sessionActions = sessionActions,
|
||||||
midSection = { Dots(pomodoroTimer = pomodoroTimer) },
|
midSection = { Dots(pomodoroTimer = pomodoroTimer) },
|
||||||
callMediaPlayer = { soundPlayer.playOn(pomodoroTimer.hasCurrentCountdownEnded()) },
|
callMediaPlayer = { soundPlayer.playOn(pomodoroTimer.hasCurrentCountdownEnded()) },
|
||||||
motivationString = { motivationString (pomodoroTimer = pomodoroTimer) }
|
motivationString = { motivationString(pomodoroTimer = pomodoroTimer) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,11 +57,13 @@ private fun Dots(pomodoroTimer: FunctionalPomodoroTimer): Int {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun Dot(color: Color) {
|
private fun Dot(color: Color) {
|
||||||
Box(modifier = Modifier
|
Box(
|
||||||
.padding(5.dp)
|
modifier = Modifier
|
||||||
.size(10.dp)
|
.padding(5.dp)
|
||||||
.clip(CircleShape)
|
.size(10.dp)
|
||||||
.background(color))
|
.clip(CircleShape)
|
||||||
|
.background(color)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,12 @@ class GetSessionScreenComposable(
|
||||||
private val soundPlayer: SoundPlayer,
|
private val soundPlayer: SoundPlayer,
|
||||||
private val open: (String) -> Unit,
|
private val open: (String) -> Unit,
|
||||||
private val sessionActions: SessionActions
|
private val sessionActions: SessionActions
|
||||||
) :
|
) :
|
||||||
FunctionalTimerVisitor<@Composable () -> Unit> {
|
FunctionalTimerVisitor<@Composable () -> Unit> {
|
||||||
|
|
||||||
override fun visitFunctionalCustomTimer(functionalCustomTimer: FunctionalCustomTimer): @Composable () -> Unit {
|
override fun visitFunctionalCustomTimer(functionalCustomTimer: FunctionalCustomTimer): @Composable () -> Unit {
|
||||||
return { CustomTimerSessionScreenComposable(
|
return {
|
||||||
|
CustomTimerSessionScreenComposable(
|
||||||
open = open,
|
open = open,
|
||||||
sessionActions = sessionActions,
|
sessionActions = sessionActions,
|
||||||
soundPlayer = soundPlayer,
|
soundPlayer = soundPlayer,
|
||||||
|
|
|
@ -23,10 +23,10 @@ fun SessionScreen(
|
||||||
open: (String) -> Unit,
|
open: (String) -> Unit,
|
||||||
sessionActions: SessionActions,
|
sessionActions: SessionActions,
|
||||||
callMediaPlayer: () -> Unit = {},
|
callMediaPlayer: () -> Unit = {},
|
||||||
midSection: @Composable () -> Int = {0},
|
midSection: @Composable () -> Int = { 0 },
|
||||||
motivationString: @Composable () -> String,
|
motivationString: @Composable () -> String,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(10.dp)
|
modifier = Modifier.padding(10.dp)
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -135,9 +135,11 @@ fun SessionRecapScreenPreview() {
|
||||||
SessionRecapScreen(
|
SessionRecapScreen(
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
sessionRecapActions = SessionRecapActions(
|
sessionRecapActions = SessionRecapActions(
|
||||||
{ SessionReport(
|
{
|
||||||
studyTime = 100,
|
SessionReport(
|
||||||
) },
|
studyTime = 100,
|
||||||
|
)
|
||||||
|
},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,7 +21,7 @@ class SignUpViewModel @Inject constructor(
|
||||||
private val accountDAO: AccountDAO,
|
private val accountDAO: AccountDAO,
|
||||||
private val userDAO: UserDAO,
|
private val userDAO: UserDAO,
|
||||||
logService: LogService
|
logService: LogService
|
||||||
) : StudeezViewModel(logService) {
|
) : StudeezViewModel(logService) {
|
||||||
var uiState = mutableStateOf(SignUpUiState())
|
var uiState = mutableStateOf(SignUpUiState())
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ class SignUpViewModel @Inject constructor(
|
||||||
fun onUsernameChange(newValue: String) {
|
fun onUsernameChange(newValue: String) {
|
||||||
uiState.value = uiState.value.copy(username = newValue)
|
uiState.value = uiState.value.copy(username = newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onEmailChange(newValue: String) {
|
fun onEmailChange(newValue: String) {
|
||||||
uiState.value = uiState.value.copy(email = newValue)
|
uiState.value = uiState.value.copy(email = newValue)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ class SplashViewModel @Inject constructor(
|
||||||
showError.value = false
|
showError.value = false
|
||||||
if (accountDAO.hasUser) {
|
if (accountDAO.hasUser) {
|
||||||
openAndPopUp(StudeezDestinations.HOME_SCREEN, StudeezDestinations.SPLASH_SCREEN)
|
openAndPopUp(StudeezDestinations.HOME_SCREEN, StudeezDestinations.SPLASH_SCREEN)
|
||||||
} else{
|
} else {
|
||||||
openAndPopUp(StudeezDestinations.SIGN_UP_SCREEN, StudeezDestinations.SPLASH_SCREEN)
|
openAndPopUp(StudeezDestinations.SIGN_UP_SCREEN, StudeezDestinations.SPLASH_SCREEN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import be.ugent.sel.studeez.screens.timer_form.form_screens.BreakTimerFormScreen
|
||||||
import be.ugent.sel.studeez.screens.timer_form.form_screens.CustomTimerFormScreen
|
import be.ugent.sel.studeez.screens.timer_form.form_screens.CustomTimerFormScreen
|
||||||
import be.ugent.sel.studeez.screens.timer_form.form_screens.EndlessTimerFormScreen
|
import be.ugent.sel.studeez.screens.timer_form.form_screens.EndlessTimerFormScreen
|
||||||
|
|
||||||
class GetTimerFormScreen: TimerInfoVisitor<AbstractTimerFormScreen> {
|
class GetTimerFormScreen : TimerInfoVisitor<AbstractTimerFormScreen> {
|
||||||
|
|
||||||
override fun visitCustomTimerInfo(customTimerInfo: CustomTimerInfo): AbstractTimerFormScreen {
|
override fun visitCustomTimerInfo(customTimerInfo: CustomTimerInfo): AbstractTimerFormScreen {
|
||||||
return CustomTimerFormScreen(customTimerInfo)
|
return CustomTimerFormScreen(customTimerInfo)
|
||||||
|
|
|
@ -18,10 +18,10 @@ fun TimerAddRoute(
|
||||||
TimerFormScreen(
|
TimerFormScreen(
|
||||||
popUp = popUp,
|
popUp = popUp,
|
||||||
getTimerInfo = viewModel::getTimerInfo,
|
getTimerInfo = viewModel::getTimerInfo,
|
||||||
extraButton= { },
|
extraButton = { },
|
||||||
AppText.add_timer
|
AppText.add_timer
|
||||||
) {
|
) {
|
||||||
viewModel.saveTimer(it, goBack = {popUp(); popUp()})
|
viewModel.saveTimer(it, goBack = { popUp(); popUp() })
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ fun TimerEditRoute(
|
||||||
TimerFormScreen(
|
TimerFormScreen(
|
||||||
popUp = popUp,
|
popUp = popUp,
|
||||||
getTimerInfo = viewModel::getTimerInfo,
|
getTimerInfo = viewModel::getTimerInfo,
|
||||||
extraButton= { deleteButton() },
|
extraButton = { deleteButton() },
|
||||||
AppText.edit_timer
|
AppText.edit_timer
|
||||||
) {
|
) {
|
||||||
viewModel.editTimer(it, goBack = popUp)
|
viewModel.editTimer(it, goBack = popUp)
|
||||||
|
|
|
@ -15,8 +15,7 @@ import be.ugent.sel.studeez.R.string as AppText
|
||||||
|
|
||||||
class BreakTimerFormScreen(
|
class BreakTimerFormScreen(
|
||||||
private val breakTimerInfo: PomodoroTimerInfo
|
private val breakTimerInfo: PomodoroTimerInfo
|
||||||
): AbstractTimerFormScreen(breakTimerInfo) {
|
) : AbstractTimerFormScreen(breakTimerInfo) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -30,7 +29,7 @@ class BreakTimerFormScreen(
|
||||||
breakTimerInfo.breakTime = newTime
|
breakTimerInfo.breakTime = newTime
|
||||||
}
|
}
|
||||||
|
|
||||||
valids["repeats"] = remember {mutableStateOf(true)}
|
valids["repeats"] = remember { mutableStateOf(true) }
|
||||||
firsts["repeats"] = remember { mutableStateOf(true) }
|
firsts["repeats"] = remember { mutableStateOf(true) }
|
||||||
|
|
||||||
LabeledErrorTextField(
|
LabeledErrorTextField(
|
||||||
|
|
|
@ -9,7 +9,7 @@ import be.ugent.sel.studeez.R.string as AppText
|
||||||
|
|
||||||
class CustomTimerFormScreen(
|
class CustomTimerFormScreen(
|
||||||
private val customTimerInfo: CustomTimerInfo
|
private val customTimerInfo: CustomTimerInfo
|
||||||
): AbstractTimerFormScreen(customTimerInfo) {
|
) : AbstractTimerFormScreen(customTimerInfo) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun ExtraFields() {
|
override fun ExtraFields() {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import be.ugent.sel.studeez.ui.theme.StudeezTheme
|
||||||
|
|
||||||
class EndlessTimerFormScreen(
|
class EndlessTimerFormScreen(
|
||||||
endlessTimerInfo: EndlessTimerInfo
|
endlessTimerInfo: EndlessTimerInfo
|
||||||
): AbstractTimerFormScreen(endlessTimerInfo) {
|
) : AbstractTimerFormScreen(endlessTimerInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
|
|
|
@ -40,7 +40,9 @@ fun TimerTypeSelectScreen(
|
||||||
val default: TimerInfo = defaultTimerInfo.getValue(timerType)
|
val default: TimerInfo = defaultTimerInfo.getValue(timerType)
|
||||||
Button(
|
Button(
|
||||||
onClick = { viewModel.onTimerTypeChosen(default, open) },
|
onClick = { viewModel.onTimerTypeChosen(default, open) },
|
||||||
modifier = Modifier.fillMaxWidth().padding(5.dp)
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(5.dp)
|
||||||
) {
|
) {
|
||||||
Text(text = timerType.name)
|
Text(text = timerType.name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,11 +68,13 @@ fun TimerOverviewScreen(
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
// Custom timer, select new duration each time
|
// Custom timer, select new duration each time
|
||||||
item {
|
item {
|
||||||
TimerEntry(timerInfo = CustomTimerInfo(
|
TimerEntry(
|
||||||
name = resources().getString(R.string.custom_name),
|
timerInfo = CustomTimerInfo(
|
||||||
description = resources().getString(R.string.custom_name),
|
name = resources().getString(R.string.custom_name),
|
||||||
studyTime = 0
|
description = resources().getString(R.string.custom_name),
|
||||||
))
|
studyTime = 0
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// Default Timers, cannot be edited
|
// Default Timers, cannot be edited
|
||||||
items(timerOverviewActions.getDefaultTimers()) {
|
items(timerOverviewActions.getDefaultTimers()) {
|
||||||
|
|
|
@ -2,6 +2,6 @@ package be.ugent.sel.studeez.ui.theme
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
val Blue100 = Color( 30, 100, 200, 255)
|
val Blue100 = Color(30, 100, 200, 255)
|
||||||
val Blue120 = Color( 27, 90, 180, 255)
|
val Blue120 = Color(27, 90, 180, 255)
|
||||||
val Yellow100 = Color(255, 210, 0, 255)
|
val Yellow100 = Color(255, 210, 0, 255)
|
Reference in a new issue