add Game of Thrones quotes

This commit is contained in:
Owen LeJeune
2023-08-02 15:05:14 -04:00
parent 6fe0b9f1dd
commit abd6e4ddee
34 changed files with 291 additions and 48 deletions

View File

@@ -1,4 +1,4 @@
package com.owenlejeune.tvtime.api
package com.owenlejeune.tvtime.api.common
import okhttp3.Interceptor
import org.koin.core.component.KoinComponent

View File

@@ -1,4 +1,4 @@
package com.owenlejeune.tvtime.api
package com.owenlejeune.tvtime.api.common
import retrofit2.Converter

View File

@@ -1,4 +1,4 @@
package com.owenlejeune.tvtime.api
package com.owenlejeune.tvtime.api.common
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader

View File

@@ -1,4 +1,4 @@
package com.owenlejeune.tvtime.api
package com.owenlejeune.tvtime.api.common
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor

View File

@@ -1,8 +1,6 @@
package com.owenlejeune.tvtime.api
package com.owenlejeune.tvtime.api.common
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializer
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import retrofit2.Converter

View File

@@ -1,4 +1,4 @@
package com.owenlejeune.tvtime.api
package com.owenlejeune.tvtime.api.common
import okhttp3.OkHttpClient

View File

@@ -1,4 +1,4 @@
package com.owenlejeune.tvtime.api
package com.owenlejeune.tvtime.api.common
enum class LoadingState {

View File

@@ -1,4 +1,4 @@
package com.owenlejeune.tvtime.api
package com.owenlejeune.tvtime.api.common
import okhttp3.OkHttpClient

View File

@@ -1,4 +1,4 @@
package com.owenlejeune.tvtime.api
package com.owenlejeune.tvtime.api.common
class QueryParam(val key: String, val param: String) {

View File

@@ -1,7 +1,6 @@
package com.owenlejeune.tvtime.api
package com.owenlejeune.tvtime.api.common
import androidx.compose.runtime.MutableState
import kotlinx.coroutines.delay
import retrofit2.Response
infix fun <T> Response<T>.storedIn(body: (T) -> Unit) {

View File

@@ -0,0 +1,12 @@
package com.owenlejeune.tvtime.api.gotquotes
import com.owenlejeune.tvtime.api.gotquotes.model.GotQuote
import retrofit2.Response
import retrofit2.http.GET
interface GotQuotesApi {
@GET("random/5")
suspend fun getRandomQuotes(): Response<List<GotQuote>>
}

View File

@@ -0,0 +1,20 @@
package com.owenlejeune.tvtime.api.gotquotes
import com.owenlejeune.tvtime.api.common.Client
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.parameter.parametersOf
class GotQuotesClient: KoinComponent {
companion object {
private const val BASE_URL = "https://api.gameofthronesquotes.xyz/v1/"
}
private val client: Client by inject { parametersOf(BASE_URL) }
fun createQuotesApi(): GotQuotesApi {
return client.create(GotQuotesApi::class.java)
}
}

View File

@@ -0,0 +1,24 @@
package com.owenlejeune.tvtime.api.gotquotes
import androidx.compose.runtime.mutableStateListOf
import com.owenlejeune.tvtime.api.gotquotes.model.GotQuote
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class GotQuotesService: KoinComponent {
private val api: GotQuotesApi by inject()
val quotes = mutableStateListOf<GotQuote>()
suspend fun getRandomQuotes() {
quotes.clear()
val response = api.getRandomQuotes()
if (response.isSuccessful) {
response.body()?.let {
quotes.addAll(it)
}
}
}
}

View File

@@ -0,0 +1,19 @@
package com.owenlejeune.tvtime.api.gotquotes.model
import com.google.gson.annotations.SerializedName
class GotQuote(
@SerializedName("sentence") val quote: String,
@SerializedName("character") val character: GotCharacter
)
class GotCharacter(
@SerializedName("name") val name: String,
@SerializedName("slug") val slug: String,
@SerializedName("house") val house: GotHouse
)
class GotHouse(
@SerializedName("name") val name: String,
@SerializedName("slug") val slug: String
)

View File

@@ -1,6 +1,6 @@
package com.owenlejeune.tvtime.api.nextmcu
import com.owenlejeune.tvtime.api.Client
import com.owenlejeune.tvtime.api.common.Client
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.parameter.parametersOf

View File

@@ -1,7 +1,7 @@
package com.owenlejeune.tvtime.api.nextmcu
import androidx.compose.runtime.mutableStateOf
import com.owenlejeune.tvtime.api.LoadingState
import com.owenlejeune.tvtime.api.common.LoadingState
import com.owenlejeune.tvtime.api.nextmcu.model.NextMCU
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

View File

@@ -2,10 +2,9 @@ package com.owenlejeune.tvtime.api.tmdb
import android.annotation.SuppressLint
import androidx.compose.ui.text.intl.Locale
import androidx.lifecycle.viewmodel.viewModelFactory
import com.owenlejeune.tvtime.BuildConfig
import com.owenlejeune.tvtime.api.Client
import com.owenlejeune.tvtime.api.QueryParam
import com.owenlejeune.tvtime.api.common.Client
import com.owenlejeune.tvtime.api.common.QueryParam
import com.owenlejeune.tvtime.api.tmdb.api.v3.AccountApi
import com.owenlejeune.tvtime.api.tmdb.api.v3.AuthenticationApi
import com.owenlejeune.tvtime.api.tmdb.api.v3.ConfigurationApi
@@ -18,7 +17,6 @@ import com.owenlejeune.tvtime.api.tmdb.api.v4.AccountV4Api
import com.owenlejeune.tvtime.api.tmdb.api.v4.AuthenticationV4Api
import com.owenlejeune.tvtime.api.tmdb.api.v4.ListV4Api
import com.owenlejeune.tvtime.extensions.addQueryParams
import com.owenlejeune.tvtime.preferences.AppPreferences
import com.owenlejeune.tvtime.ui.viewmodel.ConfigurationViewModel
import com.owenlejeune.tvtime.utils.SessionManager
import okhttp3.Interceptor

View File

@@ -4,8 +4,8 @@ import android.util.Log
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.paging.PagingData
import com.owenlejeune.tvtime.api.LoadingState
import com.owenlejeune.tvtime.api.loadRemoteData
import com.owenlejeune.tvtime.api.common.LoadingState
import com.owenlejeune.tvtime.api.common.loadRemoteData
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.AccountStates
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CastMember
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CrewMember

View File

@@ -2,8 +2,8 @@ package com.owenlejeune.tvtime.api.tmdb.api.v3
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import com.owenlejeune.tvtime.api.LoadingState
import com.owenlejeune.tvtime.api.loadRemoteData
import com.owenlejeune.tvtime.api.common.LoadingState
import com.owenlejeune.tvtime.api.common.loadRemoteData
import com.owenlejeune.tvtime.api.tmdb.TmdbClient
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.DetailCast
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.DetailCrew

View File

@@ -4,8 +4,8 @@ import android.util.Log
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.paging.PagingData
import com.owenlejeune.tvtime.api.LoadingState
import com.owenlejeune.tvtime.api.loadRemoteData
import com.owenlejeune.tvtime.api.common.LoadingState
import com.owenlejeune.tvtime.api.common.loadRemoteData
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.AccountStates
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CastMember
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CrewMember

View File

@@ -2,7 +2,14 @@ package com.owenlejeune.tvtime.di.modules
import com.google.gson.GsonBuilder
import com.owenlejeune.tvtime.BuildConfig
import com.owenlejeune.tvtime.api.*
import com.owenlejeune.tvtime.api.common.Client
import com.owenlejeune.tvtime.api.common.ConverterFactoryFactory
import com.owenlejeune.tvtime.api.common.DateTypeAdapter
import com.owenlejeune.tvtime.api.common.DebugHttpClient
import com.owenlejeune.tvtime.api.common.GsonConverter
import com.owenlejeune.tvtime.api.common.ProdHttpClient
import com.owenlejeune.tvtime.api.gotquotes.GotQuotesClient
import com.owenlejeune.tvtime.api.gotquotes.GotQuotesService
import com.owenlejeune.tvtime.api.nextmcu.NextMCUClient
import com.owenlejeune.tvtime.api.nextmcu.NextMCUService
import com.owenlejeune.tvtime.api.tmdb.TmdbClient
@@ -76,6 +83,10 @@ val networkModule = module {
single { get<NextMCUClient>().createNextMcuService() }
single { NextMCUService() }
single { GotQuotesClient() }
single { get<GotQuotesClient>().createQuotesApi() }
single { GotQuotesService() }
single<Map<Class<*>, Any>> {
mapOf(
ListItem::class.java to ListItemDeserializer(),

View File

@@ -1,8 +1,7 @@
package com.owenlejeune.tvtime.extensions
import com.owenlejeune.tvtime.api.QueryParam
import com.owenlejeune.tvtime.api.common.QueryParam
import okhttp3.HttpUrl
import okhttp3.Request
fun HttpUrl.Builder.addQueryParams(vararg queryParams: QueryParam?): HttpUrl.Builder {
return apply {

View File

@@ -39,6 +39,7 @@ class AppPreferences(context: Context) {
private val STORED_TEST_ROUTE = "stored_test_route"
private val FLOATING_BOTTOM_BAR = "floating_bottom_bar"
private val RECENT_SEARCHES = "recent_searches"
private val SHOW_GOT_QUOTES = "show_got_quotes"
}
private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE)
@@ -138,17 +139,22 @@ class AppPreferences(context: Context) {
get() = preferences.getBoolean(SHOW_BACKDROP_GALLERY, showBackdropGalleryDefault)
set(value) { preferences.put(SHOW_BACKDROP_GALLERY, value) }
/******** Special Features Preferences ********/
val showNextMcuProductionDefault: Boolean = false
var showNextMcuProduction: Boolean
get() = preferences.getBoolean(SHOW_NEXT_MCU, showNextMcuProductionDefault)
set(value) { preferences.put(SHOW_NEXT_MCU, value) }
val storedTestRouteDefault: String = ""
var storedTestRoute: String
get() = preferences.getString(STORED_TEST_ROUTE, storedTestRouteDefault) ?: storedTestRouteDefault
set(value) { preferences.put(STORED_TEST_ROUTE, value) }
/******** Special Features Preferences ********/
val showNextMcuProductionDefault: Boolean = true
var showNextMcuProduction: Boolean
get() = preferences.getBoolean(SHOW_NEXT_MCU, showNextMcuProductionDefault)
set(value) { preferences.put(SHOW_NEXT_MCU, value) }
val showGotQuotesDefault: Boolean = true
var showGotQuotes: Boolean
get() = preferences.getBoolean(SHOW_GOT_QUOTES, showGotQuotesDefault)
set(value) { preferences.put(SHOW_GOT_QUOTES, value) }
/******** General Storage ********/
var recentSearches: MutableList<String>
get() = preferences.getStringSet(RECENT_SEARCHES, emptySet())?.toMutableList() ?: emptySet<String>().toMutableList()

View File

@@ -29,14 +29,10 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.owenlejeune.tvtime.api.LoadingState
import com.owenlejeune.tvtime.extensions.isIn
import com.owenlejeune.tvtime.extensions.shimmerBackground
import com.owenlejeune.tvtime.ui.theme.FavoriteSelected
import com.owenlejeune.tvtime.ui.theme.RatingSelected
import com.owenlejeune.tvtime.ui.theme.WatchlistSelected
import com.owenlejeune.tvtime.ui.viewmodel.AccountViewModel
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
import com.owenlejeune.tvtime.utils.types.MediaViewType
import kotlinx.coroutines.launch

View File

@@ -62,6 +62,28 @@ fun ContentCard(
}
}
@Composable
fun ContentCard(
modifier: Modifier = Modifier,
heading: (@Composable () -> Unit)? = null,
backgroundColor: Color = MaterialTheme.colorScheme.surfaceVariant,
content: @Composable () -> Unit = {}
) {
Card(
modifier = modifier
.fillMaxWidth()
.wrapContentHeight(),
shape = RoundedCornerShape(10.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 8.dp),
colors = CardDefaults.cardColors(containerColor = backgroundColor)
) {
Column(modifier = Modifier.fillMaxSize()) {
heading?.invoke()
content()
}
}
}
@Composable
fun ExpandableContentCard(
modifier: Modifier = Modifier,

View File

@@ -52,7 +52,7 @@ import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.PagerState
import com.google.accompanist.pager.rememberPagerState
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.api.LoadingState
import com.owenlejeune.tvtime.api.common.LoadingState
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Episode
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.EpisodeCastMember
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.EpisodeCrewMember

View File

@@ -37,7 +37,6 @@ import androidx.paging.compose.LazyPagingItems
import coil.compose.AsyncImage
import coil.request.CachePolicy
import coil.request.ImageRequest
import com.owenlejeune.tvtime.api.LoadingState
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePagePerson
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem
import com.owenlejeune.tvtime.extensions.header

View File

@@ -70,7 +70,7 @@ import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.PagerState
import com.google.accompanist.pager.rememberPagerState
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.api.LoadingState
import com.owenlejeune.tvtime.api.common.LoadingState
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.DetailedItem
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.DetailedMovie
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.DetailedTv
@@ -92,7 +92,6 @@ import com.owenlejeune.tvtime.ui.components.AdditionalDetailItem
import com.owenlejeune.tvtime.ui.components.AvatarImage
import com.owenlejeune.tvtime.ui.components.BackButton
import com.owenlejeune.tvtime.ui.components.CastCard
import com.owenlejeune.tvtime.ui.components.CastCrewCard
import com.owenlejeune.tvtime.ui.components.ChipDefaults
import com.owenlejeune.tvtime.ui.components.ChipGroup
import com.owenlejeune.tvtime.ui.components.ChipInfo
@@ -118,6 +117,7 @@ import com.owenlejeune.tvtime.ui.theme.Typography
import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
import com.owenlejeune.tvtime.ui.viewmodel.SpecialFeaturesViewModel
import com.owenlejeune.tvtime.ui.views.extras.SpecialFeaturesViews
import com.owenlejeune.tvtime.utils.SessionManager
import com.owenlejeune.tvtime.utils.TmdbUtils
import com.owenlejeune.tvtime.utils.types.MediaViewType
@@ -386,6 +386,8 @@ fun MediaViewContent(
NextMcuProjectCard(itemId = itemId, appNavController = appNavController)
}
SpecialFeaturesViews.viewsMap[itemId]?.invoke()
if (windowSize != WindowSizeClass.Expanded) {
ReviewsCard(itemId = itemId, type = type, mainViewModel = mainViewModel, windowSize = windowSize)
}

View File

@@ -458,6 +458,15 @@ fun SpecialFeaturePreferences() {
settingsViewModel.toggleShowNextMcuProduction()
}
)
SwitchPreference(
titleText = "Show Game of Thrones Quotes",
subtitleText = "Show random quotes from Game of Thrones on the show",
checkState = settingsViewModel.showGotQuotes.collectAsState(),
onCheckedChange = {
settingsViewModel.toggleShowGotQuotes()
}
)
}
}

View File

@@ -3,11 +3,10 @@ package com.owenlejeune.tvtime.ui.viewmodel
import android.annotation.SuppressLint
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.lifecycle.ViewModel
import androidx.paging.PagingData
import com.owenlejeune.tvtime.api.LoadingState
import com.owenlejeune.tvtime.api.common.LoadingState
import com.owenlejeune.tvtime.api.tmdb.api.createPagingFlow
import com.owenlejeune.tvtime.api.tmdb.api.v3.MoviesService
import com.owenlejeune.tvtime.api.tmdb.api.v3.PeopleService
@@ -16,7 +15,6 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.model.AccountStates
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CastMember
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CrewMember
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.DetailedItem
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Episode
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.ExternalIds
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.ImageCollection
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Keyword
@@ -31,7 +29,6 @@ import com.owenlejeune.tvtime.utils.types.MediaViewType
import com.owenlejeune.tvtime.utils.types.TimeWindow
import com.owenlejeune.tvtime.utils.types.ViewableMediaTypeException
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.cancellable
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

View File

@@ -20,11 +20,12 @@ class SettingsViewModel: ViewModel() {
private val _chromaMultiplier = MutableStateFlow(preferences.chromaMultiplier)
private val _selectedColor = MutableStateFlow(preferences.selectedColor)
private val _showBottomTabLabels = MutableStateFlow(preferences.showBottomTabLabels)
private val _showFloatingBottomBar = MutableStateFlow(preferences.floatingBottomBar)
private val _showPosterTitles = MutableStateFlow(preferences.showPosterTitles)
private val _firstLaunchTesting = MutableStateFlow(preferences.firstLaunchTesting)
private val _showBackdropGallery = MutableStateFlow(preferences.showBackdropGallery)
private val _showNextMcuProduction = MutableStateFlow(preferences.showNextMcuProduction)
private val _showFloatingBottomBar = MutableStateFlow(preferences.floatingBottomBar)
private val _showGotQuotes = MutableStateFlow(preferences.showGotQuotes)
}
val showSearchBar = _showSearchBar.asStateFlow()
@@ -34,12 +35,13 @@ class SettingsViewModel: ViewModel() {
val useSystemColors = _useSystemColors.asStateFlow()
val chromaMultiplier = _chromaMultiplier.asStateFlow()
val selectedColor = _selectedColor.asStateFlow()
val showFloatingBottomBar = _showFloatingBottomBar.asStateFlow()
val showBottomTabLabels = _showBottomTabLabels.asStateFlow()
val showPosterTitles = _showPosterTitles.asStateFlow()
val firstLaunchTesting = _firstLaunchTesting.asStateFlow()
val showBackdropGallery = _showBackdropGallery.asStateFlow()
val showNextMcuProduction = _showNextMcuProduction.asStateFlow()
val showFloatingBottomBar = _showFloatingBottomBar.asStateFlow()
val showGotQuotes = _showGotQuotes.asStateFlow()
fun toggleShowSearchBar() {
_showSearchBar.value = _showSearchBar.value.not()
@@ -156,4 +158,14 @@ class SettingsViewModel: ViewModel() {
preferences.floatingBottomBar = value
}
fun toggleShowGotQuotes() {
_showGotQuotes.value = _showGotQuotes.value.not()
preferences.showGotQuotes = _showGotQuotes.value
}
fun setShowGotQuotes(value: Boolean) {
_showGotQuotes.value = value
preferences.showGotQuotes = value
}
}

View File

@@ -1,6 +1,7 @@
package com.owenlejeune.tvtime.ui.viewmodel
import androidx.lifecycle.ViewModel
import com.owenlejeune.tvtime.api.gotquotes.GotQuotesService
import com.owenlejeune.tvtime.api.nextmcu.NextMCUService
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
@@ -8,8 +9,10 @@ import org.koin.core.component.inject
class SpecialFeaturesViewModel: ViewModel(), KoinComponent {
private val mcuService: NextMCUService by inject()
private val gotQuotesService: GotQuotesService by inject()
val nextMcuProject = mcuService.nextMcuProject
val gotQuotes = gotQuotesService.quotes
suspend fun getNextMcuProject(force: Boolean = false) {
if (nextMcuProject.value == null || force) {
@@ -17,4 +20,8 @@ class SpecialFeaturesViewModel: ViewModel(), KoinComponent {
}
}
suspend fun getGotQuotes() {
gotQuotesService.getRandomQuotes()
}
}

View File

@@ -0,0 +1,112 @@
package com.owenlejeune.tvtime.ui.views.extras
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Refresh
import androidx.compose.material3.Divider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.preferences.AppPreferences
import com.owenlejeune.tvtime.ui.components.ContentCard
import com.owenlejeune.tvtime.ui.viewmodel.SpecialFeaturesViewModel
import kotlinx.coroutines.launch
import org.koin.java.KoinJavaComponent.get
object SpecialFeaturesViews {
val viewsMap: Map<Int, @Composable () -> Unit> = mapOf(
206584 to { GotQuotesView() },
1399 to { GotQuotesView() }
)
}
@Composable
fun GotQuotesView(
appPreferences: AppPreferences = get(AppPreferences::class.java)
) {
if (appPreferences.showGotQuotes) {
val scope = rememberCoroutineScope()
val viewModel = viewModel<SpecialFeaturesViewModel>()
LaunchedEffect(Unit) {
viewModel.getGotQuotes()
}
val quotes = remember { viewModel.gotQuotes }
if (quotes.isNotEmpty()) {
ContentCard(
heading = {
Row(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)
) {
Text(
text = stringResource(R.string.quotes_title),
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.weight(1f))
IconButton(
modifier = Modifier.offset(x = 8.dp, y = (-8).dp),
onClick = {
scope.launch { viewModel.getGotQuotes() }
}
) {
Icon(
imageVector = Icons.Outlined.Refresh,
contentDescription = null
)
}
}
}
) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier
.padding(horizontal = 16.dp)
.offset(y = (-12).dp)
) {
quotes.forEachIndexed { index, quote ->
Column {
Text(
text = quote.quote,
color = MaterialTheme.colorScheme.primary
)
Text(
text = " - ${quote.character.name}",
color = MaterialTheme.colorScheme.onSurfaceVariant,
fontStyle = FontStyle.Italic
)
}
if (index != quotes.size - 1) {
Divider(
modifier = Modifier.padding(vertical = 8.dp),
color = MaterialTheme.colorScheme.surface
)
}
}
Spacer(modifier = Modifier.height(1.dp))
}
}
}
}
}

View File

@@ -267,4 +267,5 @@
<string name="your_rating">Your rating: %1$d/10</string>
<string name="uncredited">Uncredited</string>
<string name="clear_search_query">Clear search query</string>
<string name="quotes_title">Quotes</string>
</resources>