Merge pull request #125 from SELab1/feed_friends

Feed friends
This commit is contained in:
brreynie 2023-05-16 11:11:10 +02:00 committed by GitHub Enterprise
commit 373a0e6209
16 changed files with 271 additions and 96 deletions

View file

@ -8,13 +8,15 @@ 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.DateRange
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
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import be.ugent.sel.studeez.navigation.StudeezDestinations.FRIENDS_FEED
import be.ugent.sel.studeez.navigation.StudeezDestinations.HOME_SCREEN 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.PROFILE_SCREEN
import be.ugent.sel.studeez.navigation.StudeezDestinations.SESSIONS_SCREEN
import be.ugent.sel.studeez.navigation.StudeezDestinations.SUBJECT_SCREEN import be.ugent.sel.studeez.navigation.StudeezDestinations.SUBJECT_SCREEN
import be.ugent.sel.studeez.resources import be.ugent.sel.studeez.resources
import be.ugent.sel.studeez.ui.theme.StudeezTheme import be.ugent.sel.studeez.ui.theme.StudeezTheme
@ -99,11 +101,11 @@ fun NavigationBar(
BottomNavigationItem( BottomNavigationItem(
icon = { icon = {
Icon( Icon(
imageVector = Icons.Outlined.DateRange, resources().getString(AppText.sessions) imageVector = Icons.Outlined.Face, resources().getString(AppText.friends_feed)
) )
}, },
label = { Text(text = resources().getString(AppText.sessions)) }, label = { Text(text = resources().getString(AppText.friends_feed)) },
selected = navigationBarActions.isSelectedTab(SESSIONS_SCREEN), selected = navigationBarActions.isSelectedTab(FRIENDS_FEED),
onClick = navigationBarActions.onSessionsClick onClick = navigationBarActions.onSessionsClick
) )

View file

@ -2,6 +2,7 @@ package be.ugent.sel.studeez.common.composable.navbar
import be.ugent.sel.studeez.common.snackbar.SnackbarManager import be.ugent.sel.studeez.common.snackbar.SnackbarManager
import be.ugent.sel.studeez.domain.LogService import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.navigation.StudeezDestinations.FRIENDS_FEED
import be.ugent.sel.studeez.navigation.StudeezDestinations.HOME_SCREEN 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.PROFILE_SCREEN
import be.ugent.sel.studeez.navigation.StudeezDestinations.SEARCH_FRIENDS_SCREEN import be.ugent.sel.studeez.navigation.StudeezDestinations.SEARCH_FRIENDS_SCREEN
@ -27,7 +28,7 @@ class NavigationBarViewModel @Inject constructor(
} }
fun onSessionsClick(open: (String) -> Unit) { fun onSessionsClick(open: (String) -> Unit) {
open(SESSIONS_SCREEN) open(FRIENDS_FEED)
} }
fun onProfileClick(open: (String) -> Unit) { fun onProfileClick(open: (String) -> Unit) {

View file

@ -7,4 +7,7 @@ interface FeedDAO {
fun getFeedEntries(): Flow<Map<String, List<FeedEntry>>> fun getFeedEntries(): Flow<Map<String, List<FeedEntry>>>
suspend fun getFeedEntriesFromUser(id: String): Map<String, List<FeedEntry>>
fun getFriendsSessions(): Flow<Map<String, List<Pair<String, FeedEntry>>>>
} }

View file

@ -1,7 +1,9 @@
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.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
@ -10,11 +12,6 @@ interface SessionDAO {
fun getSessions(): Flow<List<SessionReport>> fun getSessions(): Flow<List<SessionReport>>
suspend fun getSessionsOfUser(userId: String): List<SessionReport> suspend fun getSessionsOfUser(userId: String): List<SessionReport>
/**
* Return a list of pairs, containing the username and all the studysessions of that user.
*/
fun getFriendsSessions(): Flow<List<Pair<String,List<SessionReport>>>>
fun saveSession(newSessionReport: SessionReport) fun saveSession(newSessionReport: SessionReport)
fun deleteSession(newTimer: TimerInfo) fun deleteSession(newTimer: TimerInfo)

View file

@ -20,4 +20,5 @@ interface SubjectDAO {
fun getStudyTime(subject: Subject): Flow<Int> fun getStudyTime(subject: Subject): Flow<Int>
suspend fun getSubject(subjectId: String): Subject? suspend fun getSubject(subjectId: String): Subject?
suspend fun getSubjectOfUSer(subjectId: String, userId: String): Subject
} }

View file

@ -15,4 +15,6 @@ interface TaskDAO {
fun deleteTask(oldTask: Task) fun deleteTask(oldTask: Task)
suspend fun getTask(subjectId: String, taskId: String): Task suspend fun getTask(subjectId: String, taskId: String): Task
suspend fun getTaskFromUser(subjectId: String, taskId: String, userId: String): Task
} }

View file

@ -5,19 +5,19 @@ 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.task.Subject import be.ugent.sel.studeez.data.local.models.task.Subject
import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.data.local.models.task.Task
import be.ugent.sel.studeez.domain.FeedDAO import be.ugent.sel.studeez.domain.*
import be.ugent.sel.studeez.domain.SessionDAO
import be.ugent.sel.studeez.domain.SubjectDAO
import be.ugent.sel.studeez.domain.TaskDAO
import com.google.firebase.Timestamp import com.google.firebase.Timestamp
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import javax.inject.Inject import javax.inject.Inject
class FirebaseFeedDAO @Inject constructor( class FirebaseFeedDAO @Inject constructor(
private val friendshipDAO: FriendshipDAO,
private val sessionDAO: SessionDAO, private val sessionDAO: SessionDAO,
private val taskDAO: TaskDAO, private val taskDAO: TaskDAO,
private val subjectDAO: SubjectDAO private val subjectDAO: SubjectDAO,
private val auth: AccountDAO,
private val userDAO: UserDAO,
) : FeedDAO { ) : FeedDAO {
/** /**
@ -37,6 +37,45 @@ class FirebaseFeedDAO @Inject constructor(
} }
} }
/**
* Return a map as with key the day and value a list of feedentries for that day.
*/
override suspend fun getFeedEntriesFromUser(id: String): Map<String, List<FeedEntry>> {
return sessionDAO.getSessionsOfUser(id)
.map { sessionReport -> sessionToFeedEntryFromUser(sessionReport, id) }
.sortedByDescending { it.endTime }
.groupBy { getFormattedTime(it) }
.mapValues { (_, entries) ->
entries
.groupBy { it.taskId }
.map { fuseFeedEntries(it.component2()) }
}
}
override fun getFriendsSessions(): Flow<Map<String, List<Pair<String, FeedEntry>>>> {
return friendshipDAO.getAllFriendships(auth.currentUserId)
.map { friendships ->
friendships.map { friendship ->
val userId: String = friendship.friendId
val username = userDAO.getUsername(userId)
val friendFeed = getFeedEntriesFromUser(userId)
Pair(username, friendFeed)
}
}.map {
mergeNameAndEntries(it)
}
}
private fun mergeNameAndEntries(l: List<Pair<String, Map<String, List<FeedEntry>>>>): Map<String, List<Pair<String, FeedEntry>>> {
val new: MutableMap<String, List<Pair<String, FeedEntry>>> = mutableMapOf()
for ((name, map) in l) {
for ((day, feedEntries: List<FeedEntry>) in map) {
new[day] = new.getOrDefault(day, listOf()) + feedEntries.map { Pair(name, it) }
}
}
return new
}
private fun getFormattedTime(entry: FeedEntry): String { private fun getFormattedTime(entry: FeedEntry): String {
return DateFormat.getDateInstance().format(entry.endTime.toDate()) return DateFormat.getDateInstance().format(entry.endTime.toDate())
} }
@ -67,6 +106,10 @@ class FirebaseFeedDAO @Inject constructor(
val task: Task = taskDAO.getTask(subjectId, taskId) val task: Task = taskDAO.getTask(subjectId, taskId)
val subject: Subject = subjectDAO.getSubject(subjectId)!! val subject: Subject = subjectDAO.getSubject(subjectId)!!
return makeFeedEntry(sessionReport, subject, task)
}
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,
@ -78,4 +121,17 @@ class FirebaseFeedDAO @Inject constructor(
isArchived = task.archived || subject.archived isArchived = task.archived || subject.archived
) )
} }
/**
* Convert a sessionReport to a feedEntry. Fetch Task and Subject to get names
*/
private suspend fun sessionToFeedEntryFromUser(sessionReport: SessionReport, id: String): FeedEntry {
val subjectId: String = sessionReport.subjectId
val taskId: String = sessionReport.taskId
val task: Task = taskDAO.getTaskFromUser(subjectId, taskId, id)
val subject: Subject = subjectDAO.getSubjectOfUSer(subjectId, id)
return makeFeedEntry(sessionReport, subject, task)
}
} }

View file

@ -1,15 +1,14 @@
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.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.data.remote.FirebaseSessionReport
import be.ugent.sel.studeez.data.remote.FirebaseSessionReport.ENDTIME import be.ugent.sel.studeez.data.remote.FirebaseSessionReport.ENDTIME
import be.ugent.sel.studeez.data.remote.FirebaseSessionReport.STUDYTIME import be.ugent.sel.studeez.data.remote.FirebaseSessionReport.STUDYTIME
import be.ugent.sel.studeez.domain.AccountDAO import be.ugent.sel.studeez.domain.*
import be.ugent.sel.studeez.domain.FriendshipDAO
import be.ugent.sel.studeez.domain.SessionDAO
import be.ugent.sel.studeez.domain.UserDAO
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.Timestamp
@ -17,6 +16,7 @@ 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.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.emptyFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@ -26,8 +26,6 @@ import javax.inject.Inject
class FirebaseSessionDAO @Inject constructor( class FirebaseSessionDAO @Inject constructor(
private val firestore: FirebaseFirestore, private val firestore: FirebaseFirestore,
private val auth: AccountDAO, private val auth: AccountDAO,
private val userDAO: UserDAO,
private val friendshipDAO: FriendshipDAO
) : SessionDAO { ) : SessionDAO {
override fun getSessions(): Flow<List<SessionReport>> { override fun getSessions(): Flow<List<SessionReport>> {
@ -37,32 +35,13 @@ class FirebaseSessionDAO @Inject constructor(
} }
override suspend fun getSessionsOfUser(userId: String): List<SessionReport> { override suspend fun getSessionsOfUser(userId: String): List<SessionReport> {
val collection = firestore.collection(USER_COLLECTION) return firestore.collection(USER_COLLECTION)
.document(userId) .document(userId)
.collection(SESSION_COLLECTION) .collection(SESSION_COLLECTION)
.get().await() .get().await()
val list: MutableList<SessionReport> = mutableListOf() .map { it.toObject(SessionReport::class.java) }
for (document in collection) {
val id = document.id
val studyTime: Int = document.getField<Int>(STUDYTIME)!!
val endTime: Timestamp = document.getField<Timestamp>(ENDTIME)!!
list.add(SessionReport(id, studyTime, endTime))
}
return list
} }
override fun getFriendsSessions(): Flow<List<Pair<String, List<SessionReport>>>> {
return friendshipDAO.getAllFriendships(auth.currentUserId)
.map { friendships ->
friendships.map { friendship ->
val userId: String = friendship.friendId
val username = userDAO.getUsername(userId)
val userSessions = getSessionsOfUser(userId)
Pair(username, userSessions)
}
}
}
override fun saveSession(newSessionReport: SessionReport) { override fun saveSession(newSessionReport: SessionReport) {
currentUserSessionsCollection().add(newSessionReport) currentUserSessionsCollection().add(newSessionReport)

View file

@ -1,6 +1,5 @@
package be.ugent.sel.studeez.domain.implementation package be.ugent.sel.studeez.domain.implementation
import android.util.Log
import be.ugent.sel.studeez.data.local.models.task.Subject import be.ugent.sel.studeez.data.local.models.task.Subject
import be.ugent.sel.studeez.data.local.models.task.SubjectDocument import be.ugent.sel.studeez.data.local.models.task.SubjectDocument
import be.ugent.sel.studeez.data.local.models.task.Task import be.ugent.sel.studeez.data.local.models.task.Task
@ -35,6 +34,10 @@ class FirebaseSubjectDAO @Inject constructor(
return currentUserSubjectsCollection().document(subjectId).get().await().toObject() return currentUserSubjectsCollection().document(subjectId).get().await().toObject()
} }
override suspend fun getSubjectOfUSer(subjectId: String, userId: String): Subject {
return currentUserSubjectsCollection(userId).document(subjectId).get().await().toObject()!!
}
override fun saveSubject(newSubject: Subject) { override fun saveSubject(newSubject: Subject) {
currentUserSubjectsCollection().add(newSubject) currentUserSubjectsCollection().add(newSubject)
} }
@ -74,14 +77,14 @@ class FirebaseSubjectDAO @Inject constructor(
.map { tasks -> tasks.sumOf { it.time } } .map { tasks -> tasks.sumOf { it.time } }
} }
private fun currentUserSubjectsCollection(): CollectionReference = private fun currentUserSubjectsCollection(id: String = auth.currentUserId): CollectionReference =
firestore.collection(FirebaseCollections.USER_COLLECTION) firestore.collection(FirebaseCollections.USER_COLLECTION)
.document(auth.currentUserId) .document(id)
.collection(FirebaseCollections.SUBJECT_COLLECTION) .collection(FirebaseCollections.SUBJECT_COLLECTION)
private fun subjectTasksCollection(subject: Subject): CollectionReference = private fun subjectTasksCollection(subject: Subject, id: String = auth.currentUserId): CollectionReference =
firestore.collection(FirebaseCollections.USER_COLLECTION) firestore.collection(FirebaseCollections.USER_COLLECTION)
.document(auth.currentUserId) .document(id)
.collection(FirebaseCollections.SUBJECT_COLLECTION) .collection(FirebaseCollections.SUBJECT_COLLECTION)
.document(subject.id) .document(subject.id)
.collection(FirebaseCollections.TASK_COLLECTION) .collection(FirebaseCollections.TASK_COLLECTION)

View file

@ -30,6 +30,13 @@ class FirebaseTaskDAO @Inject constructor(
return selectedSubjectTasksCollection(subjectId).document(taskId).get().await().toObject()!! return selectedSubjectTasksCollection(subjectId).document(taskId).get().await().toObject()!!
} }
override suspend fun getTaskFromUser(subjectId: String, taskId: String, userId: String): Task {
return selectedSubjectTasksCollection(subjectId, userId)
.document(taskId)
.get()
.await().toObject(Task::class.java)!!
}
override fun saveTask(newTask: Task) { override fun saveTask(newTask: Task) {
selectedSubjectTasksCollection(newTask.subjectId).add(newTask) selectedSubjectTasksCollection(newTask.subjectId).add(newTask)
} }
@ -44,9 +51,9 @@ class FirebaseTaskDAO @Inject constructor(
selectedSubjectTasksCollection(oldTask.subjectId).document(oldTask.id).delete() selectedSubjectTasksCollection(oldTask.subjectId).document(oldTask.id).delete()
} }
private fun selectedSubjectTasksCollection(subjectId: String): CollectionReference = private fun selectedSubjectTasksCollection(subjectId: String, id: String = auth.currentUserId): CollectionReference =
firestore.collection(FirebaseCollections.USER_COLLECTION) firestore.collection(FirebaseCollections.USER_COLLECTION)
.document(auth.currentUserId) .document(id)
.collection(FirebaseCollections.SUBJECT_COLLECTION) .collection(FirebaseCollections.SUBJECT_COLLECTION)
.document(subjectId) .document(subjectId)
.collection(FirebaseCollections.TASK_COLLECTION) .collection(FirebaseCollections.TASK_COLLECTION)

View file

@ -4,7 +4,7 @@ object StudeezDestinations {
// NavBar // NavBar
const val HOME_SCREEN = "home" const val HOME_SCREEN = "home"
const val SUBJECT_SCREEN = "subjects" const val SUBJECT_SCREEN = "subjects"
const val SESSIONS_SCREEN = "sessions" const val FRIENDS_FEED = "friends_feed"
const val PROFILE_SCREEN = "profile" const val PROFILE_SCREEN = "profile"
// Drawer // Drawer

View file

@ -16,6 +16,8 @@ import be.ugent.sel.studeez.common.composable.navbar.NavigationBarViewModel
import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions import be.ugent.sel.studeez.common.composable.navbar.getNavigationBarActions
import be.ugent.sel.studeez.screens.friends.friends_overview.FriendsOveriewRoute import be.ugent.sel.studeez.screens.friends.friends_overview.FriendsOveriewRoute
import be.ugent.sel.studeez.screens.friends.friends_search.SearchFriendsRoute import be.ugent.sel.studeez.screens.friends.friends_search.SearchFriendsRoute
import be.ugent.sel.studeez.screens.friends_feed.FriendsFeedRoute
import be.ugent.sel.studeez.screens.friends_feed.FriendsFeedScreen
import be.ugent.sel.studeez.screens.home.HomeRoute import be.ugent.sel.studeez.screens.home.HomeRoute
import be.ugent.sel.studeez.screens.log_in.LoginRoute import be.ugent.sel.studeez.screens.log_in.LoginRoute
import be.ugent.sel.studeez.screens.profile.edit_profile.EditProfileRoute import be.ugent.sel.studeez.screens.profile.edit_profile.EditProfileRoute
@ -23,7 +25,6 @@ import be.ugent.sel.studeez.screens.profile.ProfileRoute
import be.ugent.sel.studeez.screens.profile.public_profile.PublicProfileRoute import be.ugent.sel.studeez.screens.profile.public_profile.PublicProfileRoute
import be.ugent.sel.studeez.screens.session.SessionRoute import be.ugent.sel.studeez.screens.session.SessionRoute
import be.ugent.sel.studeez.screens.session_recap.SessionRecapRoute 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.settings.SettingsRoute
import be.ugent.sel.studeez.screens.sign_up.SignUpRoute import be.ugent.sel.studeez.screens.sign_up.SignUpRoute
import be.ugent.sel.studeez.screens.splash.SplashRoute import be.ugent.sel.studeez.screens.splash.SplashRoute
@ -135,10 +136,11 @@ fun StudeezNavGraph(
} }
composable(StudeezDestinations.SESSIONS_SCREEN) { composable(StudeezDestinations.FRIENDS_FEED) {
SessionsRoute( FriendsFeedRoute(
drawerActions = drawerActions, drawerActions = drawerActions,
navigationBarActions = navigationBarActions navigationBarActions = navigationBarActions,
viewModel = hiltViewModel()
) )
} }

View file

@ -0,0 +1,134 @@
package be.ugent.sel.studeez.screens.friends_feed
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Card
import androidx.compose.material.Divider
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import be.ugent.sel.studeez.common.composable.DateText
import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate
import be.ugent.sel.studeez.common.composable.StealthButton
import be.ugent.sel.studeez.common.composable.TimerEntry
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
import be.ugent.sel.studeez.common.ext.spacer
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.task.Task
import be.ugent.sel.studeez.data.local.models.timer_functional.HoursMinutesSeconds
import be.ugent.sel.studeez.resources
import kotlinx.coroutines.flow.toList
import be.ugent.sel.studeez.R.string as AppText
@Composable
fun FriendsFeedRoute(
viewModel: FriendsFeedViewModel,
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions
) {
FriendsFeedScreen(
drawerActions = drawerActions,
navigationBarActions = navigationBarActions,
viewModel = viewModel
)
}
@Composable
fun FriendsFeedScreen(
drawerActions: DrawerActions,
navigationBarActions: NavigationBarActions,
viewModel: FriendsFeedViewModel
) {
PrimaryScreenTemplate(
title = resources().getString(AppText.friends_feed),
drawerActions = drawerActions,
navigationBarActions = navigationBarActions
) {
val friendsSessions = viewModel.getFriendsSessions().collectAsState(initial = emptyList())
LazyColumn() {
// Default Timers, cannot be edited
items(friendsSessions.value) {
val (day, feedEntries) = it
DateText(date = day)
feedEntries.forEach { (name, feedEntry) ->
FriendsFeedEntry(name = name, feedEntry = feedEntry)
}
Spacer(modifier = Modifier.height(10.dp))
}
}
}
}
@Composable
fun FriendsFeedEntry(
name: String,
feedEntry: FeedEntry
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 10.dp, vertical = 5.dp),
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(start = 10.dp)
.weight(11f)
) {
Box(
modifier = Modifier
.size(20.dp)
.clip(CircleShape)
.background(Color(feedEntry.argb_color)),
)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Column(
verticalArrangement = Arrangement.spacedBy(0.dp)
) {
Text(
text = "$name studied for ${feedEntry.subJectName}",
fontWeight = FontWeight.Medium,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
)
Text(
text = feedEntry.taskName,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
)
}
Text(text = HoursMinutesSeconds(feedEntry.totalStudyTime).toString())
}
}
}
}
}

View file

@ -0,0 +1,27 @@
package be.ugent.sel.studeez.screens.friends_feed
import be.ugent.sel.studeez.data.local.models.FeedEntry
import be.ugent.sel.studeez.data.local.models.task.Task
import be.ugent.sel.studeez.domain.FeedDAO
import be.ugent.sel.studeez.domain.LogService
import be.ugent.sel.studeez.domain.SessionDAO
import be.ugent.sel.studeez.screens.StudeezViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.toList
import javax.inject.Inject
@HiltViewModel
class FriendsFeedViewModel @Inject constructor(
private val feedDAO: FeedDAO,
logService: LogService
) : StudeezViewModel(logService) {
fun getFriendsSessions(): Flow<List<Pair<String, List<Pair<String, FeedEntry>>>>> {
return feedDAO.getFriendsSessions().map { it.toList() }
}
}

View file

@ -1,42 +0,0 @@
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

@ -36,6 +36,9 @@
<string name="your_feed">This is your feed</string> <string name="your_feed">This is your feed</string>
<string name="empty_feed_help_text">Click here to create you first subject and tasks to get started</string> <string name="empty_feed_help_text">Click here to create you first subject and tasks to get started</string>
<!-- Friends Feed -->
<string name="friends_feed">Feed</string>
<!-- Tasks --> <!-- Tasks -->
<string name="tasks">Tasks</string> <string name="tasks">Tasks</string>
<string name="task">Task</string> <string name="task">Task</string>