From c400ac24aef96e26d0b0354ff18a778e42749e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20St=C4=99pie=C5=84?= Date: Mon, 6 Jan 2025 16:33:22 +0100 Subject: [PATCH] Rebuild navigation structure --- app/src/main/AndroidManifest.xml | 2 +- .../androidclient/network/api/FeelBeatApi.kt | 3 +- .../network/api/KtorFeelBeatApi.kt | 2 +- .../network/api/payloads/CreateRoomPayload.kt | 2 +- .../androidclient/ui/FeelBeatApp.kt | 40 +-- .../androidclient/ui/FeelBeatRoute.kt | 20 -- .../androidclient/ui/MainActivity.kt | 10 +- .../feelbeatapp/androidclient/ui/RootRoute.kt | 6 + .../androidclient/ui/acceptgame/GameState.kt | 15 - .../androidclient/ui/app/AppScreen.kt | 172 +++++++++++ .../androidclient/ui/app/AppViewModel.kt | 39 +++ .../game}/gameresult/GameResultScreen.kt | 15 +- .../game}/gameresult/GameResultViewModel.kt | 8 +- .../game}/guesssong/GuessResultScreen.kt | 14 +- .../game}/guesssong/GuessSongScreen.kt | 22 +- .../game}/guesssong/GuessSongViewModel.kt | 8 +- .../ui/{ => app/game}/guesssong/GuessState.kt | 10 +- .../{ => app/game}/guesssong/ResultStatus.kt | 2 +- .../game}/startgame/StartGameScreen.kt | 17 +- .../game}/startgame/StartGameViewModel.kt | 4 +- .../androidclient/ui/app/home/HomeScreen.kt | 109 +++++++ .../ui/app/home/HomeViewModel.kt | 38 +++ .../ui/app/lobby/LobbyBottomBar.kt | 45 +++ .../lobby}/acceptgame/AcceptGameScreen.kt | 72 +---- .../lobby}/acceptgame/AcceptGameViewModel.kt | 6 +- .../ui/app/lobby/acceptgame/GameState.kt | 16 ++ .../androidclient/ui/app/model/Player.kt | 3 + .../ui/app/model/PlayerWithResult.kt | 6 + .../ui/{ => app}/model/Playlist.kt | 2 +- .../androidclient/ui/{ => app}/model/Room.kt | 2 +- .../ui/{ => app}/model/RoomSettings.kt | 2 +- .../androidclient/ui/app/model/Song.kt | 3 + .../ui/app/navigation/AppGraph.kt | 133 +++++++++ .../ui/app/navigation/AppRoute.kt | 17 ++ .../ui/app/navigation/GameGraph.kt | 24 ++ .../ui/app/navigation/LobbyGraph.kt | 14 + .../roomsettings/components/SettingSlider.kt | 2 +- .../components/SettingsControls.kt | 4 +- .../screens/EditRoomSettingsScreen.kt | 32 +++ .../screens/NewRoomSettingsScreen.kt | 76 +++++ .../viewmodels/EditRoomSettingsViewModel.kt | 3 + .../viewmodels/NewRoomSettingsViewModel.kt | 2 +- .../viewmodels/RoomSettingsViewModel.kt | 5 +- .../androidclient/ui/home/HomeRoute.kt | 7 - .../androidclient/ui/home/HomeScreen.kt | 267 ------------------ .../androidclient/ui/home/HomeViewModel.kt | 87 ------ .../ui/{ => login}/AuthActivity.kt | 4 +- .../androidclient/ui/model/Player.kt | 3 - .../ui/model/PlayerWithResult.kt | 5 - .../androidclient/ui/model/Song.kt | 3 - .../screens/EditRoomSettingsScreen.kt | 85 ------ .../screens/NewRoomSettingsScreen.kt | 103 ------- .../viewmodels/EditRoomSettingsViewModel.kt | 3 - app/src/main/res/values/strings.xml | 5 +- 54 files changed, 826 insertions(+), 773 deletions(-) delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/FeelBeatRoute.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/RootRoute.kt delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/acceptgame/GameState.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/AppScreen.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/AppViewModel.kt rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/game}/gameresult/GameResultScreen.kt (86%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/game}/gameresult/GameResultViewModel.kt (83%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/game}/guesssong/GuessResultScreen.kt (91%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/game}/guesssong/GuessSongScreen.kt (91%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/game}/guesssong/GuessSongViewModel.kt (94%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/game}/guesssong/GuessState.kt (60%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/game}/guesssong/ResultStatus.kt (50%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/game}/startgame/StartGameScreen.kt (86%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/game}/startgame/StartGameViewModel.kt (87%) create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/home/HomeScreen.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/home/HomeViewModel.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/LobbyBottomBar.kt rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/lobby}/acceptgame/AcceptGameScreen.kt (57%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app/lobby}/acceptgame/AcceptGameViewModel.kt (87%) create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/acceptgame/GameState.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Player.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/PlayerWithResult.kt rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app}/model/Playlist.kt (51%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app}/model/Room.kt (74%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app}/model/RoomSettings.kt (77%) create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Song.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/AppGraph.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/AppRoute.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/GameGraph.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/LobbyGraph.kt rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app}/roomsettings/components/SettingSlider.kt (95%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app}/roomsettings/components/SettingsControls.kt (93%) create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/screens/EditRoomSettingsScreen.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/screens/NewRoomSettingsScreen.kt create mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/viewmodels/EditRoomSettingsViewModel.kt rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app}/roomsettings/viewmodels/NewRoomSettingsViewModel.kt (95%) rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => app}/roomsettings/viewmodels/RoomSettingsViewModel.kt (87%) delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeRoute.kt delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeScreen.kt delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeViewModel.kt rename app/src/main/java/com/github/feelbeatapp/androidclient/ui/{ => login}/AuthActivity.kt (92%) delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Player.kt delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/PlayerWithResult.kt delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Song.kt delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/screens/EditRoomSettingsScreen.kt delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/screens/NewRoomSettingsScreen.kt delete mode 100644 app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/viewmodels/EditRoomSettingsViewModel.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 990ecb6..5575b9a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -26,7 +26,7 @@ diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/FeelBeatApi.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/FeelBeatApi.kt index 64dc97b..dd4b505 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/FeelBeatApi.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/FeelBeatApi.kt @@ -1,6 +1,7 @@ package com.github.feelbeatapp.androidclient.network.api -import com.github.feelbeatapp.androidclient.ui.model.RoomSettings +import com.github.feelbeatapp.androidclient.ui.app.model.RoomSettings + interface FeelBeatApi { suspend fun createRoom(settings: RoomSettings): String diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/KtorFeelBeatApi.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/KtorFeelBeatApi.kt index c7cc5ae..44e59a6 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/KtorFeelBeatApi.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/KtorFeelBeatApi.kt @@ -5,7 +5,7 @@ import com.github.feelbeatapp.androidclient.error.ErrorCode import com.github.feelbeatapp.androidclient.error.FeelBeatException import com.github.feelbeatapp.androidclient.network.api.payloads.CreateRoomPayload import com.github.feelbeatapp.androidclient.network.api.responses.CreateRoomResponse -import com.github.feelbeatapp.androidclient.ui.model.RoomSettings +import com.github.feelbeatapp.androidclient.ui.app.model.RoomSettings import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.request.headers diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/payloads/CreateRoomPayload.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/payloads/CreateRoomPayload.kt index e7d234b..ea39add 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/payloads/CreateRoomPayload.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/network/api/payloads/CreateRoomPayload.kt @@ -1,6 +1,6 @@ package com.github.feelbeatapp.androidclient.network.api.payloads -import com.github.feelbeatapp.androidclient.ui.model.RoomSettings +import com.github.feelbeatapp.androidclient.ui.app.model.RoomSettings import io.ktor.http.Url import kotlinx.serialization.Serializable diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/FeelBeatApp.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/FeelBeatApp.kt index 1f27ebb..bcc970d 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/FeelBeatApp.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/FeelBeatApp.kt @@ -7,44 +7,27 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController -import com.github.feelbeatapp.androidclient.ui.gameresult.GameResultScreen -import com.github.feelbeatapp.androidclient.ui.guesssong.GuessResultScreen -import com.github.feelbeatapp.androidclient.ui.guesssong.GuessSongScreen -import com.github.feelbeatapp.androidclient.ui.home.HomeScreen +import com.github.feelbeatapp.androidclient.ui.app.navigation.AppGraph import com.github.feelbeatapp.androidclient.ui.login.LoginScreen -import com.github.feelbeatapp.androidclient.ui.roomsettings.screens.NewRoomSettingsScreen -import com.github.feelbeatapp.androidclient.ui.startgame.StartGameScreen import com.github.feelbeatapp.androidclient.ui.theme.FeelBeatTheme @Composable -fun FeelBeatApp(startScreen: FeelBeatRoute, modifier: Modifier = Modifier) { +fun FeelBeatApp(startScreen: RootRoute, modifier: Modifier = Modifier) { FeelBeatTheme { val navController = rememberNavController() Box(modifier = modifier) { NavHost(navController, startDestination = startScreen.name) { - composable(route = FeelBeatRoute.LOGIN.name) { LoginScreen() } - composable(route = FeelBeatRoute.HOME.name) { - HomeScreen(navController = navController) - } - composable(route = FeelBeatRoute.NEW_ROOM_SETTINGS.name) { - NewRoomSettingsScreen( - onNavigateTo = { navController.navigate(it) }, - onNavigateBack = { navController.popBackStack() }, + composable(route = RootRoute.APP.name) { + AppGraph( + onLogout = { + navController.navigate(RootRoute.LOGIN.name) { + popUpTo(navController.graph.id) + } + } ) } - composable(route = FeelBeatRoute.GAME_RESULT.name) { - GameResultScreen(navController = navController) - } - composable(route = FeelBeatRoute.GUESS_SONG.name) { - GuessSongScreen(navController = navController) - } - composable(route = FeelBeatRoute.GUESS_RESULT.name) { - GuessResultScreen(navController = navController) - } - composable(route = FeelBeatRoute.START_GAME.name) { - StartGameScreen(navController = navController) - } + composable(route = RootRoute.LOGIN.name) { LoginScreen() } } } } @@ -53,6 +36,5 @@ fun FeelBeatApp(startScreen: FeelBeatRoute, modifier: Modifier = Modifier) { @Preview @Composable fun AppPreview() { - FeelBeatApp(FeelBeatRoute.LOGIN) - + FeelBeatApp(RootRoute.LOGIN) } diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/FeelBeatRoute.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/FeelBeatRoute.kt deleted file mode 100644 index e99ad70..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/FeelBeatRoute.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui - -enum class FeelBeatRoute { - LOGIN, - HOME, - NEW_ROOM_SETTINGS, - ROOM_SETTINGS, - ACCEPT_GAME, - GAME_RESULT, - GUESS_SONG, - GUESS_RESULT, - START_GAME; - - fun withArgs(vararg args: String): String { - return buildString { - append(name) - args.forEach { append("/$it") } - } - } -} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/MainActivity.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/MainActivity.kt index d826ab2..aa5c224 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/MainActivity.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/MainActivity.kt @@ -4,8 +4,6 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge -import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi -import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass import com.github.feelbeatapp.androidclient.auth.AuthManager import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -14,16 +12,12 @@ import javax.inject.Inject class MainActivity : ComponentActivity() { @Inject lateinit var authManager: AuthManager - @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val startRoute = - if (authManager.isAuthenticated()) FeelBeatRoute.HOME else FeelBeatRoute.LOGIN + val startRoute = if (authManager.isAuthenticated()) RootRoute.APP else RootRoute.LOGIN enableEdgeToEdge() - setContent { - FeelBeatApp(startRoute) - } + setContent { FeelBeatApp(startRoute) } } } diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/RootRoute.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/RootRoute.kt new file mode 100644 index 0000000..d071911 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/RootRoute.kt @@ -0,0 +1,6 @@ +package com.github.feelbeatapp.androidclient.ui + +enum class RootRoute { + LOGIN, + APP, +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/acceptgame/GameState.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/acceptgame/GameState.kt deleted file mode 100644 index d137a92..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/acceptgame/GameState.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui.acceptgame - -import com.github.feelbeatapp.androidclient.ui.model.Player -import com.github.feelbeatapp.androidclient.ui.model.Playlist -import com.github.feelbeatapp.androidclient.ui.model.Room -import com.github.feelbeatapp.androidclient.ui.model.Song - -data class GameState( - val players: List = emptyList(), - val songs: List = emptyList(), - val selectedRoom: Room? = null, - val playlist: Playlist = Playlist(name = "Playlist #1", songs = emptyList()), - val snippetDuration: Int = 30, - val pointsToWin: Int = 10, -) diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/AppScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/AppScreen.kt new file mode 100644 index 0000000..423dcd2 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/AppScreen.kt @@ -0,0 +1,172 @@ +package com.github.feelbeatapp.androidclient.ui.app + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +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 coil3.compose.AsyncImage +import com.github.feelbeatapp.androidclient.R +import com.github.feelbeatapp.androidclient.ui.theme.FeelBeatTheme + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AppScreen( + title: String, + backVisible: Boolean, + onLogout: () -> Unit, + onNavigateBack: () -> Unit, + appViewModel: AppViewModel = hiltViewModel(), + bottomBar: @Composable () -> Unit = {}, + content: @Composable () -> Unit = {}, +) { + val playerIdentity by appViewModel.playerIdentity.collectAsState() + + var playerIdentitySheetOpen by remember { mutableStateOf(false) } + + if (playerIdentitySheetOpen) { + ModalBottomSheet(onDismissRequest = { playerIdentitySheetOpen = false }) { + UserAccountBottomSheetContent( + playerIdentity = playerIdentity, + onLogoutClick = { + appViewModel.logout() + playerIdentitySheetOpen = false + onLogout() + }, + ) + } + } + + Scaffold( + topBar = { + AppBar( + title = title, + backVisible = backVisible, + imageUrl = playerIdentity?.imageUrl, + onAccountClick = { playerIdentitySheetOpen = true }, + onNavigateBack = onNavigateBack, + ) + }, + bottomBar = { bottomBar() }, + modifier = Modifier.fillMaxSize(), + ) { padding -> + Box(modifier = Modifier.padding(padding).fillMaxSize()) { content() } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AppBar( + title: String, + backVisible: Boolean, + imageUrl: String?, + onAccountClick: () -> Unit, + onNavigateBack: () -> Unit, +) { + CenterAlignedTopAppBar( + title = { Text(title) }, + colors = + TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + titleContentColor = MaterialTheme.colorScheme.primary, + ), + actions = { + IconButton(onClick = onAccountClick) { + AsyncImage( + model = imageUrl, + contentDescription = stringResource(R.string.player_image), + modifier = Modifier.size(80.dp).clip(MaterialTheme.shapes.large), + contentScale = ContentScale.Crop, + placeholder = painterResource(R.drawable.account), + error = painterResource(R.drawable.account), + ) + } + }, + navigationIcon = { + if (backVisible) { + IconButton(onClick = onNavigateBack) { + Icon( + Icons.AutoMirrored.Filled.KeyboardArrowLeft, + contentDescription = stringResource(R.string.back), + ) + } + } + }, + ) +} + +@Composable +fun UserAccountBottomSheetContent(playerIdentity: PlayerIdentity?, onLogoutClick: () -> Unit) { + Column( + modifier = Modifier.fillMaxWidth().padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + Box( + modifier = + Modifier.size(80.dp).background(Color.Gray, shape = MaterialTheme.shapes.large), + contentAlignment = Alignment.Center, + ) { + AsyncImage( + model = playerIdentity?.imageUrl, + contentDescription = "Player Image", + modifier = Modifier.size(80.dp).clip(MaterialTheme.shapes.large), + contentScale = ContentScale.Crop, + placeholder = painterResource(R.drawable.account), + error = painterResource(R.drawable.account), + ) + } + Text(text = playerIdentity?.name ?: "...", style = MaterialTheme.typography.titleMedium) + Box( + modifier = + Modifier.fillMaxWidth() + .background(MaterialTheme.colorScheme.primary, MaterialTheme.shapes.medium) + .padding(8.dp), + contentAlignment = Alignment.Center, + ) { + Text( + text = "log out", + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.onPrimary, + modifier = Modifier.padding(vertical = 4.dp).clickable { onLogoutClick() }, + ) + } + } +} + +@Composable +@Preview +fun AppScreenPreview() { + FeelBeatTheme { AppScreen(title = "Title", backVisible = true, {}, {}) } +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/AppViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/AppViewModel.kt new file mode 100644 index 0000000..f59ed24 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/AppViewModel.kt @@ -0,0 +1,39 @@ +package com.github.feelbeatapp.androidclient.ui.app + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.github.feelbeatapp.androidclient.auth.AuthManager +import com.github.feelbeatapp.androidclient.network.spotify.SpotifyAPI +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +data class PlayerIdentity(val name: String, val imageUrl: String) + +@HiltViewModel +class AppViewModel +@Inject +constructor(private val authManager: AuthManager, private val spotifyAPI: SpotifyAPI) : + ViewModel() { + private val _playerIdentity = MutableStateFlow(null) + val playerIdentity = _playerIdentity.asStateFlow() + + init { + loadPlayerIdentity() + } + + private fun loadPlayerIdentity() { + viewModelScope.launch(Dispatchers.IO) { + val profile = spotifyAPI.getProfile() + _playerIdentity.value = + PlayerIdentity(name = profile.displayName, imageUrl = profile.images.first().url) + } + } + + fun logout() { + authManager.logout() + } +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/gameresult/GameResultScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/gameresult/GameResultScreen.kt similarity index 86% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/gameresult/GameResultScreen.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/gameresult/GameResultScreen.kt index b51ba68..b6f0873 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/gameresult/GameResultScreen.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/gameresult/GameResultScreen.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.gameresult +package com.github.feelbeatapp.androidclient.ui.app.game.gameresult import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement @@ -27,15 +27,13 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import androidx.navigation.compose.rememberNavController import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.FeelBeatRoute -import com.github.feelbeatapp.androidclient.ui.model.PlayerWithResult +import com.github.feelbeatapp.androidclient.ui.app.model.PlayerWithResult +import com.github.feelbeatapp.androidclient.ui.app.navigation.AppRoute @Composable fun GameResultScreen( - navController: NavController, + onNavigate: (String) -> Unit, viewModel: GameResultViewModel = GameResultViewModel(), ) { val players by viewModel.players.collectAsState() @@ -60,7 +58,7 @@ fun GameResultScreen( } Button( - onClick = { navController.navigate(FeelBeatRoute.HOME) }, + onClick = { onNavigate(AppRoute.HOME.name) }, modifier = Modifier.padding(vertical = 16.dp), ) { Text(text = "CLOSE") @@ -91,6 +89,5 @@ fun PlayerScoreItem(player: PlayerWithResult) { @Preview @Composable fun GameResultPreview() { - val navController = rememberNavController() - GameResultScreen(navController = navController) + GameResultScreen({}) } diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/gameresult/GameResultViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/gameresult/GameResultViewModel.kt similarity index 83% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/gameresult/GameResultViewModel.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/gameresult/GameResultViewModel.kt index e4dcc2f..57ef033 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/gameresult/GameResultViewModel.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/gameresult/GameResultViewModel.kt @@ -1,11 +1,11 @@ -package com.github.feelbeatapp.androidclient.ui.gameresult +package com.github.feelbeatapp.androidclient.ui.app.game.gameresult import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.model.Player -import com.github.feelbeatapp.androidclient.ui.model.PlayerWithResult -import com.github.feelbeatapp.androidclient.ui.guesssong.ResultStatus +import com.github.feelbeatapp.androidclient.ui.app.game.guesssong.ResultStatus +import com.github.feelbeatapp.androidclient.ui.app.model.Player +import com.github.feelbeatapp.androidclient.ui.app.model.PlayerWithResult import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessResultScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessResultScreen.kt similarity index 91% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessResultScreen.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessResultScreen.kt index 21d1ba7..a8acc08 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessResultScreen.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessResultScreen.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.guesssong +package com.github.feelbeatapp.androidclient.ui.app.game.guesssong import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement @@ -24,14 +24,13 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import androidx.navigation.compose.rememberNavController import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.FeelBeatRoute +import com.github.feelbeatapp.androidclient.ui.app.navigation.AppRoute @Composable fun GuessResultScreen( - navController: NavController, + roomId: String, + onNavigate: (String) -> Unit, viewModel: GuessSongViewModel = GuessSongViewModel(), ) { val guessState by viewModel.guessState.collectAsState() @@ -87,7 +86,7 @@ fun GuessResultScreen( modifier = Modifier.padding(bottom = 32.dp), ) - Button(onClick = { navController.navigate(FeelBeatRoute.GUESS_SONG.name) }) { + Button(onClick = { onNavigate(AppRoute.GUESS.withArgs(mapOf("roomId" to roomId))) }) { Text(text = "NEXT") } } @@ -131,6 +130,5 @@ fun SongInfo(songTitle: String) { @Preview @Composable fun GuessResultScreenPreview() { - val nav = rememberNavController() - GuessResultScreen(navController = nav) + GuessResultScreen("roomid", {}) } diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessSongScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessSongScreen.kt similarity index 91% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessSongScreen.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessSongScreen.kt index cbdd39f..2152db3 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessSongScreen.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessSongScreen.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.guesssong +package com.github.feelbeatapp.androidclient.ui.app.game.guesssong import androidx.compose.foundation.Image import androidx.compose.foundation.border @@ -37,17 +37,16 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import androidx.navigation.compose.rememberNavController import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.FeelBeatRoute -import com.github.feelbeatapp.androidclient.ui.model.PlayerWithResult -import com.github.feelbeatapp.androidclient.ui.model.Song +import com.github.feelbeatapp.androidclient.ui.app.model.PlayerWithResult +import com.github.feelbeatapp.androidclient.ui.app.model.Song +import com.github.feelbeatapp.androidclient.ui.app.navigation.AppRoute @OptIn(ExperimentalMaterial3Api::class) @Composable fun GuessSongScreen( - navController: NavController, + roomId: String, + onNavigate: (String) -> Unit, viewModel: GuessSongViewModel = GuessSongViewModel(), ) { val guessState by viewModel.guessState.collectAsState() @@ -55,7 +54,7 @@ fun GuessSongScreen( val gameEnded by viewModel.gameEnded.collectAsState() if (gameEnded) { - navController.navigate(FeelBeatRoute.GUESS_RESULT.name) + onNavigate(AppRoute.GAME_RESULT.withArgs(mapOf("roomId" to roomId))) } Scaffold( @@ -106,7 +105,9 @@ fun GuessSongScreen( items(guessState.filteredSongs.size) { index -> SongItem( song = guessState.filteredSongs[index], - onClick = { navController.navigate(FeelBeatRoute.GUESS_RESULT.name) }, + onClick = { + onNavigate(AppRoute.GUESS_RESULT.withArgs(mapOf("roomId" to roomId))) + }, ) } } @@ -193,6 +194,5 @@ fun SongItem(song: Song, onClick: () -> Unit) { @Preview @Composable fun GuessSongPreview() { - val nav = rememberNavController() - GuessSongScreen(navController = nav) + GuessSongScreen("roomId", {}) } diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessSongViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessSongViewModel.kt similarity index 94% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessSongViewModel.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessSongViewModel.kt index 20299a3..c8aa7e7 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessSongViewModel.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessSongViewModel.kt @@ -1,12 +1,12 @@ -package com.github.feelbeatapp.androidclient.ui.guesssong +package com.github.feelbeatapp.androidclient.ui.app.game.guesssong import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.model.Player -import com.github.feelbeatapp.androidclient.ui.model.PlayerWithResult -import com.github.feelbeatapp.androidclient.ui.model.Song +import com.github.feelbeatapp.androidclient.ui.app.model.Player +import com.github.feelbeatapp.androidclient.ui.app.model.PlayerWithResult +import com.github.feelbeatapp.androidclient.ui.app.model.Song import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessState.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessState.kt similarity index 60% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessState.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessState.kt index 6ae8024..b8eb37b 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/GuessState.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/GuessState.kt @@ -1,10 +1,10 @@ -package com.github.feelbeatapp.androidclient.ui.guesssong +package com.github.feelbeatapp.androidclient.ui.app.game.guesssong import androidx.compose.ui.text.input.TextFieldValue -import com.github.feelbeatapp.androidclient.ui.model.PlayerWithResult -import com.github.feelbeatapp.androidclient.ui.model.Playlist -import com.github.feelbeatapp.androidclient.ui.model.Room -import com.github.feelbeatapp.androidclient.ui.model.Song +import com.github.feelbeatapp.androidclient.ui.app.model.PlayerWithResult +import com.github.feelbeatapp.androidclient.ui.app.model.Playlist +import com.github.feelbeatapp.androidclient.ui.app.model.Room +import com.github.feelbeatapp.androidclient.ui.app.model.Song data class GuessState( val players: List = emptyList(), diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/ResultStatus.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/ResultStatus.kt similarity index 50% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/ResultStatus.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/ResultStatus.kt index 3bc292c..d479268 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/guesssong/ResultStatus.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/guesssong/ResultStatus.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.guesssong +package com.github.feelbeatapp.androidclient.ui.app.game.guesssong enum class ResultStatus { CORRECT, diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/startgame/StartGameScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/startgame/StartGameScreen.kt similarity index 86% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/startgame/StartGameScreen.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/startgame/StartGameScreen.kt index af1fc11..7f597ce 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/startgame/StartGameScreen.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/startgame/StartGameScreen.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.startgame +package com.github.feelbeatapp.androidclient.ui.app.game.startgame import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -27,16 +27,15 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import androidx.navigation.compose.rememberNavController import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.FeelBeatRoute -import com.github.feelbeatapp.androidclient.ui.model.Player +import com.github.feelbeatapp.androidclient.ui.app.model.Player +import com.github.feelbeatapp.androidclient.ui.app.navigation.AppRoute @Composable fun StartGameScreen( + roomId: String, + onNavigate: (String) -> Unit, viewModel: StartGameViewModel = StartGameViewModel(), - navController: NavController, ) { val players by viewModel.players.collectAsState() var countdown by remember { mutableIntStateOf(value = 3) } @@ -46,7 +45,7 @@ fun StartGameScreen( kotlinx.coroutines.delay(timeMillis = 1000) countdown -= 1 } else { - navController.navigate(FeelBeatRoute.GUESS_SONG.name) + onNavigate(AppRoute.GUESS.withArgs(mapOf("roomId" to roomId))) } } @@ -56,6 +55,7 @@ fun StartGameScreen( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.SpaceEvenly, ) { + Text(roomId) Row(horizontalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.fillMaxWidth()) { players.forEach { player -> PlayerCard(player = player) } } @@ -90,6 +90,5 @@ fun PlayerCard(player: Player) { @Preview @Composable fun StartGamePreview() { - val navController = rememberNavController() - StartGameScreen(navController = navController) + StartGameScreen("roomId", {}) } diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/startgame/StartGameViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/startgame/StartGameViewModel.kt similarity index 87% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/startgame/StartGameViewModel.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/startgame/StartGameViewModel.kt index ad34c4a..e168834 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/startgame/StartGameViewModel.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/game/startgame/StartGameViewModel.kt @@ -1,9 +1,9 @@ -package com.github.feelbeatapp.androidclient.ui.startgame +package com.github.feelbeatapp.androidclient.ui.app.game.startgame import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.model.Player +import com.github.feelbeatapp.androidclient.ui.app.model.Player import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/home/HomeScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/home/HomeScreen.kt new file mode 100644 index 0000000..0894ee0 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/home/HomeScreen.kt @@ -0,0 +1,109 @@ +package com.github.feelbeatapp.androidclient.ui.app.home + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +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 androidx.hilt.navigation.compose.hiltViewModel +import com.github.feelbeatapp.androidclient.R +import com.github.feelbeatapp.androidclient.ui.app.model.Room + +@Composable +fun HomeScreen( + onRoomSelect: (Room) -> Unit, + onNewRoom: () -> Unit, + homeViewModel: HomeViewModel = hiltViewModel(), +) { + val rooms by homeViewModel.rooms.collectAsState() + + Column(modifier = Modifier.fillMaxSize()) { + Text( + text = stringResource(R.string.current_games), + style = MaterialTheme.typography.titleMedium, + modifier = Modifier.padding(16.dp), + ) + LazyColumn( + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp).weight(1f), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + items(rooms) { room -> RoomItem(room = room, onClick = { onRoomSelect(room) }) } + } + + Box( + modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp).padding(horizontal = 16.dp) + ) { + Box( + modifier = + Modifier.align(Alignment.BottomEnd) + .size(60.dp) + .background( + MaterialTheme.colorScheme.primary, + shape = MaterialTheme.shapes.medium, + ) + ) { + IconButton(onClick = onNewRoom, modifier = Modifier.fillMaxSize()) { + Icon( + imageVector = Icons.Default.Add, + contentDescription = "Add", + modifier = Modifier.size(36.dp), + tint = MaterialTheme.colorScheme.onPrimary, + ) + } + } + } + } +} + +@Composable +fun RoomItem(room: Room, onClick: () -> Unit) { + Card( + onClick = onClick, + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface), + modifier = + Modifier.fillMaxWidth() + .padding(8.dp) + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.outline, + shape = MaterialTheme.shapes.medium, + ), + ) { + Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(16.dp)) { + Text( + text = room.name, + style = MaterialTheme.typography.bodyLarge, + modifier = Modifier.weight(1f), + ) + } + } +} + +@Preview +@Composable +fun HomePreview() { + HomeScreen(onRoomSelect = {}, onNewRoom = {}) +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/home/HomeViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/home/HomeViewModel.kt new file mode 100644 index 0000000..db8b6c5 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/home/HomeViewModel.kt @@ -0,0 +1,38 @@ +package com.github.feelbeatapp.androidclient.ui.app.home + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.github.feelbeatapp.androidclient.ui.app.model.Room +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +@HiltViewModel +class HomeViewModel @Inject constructor() : ViewModel() { + private val _rooms = MutableStateFlow>(emptyList()) + val rooms: StateFlow> = _rooms.asStateFlow() + + init { + loadRooms() + } + + @SuppressWarnings("MagicNumber") + private fun loadRooms() { + viewModelScope.launch { + val exampleRooms = + listOf( + Room(1, "Pokój 1", 4, 30, 10, "https://example.com/playlist1"), + Room(2, "Pokój 2", 5, 20, 5, "https://example.com/playlist2"), + Room(3, "Pokój 3", 2, 25, 3, "https://example.com/playlist3"), + Room(4, "Pokój 4", 4, 30, 4, "https://example.com/playlist4"), + Room(5, "Pokój 5", 5, 25, 4, "https://example.com/playlist5"), + Room(6, "Pokój 6", 2, 25, 10, "https://example.com/playlist6"), + Room(7, "Pokój 7", 4, 30, 9, "https://example.com/playlist7"), + ) + _rooms.value = exampleRooms + } + } +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/LobbyBottomBar.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/LobbyBottomBar.kt new file mode 100644 index 0000000..846f00f --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/LobbyBottomBar.kt @@ -0,0 +1,45 @@ +package com.github.feelbeatapp.androidclient.ui.app.lobby + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import com.github.feelbeatapp.androidclient.R +import com.github.feelbeatapp.androidclient.ui.app.navigation.AppRoute + +@Composable +fun LobbyBottomBar( + activeRoute: AppRoute, + onNavigate: (AppRoute) -> Unit, + modifier: Modifier = Modifier, +) { + NavigationBar( + modifier = modifier, + containerColor = MaterialTheme.colorScheme.surface, + contentColor = MaterialTheme.colorScheme.primary, + ) { + NavigationBarItem( + icon = { + Icon(Icons.Filled.Home, contentDescription = stringResource(R.string.selected_room)) + }, + label = { Text(stringResource(R.string.selected_room)) }, + selected = activeRoute == AppRoute.ROOM_LOBBY, + onClick = { onNavigate(AppRoute.ROOM_LOBBY) }, + ) + NavigationBarItem( + icon = { + Icon(Icons.Filled.Settings, contentDescription = stringResource(R.string.settings)) + }, + label = { Text(stringResource(R.string.settings)) }, + selected = activeRoute == AppRoute.ROOM_EDIT, + onClick = { onNavigate(AppRoute.ROOM_EDIT) }, + ) + } +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/acceptgame/AcceptGameScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/acceptgame/AcceptGameScreen.kt similarity index 57% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/acceptgame/AcceptGameScreen.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/acceptgame/AcceptGameScreen.kt index e1a5d4f..eed9fb0 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/acceptgame/AcceptGameScreen.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/acceptgame/AcceptGameScreen.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.acceptgame +package com.github.feelbeatapp.androidclient.ui.app.lobby.acceptgame import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -10,19 +10,10 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft -import androidx.compose.material.icons.filled.Home -import androidx.compose.material.icons.filled.Settings import androidx.compose.material3.Button -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.NavigationBar -import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -31,20 +22,15 @@ 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.navigation.NavController -import androidx.navigation.compose.rememberNavController import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.model.Song -import com.github.feelbeatapp.androidclient.ui.FeelBeatRoute -import com.github.feelbeatapp.androidclient.ui.home.HomeRoute -import com.github.feelbeatapp.androidclient.ui.startgame.PlayerCard +import com.github.feelbeatapp.androidclient.ui.app.game.startgame.PlayerCard +import com.github.feelbeatapp.androidclient.ui.app.model.Song @Composable fun AcceptGameScreen( + roomId: String, + onPlay: () -> Unit, viewModel: AcceptGameViewModel = AcceptGameViewModel(), - navController: NavController, - internalNavController: NavController, - isRoomCreator: Boolean = true, ) { val gameState = viewModel.gameState.collectAsState().value @@ -56,15 +42,7 @@ fun AcceptGameScreen( .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally, ) { - Spacer(modifier = Modifier.height(24.dp)) - IconButton(onClick = { internalNavController.navigate(HomeRoute.HOME.name) }) { - Icon( - Icons.AutoMirrored.Filled.KeyboardArrowLeft, - contentDescription = stringResource(R.string.back), - modifier = Modifier.size(40.dp), - ) - } - + Text(roomId) Row( horizontalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier.fillMaxWidth().padding(16.dp), @@ -106,45 +84,12 @@ fun AcceptGameScreen( Spacer(modifier = Modifier.height(32.dp)) Button( - onClick = { navController.navigate(FeelBeatRoute.START_GAME.name) }, + onClick = onPlay, modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), ) { Text(stringResource(R.string.play), style = MaterialTheme.typography.headlineMedium) } } - - if (isRoomCreator) { - BottomNavigationBar( - internalNavController = internalNavController, - modifier = Modifier.align(Alignment.BottomCenter), - ) - } - } -} - -@Composable -fun BottomNavigationBar(internalNavController: NavController, modifier: Modifier = Modifier) { - NavigationBar( - modifier = modifier, - containerColor = MaterialTheme.colorScheme.surface, - contentColor = MaterialTheme.colorScheme.primary, - ) { - NavigationBarItem( - icon = { - Icon(Icons.Filled.Home, contentDescription = stringResource(R.string.selected_room)) - }, - label = { Text(stringResource(R.string.selected_room)) }, - selected = false, - onClick = { internalNavController.navigate(FeelBeatRoute.ACCEPT_GAME.name) }, - ) - NavigationBarItem( - icon = { - Icon(Icons.Filled.Settings, contentDescription = stringResource(R.string.settings)) - }, - label = { Text(stringResource(R.string.settings)) }, - selected = false, - onClick = { internalNavController.navigate(FeelBeatRoute.ROOM_SETTINGS.name) }, - ) } } @@ -165,6 +110,5 @@ fun SongItem(song: Song) { @Preview @Composable fun PreviewAcceptScreen() { - val navController = rememberNavController() - AcceptGameScreen(navController = navController, internalNavController = navController) + AcceptGameScreen("Room id", {}) } diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/acceptgame/AcceptGameViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/acceptgame/AcceptGameViewModel.kt similarity index 87% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/acceptgame/AcceptGameViewModel.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/acceptgame/AcceptGameViewModel.kt index 8390c65..c0aa530 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/acceptgame/AcceptGameViewModel.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/acceptgame/AcceptGameViewModel.kt @@ -1,10 +1,10 @@ -package com.github.feelbeatapp.androidclient.ui.acceptgame +package com.github.feelbeatapp.androidclient.ui.app.lobby.acceptgame import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.model.Player -import com.github.feelbeatapp.androidclient.ui.model.Song +import com.github.feelbeatapp.androidclient.ui.app.model.Player +import com.github.feelbeatapp.androidclient.ui.app.model.Song import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/acceptgame/GameState.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/acceptgame/GameState.kt new file mode 100644 index 0000000..2997039 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/lobby/acceptgame/GameState.kt @@ -0,0 +1,16 @@ +package com.github.feelbeatapp.androidclient.ui.app.lobby.acceptgame + +import com.github.feelbeatapp.androidclient.ui.app.model.Player +import com.github.feelbeatapp.androidclient.ui.app.model.Playlist +import com.github.feelbeatapp.androidclient.ui.app.model.Room +import com.github.feelbeatapp.androidclient.ui.app.model.Song + + +data class GameState( + val players: List = emptyList(), + val songs: List = emptyList(), + val selectedRoom: Room? = null, + val playlist: Playlist = Playlist(name = "Playlist #1", songs = emptyList()), + val snippetDuration: Int = 30, + val pointsToWin: Int = 10, +) diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Player.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Player.kt new file mode 100644 index 0000000..ce0244e --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Player.kt @@ -0,0 +1,3 @@ +package com.github.feelbeatapp.androidclient.ui.app.model + +data class Player(val name: String, val image: Int) diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/PlayerWithResult.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/PlayerWithResult.kt new file mode 100644 index 0000000..91d1ec5 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/PlayerWithResult.kt @@ -0,0 +1,6 @@ +package com.github.feelbeatapp.androidclient.ui.app.model + +import com.github.feelbeatapp.androidclient.ui.app.game.guesssong.ResultStatus + + +data class PlayerWithResult(val player: Player, val resultStatus: ResultStatus, val points: Int) diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Playlist.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Playlist.kt similarity index 51% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Playlist.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Playlist.kt index 9be3eac..a2b21be 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Playlist.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Playlist.kt @@ -1,3 +1,3 @@ -package com.github.feelbeatapp.androidclient.ui.model +package com.github.feelbeatapp.androidclient.ui.app.model data class Playlist(val name: String, val songs: List) diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Room.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Room.kt similarity index 74% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Room.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Room.kt index 079f7cf..c9c762c 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Room.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Room.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.model +package com.github.feelbeatapp.androidclient.ui.app.model data class Room( val id: Int, diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/RoomSettings.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/RoomSettings.kt similarity index 77% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/RoomSettings.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/RoomSettings.kt index 85f36f5..6fdd6df 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/RoomSettings.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/RoomSettings.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.model +package com.github.feelbeatapp.androidclient.ui.app.model data class RoomSettings( val maxPlayers: Int, diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Song.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Song.kt new file mode 100644 index 0000000..5398a45 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/model/Song.kt @@ -0,0 +1,3 @@ +package com.github.feelbeatapp.androidclient.ui.app.model + +data class Song(val id: Int, val title: String) diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/AppGraph.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/AppGraph.kt new file mode 100644 index 0000000..83d7ba9 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/AppGraph.kt @@ -0,0 +1,133 @@ +package com.github.feelbeatapp.androidclient.ui.app.navigation + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.navigation.compose.navigation +import androidx.navigation.compose.rememberNavController +import com.github.feelbeatapp.androidclient.R +import com.github.feelbeatapp.androidclient.ui.app.AppScreen +import com.github.feelbeatapp.androidclient.ui.app.home.HomeScreen +import com.github.feelbeatapp.androidclient.ui.app.lobby.LobbyBottomBar +import com.github.feelbeatapp.androidclient.ui.app.roomsettings.screens.NewRoomSettingsScreen +import com.github.feelbeatapp.androidclient.ui.theme.FeelBeatTheme + +@Composable +fun AppGraph(onLogout: () -> Unit) { + val navController = rememberNavController() + val navBackStackEntry by navController.currentBackStackEntryAsState() + val route = navBackStackEntry?.destination?.route + + AppScreen( + title = getRouteTitle(route), + backVisible = getBackButtonVisibility(route), + onLogout = onLogout, + onNavigateBack = getNavigateBackBehaviour(route, navController), + bottomBar = + getBottomBar( + route, + onNavigate = { + val roomId = navBackStackEntry?.getRoomId() + if (roomId != null) { + navController.navigate(it.withArgs(mapOf("roomId" to roomId))) + } + }, + ), + ) { + NavHost(navController = navController, startDestination = AppRoute.HOME.route) { + composable(route = AppRoute.HOME.route) { + HomeScreen( + onRoomSelect = { room -> + navController.navigate( + AppRoute.ROOM_LOBBY.withArgs(mapOf("roomId" to room.id.toString())) + ) + }, + onNewRoom = { navController.navigate(AppRoute.NEW_ROOM.route) }, + ) + } + composable(route = AppRoute.NEW_ROOM.route) { + NewRoomSettingsScreen( + onRoomCreated = { + navController.navigate( + AppRoute.ROOM_LOBBY.withArgs(mapOf("roomId" to it)) + ) { + popUpTo(AppRoute.HOME.route) + } + } + ) + } + navigation(route = AppRoute.ROOM.route, startDestination = AppRoute.ROOM_LOBBY.route) { + lobbyGraph( + onPlay = { + val roomId = navBackStackEntry?.getRoomId() + if (roomId != null) { + navController.navigate( + AppRoute.START_GAME.withArgs(mapOf("roomId" to roomId)) + ) + } + } + ) + } + + navigation(route = AppRoute.GAME.route, startDestination = AppRoute.START_GAME.route) { + gameGraph(onNavigate = { navController.navigate(it) }) + } + } + } +} + +@Composable +fun getRouteTitle(route: String?): String { + return stringResource( + when (route) { + AppRoute.ROOM_LOBBY.route -> R.string.get_ready + AppRoute.ROOM_EDIT.route -> R.string.edit_room + AppRoute.NEW_ROOM.route -> R.string.create_room + else -> R.string.app_name + } + ) +} + +fun getBackButtonVisibility(route: String?): Boolean { + return when (route) { + AppRoute.HOME.route -> false + else -> true + } +} + +fun getBottomBar(route: String?, onNavigate: (AppRoute) -> Unit): @Composable () -> Unit { + return when (route) { + AppRoute.ROOM_LOBBY.route -> ({ + LobbyBottomBar(AppRoute.ROOM_LOBBY, onNavigate = onNavigate) + }) + AppRoute.ROOM_EDIT.route -> ({ + LobbyBottomBar(AppRoute.ROOM_EDIT, onNavigate = onNavigate) + }) + else -> ({}) + } +} + +fun getNavigateBackBehaviour(route: String?, navController: NavHostController): () -> Unit { + return when (route) { + AppRoute.ROOM_LOBBY.route, + AppRoute.ROOM_EDIT.route -> ({ navController.popBackStack(AppRoute.HOME.route, false) }) + else -> ({ navController.navigateUp() }) + } +} + +fun NavBackStackEntry.getRoomId(): String { + val roomId = arguments?.getString("roomId") + return roomId!! +} + +@Composable +@Preview +fun AppInternalRouterPreview() { + FeelBeatTheme { AppGraph({}) } +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/AppRoute.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/AppRoute.kt new file mode 100644 index 0000000..a55029a --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/AppRoute.kt @@ -0,0 +1,17 @@ +package com.github.feelbeatapp.androidclient.ui.app.navigation + +enum class AppRoute(val route: String) { + HOME("home"), + NEW_ROOM("new_room"), + ROOM("room"), + ROOM_LOBBY("room/{roomId}"), + ROOM_EDIT("room/{roomId}/edit"), + GAME("game"), + START_GAME("game/{roomId}"), + GUESS("game/{roomId}/guess"), + GUESS_RESULT("game/{roomId}/guess_result"), + GAME_RESULT("game/{roomId}/result"); + + fun withArgs(args: Map): String = + args.entries.fold(route) { acc, (key, value) -> acc.replace("{$key}", value) } +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/GameGraph.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/GameGraph.kt new file mode 100644 index 0000000..f42c85c --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/GameGraph.kt @@ -0,0 +1,24 @@ +package com.github.feelbeatapp.androidclient.ui.app.navigation + +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable +import com.github.feelbeatapp.androidclient.ui.app.game.gameresult.GameResultScreen +import com.github.feelbeatapp.androidclient.ui.app.game.guesssong.GuessResultScreen +import com.github.feelbeatapp.androidclient.ui.app.game.guesssong.GuessSongScreen +import com.github.feelbeatapp.androidclient.ui.app.game.startgame.StartGameScreen + +fun NavGraphBuilder.gameGraph(onNavigate: (String) -> Unit) { + composable(route = AppRoute.START_GAME.route) { + StartGameScreen(roomId = it.getRoomId(), onNavigate = onNavigate) + } + + composable(route = AppRoute.GUESS.route) { + GuessSongScreen(roomId = it.getRoomId(), onNavigate = onNavigate) + } + + composable(route = AppRoute.GUESS_RESULT.route) { + GuessResultScreen(roomId = it.getRoomId(), onNavigate = onNavigate) + } + + composable(route = AppRoute.GAME_RESULT.route) { GameResultScreen(onNavigate = onNavigate) } +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/LobbyGraph.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/LobbyGraph.kt new file mode 100644 index 0000000..2e2c412 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/navigation/LobbyGraph.kt @@ -0,0 +1,14 @@ +package com.github.feelbeatapp.androidclient.ui.app.navigation + +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable +import com.github.feelbeatapp.androidclient.ui.app.lobby.acceptgame.AcceptGameScreen +import com.github.feelbeatapp.androidclient.ui.app.roomsettings.screens.EditRoomSettingsScreen + + +fun NavGraphBuilder.lobbyGraph(onPlay: () -> Unit) { + composable(route = AppRoute.ROOM_LOBBY.route) { + AcceptGameScreen(it.getRoomId(), onPlay = onPlay) + } + composable(route = AppRoute.ROOM_EDIT.route) { EditRoomSettingsScreen() } +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/components/SettingSlider.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/components/SettingSlider.kt similarity index 95% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/components/SettingSlider.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/components/SettingSlider.kt index 71d5818..5895759 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/components/SettingSlider.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/components/SettingSlider.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.roomsettings.components +package com.github.feelbeatapp.androidclient.ui.app.roomsettings.components import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/components/SettingsControls.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/components/SettingsControls.kt similarity index 93% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/components/SettingsControls.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/components/SettingsControls.kt index afe23fa..007e522 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/components/SettingsControls.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/components/SettingsControls.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.roomsettings.components +package com.github.feelbeatapp.androidclient.ui.app.roomsettings.components import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -15,7 +15,7 @@ import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.roomsettings.viewmodels.RoomSettingsViewModel +import com.github.feelbeatapp.androidclient.ui.app.roomsettings.viewmodels.RoomSettingsViewModel @Composable fun SettingsControls(viewModel: RoomSettingsViewModel) { diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/screens/EditRoomSettingsScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/screens/EditRoomSettingsScreen.kt new file mode 100644 index 0000000..bfb065a --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/screens/EditRoomSettingsScreen.kt @@ -0,0 +1,32 @@ +package com.github.feelbeatapp.androidclient.ui.app.roomsettings.screens + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.github.feelbeatapp.androidclient.ui.app.roomsettings.components.SettingsControls +import com.github.feelbeatapp.androidclient.ui.app.roomsettings.viewmodels.EditRoomSettingsViewModel +import com.github.feelbeatapp.androidclient.ui.app.roomsettings.viewmodels.RoomSettingsViewModel + +@Composable +fun EditRoomSettingsScreen( + viewModel: RoomSettingsViewModel = EditRoomSettingsViewModel(), + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier.fillMaxSize().padding(16.dp), + verticalArrangement = Arrangement.spacedBy(24.dp), + ) { + SettingsControls(viewModel) + } +} + +@Preview(showBackground = true, widthDp = 360, heightDp = 640) +@Composable +fun PreviewRoomSettingsScreen() { + EditRoomSettingsScreen() +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/screens/NewRoomSettingsScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/screens/NewRoomSettingsScreen.kt new file mode 100644 index 0000000..bcb2729 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/screens/NewRoomSettingsScreen.kt @@ -0,0 +1,76 @@ +package com.github.feelbeatapp.androidclient.ui.app.roomsettings.screens + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +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 com.github.feelbeatapp.androidclient.R +import com.github.feelbeatapp.androidclient.ui.app.roomsettings.components.SettingsControls +import com.github.feelbeatapp.androidclient.ui.app.roomsettings.viewmodels.NewRoomSettingsViewModel + +@Composable +fun NewRoomSettingsScreen( + onRoomCreated: (String) -> Unit, + newRoomSettingsViewModel: NewRoomSettingsViewModel = hiltViewModel(), + modifier: Modifier = Modifier, +) { + val roomCreationState by newRoomSettingsViewModel.roomCreationState.collectAsState() + val createdRoomId by newRoomSettingsViewModel.roomCreated.collectAsState(null) + + LaunchedEffect(createdRoomId) { + val roomId = createdRoomId + if (roomId != null) { + onRoomCreated(roomId) + } + } + + Column( + modifier = modifier.fillMaxSize().padding(16.dp), + verticalArrangement = Arrangement.spacedBy(24.dp), + ) { + SettingsControls(viewModel = newRoomSettingsViewModel) + + Text(roomCreationState.errorMessage ?: "") + + if (roomCreationState.loading) { + Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) { + CircularProgressIndicator( + color = MaterialTheme.colorScheme.secondary, + trackColor = MaterialTheme.colorScheme.surfaceVariant, + strokeWidth = 4.dp, + modifier = Modifier.width(50.dp).height(50.dp), + ) + } + } else if (createdRoomId == null) { + Button( + onClick = { newRoomSettingsViewModel.createRoom() }, + modifier = Modifier.fillMaxWidth().height(56.dp), + ) { + Text(stringResource(R.string.create_room)) + } + } + } +} + +@Preview(showBackground = true, widthDp = 360, heightDp = 640) +@Composable +fun PreviewSettingsScreen() { + NewRoomSettingsScreen(onRoomCreated = {}) +} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/viewmodels/EditRoomSettingsViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/viewmodels/EditRoomSettingsViewModel.kt new file mode 100644 index 0000000..2049bd2 --- /dev/null +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/viewmodels/EditRoomSettingsViewModel.kt @@ -0,0 +1,3 @@ +package com.github.feelbeatapp.androidclient.ui.app.roomsettings.viewmodels + +class EditRoomSettingsViewModel : RoomSettingsViewModel() diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/viewmodels/NewRoomSettingsViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/viewmodels/NewRoomSettingsViewModel.kt similarity index 95% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/viewmodels/NewRoomSettingsViewModel.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/viewmodels/NewRoomSettingsViewModel.kt index aeff2f3..636e205 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/viewmodels/NewRoomSettingsViewModel.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/viewmodels/NewRoomSettingsViewModel.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui.roomsettings.viewmodels +package com.github.feelbeatapp.androidclient.ui.app.roomsettings.viewmodels import androidx.lifecycle.viewModelScope import com.github.feelbeatapp.androidclient.network.api.FeelBeatApi diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/viewmodels/RoomSettingsViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/viewmodels/RoomSettingsViewModel.kt similarity index 87% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/viewmodels/RoomSettingsViewModel.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/viewmodels/RoomSettingsViewModel.kt index ae662dc..8b8fb80 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/viewmodels/RoomSettingsViewModel.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/app/roomsettings/viewmodels/RoomSettingsViewModel.kt @@ -1,8 +1,7 @@ -package com.github.feelbeatapp.androidclient.ui.roomsettings.viewmodels +package com.github.feelbeatapp.androidclient.ui.app.roomsettings.viewmodels import androidx.lifecycle.ViewModel -import com.github.feelbeatapp.androidclient.ui.model.RoomSettings -import dagger.hilt.android.lifecycle.HiltViewModel +import com.github.feelbeatapp.androidclient.ui.app.model.RoomSettings import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeRoute.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeRoute.kt deleted file mode 100644 index 3e2bd53..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeRoute.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui.home - -enum class HomeRoute { - HOME, - ROOM_SETTINGS, - ACCEPT_GAME, -} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeScreen.kt deleted file mode 100644 index 54aaa5d..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeScreen.kt +++ /dev/null @@ -1,267 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui.home - -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Add -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.CenterAlignedTopAppBar -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -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 androidx.navigation.NavController -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController -import coil3.compose.AsyncImage -import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.model.Room -import com.github.feelbeatapp.androidclient.ui.FeelBeatRoute -import com.github.feelbeatapp.androidclient.ui.acceptgame.AcceptGameScreen -import com.github.feelbeatapp.androidclient.ui.roomsettings.screens.EditRoomSettingsScreen - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun HomeScreen( - viewModel: HomeViewModel = hiltViewModel(), - modifier: Modifier = Modifier, - navController: NavController, -) { - val title = stringResource(R.string.feel_beat) - val playerName by viewModel.playerName.collectAsState() - val playerImageUrl by viewModel.playerImageUrl.collectAsState() - val internalNavController = rememberNavController() - - var isBottomSheetVisible by remember { mutableStateOf(false) } - - if (isBottomSheetVisible) { - ModalBottomSheet(onDismissRequest = { isBottomSheetVisible = false }) { - UserAccountBottomSheetContent( - onLogoutClick = { - viewModel.logout() - isBottomSheetVisible = false - navController.navigate(FeelBeatRoute.LOGIN.name) - }, - name = playerName.toString(), - imageUrl = playerImageUrl.toString(), - ) - } - } - - Scaffold( - topBar = { - HomeTopBar(title, imageUrl = playerImageUrl.toString()) { isBottomSheetVisible = true } - } - ) { innerPadding -> - Column(modifier = modifier.padding(innerPadding).fillMaxSize()) { - NavHost(internalNavController, startDestination = HomeRoute.HOME.name) { - composable(route = HomeRoute.HOME.name) { - HomeBody( - viewModel = viewModel, - internalNavController = internalNavController, - navController = navController, - ) - } - composable(route = HomeRoute.ACCEPT_GAME.name) { - AcceptGameScreen( - internalNavController = internalNavController, - navController = navController, - ) - } - composable(route = HomeRoute.ROOM_SETTINGS.name) { - EditRoomSettingsScreen(internalNavController = internalNavController) - } - } - } - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun HomeTopBar(title: String, imageUrl: String, onAccountClick: () -> Unit) { - CenterAlignedTopAppBar( - title = { Text(title) }, - colors = - TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme.primaryContainer, - titleContentColor = MaterialTheme.colorScheme.primary, - ), - actions = { - IconButton(onClick = onAccountClick) { - AsyncImage( - model = imageUrl, - contentDescription = "Player Image", - modifier = Modifier.size(80.dp).clip(MaterialTheme.shapes.large), - contentScale = ContentScale.Crop, - placeholder = painterResource(R.drawable.account), - error = painterResource(R.drawable.account), - ) - } - }, - ) -} - -@Composable -fun HomeBody( - viewModel: HomeViewModel, - navController: NavController, - internalNavController: NavController, -) { - val rooms by viewModel.rooms.collectAsState() - val selectedRoom by viewModel.selectedRoom.collectAsState() - - Column(modifier = Modifier.fillMaxSize()) { - Text( - text = stringResource(R.string.current_games), - style = MaterialTheme.typography.titleMedium, - modifier = Modifier.padding(16.dp), - ) - - LazyColumn( - modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp).weight(1f), - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - items(rooms) { room -> - RoomItem( - room = room, - isSelected = room == selectedRoom, - onClick = { internalNavController.navigate(FeelBeatRoute.ACCEPT_GAME.name) }, - ) - } - } - - Box( - modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp).padding(horizontal = 16.dp) - ) { - Box( - modifier = - Modifier.align(Alignment.BottomEnd) - .size(60.dp) - .background( - MaterialTheme.colorScheme.primary, - shape = MaterialTheme.shapes.medium, - ) - ) { - IconButton( - onClick = { navController.navigate(FeelBeatRoute.NEW_ROOM_SETTINGS.name) }, - modifier = Modifier.fillMaxSize(), - ) { - Icon( - imageVector = Icons.Default.Add, - contentDescription = "Add", - modifier = Modifier.size(36.dp), - tint = MaterialTheme.colorScheme.onPrimary, - ) - } - } - } - } -} - -@Composable -fun UserAccountBottomSheetContent(onLogoutClick: () -> Unit, name: String, imageUrl: String) { - Column( - modifier = Modifier.fillMaxWidth().padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(16.dp), - ) { - Box( - modifier = - Modifier.size(80.dp).background(Color.Gray, shape = MaterialTheme.shapes.large), - contentAlignment = Alignment.Center, - ) { - AsyncImage( - model = imageUrl, - contentDescription = "Player Image", - modifier = Modifier.size(80.dp).clip(MaterialTheme.shapes.large), - contentScale = ContentScale.Crop, - placeholder = painterResource(R.drawable.account), - error = painterResource(R.drawable.account), - ) - } - Text(text = name, style = MaterialTheme.typography.titleMedium) - Box( - modifier = - Modifier.fillMaxWidth() - .background(MaterialTheme.colorScheme.primary, MaterialTheme.shapes.medium) - .padding(8.dp), - contentAlignment = Alignment.Center, - ) { - Text( - text = "log out", - style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.onPrimary, - modifier = Modifier.padding(vertical = 4.dp).clickable { onLogoutClick() }, - ) - } - } -} - -@Composable -fun RoomItem(room: Room, isSelected: Boolean, onClick: () -> Unit) { - Card( - onClick = onClick, - colors = - CardDefaults.cardColors( - containerColor = - if (isSelected) MaterialTheme.colorScheme.primaryContainer - else MaterialTheme.colorScheme.surface - ), - modifier = - Modifier.fillMaxWidth() - .padding(8.dp) - .border( - width = 1.dp, - color = MaterialTheme.colorScheme.outline, - shape = MaterialTheme.shapes.medium, - ), - ) { - Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(16.dp)) { - Text( - text = room.name, - style = MaterialTheme.typography.bodyLarge, - modifier = Modifier.weight(1f), - ) - } - } -} - -@Preview -@Composable -fun HomePreview() { - val navController = rememberNavController() - HomeScreen(navController = navController) -} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeViewModel.kt deleted file mode 100644 index 06d507d..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/home/HomeViewModel.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui.home - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.github.feelbeatapp.androidclient.auth.AuthManager -import com.github.feelbeatapp.androidclient.network.spotify.KtorSpotifyAPI -import com.github.feelbeatapp.androidclient.ui.model.Room -import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch - -@HiltViewModel -class HomeViewModel -@Inject -constructor(private val authManager: AuthManager, private val spotifyAPI: KtorSpotifyAPI) : - ViewModel() { - private val _rooms = MutableStateFlow>(emptyList()) - val rooms: StateFlow> = _rooms.asStateFlow() - - private val _selectedRoom = MutableStateFlow(null) - val selectedRoom: StateFlow = _selectedRoom.asStateFlow() - - private val _playerName = MutableStateFlow(null) - val playerName: StateFlow = _playerName.asStateFlow() - - private val _playerImageUrl = MutableStateFlow(null) - val playerImageUrl: StateFlow = _playerImageUrl.asStateFlow() - - init { - loadRooms() - loadPlayerData() - } - - private fun loadPlayerData() { - viewModelScope.launch { - try { - val profile = spotifyAPI.getProfile() - _playerName.value = profile.displayName - _playerImageUrl.value = profile.images.first().url - } catch (e: Exception) { - print(e.message) - _playerName.value = "Player" - } - } - } - - fun logout() { - authManager.logout() - } - - @SuppressWarnings("MagicNumber") - private fun loadRooms() { - viewModelScope.launch { - val exampleRooms = - listOf( - Room(1, "Pokój 1", 4, 30, 10, "https://example.com/playlist1"), - Room(2, "Pokój 2", 5, 20, 5, "https://example.com/playlist2"), - Room(3, "Pokój 3", 2, 25, 3, "https://example.com/playlist3"), - Room(4, "Pokój 4", 4, 30, 4, "https://example.com/playlist4"), - Room(5, "Pokój 5", 5, 25, 4, "https://example.com/playlist5"), - Room(6, "Pokój 6", 2, 25, 10, "https://example.com/playlist6"), - Room(7, "Pokój 7", 4, 30, 9, "https://example.com/playlist7"), - ) - _rooms.value = exampleRooms - } - } - - fun selectRoom(room: Room) { - _selectedRoom.value = room - } - - fun addRoom(name: String) { - val newRoom = - Room( - id = _rooms.value.size + 1, - name = name, - maxPlayers = 4, - snippetDuration = 30, - pointsToWin = 10, - playlistLink = "link", - ) - _rooms.value += newRoom - } -} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/AuthActivity.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/login/AuthActivity.kt similarity index 92% rename from app/src/main/java/com/github/feelbeatapp/androidclient/ui/AuthActivity.kt rename to app/src/main/java/com/github/feelbeatapp/androidclient/ui/login/AuthActivity.kt index e755a92..becc1a4 100644 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/AuthActivity.kt +++ b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/login/AuthActivity.kt @@ -1,4 +1,4 @@ -package com.github.feelbeatapp.androidclient.ui +package com.github.feelbeatapp.androidclient.ui.login import android.content.Intent import android.net.Uri @@ -7,7 +7,7 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import com.github.feelbeatapp.androidclient.auth.AuthManager -import com.github.feelbeatapp.androidclient.ui.login.AuthLoadingScreen +import com.github.feelbeatapp.androidclient.ui.MainActivity import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject import kotlinx.coroutines.CoroutineScope diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Player.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Player.kt deleted file mode 100644 index ecd117a..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Player.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui.model - -data class Player(val name: String, val image: Int) diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/PlayerWithResult.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/PlayerWithResult.kt deleted file mode 100644 index 4c88e59..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/PlayerWithResult.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui.model - -import com.github.feelbeatapp.androidclient.ui.guesssong.ResultStatus - -data class PlayerWithResult(val player: Player, val resultStatus: ResultStatus, val points: Int) diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Song.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Song.kt deleted file mode 100644 index 189cf0d..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/model/Song.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui.model - -data class Song(val id: Int, val title: String) diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/screens/EditRoomSettingsScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/screens/EditRoomSettingsScreen.kt deleted file mode 100644 index eecbb41..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/screens/EditRoomSettingsScreen.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui.roomsettings.screens - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Home -import androidx.compose.material.icons.filled.Settings -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.NavigationBar -import androidx.compose.material3.NavigationBarItem -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -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.navigation.NavController -import androidx.navigation.compose.rememberNavController -import com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.FeelBeatRoute -import com.github.feelbeatapp.androidclient.ui.roomsettings.components.SettingsControls -import com.github.feelbeatapp.androidclient.ui.roomsettings.viewmodels.EditRoomSettingsViewModel -import com.github.feelbeatapp.androidclient.ui.roomsettings.viewmodels.RoomSettingsViewModel - -@Composable -fun EditRoomSettingsScreen( - viewModel: RoomSettingsViewModel = EditRoomSettingsViewModel(), - internalNavController: NavController, - modifier: Modifier = Modifier, - isRoomCreator: Boolean = true, -) { - Scaffold( - bottomBar = { - if (isRoomCreator) { - BottomNavigationBar(navController = internalNavController) - } - }, - content = { padding -> - Column( - modifier = modifier.fillMaxSize().padding(padding).padding(16.dp), - verticalArrangement = Arrangement.spacedBy(24.dp), - ) { - SettingsControls(viewModel) - } - }, - ) -} - -@Composable -fun BottomNavigationBar(navController: NavController, modifier: Modifier = Modifier) { - NavigationBar( - modifier = modifier, - containerColor = MaterialTheme.colorScheme.surface, - contentColor = MaterialTheme.colorScheme.primary, - ) { - NavigationBarItem( - icon = { - Icon(Icons.Filled.Home, contentDescription = stringResource(R.string.selected_room)) - }, - label = { Text(stringResource(R.string.selected_room)) }, - selected = false, - onClick = { navController.navigate(FeelBeatRoute.ACCEPT_GAME.name) }, - ) - NavigationBarItem( - icon = { - Icon(Icons.Filled.Settings, contentDescription = stringResource(R.string.settings)) - }, - label = { Text(stringResource(R.string.settings)) }, - selected = false, - onClick = { navController.navigate(FeelBeatRoute.ROOM_SETTINGS.name) }, - ) - } -} - -@Preview(showBackground = true, widthDp = 360, heightDp = 640) -@Composable -fun PreviewRoomSettingsScreen() { - val navController = rememberNavController() - EditRoomSettingsScreen(internalNavController = navController) -} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/screens/NewRoomSettingsScreen.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/screens/NewRoomSettingsScreen.kt deleted file mode 100644 index 4e4a8ad..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/screens/NewRoomSettingsScreen.kt +++ /dev/null @@ -1,103 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui.roomsettings.screens - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft -import androidx.compose.material3.Button -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBar -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -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 com.github.feelbeatapp.androidclient.R -import com.github.feelbeatapp.androidclient.ui.FeelBeatRoute -import com.github.feelbeatapp.androidclient.ui.roomsettings.components.SettingsControls -import com.github.feelbeatapp.androidclient.ui.roomsettings.viewmodels.NewRoomSettingsViewModel - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun NewRoomSettingsScreen( - viewModel: NewRoomSettingsViewModel = hiltViewModel(), - onNavigateTo: (String) -> Unit, - onNavigateBack: () -> Unit, - modifier: Modifier = Modifier, -) { - val roomCreationState by viewModel.roomCreationState.collectAsState() - val createdRoomId by viewModel.roomCreated.collectAsState(null) - - val roomId = createdRoomId - if (roomId != null) { - onNavigateTo(FeelBeatRoute.ACCEPT_GAME.withArgs(roomId)) - } - - Scaffold( - topBar = { - TopAppBar( - title = { Text(stringResource(R.string.new_room)) }, - navigationIcon = { - IconButton(onClick = onNavigateBack) { - Icon( - Icons.AutoMirrored.Filled.KeyboardArrowLeft, - contentDescription = stringResource(R.string.back), - ) - } - }, - ) - }, - content = { padding -> - Column( - modifier = modifier.fillMaxSize().padding(padding).padding(16.dp), - verticalArrangement = Arrangement.spacedBy(24.dp), - ) { - SettingsControls(viewModel = viewModel) - - Text(roomCreationState.errorMessage ?: "") - - if (roomCreationState.loading) { - Row( - horizontalArrangement = Arrangement.Center, - modifier = Modifier.fillMaxWidth(), - ) { - CircularProgressIndicator( - color = MaterialTheme.colorScheme.secondary, - trackColor = MaterialTheme.colorScheme.surfaceVariant, - strokeWidth = 4.dp, - modifier = Modifier.width(50.dp).height(50.dp), - ) - } - } else if (createdRoomId == null) { - Button( - onClick = { viewModel.createRoom() }, - modifier = Modifier.fillMaxWidth().height(56.dp), - ) { - Text(stringResource(R.string.create_room)) - } - } - } - }, - ) -} - -@Preview(showBackground = true, widthDp = 360, heightDp = 640) -@Composable -fun PreviewSettingsScreen() { - NewRoomSettingsScreen(onNavigateTo = {}, onNavigateBack = {}) -} diff --git a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/viewmodels/EditRoomSettingsViewModel.kt b/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/viewmodels/EditRoomSettingsViewModel.kt deleted file mode 100644 index 828b1c3..0000000 --- a/app/src/main/java/com/github/feelbeatapp/androidclient/ui/roomsettings/viewmodels/EditRoomSettingsViewModel.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.github.feelbeatapp.androidclient.ui.roomsettings.viewmodels - -class EditRoomSettingsViewModel : RoomSettingsViewModel() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 83e7531..c0f30be 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,5 @@ - FeelBeatAndroidClient + FeelBeat Go back Settings Account @@ -13,7 +13,7 @@ Snippet Duration: %1$d seconds Points to Win: %1$d Playlist: %1$s - New room + Create new room Max number of players How many turns How many points per second you loose @@ -34,4 +34,5 @@ Authorization server is unreachable With how many points you starting to guess How many points you will loose after incorrect guess + Get ready \ No newline at end of file