j'essaye de comprendre

workShana
Shana CASCARRA 1 year ago
commit 76a51f1de0

@ -1,6 +1,7 @@
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 {
@ -55,6 +56,9 @@ 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.12.0") implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
@ -71,6 +75,11 @@ dependencies {
implementation("com.google.android.exoplayer:exoplayer-core:2.19.1") implementation("com.google.android.exoplayer:exoplayer-core:2.19.1")
implementation ("com.google.android.exoplayer:exoplayer-ui: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,7 +12,10 @@
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,15 +1,16 @@
package com.example.veraxapplication package com.example.veraxapplication
import ArticlesViewModel
import android.os.Bundle import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.ui.graphics.Color import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.veraxapplication.articles.IArticlesDataManager import com.example.veraxapplication.articles.IArticlesDataManager
import com.example.veraxapplication.articles.StubArticles import com.example.veraxapplication.articles.StubArticles
import com.example.veraxapplication.modele.ApiClient
import com.example.veraxapplication.modele.articles.Article
import com.example.veraxapplication.navigation.VeraxNavHost
import com.example.veraxapplication.ui.article.AfficherArticle
import com.example.veraxapplication.ui.topBar.TopBarVerax import com.example.veraxapplication.ui.topBar.TopBarVerax
@ -19,31 +20,40 @@ import com.example.veraxapplication.ui.topBar.TopBarVerax
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
// un truc vite fait pour avoir un visi override fun onCreate(savedInstanceState: Bundle?) {
// var article = listOf("Thinkerview", "thinkerview.jgp", "Thinkerview est une chaîne youtube d'interview-débat") super.onCreate(savedInstanceState)
//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")))) setContent {
VeraxContent()
}
}
}
@Composable
fun VeraxContent() {
// 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()
// Observer les données du ViewModel
val articlesViewModel: ArticlesViewModel = viewModel()
var theme = listOf("Economique", "Culture", "Politique", "Faits divers") // Observez les articles du ViewModel
val articlesApi by articlesViewModel.articles.observeAsState(initial = articles)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
var theme = listOf("Economique", "Culture", "Politique", "Faits divers")
// TopBarVerax(theme = theme, articles = articlesApi) for(a in articlesApi){
TopBarVerax(theme = theme, articles = articles) Log.d("Articles : ", a.contenus.toString())
}
// VeraxNavHost() TopBarVerax(articles = articlesApi, theme = theme)
}
}
} }

@ -1,22 +0,0 @@
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,27 @@
package com.example.veraxapplication.modele
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitClientUser {
private const val BASE_URL = "https://codefirst.iut.uca.fr/containers/Verax-verax-api"
val retrofit: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
// interface UserApiService {
// @GET("users")
// suspend fun getUsers() : List<User>
// }
}
object ApiClientUser {
val apiService: UserApiService by lazy {
RetrofitClientUser.retrofit.create(UserApiService::class.java)
}
}

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

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

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

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

@ -0,0 +1,54 @@
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)
}
}
}
}

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

@ -9,10 +9,11 @@ class Article(
val temps: String, val temps: String,
val date: String, val date: String,
val auteur: String, val auteur: String,
val categorie: String,
val note: String,
val imagePrincipale: String val imagePrincipale: String
) { ) {
val note = 1.0 public val lContenus: MutableList<Contenu> = java.util.ArrayList()
private val lContenus: MutableList<Contenu> = java.util.ArrayList()
init { init {
// Initialisation des contenus si nécessaire // Initialisation des contenus si nécessaire
@ -30,4 +31,6 @@ 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,13 +1,9 @@
package com.example.veraxapplication.articles package com.example.veraxapplication.articles
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 {
@ -28,8 +24,10 @@ 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",
"date a revoir", "02/09/2024",
"Siwa", "Tony",
"Politique",
"12",
"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&"
) )
article1.remplirArticle(contenuMap["article1"]) article1.remplirArticle(contenuMap["article1"])
@ -41,8 +39,10 @@ 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",
"date a revoir", "02/09/2024",
"Siwa", "Tony",
"Politique",
"12",
"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&"
) )
article2.remplirArticle(contenuMap["article5"]) article2.remplirArticle(contenuMap["article5"])
@ -54,8 +54,11 @@ 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",
"date a revoir", "02/09/2024",
"Siwa", "Tony",
"Politique",
"12",
"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&"
) )
article3.remplirArticle(contenuMap["article4"]) article3.remplirArticle(contenuMap["article4"])
@ -67,8 +70,10 @@ 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",
"date a revoir", "02/09/2024",
"Luthen", "Tony",
"Politique",
"12",
"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&"
) )
article4.remplirArticle(contenuMap["article6"]) article4.remplirArticle(contenuMap["article6"])

@ -0,0 +1,3 @@
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 : Char)

@ -1,11 +1,11 @@
package com.example.veraxapplication.ui.article package com.example.veraxapplication.ui.article
import VideoPlayer 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.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.padding import androidx.compose.foundation.layout.padding
@ -33,15 +33,14 @@ 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 (Modifier.clickable { /*faut je regarde la doc*/ }){ Box {
AffichageUnArticleInfo(e = article, goToArticle) AffichageUnArticleInfo(e = article, goToArticle)
} }
} }
} }
} }
@ -52,30 +51,17 @@ fun AffichageUnArticleInfo(e : Article, goToArticle: (Article) -> Unit){
.padding(7.dp) .padding(7.dp)
.border(width = 1.dp, color = Color.Black, shape = RoundedCornerShape(10.dp)) .border(width = 1.dp, color = Color.Black, shape = RoundedCornerShape(10.dp))
.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)
Box(modifier = Modifier
.padding(15.dp) var imageURl = e.note
.border(width = 1.dp, color = Color.Black, shape = RoundedCornerShape(10.dp)) Log.d("ImageLoad", "URL de l'image reçue de l'API : $imageURl")
.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 = imageURl
), ),
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
contentDescription = null, contentDescription = null,
@ -172,61 +158,3 @@ fun AfficherArticle(e : Article){
} }
} }
} }
/*
@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))
}
}
}*/

@ -11,7 +11,6 @@ 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,8 +37,6 @@ 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)

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">181.214.189.133</domain>
</domain-config>
</network-security-config>
Loading…
Cancel
Save