Merge branch 'development' into feed_friends
This commit is contained in:
		
						commit
						754cad20ed
					
				
					 47 changed files with 1441 additions and 174 deletions
				
			
		
							
								
								
									
										74
									
								
								app/src/androidTest/java/be/ugent/sel/studeez/FabTest.kt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								app/src/androidTest/java/be/ugent/sel/studeez/FabTest.kt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.material.FloatingActionButton | ||||
| import androidx.compose.ui.test.hasClickAction | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onNodeWithContentDescription | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.common.composable.AddButtonActions | ||||
| import be.ugent.sel.studeez.common.composable.ExpandedAddButton | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class FabTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun expandFabTest() { | ||||
|         var expand = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             FloatingActionButton( | ||||
|                 onClick = {expand = true} | ||||
|             ) {} | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNode(hasClickAction()) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(expand) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun fabTest() { | ||||
|         var task = false | ||||
|         var session = false | ||||
|         var friend = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             ExpandedAddButton( | ||||
|                 addButtonActions = AddButtonActions( | ||||
|                     {task = true}, | ||||
|                     {friend = true}, | ||||
|                     {session = true} | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription("Session") | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription("Task") | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription("Friend") | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(task) | ||||
|         assert(session) | ||||
|         assert(friend) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										207
									
								
								app/src/androidTest/java/be/ugent/sel/studeez/HomeScreenTest.kt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								app/src/androidTest/java/be/ugent/sel/studeez/HomeScreenTest.kt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,207 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onAllNodesWithContentDescription | ||||
| import androidx.compose.ui.test.onAllNodesWithText | ||||
| import androidx.compose.ui.test.onNodeWithContentDescription | ||||
| import androidx.compose.ui.test.onNodeWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.common.composable.drawer.DrawerActions | ||||
| import be.ugent.sel.studeez.common.composable.feed.FeedUiState | ||||
| import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions | ||||
| import be.ugent.sel.studeez.data.local.models.FeedEntry | ||||
| import be.ugent.sel.studeez.screens.home.HomeScreen | ||||
| import org.junit.Assert | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class HomeScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun homeScreenTest() { | ||||
|         var continueTask = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             HomeScreen( | ||||
|                 drawerActions = DrawerActions({}, {}, {}, {}, {}), | ||||
|                 navigationBarActions = NavigationBarActions({false}, {}, {}, {}, {}, {}, {}, {}), | ||||
|                 feedUiState = FeedUiState.Succes(mapOf( | ||||
|                     "08 May 2023" to listOf( | ||||
|                         FeedEntry( | ||||
|                             argb_color = 0xFFABD200, | ||||
|                             subJectName = "Test Subject", | ||||
|                             taskName = "Test Task", | ||||
|                             totalStudyTime = 600, | ||||
|                         ) | ||||
|                     ) | ||||
|                 )), | ||||
|                 continueTask = {_, _ -> continueTask = true }, | ||||
|                 onEmptyFeedHelp = {}, | ||||
|                 onViewFriendsClick = {}, | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 "continue", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         Assert.assertTrue(continueTask) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun drawerTest() { | ||||
|         var homebuttontest = false | ||||
|         var timersbuttontest = false | ||||
|         var settingsbuttontest = false | ||||
|         var logoutbuttontest = false | ||||
|         var aboutbuttontest = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             HomeScreen( | ||||
|                 drawerActions = DrawerActions( | ||||
|                     {homebuttontest = true}, | ||||
|                     {timersbuttontest = true}, | ||||
|                     {settingsbuttontest = true}, | ||||
|                     {logoutbuttontest = true}, | ||||
|                     {aboutbuttontest = true} | ||||
|                 ), | ||||
|                 navigationBarActions = NavigationBarActions({false}, {}, {}, {}, {}, {}, {}, {}), | ||||
|                 feedUiState = FeedUiState.Succes(mapOf()), | ||||
|                 continueTask = {_, _ -> }, | ||||
|                 onEmptyFeedHelp = {}, | ||||
|                 onViewFriendsClick = {}, | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onAllNodesWithText( | ||||
|                 "home", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             )[2] // Third node has the button | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 "timer", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 "settings", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 "log out", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 "about", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         Assert.assertTrue(homebuttontest) | ||||
|         Assert.assertTrue(timersbuttontest) | ||||
|         Assert.assertTrue(settingsbuttontest) | ||||
|         Assert.assertTrue(logoutbuttontest) | ||||
|         Assert.assertTrue(aboutbuttontest) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun navigationbarTest() { | ||||
|         var hometest = false | ||||
|         var tasktest = false | ||||
|         var sessiontest = false | ||||
|         var profiletest = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             HomeScreen( | ||||
|                 drawerActions = DrawerActions({}, {}, {}, {}, {}), | ||||
|                 navigationBarActions = NavigationBarActions( | ||||
|                     {false}, | ||||
|                     {hometest = true}, | ||||
|                     {tasktest = true}, | ||||
|                     {sessiontest = true}, | ||||
|                     {profiletest = true}, | ||||
|                     {}, {}, {} | ||||
|                 ), | ||||
|                 feedUiState = FeedUiState.Succes(mapOf()), | ||||
|                 continueTask = {_, _ -> }, | ||||
|                 onEmptyFeedHelp = {}, | ||||
|                 onViewFriendsClick = {}, | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onAllNodesWithContentDescription( | ||||
|                 "Home", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             )[0] // Third node has the button | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription( | ||||
|                 "tasks", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription( | ||||
|                 "session", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription( | ||||
|                 "profile", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         Assert.assertTrue(hometest) | ||||
|         Assert.assertTrue(tasktest) | ||||
|         Assert.assertTrue(sessiontest) | ||||
|         Assert.assertTrue(profiletest) | ||||
|     } | ||||
| } | ||||
|  | @ -14,7 +14,7 @@ import org.junit.Assert.* | |||
|  * See [testing documentation](http://d.android.com/tools/testing). | ||||
|  */ | ||||
| @RunWith(AndroidJUnit4::class) | ||||
| class ExampleInstrumentedTest { | ||||
| class InstrumentedTest { | ||||
|     @Test | ||||
|     fun useAppContext() { | ||||
|         // Context of the app under test. | ||||
|  | @ -0,0 +1,68 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onAllNodesWithText | ||||
| import androidx.compose.ui.test.onNodeWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.screens.log_in.LoginScreen | ||||
| import be.ugent.sel.studeez.screens.log_in.LoginScreenActions | ||||
| import be.ugent.sel.studeez.screens.log_in.LoginUiState | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class LoginScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun loginScreenTest() { | ||||
|         var login = false | ||||
|         var signup = false | ||||
|         var forgot_password = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             LoginScreen( | ||||
|                 uiState = LoginUiState(), | ||||
|                 loginScreenActions = LoginScreenActions( | ||||
|                     {}, {}, | ||||
|                     {signup = true}, | ||||
|                     {login = true}, | ||||
|                     {forgot_password = true} | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onAllNodesWithText( | ||||
|                 text = "Sign in", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             )[0] // The first object is the button | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "Forgot", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "Sign up", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(signup) | ||||
|         assert(login) | ||||
|         assert(forgot_password) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,70 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.test.assert | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onNodeWithContentDescription | ||||
| import androidx.compose.ui.test.onNodeWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.screens.profile.edit_profile.EditProfileActions | ||||
| import be.ugent.sel.studeez.screens.profile.edit_profile.EditProfileScreen | ||||
| import be.ugent.sel.studeez.screens.profile.edit_profile.ProfileEditUiState | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class ProfileEditScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun profileEditScreenTest() { | ||||
|         var edit_save = false | ||||
|         var goback = false | ||||
|         var delete_click = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             EditProfileScreen( | ||||
|                 goBack = {goback = true}, | ||||
|                 uiState = ProfileEditUiState(), | ||||
|                 editProfileActions = EditProfileActions( | ||||
|                     onUserNameChange = {}, | ||||
|                     onBiographyChange = {}, | ||||
|                     onSaveClick = {edit_save = true}, | ||||
|                     onDeleteClick = { delete_click = true }, | ||||
|                 ), | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "save", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "delete", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription( | ||||
|                 label = "go back", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(edit_save) | ||||
|         assert(goback) | ||||
|         assert(delete_click) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,61 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onNodeWithContentDescription | ||||
| import androidx.compose.ui.test.onNodeWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.common.composable.drawer.DrawerActions | ||||
| import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions | ||||
| import be.ugent.sel.studeez.screens.profile.ProfileActions | ||||
| import be.ugent.sel.studeez.screens.profile.ProfileScreen | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class ProfileScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun profileScreenTest() { | ||||
|         var edit = false | ||||
|         var view_friends = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             ProfileScreen( | ||||
|                 profileActions = ProfileActions( | ||||
|                     getUsername = {null}, | ||||
|                     onEditProfileClick = {edit = true}, | ||||
|                     getBiography = {null}, | ||||
|                     getAmountOfFriends = { flowOf(0) }, | ||||
|                     onViewFriendsClick = {view_friends = true} | ||||
|                 ), | ||||
|                 drawerActions = DrawerActions({}, {}, {}, {}, {}), | ||||
|                 navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}, {}, {}, {}) | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription( | ||||
|                 label = "edit profile", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "friends", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true, | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(edit) | ||||
|         assert(view_friends) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,75 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onNodeWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.data.local.models.SessionReport | ||||
| import be.ugent.sel.studeez.screens.session_recap.SessionRecapActions | ||||
| import be.ugent.sel.studeez.screens.session_recap.SessionRecapScreen | ||||
| import com.google.firebase.Timestamp | ||||
| import org.junit.Assert | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| 
 | ||||
| class SessionRecapScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun sessionRecapTest() { | ||||
|         var saveCalled = false | ||||
|         var discardCalled = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             SessionRecapScreen( | ||||
|                 Modifier, | ||||
|                 SessionRecapActions( | ||||
|                     { | ||||
|                         SessionReport( | ||||
|                             "", | ||||
|                             0, | ||||
|                             Timestamp(0, 0), | ||||
|                             "") | ||||
|                     }, | ||||
|                     { saveCalled = true }, | ||||
|                     { discardCalled = true } | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 "You studied", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 "save", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 "discard", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         Assert.assertTrue(saveCalled) | ||||
|         Assert.assertTrue(discardCalled) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,52 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onAllNodesWithText | ||||
| import androidx.compose.ui.test.onNodeWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.screens.sign_up.SignUpActions | ||||
| import be.ugent.sel.studeez.screens.sign_up.SignUpScreen | ||||
| import be.ugent.sel.studeez.screens.sign_up.SignUpUiState | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class SignUpScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun signupScreenTest() { | ||||
|         var create = false | ||||
|         var login = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             SignUpScreen( | ||||
|                 uiState = SignUpUiState(), | ||||
|                 signUpActions = SignUpActions({}, {}, {}, {}, {create = true}, {login = true}) | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "log in", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onAllNodesWithText( | ||||
|                 text = "Create account", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             )[0] // First node has the button | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(login) | ||||
|         assert(create) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,40 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onAllNodesWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.screens.splash.SplashScreen | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class SplashScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun splashScreenTest() { | ||||
|         var tryAgain = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             SplashScreen( | ||||
|                 Modifier, | ||||
|                 {tryAgain = true}, | ||||
|                 true | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onAllNodesWithText( | ||||
|                 text = "try again", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             )[1] // Second node is the button | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(tryAgain) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,158 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onNodeWithContentDescription | ||||
| import androidx.compose.ui.test.onNodeWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.common.composable.DeleteButton | ||||
| import be.ugent.sel.studeez.common.composable.drawer.DrawerActions | ||||
| import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions | ||||
| import be.ugent.sel.studeez.data.local.models.task.Subject | ||||
| import be.ugent.sel.studeez.screens.subjects.SubjectScreen | ||||
| import be.ugent.sel.studeez.screens.subjects.SubjectUiState | ||||
| import be.ugent.sel.studeez.screens.subjects.form.SubjectForm | ||||
| import be.ugent.sel.studeez.screens.subjects.form.SubjectFormUiState | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class SubjectScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun addSubjectScreenTest() { | ||||
|         var confirm = false | ||||
|         var goback = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             SubjectForm( | ||||
|                 title = R.string.new_subject, | ||||
|                 goBack = {goback = true}, | ||||
|                 uiState = SubjectFormUiState(), | ||||
|                 onConfirm = {confirm = true}, | ||||
|                 onNameChange = {}, | ||||
|                 onColorChange = {}, | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "confirm", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription( | ||||
|                 label = "go back", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(confirm) | ||||
|         assert(goback) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun editSubjectScreenTest() { | ||||
|         var confirm = false | ||||
|         var delete = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             SubjectForm( | ||||
|                 title = R.string.edit_subject, | ||||
|                 goBack = {}, | ||||
|                 uiState = SubjectFormUiState( | ||||
|                     name = "Test Subject", | ||||
|                 ), | ||||
|                 onConfirm = {confirm = true}, | ||||
|                 onNameChange = {}, | ||||
|                 onColorChange = {}, | ||||
|             ) | ||||
|             DeleteButton(text = R.string.delete_subject) { | ||||
|                 delete = true | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "confirm", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "delete", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(confirm) | ||||
|         assert(delete) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun subjectScreenTest() { | ||||
|         var view = false | ||||
|         var add = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             SubjectScreen( | ||||
|                 drawerActions = DrawerActions({}, {}, {}, {}, {}), | ||||
|                 navigationBarActions = NavigationBarActions({false}, {}, {}, {}, {}, {}, {}, {}), | ||||
|                 onAddSubject = { add = true }, | ||||
|                 onViewSubject = { view = true }, | ||||
|                 getStudyTime = { flowOf() }, | ||||
|                 getCompletedTaskCount = { flowOf() }, | ||||
|                 getTaskCount = { flowOf() }, | ||||
|                 uiState = SubjectUiState.Succes( | ||||
|                     listOf( | ||||
|                         Subject( | ||||
|                             id = "", | ||||
|                             name = "Test Subject", | ||||
|                             argb_color = 0xFFFFD200, | ||||
|                             archived = false | ||||
|                         ) | ||||
|                     ) | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "view", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "new subject", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(add) | ||||
|         assert(view) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										160
									
								
								app/src/androidTest/java/be/ugent/sel/studeez/TaskScreenTest.kt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								app/src/androidTest/java/be/ugent/sel/studeez/TaskScreenTest.kt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,160 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onNodeWithContentDescription | ||||
| import androidx.compose.ui.test.onNodeWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.common.composable.DeleteButton | ||||
| 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.screens.tasks.TaskActions | ||||
| import be.ugent.sel.studeez.screens.tasks.TaskScreen | ||||
| import be.ugent.sel.studeez.screens.tasks.form.TaskForm | ||||
| import be.ugent.sel.studeez.screens.tasks.form.TaskFormUiState | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class TaskScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun addTaskScreenTest() { | ||||
|         var confirm = false | ||||
|         var goback = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             TaskForm( | ||||
|                 title = R.string.new_task, | ||||
|                 goBack = {goback = true}, | ||||
|                 uiState = TaskFormUiState(), | ||||
|                 onConfirm = {confirm = true}, | ||||
|                 onNameChange = {}, | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "confirm", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription( | ||||
|                 label = "go back", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(confirm) | ||||
|         assert(goback) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun editTaskScreenTest() { | ||||
|         var confirm = false | ||||
|         var delete = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             TaskForm( | ||||
|                 title = R.string.edit_task, | ||||
|                 goBack = {}, | ||||
|                 uiState = TaskFormUiState( | ||||
|                     name = "Test Task", | ||||
|                 ), | ||||
|                 onConfirm = {confirm = true}, | ||||
|                 onNameChange = {}, | ||||
|             ) { | ||||
|                 DeleteButton(text = R.string.delete_task) { | ||||
|                     delete = true | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "confirm", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "delete", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(confirm) | ||||
|         assert(delete) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun taskScreenTest() { | ||||
|         var add = false | ||||
|         var edit = false | ||||
|         var start = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             TaskScreen( | ||||
|                 goBack = {}, | ||||
|                 taskActions = TaskActions( | ||||
|                     {add = true}, | ||||
|                     { Subject(name = "Test Subject") }, | ||||
|                     { flowOf(listOf(Task())) }, | ||||
|                     { _, _ -> run {} }, | ||||
|                     {edit = true}, | ||||
|                     {start = true}, | ||||
|                     {}, | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithContentDescription( | ||||
|                 label = "edit", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "new", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "start", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(add) | ||||
|         assert(edit) | ||||
|         assert(start) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,58 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onNodeWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.common.composable.drawer.DrawerActions | ||||
| import be.ugent.sel.studeez.data.local.models.timer_info.EndlessTimerInfo | ||||
| import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewActions | ||||
| import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewScreen | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class TimerOverviewScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun timerOverviewScreenTest() { | ||||
|         var add = false | ||||
|         var edit = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             TimerOverviewScreen( | ||||
|                 timerOverviewActions = TimerOverviewActions( | ||||
|                     { flowOf(listOf(EndlessTimerInfo("", ""))) }, | ||||
|                     { listOf() }, | ||||
|                     {edit = true}, | ||||
|                     {add = true} | ||||
|                 ), | ||||
|                 drawerActions = DrawerActions({}, {}, {}, {}, {}) | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "add", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "edit", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(add) | ||||
|         assert(edit) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,40 @@ | |||
| package be.ugent.sel.studeez | ||||
| 
 | ||||
| import androidx.compose.ui.test.junit4.createComposeRule | ||||
| import androidx.compose.ui.test.onNodeWithText | ||||
| import androidx.compose.ui.test.performClick | ||||
| import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionActions | ||||
| import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionScreen | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class TimerSelectionScreenTest { | ||||
|     @get:Rule | ||||
|     val composeTestRule = createComposeRule() | ||||
| 
 | ||||
|     @Test | ||||
|     fun timerOverviewScreenTest() { | ||||
|         var start = false | ||||
| 
 | ||||
|         composeTestRule.setContent { | ||||
|             TimerSelectionScreen( | ||||
|                 timerSelectionActions = TimerSelectionActions({ flowOf()}, {start = true}, 0), | ||||
|                 popUp = {} | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composeTestRule.waitForIdle() | ||||
| 
 | ||||
|         composeTestRule | ||||
|             .onNodeWithText( | ||||
|                 text = "start", | ||||
|                 substring = true, | ||||
|                 ignoreCase = true | ||||
|             ) | ||||
|             .assertExists() | ||||
|             .performClick() | ||||
| 
 | ||||
|         assert(start) | ||||
|     } | ||||
| } | ||||
|  | @ -227,12 +227,14 @@ fun SearchField( | |||
|     onValueChange: (String) -> Unit, | ||||
|     onSubmit: () -> Unit, | ||||
|     @StringRes label: Int, | ||||
|     modifier: Modifier = Modifier | ||||
|     modifier: Modifier = Modifier, | ||||
|     enabled: Boolean = true | ||||
| ) { | ||||
|     OutlinedTextField( | ||||
|         value = value, | ||||
|         onValueChange = onValueChange, | ||||
|         modifier = modifier, | ||||
|         enabled = enabled, | ||||
|         label = { Text(text = stringResource(id = label)) }, | ||||
|         trailingIcon = { | ||||
|             IconButton(onClick = onSubmit) { | ||||
|  |  | |||
|  | @ -81,7 +81,7 @@ fun FeedWithElements( | |||
|                 Text( | ||||
|                     text = "${HoursMinutesSeconds(totalDayStudyTime)}", | ||||
|                     fontSize = 15.sp, | ||||
|                     fontWeight = FontWeight.Bold | ||||
|                     fontWeight = FontWeight.Medium | ||||
|                 ) | ||||
|             } | ||||
|             feedEntries.forEach { feedEntry -> | ||||
|  |  | |||
|  | @ -56,7 +56,7 @@ fun FeedEntry( | |||
|                     ) { | ||||
|                         Text( | ||||
|                             text = feedEntry.subJectName, | ||||
|                             fontWeight = FontWeight.Bold, | ||||
|                             fontWeight = FontWeight.Medium, | ||||
|                             overflow = TextOverflow.Ellipsis, | ||||
|                             maxLines = 1, | ||||
|                         ) | ||||
|  |  | |||
|  | @ -5,6 +5,9 @@ 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.PROFILE_SCREEN | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations.SEARCH_FRIENDS_SCREEN | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations.SELECT_SUBJECT | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations.SESSIONS_SCREEN | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations.SUBJECT_SCREEN | ||||
| import be.ugent.sel.studeez.screens.StudeezViewModel | ||||
| import dagger.hilt.android.lifecycle.HiltViewModel | ||||
|  | @ -33,13 +36,11 @@ class NavigationBarViewModel @Inject constructor( | |||
|     } | ||||
| 
 | ||||
|     fun onAddTaskClick(open: (String) -> Unit) { | ||||
|         // TODO open(CREATE_TASK_SCREEN) | ||||
|         SnackbarManager.showMessage(AppText.create_task_not_possible_yet) // TODO Remove | ||||
|         open(SELECT_SUBJECT) | ||||
|     } | ||||
| 
 | ||||
|     fun onAddFriendClick(open: (String) -> Unit) { | ||||
|         // TODO open(SEARCH_FRIENDS_SCREEN) | ||||
|         SnackbarManager.showMessage(AppText.add_friend_not_possible_yet) // TODO Remove | ||||
|         open(SEARCH_FRIENDS_SCREEN) | ||||
|     } | ||||
| 
 | ||||
|     fun onAddSessionClick(open: (String) -> Unit) { | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import androidx.compose.foundation.layout.* | |||
| import androidx.compose.foundation.shape.CircleShape | ||||
| import androidx.compose.material.Card | ||||
| import androidx.compose.material.Icon | ||||
| import androidx.compose.material.MaterialTheme | ||||
| import androidx.compose.material.Text | ||||
| import androidx.compose.material.icons.Icons | ||||
| import androidx.compose.material.icons.filled.List | ||||
|  | @ -30,10 +31,10 @@ import be.ugent.sel.studeez.R.string as AppText | |||
| @Composable | ||||
| fun SubjectEntry( | ||||
|     subject: Subject, | ||||
|     onViewSubject: () -> Unit, | ||||
|     getTaskCount: () -> Flow<Int>, | ||||
|     getCompletedTaskCount: () -> Flow<Int>, | ||||
|     getStudyTime: () -> Flow<Int>, | ||||
|     selectButton: @Composable (RowScope) -> Unit, | ||||
| ) { | ||||
|     val studytime by getStudyTime().collectAsState(initial = 0) | ||||
|     val taskCount by getTaskCount().collectAsState(initial = 0) | ||||
|  | @ -65,16 +66,17 @@ fun SubjectEntry( | |||
|                 ) { | ||||
|                     Text( | ||||
|                         text = subject.name, | ||||
|                         fontWeight = FontWeight.Bold, | ||||
|                         overflow = TextOverflow.Ellipsis, | ||||
|                         maxLines = 1, | ||||
|                         fontWeight = FontWeight.Medium | ||||
|                     ) | ||||
|                     Row( | ||||
|                         horizontalArrangement = Arrangement.spacedBy(10.dp), | ||||
|                         verticalAlignment = Alignment.CenterVertically, | ||||
|                         verticalAlignment = Alignment.CenterVertically | ||||
|                     ) { | ||||
|                         Text( | ||||
|                             text = HoursMinutesSeconds(studytime).toString(), | ||||
|                             color = MaterialTheme.colors.onBackground.copy(alpha = 0.6f) | ||||
|                         ) | ||||
|                         Row( | ||||
|                             verticalAlignment = Alignment.CenterVertically, | ||||
|  | @ -82,21 +84,18 @@ fun SubjectEntry( | |||
|                         ) { | ||||
|                             Icon( | ||||
|                                 imageVector = Icons.Default.List, | ||||
|                                 contentDescription = stringResource(id = AppText.tasks) | ||||
|                                 contentDescription = stringResource(id = AppText.tasks), | ||||
|                                 tint = MaterialTheme.colors.onBackground.copy(alpha = 0.6f) | ||||
|                             ) | ||||
|                             Text( | ||||
|                                 text = "${completedTaskCount}/${taskCount}", | ||||
|                                 color = MaterialTheme.colors.onBackground.copy(alpha = 0.6f) | ||||
|                             ) | ||||
|                             Text(text = "${completedTaskCount}/${taskCount}") | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             StealthButton( | ||||
|                 text = AppText.view_tasks, | ||||
|                 modifier = Modifier | ||||
|                     .padding(start = 10.dp, end = 5.dp) | ||||
|                     .weight(1f) | ||||
|             ) { | ||||
|                 onViewSubject() | ||||
|             } | ||||
|             selectButton(this) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -109,11 +108,16 @@ fun SubjectEntryPreview() { | |||
|             name = "Test Subject", | ||||
|             argb_color = 0xFFFFD200, | ||||
|         ), | ||||
|         onViewSubject = {}, | ||||
|         getTaskCount = { flowOf() }, | ||||
|         getCompletedTaskCount = { flowOf() }, | ||||
|         getStudyTime = { flowOf() }, | ||||
|     ) | ||||
|     ) { | ||||
|         StealthButton( | ||||
|             text = AppText.view_tasks, | ||||
|             modifier = Modifier | ||||
|                 .padding(start = 10.dp, end = 5.dp) | ||||
|         ) {} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
|  | @ -124,9 +128,8 @@ fun OverflowSubjectEntryPreview() { | |||
|             name = "Testttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt", | ||||
|             argb_color = 0xFFFFD200, | ||||
|         ), | ||||
|         onViewSubject = {}, | ||||
|         getTaskCount = { flowOf() }, | ||||
|         getCompletedTaskCount = { flowOf() }, | ||||
|         getStudyTime = { flowOf() }, | ||||
|     ) | ||||
|     ) {} | ||||
| } | ||||
|  | @ -5,6 +5,7 @@ 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.timer_functional.FunctionalTimer | ||||
| import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo | ||||
| import be.ugent.sel.studeez.domain.UserDAO | ||||
| import javax.inject.Inject | ||||
| import javax.inject.Singleton | ||||
| 
 | ||||
|  | @ -42,4 +43,11 @@ class SelectedSubject @Inject constructor() : SelectedState<Subject>() { | |||
| @Singleton | ||||
| class SelectedTimerInfo @Inject constructor() : SelectedState<TimerInfo>() { | ||||
|     override lateinit var value: TimerInfo | ||||
| } | ||||
| 
 | ||||
| @Singleton | ||||
| class SelectedUserId @Inject constructor( | ||||
|     userDAO: UserDAO | ||||
| ): SelectedState<String>() { | ||||
|     override var value: String = userDAO.getCurrentUserId() | ||||
| } | ||||
|  | @ -1,7 +1,6 @@ | |||
| package be.ugent.sel.studeez.data.local.models.task | ||||
| 
 | ||||
| import com.google.firebase.firestore.DocumentId | ||||
| import com.google.firebase.firestore.Exclude | ||||
| 
 | ||||
| data class Subject( | ||||
|     @DocumentId val id: String = "", | ||||
|  |  | |||
|  | @ -1,11 +1,10 @@ | |||
| package be.ugent.sel.studeez.domain.implementation | ||||
| 
 | ||||
| import androidx.compose.runtime.collectAsState | ||||
| import be.ugent.sel.studeez.common.snackbar.SnackbarManager | ||||
| import be.ugent.sel.studeez.data.local.models.Friendship | ||||
| import be.ugent.sel.studeez.data.remote.FirebaseFriendship.ACCEPTED | ||||
| import be.ugent.sel.studeez.data.remote.FirebaseFriendship.FRIENDSSINCE | ||||
| import be.ugent.sel.studeez.data.remote.FirebaseFriendship.FRIENDID | ||||
| import be.ugent.sel.studeez.data.remote.FirebaseFriendship.FRIENDSSINCE | ||||
| import be.ugent.sel.studeez.domain.AccountDAO | ||||
| import be.ugent.sel.studeez.domain.FriendshipDAO | ||||
| import be.ugent.sel.studeez.domain.implementation.FirebaseCollections.FRIENDS_COLLECTION | ||||
|  | @ -18,6 +17,7 @@ import kotlinx.coroutines.flow.Flow | |||
| import kotlinx.coroutines.flow.catch | ||||
| import kotlinx.coroutines.flow.flow | ||||
| import kotlinx.coroutines.flow.map | ||||
| import kotlinx.coroutines.tasks.await | ||||
| import javax.inject.Inject | ||||
| import kotlin.coroutines.resume | ||||
| import kotlin.coroutines.resumeWithException | ||||
|  | @ -75,24 +75,40 @@ class FirebaseFriendshipDAO @Inject constructor( | |||
|         val currentUserId: String = auth.currentUserId | ||||
|         val otherUserId: String = id | ||||
| 
 | ||||
|         // Add entry to current user | ||||
|         currentUserDocument() | ||||
|             .collection(FRIENDS_COLLECTION) | ||||
|             .add(mapOf( | ||||
|                 FRIENDID to otherUserId, | ||||
|                 ACCEPTED to true, // TODO Make it not automatically accepted. | ||||
|                 FRIENDSSINCE to Timestamp.now() | ||||
|             )) | ||||
| 
 | ||||
|         // Add entry to other user | ||||
|         // Check if the friendship already exists for the logged in user | ||||
|         var allowed = false | ||||
|         firestore.collection(USER_COLLECTION) | ||||
|             .document(otherUserId) | ||||
|             .document(currentUserId) | ||||
|             .collection(FRIENDS_COLLECTION) | ||||
|             .add(mapOf( | ||||
|                 FRIENDID to currentUserId, | ||||
|                 ACCEPTED to true, // TODO Make it not automatically accepted. | ||||
|                 FRIENDSSINCE to Timestamp.now() | ||||
|             )) | ||||
|             .whereEqualTo(FRIENDID, otherUserId) | ||||
|             .get() | ||||
|             .addOnSuccessListener { | ||||
|                 allowed = it.documents.isEmpty() | ||||
| 
 | ||||
|                 if (allowed) { | ||||
|                     // Add entry to current user | ||||
|                     currentUserDocument() | ||||
|                         .collection(FRIENDS_COLLECTION) | ||||
|                         .add(mapOf( | ||||
|                             FRIENDID to otherUserId, | ||||
|                             ACCEPTED to true, // TODO Make it not automatically accepted. | ||||
|                             FRIENDSSINCE to Timestamp.now() | ||||
|                         )) | ||||
| 
 | ||||
|                     // Add entry to other user | ||||
|                     firestore.collection(USER_COLLECTION) | ||||
|                         .document(otherUserId) | ||||
|                         .collection(FRIENDS_COLLECTION) | ||||
|                         .add(mapOf( | ||||
|                             FRIENDID to currentUserId, | ||||
|                             ACCEPTED to true, // TODO Make it not automatically accepted. | ||||
|                             FRIENDSSINCE to Timestamp.now() | ||||
|                         )) | ||||
|                 } | ||||
|             }.addOnSuccessListener { | ||||
|                 val message = if (allowed) AppText.success else AppText.already_friend | ||||
|                 SnackbarManager.showMessage(message) | ||||
|             } | ||||
| 
 | ||||
|         return true | ||||
|     } | ||||
|  |  | |||
|  | @ -94,4 +94,4 @@ class FirebaseSubjectDAO @Inject constructor( | |||
| 
 | ||||
|     fun Query.subjectNotArchived(): Query = | ||||
|         this.whereEqualTo(SubjectDocument.archived, false) | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ object StudeezDestinations { | |||
|     const val EDIT_SUBJECT_FORM = "edit_subject" | ||||
|     const val TASKS_SCREEN = "tasks" | ||||
|     const val ADD_TASK_FORM = "add_task" | ||||
|     const val SELECT_SUBJECT = "select_subject" | ||||
|     const val EDIT_TASK_FORM = "edit_task" | ||||
| 
 | ||||
|     // Friends flow | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ import be.ugent.sel.studeez.screens.splash.SplashRoute | |||
| import be.ugent.sel.studeez.screens.subjects.SubjectRoute | ||||
| import be.ugent.sel.studeez.screens.subjects.form.SubjectCreateRoute | ||||
| import be.ugent.sel.studeez.screens.subjects.form.SubjectEditRoute | ||||
| import be.ugent.sel.studeez.screens.subjects.select.SubjectSelectionRoute | ||||
| import be.ugent.sel.studeez.screens.tasks.TaskRoute | ||||
| import be.ugent.sel.studeez.screens.tasks.form.TaskCreateRoute | ||||
| import be.ugent.sel.studeez.screens.tasks.form.TaskEditRoute | ||||
|  | @ -69,7 +70,7 @@ fun StudeezNavGraph( | |||
|         // NavBar | ||||
|         composable(StudeezDestinations.HOME_SCREEN) { | ||||
|             HomeRoute( | ||||
|                 open, | ||||
|                 open = open, | ||||
|                 drawerActions = drawerActions, | ||||
|                 navigationBarActions = navigationBarActions, | ||||
|                 feedViewModel = hiltViewModel(), | ||||
|  | @ -86,6 +87,14 @@ fun StudeezNavGraph( | |||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composable(StudeezDestinations.SELECT_SUBJECT) { | ||||
|             SubjectSelectionRoute( | ||||
|                 open = { openAndPopUp(it, StudeezDestinations.SELECT_SUBJECT) }, | ||||
|                 goBack = goBack, | ||||
|                 viewModel = hiltViewModel(), | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         composable(StudeezDestinations.ADD_SUBJECT_FORM) { | ||||
|             SubjectCreateRoute( | ||||
|                 goBack = goBack, | ||||
|  | @ -104,7 +113,7 @@ fun StudeezNavGraph( | |||
| 
 | ||||
|         composable(StudeezDestinations.TASKS_SCREEN) { | ||||
|             TaskRoute( | ||||
|                 goBack = goBack, | ||||
|                 goBack = { openAndPopUp(StudeezDestinations.SUBJECT_SCREEN, StudeezDestinations.TASKS_SCREEN) }, | ||||
|                 open = open, | ||||
|                 viewModel = hiltViewModel(), | ||||
|             ) | ||||
|  |  | |||
|  | @ -1,15 +1,14 @@ | |||
| package be.ugent.sel.studeez.screens.friends.friends_overview | ||||
| 
 | ||||
| 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.* | ||||
| import androidx.compose.material.icons.Icons | ||||
| import androidx.compose.material.icons.filled.ArrowBack | ||||
| import androidx.compose.material.icons.filled.Delete | ||||
| import androidx.compose.material.icons.filled.Person | ||||
| import androidx.compose.material.icons.filled.Search | ||||
| import androidx.compose.runtime.* | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
|  | @ -23,7 +22,6 @@ import androidx.compose.ui.unit.sp | |||
| import be.ugent.sel.studeez.R | ||||
| import be.ugent.sel.studeez.common.composable.BasicButton | ||||
| import be.ugent.sel.studeez.common.composable.ProfilePicture | ||||
| import be.ugent.sel.studeez.common.composable.SearchField | ||||
| import be.ugent.sel.studeez.common.composable.drawer.DrawerEntry | ||||
| import be.ugent.sel.studeez.common.ext.basicButton | ||||
| import be.ugent.sel.studeez.data.local.models.Friendship | ||||
|  | @ -89,13 +87,32 @@ fun FriendsOverviewScreen( | |||
|         topBar = { | ||||
|             TopAppBar( | ||||
|                 title = { | ||||
|                     // TODO Link to each other | ||||
|                     SearchField( | ||||
|                         value = uiState.queryString, | ||||
|                         onValueChange = friendsOverviewActions.onQueryStringChange, | ||||
|                         onSubmit = friendsOverviewActions.onSubmit, | ||||
|                         label = AppText.search_friends | ||||
|                     ) | ||||
|                     // TODO Make search field | ||||
| //                    SearchField( | ||||
| //                        value = uiState.queryString, | ||||
| //                        onValueChange = friendsOverviewActions.onQueryStringChange, | ||||
| //                        onSubmit = friendsOverviewActions.onSubmit, | ||||
| //                        label = AppText.search_friends, | ||||
| //                        enabled = false | ||||
| //                    ) | ||||
|                         IconButton( | ||||
|                             onClick = friendsOverviewActions.onSubmit, | ||||
| //                            modifier = Modifier.background( | ||||
| //                                color = MaterialTheme.colors.background | ||||
| //                            ), | ||||
|                         ) { | ||||
|                             Row { | ||||
|                                 Text( | ||||
|                                     text = stringResource(id = AppText.click_search_friends), | ||||
|                                     color = MaterialTheme.colors.onPrimary | ||||
|                                 ) | ||||
|                                 Icon( | ||||
|                                     imageVector = Icons.Default.Search, | ||||
|                                     contentDescription = stringResource(AppText.search_friends), | ||||
|                                     tint = MaterialTheme.colors.onPrimary | ||||
|                                 ) | ||||
|                             } | ||||
|                         } | ||||
|                 }, | ||||
|                 navigationIcon = { | ||||
|                     IconButton(onClick = popUp) { | ||||
|  | @ -162,49 +179,52 @@ fun FriendsEntry( | |||
|     viewProfile: (String) -> Unit, | ||||
|     removeFriend: (Friendship) -> Unit | ||||
| ) { | ||||
|     Row ( | ||||
|         modifier = Modifier | ||||
|             .fillMaxWidth() | ||||
|             .padding(horizontal = 15.dp, vertical = 7.dp), | ||||
|     ) { | ||||
|         Box( | ||||
|             modifier = Modifier | ||||
|                 .padding(vertical = 4.dp) | ||||
|         ) { | ||||
|             ProfilePicture() | ||||
|         } | ||||
| 
 | ||||
|         Box ( | ||||
|     Card { | ||||
|         Row ( | ||||
|             modifier = Modifier | ||||
|                 .fillMaxWidth() | ||||
|                 .padding(horizontal = 15.dp, vertical = 7.dp), | ||||
|             horizontalArrangement = Arrangement.spacedBy(15.dp) | ||||
|         ) { | ||||
|             Column ( | ||||
|             Box( | ||||
|                 modifier = Modifier | ||||
|                     .padding(vertical = 4.dp) | ||||
|             ) { | ||||
|                 Text( | ||||
|                     text = user.username, | ||||
|                     fontSize = 16.sp, | ||||
|                     maxLines = 1, | ||||
|                     overflow = TextOverflow.Ellipsis | ||||
|                 ) | ||||
|                 Text( | ||||
|                     text = "${resources().getString(AppText.app_name)} ${resources().getString(AppText.friend)}", | ||||
|                     fontSize = 14.sp, | ||||
|                     maxLines = 1, | ||||
|                     overflow = TextOverflow.Ellipsis | ||||
|                 ) | ||||
|                 ProfilePicture() | ||||
|             } | ||||
| 
 | ||||
|             Box( | ||||
|                 modifier = Modifier.fillMaxWidth(), | ||||
|                 contentAlignment = Alignment.CenterEnd | ||||
|             Box ( | ||||
|                 modifier = Modifier | ||||
|                     .fillMaxWidth() | ||||
|             ) { | ||||
|                 FriendsOverviewDropDown( | ||||
|                     friendship = friendship, | ||||
|                     viewProfile = viewProfile, | ||||
|                     removeFriend = removeFriend | ||||
|                 ) | ||||
|                 Column ( | ||||
|                     modifier = Modifier | ||||
|                         .padding(vertical = 4.dp) | ||||
|                 ) { | ||||
|                     Text( | ||||
|                         text = user.username, | ||||
|                         fontSize = 16.sp, | ||||
|                         maxLines = 1, | ||||
|                         overflow = TextOverflow.Ellipsis | ||||
|                     ) | ||||
|                     Text( | ||||
|                         text = "${resources().getString(AppText.app_name)} ${resources().getString(AppText.friend)}", | ||||
|                         fontSize = 14.sp, | ||||
|                         maxLines = 1, | ||||
|                         overflow = TextOverflow.Ellipsis | ||||
|                     ) | ||||
|                 } | ||||
| 
 | ||||
|                 Box( | ||||
|                     modifier = Modifier.fillMaxWidth(), | ||||
|                     contentAlignment = Alignment.CenterEnd | ||||
|                 ) { | ||||
|                     FriendsOverviewDropDown( | ||||
|                         friendship = friendship, | ||||
|                         viewProfile = viewProfile, | ||||
|                         removeFriend = removeFriend | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| package be.ugent.sel.studeez.screens.friends.friends_overview | ||||
| 
 | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| import be.ugent.sel.studeez.data.SelectedUserId | ||||
| import be.ugent.sel.studeez.data.local.models.Friendship | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import be.ugent.sel.studeez.domain.FriendshipDAO | ||||
|  | @ -8,7 +9,6 @@ import be.ugent.sel.studeez.domain.LogService | |||
| import be.ugent.sel.studeez.domain.UserDAO | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||
| import be.ugent.sel.studeez.screens.StudeezViewModel | ||||
| import be.ugent.sel.studeez.screens.profile.public_profile.SelectedProfileState | ||||
| import dagger.hilt.android.lifecycle.HiltViewModel | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.combine | ||||
|  | @ -19,12 +19,12 @@ import javax.inject.Inject | |||
| class FriendsOverviewViewModel @Inject constructor( | ||||
|     private val userDAO: UserDAO, | ||||
|     private val friendshipDAO: FriendshipDAO, | ||||
|     private val selectedProfileState: SelectedProfileState, | ||||
|     private val selectedUserIdState: SelectedUserId, | ||||
|     logService: LogService | ||||
| ) : StudeezViewModel(logService) { | ||||
| 
 | ||||
|     var uiState = mutableStateOf(FriendsOverviewUiState( | ||||
|         userId = selectedProfileState.selectedUserId | ||||
|         userId = selectedUserIdState.value | ||||
|     )) | ||||
|         private set | ||||
| 
 | ||||
|  | @ -63,7 +63,7 @@ class FriendsOverviewViewModel @Inject constructor( | |||
|         userId: String, | ||||
|         open: (String) -> Unit | ||||
|     ) { | ||||
|         selectedProfileState.selectedUserId = userId | ||||
|         selectedUserIdState.value = userId | ||||
|         open(StudeezDestinations.PUBLIC_PROFILE_SCREEN) | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ import androidx.compose.material.* | |||
| import androidx.compose.material.icons.Icons | ||||
| import androidx.compose.material.icons.filled.ArrowBack | ||||
| import androidx.compose.material.icons.filled.Person | ||||
| import androidx.compose.material.icons.filled.Search | ||||
| import androidx.compose.runtime.* | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
|  | @ -82,14 +83,16 @@ fun SearchFriendsScreen( | |||
|         topBar = { | ||||
|             TopAppBar( | ||||
|                 title = { | ||||
|                     SearchField( | ||||
|                         value = query, | ||||
|                         onValueChange = { newValue -> | ||||
|                             searchFriendsActions.onQueryStringChange(newValue) | ||||
|                             query = newValue | ||||
|                         }, | ||||
|                         onSubmit = { }, | ||||
|                         label = AppText.search_friends | ||||
|                     // TODO Make search field | ||||
| //                    SearchField( | ||||
| //                        value = uiState.queryString, | ||||
| //                        onValueChange = friendsOverviewActions.onQueryStringChange, | ||||
| //                        onSubmit = friendsOverviewActions.onSubmit, | ||||
| //                        label = AppText.search_friends, | ||||
| //                        enabled = false | ||||
| //                    ) | ||||
|                     Text( | ||||
|                         text = stringResource(id = AppText.searching_friends) | ||||
|                     ) | ||||
|                 }, | ||||
|                 navigationIcon = { | ||||
|  |  | |||
|  | @ -1,22 +1,22 @@ | |||
| package be.ugent.sel.studeez.screens.friends.friends_search | ||||
| 
 | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| import be.ugent.sel.studeez.data.SelectedUserId | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import be.ugent.sel.studeez.data.remote.FirebaseUser | ||||
| import be.ugent.sel.studeez.domain.LogService | ||||
| import be.ugent.sel.studeez.domain.UserDAO | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||
| import be.ugent.sel.studeez.screens.StudeezViewModel | ||||
| import be.ugent.sel.studeez.screens.profile.public_profile.SelectedProfileState | ||||
| import dagger.hilt.android.lifecycle.HiltViewModel | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.filter | ||||
| import kotlinx.coroutines.flow.map | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| @HiltViewModel | ||||
| class SearchFriendsViewModel @Inject constructor( | ||||
|     private val userDAO: UserDAO, | ||||
|     private val selectedProfileState: SelectedProfileState, | ||||
|     private val selectedProfileState: SelectedUserId, | ||||
|     logService: LogService | ||||
| ): StudeezViewModel(logService) { | ||||
| 
 | ||||
|  | @ -49,8 +49,8 @@ class SearchFriendsViewModel @Inject constructor( | |||
|      */ | ||||
|     fun getAllUsers(): Flow<List<User>> { | ||||
|         return userDAO.getAllUsers() | ||||
|             .filter { users -> | ||||
|                 users.any { user -> | ||||
|             .map { users -> | ||||
|                 users.filter { user -> | ||||
|                     user.id != userDAO.getCurrentUserId() | ||||
|                 } | ||||
|             } | ||||
|  | @ -60,7 +60,7 @@ class SearchFriendsViewModel @Inject constructor( | |||
|         userId: String, | ||||
|         open: (String) -> Unit | ||||
|     ) { | ||||
|         selectedProfileState.selectedUserId = userId | ||||
|         selectedProfileState.value = userId | ||||
|         open(StudeezDestinations.PUBLIC_PROFILE_SCREEN) | ||||
|     } | ||||
| } | ||||
|  | @ -18,6 +18,7 @@ import be.ugent.sel.studeez.R | |||
| import be.ugent.sel.studeez.common.composable.Headline | ||||
| import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate | ||||
| import be.ugent.sel.studeez.common.composable.drawer.DrawerEntry | ||||
| import be.ugent.sel.studeez.common.snackbar.SnackbarManager | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import be.ugent.sel.studeez.resources | ||||
| import be.ugent.sel.studeez.screens.profile.AmountOfFriendsButton | ||||
|  | @ -30,7 +31,7 @@ data class PublicProfileActions( | |||
|     val getUserDetails: () -> Flow<User>, | ||||
|     val getAmountOfFriends: () -> Flow<Int>, | ||||
|     val onViewFriendsClick: () -> Unit, | ||||
|     val sendFriendRequest: () -> Boolean | ||||
|     val sendFriendRequest: () -> Unit | ||||
| ) | ||||
| 
 | ||||
| fun getPublicProfileActions( | ||||
|  | @ -43,9 +44,11 @@ fun getPublicProfileActions( | |||
|             userId = viewModel.uiState.value.userId | ||||
|         ) }, | ||||
|         onViewFriendsClick = { viewModel.onViewFriendsClick(open) }, | ||||
|         sendFriendRequest = { viewModel.sendFriendRequest( | ||||
|             userId = viewModel.uiState.value.userId | ||||
|         ) } | ||||
|         sendFriendRequest = { | ||||
|             viewModel.sendFriendRequest( | ||||
|                 userId = viewModel.uiState.value.userId | ||||
|             ) | ||||
|         } | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
|  | @ -129,7 +132,7 @@ fun PublicProfilePreview() { | |||
|                 }, | ||||
|                 getAmountOfFriends = { flowOf(113) }, | ||||
|                 onViewFriendsClick = {}, | ||||
|                 sendFriendRequest = { true } | ||||
|                 sendFriendRequest = {} | ||||
|             ), | ||||
|             popUp = {} | ||||
|         ) | ||||
|  | @ -138,7 +141,7 @@ fun PublicProfilePreview() { | |||
| 
 | ||||
| @Composable | ||||
| fun PublicProfileEllipsis( | ||||
|     sendFriendRequest: () -> Boolean | ||||
|     sendFriendRequest: () -> Unit | ||||
| ) { | ||||
|     var expanded by remember { mutableStateOf(false) } | ||||
| 
 | ||||
|  | @ -147,8 +150,7 @@ fun PublicProfileEllipsis( | |||
|     ) { | ||||
|         Icon( | ||||
|             imageVector = ImageVector.vectorResource(id = R.drawable.ic_more_horizontal), | ||||
|             contentDescription = resources().getString(AppText.view_more), | ||||
|             modifier = Modifier.fillMaxSize() | ||||
|             contentDescription = resources().getString(AppText.view_more) | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|  | @ -172,7 +174,7 @@ fun PublicProfileEllipsis( | |||
| fun PublicProfileEllipsisPreview() { | ||||
|     StudeezTheme { | ||||
|         PublicProfileEllipsis( | ||||
|             sendFriendRequest = { true } | ||||
|             sendFriendRequest = {} | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|  | @ -1,6 +1,8 @@ | |||
| package be.ugent.sel.studeez.screens.profile.public_profile | ||||
| 
 | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| import be.ugent.sel.studeez.common.snackbar.SnackbarManager | ||||
| import be.ugent.sel.studeez.data.SelectedUserId | ||||
| import be.ugent.sel.studeez.data.local.models.User | ||||
| import be.ugent.sel.studeez.domain.FriendshipDAO | ||||
| import be.ugent.sel.studeez.domain.LogService | ||||
|  | @ -9,20 +11,20 @@ import be.ugent.sel.studeez.navigation.StudeezDestinations | |||
| import be.ugent.sel.studeez.screens.StudeezViewModel | ||||
| import dagger.hilt.android.lifecycle.HiltViewModel | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.selects.select | ||||
| import javax.inject.Inject | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
| 
 | ||||
| @HiltViewModel | ||||
| class PublicProfileViewModel @Inject constructor( | ||||
|     private val userDAO: UserDAO, | ||||
|     private val friendshipDAO: FriendshipDAO, | ||||
|     selectedProfileState: SelectedProfileState, | ||||
|     selectedUserIdState: SelectedUserId, | ||||
|     logService: LogService | ||||
| ): StudeezViewModel(logService) { | ||||
| 
 | ||||
|     val uiState = mutableStateOf( | ||||
|         PublicProfileUiState( | ||||
|             userId = selectedProfileState.selectedUserId | ||||
|             userId = selectedUserIdState.value | ||||
|         ) | ||||
|     ) | ||||
| 
 | ||||
|  | @ -53,8 +55,8 @@ class PublicProfileViewModel @Inject constructor( | |||
| 
 | ||||
|     fun sendFriendRequest( | ||||
|         userId: String | ||||
|     ): Boolean { | ||||
|         return friendshipDAO.sendFriendshipRequest(userId) | ||||
|     ) { | ||||
|         friendshipDAO.sendFriendshipRequest(userId) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,12 +0,0 @@ | |||
| package be.ugent.sel.studeez.screens.profile.public_profile | ||||
| 
 | ||||
| import be.ugent.sel.studeez.domain.UserDAO | ||||
| import javax.inject.Inject | ||||
| import javax.inject.Singleton | ||||
| 
 | ||||
| @Singleton | ||||
| class SelectedProfileState @Inject constructor( | ||||
|     userDAO: UserDAO | ||||
| ) { | ||||
|     var selectedUserId: String = userDAO.getCurrentUserId() | ||||
| } | ||||
|  | @ -1,10 +1,6 @@ | |||
| package be.ugent.sel.studeez.screens.session | ||||
| 
 | ||||
| import android.annotation.SuppressLint | ||||
| import android.content.Context | ||||
| import android.media.MediaPlayer | ||||
| import android.media.RingtoneManager | ||||
| import android.net.Uri | ||||
| import kotlinx.coroutines.delay | ||||
| import javax.inject.Singleton | ||||
| import kotlin.time.Duration.Companion.seconds | ||||
|  | @ -14,10 +10,8 @@ object InvisibleSessionManager { | |||
|     private var viewModel: SessionViewModel? = null | ||||
|     private lateinit var mediaPlayer: MediaPlayer | ||||
| 
 | ||||
|     fun setParameters(viewModel: SessionViewModel, context: Context) { | ||||
|         val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) | ||||
|         this.mediaPlayer = MediaPlayer.create(context, uri) | ||||
|         this.mediaPlayer.isLooping = false | ||||
|     fun setParameters(viewModel: SessionViewModel, mediaPlayer: MediaPlayer) { | ||||
|         this.mediaPlayer = mediaPlayer | ||||
|         this.viewModel = viewModel | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,8 @@ | |||
| package be.ugent.sel.studeez.screens.session | ||||
| 
 | ||||
| import android.media.MediaPlayer | ||||
| import android.media.RingtoneManager | ||||
| import android.net.Uri | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.platform.LocalContext | ||||
| import be.ugent.sel.studeez.data.local.models.timer_functional.FunctionalTimer | ||||
|  | @ -28,8 +31,11 @@ fun SessionRoute( | |||
|     openAndPopUp: (String, String) -> Unit, | ||||
|     viewModel: SessionViewModel, | ||||
| ) { | ||||
|     val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) | ||||
|     val mediaPlayer = MediaPlayer.create(LocalContext.current, uri) | ||||
|     mediaPlayer.isLooping = false | ||||
| 
 | ||||
|     InvisibleSessionManager.setParameters(viewModel = viewModel, context = LocalContext.current) | ||||
|     InvisibleSessionManager.setParameters(viewModel = viewModel, mediaPlayer = mediaPlayer) | ||||
| 
 | ||||
|     val soundPlayer = SoundPlayer(LocalContext.current) | ||||
|     val sessionActions = getSessionActions(viewModel, openAndPopUp) | ||||
|  |  | |||
|  | @ -15,10 +15,12 @@ import androidx.compose.ui.tooling.preview.Preview | |||
| import androidx.compose.ui.unit.dp | ||||
| import be.ugent.sel.studeez.common.composable.NewTaskSubjectButton | ||||
| import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate | ||||
| import be.ugent.sel.studeez.common.composable.StealthButton | ||||
| import be.ugent.sel.studeez.common.composable.drawer.DrawerActions | ||||
| import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions | ||||
| import be.ugent.sel.studeez.common.composable.tasks.SubjectEntry | ||||
| import be.ugent.sel.studeez.data.local.models.task.Subject | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
|  | @ -35,11 +37,11 @@ fun SubjectRoute( | |||
|         drawerActions = drawerActions, | ||||
|         navigationBarActions = navigationBarActions, | ||||
|         onAddSubject = { viewModel.onAddSubject(open) }, | ||||
|         onViewSubject = { viewModel.onViewSubject(it, open) }, | ||||
|         onViewSubject = { viewModel.onSelectSubject(it) { open(StudeezDestinations.TASKS_SCREEN) } }, | ||||
|         getTaskCount = viewModel::getTaskCount, | ||||
|         getCompletedTaskCount = viewModel::getCompletedTaskCount, | ||||
|         getStudyTime = viewModel::getStudyTime, | ||||
|         uiState, | ||||
|         uiState = uiState, | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
|  | @ -76,14 +78,22 @@ fun SubjectScreen( | |||
|                 ) { | ||||
|                     NewTaskSubjectButton(onClick = onAddSubject, AppText.new_subject) | ||||
|                     LazyColumn { | ||||
|                         items(uiState.subjects) { | ||||
|                         items(uiState.subjects) { subject -> | ||||
|                             SubjectEntry( | ||||
|                                 subject = it, | ||||
|                                 onViewSubject = { onViewSubject(it) }, | ||||
|                                 getTaskCount = { getTaskCount(it) }, | ||||
|                                 getCompletedTaskCount = { getCompletedTaskCount(it) }, | ||||
|                                 getStudyTime = { getStudyTime(it) }, | ||||
|                             ) | ||||
|                                 subject = subject, | ||||
|                                 getTaskCount = { getTaskCount(subject) }, | ||||
|                                 getCompletedTaskCount = { getCompletedTaskCount(subject) }, | ||||
|                                 getStudyTime = { getStudyTime(subject) }, | ||||
|                             ) { | ||||
|                                 StealthButton( | ||||
|                                     text = AppText.view_tasks, | ||||
|                                     modifier = Modifier | ||||
|                                         .padding(start = 10.dp, end = 5.dp) | ||||
|                                         .weight(1f) | ||||
|                                 ) { | ||||
|                                     onViewSubject(subject) | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  |  | |||
|  | @ -42,8 +42,8 @@ class SubjectViewModel @Inject constructor( | |||
|         return subjectDAO.getStudyTime(subject) | ||||
|     } | ||||
| 
 | ||||
|     fun onViewSubject(subject: Subject, open: (String) -> Unit) { | ||||
|     fun onSelectSubject(subject: Subject, open: () -> Unit) { | ||||
|         selectedSubject.set(subject) | ||||
|         open(StudeezDestinations.TASKS_SCREEN) | ||||
|         open() | ||||
|     } | ||||
| } | ||||
|  | @ -18,7 +18,6 @@ import be.ugent.sel.studeez.common.composable.BasicButton | |||
| import be.ugent.sel.studeez.common.composable.DeleteButton | ||||
| import be.ugent.sel.studeez.common.composable.FormComposable | ||||
| import be.ugent.sel.studeez.common.composable.LabelledInputField | ||||
| import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate | ||||
| import be.ugent.sel.studeez.common.ext.basicButton | ||||
| import be.ugent.sel.studeez.common.ext.fieldModifier | ||||
| import be.ugent.sel.studeez.common.ext.generateRandomArgb | ||||
|  |  | |||
|  | @ -2,8 +2,6 @@ package be.ugent.sel.studeez.screens.subjects.form | |||
| 
 | ||||
| import androidx.compose.runtime.MutableState | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| import androidx.compose.ui.graphics.Color | ||||
| import be.ugent.sel.studeez.common.ext.generateRandomArgb | ||||
| import be.ugent.sel.studeez.data.SelectedSubject | ||||
| import be.ugent.sel.studeez.data.local.models.task.Subject | ||||
| import be.ugent.sel.studeez.domain.LogService | ||||
|  |  | |||
|  | @ -0,0 +1,128 @@ | |||
| package be.ugent.sel.studeez.screens.subjects.select | ||||
| 
 | ||||
| import androidx.compose.foundation.layout.* | ||||
| import androidx.compose.foundation.lazy.LazyColumn | ||||
| import androidx.compose.foundation.lazy.items | ||||
| import androidx.compose.material.CircularProgressIndicator | ||||
| import androidx.compose.material.MaterialTheme | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.collectAsState | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.res.stringResource | ||||
| 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.SecondaryScreenTemplate | ||||
| import be.ugent.sel.studeez.common.composable.StealthButton | ||||
| import be.ugent.sel.studeez.common.composable.tasks.SubjectEntry | ||||
| import be.ugent.sel.studeez.data.local.models.task.Subject | ||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||
| import be.ugent.sel.studeez.screens.subjects.SubjectUiState | ||||
| import be.ugent.sel.studeez.screens.subjects.SubjectViewModel | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.flowOf | ||||
| 
 | ||||
| @Composable | ||||
| fun SubjectSelectionRoute( | ||||
|     open: (String) -> Unit, | ||||
|     goBack: () -> Unit, | ||||
|     viewModel: SubjectViewModel, | ||||
| ) { | ||||
|     val uiState by viewModel.uiState.collectAsState() | ||||
|     SubjectSelectionScreen( | ||||
|         onViewSubject = { viewModel.onSelectSubject(it) { open(StudeezDestinations.ADD_TASK_FORM) } }, | ||||
|         getTaskCount = viewModel::getTaskCount, | ||||
|         getCompletedTaskCount = viewModel::getCompletedTaskCount, | ||||
|         getStudyTime = viewModel::getStudyTime, | ||||
|         goBack = goBack, | ||||
|         uiState = uiState, | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Composable | ||||
| fun SubjectSelectionScreen( | ||||
|     goBack: () -> Unit, | ||||
|     onViewSubject: (Subject) -> Unit, | ||||
|     getTaskCount: (Subject) -> Flow<Int>, | ||||
|     getCompletedTaskCount: (Subject) -> Flow<Int>, | ||||
|     getStudyTime: (Subject) -> Flow<Int>, | ||||
|     uiState: SubjectUiState, | ||||
| ) { | ||||
|     SecondaryScreenTemplate( | ||||
|         title = stringResource(R.string.select_subject_title), | ||||
|         barAction = {}, | ||||
|         popUp = goBack, | ||||
|     ) { | ||||
|         when (uiState) { | ||||
|             SubjectUiState.Loading -> Column( | ||||
|                 modifier = Modifier | ||||
|                     .fillMaxWidth() | ||||
|                     .fillMaxHeight(), | ||||
|                 verticalArrangement = Arrangement.Center, | ||||
|                 horizontalAlignment = Alignment.CenterHorizontally | ||||
|             ) { | ||||
|                 CircularProgressIndicator(color = MaterialTheme.colors.onBackground) | ||||
|             } | ||||
|             is SubjectUiState.Succes -> { | ||||
|                 Column( | ||||
|                     modifier = Modifier.padding(top = 5.dp) | ||||
|                 ) { | ||||
|                     LazyColumn { | ||||
|                         items(uiState.subjects) { subject -> | ||||
|                             SubjectEntry( | ||||
|                                 subject = subject, | ||||
|                                 getTaskCount = { getTaskCount(subject) }, | ||||
|                                 getCompletedTaskCount = { getCompletedTaskCount(subject) }, | ||||
|                                 getStudyTime = { getStudyTime(subject) }, | ||||
|                             ) { | ||||
|                                 StealthButton( | ||||
|                                     text = R.string.select_subject, | ||||
|                                     modifier = Modifier | ||||
|                                         .padding(start = 4.dp, end = 4.dp) | ||||
|                                         .weight(1f) | ||||
|                                 ) { | ||||
|                                     onViewSubject(subject) | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun SubjectScreenPreview() { | ||||
|     SubjectSelectionScreen( | ||||
|         goBack = {}, | ||||
|         onViewSubject = {}, | ||||
|         getTaskCount = { flowOf() }, | ||||
|         getCompletedTaskCount = { flowOf() }, | ||||
|         getStudyTime = { flowOf() }, | ||||
|         uiState = SubjectUiState.Succes( | ||||
|             listOf( | ||||
|                 Subject( | ||||
|                     name = "Test Subject", | ||||
|                     argb_color = 0xFFFFD200, | ||||
|                 ) | ||||
|             ) | ||||
|         ) | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun SubjectScreenLoadingPreview() { | ||||
|     SubjectSelectionScreen( | ||||
|         goBack = {}, | ||||
|         onViewSubject = {}, | ||||
|         getTaskCount = { flowOf() }, | ||||
|         getCompletedTaskCount = { flowOf() }, | ||||
|         getStudyTime = { flowOf() }, | ||||
|         uiState = SubjectUiState.Loading, | ||||
|     ) | ||||
| } | ||||
|  | @ -4,7 +4,6 @@ import androidx.annotation.StringRes | |||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import be.ugent.sel.studeez.common.composable.DeleteButton | ||||
| import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate | ||||
| import be.ugent.sel.studeez.common.composable.FormComposable | ||||
| import be.ugent.sel.studeez.data.local.models.timer_info.TimerInfo | ||||
| import be.ugent.sel.studeez.R.string as AppText | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ import androidx.compose.runtime.Composable | |||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.compose.ui.tooling.preview.Preview | ||||
| import androidx.compose.ui.unit.dp | ||||
| import androidx.hilt.navigation.compose.hiltViewModel | ||||
| import be.ugent.sel.studeez.common.composable.SecondaryScreenTemplate | ||||
|  | @ -46,4 +47,13 @@ fun TimerTypeSelectScreen( | |||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @Preview | ||||
| @Composable | ||||
| fun TimerTypeSelectScreenPreview() { | ||||
|     TimerTypeSelectScreen( | ||||
|         open = {}, | ||||
|         popUp = {} | ||||
|     ) | ||||
| } | ||||
|  | @ -43,6 +43,7 @@ | |||
|     <string name="tasks">Tasks</string> | ||||
|     <string name="task">Task</string> | ||||
|     <string name="my_subjects">My Subjects</string> | ||||
|     <string name="select_subject_title">Select Subject</string> | ||||
|     <string name="new_subject">New Subject</string> | ||||
|     <string name="new_task">New Task</string> | ||||
|     <string name="edit_subject">Edit Subject</string> | ||||
|  | @ -50,6 +51,7 @@ | |||
|     <string name="delete_subject">Delete Subject</string> | ||||
|     <string name="delete_task">Delete Task</string> | ||||
|     <string name="view_tasks">View</string> | ||||
|     <string name="select_subject">Select</string> | ||||
|     <string name="regenerate_color">Regenerate Color</string> | ||||
| 
 | ||||
|     <!-- Sessions --> | ||||
|  | @ -135,6 +137,9 @@ | |||
|     <string name="send_friend_request">Send friend request</string> | ||||
|     <string name="remove_friend">Remove as friend</string> | ||||
|     <string name="show_profile">Show profile</string> | ||||
|     <string name="click_search_friends">Click to search friends</string> | ||||
|     <string name="searching_friends">Searching friends</string> | ||||
|     <string name="already_friend">You are already befriended with that person.</string> | ||||
| 
 | ||||
|     <!-- ========== Create & edit screens ========== --> | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,13 +7,14 @@ import org.junit.Test | |||
| class FunctionalPomodoroTimerUnitTest : FunctionalTimerUnitTest() { | ||||
|     private val breakTime = 10 | ||||
|     private val breaks = 2 | ||||
|     private val repeats = 3 // = breaks + 1 | ||||
|     override val hours = 0 | ||||
|     override val minutes = 0 | ||||
|     override val seconds = 10 | ||||
|     private lateinit var pomodoroTimer: FunctionalPomodoroTimer | ||||
| 
 | ||||
|     override fun setTimer() { | ||||
|         pomodoroTimer = FunctionalPomodoroTimer(time, breakTime, breaks) | ||||
|         pomodoroTimer = FunctionalPomodoroTimer(time, breakTime, repeats) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|  |  | |||
|  | @ -1,12 +1,11 @@ | |||
| package be.ugent.sel.studeez.timer_functional | ||||
| 
 | ||||
| import android.media.MediaPlayer | ||||
| import be.ugent.sel.studeez.data.SelectedSessionReport | ||||
| import be.ugent.sel.studeez.data.SelectedTask | ||||
| import be.ugent.sel.studeez.data.SelectedTimer | ||||
| 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 | ||||
| import be.ugent.sel.studeez.domain.LogService | ||||
| import be.ugent.sel.studeez.domain.implementation.LogServiceImpl | ||||
| import be.ugent.sel.studeez.screens.session.InvisibleSessionManager | ||||
| import be.ugent.sel.studeez.screens.session.SessionViewModel | ||||
|  | @ -22,13 +21,13 @@ import org.mockito.kotlin.mock | |||
| class InvisibleSessionManagerTest { | ||||
|     private var selectedTimer: SelectedTimer = SelectedTimer() | ||||
|     private lateinit var viewModel: SessionViewModel | ||||
|     private var mediaPlayer: MediaPlayer = mock() | ||||
| 
 | ||||
| 
 | ||||
|     @Test | ||||
|     fun InvisibleEndlessTimerTest() = runTest { | ||||
|         selectedTimer.set(FunctionalEndlessTimer()) | ||||
|         viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), mock(), LogServiceImpl()) | ||||
|         InvisibleSessionManager.setParameters(viewModel, mediaPlayer) | ||||
|         viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), SelectedTask(), LogServiceImpl()) | ||||
|         InvisibleSessionManager.setParameters(viewModel, mock()) | ||||
| 
 | ||||
|         val test = launch { | ||||
|             InvisibleSessionManager.updateTimer() | ||||
|  | @ -47,10 +46,10 @@ class InvisibleSessionManagerTest { | |||
|     fun InvisiblePomodoroTimerTest() = runTest { | ||||
|         val studyTime = 10 | ||||
|         val breakTime = 5 | ||||
|         val repeats = 1 | ||||
|         val repeats = 2 | ||||
|         selectedTimer.set(FunctionalPomodoroTimer(studyTime, breakTime, repeats)) | ||||
|         viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), mock(), LogServiceImpl()) | ||||
|         InvisibleSessionManager.setParameters(viewModel, mediaPlayer) | ||||
|         viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), SelectedTask(), LogServiceImpl()) | ||||
|         InvisibleSessionManager.setParameters(viewModel, mock()) | ||||
| 
 | ||||
|         val test = launch { | ||||
|             InvisibleSessionManager.updateTimer() | ||||
|  | @ -82,8 +81,8 @@ class InvisibleSessionManagerTest { | |||
|     @Test | ||||
|     fun InvisibleCustomTimerTest() = runTest { | ||||
|         selectedTimer.set(FunctionalCustomTimer(5)) | ||||
|         viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), mock(), LogServiceImpl()) | ||||
|         InvisibleSessionManager.setParameters(viewModel, mediaPlayer) | ||||
|         viewModel = SessionViewModel(selectedTimer, SelectedSessionReport(), SelectedTask(), LogServiceImpl()) | ||||
|         InvisibleSessionManager.setParameters(viewModel, mock()) | ||||
| 
 | ||||
|         val test = launch { | ||||
|             InvisibleSessionManager.updateTimer() | ||||
|  |  | |||
		Reference in a new issue
	
	 brreynie
						brreynie