Compare commits

...

No commits in common. 'navigation' and 'master' have entirely different histories.

@ -7,13 +7,13 @@ import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
@ -33,13 +33,11 @@ import com.iqball.app.net.service.IQBallService
import com.iqball.app.page.HomePage import com.iqball.app.page.HomePage
import com.iqball.app.page.LoginPage import com.iqball.app.page.LoginPage
import com.iqball.app.page.RegisterPage import com.iqball.app.page.RegisterPage
import com.iqball.app.page.VisualizerPage
import com.iqball.app.serialization.EitherTypeAdapterFactory import com.iqball.app.serialization.EitherTypeAdapterFactory
import com.iqball.app.serialization.EnumTypeAdapterFactory import com.iqball.app.serialization.EnumTypeAdapterFactory
import com.iqball.app.session.DataSession import com.iqball.app.session.DataSession
import com.iqball.app.session.Session import com.iqball.app.session.Session
import com.iqball.app.ui.theme.IQBallTheme import com.iqball.app.ui.theme.IQBallTheme
import com.iqball.app.vm.SessionViewModel
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
@ -96,7 +94,8 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background color = MaterialTheme.colorScheme.background
) { ) {
App(service) val sessionState = remember { mutableStateOf<Session>(DataSession()) }
App(service, sessionState)
} }
} }
} }
@ -104,16 +103,16 @@ class MainActivity : ComponentActivity() {
} }
@Composable @Composable
fun App(service: IQBallService) { fun App(service: IQBallService, sessionState: MutableState<Session>) {
val navController = rememberNavController() val navController = rememberNavController()
var session by viewModel<SessionViewModel>().session
NavHost(navController = navController, startDestination = "login") { NavHost(navController = navController, startDestination = "login") {
composable("login") { composable("login") {
LoginPage( LoginPage(
service = service, service = service,
onLoginSuccess = { auth -> onLoginSuccess = { auth ->
session = DataSession(auth) Log.i("ZIZI", "auth : ${auth}")
sessionState.value = DataSession(auth)
navController.navigate("home") navController.navigate("home")
Log.i("ZIZI", "auth : ${auth}") Log.i("ZIZI", "auth : ${auth}")
}, },
@ -126,7 +125,7 @@ fun App(service: IQBallService) {
RegisterPage( RegisterPage(
service = service, service = service,
onRegisterSuccess = { auth -> onRegisterSuccess = { auth ->
session = DataSession(auth) sessionState.value = DataSession(auth)
navController.navigate("home") navController.navigate("home")
}, },
onNavigateToLogin = { onNavigateToLogin = {
@ -135,10 +134,7 @@ fun App(service: IQBallService) {
) )
} }
composable("home") { composable("home") {
HomePage(service = service, auth = session.auth!!, navController = navController) HomePage(service = service, sessionState.value.auth!!)
}
composable("view/{id}") {
VisualizerPage(service = service, auth = session.auth!!, tacticId = it.arguments!!.getString("id")!!.toInt())
} }
} }
} }

@ -1,12 +1,14 @@
package com.iqball.app.page package com.iqball.app.page
import com.iqball.app.model.Tactic
import com.iqball.app.model.Team
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Canvas import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -20,6 +22,7 @@ import androidx.compose.foundation.lazy.staggeredgrid.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.core.graphics.toColorInt
import androidx.compose.material3.CenterAlignedTopAppBar import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -28,28 +31,24 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarDefaults.pinnedScrollBehavior import androidx.compose.material3.TopAppBarDefaults.pinnedScrollBehavior
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.graphics.toColorInt
import androidx.navigation.NavController
import arrow.core.Either import arrow.core.Either
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.iqball.app.model.Tactic import com.iqball.app.net.service.AuthService
import com.iqball.app.model.Team
import com.iqball.app.net.service.IQBallService import com.iqball.app.net.service.IQBallService
import com.iqball.app.net.service.UserService import com.iqball.app.net.service.UserService
import com.iqball.app.session.Authentication import com.iqball.app.session.Authentication
@ -61,17 +60,15 @@ import java.time.format.DateTimeFormatter
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun HomePage(service: IQBallService, fun HomePage(service: IQBallService, auth: Authentication) {
auth: Authentication,
navController: NavController) {
val tactics: List<Tactic> val tactics: List<Tactic>
val teams: List<Team> val teams: List<Team>
var invalid = false var invalid = false
val data = getDataFromApi(service, auth) val data = getDataFromApi(service, auth)
if (data == null) { if (data == null) {
tactics = listOf() tactics = listOf<Tactic>()
teams = listOf() teams = listOf<Team>()
invalid = true invalid = true
} else { } else {
@ -99,7 +96,7 @@ fun HomePage(service: IQBallService,
) )
}, },
) { innerPadding -> ) { innerPadding ->
Body(innerPadding, tactics, teams, invalid, navController) Body(innerPadding, tactics, teams, invalid)
} }
} }
@ -108,8 +105,7 @@ private fun Body(
padding: PaddingValues, padding: PaddingValues,
tactics: List<Tactic>, tactics: List<Tactic>,
teams: List<Team>, teams: List<Team>,
invalid: Boolean, invalid: Boolean
navController: NavController
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
@ -119,9 +115,7 @@ private fun Body(
val tabs = listOf<Pair<String, @Composable () -> Unit>>( val tabs = listOf<Pair<String, @Composable () -> Unit>>(
Pair("Espace personnel") { Pair("Espace personnel") {
ListComponentCard(tactics) { tactic -> ListComponentCard(tactics) { tactic ->
TacticCard(tactic = tactic, onClick = { TacticCard(tactic = tactic)
navController.navigate("view/${tactic.id}")
})
} }
}, },
Pair("Mes équipes") { Pair("Mes équipes") {
@ -136,6 +130,7 @@ private fun Body(
return return
} }
TextCentered( TextCentered(
text = "Erreur : Aucune connexion internet. Veillez activer votre connexion internet puis relancer l'application", text = "Erreur : Aucune connexion internet. Veillez activer votre connexion internet puis relancer l'application",
fontSize = 20.sp fontSize = 20.sp
@ -202,7 +197,7 @@ private fun <C> ListComponentCard(items: List<C>, componentCard: @Composable (C)
} }
@Composable @Composable
private fun TacticCard(tactic: Tactic, onClick: () -> Unit) { private fun TacticCard(tactic: Tactic) {
Column( Column(
modifier = Modifier modifier = Modifier
.padding(5.dp) .padding(5.dp)
@ -215,7 +210,6 @@ private fun TacticCard(tactic: Tactic, onClick: () -> Unit) {
color = Color.White color = Color.White
) )
.padding(15.dp) .padding(15.dp)
.clickable { onClick() }
) { ) {
Row { Row {
TextCentered(text = tactic.name, fontSize = 16.sp) TextCentered(text = tactic.name, fontSize = 16.sp)

@ -4,7 +4,6 @@ import android.content.res.Configuration
import android.util.Log import android.util.Log
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -44,7 +43,6 @@ import com.iqball.app.model.tactic.StepContent
import com.iqball.app.model.tactic.StepNodeInfo import com.iqball.app.model.tactic.StepNodeInfo
import com.iqball.app.model.tactic.getParent import com.iqball.app.model.tactic.getParent
import com.iqball.app.net.service.TacticService import com.iqball.app.net.service.TacticService
import com.iqball.app.session.Authentication
import com.iqball.app.session.Token import com.iqball.app.session.Token
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.engawapg.lib.zoomable.ZoomState import net.engawapg.lib.zoomable.ZoomState
@ -61,10 +59,10 @@ private data class VisualizerInitialData(
@Composable @Composable
fun VisualizerPage( fun VisualizerPage(
service: TacticService, service: TacticService,
auth: Authentication, auth: Token,
tacticId: Int, tacticId: Int,
) { ) {
val dataEither = remember { initializeVisualizer(service, auth.token, tacticId) } val dataEither = remember { initializeVisualizer(service, auth, tacticId) }
val showTree = remember { mutableStateOf(true) } val showTree = remember { mutableStateOf(true) }
val (info, stepsTree) = when (dataEither) { val (info, stepsTree) = when (dataEither) {
@ -74,7 +72,7 @@ fun VisualizerPage(
} }
fun getStepContent(step: Int): StepContent = runBlocking { fun getStepContent(step: Int): StepContent = runBlocking {
val result = service.getTacticStepContent(auth.token, tacticId, step).onLeft { val result = service.getTacticStepContent(auth, tacticId, step).onLeft {
Log.e( Log.e(
"received error response from server when retrieving step content: {}", "received error response from server when retrieving step content: {}",
it.toString() it.toString()
@ -115,6 +113,7 @@ fun VisualizerPage(
val courtModifier = val courtModifier =
if (showTree.value) Modifier.width(IntrinsicSize.Min) else Modifier.fillMaxWidth() if (showTree.value) Modifier.width(IntrinsicSize.Min) else Modifier.fillMaxWidth()
val courtZoomState = remember { ZoomState() } val courtZoomState = remember { ZoomState() }
Row(modifier = Modifier.background(Color.LightGray)) { Row(modifier = Modifier.background(Color.LightGray)) {
@ -143,27 +142,32 @@ fun VisualizerPage(
else -> throw Exception("Could not determine device's orientation.") else -> throw Exception("Could not determine device's orientation.")
} }
} }
} }
@Composable @Composable
private fun VisualizerHeader(title: String, showTree: MutableState<Boolean>) { private fun VisualizerHeader(title: String, showTree: MutableState<Boolean>) {
Box(
Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.zIndex(10000F) .zIndex(10000F)
.background(Color.White), .background(Color.White),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) { ) {
IconButton(onClick = { /*TODO*/ }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Back",
tint = Color.Black
)
}
Text( Text(text = title, color = Color.Black)
text = title,
color = Color.Black,
modifier = Modifier.align(Alignment.Center)
)
IconButton( IconButton(onClick = { showTree.value = !showTree.value }) {
onClick = { showTree.value = !showTree.value },
modifier = Modifier.align(Alignment.CenterEnd)
) {
Icon( Icon(
painter = painterResource(id = R.drawable.tree_icon), painter = painterResource(id = R.drawable.tree_icon),
contentDescription = "toggle show tree" contentDescription = "toggle show tree"

@ -1,4 +1,4 @@
package com.iqball.app.session package com.iqball.app.session
typealias Token = String typealias Token = String
data class Authentication(val token: Token, val expirationDate: Long) data class Authentication(val token: String, val expirationDate: Long)

@ -1,11 +0,0 @@
package com.iqball.app.vm
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import com.iqball.app.session.DataSession
import com.iqball.app.session.Session
class SessionViewModel : ViewModel() {
val session: MutableState<Session> = mutableStateOf(DataSession())
}
Loading…
Cancel
Save