mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-08 12:42:44 -05:00
display list of seasons/episodes on tv series details page
This commit is contained in:
@@ -55,4 +55,7 @@ interface TvApi {
|
||||
@Query("session_id") sessionId: String
|
||||
): Response<StatusResponse>
|
||||
|
||||
@GET("tv/{id}/season/{season}")
|
||||
suspend fun getSeason(@Path("id") seriesId: Int, @Path("season") seasonNumber: Int): Response<Season>
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.model.ImageCollection
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.KeywordsResponse
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RatingBody
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.ReviewResponse
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Season
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.StatusResponse
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TvContentRatings
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.VideoResponse
|
||||
@@ -77,4 +78,8 @@ class TvService: KoinComponent, DetailService, HomePageService {
|
||||
return service.getKeywords(id)
|
||||
}
|
||||
|
||||
suspend fun getSeason(seriesId: Int, seasonId: Int): Response<Season> {
|
||||
return service.getSeason(seriesId, seasonId)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class Episode(
|
||||
@SerializedName("name")
|
||||
val name: String,
|
||||
@SerializedName("overview")
|
||||
val overview: String,
|
||||
@SerializedName("episode_number")
|
||||
val episodeNumber: Int,
|
||||
@SerializedName("season_number")
|
||||
val seasonNumber: Int,
|
||||
@SerializedName("still_path")
|
||||
val stillPath: String?,
|
||||
@SerializedName("air_date")
|
||||
val airDate: String?
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class Season(
|
||||
@SerializedName("name")
|
||||
val name: String,
|
||||
@SerializedName("episodes")
|
||||
val episodes: List<Episode>
|
||||
)
|
||||
@@ -1,40 +1,47 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import android.content.Context
|
||||
import android.media.MediaActionSound
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.animation.core.LinearOutSlowInEasing
|
||||
import androidx.compose.animation.core.LinearEasing
|
||||
import androidx.compose.animation.core.RepeatMode
|
||||
import androidx.compose.animation.core.infiniteRepeatable
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Movie
|
||||
import androidx.compose.material.icons.filled.Send
|
||||
import androidx.compose.material.icons.outlined.ExpandLess
|
||||
import androidx.compose.material.icons.outlined.ExpandMore
|
||||
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.draw.rotate
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavController
|
||||
import com.google.accompanist.flowlayout.FlowRow
|
||||
import coil.compose.AsyncImage
|
||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.pager.HorizontalPager
|
||||
import com.google.accompanist.pager.PagerState
|
||||
import com.google.accompanist.pager.rememberPagerState
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
@@ -49,6 +56,8 @@ import com.owenlejeune.tvtime.extensions.listItems
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.*
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.TabNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.Tabs
|
||||
import com.owenlejeune.tvtime.ui.theme.FavoriteSelected
|
||||
import com.owenlejeune.tvtime.ui.theme.RatingSelected
|
||||
import com.owenlejeune.tvtime.ui.theme.WatchlistSelected
|
||||
@@ -57,7 +66,6 @@ import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||
import kotlinx.coroutines.*
|
||||
import org.json.JSONObject
|
||||
import org.koin.java.KoinJavaComponent
|
||||
import org.koin.java.KoinJavaComponent.get
|
||||
import java.text.DecimalFormat
|
||||
|
||||
@@ -194,7 +202,7 @@ private fun MediaViewContent(
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
// modifier = Modifier.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
if (type == MediaViewType.MOVIE) {
|
||||
@@ -205,18 +213,55 @@ private fun MediaViewContent(
|
||||
|
||||
ActionsView(itemId = itemId, type = type, service = service)
|
||||
|
||||
OverviewCard(itemId = itemId, mediaItem = mediaItem, service = service)
|
||||
if (type == MediaViewType.MOVIE) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
) {
|
||||
MainContent(
|
||||
itemId = itemId,
|
||||
mediaItem = mediaItem,
|
||||
type = type,
|
||||
service = service,
|
||||
appNavController = appNavController,
|
||||
windowSize = windowSize
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val tabState = rememberPagerState()
|
||||
val tabs = listOf(DetailsTab, SeasonsTab)
|
||||
TvSeriesTabs(pagerState = tabState, tabs = tabs)
|
||||
HorizontalPager(
|
||||
count = tabs.size,
|
||||
state = tabState,
|
||||
userScrollEnabled = false
|
||||
) { page ->
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
) {
|
||||
when (tabs[page]) {
|
||||
is DetailsTab -> {
|
||||
MainContent(
|
||||
itemId = itemId,
|
||||
mediaItem = mediaItem,
|
||||
type = type,
|
||||
service = service,
|
||||
appNavController = appNavController,
|
||||
windowSize = windowSize
|
||||
)
|
||||
}
|
||||
|
||||
CastCard(itemId = itemId, service = service, appNavController = appNavController)
|
||||
|
||||
SimilarContentCard(itemId = itemId, service = service, mediaType = type, appNavController = appNavController)
|
||||
|
||||
VideosCard(itemId = itemId, service = service)
|
||||
|
||||
AdditionalDetailsCard(itemId = itemId, mediaItem = mediaItem, service = service, type = type)
|
||||
|
||||
if (windowSize != WindowSizeClass.Expanded) {
|
||||
ReviewsCard(itemId = itemId, service = service)
|
||||
is SeasonsTab -> {
|
||||
SeasonsTab(
|
||||
itemId = itemId,
|
||||
mediaItem = mediaItem,
|
||||
service = service as TvService
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,6 +283,173 @@ private fun MediaViewContent(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
@Composable
|
||||
private fun TvSeriesTabs(
|
||||
pagerState: PagerState,
|
||||
tabs: List<TabNavItem>
|
||||
) {
|
||||
Tabs(
|
||||
modifier = Modifier.offset(y = (-16).dp),
|
||||
pagerState = pagerState,
|
||||
tabs = tabs
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SeasonsTab(
|
||||
itemId: Int?,
|
||||
mediaItem: MutableState<DetailedItem?>,
|
||||
service: TvService
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
mediaItem.value?.let { tv ->
|
||||
val series = tv as DetailedTv
|
||||
|
||||
val seasons = remember { mutableStateMapOf<Int, Season>() }
|
||||
LaunchedEffect(Unit) {
|
||||
itemId?.let {
|
||||
for (i in 0..series.numberOfSeasons) {
|
||||
scope.launch {
|
||||
val season = service.getSeason(it, i)
|
||||
if (season.isSuccessful) {
|
||||
seasons[i] = season.body()!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
seasons.toSortedMap().values.forEach { season ->
|
||||
SeasonSection(season = season)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SeasonSection(season: Season) {
|
||||
var isExpanded by remember { mutableStateOf(false) }
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.background(color = MaterialTheme.colorScheme.surfaceVariant)
|
||||
.clickable {
|
||||
isExpanded = !isExpanded
|
||||
}
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.padding(horizontal = 24.dp, vertical = 24.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = season.name,
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
var currentRotation by remember { mutableStateOf(0f) }
|
||||
val rotation = remember { androidx.compose.animation.core.Animatable(currentRotation) }
|
||||
LaunchedEffect(isExpanded) {
|
||||
rotation.animateTo(
|
||||
targetValue = if (isExpanded) 180f else 0f,
|
||||
animationSpec = tween(200, easing = LinearEasing)
|
||||
) {
|
||||
currentRotation = value
|
||||
}
|
||||
}
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.ExpandMore,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
.rotate(currentRotation),
|
||||
tint = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = isExpanded,
|
||||
enter = expandVertically(),
|
||||
exit = shrinkVertically()
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
season.episodes.forEachIndexed { index, episode ->
|
||||
EpisodeItem(episode = episode)
|
||||
if (index != season.episodes.size - 1) {
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EpisodeItem(episode: Episode) {
|
||||
val height = 170.dp
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
modifier = Modifier.height(height)
|
||||
) {
|
||||
AsyncImage(
|
||||
model = TmdbUtils.getFullEpisodeStillPath(episode),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(width = 100.dp, height = height)
|
||||
.clip(RoundedCornerShape(10.dp)),
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "S${episode.seasonNumber}E${episode.episodeNumber} • ${episode.name}",
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
TmdbUtils.convertEpisodeDate(episode.airDate)?.let {
|
||||
Text(
|
||||
text = it,
|
||||
fontStyle = FontStyle.Italic,
|
||||
fontSize = 12.sp
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = episode.overview,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainContent(
|
||||
itemId: Int?,
|
||||
mediaItem: MutableState<DetailedItem?>,
|
||||
type: MediaViewType,
|
||||
service: DetailService,
|
||||
appNavController: NavController,
|
||||
windowSize: WindowSizeClass
|
||||
) {
|
||||
OverviewCard(itemId = itemId, mediaItem = mediaItem, service = service)
|
||||
|
||||
CastCard(itemId = itemId, service = service, appNavController = appNavController)
|
||||
|
||||
SimilarContentCard(itemId = itemId, service = service, mediaType = type, appNavController = appNavController)
|
||||
|
||||
VideosCard(itemId = itemId, service = service, modifier = Modifier.fillMaxWidth())
|
||||
|
||||
AdditionalDetailsCard(itemId = itemId, mediaItem = mediaItem, service = service, type = type)
|
||||
|
||||
if (windowSize != WindowSizeClass.Expanded) {
|
||||
ReviewsCard(itemId = itemId, service = service)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MiscTvDetails(mediaItem: MutableState<DetailedItem?>, service: TvService) {
|
||||
mediaItem.value?.let { tv ->
|
||||
@@ -249,7 +461,8 @@ private fun MiscTvDetails(mediaItem: MutableState<DetailedItem?>, service: TvSer
|
||||
MiscDetails(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight(),
|
||||
.wrapContentHeight()
|
||||
.padding(horizontal = 16.dp),
|
||||
year = TmdbUtils.getSeriesRun(series),
|
||||
runtime = TmdbUtils.convertRuntimeToHoursMinutes(series),
|
||||
genres = series.genres,
|
||||
@@ -269,7 +482,8 @@ private fun MiscMovieDetails(mediaItem: MutableState<DetailedItem?>, service: Mo
|
||||
MiscDetails(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight(),
|
||||
.wrapContentHeight()
|
||||
.padding(horizontal = 16.dp),
|
||||
year = TmdbUtils.getMovieReleaseYear(movie),
|
||||
runtime = TmdbUtils.convertRuntimeToHoursMinutes(movie),
|
||||
genres = movie.genres,
|
||||
@@ -328,7 +542,8 @@ private fun ActionsView(
|
||||
val session = SessionManager.currentSession.value
|
||||
Row(
|
||||
modifier = modifier
|
||||
.wrapContentSize(),
|
||||
.wrapContentSize()
|
||||
.padding(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
RateButton(
|
||||
@@ -985,7 +1200,11 @@ fun SimilarContentCard(
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun VideosCard(itemId: Int?, service: DetailService, modifier: Modifier = Modifier) {
|
||||
fun VideosCard(
|
||||
itemId: Int?,
|
||||
service: DetailService,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val videoResponse = remember { mutableStateOf<VideoResponse?>(null) }
|
||||
itemId?.let {
|
||||
if (videoResponse.value == null) {
|
||||
@@ -1373,4 +1592,13 @@ private fun addToFavorite(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DetailsTab: TabNavItem("details_route") {
|
||||
override val name: String
|
||||
get() = "Details"
|
||||
}
|
||||
object SeasonsTab: TabNavItem("seasons_route") {
|
||||
override val name: String
|
||||
get() = "Seasons"
|
||||
}
|
||||
@@ -75,9 +75,9 @@ sealed class OnboardingPage(
|
||||
.padding(all = 24.dp)
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.tmdb_logo),
|
||||
painter = painterResource(id = R.drawable.tmdb_logo_long),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(32.dp),
|
||||
modifier = Modifier.height(height = 16.dp),
|
||||
tint = Color.Unspecified
|
||||
)
|
||||
Text(
|
||||
|
||||
@@ -11,6 +11,7 @@ object TmdbUtils {
|
||||
private const val PERSON_BASE = "https://www.themoviedb.org/t/p/w600_and_h900_bestv2"
|
||||
private const val GRAVATAR_BASE = "https://www.gravatar.com/avatar/"
|
||||
private const val AVATAR_BASE = "https://www.themoviedb.org/t/p/w150_and_h150_face"
|
||||
private const val STILL_BASE = "https://www.themoviedb.org/t/p/w454_and_h254_bestv2/"
|
||||
|
||||
private const val DEF_REGION = "US"
|
||||
|
||||
@@ -63,6 +64,16 @@ object TmdbUtils {
|
||||
return getFullAvatarPath(author.avatarPath)
|
||||
}
|
||||
|
||||
fun getFullEpisodeStillPath(path: String?): String? {
|
||||
return path?.let {
|
||||
"${STILL_BASE}${path}"
|
||||
}
|
||||
}
|
||||
|
||||
fun getFullEpisodeStillPath(episode: Episode): String? {
|
||||
return getFullEpisodeStillPath(episode.stillPath)
|
||||
}
|
||||
|
||||
fun getMovieReleaseYear(movie: DetailedMovie): String {
|
||||
return movie.releaseDate.split("-")[0]
|
||||
}
|
||||
@@ -208,4 +219,15 @@ object TmdbUtils {
|
||||
return "$${thousands}"
|
||||
}
|
||||
|
||||
fun convertEpisodeDate(inDate: String?): String? {
|
||||
if (inDate == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val origFormat = SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault())
|
||||
val outFormat = SimpleDateFormat("MMMM dd, yyyy", java.util.Locale.getDefault())
|
||||
|
||||
return origFormat.parse(inDate)?.let { outFormat.format(it) }
|
||||
}
|
||||
|
||||
}
|
||||
22
app/src/main/res/drawable/tmdb_logo_long.xml
Normal file
22
app/src/main/res/drawable/tmdb_logo_long.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="489.04dp"
|
||||
android:height="35.4dp"
|
||||
android:viewportWidth="489.04"
|
||||
android:viewportHeight="35.4">
|
||||
<path
|
||||
android:pathData="M293.5,0h8.9l8.75,23.2h0.1L320.15,0h8.35L313.9,35.4h-6.25ZM340.1,0h7.8L347.9,35.4h-7.8ZM362.3,0h24.05L386.35,7.2L370.1,7.2v6.6h15.35L385.45,21L370.1,21v7.2h17.15v7.2L362.3,35.4ZM417.3,0L429,0a33.54,33.54 0,0 1,8.07 1A18.55,18.55 0,0 1,443.75 4a15.1,15.1 0,0 1,4.52 5.53A18.5,18.5 0,0 1,450 17.8a16.91,16.91 0,0 1,-1.63 7.58,16.37 16.37,0 0,1 -4.37,5.5 19.52,19.52 0,0 1,-6.35 3.37A24.59,24.59 0,0 1,430 35.4L417.29,35.4ZM425.11,28.2h4a21.57,21.57 0,0 0,5 -0.55,10.87 10.87,0 0,0 4,-1.83 8.69,8.69 0,0 0,2.67 -3.34,11.92 11.92,0 0,0 1,-5.08 9.87,9.87 0,0 0,-1 -4.52,9 9,0 0,0 -2.62,-3.18 11.68,11.68 0,0 0,-3.88 -1.88,17.43 17.43,0 0,0 -4.67,-0.62h-4.6ZM461.24,0h13.2a34.42,34.42 0,0 1,4.63 0.32,12.9 12.9,0 0,1 4.17,1.3 7.88,7.88 0,0 1,3 2.73A8.34,8.34 0,0 1,487.39 9a7.42,7.42 0,0 1,-1.67 5,9.28 9.28,0 0,1 -4.43,2.82v0.1a10,10 0,0 1,3.18 1,8.38 8.38,0 0,1 2.45,1.85 7.79,7.79 0,0 1,1.57 2.62,9.16 9.16,0 0,1 0.55,3.2 8.52,8.52 0,0 1,-1.2 4.68,9.42 9.42,0 0,1 -3.1,3 13.38,13.38 0,0 1,-4.27 1.65,23.11 23.11,0 0,1 -4.73,0.5h-14.5ZM469,14.15h5.65a8.16,8.16 0,0 0,1.78 -0.2A4.78,4.78 0,0 0,478 13.3a3.34,3.34 0,0 0,1.13 -1.2,3.63 3.63,0 0,0 0.42,-1.8 3.22,3.22 0,0 0,-0.47 -1.82,3.33 3.33,0 0,0 -1.23,-1.13 5.77,5.77 0,0 0,-1.7 -0.58,10.79 10.79,0 0,0 -1.85,-0.17L469,6.6ZM469,28.8h7a8.91,8.91 0,0 0,1.83 -0.2,4.78 4.78,0 0,0 1.67,-0.7 4,4 0,0 0,1.23 -1.3,3.71 3.71,0 0,0 0.47,-2 3.13,3.13 0,0 0,-0.62 -2A4,4 0,0 0,479 21.45,7.83 7.83,0 0,0 477,20.9a15.12,15.12 0,0 0,-2.05 -0.15L469,20.75ZM204,35.33L271,35.33a17.66,17.66 0,0 0,17.66 -17.66h0A17.67,17.67 0,0 0,271 0L204.06,0A17.67,17.67 0,0 0,186.4 17.67h0A17.66,17.66 0,0 0,204.06 35.33ZM10.1,6.9L0,6.9L0,0L28,0L28,6.9L17.9,6.9L17.9,35.4L10.1,35.4ZM39,0h7.8L46.8,13.2L61.9,13.2L61.9,0h7.8L69.7,35.4L61.9,35.4L61.9,20.1L46.75,20.1L46.75,35.4L39,35.4ZM80.2,0h24L104.2,7.2L88,7.2v6.6h15.35L103.35,21L88,21v7.2h17.15v7.2h-25ZM135.2,0L147,0l8.15,23.1h0.1L163.45,0L175.2,0L175.2,35.4h-7.8L167.4,8.25h-0.1L158,35.4h-5.95l-9,-27.15L143,8.25L143,35.4h-7.8Z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="0"
|
||||
android:startY="17.7"
|
||||
android:endX="489.04"
|
||||
android:endY="17.7"
|
||||
android:type="linear">
|
||||
<item android:offset="0" android:color="#FF90CEA1"/>
|
||||
<item android:offset="0.56" android:color="#FF3CBEC9"/>
|
||||
<item android:offset="1" android:color="#FF00B3E5"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</vector>
|
||||
Reference in New Issue
Block a user