Compare commits

..

5 Commits

@ -1,7 +1,6 @@
plugins { plugins {
id("com.android.application") id("com.android.application")
id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.android")
kotlin("plugin.serialization") version "1.5.10"
} }
android { android {
@ -56,24 +55,12 @@ dependencies {
implementation ("com.squareup.retrofit2:retrofit:2.9.0") implementation ("com.squareup.retrofit2:retrofit:2.9.0")
implementation ("com.squareup.retrofit2:converter-gson:2.9.0") implementation ("com.squareup.retrofit2:converter-gson:2.9.0")
implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0")
implementation ("androidx.compose.runtime:runtime-livedata:1.0.0-alpha07")
implementation("androidx.core:core-ktx:1.10.1") implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
implementation("androidx.activity:activity-compose:1.7.0") implementation("androidx.activity:activity-compose:1.7.0")
implementation("androidx.navigation:navigation-compose:2.4.0-alpha08") implementation("androidx.navigation:navigation-compose:2.4.0-alpha08")
implementation ("androidx.media3:media3-session:1.3.0")
implementation("com.google.android.exoplayer:exoplayer-core:2.19.1")
implementation ("com.google.android.exoplayer:exoplayer-ui:2.19.1")
implementation ("com.squareup.okhttp3:logging-interceptor:4.9.1")
implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
implementation ("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0")
implementation(platform("androidx.compose:compose-bom:2023.08.00")) implementation(platform("androidx.compose:compose-bom:2023.08.00"))
implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-graphics")

@ -12,10 +12,7 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.VeraxApplication" android:theme="@style/Theme.VeraxApplication"
tools:targetApi="31" tools:targetApi="31">
android:networkSecurityConfig="@xml/network_security_config"
>
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"

@ -1,63 +1,49 @@
package com.example.veraxapplication package com.example.veraxapplication
import ArticlesViewModel
import IUsersDataManager
import StubUsers
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color
import androidx.compose.runtime.getValue import com.example.veraxapplication.articles.IArticlesDataManager
import androidx.compose.runtime.livedata.observeAsState
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.veraxapplication.modele.IArticlesDataManager
import com.example.veraxapplication.articles.StubArticles import com.example.veraxapplication.articles.StubArticles
import com.example.veraxapplication.modele.api.UsersViewModel import com.example.veraxapplication.modele.ApiClient
import com.example.veraxapplication.modele.articles.Article
import com.example.veraxapplication.navigation.VeraxNavHost import com.example.veraxapplication.navigation.VeraxNavHost
import com.example.veraxapplication.ui.connexion.AfficherForm import com.example.veraxapplication.ui.article.AfficherArticle
import com.example.veraxapplication.ui.topBar.TopBarVerax import com.example.veraxapplication.ui.topBar.TopBarVerax
// doc navBar: https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#TopAppBar(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Function0,kotlin.Function1,androidx.compose.foundation.layout.WindowInsets,androidx.compose.material3.TopAppBarColors,androidx.compose.material3.TopAppBarScrollBehavior) // doc navBar: https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#TopAppBar(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Function0,kotlin.Function1,androidx.compose.foundation.layout.WindowInsets,androidx.compose.material3.TopAppBarColors,androidx.compose.material3.TopAppBarScrollBehavior)
// doc compose, pleins de trucs: https://developer.android.com/jetpack/compose/text?hl=fr // doc compose, pleins de trucs: https://developer.android.com/jetpack/compose/text?hl=fr
//doc couleur background pas finie: https://developer.android.com/jetpack/compose/components/scaffold //doc couleur background pas finie: https://developer.android.com/jetpack/compose/components/scaffold
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
VeraxContent()
}
}
}
@Composable class MainActivity : ComponentActivity() {
fun VeraxContent() {
// un truc vite fait pour avoir un visi
// var article = listOf("Thinkerview", "thinkerview.jgp", "Thinkerview est une chaîne youtube d'interview-débat")
//var articles = listOf( Article("Thinkerview", "This is a descrition", Author = "IAmAGreatAuthor", Image = "https://www.gstatic.com/webp/gallery/1.jpg", LectureTime = "12", Content = listOf(Paragraph("This is a paragraph"), Paragraph("This is another paragraph"), Paragraph("This is a third paragraph"))), Article("Thinkerview", "This is a descrition", Author = "IAmAGreatAuthor", Image = "https://www.gstatic.com/webp/gallery/1.jpg", LectureTime = "12", Content = listOf(Paragraph("This is a paragraph"), Paragraph("This is another paragraph"), Paragraph("This is a third paragraph"))))
// Initialiser les données ou observer les données du ViewModel
var dataManager: IArticlesDataManager = StubArticles() var dataManager: IArticlesDataManager = StubArticles()
var articles = dataManager.getDerniersArticles(4) var articles = dataManager.getDerniersArticles(4)
val articlesApi = ApiClient.apiService.getArticles()
var usersManager: IUsersDataManager = StubUsers()
var users = usersManager.getUsers();
// Observer les données du ViewModel var theme = listOf("Economique", "Culture", "Politique", "Faits divers")
val articlesViewModel: ArticlesViewModel = viewModel()
// Observez les articles du ViewModel
val articlesApi by articlesViewModel.articles.observeAsState(initial = articles)
val usersViewModel: UsersViewModel = viewModel()
val usersApi by usersViewModel.users.observeAsState(initial = users) override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
var theme = listOf("Economique", "Culture", "Politique", "Faits divers") // TopBarVerax(theme = theme, articles = articlesApi)
TopBarVerax(theme = theme, articles = articles)
// VeraxNavHost()
TopBarVerax(articles = articlesApi, theme = theme, articlesStub= articles) }
}
} }

@ -1,11 +0,0 @@
package com.example.veraxapplication.data
/*
data class Article(
var Title : String,
var Description : String,
var Image : String,
var Author : String,
var Content : List<Paragraph>,
var LectureTime : String
)
*/

@ -1,6 +0,0 @@
package com.example.veraxapplication.data
/*
data class Paragraph(
var Content : String,
)
*/

@ -0,0 +1,22 @@
package com.example.veraxapplication.modele
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitClient {
private const val BASE_URL = "http://181.214.189.133:9092/"
val retrofit: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
}
object ApiClient {
val apiService: ApiService by lazy {
RetrofitClient.retrofit.create(ApiService::class.java)
}
}

@ -0,0 +1,10 @@
package com.example.veraxapplication.modele
import com.example.veraxapplication.modele.articles.Article
import retrofit2.Call
import retrofit2.http.GET
interface ApiService {
@GET("articles/")
fun getArticles(): Call<List<Article>>
}

@ -1,4 +1,4 @@
package com.example.veraxapplication.modele package com.example.veraxapplication.articles
import com.example.veraxapplication.modele.articles.Article import com.example.veraxapplication.modele.articles.Article

@ -1,9 +0,0 @@
import com.example.veraxapplication.modele.user.User
interface IUsersDataManager {
val allUsers: List<Any?>?
fun getUser(pseudo : String): User?
fun getUsers(): List<User>
}

@ -1,53 +0,0 @@
package com.example.veraxapplication.modele.api
import com.example.veraxapplication.modele.articles.Article
import com.google.gson.annotations.SerializedName
data class ArticleDTO (
@SerializedName("id")
val id: Int,
@SerializedName("titre")
val titre: String,
@SerializedName("description")
val description: String,
@SerializedName("temps")
val temps: String,
@SerializedName("date")
val date: String,
@SerializedName("auteur")
val auteur: String,
@SerializedName("categorie")
val categorie: String,
@SerializedName("imagePrincipale")
val imagePrincipale: String,
@SerializedName("note")
val note: String,
) {
fun toModel(): Article {
return Article(
id,
titre,
description,
temps,
date,
auteur,
categorie,
imagePrincipale,
note,
)
}
}
data class ContenuDTO (
@SerializedName("id")
val id: Int,
@SerializedName("typeContenu")
val typeContenu: String,
@SerializedName("titre")
val titre: String,
@SerializedName("texte")
val texte: String,
)

@ -1,54 +0,0 @@
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.veraxapplication.modele.api.IArticleService
import com.example.veraxapplication.modele.articles.Article
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object ArticleApiClient {
private const val BASE_URL = "http://181.214.189.133:9092/"
private val logging = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
private val httpClient = OkHttpClient.Builder().apply {
addInterceptor(logging)
}.build()
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build()
}
class ArticlesViewModel : ViewModel() {
private val _articles = MutableLiveData<List<Article>>()
val articles: LiveData<List<Article>> = _articles
private val service = ArticleApiClient.retrofit.create(IArticleService::class.java)
init {
loadArticles()
}
fun loadArticles() {
viewModelScope.launch {
try {
val articlesDto = service.getArticles() // Pas besoin d'appeler .execute()
// Convertissez les DTO en modèles de données si nécessaire
_articles.value = articlesDto.map { it.toModel() }
} catch (e: Exception) {
Log.e("ArticlesViewModel", "Erreur lors du chargement des articles", e)
}
}
}
}

@ -1,8 +0,0 @@
package com.example.veraxapplication.modele.api
import retrofit2.http.GET
interface IArticleService {
@GET("articles")
suspend fun getArticles(): List<ArticleDTO>
}

@ -1,11 +0,0 @@
package com.example.veraxapplication.modele.api
import com.example.veraxapplication.modele.user.User
import retrofit2.Call
import retrofit2.http.GET
interface IUserService {
@GET("users")
suspend fun getUsers(): List<UserDTO>
}

@ -1,32 +0,0 @@
package com.example.veraxapplication.modele.api
import com.example.veraxapplication.modele.user.User
import com.google.gson.annotations.SerializedName
data class UserDTO (
@SerializedName("pseudo")
val pseudo: String,
@SerializedName("mdp")
val mdp: String,
@SerializedName("mail")
val mail: String,
@SerializedName("nom")
val nom: String,
@SerializedName("prenom")
val prenom: String,
@SerializedName("role")
val role: String,
) {
fun toModel(): User {
return User(
pseudo,
mdp,
mail,
nom,
prenom,
role,
)
}
}

@ -1,63 +0,0 @@
package com.example.veraxapplication.modele.api
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.veraxapplication.modele.articles.Article
import com.example.veraxapplication.modele.user.User
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitClientUser {
private const val BASE_URL = "https://codefirst.iut.uca.fr/containers/Verax-verax-api"
private val logging = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
private val httpClient = OkHttpClient.Builder().apply {
addInterceptor(logging)
}.build()
val retrofit: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
// interface UserApiService {
// @GET("users")
// suspend fun getUsers() : List<User>
// }
}
class UsersViewModel : ViewModel() {
private val _users = MutableLiveData<List<User>>()
val users: LiveData<List<User>> = _users
private val service = ArticleApiClient.retrofit.create(IUserService::class.java)
init {
loadUsers()
}
fun loadUsers() {
viewModelScope.launch {
try {
val usersDto = service.getUsers() // Pas besoin d'appeler .execute()
// Convertissez les DTO en modèles de données si nécessaire
_users.value = usersDto.map { it.toModel() }
} catch (e: Exception) {
Log.e("UsersViewModel", "Erreur lors du chargement des users", e)
}
}
}
}

@ -9,11 +9,10 @@ class Article(
val temps: String, val temps: String,
val date: String, val date: String,
val auteur: String, val auteur: String,
val categorie: String, val imagePrincipale: String
val imagePrincipale: String,
val note: String
) { ) {
public val lContenus: MutableList<Contenu> = java.util.ArrayList() val note = 1.0
private val lContenus: MutableList<Contenu> = java.util.ArrayList()
init { init {
// Initialisation des contenus si nécessaire // Initialisation des contenus si nécessaire
@ -31,6 +30,4 @@ class Article(
override fun toString(): String { override fun toString(): String {
return "Article(id=$id, titre='$titre', description='$description', temps='$temps', date='$date', auteur='$auteur', imagePrincipale='$imagePrincipale', note=$note, contenus=${lContenus.size} contenus)" return "Article(id=$id, titre='$titre', description='$description', temps='$temps', date='$date', auteur='$auteur', imagePrincipale='$imagePrincipale', note=$note, contenus=${lContenus.size} contenus)"
} }
} }

@ -1,10 +1,13 @@
package com.example.veraxapplication.articles package com.example.veraxapplication.articles
import com.example.veraxapplication.modele.IArticlesDataManager import android.os.Build
import androidx.annotation.RequiresApi
import com.example.veraxapplication.modele.articles.Article import com.example.veraxapplication.modele.articles.Article
import com.example.veraxapplication.modele.articles.contenus.Contenu import com.example.veraxapplication.modele.articles.contenus.Contenu
import com.example.veraxapplication.modele.articles.contenus.ContenuMedia import com.example.veraxapplication.modele.articles.contenus.ContenuMedia
import com.example.veraxapplication.modele.articles.contenus.ContenuParagraphe import com.example.veraxapplication.modele.articles.contenus.ContenuParagraphe
import java.time.LocalDate
import kotlin.math.min
class StubArticles() : IArticlesDataManager { class StubArticles() : IArticlesDataManager {
@ -25,11 +28,9 @@ class StubArticles() : IArticlesDataManager {
"Thinkerview", "Thinkerview",
"Thinkerview est une chaîne passionnante chaîne youtube d'interview-débat.", "Thinkerview est une chaîne passionnante chaîne youtube d'interview-débat.",
"3", "3",
"02/09/2024", "date a revoir",
"Siwa", "Siwa",
"Politique", "https://cdn.discordapp.com/attachments/1150826798549049554/1219554341388816437/stub1.webp?ex=660bb97d&is=65f9447d&hm=3e1e8d3372ae897fa4e2aa1ec730d976d74b35fce96cb8d78d6f9239e2836564&"
"https://cdn.discordapp.com/attachments/1150826798549049554/1219554341388816437/stub1.webp?ex=660bb97d&is=65f9447d&hm=3e1e8d3372ae897fa4e2aa1ec730d976d74b35fce96cb8d78d6f9239e2836564&",
"12"
) )
article1.remplirArticle(contenuMap["article1"]) article1.remplirArticle(contenuMap["article1"])
lArticles!!.add(article1) lArticles!!.add(article1)
@ -40,11 +41,9 @@ class StubArticles() : IArticlesDataManager {
"Le réchauffement climatique : un mythe ?", "Le réchauffement climatique : un mythe ?",
"Revenons sur les différentes controverses à ce sujet.", "Revenons sur les différentes controverses à ce sujet.",
"7", "7",
"02/09/2024", "date a revoir",
"Siwa", "Siwa",
"Politique", "https://cdn.discordapp.com/attachments/1150826798549049554/1219555874339815454/stub2.webp?ex=660bbaea&is=65f945ea&hm=80aef945e8410b18395c716fdd19265608f7b1263731192d5c69f807fce9e944&"
"https://cdn.discordapp.com/attachments/1150826798549049554/1219555874339815454/stub2.webp?ex=660bbaea&is=65f945ea&hm=80aef945e8410b18395c716fdd19265608f7b1263731192d5c69f807fce9e944&",
"12"
) )
article2.remplirArticle(contenuMap["article5"]) article2.remplirArticle(contenuMap["article5"])
lArticles!!.add(article2) lArticles!!.add(article2)
@ -55,11 +54,9 @@ class StubArticles() : IArticlesDataManager {
"La terre plate : vraiment ?", "La terre plate : vraiment ?",
"Pour réfuter la fausse croyance que la Terre est plate, il est essentiel de s'appuyer sur des preuves scientifiques et des observations historiques. ", "Pour réfuter la fausse croyance que la Terre est plate, il est essentiel de s'appuyer sur des preuves scientifiques et des observations historiques. ",
"5", "5",
"02/09/2024", "date a revoir",
"Siwa", "Siwa",
"Politique", "https://cdn.discordapp.com/attachments/1150826798549049554/1219547864196317225/stub1.webp?ex=660bb374&is=65f93e74&hm=a9e5dd48faa3ae68c358309af8949c46dfd4dea9c4d6e3d845d707784e5341cf&"
"https://cdn.discordapp.com/attachments/1150826798549049554/1219547864196317225/stub1.webp?ex=660bb374&is=65f93e74&hm=a9e5dd48faa3ae68c358309af8949c46dfd4dea9c4d6e3d845d707784e5341cf&",
"12"
) )
article3.remplirArticle(contenuMap["article4"]) article3.remplirArticle(contenuMap["article4"])
lArticles!!.add(article3) lArticles!!.add(article3)
@ -70,11 +67,9 @@ class StubArticles() : IArticlesDataManager {
"L'ia & humanité : quel avenir ? ", "L'ia & humanité : quel avenir ? ",
"Explorons les progrès remarquables dans le domaine de l'IA, les secteurs qu'elle révolutionne, et les implications éthiques majeures qu'elle soulève.", "Explorons les progrès remarquables dans le domaine de l'IA, les secteurs qu'elle révolutionne, et les implications éthiques majeures qu'elle soulève.",
"9", "9",
"02/09/2024", "date a revoir",
"Luthen", "Luthen",
"Politique", "https://cdn.discordapp.com/attachments/1150826798549049554/1219560686254817290/stub1.webp?ex=660bbf65&is=65f94a65&hm=021bd8c90c89347f31373468cc7a03ae15f1d3f9988a5b4325149c6df938d7bb&"
"https://cdn.discordapp.com/attachments/1150826798549049554/1219560686254817290/stub1.webp?ex=660bbf65&is=65f94a65&hm=021bd8c90c89347f31373468cc7a03ae15f1d3f9988a5b4325149c6df938d7bb&",
"12"
) )
article4.remplirArticle(contenuMap["article6"]) article4.remplirArticle(contenuMap["article6"])
lArticles!!.add(article4) lArticles!!.add(article4)

@ -1,78 +0,0 @@
import com.example.veraxapplication.modele.IArticlesDataManager
import com.example.veraxapplication.modele.articles.Article
import com.example.veraxapplication.modele.articles.contenus.Contenu
import com.example.veraxapplication.modele.articles.contenus.ContenuMedia
import com.example.veraxapplication.modele.articles.contenus.ContenuParagraphe
import com.example.veraxapplication.modele.user.User
class StubUsers() : IUsersDataManager {
private var lUsers: MutableList<User>? = null
init {
chargerUsers()
}
private fun chargerUsers() {
lUsers = java.util.ArrayList<User>()
val user1 = User (
"NoaSil",
"1234",
"",
"Sillard",
"Noa",
"Admin"
)
lUsers!!.add(user1)
val user2 = User (
"Sha",
"1234",
"",
"Cascarra",
"Shana",
"Admin"
)
lUsers!!.add(user2)
val user3 = User (
"TonyF",
"1234",
"tony@gmail.com",
"Fages",
"Tony",
"Admin"
)
lUsers!!.add(user3)
val user4 = User (
"JeanSwaggLaPuissance63",
"1234",
"jean.lapuissance@gmail.com",
"Marcillac",
"Jean",
"Admin"
)
lUsers!!.add(user4)
}
override val allUsers: List<User>?
get() = lUsers
override fun getUser(pseudo : String): User? {
println("Passage dans getUser avec comme pseudo : $pseudo")
lUsers?.let {
println("Nombre d'utilisateurs disponibles : ${it.size}")
val userARenvoyer: User? = it.find { user -> user.pseudo == pseudo }
return userARenvoyer
}
return null
}
override fun getUsers(): List<User>
{
return lUsers?.takeIf { it.isNotEmpty() }?.take(lUsers!!.size) ?: emptyList()
}
}

@ -1,3 +0,0 @@
package com.example.veraxapplication.modele.user
data class User(val pseudo : String, val mdp : String, val mail : String, val nom : String, val prenom : String, val role : String)

@ -0,0 +1,44 @@
package com.example.veraxapplication.navigation
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.example.veraxapplication.articles.IArticlesDataManager
import com.example.veraxapplication.articles.StubArticles
//import com.example.veraxapplication.HomeScreen
//https://codefirst.iut.uca.fr/git/Kotlin_Android/Android_TP_2/src/branch/master/app/src/main/java/fr/iut/tp2/navigation/TP2NavHost.kt
@Composable
fun NavHost(){
val navController = rememberNavController()
val dataManager : IArticlesDataManager = StubArticles()
var articles = dataManager.getDerniersArticles(4)
NavHost(
modifier = Modifier.fillMaxSize(),
navController = navController,
startDestination = "home"
) {
composable(route = "home") {
/* HomeScreen(
//article = , //recup l article cliqué
goToArticle = {
navController.navigate("articleALaUne/${it.id}")
}
)
}
composable(
route = "articleALaUne/{articleId}",
arguments = navArgument("articleALaUne") { type = NavType.LongType })
*/
}
}
}

@ -1,18 +1,20 @@
package com.example.veraxapplication.navigation package com.example.veraxapplication.navigation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.navigation.NavController
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.NavType import androidx.navigation.NavType
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
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.example.veraxapplication.MainActivity
import com.example.veraxapplication.modele.articles.Article import com.example.veraxapplication.modele.articles.Article
import com.example.veraxapplication.ui.article.AffichageLesArticles import com.example.veraxapplication.ui.article.AffichageLesArticles
import com.example.veraxapplication.ui.article.AfficherArticle import com.example.veraxapplication.ui.article.AfficherArticle
@Composable @Composable
fun VeraxNavHost(articles : List<Article>, navController: NavHostController, articlesStub: List<Article>) { fun VeraxNavHost(articles : List<Article>, navController: NavHostController) {
NavHost( NavHost(
@ -33,7 +35,7 @@ fun VeraxNavHost(articles : List<Article>, navController: NavHostController, art
arguments= listOf(navArgument("articleid"){ type= NavType.IntType}) arguments= listOf(navArgument("articleid"){ type= NavType.IntType})
){ ){
it.arguments?.getInt("articleid")?.let { articleid -> it.arguments?.getInt("articleid")?.let { articleid ->
articlesStub.find { it.id == articleid }?.let { articles.find { it.id == articleid }?.let {
AfficherArticle( AfficherArticle(
e = it e = it
) )

@ -1,18 +1,15 @@
package com.example.veraxapplication.ui.article package com.example.veraxapplication.ui.article
import VideoPlayer
import android.util.Log
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
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.clickable
import androidx.compose.foundation.clipScrollableContainer
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
@ -32,18 +29,20 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import coil.compose.rememberImagePainter import coil.compose.rememberImagePainter
import com.example.veraxapplication.modele.articles.Article import com.example.veraxapplication.modele.articles.Article
import com.example.veraxapplication.modele.articles.contenus.Contenu
import com.example.veraxapplication.modele.articles.contenus.ContenuMedia import com.example.veraxapplication.modele.articles.contenus.ContenuMedia
import com.example.veraxapplication.modele.articles.contenus.ContenuParagraphe import com.example.veraxapplication.modele.articles.contenus.ContenuParagraphe
import com.example.veraxapplication.ui.theme.Salmon import com.example.veraxapplication.ui.theme.Salmon
@Composable @Composable
fun AffichageLesArticles(articles : List<Article>, goToArticle: (Article) -> Unit){ fun AffichageLesArticles(articles : List<Article>, goToArticle: (Article) -> Unit
){
Column(modifier = Modifier.verticalScroll(rememberScrollState())){ Column(modifier = Modifier.verticalScroll(rememberScrollState())){
for(article in articles){ for(article in articles){
Box { Box (Modifier.clickable { /*faut je regarde la doc*/ }
.background(color = Color(android.graphics.Color.parseColor("#e7dfd8")))){
AffichageUnArticleInfo(e = article, goToArticle) AffichageUnArticleInfo(e = article, goToArticle)
} }
} }
} }
} }
@ -51,9 +50,17 @@ fun AffichageLesArticles(articles : List<Article>, goToArticle: (Article) -> Uni
@Composable @Composable
fun AffichageUnArticleInfo(e : Article, goToArticle: (Article) -> Unit){ fun AffichageUnArticleInfo(e : Article, goToArticle: (Article) -> Unit){
Column(modifier = Modifier Column(modifier = Modifier
.padding(7.dp) .padding(12.dp,12.dp,12.dp,20.dp)
.border(width = 1.dp, color = Color.Black, shape = RoundedCornerShape(10.dp)) .background(Color.White)
//.border(width = 1.dp, color = Color.Black, shape = RoundedCornerShape(10.dp))
//.clip(RoundedCornerShape(50.dp)) //ca marche mais il y a comme un rectange blanc derriere
.padding(5.dp)) { .padding(5.dp)) {
/*DisplayTitle(title = e.Title)
DisplayHeader(author = e.Author, description = e.Description, lectureTime = e.LectureTime)
DisplayImage(image = e.Image)
DisplayContentArticle(content = e.Content)*/
Text(text = e.titre, fontFamily = FontFamily.Serif, fontSize = 30.sp) Text(text = e.titre, fontFamily = FontFamily.Serif, fontSize = 30.sp)
@ -81,7 +88,6 @@ fun AffichageUnArticleInfo(e : Article, goToArticle: (Article) -> Unit){
.padding(5.dp, 35.dp) .padding(5.dp, 35.dp)
) )
Button(onClick = { goToArticle(e) }, Button(onClick = { goToArticle(e) },
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
containerColor = Salmon, containerColor = Salmon,
@ -104,12 +110,23 @@ fun AfficherArticle(e : Article){
.padding(7.dp) .padding(7.dp)
.padding(5.dp)) { .padding(5.dp)) {
Text(text = e.titre, fontFamily = FontFamily.Serif, fontSize = 30.sp)
// Affichage des informations de l'article
DisplayHeader(author = e.auteur, description = e.description, lectureTime = e.temps)
Text(text = e.titre, fontFamily = FontFamily.Serif, fontSize = 30.sp)
Box(
modifier = Modifier
.padding(15.dp)
.border(width = 1.dp, color = Color.Black, shape = RoundedCornerShape(10.dp))
.clip(RoundedCornerShape(10.dp))
.background(Salmon)
) {
Column(modifier = Modifier.padding(15.dp)) {
Text(text = "Auteur : "+e.auteur, fontSize = 17.sp)
Text(text = "Description : "+e.description, fontSize = 17.sp)
Text(text = "Temps de lecture : " + e.temps + " minutes", fontSize = 17.sp)
}
}
Image( Image(
painter = rememberImagePainter( painter = rememberImagePainter(
data = e.imagePrincipale data = e.imagePrincipale
@ -123,67 +140,97 @@ fun AfficherArticle(e : Article){
) )
// Affichage contenus Column (modifier = Modifier.align(Alignment.Start)){
DisplayContenu(e.lContenus) for (text in e.contenus){
when(text){
}
}
@Composable
fun DisplayHeader(author: String, description: String, lectureTime: String) {
Box(
modifier = Modifier
.padding(15.dp)
.border(width = 1.dp, color = Color.Black, shape = RoundedCornerShape(10.dp))
.clip(RoundedCornerShape(10.dp))
.background(Salmon)
) {
Column(modifier = Modifier.padding(15.dp)) {
Text(text = "Auteur : "+ author, fontSize = 17.sp)
Text(text = "Description : "+ description, fontSize = 17.sp)
Text(text = "Temps de lecture : " + lectureTime + " minutes", fontSize = 17.sp)
}
}
}
@Composable
fun DisplayContenu(contenus: List<Contenu>) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
for (contenu in contenus) {
when (contenu) {
is ContenuMedia -> { is ContenuMedia -> {
Log.d("Img", contenu.titre + " " + contenu.lien) Text(text = text.titre, fontSize = 20.sp, fontWeight = FontWeight.Bold)
Text(text = contenu.titre, fontSize = 20.sp, fontWeight = FontWeight.Bold) when(text.typeContenu){
when (contenu.typeContenu) {
"image" -> { "image" -> {
Image( Image(
painter = rememberImagePainter(data = contenu.lien), painter = rememberImagePainter(
data = text.lien
),
contentScale = ContentScale.FillHeight , contentScale = ContentScale.FillHeight ,
contentDescription = null, contentDescription = null,
modifier = Modifier modifier = Modifier
.size(350.dp) .size(350.dp)
.align(Alignment.CenterHorizontally)
.padding(5.dp, 35.dp) .padding(5.dp, 35.dp)
.fillMaxWidth()
.wrapContentWidth(Alignment.CenterHorizontally) // Centrer l'image
) )
} }
"video" -> { "video" -> {
Text( Text(text = "Ici une video ..."+ text.toString(), fontSize = 15.sp, textAlign = TextAlign.Start)
text = "Ici une video ..." + contenu.toString(), //faut je vois comment on fait pour inclure une video ...
fontSize = 15.sp,
textAlign = TextAlign.Start
)
VideoPlayer(videoUrl = contenu.lien)
} }
} }
} }
is ContenuParagraphe ->{ is ContenuParagraphe ->{
Text(text = contenu.titre, fontSize = 20.sp, fontWeight = FontWeight.Bold) Text(text = text.titre, fontSize = 20.sp, fontWeight = FontWeight.Bold)
Text(text = contenu.texte, fontSize = 16.sp, textAlign = TextAlign.Start) Text(text = text.toString(), fontSize = 16.sp, textAlign = TextAlign.Start)
}
}
}
}
}
}
/*
@Composable
fun DisplayImage(image: String) {
Log.d("DisplayImage", "Chargement de l'image à partir de l'URL : $image")
Log.d("DisplayImage", "Painter créé avec succès")
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Image(
painter = rememberImagePainter(
data = image,
builder = {
scale(Scale.FILL)
} }
),
contentDescription = null,
modifier = Modifier.fillMaxSize(),
)
} }
} }
@Composable
fun DisplayHeader(author: String, description: String, lectureTime: String) {
Box(modifier = Modifier
.fillMaxWidth()
.border(width = 1.dp, color = Color.Black, shape = RoundedCornerShape(10.dp))
.clip(RoundedCornerShape(10.dp))
.background(Salmon)
.padding(10.dp)) {
Column () {
Text(text = author)
Text(text = description)
Text(text = "Lecture Time: " + lectureTime + " minutes")
}
}
}
@Composable
fun DisplayTitle(title: String) {
Column(modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally){
Text(text = title, fontFamily = FontFamily.Serif, fontSize = 30.sp)
} }
} }
@Composable
fun DisplayContentArticle(content: List<Contenu>) {
Column {
for(e in content){
Text(text = e.Content, fontSize = 15.sp, fontFamily = FontFamily.Serif, textAlign = TextAlign.Justify, modifier = Modifier.padding(10.dp))
}
}
}*/

@ -1,41 +0,0 @@
import android.view.ViewGroup
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.ui.PlayerView
@Composable
fun VideoPlayer(videoUrl : String){
val context = LocalContext.current
val player = ExoPlayer.Builder(context).build()
val playerView = PlayerView(context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
val mediaItem = MediaItem.Builder()
.setUri(videoUrl)
.build()
player.setMediaItem(mediaItem)
player.prepare()
player.play()
AndroidView(
factory = { context -> playerView },
modifier = Modifier.fillMaxSize(),
update = { view ->
view.player = player
}
)
}

@ -1,23 +0,0 @@
package com.example.veraxapplication.ui.connexion
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.example.veraxapplication.modele.user.User
@Composable
fun AfficherForm(users : List<User>) {
var pseudo = "DEFAULT"
var mdp = "DEFAULT"
Column {
TextField(value = "Pseudo", onValueChange = { value -> pseudo = value }, modifier = Modifier.padding(5.dp))
TextField(value = "Mot de passe", onValueChange = { value -> mdp = value }, modifier = Modifier.padding(5.dp))
for (u in users) {
Text(text = u.pseudo)
}
}
}

@ -5,13 +5,13 @@ import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Menu import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.CenterAlignedTopAppBar import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenu
@ -38,28 +38,33 @@ import androidx.navigation.compose.rememberNavController
import com.example.veraxapplication.R import com.example.veraxapplication.R
import com.example.veraxapplication.modele.articles.Article import com.example.veraxapplication.modele.articles.Article
import com.example.veraxapplication.navigation.VeraxNavHost import com.example.veraxapplication.navigation.VeraxNavHost
import com.example.veraxapplication.ui.article.AffichageLesArticles
import com.example.veraxapplication.ui.article.AfficherArticle
import com.example.veraxapplication.ui.theme.Orange import com.example.veraxapplication.ui.theme.Orange
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun TopBarVerax(theme: List<String>, articles: List<Article>, articlesStub : List<Article>) { fun TopBarVerax(theme: List<String>, articles: List<Article>) {
/*var leMenu by remember { mutableStateOf(false) }*/ var leMenu by remember {
mutableStateOf(false)
}
val navController = rememberNavController() val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState() val navBackStackEntry by navController.currentBackStackEntryAsState()
Row( modifier = Modifier.background(Color.Blue).fillMaxSize()) { Row() {
Scaffold( Scaffold(
topBar = { topBar = {
CenterAlignedTopAppBar( CenterAlignedTopAppBar(
title = { title = {
Text( Text(
//text = R.string.app_name,
text = "Verax", text = "Verax",
style = TextStyle(fontSize = 35.sp), style = TextStyle(fontSize = 35.sp),
color = colorResource(R.color.red), color = colorResource(R.color.red),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
/*backcolor = topAppBarColors(
containerColor = MaterialTheme.colorScheme.primaryContainer),*/ //version recommandée par le prof
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
}, },
@ -73,7 +78,7 @@ fun TopBarVerax(theme: List<String>, articles: List<Article>, articlesStub : Lis
} }
} }
}/*, },
actions = { actions = {
IconButton(onClick = { leMenu = !leMenu }) { IconButton(onClick = { leMenu = !leMenu }) {
Icon( Icon(
@ -102,14 +107,33 @@ fun TopBarVerax(theme: List<String>, articles: List<Article>, articlesStub : Lis
.padding(10.dp) .padding(10.dp)
) )
}, },
onClick = { } onClick = { /* faut un moyen d'appeler une methode diff pour chaque, ca doit etre faisable facilement */ }
) )
} }
} }
}*/ }
) )
}/*,
bottomBar = {
// Faudrait pouvoir faire un flex sur les boutons parce que là ils sont juste côte à côte
BottomAppBar(containerColor = Color.Black, contentColor = Color.White) {
IconButton(onClick = { /*TODO*/ }) {
Icon(
imageVector = Icons.Filled.Home,
contentDescription = "Home",
Modifier.size(35.dp)
)
} }
IconButton(onClick = { /*TODO*/ }) {
Icon(
imageVector = Icons.Filled.Person,
contentDescription = "Account",
Modifier.size(35.dp)
)
}
}
}*/
) { innerPadding -> ) { innerPadding ->
Column( Column(
modifier = Modifier modifier = Modifier
@ -117,7 +141,11 @@ fun TopBarVerax(theme: List<String>, articles: List<Article>, articlesStub : Lis
verticalArrangement = Arrangement.spacedBy(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp),
) { ) {
VeraxNavHost(articles = articles, navController, articlesStub= articlesStub) // AffichageLesArticles(articles = articles)
// AfficherArticle(articles.get(0))
VeraxNavHost(articles = articles, navController)
} }
} }

@ -1,3 +1,3 @@
<resources> <resources>
<string name="app_name">Verax</string> <string name="app_name">VeraxApplication</string>
</resources> </resources>

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">181.214.189.133</domain>
<domain includeSubdomains="true">codefirst.iut.uca.fr/containers/Verax-verax-api</domain>
</domain-config>
</network-security-config>
Loading…
Cancel
Save