Compare commits
99 Commits
componentQ
...
master
After Width: | Height: | Size: 44 KiB |
@ -0,0 +1,26 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="202"
|
||||||
|
android:viewportHeight="202">
|
||||||
|
<group android:scaleX="1.2"
|
||||||
|
android:scaleY="1.2"
|
||||||
|
android:translateX="-20.2"
|
||||||
|
android:translateY="-20.2">
|
||||||
|
<path
|
||||||
|
android:pathData="M30,0L172,0A26,26 0,0 1,198 26L198,168A26,26 0,0 1,172 194L30,194A26,26 0,0 1,4 168L4,26A26,26 0,0 1,30 0z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="198"
|
||||||
|
android:startY="194"
|
||||||
|
android:endX="-6.98"
|
||||||
|
android:endY="181.61"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0" android:color="#FF4A148C"/>
|
||||||
|
<item android:offset="1" android:color="#FF7B1FA2"/>
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
</group>
|
||||||
|
</vector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 44 KiB |
@ -1,16 +0,0 @@
|
|||||||
package com.example.what_the_fantasy.Logs
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import com.example.what_the_fantasy.data.model.User
|
|
||||||
|
|
||||||
class LogsUsers{
|
|
||||||
fun logDebugDisplayUsers(users : List<User>, titleLog : String){
|
|
||||||
for(user in users){
|
|
||||||
Log.e(titleLog, "User created: ${user.username} => ${user.email} => ${user.imgUrl} => ${user.language}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun logDebugDisplayUser(user : User, titleLog : String){
|
|
||||||
Log.e(titleLog, "User created: ${user.username} => ${user.email}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.example.what_the_fantasy.data.local
|
||||||
|
|
||||||
|
import com.example.what_the_fantasy.data.model.Quote
|
||||||
|
import com.example.what_the_fantasy.data.model.SrcLanguage
|
||||||
|
import com.example.what_the_fantasy.data.model.SrcType
|
||||||
|
|
||||||
|
object DailyQuoteStub {
|
||||||
|
val dailyQuote = Quote(
|
||||||
|
id = 1,
|
||||||
|
content = "All we have to decide is what to do with the time that is given us.",
|
||||||
|
likes = 466,
|
||||||
|
language = SrcLanguage.vo,
|
||||||
|
character = CharacterStub.gandalf.name,
|
||||||
|
source = "The Lord of the Rings: The Fellowship of the Ring",
|
||||||
|
date = 2000,
|
||||||
|
type = SrcType.Movie,
|
||||||
|
imgUrl = CharacterStub.gandalf.imgUrl
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.example.what_the_fantasy.data.local
|
||||||
|
|
||||||
|
import com.example.what_the_fantasy.data.local.QuoteStub.quotes
|
||||||
|
import com.example.what_the_fantasy.data.local.UserStub.users
|
||||||
|
import com.example.what_the_fantasy.data.model.Favorite
|
||||||
|
|
||||||
|
object FavoriteStub {
|
||||||
|
val favorites: MutableList<Favorite> = mutableListOf(
|
||||||
|
Favorite(users[0], mutableListOf(quotes[0], quotes[1], quotes[12])), // Aragorn123 aime ces citations
|
||||||
|
Favorite(users[1], mutableListOf(quotes[5], quotes[6], quotes[7])), // Legolas456 aime ces citations
|
||||||
|
Favorite(users[2], mutableListOf(quotes[8], quotes[9], quotes[10])), // Gandalf789 aime ces citations
|
||||||
|
Favorite(users[3], mutableListOf(quotes[11], quotes[12], quotes[13])), // FrodoBaggins aime ces citations
|
||||||
|
Favorite(users[4], mutableListOf(quotes[14], quotes[15], quotes[16])), // Gimli999 aime ces citations
|
||||||
|
Favorite(users[5], mutableListOf(quotes[17], quotes[18], quotes[19])), // Galadriel321 aime ces citations
|
||||||
|
Favorite(users[6], mutableListOf(quotes[17], quotes[2], quotes[7])), // Boromir654 aime ces citations
|
||||||
|
Favorite(users[7], mutableListOf(quotes[3], quotes[4], quotes[10])), // Eowyn777 aime ces citations
|
||||||
|
Favorite(users[8], mutableListOf(quotes[6], quotes[8], quotes[9])), // Saruman888 aime ces citations
|
||||||
|
Favorite(users[9], mutableListOf(quotes[5], quotes[13], quotes[15])), // Faramir222 aime ces citations
|
||||||
|
Favorite(users[10], mutableListOf(quotes[12], quotes[17], quotes[16])) // dev aime ces citations
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.example.what_the_fantasy.data.model
|
||||||
|
|
||||||
|
data class Comment(
|
||||||
|
val content : String,
|
||||||
|
val user : String,
|
||||||
|
val date : String,
|
||||||
|
val img : String
|
||||||
|
)
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.example.what_the_fantasy.data.model
|
||||||
|
|
||||||
|
class Favorite (
|
||||||
|
val user: User,
|
||||||
|
val quote: List<Quote>
|
||||||
|
)
|
@ -1,6 +1,6 @@
|
|||||||
package com.example.what_the_fantasy.data.model
|
package com.example.what_the_fantasy.data.model
|
||||||
|
|
||||||
enum class SrcLanguage {
|
enum class SrcLanguage {
|
||||||
fr,
|
vf,
|
||||||
vo
|
vo
|
||||||
}
|
}
|
@ -1,7 +1,10 @@
|
|||||||
package com.example.what_the_fantasy.data.model
|
package com.example.what_the_fantasy.data.model
|
||||||
|
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import com.example.what_the_fantasy.R
|
||||||
|
|
||||||
enum class SrcType (val value: String) {
|
enum class SrcType (val value: String) {
|
||||||
Movie("@string/movie"),
|
Movie("movie" ),
|
||||||
VideoGame("@string/videoGame"),
|
VideoGame("videoGame"),
|
||||||
Series("@string/series"),
|
Series("series"),
|
||||||
}
|
}
|
@ -1,22 +1,43 @@
|
|||||||
package com.example.what_the_fantasy.data.services
|
package com.example.what_the_fantasy.data.services
|
||||||
|
|
||||||
import com.example.what_the_fantasy.data.local.UserStub.users
|
import com.example.what_the_fantasy.data.model.Favorite
|
||||||
|
import com.example.what_the_fantasy.data.model.Comment
|
||||||
|
import com.example.what_the_fantasy.data.model.Quote
|
||||||
|
import com.example.what_the_fantasy.data.model.SrcLanguage
|
||||||
import com.example.what_the_fantasy.data.model.User
|
import com.example.what_the_fantasy.data.model.User
|
||||||
|
import com.example.what_the_fantasy.ui.states.AuthUserState
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
interface IServices {
|
interface IServices {
|
||||||
fun EditUsername(username : String, index : Int)
|
|
||||||
fun EditEmail(email : String, index : Int)
|
|
||||||
fun EditPasswd(passwd : String, index : Int)
|
|
||||||
fun EditImage(imageURL : String, index : Int)
|
|
||||||
|
|
||||||
fun CreateUser(username : String, email : String, passwd : String, services : IServices) : Boolean
|
fun validLogin(username : String,
|
||||||
fun getFavorite(username: String)
|
passwd : String,
|
||||||
fun getAllUsers(): List<User>
|
navController: (Int) -> Unit,
|
||||||
|
initialierCurrentUser : (Int) ->Unit): Boolean
|
||||||
|
|
||||||
|
fun EditUsername(username : String, index : Int) : Boolean
|
||||||
|
fun EditEmail(email : String, index : Int) : Boolean
|
||||||
|
fun EditPasswd(passwd : String, index : Int)
|
||||||
|
fun EditImage(index : Int) : String
|
||||||
|
fun ChangeLangage(index : Int): SrcLanguage
|
||||||
|
fun isUsernameExist(username : String) : Boolean
|
||||||
|
fun isEmailExist(email : String) : Boolean
|
||||||
|
|
||||||
|
fun AddFav(userId: Int, QuoteId : Int)
|
||||||
|
fun SupFav(userId: Int, QuoteId : Int)
|
||||||
|
fun AddComment(content : String)
|
||||||
|
fun CreateUser(username : String, email : String, passwd : String) : Boolean
|
||||||
|
fun getFavorite(user: User): List<Quote>
|
||||||
|
fun getAllUsers(): List<User>
|
||||||
|
fun getComment(quoteId : Int) : List<Comment>
|
||||||
fun getUserById(id: Int): User?
|
fun getUserById(id: Int): User?
|
||||||
|
|
||||||
fun SearchQuote(quote : String)
|
fun getQuote( id : Int): Quote?
|
||||||
|
|
||||||
|
|
||||||
|
fun isFavorite(idQuote : Int, iduser: Int): Boolean
|
||||||
|
fun getAllFavorite(): List<Favorite>
|
||||||
|
fun getAllQuote(): List<Quote>
|
||||||
|
fun getSomeQuotes(nb: Int, page: Int) : MutableList<Quote>
|
||||||
|
|
||||||
|
fun search(type : String ,search:String ,indexCount: Int): List<Quote>
|
||||||
}
|
}
|
@ -1,41 +1,89 @@
|
|||||||
package com.example.what_the_fantasy.data.services
|
package com.example.what_the_fantasy.data.services
|
||||||
|
|
||||||
import com.example.what_the_fantasy.data.model.User
|
//import com.example.what_the_fantasy.data.model.Comment
|
||||||
|
//import com.example.what_the_fantasy.data.model.Favorite
|
||||||
|
//import com.example.what_the_fantasy.data.model.Quote
|
||||||
|
//import com.example.what_the_fantasy.data.model.User
|
||||||
|
////import com.example.what_the_fantasy.ui.navigations.Destination
|
||||||
|
|
||||||
class ServicesAPI : IServices {
|
//class ServicesAPI : IServices {
|
||||||
override fun EditUsername(username: String, index : Int) {
|
// override fun EditUsername(username: String, index : Int): Boolean {
|
||||||
TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
override fun EditEmail(email: String, index : Int) {
|
// override fun EditEmail(email: String, index : Int): Boolean {
|
||||||
TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
override fun EditPasswd(passwd: String, index : Int) {
|
// override fun EditPasswd(passwd: String, index : Int) {
|
||||||
TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
override fun EditImage(imageURL: String, index : Int) {
|
// override fun EditImage(imageURL: String, index : Int) {
|
||||||
TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
override fun CreateUser(username: String, email: String, passwd: String, services: IServices) : Boolean {
|
// override fun ChangeLangage(user: User) {
|
||||||
TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
override fun SearchQuote(quote: String) {
|
// override fun AddFav(userId: Int, QuoteId: Int) {
|
||||||
TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
override fun getFavorite(username: String) {
|
// override fun SupFav(userId: Int, QuoteId: Int) {
|
||||||
TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
override fun getAllUsers(): List<User> {
|
// override fun AddComment(content: String) {
|
||||||
TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
override fun getUserById(id: Int): User? {
|
// override fun CreateUser(username: String, email: String, passwd: String, services: IServices) : Boolean {
|
||||||
TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
}
|
// }
|
||||||
}
|
//
|
||||||
|
// override fun getFavorite(user: User): List<Quote> {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun SearchQuote(quote: String) {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun getQuote(id: Int): Quote? {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun isFavorite(id: Int, user: User): Boolean {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun getAllFavorite(): List<Favorite> {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun getAllQuote(): List<Quote> {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun getSomeQuotes(nb: Int, page: Int): MutableList<Quote> {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun getAllUsers(): List<User> {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun getComment(quoteId: Int): List<Comment> {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun getUserById(id: Int): User? {
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun search(type : String ,search:String ,indexCount: Int): List<Quote>{
|
||||||
|
// TODO("Not yet implemented")
|
||||||
|
// }
|
||||||
|
//}
|
@ -1,4 +1,4 @@
|
|||||||
package com.example.what_the_fantasy.ui.components
|
package com.example.what_the_fantasy.data.services
|
||||||
|
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.example.what_the_fantasy.logs
|
||||||
|
import android.util.Log
|
||||||
|
import com.example.what_the_fantasy.data.model.User
|
||||||
|
|
||||||
|
class LogsUsers{
|
||||||
|
fun logDebugAllUsers(users : List<User>, titleLog : String){
|
||||||
|
for(user in users){
|
||||||
|
Log.d(titleLog, "User created: ${user.username} => ${user.email} => ${user.imgUrl} => ${user.langage}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logDebugUserEmail(user : User?, titleLog : String){
|
||||||
|
Log.d(titleLog, "User created: ${user?.username} => ${user?.email}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logDebugUserLangage(user : User?, titleLog : String){
|
||||||
|
Log.d(titleLog, "User Change: ${user?.username} => ${user?.langage}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logInformationUserConnect(user : User?, titleLog : String){
|
||||||
|
Log.i(titleLog, "${user?.username} logged in")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unlogInformationUserConnect(titleLog : String){
|
||||||
|
Log.i(titleLog, "Logged out")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun favoriteInformationUserTrue(titleLog : String, quoteId : Int, userId : Int){
|
||||||
|
Log.i(titleLog, "User $userId added quote $quoteId to favorites")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun favoriteInformationUserFalse(titleLog : String, quoteId : Int, userId : Int){
|
||||||
|
Log.i(titleLog, "User $userId removed quote $quoteId from favorites")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun shareInformationUser(titleLog : String, quoteId : Int, userId : Int){
|
||||||
|
Log.i(titleLog, "User $userId shared quote $quoteId")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.example.what_the_fantasy.repository
|
||||||
|
|
||||||
|
import com.example.what_the_fantasy.data.services.IServices
|
||||||
|
import okhttp3.Request
|
||||||
|
|
||||||
|
class AuthRepository {}
|
@ -1,68 +0,0 @@
|
|||||||
package com.example.what_the_fantasy.ui.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import coil.compose.AsyncImage
|
|
||||||
import com.example.what_the_fantasy.R
|
|
||||||
import com.example.what_the_fantasy.data.model.Quote
|
|
||||||
import com.example.what_the_fantasy.ui.theme.gradienBox
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun LittleQuoteComponent(quote : Quote){
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth(0.9f)
|
|
||||||
.clip(RoundedCornerShape(16.dp))
|
|
||||||
.background(gradienBox)
|
|
||||||
) {
|
|
||||||
val sizeTextInfoQuote = 13
|
|
||||||
val lineHeightText = 12
|
|
||||||
val sizeTextQuote = 16
|
|
||||||
|
|
||||||
AsyncImage(
|
|
||||||
model = quote.imgUrl,
|
|
||||||
contentDescription = "Quote picture",
|
|
||||||
modifier = Modifier
|
|
||||||
.size(130.dp)
|
|
||||||
.clip(RoundedCornerShape(16.dp))
|
|
||||||
)
|
|
||||||
Column(modifier = Modifier.padding(10.dp)) {
|
|
||||||
|
|
||||||
TextInfoQuote(
|
|
||||||
quote.content,
|
|
||||||
sizeTextQuote,
|
|
||||||
lineHeightText
|
|
||||||
)
|
|
||||||
|
|
||||||
SpaceHeightComponent(40)
|
|
||||||
|
|
||||||
TextInfoQuote("${stringResource(R.string.dateQuote)} : ${quote.date}", sizeTextInfoQuote, lineHeightText)
|
|
||||||
TextInfoQuote("${quote.type} : ${quote.source}", sizeTextInfoQuote, lineHeightText)
|
|
||||||
TextInfoQuote("${stringResource(R.string.CharacterQuote)}: ${quote.character}", sizeTextInfoQuote, lineHeightText)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun TextInfoQuote(text : String, fontSizeText : Int, lineHeightText : Int){
|
|
||||||
Text(text,
|
|
||||||
color = Color.White,
|
|
||||||
fontSize = fontSizeText.sp,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
lineHeight = lineHeightText.sp)
|
|
||||||
}
|
|
@ -0,0 +1,92 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
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.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import coil.compose.rememberAsyncImagePainter
|
||||||
|
import com.example.what_the_fantasy.R
|
||||||
|
import com.example.what_the_fantasy.data.model.Quote
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun QuoteLittle(quote: Quote, modifier: Modifier = Modifier) {
|
||||||
|
val Character = stringResource(R.string.CharacterQuote)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(8.dp)
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = rememberAsyncImagePainter(quote.imgUrl),
|
||||||
|
contentDescription = "Character Image",
|
||||||
|
contentScale = ContentScale.Crop,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(width = 135.dp, height = 135.dp)
|
||||||
|
.clip(
|
||||||
|
RoundedCornerShape(
|
||||||
|
topStart = 12.dp,
|
||||||
|
bottomStart = 12.dp,
|
||||||
|
topEnd = 0.dp,
|
||||||
|
bottomEnd = 0.dp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.height(135.dp)
|
||||||
|
.clip(
|
||||||
|
RoundedCornerShape(
|
||||||
|
topEnd = 12.dp,
|
||||||
|
bottomEnd = 12.dp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.background(MaterialTheme.colorScheme.primary)
|
||||||
|
.padding(12.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = quote.content,
|
||||||
|
color = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "${quote.type} : ${quote.source}",
|
||||||
|
color = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "${Character}: ${quote.character}",
|
||||||
|
color = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.example.what_the_fantasy.R
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun VisibleIconPasswordComponent(passwordVisible : Boolean){
|
||||||
|
Icon(
|
||||||
|
painterResource(
|
||||||
|
if(passwordVisible){
|
||||||
|
R.drawable.password_visible
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
R.drawable.password_no_visible
|
||||||
|
}
|
||||||
|
),
|
||||||
|
contentDescription = "visible",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(20.dp),
|
||||||
|
tint = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
}
|
@ -1,171 +1,320 @@
|
|||||||
package com.example.what_the_fantasy.ui.navigations
|
package com.example.what_the_fantasy.ui.navigations
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
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
|
||||||
|
import androidx.navigation.toRoute
|
||||||
import com.example.what_the_fantasy.data.services.ServicesStub
|
import com.example.what_the_fantasy.data.services.ServicesStub
|
||||||
import com.example.what_the_fantasy.ui.screens.AccueilPage
|
import com.example.what_the_fantasy.ui.screens.*
|
||||||
import com.example.what_the_fantasy.ui.screens.FavoritePage
|
import com.example.what_the_fantasy.ui.viewModels.AuthUserViewModel
|
||||||
import com.example.what_the_fantasy.ui.screens.LoginPage
|
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
|
||||||
import com.example.what_the_fantasy.ui.screens.ProfilPage
|
import com.example.what_the_fantasy.ui.viewModels.QuoteInformationUserViewModel
|
||||||
import com.example.what_the_fantasy.ui.screens.QuizEndPage
|
import com.example.what_the_fantasy.ui.viewModels.SearchViewModel
|
||||||
import com.example.what_the_fantasy.ui.screens.QuizMenu
|
import com.example.what_the_fantasy.ui.viewModels.SignInUserViewModel
|
||||||
import com.example.what_the_fantasy.ui.screens.QuizPage
|
import kotlinx.serialization.Serializable
|
||||||
import com.example.what_the_fantasy.ui.screens.QuotePage
|
|
||||||
import com.example.what_the_fantasy.ui.screens.SearchPage
|
@Serializable
|
||||||
import com.example.what_the_fantasy.ui.screens.SignUpPage
|
data class Accueil(val userIndex: Int)
|
||||||
import com.example.what_the_fantasy.ui.screens.SubmitQuotePage
|
|
||||||
|
@Serializable
|
||||||
|
data object Login
|
||||||
|
|
||||||
sealed class Destination(val route: String) {
|
@Serializable
|
||||||
data object Login : Destination("Login")
|
data class Favorite(val userIndex: Int)
|
||||||
data object Accueil : Destination("Accueil/{userIndex}") { // Ajout du paramètre userIndex
|
|
||||||
fun createRoute(userIndex: Int) = "Accueil/$userIndex" // Fonction pour créer la route avec l'index
|
@Serializable
|
||||||
}
|
data class Profil(val userIndex: Int)
|
||||||
data object Favorite : Destination("Favorite/{userIndex}") { // Ajout du paramètre userIndex
|
|
||||||
fun createRoute(userIndex: Int) = "Favorite/$userIndex" // Fonction pour créer la route avec l'index
|
@Serializable
|
||||||
}
|
data class QuizMenu(val userIndex: Int)
|
||||||
data object Profil : Destination("Profil/{userIndex}") { // Ajout du paramètre userIndex
|
|
||||||
fun createRoute(userIndex: Int) = "Profil/$userIndex" // Fonction pour créer la route avec l'index
|
@Serializable
|
||||||
}
|
data class Quiz(val userIndex: Int, val idQuiz: Int)
|
||||||
data object QuizMenu : Destination("QuizMenu/{userIndex}") { // Ajout du paramètre userIndex
|
|
||||||
fun createRoute(userIndex: Int) = "QuizMenu/$userIndex" // Fonction pour créer la route avec l'index
|
@Serializable
|
||||||
}
|
data class QuizEnd(val userIndex: Int, val idQuiz: Int, val pts: Int)
|
||||||
data object Quiz : Destination("Quiz/{idQuiz}") {
|
|
||||||
// Ajout paramètre idQuiz
|
@Serializable
|
||||||
fun createId(idQuiz : Int) = "Quiz/$idQuiz"
|
data class QuizRandom(val userIndex: Int)
|
||||||
}
|
|
||||||
data object QuizEnd : Destination("QuizEnd/{idQuiz}/{pts}") {
|
@Serializable
|
||||||
// Ajout paramètres idQuiz et pts
|
data class OneQuote(val quoteId: Int, val userIndex: Int)
|
||||||
fun createIdAndPts(idQuiz : Int, pts : Int) = "QuizEnd/$idQuiz/$pts"
|
|
||||||
}
|
|
||||||
data object Quote : Destination("Quote")
|
@Serializable
|
||||||
data object Search : Destination("Search")
|
data class Search(val userIndex: Int,val type : String = "contenu", val search: String = "")
|
||||||
data object SignUp : Destination("SignUp")
|
|
||||||
data object SubmitQuote : Destination("SubmitQuote")
|
@Serializable
|
||||||
}
|
data object SignUp
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class SubmitQuote(val userIndex: Int)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RecapSubmit(val userIndex: Int,
|
||||||
|
val quoteContent : String,
|
||||||
|
val character : String,
|
||||||
|
val source : String)
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppNavigator() {
|
fun AppNavigator() {
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val services = ServicesStub()
|
val services = ServicesStub()
|
||||||
NavHost(navController, startDestination = Destination.Login.route) {
|
|
||||||
composable(Destination.Login.route) {
|
//ViewModel pour l'authentification
|
||||||
LoginPage(
|
val authUserVM : AuthUserViewModel = viewModel()
|
||||||
navControllerSignUp = {
|
val authState by authUserVM.userState.collectAsState()
|
||||||
navController.navigate(Destination.SignUp.route)
|
|
||||||
},
|
//ViewModel pour l'inscription
|
||||||
navControllerProfil = { userIndex ->
|
val signInUserVM : SignInUserViewModel = viewModel()
|
||||||
navController.navigate(Destination.Profil.createRoute(userIndex)) {
|
val signInState by signInUserVM.userState.collectAsState()
|
||||||
// Vider pile de navigation pour empêcher le retour à la page Login
|
|
||||||
popUpTo(Destination.Login.route) { inclusive = true }
|
//ViewModel pour l'utilisateur
|
||||||
}
|
val currentUserVM : CurrentUserViewModel = viewModel()
|
||||||
},
|
val currentUserState by currentUserVM.currentUserState.collectAsState()
|
||||||
services
|
|
||||||
)
|
//ViewModel pour la recherche
|
||||||
}
|
val searchVM : SearchViewModel = viewModel()
|
||||||
composable(Destination.Accueil.route) {
|
val searchState by searchVM.searchState.collectAsState()
|
||||||
val userIndex = it.arguments?.getString("userIndex")?.toInt() ?: -1
|
|
||||||
AccueilPage(
|
//ViewModel pour les commentaires et likes des citations
|
||||||
index = userIndex,
|
val quoteInformationUserVM : QuoteInformationUserViewModel = viewModel()
|
||||||
navFavorite = { userIndex ->
|
val quoteInformationUserState by quoteInformationUserVM.quoteState.collectAsState()
|
||||||
navController.navigate(Destination.Favorite.createRoute(userIndex)) // Passe l'index à Profil
|
|
||||||
},
|
Scaffold(
|
||||||
navQuiz = { userIndex ->
|
modifier = Modifier.fillMaxSize(),
|
||||||
navController.navigate(Destination.QuizMenu.createRoute(userIndex)) // Passe l'index à Profil
|
containerColor = MaterialTheme.colorScheme.onPrimary
|
||||||
},
|
) { paddingValues ->
|
||||||
navProfil = { userIndex ->
|
Box(modifier = Modifier.padding(paddingValues)) {
|
||||||
navController.navigate(Destination.Profil.createRoute(userIndex)) // Passe l'index à Profil
|
|
||||||
|
NavHost(navController, startDestination = Login) {
|
||||||
|
composable<Login> {
|
||||||
|
LoginPage(
|
||||||
|
navControllerSignUp = { navController.navigate(SignUp) },
|
||||||
|
navControllerProfil = { userIndex ->
|
||||||
|
navController.navigate(Profil(userIndex)) {
|
||||||
|
popUpTo(Login) { inclusive = true }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
authUserVM = authUserVM,
|
||||||
|
authState = authState,
|
||||||
|
initialierCurrentUser ={currentUserVM.initialiseCurrentUser(it)}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
) }
|
|
||||||
composable(Destination.Favorite.route) {
|
composable<Accueil> {
|
||||||
val userIndex = it.arguments?.getString("userIndex")?.toInt() ?: -1
|
//val accueil: Accueil = it.toRoute()
|
||||||
FavoritePage(
|
AccueilPage(
|
||||||
index = userIndex,
|
navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
|
||||||
navAccueil ={ userIndex ->
|
navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
|
||||||
navController.navigate(Destination.Accueil.createRoute(userIndex)) // Passe l'index à Profil
|
navProfil = { navController.navigate(Profil(currentUserState.id)) },
|
||||||
},
|
navQuote = { quoteId ->
|
||||||
navQuiz = { userIndex ->
|
navController.navigate(
|
||||||
navController.navigate(Destination.QuizMenu.createRoute(userIndex)) // Passe l'index à Profil
|
OneQuote(
|
||||||
},
|
quoteId,
|
||||||
navProfil = { userIndex ->
|
currentUserState.id
|
||||||
navController.navigate(Destination.Profil.createRoute(userIndex)) // Passe l'index à Profil
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navSearch = { navController.navigate(Search(currentUserState.id))},
|
||||||
|
services = services,
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
) }
|
composable<Favorite> {
|
||||||
composable(Destination.Profil.route) {
|
//val favorite: Favorite = it.toRoute()
|
||||||
// Récupère l'index passé dans la route
|
FavoritePage(
|
||||||
val userIndex = it.arguments?.getString("userIndex")?.toInt() ?: -1
|
navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
|
||||||
ProfilPage(
|
navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
|
||||||
index = userIndex,
|
navProfil = { navController.navigate(Profil(currentUserState.id)) },
|
||||||
navFavorite = { userIndex ->
|
navQuote = { quoteId ->
|
||||||
navController.navigate(Destination.Favorite.createRoute(userIndex)) // Passe l'index à Profil
|
navController.navigate(
|
||||||
},
|
OneQuote(
|
||||||
navAccueil ={ userIndex ->
|
quoteId,
|
||||||
navController.navigate(Destination.Accueil.createRoute(userIndex)) // Passe l'index à Profil
|
currentUserState.id
|
||||||
},
|
)
|
||||||
navQuiz = { userIndex ->
|
)
|
||||||
navController.navigate(Destination.QuizMenu.createRoute(userIndex)) // Passe l'index à Profil
|
},
|
||||||
},
|
navSearch = { navController.navigate(Search(currentUserState.id))},
|
||||||
navUnLog = {
|
services = services,
|
||||||
navController.navigate(Destination.Login.route) {
|
currentUserVM = currentUserVM,
|
||||||
// Vider pile de navigation pour empêcher le retour à la page profil
|
currentUserState = currentUserState,
|
||||||
popUpTo(Destination.Profil.route) { inclusive = true }
|
)
|
||||||
}
|
|
||||||
},
|
|
||||||
services = services
|
|
||||||
)
|
|
||||||
}
|
|
||||||
composable(Destination.Quote.route) { QuotePage() }
|
|
||||||
composable(Destination.Search.route) { SearchPage() }
|
|
||||||
composable(Destination.SignUp.route) { SignUpPage(
|
|
||||||
navControllerLogin = {
|
|
||||||
navController.navigate(Destination.Login.route){
|
|
||||||
// Vider pile de navigation pour empêcher le retour à la page Sign up
|
|
||||||
popUpTo(Destination.Login.route) { inclusive = true }
|
|
||||||
}
|
}
|
||||||
},services) }
|
composable<Profil> {
|
||||||
composable(Destination.SubmitQuote.route) { SubmitQuotePage() }
|
val profil: Profil = it.toRoute()
|
||||||
|
ProfilPage(
|
||||||
composable(Destination.QuizMenu.route) {
|
navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
|
||||||
//val userIndex = it.arguments?.getString("userIndex")?.toInt() ?: -1
|
navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
|
||||||
QuizMenu(
|
navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
|
||||||
//index = userIndex,
|
navSubmitQuote = { navController.navigate(SubmitQuote(currentUserState.id)) },
|
||||||
// navAccueil = { userIndex ->
|
navUnLog = {
|
||||||
// navController.navigate(Destination.Accueil.createRoute(userIndex)) // Passe l'index à Profil
|
navController.navigate(Login) {
|
||||||
// },
|
popUpTo(profil) { inclusive = true }
|
||||||
// navFavorite = { userIndex ->
|
}
|
||||||
// navController.navigate(Destination.Favorite.createRoute(userIndex)) // Passe l'index à Profil
|
},
|
||||||
// },
|
currentUserVM = currentUserVM,
|
||||||
// navProfil = { userIndex ->
|
currentUserState = currentUserState,
|
||||||
// navController.navigate(Destination.Profil.createRoute(userIndex)) // Passe l'index à Profil
|
navSearch = { navController.navigate(Search(profil.userIndex))},
|
||||||
// },
|
)
|
||||||
navControllerQuiz = { id ->
|
|
||||||
navController.navigate(Destination.Quiz.createId(id))
|
|
||||||
}
|
}
|
||||||
)
|
composable<OneQuote> {
|
||||||
}
|
val quote: OneQuote = it.toRoute()
|
||||||
composable(Destination.Quiz.route) { backStackEntry ->
|
QuotePage(
|
||||||
val idQuiz = backStackEntry.arguments?.getString("idQuiz")?.toInt() ?: 0
|
quoteId = quote.quoteId,
|
||||||
QuizPage(
|
navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
|
||||||
navControllerQuizEnd = { idQuiz, pts ->
|
navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
|
||||||
navController.navigate(Destination.QuizEnd.createIdAndPts(idQuiz, pts))
|
navProfil = { navController.navigate(Profil(currentUserState.id)) },
|
||||||
},
|
navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
|
||||||
navControllerQuizMenu = { navController.navigate(Destination.QuizMenu.route) },
|
service = services,
|
||||||
navControllerMenu = { navController.navigate(Destination.Accueil.route) },
|
currentUserVM = currentUserVM,
|
||||||
idQuiz
|
currentUserState = currentUserState,
|
||||||
)
|
navSearch = { navController.navigate(Search(currentUserState.id))},
|
||||||
}
|
quoteInformationUserVM = quoteInformationUserVM,
|
||||||
composable(Destination.QuizEnd.route) { backStackEntry ->
|
quoteInformationUserState = quoteInformationUserState,
|
||||||
val idQuiz = backStackEntry.arguments?.getString("idQuiz")?.toInt() ?: 0
|
)
|
||||||
val pts = backStackEntry.arguments?.getString("pts")?.toInt() ?: 0
|
}
|
||||||
QuizEndPage(
|
composable<Search> {
|
||||||
idQuiz,
|
val search: Search = it.toRoute()
|
||||||
pts,
|
SearchPage(
|
||||||
navControllerQuizMenu = { navController.navigate(Destination.QuizMenu.route) },
|
navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
|
||||||
navControllerMenu = { navController.navigate(Destination.Accueil.route) }
|
navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
|
||||||
)
|
navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
|
||||||
|
navProfil = { navController.navigate(Profil(currentUserState.id)) },
|
||||||
|
navQuote = { quoteId -> navController.navigate(OneQuote(quoteId,currentUserState.id)) },
|
||||||
|
navSearch = {type,newSearch -> navController.navigate(Search(currentUserState.id,type,newSearch))},
|
||||||
|
type = search.type,
|
||||||
|
search = search.search,
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
searchVM = searchVM,
|
||||||
|
searchState = searchState
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable<SignUp> {
|
||||||
|
SignUpPage(
|
||||||
|
navControllerLogin = {
|
||||||
|
navController.navigate(Login) {
|
||||||
|
popUpTo(Login) { inclusive = true }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
signInUserVM = signInUserVM,
|
||||||
|
signInState = signInState
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable<SubmitQuote> {
|
||||||
|
//val submitQuote: SubmitQuote = it.toRoute()
|
||||||
|
SubmitQuotePage(
|
||||||
|
navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
|
||||||
|
navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
|
||||||
|
navProfil = { navController.navigate(Profil(currentUserState.id)) },
|
||||||
|
navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
|
||||||
|
navRecap = { quoteContent, character, source ->
|
||||||
|
navController.navigate(
|
||||||
|
RecapSubmit(
|
||||||
|
currentUserState.id,
|
||||||
|
quoteContent,
|
||||||
|
character,
|
||||||
|
source
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable<RecapSubmit> {
|
||||||
|
val recapSubmit: RecapSubmit = it.toRoute()
|
||||||
|
RecapSubmitPage(
|
||||||
|
quoteContent = recapSubmit.quoteContent,
|
||||||
|
character = recapSubmit.character,
|
||||||
|
source = recapSubmit.source,
|
||||||
|
navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
|
||||||
|
navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
|
||||||
|
navProfil = { navController.navigate(Profil(currentUserState.id)) },
|
||||||
|
navSearch = { navController.navigate(Search(currentUserState.id))},
|
||||||
|
navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
composable<QuizMenu> {
|
||||||
|
//val quizMenu: QuizMenu = it.toRoute()
|
||||||
|
QuizMenu(
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
|
||||||
|
navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
|
||||||
|
navProfil = { navController.navigate(Profil(currentUserState.id)) },
|
||||||
|
navSearch = { navController.navigate(Search(currentUserState.id))},
|
||||||
|
navControllerQuiz = { idQuiz ->
|
||||||
|
navController.navigate(Quiz(currentUserState.id, idQuiz))
|
||||||
|
},
|
||||||
|
navControllerRandomQuiz = { navController.navigate(QuizRandom(currentUserState.id)) }
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable<Quiz> {
|
||||||
|
val quiz: Quiz = it.toRoute()
|
||||||
|
QuizPage(
|
||||||
|
navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
|
||||||
|
navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
|
||||||
|
navProfil = { navController.navigate(Profil(currentUserState.id)) },
|
||||||
|
navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
|
||||||
|
navControllerQuizEnd = { idQuiz, pts ->
|
||||||
|
navController.navigate(QuizEnd(currentUserState.id, idQuiz, pts))
|
||||||
|
},
|
||||||
|
navSearch = { navController.navigate(Search(currentUserState.id))},
|
||||||
|
idQuiz = quiz.idQuiz,
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable<QuizEnd> {
|
||||||
|
val quizEnd: QuizEnd = it.toRoute()
|
||||||
|
QuizEndPage(
|
||||||
|
idQuiz = quizEnd.idQuiz,
|
||||||
|
points = quizEnd.pts,
|
||||||
|
navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
|
||||||
|
navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
|
||||||
|
navProfil = { navController.navigate(Profil(currentUserState.id)) },
|
||||||
|
navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
|
||||||
|
navSearch = { navController.navigate(Search(currentUserState.id))},
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
composable<QuizRandom> {
|
||||||
|
val quizRandom: QuizRandom = it.toRoute()
|
||||||
|
QuizRandom(
|
||||||
|
navAccueil = { navController.navigate(Accueil(quizRandom.userIndex)) },
|
||||||
|
navFavorite = { navController.navigate(Favorite(quizRandom.userIndex)) },
|
||||||
|
navProfil = { navController.navigate(Profil(quizRandom.userIndex)) },
|
||||||
|
navQuiz = { navController.navigate(QuizMenu(quizRandom.userIndex)) },
|
||||||
|
navSearch = { navController.navigate(Search(quizRandom.userIndex)) },
|
||||||
|
navControllerQuizEnd = { idQuiz, pts ->
|
||||||
|
navController.navigate(QuizEnd(quizRandom.userIndex, idQuiz, pts))
|
||||||
|
},
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,42 +1,148 @@
|
|||||||
package com.example.what_the_fantasy.ui.screens
|
package com.example.what_the_fantasy.ui.screens
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.what_the_fantasy.R
|
||||||
|
import com.example.what_the_fantasy.data.local.DailyQuoteStub
|
||||||
|
import com.example.what_the_fantasy.data.model.Quote
|
||||||
import com.example.what_the_fantasy.data.services.IServices
|
import com.example.what_the_fantasy.data.services.IServices
|
||||||
import com.example.what_the_fantasy.ui.components.NavBar
|
import com.example.what_the_fantasy.ui.components.NavBar
|
||||||
|
import com.example.what_the_fantasy.ui.components.QuoteLittle
|
||||||
|
import com.example.what_the_fantasy.ui.states.CurrentUserState
|
||||||
|
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
|
||||||
import com.example.what_the_fantasy.ui.theme.colorBackground
|
import com.example.what_the_fantasy.ui.theme.colorBackground
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AccueilPage(
|
fun AccueilPage(
|
||||||
index: Int,
|
navFavorite: () -> Unit,
|
||||||
navFavorite:(Int) -> Unit,
|
navQuiz: () -> Unit,
|
||||||
navQuiz: (Int) -> Unit,
|
navProfil: () -> Unit,
|
||||||
navProfil:(Int) -> Unit
|
navQuote: (Int) -> Unit,
|
||||||
|
navSearch: () -> Unit,
|
||||||
|
services: IServices,
|
||||||
|
currentUserVM : CurrentUserViewModel,
|
||||||
|
currentUserState : CurrentUserState,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
NavBar(onAccueil = true,
|
val dailyQuote = DailyQuoteStub.dailyQuote
|
||||||
index = index,
|
|
||||||
|
val titleDalyQuote = stringResource(R.string.TitleHomeDailyQuote)
|
||||||
|
val titleSuggestion = stringResource(R.string.TitleHomeSuggestion)
|
||||||
|
|
||||||
|
val page = remember { mutableIntStateOf(1) }
|
||||||
|
val quotes = remember { mutableStateListOf<Quote>() }
|
||||||
|
val state = rememberLazyListState()
|
||||||
|
val layoutInfo = remember { derivedStateOf { state.layoutInfo } }
|
||||||
|
val isLoading = remember { mutableStateOf(false) }
|
||||||
|
val visibleItemsInfo = layoutInfo.value.visibleItemsInfo
|
||||||
|
val fullyVisibleItemsInfo = visibleItemsInfo.toMutableList()
|
||||||
|
val lastItem = if (fullyVisibleItemsInfo.isNotEmpty()) fullyVisibleItemsInfo.last() else null
|
||||||
|
|
||||||
|
|
||||||
|
LaunchedEffect(page.intValue) {
|
||||||
|
if (!isLoading.value) {
|
||||||
|
isLoading.value = true
|
||||||
|
delay(500)
|
||||||
|
val newQuotes = services.getSomeQuotes(15, page.intValue)
|
||||||
|
val uniqueQuotes = newQuotes.filterNot { new -> quotes.any { it.id == new.id } }
|
||||||
|
|
||||||
|
if (uniqueQuotes.isNotEmpty()) {
|
||||||
|
quotes.addAll(uniqueQuotes)
|
||||||
|
} else {
|
||||||
|
println("Aucune nouvelle quote à la page ${page.intValue}, stop pagination.")
|
||||||
|
}
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NavBar(
|
||||||
|
onAccueil = true,
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
navControllerFavorite = navFavorite,
|
navControllerFavorite = navFavorite,
|
||||||
navControllerAccueil = { },
|
|
||||||
navControllerProfil = navProfil,
|
navControllerProfil = navProfil,
|
||||||
navControllerQuiz = navQuiz
|
navControllerQuiz = navQuiz,
|
||||||
){
|
navControllerSearch = navSearch
|
||||||
Box(
|
) {
|
||||||
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(colorBackground),
|
.background(MaterialTheme.colorScheme.background)
|
||||||
contentAlignment = Alignment.Center
|
) {
|
||||||
){
|
LazyColumn(modifier = Modifier.weight(1f), state = state) {
|
||||||
Column {
|
item {
|
||||||
Text("Accueil", color = Color.White, fontSize = 20.sp)
|
Column(Modifier.clickable { navQuote(dailyQuote.id) }) {
|
||||||
|
Text(
|
||||||
|
text = titleDalyQuote,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
fontSize = 24.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
QuoteLittle(dailyQuote)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = titleSuggestion,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
fontSize = 24.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
items(quotes) { quote ->
|
||||||
|
if (quote.language == currentUserState.langage) {
|
||||||
|
Column(Modifier.clickable { navQuote(quote.id ) }) {
|
||||||
|
QuoteLittle(quote)
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
if (lastItem?.index == quotes.size) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LaunchedEffect(remember { derivedStateOf { state.firstVisibleItemIndex } }, remember { derivedStateOf { state.layoutInfo } }.value.totalItemsCount) {
|
||||||
|
if (!isLoading.value && state.layoutInfo.visibleItemsInfo.isNotEmpty()) {
|
||||||
|
val lastVisibleItem = state.layoutInfo.visibleItemsInfo.last()
|
||||||
|
if (lastVisibleItem.index >= state.layoutInfo.totalItemsCount - 1) {
|
||||||
|
page.intValue++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,69 +1,77 @@
|
|||||||
package com.example.what_the_fantasy.ui.screens
|
package com.example.what_the_fantasy.ui.screens
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import com.example.what_the_fantasy.R
|
import com.example.what_the_fantasy.R
|
||||||
import com.example.what_the_fantasy.data.local.QuoteStub
|
import com.example.what_the_fantasy.data.services.IServices
|
||||||
import com.example.what_the_fantasy.ui.components.LittleQuoteComponent
|
|
||||||
import com.example.what_the_fantasy.ui.components.NavBar
|
import com.example.what_the_fantasy.ui.components.NavBar
|
||||||
import com.example.what_the_fantasy.ui.components.TitlePageComponent
|
import com.example.what_the_fantasy.ui.components.QuoteLittle
|
||||||
|
import com.example.what_the_fantasy.ui.states.CurrentUserState
|
||||||
import com.example.what_the_fantasy.ui.theme.colorBackground
|
import com.example.what_the_fantasy.ui.theme.colorBackground
|
||||||
|
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FavoritePage(
|
fun FavoritePage(
|
||||||
index: Int,
|
navAccueil: () -> Unit,
|
||||||
navAccueil: (Int) -> Unit,
|
navQuiz: () -> Unit,
|
||||||
navQuiz: (Int) -> Unit,
|
navProfil: () -> Unit,
|
||||||
navProfil: (Int) -> Unit
|
navQuote: (Int) -> Unit,
|
||||||
|
navSearch: () -> Unit,
|
||||||
|
services: IServices,
|
||||||
|
currentUserVM : CurrentUserViewModel,
|
||||||
|
currentUserState : CurrentUserState,
|
||||||
) {
|
) {
|
||||||
NavBar(
|
val user = services.getUserById(currentUserState.id) ?: return
|
||||||
onFavorite = true,
|
|
||||||
index = index,
|
val quotes = services.getFavorite(user)
|
||||||
navControllerFavorite = { },
|
|
||||||
|
val titlePage = stringResource(R.string.TitleFavorite)
|
||||||
|
NavBar(onFavorite = true,
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
navControllerFavorite = { },
|
||||||
navControllerAccueil = navAccueil,
|
navControllerAccueil = navAccueil,
|
||||||
navControllerProfil = navProfil,
|
navControllerProfil = navProfil,
|
||||||
navControllerQuiz = navQuiz
|
navControllerQuiz = navQuiz,
|
||||||
|
navControllerSearch = navSearch
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(colorBackground),
|
.background(MaterialTheme.colorScheme.background),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.TopCenter
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier
|
LazyColumn {
|
||||||
.padding(top = 20.dp),
|
item {
|
||||||
horizontalAlignment = Alignment.CenterHorizontally) {
|
Text(
|
||||||
TitlePageComponent(R.string.TitleFavorite, Color.White)
|
text = titlePage,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
LazyColumn(
|
fontSize = 24.sp,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxWidth()
|
||||||
.background(Color(0xFF100C1B))
|
.padding(16.dp),
|
||||||
.padding(top = 16.dp),
|
textAlign = TextAlign.Center
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
)
|
||||||
) {
|
}
|
||||||
items(QuoteStub.allQuotes) { quote ->
|
items(quotes) { quote ->
|
||||||
LittleQuoteComponent(quote)
|
Column(Modifier.clickable { navQuote(quote.id) }) {
|
||||||
|
QuoteLittle(quote)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,165 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.screens
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.what_the_fantasy.data.local.QuestionStub
|
||||||
|
import com.example.what_the_fantasy.ui.components.NavBar
|
||||||
|
import com.example.what_the_fantasy.ui.states.CurrentUserState
|
||||||
|
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun QuizRandom(
|
||||||
|
navFavorite: () -> Unit,
|
||||||
|
navAccueil: () -> Unit,
|
||||||
|
navProfil:() -> Unit,
|
||||||
|
navQuiz: () -> Unit,
|
||||||
|
navSearch: () -> Unit,
|
||||||
|
navControllerQuizEnd: (Int, Int) -> Unit,
|
||||||
|
currentUserVM : CurrentUserViewModel,
|
||||||
|
currentUserState : CurrentUserState,
|
||||||
|
) {
|
||||||
|
val questions = QuestionStub.shuffleRandomQuestions
|
||||||
|
var idCurrentQuestion by remember { mutableIntStateOf(0) }
|
||||||
|
var pts by remember { mutableIntStateOf(0) }
|
||||||
|
var lifes by remember { mutableIntStateOf(3) }
|
||||||
|
|
||||||
|
val gradient = Brush.linearGradient(
|
||||||
|
colors = listOf(MaterialTheme.colorScheme.onPrimary, MaterialTheme.colorScheme.onPrimary),
|
||||||
|
start = Offset(0f, 1000f),
|
||||||
|
end = Offset(1000f, 0f)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun onAnswerSelected(answer: String) {
|
||||||
|
val currentQuestion = questions[idCurrentQuestion]
|
||||||
|
val correctAnswer = mapOf(
|
||||||
|
"A" to currentQuestion.ansA,
|
||||||
|
"B" to currentQuestion.ansB,
|
||||||
|
"C" to currentQuestion.ansC,
|
||||||
|
"D" to currentQuestion.ansD
|
||||||
|
)[currentQuestion.correctAns]
|
||||||
|
|
||||||
|
if (answer == correctAnswer) pts++
|
||||||
|
else {
|
||||||
|
lifes -= 1
|
||||||
|
Log.d("Quiz Debug", "Lifes -1 :, $lifes")
|
||||||
|
}
|
||||||
|
if (idCurrentQuestion < questions.size - 1 && lifes > 0) idCurrentQuestion++
|
||||||
|
else {
|
||||||
|
navControllerQuizEnd(-1, pts)
|
||||||
|
Log.d("Quiz Debug", "Game over lifes : $lifes")
|
||||||
|
} // Retour menu
|
||||||
|
}
|
||||||
|
NavBar(
|
||||||
|
navControllerFavorite = navFavorite,
|
||||||
|
navControllerAccueil = navAccueil,
|
||||||
|
navControllerProfil = navProfil,
|
||||||
|
navControllerQuiz = navQuiz,
|
||||||
|
navControllerSearch = navSearch,
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
){
|
||||||
|
Column (
|
||||||
|
modifier = Modifier.fillMaxSize().background(Color(0xFF100C1B))
|
||||||
|
) {
|
||||||
|
// Contenu princiapl
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(0.8f)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 50.dp, vertical = 20.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
val question = questions[idCurrentQuestion]
|
||||||
|
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
if (questions != null) {
|
||||||
|
Text(
|
||||||
|
text = "▶ Random Quiz ◀",
|
||||||
|
color = Color.White,
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(Modifier.height(20.dp))
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(brush = gradient, shape = RoundedCornerShape(20.dp))
|
||||||
|
.height(800.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
"Question ${idCurrentQuestion + 1}",
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 20.dp)
|
||||||
|
.weight(0.1f),
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 25.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
question.question,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 25.dp)
|
||||||
|
.weight(0.1f),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(0.7f)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.padding(vertical = 30.dp),
|
||||||
|
verticalArrangement = Arrangement.SpaceBetween
|
||||||
|
|
||||||
|
) {
|
||||||
|
listOf(
|
||||||
|
question.ansA,
|
||||||
|
question.ansB,
|
||||||
|
question.ansC,
|
||||||
|
question.ansD
|
||||||
|
).forEach { answer ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(220.dp)
|
||||||
|
.height(50.dp)
|
||||||
|
.background(Color.White, shape = RoundedCornerShape(16.dp))
|
||||||
|
.clickable { onAnswerSelected(answer) }
|
||||||
|
.padding(horizontal = 8.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(answer, color = Color.Black, fontSize = 18.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,447 @@
|
|||||||
package com.example.what_the_fantasy.ui.screens
|
package com.example.what_the_fantasy.ui.screens
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.expandVertically
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.shrinkVertically
|
||||||
|
import androidx.compose.animation.slideInVertically
|
||||||
|
import androidx.compose.animation.slideOutVertically
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
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.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.Send
|
||||||
|
import androidx.compose.material.icons.filled.Favorite
|
||||||
|
import androidx.compose.material.icons.filled.FavoriteBorder
|
||||||
|
import androidx.compose.material.icons.filled.Share
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
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.graphics.ColorFilter
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.what_the_fantasy.R
|
||||||
|
import coil.compose.AsyncImage
|
||||||
|
import com.example.what_the_fantasy.data.model.Comment
|
||||||
|
import com.example.what_the_fantasy.data.model.Quote
|
||||||
|
import com.example.what_the_fantasy.data.services.IServices
|
||||||
|
import com.example.what_the_fantasy.logs.LogsUsers
|
||||||
import com.example.what_the_fantasy.ui.components.NavBar
|
import com.example.what_the_fantasy.ui.components.NavBar
|
||||||
|
import com.example.what_the_fantasy.ui.states.CurrentUserState
|
||||||
|
import com.example.what_the_fantasy.ui.states.QuoteInformationUserState
|
||||||
|
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
|
||||||
|
import com.example.what_the_fantasy.ui.viewModels.QuoteInformationUserViewModel
|
||||||
|
|
||||||
|
var isCommentVisible by mutableStateOf(false)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun QuotePage(
|
||||||
|
quoteId : Int,
|
||||||
|
service : IServices,
|
||||||
|
navAccueil: () -> Unit,
|
||||||
|
navFavorite:() -> Unit,
|
||||||
|
navQuiz: () -> Unit,
|
||||||
|
navProfil:() -> Unit,
|
||||||
|
navSearch: () -> Unit,
|
||||||
|
currentUserVM : CurrentUserViewModel,
|
||||||
|
currentUserState : CurrentUserState,
|
||||||
|
quoteInformationUserVM : QuoteInformationUserViewModel,
|
||||||
|
quoteInformationUserState : QuoteInformationUserState
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
// utiliser ViewModel
|
||||||
|
val quote = service.getQuote(quoteId) ?: return
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
val favorite by remember { mutableStateOf(service.isFavorite(
|
||||||
|
idQuote = quoteId,
|
||||||
|
iduser = currentUserState.id)) }
|
||||||
|
|
||||||
|
NavBar(
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
navControllerFavorite = navFavorite,
|
||||||
|
navControllerAccueil = navAccueil,
|
||||||
|
navControllerProfil = navProfil,
|
||||||
|
navControllerQuiz = navQuiz,
|
||||||
|
navControllerSearch = navSearch
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
|
.verticalScroll(rememberScrollState()),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier
|
||||||
|
.padding(15.dp)
|
||||||
|
.background(
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Row(modifier = Modifier.padding(15.dp)) {
|
||||||
|
ImageQuote(
|
||||||
|
imageUrl = quote.imgUrl
|
||||||
|
)
|
||||||
|
Column {
|
||||||
|
|
||||||
|
FunctionalIcon(
|
||||||
|
isFavorite = favorite,
|
||||||
|
userId = currentUserState.id,
|
||||||
|
quoteId = quoteId,
|
||||||
|
context = context,
|
||||||
|
quoteInformationUserVM = quoteInformationUserVM,
|
||||||
|
quoteInformationUserState = quoteInformationUserState,
|
||||||
|
quote = quote
|
||||||
|
)
|
||||||
|
QuoteText(
|
||||||
|
text = '"' + quote.content + '"'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column(modifier = Modifier
|
||||||
|
.padding(15.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
InfoQuoteText(
|
||||||
|
nameId = R.string.source,
|
||||||
|
text = quote.source
|
||||||
|
)
|
||||||
|
InfoQuoteText(
|
||||||
|
nameId = R.string.charac,
|
||||||
|
text = quote.character
|
||||||
|
)
|
||||||
|
|
||||||
|
InfoQuoteText(
|
||||||
|
nameId = R.string.date,
|
||||||
|
text = quote.date.toString()
|
||||||
|
)
|
||||||
|
InfoQuoteText(
|
||||||
|
nameId = R.string.type,
|
||||||
|
text = quote.type.toString()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 10.dp)
|
||||||
|
.align(alignment = Alignment.End)
|
||||||
|
) {
|
||||||
|
LikeInfo(
|
||||||
|
likes = quote.likes,
|
||||||
|
quoteInformationUserVM
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = isCommentVisible,
|
||||||
|
enter = expandVertically(
|
||||||
|
expandFrom = Alignment.CenterVertically
|
||||||
|
) + fadeIn(
|
||||||
|
initialAlpha = 0.3f
|
||||||
|
) + slideInVertically(
|
||||||
|
initialOffsetY = { -40 }
|
||||||
|
),
|
||||||
|
exit = slideOutVertically() + shrinkVertically() + fadeOut()
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(MaterialTheme.colorScheme.primary)
|
||||||
|
.fillMaxSize()){
|
||||||
|
Column {
|
||||||
|
AddComment(currentUserState.id, service, quoteInformationUserState, quoteInformationUserVM)
|
||||||
|
LstComment(service.getComment(quoteId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ Composants non partager de la page --------------------------------------
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun QuoteText(text: String ){
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
modifier = Modifier.padding(start = 10.dp, top = 15.dp),
|
||||||
|
fontWeight = FontWeight(1000),
|
||||||
|
fontSize = 20.sp,
|
||||||
|
color = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ImageQuote(imageUrl : String){
|
||||||
|
AsyncImage(
|
||||||
|
model = imageUrl,
|
||||||
|
contentDescription = stringResource(R.string.profilePict),
|
||||||
|
modifier = Modifier
|
||||||
|
.size(150.dp)
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FunctionalIcon(isFavorite: Boolean,
|
||||||
|
userId : Int,
|
||||||
|
quoteId : Int,
|
||||||
|
context : Context,
|
||||||
|
quoteInformationUserVM : QuoteInformationUserViewModel,
|
||||||
|
quoteInformationUserState : QuoteInformationUserState,
|
||||||
|
quote : Quote
|
||||||
|
){
|
||||||
|
val logsUsers = LogsUsers()
|
||||||
|
|
||||||
|
Row(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
|
||||||
|
val sendIntent = Intent().apply {
|
||||||
|
action = Intent.ACTION_SEND
|
||||||
|
// lien a changer quand le site sra deployer
|
||||||
|
putExtra(Intent.EXTRA_TEXT, "http://wfWebsite/quote/$quoteId")
|
||||||
|
type = "text/plain"
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
logsUsers.shareInformationUser("ShareQuote", quoteId, userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
val shareIntent = Intent.createChooser(sendIntent, null)
|
||||||
|
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
|
||||||
|
context.startActivity(shareIntent)
|
||||||
|
},
|
||||||
|
modifier = Modifier.padding(start = 15.dp)
|
||||||
|
) {
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Share,
|
||||||
|
contentDescription = stringResource(R.string.share),
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
isCommentVisible = !isCommentVisible
|
||||||
|
},
|
||||||
|
modifier = Modifier.padding(start = 20.dp)
|
||||||
|
){
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.message),
|
||||||
|
contentDescription ="message",
|
||||||
|
modifier = Modifier.size(30.dp),
|
||||||
|
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onPrimary)
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isFavorite){
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
quoteInformationUserVM.supFav(userId = userId, idQuote = quoteId)
|
||||||
|
quote.likes = quoteInformationUserState.like
|
||||||
|
//Log.e("Like", "Coeur ${quote.likes} ${quoteInformationUserState.like}")
|
||||||
|
logsUsers.favoriteInformationUserFalse("Favorite", quoteId, userId)
|
||||||
|
}, //sup fav
|
||||||
|
modifier = Modifier.padding(start = 20.dp)
|
||||||
|
){
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Favorite,
|
||||||
|
contentDescription = stringResource(R.string.favorite),
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
quoteInformationUserVM.addFav(userId = userId, idQuote = quoteId)
|
||||||
|
quote.likes = quoteInformationUserState.like
|
||||||
|
logsUsers.favoriteInformationUserTrue("Favorite", quoteId, userId)
|
||||||
|
}, //add fav
|
||||||
|
modifier = Modifier.padding(start = 50.dp)
|
||||||
|
){
|
||||||
|
Icon(
|
||||||
|
Icons.Default.FavoriteBorder,
|
||||||
|
contentDescription = stringResource(R.string.favorite),
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun InfoQuoteText(nameId : Int, text : String){
|
||||||
|
Column(modifier = Modifier.padding(bottom = 20.dp)){
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = nameId),
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight(500),
|
||||||
|
color = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight(400),
|
||||||
|
modifier = Modifier
|
||||||
|
.background(
|
||||||
|
color = MaterialTheme.colorScheme.background,
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
.padding(5.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LikeInfo(likes : Int,
|
||||||
|
quoteInformationUserVM : QuoteInformationUserViewModel){
|
||||||
|
quoteInformationUserVM.setLike(likes)
|
||||||
|
//Log.e("Like", "LikeInfo => Nb Like : ${likes}")
|
||||||
|
Text(
|
||||||
|
text = likes.toString(),
|
||||||
|
color = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Favorite,
|
||||||
|
contentDescription = stringResource(R.string.favorite),
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AddComment(userId: Int,
|
||||||
|
service: IServices,
|
||||||
|
quoteInformationUserState: QuoteInformationUserState,
|
||||||
|
quoteInformationUserVM: QuoteInformationUserViewModel) {
|
||||||
|
// var text by remember { mutableStateOf(quoteInformationUserState.comment) }
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(15.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
IconButton(
|
||||||
|
onClick = { isCommentVisible = !isCommentVisible }
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
|
contentDescription = stringResource(R.string.send),
|
||||||
|
tint = MaterialTheme.colorScheme.onPrimary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
TextField(
|
||||||
|
value = quoteInformationUserState.comment,
|
||||||
|
onValueChange = { quoteInformationUserVM.setComment(it) },
|
||||||
|
label = { Text(stringResource(R.string.comment)) },
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(horizontal = 8.dp),
|
||||||
|
shape = RoundedCornerShape(20.dp),
|
||||||
|
colors = TextFieldDefaults.colors(
|
||||||
|
focusedContainerColor = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
unfocusedContainerColor = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
focusedIndicatorColor = Color.Transparent,
|
||||||
|
unfocusedIndicatorColor = Color.Transparent,
|
||||||
|
focusedLabelColor = MaterialTheme.colorScheme.primary,
|
||||||
|
unfocusedLabelColor = MaterialTheme.colorScheme.primary
|
||||||
|
),
|
||||||
|
trailingIcon = {
|
||||||
|
IconButton(
|
||||||
|
onClick = { isCommentVisible = !isCommentVisible }
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.AutoMirrored.Filled.Send,
|
||||||
|
contentDescription = "Retour",
|
||||||
|
tint = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@Composable
|
@Composable
|
||||||
fun QuotePage() {
|
fun LstComment(lst: List<Comment>) {
|
||||||
}
|
LazyColumn(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
modifier = Modifier.padding(10.dp)
|
||||||
|
) {
|
||||||
|
items(lst) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(
|
||||||
|
color = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
shape = RoundedCornerShape(15.dp)
|
||||||
|
)
|
||||||
|
.padding(12.dp)
|
||||||
|
) {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
AsyncImage(
|
||||||
|
model = it.img,
|
||||||
|
contentDescription = stringResource(R.string.profilePict),
|
||||||
|
modifier = Modifier
|
||||||
|
.size(50.dp)
|
||||||
|
.clip(RoundedCornerShape(50))
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "${it.user} • ${it.date}",
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
modifier = Modifier.padding(start = 12.dp),
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 14.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = it.content,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
modifier = Modifier.padding(top = 10.dp, start = 8.dp, end = 8.dp),
|
||||||
|
fontSize = 14.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -0,0 +1,170 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
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.material3.Text
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.drawBehind
|
||||||
|
import androidx.compose.ui.geometry.CornerRadius
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.what_the_fantasy.R
|
||||||
|
import coil.compose.AsyncImage
|
||||||
|
import com.example.what_the_fantasy.ui.components.NavBar
|
||||||
|
import com.example.what_the_fantasy.ui.theme.gradienBox
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import com.example.what_the_fantasy.data.model.Character
|
||||||
|
import com.example.what_the_fantasy.ui.states.CurrentUserState
|
||||||
|
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RecapSubmitPage(
|
||||||
|
navFavorite: () -> Unit,
|
||||||
|
navAccueil: () -> Unit,
|
||||||
|
navProfil:() -> Unit,
|
||||||
|
navSearch: () -> Unit,
|
||||||
|
navQuiz : () -> Unit,
|
||||||
|
quoteContent : String,
|
||||||
|
character: String,
|
||||||
|
source: String,
|
||||||
|
currentUserVM : CurrentUserViewModel,
|
||||||
|
currentUserState : CurrentUserState,
|
||||||
|
) {
|
||||||
|
NavBar(onQuiz = true,
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
navControllerFavorite = navFavorite,
|
||||||
|
navControllerAccueil = navAccueil,
|
||||||
|
navControllerProfil = navProfil,
|
||||||
|
navControllerQuiz = navQuiz,
|
||||||
|
navControllerSearch = navSearch
|
||||||
|
) {
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
|
) {
|
||||||
|
// Contenu princiapl
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(0.9f)
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(20.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "▶ Recap de la citation ◀",
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 25.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(20.dp))
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(brush = gradient, shape = RoundedCornerShape(20.dp))
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(vertical = 30.dp)
|
||||||
|
.verticalScroll(rememberScrollState()),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier
|
||||||
|
.padding(15.dp)
|
||||||
|
.drawBehind {
|
||||||
|
drawRoundRect(
|
||||||
|
gradienBox,
|
||||||
|
cornerRadius = CornerRadius(15.dp.toPx()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Row(modifier = Modifier.padding(15.dp)) {
|
||||||
|
ImageQuote(
|
||||||
|
imageUrl = "https://img.freepik.com/vecteurs-libre/personnage-guerrier-fantaisie_1045-185.jpg?size=338&ext=jpg"
|
||||||
|
)
|
||||||
|
Column {
|
||||||
|
QuoteText(
|
||||||
|
text = '"' + quoteContent + '"'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column(modifier = Modifier
|
||||||
|
.padding(15.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
InfoQuoteText(
|
||||||
|
nameId = R.string.source,
|
||||||
|
text = source
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "Character : $character"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun QuoteText2(text: String ){
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
modifier = Modifier.padding(start = 10.dp, top = 15.dp),
|
||||||
|
fontWeight = FontWeight(1000),
|
||||||
|
fontSize = 20.sp,
|
||||||
|
color = MaterialTheme.colorScheme.background
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ImageQuote2(imageUrl : String){
|
||||||
|
AsyncImage(
|
||||||
|
model = imageUrl,
|
||||||
|
contentDescription = "exemple",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(150.dp)
|
||||||
|
.clip(RoundedCornerShape(15.dp))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun InfoQuoteText2(nameId : Int, text : String){
|
||||||
|
Column(modifier = Modifier.padding(bottom = 20.dp)){
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight(400),
|
||||||
|
modifier = Modifier
|
||||||
|
.drawBehind {
|
||||||
|
drawRoundRect(
|
||||||
|
Color(255,255,255),
|
||||||
|
cornerRadius = CornerRadius(15.dp.toPx())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.padding(5.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,203 @@
|
|||||||
package com.example.what_the_fantasy.ui.screens
|
package com.example.what_the_fantasy.ui.screens
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import android.util.Log
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.foundation.selection.selectable
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.Search
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.semantics.Role
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.example.what_the_fantasy.R
|
||||||
|
import com.example.what_the_fantasy.data.model.Quote
|
||||||
|
import com.example.what_the_fantasy.data.services.IServices
|
||||||
import com.example.what_the_fantasy.ui.components.NavBar
|
import com.example.what_the_fantasy.ui.components.NavBar
|
||||||
|
import com.example.what_the_fantasy.ui.components.QuoteLittle
|
||||||
|
import com.example.what_the_fantasy.ui.states.CurrentUserState
|
||||||
|
import com.example.what_the_fantasy.ui.states.SearchState
|
||||||
|
import com.example.what_the_fantasy.ui.viewModels.AuthUserViewModel
|
||||||
|
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
|
||||||
|
import com.example.what_the_fantasy.ui.viewModels.SearchViewModel
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SearchPage() {
|
fun SearchPage(
|
||||||
}
|
navFavorite: () -> Unit,
|
||||||
|
navAccueil: () -> Unit,
|
||||||
|
navProfil: () -> Unit,
|
||||||
|
navQuiz: () -> Unit,
|
||||||
|
navQuote: (Int) -> Unit,
|
||||||
|
navSearch: (String, String) -> Unit,
|
||||||
|
type: String,
|
||||||
|
search: String,
|
||||||
|
currentUserVM : CurrentUserViewModel,
|
||||||
|
currentUserState : CurrentUserState,
|
||||||
|
searchVM : SearchViewModel,
|
||||||
|
searchState : SearchState,
|
||||||
|
) {
|
||||||
|
|
||||||
|
|
||||||
|
val textQuoteSearch = stringResource(id = R.string.QuoteSearch)
|
||||||
|
val textTitleSearch = stringResource(id = R.string.TitleQuoteSearch)
|
||||||
|
val textCharacterSearch = stringResource(id = R.string.character)
|
||||||
|
val textSearch = stringResource(id = R.string.Search)
|
||||||
|
|
||||||
|
val filtre = listOf("contenu", "personnage", "titre")
|
||||||
|
//val filtre = listOf(textQuoteSearch, textCharacterSearch, textTitleSearch)
|
||||||
|
val (newFiltre, onFiltreSelected) = remember { mutableStateOf(type) }
|
||||||
|
|
||||||
|
val page = remember { mutableIntStateOf(1) }
|
||||||
|
val quotes = remember { mutableStateListOf<Quote>() }
|
||||||
|
val isLoading = remember { mutableStateOf(false) }
|
||||||
|
val state = rememberLazyListState()
|
||||||
|
|
||||||
|
LaunchedEffect(page.intValue, type, search) {
|
||||||
|
if (!isLoading.value) {
|
||||||
|
isLoading.value = true
|
||||||
|
delay(500)
|
||||||
|
val newQuotes = searchVM.search(type, search, page.intValue * 15)
|
||||||
|
val uniqueQuotes = newQuotes.filterNot { new -> quotes.any { it.id == new.id } }
|
||||||
|
if (uniqueQuotes.isNotEmpty()) {
|
||||||
|
quotes.addAll(uniqueQuotes)
|
||||||
|
}
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NavBar(
|
||||||
|
onAccueil = true,
|
||||||
|
navControllerFavorite = navFavorite,
|
||||||
|
navControllerAccueil = navAccueil,
|
||||||
|
navControllerProfil = navProfil,
|
||||||
|
navControllerQuiz = navQuiz,
|
||||||
|
navControllerSearch = { navSearch("contenu", "") },
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
|
||||||
|
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "▶ " + stringResource(R.string.TitleSearch) + " ◀",
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
fontSize = 24.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = searchState.search,
|
||||||
|
onValueChange = {
|
||||||
|
searchVM.setSearch(it)
|
||||||
|
},
|
||||||
|
textStyle = TextStyle(color = MaterialTheme.colorScheme.onBackground),
|
||||||
|
label = { Text(textSearch) },
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 2.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(70.dp),
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
|
||||||
|
maxLines = 1,
|
||||||
|
shape = CircleShape,
|
||||||
|
trailingIcon = {
|
||||||
|
IconButton(
|
||||||
|
onClick = { navSearch(newFiltre, searchState.search) },
|
||||||
|
modifier = Modifier
|
||||||
|
.size(50.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
) {
|
||||||
|
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.search),
|
||||||
|
contentDescription = "search",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(30.dp),
|
||||||
|
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Row(horizontalArrangement = Arrangement.SpaceAround) {
|
||||||
|
filtre.forEach { typeItem ->
|
||||||
|
Row(
|
||||||
|
Modifier
|
||||||
|
.height(56.dp)
|
||||||
|
.selectable(
|
||||||
|
selected = (typeItem == newFiltre),
|
||||||
|
onClick = { onFiltreSelected(typeItem) },
|
||||||
|
role = Role.RadioButton
|
||||||
|
)
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
RadioButton(
|
||||||
|
selected = (typeItem == newFiltre),
|
||||||
|
onClick = null
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = typeItem,
|
||||||
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
|
modifier = Modifier.padding(start = 16.dp),
|
||||||
|
color = MaterialTheme.colorScheme.onBackground
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
state = state
|
||||||
|
) {
|
||||||
|
items(quotes) { quote ->
|
||||||
|
Column(Modifier.clickable { navQuote(quote.id) }) {
|
||||||
|
if(quote.language == currentUserState.langage) { // affiche les suggestions de citation dans la bonne langue
|
||||||
|
QuoteLittle(quote)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
if (state.layoutInfo.visibleItemsInfo.lastOrNull()?.index == quotes.size - 1 && !isLoading.value) {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
page.intValue++
|
||||||
|
}
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,8 +1,267 @@
|
|||||||
package com.example.what_the_fantasy.ui.screens
|
package com.example.what_the_fantasy.ui.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
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.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
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.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.example.what_the_fantasy.R
|
||||||
|
import com.example.what_the_fantasy.ui.components.ErrorMessageSubmitQuoteComponent
|
||||||
import com.example.what_the_fantasy.ui.components.NavBar
|
import com.example.what_the_fantasy.ui.components.NavBar
|
||||||
|
import com.example.what_the_fantasy.ui.components.SpaceHeightComponent
|
||||||
|
import com.example.what_the_fantasy.ui.components.TitlePageComponent
|
||||||
|
import com.example.what_the_fantasy.ui.states.CurrentUserState
|
||||||
|
import com.example.what_the_fantasy.ui.theme.colorBackground
|
||||||
|
import com.example.what_the_fantasy.ui.theme.gradienBox
|
||||||
|
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SubmitQuotePage() {
|
fun SubmitQuotePage(
|
||||||
}
|
navFavorite: () -> Unit,
|
||||||
|
navAccueil: () -> Unit,
|
||||||
|
navProfil:() -> Unit,
|
||||||
|
navQuiz: () -> Unit,
|
||||||
|
navRecap: (String, String, String) -> Unit,
|
||||||
|
currentUserVM : CurrentUserViewModel,
|
||||||
|
currentUserState : CurrentUserState,
|
||||||
|
) {
|
||||||
|
NavBar(
|
||||||
|
currentUserVM = currentUserVM,
|
||||||
|
currentUserState = currentUserState,
|
||||||
|
navControllerFavorite = navFavorite,
|
||||||
|
navControllerAccueil = navAccueil,
|
||||||
|
navControllerProfil = navProfil,
|
||||||
|
navControllerQuiz = navQuiz
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
|
.verticalScroll(rememberScrollState()),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
){
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(0.9f)
|
||||||
|
.padding(20.dp)
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(MaterialTheme.colorScheme.onPrimary)
|
||||||
|
.padding(20.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
TitlePageComponent(R.string.titleSubmitQuote, MaterialTheme.colorScheme.onBackground)
|
||||||
|
SpaceHeightComponent(20)
|
||||||
|
SubmitQuoteButton(
|
||||||
|
quoteTextField(R.string.quote),
|
||||||
|
characterTextField(R.string.character),
|
||||||
|
sourceTextField(R.string.source),
|
||||||
|
timeCodeTextField(R.string.timeCode),
|
||||||
|
yearTextField(R.string.year),
|
||||||
|
R.string.titleButtonSubmit,
|
||||||
|
18,
|
||||||
|
MaterialTheme.colorScheme.background,
|
||||||
|
MaterialTheme.colorScheme.onBackground,
|
||||||
|
navRecap
|
||||||
|
)
|
||||||
|
SpaceHeightComponent(20)
|
||||||
|
BackButton(R.string.titleButtonBack, 12, Color.White,navProfil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun quoteTextField(textQuoteResId : Int) : String{
|
||||||
|
val textQuote = stringResource(id = textQuoteResId)
|
||||||
|
var quote by remember { mutableStateOf("") }
|
||||||
|
Column(modifier = Modifier.padding(top = 16.dp)) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = quote,
|
||||||
|
onValueChange = { quote = it },
|
||||||
|
label = { Text(textQuote, color = MaterialTheme.colorScheme.onBackground) },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp),
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
|
||||||
|
shape = RoundedCornerShape(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return quote;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun characterTextField(textCharacterResId : Int) : String{
|
||||||
|
val textCharacter = stringResource(id = textCharacterResId)
|
||||||
|
var character by remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
Column(modifier = Modifier.padding(top = 16.dp)) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = character,
|
||||||
|
onValueChange = { character = it },
|
||||||
|
label = { Text(textCharacter, color = MaterialTheme.colorScheme.onBackground) },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp),
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
|
||||||
|
shape = RoundedCornerShape(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return character;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun sourceTextField(textSourceResId : Int) : String{
|
||||||
|
val textSource = stringResource(id = textSourceResId)
|
||||||
|
var source by remember { mutableStateOf("") }
|
||||||
|
Column(modifier = Modifier.padding(top = 16.dp)) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = source,
|
||||||
|
onValueChange = { source = it },
|
||||||
|
label = { Text(textSource, color = MaterialTheme.colorScheme.onBackground) },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp),
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
|
||||||
|
shape = RoundedCornerShape(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun timeCodeTextField(textTimeCodeResId : Int) : String{
|
||||||
|
val textTimeCode = stringResource(id = textTimeCodeResId)
|
||||||
|
var timeCode by remember { mutableStateOf("") }
|
||||||
|
Column(modifier = Modifier.padding(top = 16.dp)) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = timeCode,
|
||||||
|
onValueChange = { timeCode = it },
|
||||||
|
label = { Text(textTimeCode, color = MaterialTheme.colorScheme.onBackground) },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp),
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
|
||||||
|
shape = RoundedCornerShape(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return timeCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun yearTextField(textYearResId : Int) : String{
|
||||||
|
val textYear = stringResource(id = textYearResId)
|
||||||
|
var year by remember { mutableStateOf("") }
|
||||||
|
Column(modifier = Modifier.padding(top = 16.dp, bottom = 30.dp)) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = year,
|
||||||
|
onValueChange = { year = it },
|
||||||
|
label = { Text(textYear, color = MaterialTheme.colorScheme.onBackground) },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp),
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
|
||||||
|
shape = RoundedCornerShape(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SubmitQuoteButton(
|
||||||
|
quote: String,
|
||||||
|
character: String,
|
||||||
|
source: String,
|
||||||
|
timeCode: String,
|
||||||
|
year: String,
|
||||||
|
titleResId: Int,
|
||||||
|
size: Int,
|
||||||
|
colorButton: Color,
|
||||||
|
colorText: Color,
|
||||||
|
navRecap : (String, String, String) -> Unit
|
||||||
|
) {
|
||||||
|
val title = stringResource(id = titleResId)
|
||||||
|
var showError by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { showError = !goToRecap(quote, character, source, timeCode, year, navRecap) },
|
||||||
|
colors = ButtonDefaults.buttonColors(containerColor = colorButton),
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
Text(title, fontSize = size.sp, color = colorText)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showError) {
|
||||||
|
ErrorMessageSubmitQuoteComponent(R.string.ErrorSubmitQuote)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun goToRecap(quote: String,
|
||||||
|
character: String,
|
||||||
|
source: String,
|
||||||
|
timeCode: String,
|
||||||
|
year: String,
|
||||||
|
navRecap : (String, String, String) -> Unit): Boolean {
|
||||||
|
if (validSubmitQuote(quote, character, source, timeCode, year)) {
|
||||||
|
navRecap(quote, character, source)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun validSubmitQuote(quote : String, character : String, source: String, timeCode: String, year: String): Boolean{
|
||||||
|
|
||||||
|
val quoteRegex = """^[A-Za-zÀ-ÿ0-9\s\-\.,!?'"()]+$""".toRegex()
|
||||||
|
val timeCodeRegex = """^\d{1}:\d{2}:\d{2}$""".toRegex()
|
||||||
|
val movieTitleRegex = """^[A-Za-z0-9\s\-\(\):]+$""".toRegex()
|
||||||
|
val characterRegex = """^[A-Za-zÀ-ÿ\s\-']+$""".toRegex()
|
||||||
|
val invalidRegex = """^[a-zA-Z0-9]*$""".toRegex()
|
||||||
|
|
||||||
|
val isNotBlank = quote.isNotBlank() && quote.matches(quoteRegex) && !quote.matches(invalidRegex) && quote.length in 3..100 &&
|
||||||
|
character.isNotBlank() && character.matches(characterRegex) && character.length in 3..50 && /*!character.matches(invalidRegex) &&*/
|
||||||
|
source.isNotBlank() && source.matches(movieTitleRegex) && source.length in 3..50 && /*!source.matches(invalidRegex) &&*/
|
||||||
|
timeCode.isNotBlank() && timeCode.matches(timeCodeRegex) &&
|
||||||
|
year.isNotBlank() && year.all { it.isDigit() } && year.length == 4 && year.toInt() in 1900..2025
|
||||||
|
return isNotBlank
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun BackButton(titleResId : Int, size : Int, color : Color, navController: () -> Unit) {
|
||||||
|
val title = stringResource(id = titleResId)
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
fontSize = size.sp,
|
||||||
|
color = color,
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
navController()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.states
|
||||||
|
|
||||||
|
import com.example.what_the_fantasy.data.model.SrcLanguage
|
||||||
|
import com.example.what_the_fantasy.data.model.User
|
||||||
|
|
||||||
|
data class AuthUserState (
|
||||||
|
val username : String = "",
|
||||||
|
val password: String = "",
|
||||||
|
)
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.states
|
||||||
|
|
||||||
|
import com.example.what_the_fantasy.data.model.SrcLanguage
|
||||||
|
|
||||||
|
data class CurrentUserState (
|
||||||
|
var id : Int = -1,
|
||||||
|
val imagePath : String ="",
|
||||||
|
var username :String="",
|
||||||
|
var email : String="",
|
||||||
|
var password : String="",
|
||||||
|
var confirmPassword : String="",
|
||||||
|
val langage : SrcLanguage = SrcLanguage.vo
|
||||||
|
)
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.states
|
||||||
|
|
||||||
|
data class QuoteInformationUserState (
|
||||||
|
val comment : String ="",
|
||||||
|
val isFavorite : Boolean = false,
|
||||||
|
val like : Int = 0
|
||||||
|
)
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.states
|
||||||
|
|
||||||
|
data class SearchState (
|
||||||
|
var search : String = ""
|
||||||
|
)
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.states
|
||||||
|
|
||||||
|
data class SignInUserState (
|
||||||
|
val username : String ="",
|
||||||
|
val email : String ="",
|
||||||
|
val password : String ="",
|
||||||
|
val confirmPassword : String ="",
|
||||||
|
)
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.viewModels
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.example.what_the_fantasy.data.services.ServicesStub
|
||||||
|
import com.example.what_the_fantasy.ui.states.AuthUserState
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
|
class AuthUserViewModel : ViewModel(){
|
||||||
|
private val services = ServicesStub() // faire repository qui gère les services Stub et API
|
||||||
|
private val _userState = MutableStateFlow(AuthUserState())
|
||||||
|
val userState : StateFlow<AuthUserState> = _userState.asStateFlow()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun setUsername(username : String){
|
||||||
|
_userState.update { it.copy(username=username) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setPassword(password : String){
|
||||||
|
_userState.update { it.copy(password=password) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun validLogin(username : String, passwd : String, navController: (Int) -> Unit, initialierCurrentUser : (Int) -> Unit) : Boolean{
|
||||||
|
return services.validLogin(username,passwd, navController, initialierCurrentUser)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.viewModels
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.example.what_the_fantasy.data.model.SrcLanguage
|
||||||
|
import com.example.what_the_fantasy.data.services.ServicesStub
|
||||||
|
import com.example.what_the_fantasy.ui.states.CurrentUserState
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
|
class CurrentUserViewModel : ViewModel(){
|
||||||
|
private val services = ServicesStub() // faire repository qui gère les services Stub et API
|
||||||
|
private val _currentUserState = MutableStateFlow(CurrentUserState())
|
||||||
|
var currentUserState : StateFlow<CurrentUserState> = _currentUserState.asStateFlow()
|
||||||
|
|
||||||
|
|
||||||
|
fun initialiseCurrentUser(index : Int){
|
||||||
|
services.getUserById(index)?.let {
|
||||||
|
setId(it.id)
|
||||||
|
setUsername(it.username)
|
||||||
|
setEmail(it.email)
|
||||||
|
setPassword(it.password)
|
||||||
|
setLangue(it.langage)
|
||||||
|
setImage(it.imgUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearCurrentUser(){
|
||||||
|
_currentUserState.value = CurrentUserState()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setId(id : Int){
|
||||||
|
_currentUserState.update {it.copy(id = id)}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUsername(username : String){
|
||||||
|
_currentUserState.update {it.copy(username = username)}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setEmail(email : String){
|
||||||
|
_currentUserState.update {it.copy(email = email)}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setPassword(password : String){
|
||||||
|
_currentUserState.update {it.copy(password = password)}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun setLangue(langue : SrcLanguage){
|
||||||
|
_currentUserState.update {it.copy(langage = langue)}
|
||||||
|
}
|
||||||
|
fun setImage(imagePath : String){
|
||||||
|
_currentUserState.update {it.copy(imagePath = imagePath)}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun editUsername(username : String, index : Int) : Boolean{
|
||||||
|
_currentUserState.update {it.copy(username = username)}
|
||||||
|
return services.EditUsername(username, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun editEmail(email : String, index : Int) : Boolean{
|
||||||
|
_currentUserState.update {
|
||||||
|
it.copy(email = email)
|
||||||
|
}
|
||||||
|
return services.EditEmail(email, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun editPassword(password : String, index : Int){
|
||||||
|
services.EditPasswd(password, index)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun editLangue(index : Int){
|
||||||
|
val langage = services.ChangeLangage(index)
|
||||||
|
|
||||||
|
_currentUserState.update {
|
||||||
|
it.copy(langage = langage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun editImage(index : Int){
|
||||||
|
val image = services.EditImage(index)
|
||||||
|
|
||||||
|
_currentUserState.update {
|
||||||
|
it.copy(imagePath = image)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.viewModels
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.example.what_the_fantasy.data.services.ServicesStub
|
||||||
|
import com.example.what_the_fantasy.ui.states.QuoteInformationUserState
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
|
class QuoteInformationUserViewModel: ViewModel() {
|
||||||
|
private val services = ServicesStub() // faire repository qui gère les services Stub et API
|
||||||
|
private val _quoteState = MutableStateFlow(QuoteInformationUserState())
|
||||||
|
val quoteState : StateFlow<QuoteInformationUserState> = _quoteState.asStateFlow()
|
||||||
|
|
||||||
|
fun setComment(comment : String){
|
||||||
|
_quoteState.update { it.copy(comment=comment) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setFavorite(isFavorite : Boolean){
|
||||||
|
_quoteState.update { it.copy(isFavorite=isFavorite) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setLike(like : Int){
|
||||||
|
if(like >= 0) {
|
||||||
|
_quoteState.update { it.copy(like=like) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addFav(userId: Int, idQuote: Int) {
|
||||||
|
services.AddFav(userId, idQuote)
|
||||||
|
setLike(quoteState.value.like + 1)
|
||||||
|
setFavorite(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun supFav(userId: Int, idQuote: Int) {
|
||||||
|
services.SupFav(userId, idQuote)
|
||||||
|
setLike(quoteState.value.like - 1)
|
||||||
|
setFavorite(false)
|
||||||
|
//Log.e("Like", "Service ${quoteState.value.like}")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.viewModels
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.example.what_the_fantasy.data.model.Quote
|
||||||
|
import com.example.what_the_fantasy.data.services.ServicesStub
|
||||||
|
import com.example.what_the_fantasy.ui.states.CurrentUserState
|
||||||
|
import com.example.what_the_fantasy.ui.states.SearchState
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
|
class SearchViewModel : ViewModel() {
|
||||||
|
private val services = ServicesStub() // faire repository qui gère les services Stub et API
|
||||||
|
private val _searchState = MutableStateFlow(SearchState())
|
||||||
|
var searchState : StateFlow<SearchState> = _searchState.asStateFlow()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun setSearch(search : String){
|
||||||
|
_searchState.update {it.copy(search = search)}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun search(type : String ,search:String ,indexCount: Int): List<Quote>{
|
||||||
|
return services.search(type,search,indexCount)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.example.what_the_fantasy.ui.viewModels
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.example.what_the_fantasy.data.services.ServicesStub
|
||||||
|
import com.example.what_the_fantasy.ui.states.SignInUserState
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
|
class SignInUserViewModel: ViewModel() {
|
||||||
|
private val services = ServicesStub() // faire repository qui gère les services Stub et API
|
||||||
|
private val _userState = MutableStateFlow(SignInUserState())
|
||||||
|
val userState : StateFlow<SignInUserState> = _userState.asStateFlow()
|
||||||
|
|
||||||
|
fun createUser(username: String, email: String, passwd: String) : Boolean{
|
||||||
|
return services.CreateUser(username, email, passwd)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUsername(username : String){
|
||||||
|
_userState.update { it.copy(username=username) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setEmail(email : String){
|
||||||
|
_userState.update { it.copy(email=email) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setPassword(password : String){
|
||||||
|
_userState.update { it.copy(password=password) }
|
||||||
|
}
|
||||||
|
fun setConfirmPassword(confirmPassword : String){
|
||||||
|
_userState.update { it.copy(confirmPassword=confirmPassword) }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,30 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="85.84757"
|
|
||||||
android:endY="92.4963"
|
|
||||||
android:startX="42.9492"
|
|
||||||
android:startY="49.59793"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#44000000"
|
|
||||||
android:offset="0.0" />
|
|
||||||
<item
|
|
||||||
android:color="#00000000"
|
|
||||||
android:offset="1.0" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:fillType="nonZero"
|
|
||||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
|
||||||
android:strokeWidth="1"
|
|
||||||
android:strokeColor="#00000000" />
|
|
||||||
</vector>
|
|
@ -0,0 +1,21 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="202dp"
|
||||||
|
android:height="202dp"
|
||||||
|
android:viewportWidth="202"
|
||||||
|
android:viewportHeight="202">
|
||||||
|
<path
|
||||||
|
android:pathData="M30,0L172,0A26,26 0,0 1,198 26L198,168A26,26 0,0 1,172 194L30,194A26,26 0,0 1,4 168L4,26A26,26 0,0 1,30 0z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="198"
|
||||||
|
android:startY="194"
|
||||||
|
android:endX="-6.98"
|
||||||
|
android:endY="181.61"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0" android:color="#FF4A148C"/>
|
||||||
|
<item android:offset="1" android:color="#FF7B1FA2"/>
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
</vector>
|
@ -0,0 +1,12 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="32dp"
|
||||||
|
android:height="33dp"
|
||||||
|
android:viewportWidth="32"
|
||||||
|
android:viewportHeight="33">
|
||||||
|
<path
|
||||||
|
android:pathData="M16,3.628C24.322,-5.496 45.127,10.47 16,31C-13.127,10.472 7.679,-5.496 16,3.628Z"
|
||||||
|
android:strokeWidth="2"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:strokeColor="#ffffff"/>
|
||||||
|
</vector>
|
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="30dp"
|
||||||
|
android:height="30dp"
|
||||||
|
android:viewportWidth="30"
|
||||||
|
android:viewportHeight="30">
|
||||||
|
<path
|
||||||
|
android:pathData="M15,2.628C23.322,-6.496 44.127,9.47 15,30C-14.127,9.472 6.679,-6.496 15,2.628Z"
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:fillType="evenOdd"/>
|
||||||
|
</vector>
|
@ -0,0 +1,23 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="239dp"
|
||||||
|
android:height="143dp"
|
||||||
|
android:viewportWidth="239"
|
||||||
|
android:viewportHeight="143">
|
||||||
|
<path
|
||||||
|
android:pathData="M161.92,11.53C158.02,11.53 154.18,12.27 150.4,13.74C146.73,15.21 142.78,17.42 138.55,20.37C139.1,21.5 139.55,22.86 139.88,24.45C140.22,25.92 140.38,27.62 140.38,29.54C140.38,33.96 139.55,39.46 137.88,46.03C136.32,52.6 134.26,59.57 131.7,66.94C129.14,74.3 126.42,81.55 123.52,88.69C120.63,95.83 117.9,102.23 115.34,107.9H111V99.57C111.11,96.06 111.17,92.32 111.17,88.35C111.28,84.27 111.34,80.36 111.34,76.62C111.45,72.77 111.5,69.54 111.5,66.94C113.73,60.25 115.62,54.08 117.18,48.41C118.74,42.63 119.52,37.53 119.52,33.11C119.52,27.79 118.01,23.6 115.01,20.54C112.12,17.48 106.94,15.95 99.48,15.95C94.59,15.95 90.36,16.74 86.8,18.33C83.24,19.8 79.51,22.07 75.61,25.13C77.62,31.02 79.17,36.57 80.29,41.78C81.51,46.99 82.4,52.38 82.96,57.93C81.07,66.54 78.67,75.32 75.78,84.27C73,93.22 70.05,101.1 66.93,107.9H62.59C62.59,103.82 62.65,99.34 62.76,94.47C62.98,89.6 63.09,84.56 63.09,79.34C63.09,71.3 62.76,63.31 62.09,55.38C61.53,47.33 60.25,40.03 58.25,33.45C56.25,26.77 53.24,21.44 49.24,17.48C45.23,13.51 39.83,11.53 33.04,11.53C23.25,11.53 14.57,14.47 7,20.37C11.45,23.43 15.01,27.39 17.68,32.26C20.36,37.14 22.36,42.58 23.69,48.58C25.03,54.59 25.92,60.87 26.36,67.45C26.81,74.02 27.03,80.53 27.03,86.99C27.03,91.18 26.98,95.72 26.87,100.59V118.26C26.87,125.63 29.2,130.96 33.88,134.24C38.55,137.41 46.51,139 57.75,139C63.65,139 68.99,138.21 73.78,136.62C78.56,135.15 82.96,133.28 86.96,131.01C88.86,133.73 91.86,135.71 95.98,136.96C100.21,138.32 105.94,139 113.17,139C121.74,139 128.92,137.64 134.71,134.92C140.61,132.2 145.73,128.58 150.07,124.04L147.73,114.69C149.4,110.62 151.51,105.8 154.07,100.25C156.74,94.7 159.47,88.8 162.25,82.57C165.04,76.23 167.65,69.88 170.1,63.54C172.66,57.19 174.72,51.19 176.28,45.52M170.12,62.92C171.86,63.54 173.63,64.06 175.43,64.46C177.77,64.53 180.41,64.54 183.36,64.51C186.45,64.4 189.14,64.25 191.41,64.07C191.54,65.61 191.43,67.15 191.08,68.69C190.87,70.15 190.66,71.32 190.46,72.2C189.27,77.49 186.55,80.93 182.3,82.52C178.17,84.14 173.64,84.39 168.7,83.28C166.46,82.77 164.41,82.19 162.56,81.54M161.45,11.53C174.63,10.18 225.12,8.37 233.62,6C234.54,11.09 235,15.38 235,18.88C235,23.85 233.68,28.09 231.04,31.6C228.39,35.1 224.83,37.75 220.35,39.56C215.99,41.26 194.72,42.73 189.32,42.73C185.75,42.73 171.26,43.4 171.26,43.4"
|
||||||
|
android:strokeWidth="8"
|
||||||
|
android:fillColor="#00000000">
|
||||||
|
<aapt:attr name="android:strokeColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="235"
|
||||||
|
android:startY="139"
|
||||||
|
android:endX="-4.21"
|
||||||
|
android:endY="114.21"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0" android:color="#FF4A148C"/>
|
||||||
|
<item android:offset="1" android:color="#FF7B1FA2"/>
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
</vector>
|
@ -0,0 +1,49 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="227dp"
|
||||||
|
android:height="133dp"
|
||||||
|
android:viewportWidth="227"
|
||||||
|
android:viewportHeight="133">
|
||||||
|
<path
|
||||||
|
android:pathData="M50.53,133C39.34,133 31.41,131.41 26.76,128.24C22.11,124.96 19.78,119.63 19.78,112.26C19.78,105.24 19.78,99.35 19.78,94.59C19.89,89.72 19.94,85.18 19.94,80.99C19.94,74.53 19.72,68.02 19.28,61.45C18.84,54.87 17.95,48.59 16.62,42.58C15.29,36.58 13.3,31.14 10.64,26.26C7.98,21.39 4.43,17.43 0,14.37C7.53,8.47 16.18,5.53 25.93,5.53C32.69,5.53 38.06,7.51 42.05,11.48C46.04,15.44 49.03,20.77 51.03,27.45C53.02,34.03 54.29,41.33 54.85,49.38C55.51,57.31 55.85,65.3 55.85,73.34C55.85,78.56 55.73,83.6 55.51,88.47C55.4,93.34 55.35,97.82 55.35,101.9H59.67C62.77,95.1 65.71,87.22 68.48,78.27C71.36,69.32 73.74,60.54 75.62,51.93C75.07,46.38 74.18,40.99 72.96,35.78C71.86,30.57 70.31,25.02 68.31,19.13C72.19,16.07 75.9,13.8 79.45,12.33C82.99,10.74 87.2,9.95 92.08,9.95C99.5,9.95 104.65,11.48 107.54,14.54C110.53,17.6 112.02,21.79 112.02,27.11C112.02,31.53 111.25,36.63 109.7,42.41C108.14,48.08 106.26,54.25 104.04,60.94C104.04,63.54 103.99,66.77 103.88,70.62C103.88,74.36 103.82,78.27 103.71,82.35C103.71,86.32 103.66,90.06 103.55,93.57C103.55,97.08 103.55,99.86 103.55,101.9H107.87C110.42,96.23 113.13,89.83 116.01,82.69C118.89,75.55 121.61,68.3 124.16,60.94C126.71,53.57 128.76,46.6 130.31,40.03C131.97,33.46 132.8,27.96 132.8,23.54C132.8,21.62 132.63,19.92 132.3,18.45C131.97,16.86 131.52,15.5 130.97,14.37C135.18,11.42 139.12,9.21 142.77,7.74C146.54,6.27 150.36,5.53 154.24,5.53C160.33,5.53 164.6,7.34 167.04,10.97C169.59,14.48 170.86,19.07 170.86,24.73C170.86,28.93 170.09,33.86 168.53,39.52C166.98,45.19 164.93,51.19 162.38,57.54C159.95,63.88 157.34,70.23 154.57,76.57C151.8,82.8 149.09,88.7 146.43,94.25C143.88,99.8 141.77,104.62 140.11,108.69L142.44,118.04C138.12,122.58 133.02,126.2 127.15,128.92C121.39,131.64 114.24,133 105.71,133C98.5,133 92.8,132.32 88.59,130.96C84.49,129.71 81.5,127.73 79.61,125.01C75.62,127.28 71.25,129.15 66.48,130.62C61.72,132.21 56.4,133 50.53,133Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="227"
|
||||||
|
android:startY="133"
|
||||||
|
android:endX="-11.19"
|
||||||
|
android:endY="108.42"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0" android:color="#FF4A148C"/>
|
||||||
|
<item android:offset="1" android:color="#FF7B1FA2"/>
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:pathData="M162.4,56.92C160.67,56.29 158.96,55.55 157.27,54.71L149.45,73.09C151.24,73.96 153.05,74.78 154.88,75.54C156.72,76.19 158.76,76.77 160.99,77.28C165.9,78.39 170.42,78.14 174.53,76.52C178.76,74.93 181.47,71.49 182.66,66.2C182.86,65.32 183.06,64.15 183.27,62.69C183.62,61.15 183.73,59.61 183.6,58.07C181.34,58.25 178.66,58.4 175.59,58.51C172.65,58.54 170.02,58.53 167.69,58.46C165.9,58.06 164.14,57.54 162.4,56.92Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="227"
|
||||||
|
android:startY="133"
|
||||||
|
android:endX="-11.19"
|
||||||
|
android:endY="108.42"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0" android:color="#FF4A148C"/>
|
||||||
|
<item android:offset="1" android:color="#FF7B1FA2"/>
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:pathData="M184.59,9.27C173.3,10.43 161.1,6.56 161.1,6.56V31.48C161.1,31.48 168.02,34.47 171.22,35.37C174.54,36.28 177.97,36.73 181.52,36.73C186.89,36.73 208.07,35.26 212.41,33.56C216.88,31.75 220.42,29.1 223.05,25.6C225.68,22.09 227,17.85 227,12.88C227,9.38 226.54,5.09 225.63,0C217.16,2.37 197.71,7.92 184.59,9.27Z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="227"
|
||||||
|
android:startY="133"
|
||||||
|
android:endX="-11.19"
|
||||||
|
android:endY="108.42"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0" android:color="#FF4A148C"/>
|
||||||
|
<item android:offset="1" android:color="#FF7B1FA2"/>
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
</vector>
|
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
</selector>
|
|
Before Width: | Height: | Size: 20 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="256dp"
|
||||||
|
android:height="256dp"
|
||||||
|
android:viewportWidth="256"
|
||||||
|
android:viewportHeight="256">
|
||||||
|
<path
|
||||||
|
android:pathData="M115.8,18C90.7,20.2 67,29.2 47.6,43.8c-4.7,3.6 -13.8,12.4 -17.5,17C7.9,88.2 3.8,123.2 19.2,154c4.9,9.8 9.9,16.6 19,26c9.9,10.3 9.8,9.8 10.1,32.1l0.2,17.3l1.2,2.1c2.8,4.7 6.9,7.1 12.1,7.1c2.3,0 3.9,-0.3 5.3,-1c1.2,-0.5 9.1,-5.4 17.7,-10.9c8.6,-5.5 16.7,-10.4 18.2,-10.9c5.1,-1.9 8.2,-2.2 20.1,-2c12.5,0.3 20,-0.2 29.8,-2c12.8,-2.3 24,-6 35.5,-11.8c42.5,-21.2 64.2,-60.6 55.8,-101.5c-6,-29.3 -29.2,-55.7 -61.4,-69.7C162.2,19.8 138.5,16 115.8,18zM145.3,32.4c14.3,1.9 25.6,5.2 37.8,11.1c28.9,14 46.2,37.4 48.7,66.1c1.5,16.2 -2.8,33.1 -11.9,47.1c-13.1,20.1 -36.5,35 -63.8,40.6c-10.9,2.3 -13.4,2.5 -30.3,2.6c-17,0.1 -19.2,0.3 -25.8,2.4c-5.3,1.7 -7.1,2.7 -23.3,13l-14.5,9.3l-0.2,-15.6l-0.2,-15.5l-1.7,-4.8c-2.5,-7.1 -5.3,-11.3 -11.9,-18c-13.7,-13.9 -20.1,-25.2 -23.2,-41.2c-1.3,-6.8 -1.4,-19.4 -0.2,-26.4c4.6,-25.5 21.7,-46.8 48,-59.5c12.7,-6.1 25.8,-9.8 39.7,-11.2c2.8,-0.3 5.8,-0.6 6.7,-0.7C122.5,31.2 140.4,31.8 145.3,32.4z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</vector>
|
@ -0,0 +1,18 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="96dp"
|
||||||
|
android:height="96dp"
|
||||||
|
android:viewportWidth="96"
|
||||||
|
android:viewportHeight="96">
|
||||||
|
<path
|
||||||
|
android:pathData="M45.6,45.8c-38,38.1 -40.4,41 -35.2,42 1.3,0.3 5,-2.8 12.1,-9.8l10.2,-10.2 4.3,2.8c3.7,2.5 5.4,2.9 11,2.9 5.5,-0 7.3,-0.4 10.7,-2.7 6.3,-4.1 8.8,-9 8.8,-16.9 0,-5.5 -0.4,-7.2 -2.9,-10.9l-2.8,-4.3 4.4,-4.3 4.3,-4.4 4.6,3.8c6.1,5 10.6,10.9 13.5,17.9 1.9,4.7 2.7,5.8 4.6,5.8 2,-0 2.3,-0.5 2.1,-3.3 -0.2,-5.8 -5.2,-14.3 -12.8,-21.8l-7.3,-7.2 6.5,-6.3c4.3,-4.3 6.3,-7.1 6.1,-8.4 -0.8,-5.5 -4,-2.9 -42.2,35.3zM60,47.2c7.6,12.4 -9,27.1 -20.1,17.9l-2.4,-2 2.6,-2.6c2.3,-2.3 2.8,-2.5 5.2,-1.4 5.4,2.5 10.5,-2.9 7.7,-8.1 -1,-1.8 -0.8,-2.6 1.1,-4.6 2.9,-3.1 3.5,-3 5.9,0.8z"
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:strokeColor="#00000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M36,19.6c-9.3,2.5 -16.2,6.4 -23.1,13.3 -10.1,10.2 -15.8,24.1 -10.1,24.9 1.4,0.2 2.4,-0.3 2.8,-1.5 7.1,-21 25.4,-33.7 46,-31.9 6.6,0.5 7.3,0.4 9.3,-1.8l2.3,-2.4 -5.2,-1.1c-6.8,-1.5 -15.3,-1.3 -22,0.5z"
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:strokeColor="#00000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M41.2,35.1c-6.6,1.9 -14.3,12.8 -13,18.4 0.2,0.7 4.9,-3.3 10.7,-9.1 10.8,-10.9 11,-11.8 2.3,-9.3z"
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:strokeColor="#00000000"/>
|
||||||
|
</vector>
|
@ -0,0 +1,14 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="96dp"
|
||||||
|
android:height="96dp"
|
||||||
|
android:viewportWidth="96"
|
||||||
|
android:viewportHeight="96">
|
||||||
|
<path
|
||||||
|
android:pathData="M36,19.6c-9.3,2.5 -16.2,6.4 -23.1,13.3 -10.1,10.2 -15.8,24.1 -10.1,24.9 1.4,0.2 2.4,-0.3 2.8,-1.5 2.4,-7.2 6.8,-14.6 11.2,-19 22.4,-22.4 59.9,-14.8 71.8,14.6 1.9,4.5 2.7,5.6 4.6,5.6 5.9,-0 -0.1,-14.5 -10.1,-24.5 -12.9,-12.7 -30.6,-17.8 -47.1,-13.4z"
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:strokeColor="#00000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M40.5,35.9c-12.5,5.8 -15.5,20.7 -6.1,30.9 11.1,12.2 32.6,3.5 32.6,-13.2 0,-2.5 -0.5,-5.7 -1.1,-7.3 -2.4,-6.4 -10.9,-12.3 -17.9,-12.3 -1.9,-0 -5.3,0.9 -7.5,1.9zM53.5,41.4c10.4,4.4 9.8,20 -1,24.1 -4.5,1.8 -8.8,1.2 -12.5,-1.8 -7.5,-5.8 -6.2,-18.6 2.3,-22.2 4.1,-1.8 6.9,-1.8 11.2,-0.1z"
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:strokeColor="#00000000"/>
|
||||||
|
</vector>
|
Before Width: | Height: | Size: 16 KiB |
@ -0,0 +1,11 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="22dp"
|
||||||
|
android:height="32dp"
|
||||||
|
android:viewportWidth="22"
|
||||||
|
android:viewportHeight="32">
|
||||||
|
<path
|
||||||
|
android:pathData="M14.086,20.901C12.995,20.24 12.641,20.24 9.633,20.901C9.85,19.378 9.633,17.655 9.633,16.564C9.633,15.071 10.297,14.441 11.234,13.46C12.172,12.48 12.641,11.463 12.641,10.41C12.641,9.65 12.419,8.964 11.977,8.351C11.534,7.739 10.753,7.432 9.633,7.432C8.721,7.432 7.823,7.739 6.938,8.351C6.078,8.964 5.362,10.103 4.789,11.77C3.513,11.647 2.563,11.206 1.938,10.446C1.313,9.687 1,8.817 1,7.837C1,6.783 1.339,5.729 2.016,4.676C2.719,3.622 3.773,2.752 5.18,2.066C6.612,1.355 8.396,1 10.531,1C13.083,1 15.115,1.404 16.625,2.213C18.162,3.022 19.268,4.063 19.945,5.337C20.648,6.611 21,7.935 21,9.307C21,10.851 20.74,12.272 20.219,13.571C19.724,14.845 19.034,15.948 18.148,16.879C17.289,17.81 16.326,18.533 15.258,19.047C14.19,19.562 14.713,20.462 14.086,20.901ZM10.705,31C9.507,31 8.504,30.632 7.697,29.897C6.915,29.138 6.525,28.219 6.525,27.141C6.525,26.307 6.746,25.548 7.189,24.862C7.632,24.151 8.218,23.575 8.947,23.134C9.702,22.693 10.535,22.472 11.447,22.472C12.645,22.472 13.634,22.852 14.415,23.612C15.223,24.347 15.626,25.254 15.626,26.332C15.626,27.141 15.405,27.9 14.962,28.611C14.52,29.322 13.921,29.897 13.165,30.338C12.436,30.779 11.616,31 10.705,31Z"
|
||||||
|
android:strokeWidth="2"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#ffffff"/>
|
||||||
|
</vector>
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="20dp"
|
||||||
|
android:height="30dp"
|
||||||
|
android:viewportWidth="20"
|
||||||
|
android:viewportHeight="30">
|
||||||
|
<path
|
||||||
|
android:pathData="M13.086,19.901C11.995,19.24 11.641,19.24 8.633,19.901C8.85,18.378 8.633,16.655 8.633,15.564C8.633,14.071 9.297,13.441 10.234,12.46C11.172,11.48 11.641,10.463 11.641,9.41C11.641,8.65 11.419,7.964 10.977,7.351C10.534,6.739 9.753,6.432 8.633,6.432C7.721,6.432 6.823,6.739 5.938,7.351C5.078,7.964 4.362,9.103 3.789,10.77C2.513,10.647 1.563,10.206 0.938,9.446C0.313,8.687 0,7.817 0,6.837C0,5.783 0.339,4.729 1.016,3.676C1.719,2.622 2.773,1.752 4.18,1.066C5.612,0.355 7.396,0 9.531,0C12.083,0 14.115,0.404 15.625,1.213C17.162,2.022 18.268,3.063 18.945,4.337C19.648,5.611 20,6.935 20,8.307C20,9.851 19.74,11.272 19.219,12.571C18.724,13.845 18.034,14.948 17.148,15.879C16.289,16.81 15.325,17.533 14.258,18.047C13.19,18.562 13.713,19.462 13.086,19.901ZM9.705,30C8.507,30 7.504,29.632 6.697,28.897C5.915,28.138 5.525,27.219 5.525,26.141C5.525,25.307 5.746,24.548 6.189,23.862C6.632,23.151 7.218,22.575 7.947,22.134C8.702,21.693 9.535,21.472 10.447,21.472C11.645,21.472 12.634,21.852 13.415,22.612C14.223,23.347 14.626,24.254 14.626,25.332C14.626,26.141 14.405,26.9 13.962,27.611C13.52,28.322 12.921,28.897 12.165,29.338C11.436,29.779 10.616,30 9.705,30Z"
|
||||||
|
android:fillColor="#ffffff"/>
|
||||||
|
</vector>
|
Before Width: | Height: | Size: 11 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="256dp"
|
||||||
|
android:height="256dp"
|
||||||
|
android:viewportWidth="256"
|
||||||
|
android:viewportHeight="256">
|
||||||
|
<path
|
||||||
|
android:pathData="M96.1,10.5c-18.4,1.9 -36,9.2 -50.7,21.1c-4.1,3.3 -12.3,11.7 -15.2,15.5c-3.9,5 -7.8,11.4 -10.4,16.6C3.7,96.9 7.6,135 30.2,164.6c2.9,3.9 11.2,12.3 15.2,15.5c34.5,27.8 82.4,28.8 117.6,2.4l5.2,-3.9l33.4,33.4c36.3,36.2 34.3,34.5 38.6,33.7c2.2,-0.4 5.1,-3.4 5.5,-5.5c0.8,-4.2 2.4,-2.3 -33.7,-38.6l-33.4,-33.4l3.9,-5.2c26.4,-35.2 25.4,-83.2 -2.4,-117.6c-3.3,-4.1 -11.7,-12.3 -15.5,-15.2C144.7,15 120.4,8 96.1,10.5zM116,25.4c9.6,1.2 17.5,3.6 25.9,7.9c40,20 56.4,68.8 36.5,108.5c-14,27.7 -42,45.1 -72.6,45.1c-27,0 -52.4,-13.7 -67.6,-36.5C18.7,121.3 20.7,82 42.9,54.7c2.7,-3.3 9.4,-9.9 12.7,-12.5C72.2,28.9 95,22.6 116,25.4z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</vector>
|
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.1 KiB |