mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-08 12:42:44 -05:00
add items to about page and add attribution
This commit is contained in:
@@ -33,8 +33,8 @@ android {
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
@@ -118,7 +118,7 @@ dependencies {
|
||||
implementation "io.insert-koin:koin-android:$koin"
|
||||
|
||||
// coil
|
||||
def coil = "2.0.0-rc01"
|
||||
def coil = "2.2.2"
|
||||
implementation "io.coil-kt:coil-compose:$coil"
|
||||
|
||||
//Coroutines
|
||||
@@ -135,9 +135,11 @@ dependencies {
|
||||
def markdown = "0.2.1"
|
||||
implementation "org.jetbrains:markdown:$markdown"
|
||||
|
||||
implementation 'de.charlex.compose:revealswipe:1.0.0'
|
||||
def revealSwipe = "1.0.0"
|
||||
implementation "de.charlex.compose:revealswipe:$revealSwipe"
|
||||
|
||||
implementation 'com.github.jeziellago:compose-markdown:0.3.3'
|
||||
def compose_markdown = "0.3.3"
|
||||
implementation "com.github.jeziellago:compose-markdown:$compose_markdown"
|
||||
|
||||
// testing
|
||||
def junit = "4.13.2"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.owenlejeune.tvtime
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.window.OnBackInvokedDispatcher
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
@@ -40,6 +42,14 @@ import org.koin.android.ext.android.inject
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
class OnboardingActivity: MonetCompatActivity() {
|
||||
|
||||
companion object {
|
||||
fun showActivity(sourceActivity: Context) {
|
||||
val intent = Intent(sourceActivity, OnboardingActivity::class.java)
|
||||
// intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
sourceActivity.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private val preferences: AppPreferences by inject()
|
||||
|
||||
private lateinit var pagerState: PagerState
|
||||
@@ -104,53 +114,56 @@ class OnboardingActivity: MonetCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
Box(
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(all = 12.dp)
|
||||
) {
|
||||
Button(
|
||||
modifier = Modifier.align(Alignment.CenterStart),
|
||||
enabled = true,
|
||||
onClick = {
|
||||
preferences.firstLaunch = false
|
||||
launchActivity(MainActivity::class.java)
|
||||
}
|
||||
OnboardingPage[pagerState.currentPage].footer.invoke(this@Column)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
val skipText = if (preferences.firstLaunchTesting)
|
||||
stringResource(id = R.string.action_skip_testing)
|
||||
else
|
||||
stringResource(id = R.string.action_skip)
|
||||
Text(text = skipText)
|
||||
}
|
||||
|
||||
HorizontalPagerIndicator(
|
||||
pagerState = pagerState,
|
||||
modifier = Modifier
|
||||
.align(Alignment.Center)
|
||||
.padding(16.dp),
|
||||
activeColor = MaterialTheme.colorScheme.secondary
|
||||
)
|
||||
|
||||
Button(
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
shape = CircleShape,
|
||||
enabled = nextButtonEnabled.value,
|
||||
onClick = {
|
||||
if (isLastPage) {
|
||||
Button(
|
||||
enabled = true,
|
||||
onClick = {
|
||||
preferences.firstLaunch = false
|
||||
launchActivity(MainActivity::class.java)
|
||||
} else {
|
||||
coroutineScope.launch {
|
||||
pagerState.animateScrollToPage(pagerState.currentPage + 1)
|
||||
}
|
||||
) {
|
||||
val skipText = if (preferences.firstLaunchTesting)
|
||||
stringResource(id = R.string.action_skip_testing)
|
||||
else
|
||||
stringResource(id = R.string.action_skip)
|
||||
Text(text = skipText)
|
||||
}
|
||||
|
||||
HorizontalPagerIndicator(
|
||||
pagerState = pagerState,
|
||||
modifier = Modifier
|
||||
.padding(16.dp),
|
||||
activeColor = MaterialTheme.colorScheme.secondary
|
||||
)
|
||||
|
||||
Button(
|
||||
shape = CircleShape,
|
||||
enabled = nextButtonEnabled.value,
|
||||
onClick = {
|
||||
if (isLastPage) {
|
||||
preferences.firstLaunch = false
|
||||
launchActivity(MainActivity::class.java)
|
||||
} else {
|
||||
coroutineScope.launch {
|
||||
pagerState.animateScrollToPage(pagerState.currentPage + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
if (!isLastPage) {
|
||||
Text(stringResource(id = R.string.get_started))
|
||||
} else {
|
||||
Icon(imageVector = Icons.Filled.ArrowForward, contentDescription = null)
|
||||
) {
|
||||
if (!isLastPage) {
|
||||
Text(stringResource(id = R.string.get_started))
|
||||
} else {
|
||||
Icon(imageVector = Icons.Filled.ArrowForward, contentDescription = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,7 +198,7 @@ class OnboardingActivity: MonetCompatActivity() {
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
Spacer(modifier = Modifier.height(50.dp))
|
||||
page.additionalContent(this@OnboardingActivity, nextButtonEnabled)
|
||||
page.additionalContent(this@Column, this@OnboardingActivity, nextButtonEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,27 +45,6 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
@Composable
|
||||
fun Gallery(
|
||||
pagerState: PagerState,
|
||||
models: List<Any?>,
|
||||
modifier: Modifier = Modifier,
|
||||
contentDescriptions: List<String> = emptyList()
|
||||
) {
|
||||
HorizontalPager(
|
||||
count = models.size,
|
||||
state = pagerState,
|
||||
modifier = modifier
|
||||
) { page ->
|
||||
AsyncImage(
|
||||
model = models[page],
|
||||
contentDescription = contentDescriptions[page],
|
||||
contentScale = ContentScale.FillWidth
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
@Composable
|
||||
fun TapGallery(
|
||||
@@ -145,7 +124,7 @@ fun TapGallery(
|
||||
imageVector = Icons.Outlined.ChevronLeft,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
tint = MaterialTheme.colorScheme.surface
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
|
||||
@@ -160,114 +139,10 @@ fun TapGallery(
|
||||
imageVector = Icons.Outlined.ChevronRight,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
tint = MaterialTheme.colorScheme.surface
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
// Box(
|
||||
// modifier = Modifier
|
||||
// .background(brush = leftGradient)
|
||||
// .height(height = sizeImage.value.height.toDp())
|
||||
// .width((sizeImage.value.width/2).toDp())
|
||||
// .align(Alignment.CenterStart)
|
||||
// .onGloballyPositioned { leftSizeImage.value = it.size }
|
||||
// .clickable {
|
||||
// val target =
|
||||
// if (pagerState.currentPage == 0) models.size - 1 else pagerState.currentPage - 1
|
||||
// scope.launch { pagerState.animateScrollToPage(target) }
|
||||
// }
|
||||
// ) {
|
||||
// Icon(
|
||||
// imageVector = Icons.Outlined.ChevronLeft,
|
||||
// contentDescription = null,
|
||||
// modifier = Modifier
|
||||
// .size(48.dp)
|
||||
// .padding(start = 24.dp)
|
||||
// .align(Alignment.CenterStart),
|
||||
// tint = MaterialTheme.colorScheme.surface
|
||||
// )
|
||||
// }
|
||||
// Box(
|
||||
// modifier = Modifier
|
||||
// .background(brush = rightGradient)
|
||||
// .height(height = sizeImage.value.height.toDp())
|
||||
// .width((sizeImage.value.width/2).toDp())
|
||||
// .align(Alignment.CenterEnd)
|
||||
// .onGloballyPositioned { rightSizeImage.value = it.size }
|
||||
// .clickable {
|
||||
// val target =
|
||||
// if (pagerState.currentPage == models.size - 1) 0 else pagerState.currentPage + 1
|
||||
// scope.launch { pagerState.animateScrollToPage(target) }
|
||||
// }
|
||||
// ) {
|
||||
// Icon(
|
||||
// imageVector = Icons.Outlined.ChevronRight,
|
||||
// contentDescription = null,
|
||||
// modifier = Modifier
|
||||
// .size(48.dp)
|
||||
// .padding(end = 24.dp)
|
||||
// .align(Alignment.CenterEnd),
|
||||
// tint = MaterialTheme.colorScheme.surface
|
||||
// )
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// AnimatedVisibility(
|
||||
// visible = showControls.value,
|
||||
// enter = fadeIn(),
|
||||
// exit = fadeOut()
|
||||
// ) {
|
||||
// val leftSizeImage = remember { mutableStateOf(IntSize.Zero) }
|
||||
// val leftGradient = Brush.horizontalGradient(
|
||||
// colors = listOf(Color.Black, Color.Transparent),
|
||||
// startX = 0f,
|
||||
// endX = leftSizeImage.value.width.toFloat()
|
||||
// )
|
||||
// Box(
|
||||
// modifier = Modifier
|
||||
// .background(brush = leftGradient)
|
||||
// .fillMaxHeight()
|
||||
// .width(100.dp)
|
||||
// .align(Alignment.CenterStart)
|
||||
// .onGloballyPositioned { leftSizeImage.value = it.size }
|
||||
// .clickable {
|
||||
// val target =
|
||||
// if (pagerState.currentPage == 0) models.size - 1 else pagerState.currentPage + 1
|
||||
// scope.launch { pagerState.animateScrollToPage(target) }
|
||||
// }
|
||||
// ) {
|
||||
// Icon(
|
||||
// imageVector = Icons.Outlined.ChevronLeft,
|
||||
// contentDescription = null,
|
||||
// modifier = Modifier.size(48.dp)
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// val rightSizeImage = remember { mutableStateOf(IntSize.Zero) }
|
||||
// val rightGradient = Brush.horizontalGradient(
|
||||
// colors = listOf(Color.Black, Color.Transparent),
|
||||
// startX = leftSizeImage.value.width.toFloat(),
|
||||
// endX = 0f
|
||||
// )
|
||||
// Box(
|
||||
// modifier = Modifier
|
||||
// .background(brush = rightGradient)
|
||||
// .fillMaxHeight()
|
||||
// .width(100.dp)
|
||||
// .align(Alignment.CenterEnd)
|
||||
// .onGloballyPositioned { rightSizeImage.value = it.size }
|
||||
// .clickable {
|
||||
// val target =
|
||||
// if (pagerState.currentPage == models.size - 1) 0 else pagerState.currentPage - 1
|
||||
// scope.launch { pagerState.animateScrollToPage(target) }
|
||||
// }
|
||||
// ) {
|
||||
// Icon(
|
||||
// imageVector = Icons.Outlined.ChevronRight,
|
||||
// contentDescription = null,
|
||||
// modifier = Modifier.size(48.dp)
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,9 @@ import androidx.compose.foundation.layout.RowScope
|
||||
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.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.material.icons.outlined.Login
|
||||
@@ -30,9 +32,11 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
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.compositeOver
|
||||
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.text.style.TextAlign
|
||||
@@ -213,12 +217,27 @@ fun ProfileMenuOverlay(
|
||||
|
||||
MenuDivider()
|
||||
|
||||
Text(
|
||||
text = "${stringResource(id = R.string.app_name)} v${BuildConfig.VERSION_NAME}",
|
||||
fontSize = 10.sp,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = "${stringResource(id = R.string.app_name)} v${BuildConfig.VERSION_NAME}",
|
||||
fontSize = 10.sp
|
||||
)
|
||||
Text(text = "•")
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.tmdb_logo),
|
||||
tint = Color.Unspecified,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.powered_by_tmdb),
|
||||
fontSize = 10.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,6 +256,8 @@ private fun ProfileMenuItem(
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.padding(horizontal = 4.dp)
|
||||
.clickable(
|
||||
enabled = onClick != null,
|
||||
onClick = onClick ?: {}
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavHostController
|
||||
import coil.compose.AsyncImage
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.DetailService
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.MoviesService
|
||||
@@ -47,6 +48,10 @@ fun SearchScreen(
|
||||
title: String,
|
||||
mediaViewType: MediaViewType
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
systemUiController.setStatusBarColor(color = MaterialTheme.colorScheme.background)
|
||||
systemUiController.setNavigationBarColor(color = MaterialTheme.colorScheme.background)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
|
||||
@@ -8,10 +8,16 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
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.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.outlined.Description
|
||||
@@ -34,13 +40,17 @@ 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.vector.ImageVector
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavController
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.owenlejeune.tvtime.BuildConfig
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.utils.FileUtils
|
||||
@@ -51,6 +61,10 @@ import dev.jeziellago.compose.markdowntext.MarkdownText
|
||||
fun AboutView(
|
||||
appNavController: NavController
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
systemUiController.setStatusBarColor(color = MaterialTheme.colorScheme.background)
|
||||
systemUiController.setNavigationBarColor(color = MaterialTheme.colorScheme.background)
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
||||
@@ -78,11 +92,10 @@ fun AboutView(
|
||||
) {
|
||||
Box(modifier = Modifier.padding(it)) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp),
|
||||
modifier = Modifier.padding(horizontal = 24.dp)
|
||||
modifier = Modifier.padding(horizontal = 12.dp)
|
||||
) {
|
||||
AboutItem(
|
||||
title = "App Info",
|
||||
title = stringResource(R.string.app_info_label),
|
||||
subtitle = "v${BuildConfig.VERSION_NAME}",
|
||||
icon = Icons.Outlined.Info,
|
||||
onClick = {
|
||||
@@ -96,7 +109,7 @@ fun AboutView(
|
||||
|
||||
var showChangeLog by remember { mutableStateOf(false) }
|
||||
AboutItem(
|
||||
title = "Changelog",
|
||||
title = stringResource(R.string.changelog_label),
|
||||
icon = Icons.Outlined.Description,
|
||||
onClick = { showChangeLog = true }
|
||||
)
|
||||
@@ -104,6 +117,18 @@ fun AboutView(
|
||||
visible = showChangeLog,
|
||||
onDismissRequest = { showChangeLog = false }
|
||||
)
|
||||
|
||||
AboutItem(
|
||||
title = "Privacy Policy",
|
||||
onClick = {}
|
||||
)
|
||||
|
||||
AboutItem(
|
||||
title = "Terms of Use",
|
||||
onClick = {}
|
||||
)
|
||||
|
||||
AttributionSection()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,29 +138,34 @@ fun AboutView(
|
||||
private fun AboutItem(
|
||||
title: String,
|
||||
subtitle: String? = null,
|
||||
icon: ImageVector,
|
||||
icon: ImageVector? = null,
|
||||
onClick: (() -> Unit)? = null
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.clickable(
|
||||
onClick = onClick ?: {},
|
||||
enabled = onClick != null
|
||||
),
|
||||
horizontalArrangement = Arrangement.spacedBy(24.dp)
|
||||
)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = subtitle,
|
||||
modifier = Modifier.align(Alignment.CenterVertically),
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
icon?.let {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = subtitle,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterVertically)
|
||||
.padding(all = 12.dp),
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterVertically)
|
||||
.weight(1f)
|
||||
.padding(all = 12.dp)
|
||||
) {
|
||||
val titleColor = MaterialTheme.colorScheme.onBackground
|
||||
val subtitleColor = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
@@ -161,12 +191,54 @@ private fun ChangeLogDialog(
|
||||
Button(
|
||||
onClick = onDismissRequest
|
||||
) {
|
||||
Text(text = "Close")
|
||||
Text(text = stringResource(id = R.string.action_dismiss))
|
||||
}
|
||||
},
|
||||
text = {
|
||||
MarkdownText(markdown = changeLog)
|
||||
MarkdownText(
|
||||
markdown = changeLog,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.AttributionSection() {
|
||||
val context = LocalContext.current
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.clickable(
|
||||
onClick = {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(context.getString(R.string.tmdb_home_page)))
|
||||
context.startActivity(intent)
|
||||
}
|
||||
)
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.tmdb_logo),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(32.dp),
|
||||
tint = Color.Unspecified
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.attribution_text),
|
||||
fontSize = 12.sp
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
}
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,11 @@ import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
@@ -24,6 +26,7 @@ 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
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.*
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v4.model.V4AccountList
|
||||
@@ -48,59 +51,67 @@ fun AccountView(
|
||||
appNavController: NavHostController,
|
||||
doSignInPartTwo: Boolean = false
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
systemUiController.setStatusBarColor(color = MaterialTheme.colorScheme.background)
|
||||
systemUiController.setNavigationBarColor(color = MaterialTheme.colorScheme.background)
|
||||
|
||||
val currentSessionState = remember { SessionManager.currentSession }
|
||||
val currentSession = currentSessionState.value
|
||||
|
||||
val showProfileMenuOverlay = remember { mutableStateOf(false) }
|
||||
|
||||
ProfileMenuContainer(
|
||||
appNavController = appNavController,
|
||||
visible = showProfileMenuOverlay.value,
|
||||
onDismissRequest = { showProfileMenuOverlay.value = false }
|
||||
) {
|
||||
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
||||
val topAppBarScrollState = rememberTopAppBarScrollState()
|
||||
val scrollBehavior = remember(decayAnimationSpec) {
|
||||
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec, topAppBarScrollState)
|
||||
}
|
||||
Scaffold(
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
LargeTopAppBar(
|
||||
scrollBehavior = scrollBehavior,
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = { appNavController.popBackStack() }
|
||||
) {
|
||||
Icon(
|
||||
Icons.Filled.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
},
|
||||
title = {
|
||||
if (currentSession?.isAuthorized == false) {
|
||||
Text(text = stringResource(id = R.string.account_not_logged_in))
|
||||
} else {
|
||||
val accountDetails = remember { currentSession!!.accountDetails }
|
||||
Text(text = getAccountName(accountDetails.value))
|
||||
}
|
||||
},
|
||||
colors = TopAppBarDefaults.largeTopAppBarColors(scrolledContainerColor = MaterialTheme.colorScheme.background),
|
||||
actions = {
|
||||
AccountIcon(
|
||||
modifier = Modifier.padding(start = 12.dp),
|
||||
size = 32.dp,
|
||||
onClick = { showProfileMenuOverlay.value = true }
|
||||
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
||||
val topAppBarScrollState = rememberTopAppBarScrollState()
|
||||
val scrollBehavior = remember(decayAnimationSpec) {
|
||||
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec, topAppBarScrollState)
|
||||
}
|
||||
Scaffold(
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
LargeTopAppBar(
|
||||
scrollBehavior = scrollBehavior,
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = { appNavController.popBackStack() }
|
||||
) {
|
||||
Icon(
|
||||
Icons.Filled.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
}
|
||||
)
|
||||
}
|
||||
) {
|
||||
Box(modifier = Modifier.padding(it)) {
|
||||
AccountViewContent(appNavController = appNavController, doSignInPartTwo = doSignInPartTwo)
|
||||
}
|
||||
},
|
||||
title = {
|
||||
if (currentSession?.isAuthorized == false) {
|
||||
Text(text = stringResource(id = R.string.account_not_logged_in))
|
||||
} else {
|
||||
val accountDetails = remember { currentSession!!.accountDetails }
|
||||
Text(text = getAccountName(accountDetails.value))
|
||||
}
|
||||
},
|
||||
colors = TopAppBarDefaults.largeTopAppBarColors(scrolledContainerColor = MaterialTheme.colorScheme.background),
|
||||
actions = {
|
||||
var showDropDownMenu by remember { mutableStateOf(false) }
|
||||
AccountIcon(
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
size = 32.dp,
|
||||
onClick = { showDropDownMenu = true }
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = showDropDownMenu,
|
||||
onDismissRequest = { showDropDownMenu = false}
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(id = R.string.action_sign_out)) },
|
||||
onClick = {
|
||||
SessionManager.clearSession()
|
||||
appNavController.popBackStack()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) {
|
||||
Box(modifier = Modifier.padding(it)) {
|
||||
AccountViewContent(appNavController = appNavController, doSignInPartTwo = doSignInPartTwo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import androidx.navigation.NavController
|
||||
import coil.compose.AsyncImage
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.AccountService
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.MarkAsFavoriteBody
|
||||
@@ -65,6 +66,10 @@ fun ListDetailView(
|
||||
windowSize: WindowSizeClass,
|
||||
preferences: AppPreferences = KoinJavaComponent.get(AppPreferences::class.java)
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
systemUiController.setStatusBarColor(color = MaterialTheme.colorScheme.background)
|
||||
systemUiController.setNavigationBarColor(color = MaterialTheme.colorScheme.background)
|
||||
|
||||
val service = ListV4Service()
|
||||
|
||||
val parentList = remember { mutableStateOf<MediaList?>(null) }
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.google.accompanist.flowlayout.FlowRow
|
||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.pager.PagerState
|
||||
import com.google.accompanist.pager.rememberPagerState
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.AccountService
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.DetailService
|
||||
@@ -69,6 +70,10 @@ fun MediaDetailView(
|
||||
windowSize: WindowSizeClass,
|
||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
systemUiController.setStatusBarColor(color = MaterialTheme.colorScheme.background)
|
||||
systemUiController.setNavigationBarColor(color = MaterialTheme.colorScheme.background)
|
||||
|
||||
val service = when (type) {
|
||||
MediaViewType.MOVIE -> MoviesService()
|
||||
MediaViewType.TV -> TvService()
|
||||
|
||||
@@ -20,6 +20,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.PeopleService
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.DetailPerson
|
||||
@@ -40,6 +41,10 @@ fun PersonDetailView(
|
||||
appNavController: NavController,
|
||||
personId: Int?
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
systemUiController.setStatusBarColor(color = MaterialTheme.colorScheme.background)
|
||||
systemUiController.setNavigationBarColor(color = MaterialTheme.colorScheme.background)
|
||||
|
||||
val person = remember { mutableStateOf<DetailPerson?>(null) }
|
||||
personId?.let {
|
||||
if (person.value == null) {
|
||||
|
||||
@@ -30,8 +30,10 @@ import androidx.navigation.NavController
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.kieronquinn.monetcompat.core.MonetCompat
|
||||
import com.owenlejeune.tvtime.BuildConfig
|
||||
import com.owenlejeune.tvtime.OnboardingActivity
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.*
|
||||
@@ -53,6 +55,10 @@ fun SettingsTab(
|
||||
route: String? = null,
|
||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
systemUiController.setStatusBarColor(color = MaterialTheme.colorScheme.background)
|
||||
systemUiController.setNavigationBarColor(color = MaterialTheme.colorScheme.background)
|
||||
|
||||
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
||||
val topAppBarScrollState = rememberTopAppBarScrollState()
|
||||
val scrollBehavior = remember(decayAnimationSpec) {
|
||||
@@ -445,6 +451,15 @@ private fun DevPreferences(
|
||||
preferences.firstLaunchTesting = isChecked
|
||||
}
|
||||
)
|
||||
Text(
|
||||
text = "Show onboarding UI",
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp, vertical = 12.dp)
|
||||
.clickable {
|
||||
OnboardingActivity.showActivity(context)
|
||||
}
|
||||
)
|
||||
|
||||
val shouldShowPalette = remember { mutableStateOf(false) }
|
||||
Text(
|
||||
|
||||
@@ -14,11 +14,13 @@ import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SmallTopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavController
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.google.accompanist.web.AccompanistWebViewClient
|
||||
import com.google.accompanist.web.WebView
|
||||
import com.google.accompanist.web.rememberWebViewState
|
||||
@@ -32,6 +34,10 @@ fun WebLinkView(
|
||||
url: String,
|
||||
appNavController: NavController
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
systemUiController.setStatusBarColor(color = MaterialTheme.colorScheme.background)
|
||||
systemUiController.setNavigationBarColor(color = MaterialTheme.colorScheme.background)
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
SmallTopAppBar(
|
||||
|
||||
@@ -4,8 +4,16 @@ import android.os.Build
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Brightness6
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
@@ -13,13 +21,19 @@ import androidx.compose.material.icons.outlined.DarkMode
|
||||
import androidx.compose.material.icons.outlined.LightMode
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
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 com.kieronquinn.monetcompat.core.MonetCompat
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
@@ -34,7 +48,8 @@ sealed class OnboardingPage(
|
||||
@StringRes val title: Int,
|
||||
@StringRes val description: Int,
|
||||
@DrawableRes val image: Int? = null,
|
||||
val additionalContent: @Composable (AppCompatActivity, MutableState<Boolean>) -> Unit = { a, e -> }
|
||||
val additionalContent: @Composable ColumnScope.(AppCompatActivity, MutableState<Boolean>) -> Unit = { _, _ -> },
|
||||
val footer: @Composable ColumnScope.() -> Unit = {}
|
||||
) {
|
||||
|
||||
companion object: KoinComponent {
|
||||
@@ -49,7 +64,29 @@ sealed class OnboardingPage(
|
||||
order = 0,
|
||||
title = R.string.app_name,
|
||||
description = R.string.intro_page_desc,
|
||||
image = R.drawable.ic_launcher_foreground
|
||||
image = R.drawable.ic_launcher_foreground,
|
||||
footer = {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.wrapContentWidth()
|
||||
.padding(all = 24.dp)
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.tmdb_logo),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(32.dp),
|
||||
tint = Color.Unspecified
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.attribution_text),
|
||||
fontSize = 12.sp,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
object SignInPage: OnboardingPage(
|
||||
|
||||
22
app/src/main/res/drawable/tmdb_logo.xml
Normal file
22
app/src/main/res/drawable/tmdb_logo.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="185.04dp"
|
||||
android:height="133.4dp"
|
||||
android:viewportWidth="185.04"
|
||||
android:viewportHeight="133.4">
|
||||
<path
|
||||
android:pathData="M51.06,66.7h0A17.67,17.67 0,0 1,68.73 49h-0.1A17.67,17.67 0,0 1,86.3 66.7h0A17.67,17.67 0,0 1,68.63 84.37h0.1A17.67,17.67 0,0 1,51.06 66.7ZM133.73,35.37h32.9A17.67,17.67 0,0 0,184.3 17.7h0A17.67,17.67 0,0 0,166.63 0h-32.9A17.67,17.67 0,0 0,116.06 17.7h0A17.67,17.67 0,0 0,133.73 35.37ZM20.73,133.37h63.9A17.67,17.67 0,0 0,102.3 115.7h0A17.67,17.67 0,0 0,84.63 98L20.73,98A17.67,17.67 0,0 0,3.06 115.7h0A17.67,17.67 0,0 0,20.73 133.37ZM104.65,84.37h6.25L125.5,49h-8.35l-8.9,23.2h-0.1L99.4,49L90.5,49ZM137.1,84.37h7.8L144.9,49h-7.8ZM159.3,84.37h24.95L184.25,77.2L167.1,77.2L167.1,70h15.35L182.45,62.8L167.1,62.8L167.1,56.2h16.25L183.35,49h-24ZM10.1,35.4h7.8L17.9,6.9L28,6.9L28,0L0,0L0,6.9L10.1,6.9ZM39,35.4h7.8L46.8,20.1L61.9,20.1L61.9,35.4h7.8L69.7,0L61.9,0L61.9,13.2L46.75,13.2L46.75,0L39,0ZM80.25,35.4h25L105.25,28.2L88,28.2L88,21h15.35L103.35,13.8L88,13.8L88,7.2h16.25L104.25,0h-24ZM1.25,84.4L9,84.4L9,57.25h0.1l9,27.15L24,84.4l9.3,-27.15h0.1L33.4,84.4h7.8L41.2,49L29.45,49l-8.2,23.1h-0.1L13,49L1.2,49ZM113.34,133.4L126,133.4a24.59,24.59 0,0 0,7.56 -1.15,19.52 19.52,0 0,0 6.35,-3.37 16.37,16.37 0,0 0,4.37 -5.5A16.91,16.91 0,0 0,146 115.8a18.5,18.5 0,0 0,-1.68 -8.25,15.1 15.1,0 0,0 -4.52,-5.53A18.55,18.55 0,0 0,133.07 99,33.54 33.54,0 0,0 125,98L113.29,98ZM121.15,105.2h4.6a17.43,17.43 0,0 1,4.67 0.62,11.68 11.68,0 0,1 3.88,1.88 9,9 0,0 1,2.62 3.18,9.87 9.87,0 0,1 1,4.52 11.92,11.92 0,0 1,-1 5.08,8.69 8.69,0 0,1 -2.67,3.34 10.87,10.87 0,0 1,-4 1.83,21.57 21.57,0 0,1 -5,0.55L121.1,126.2ZM157.29,133.4h14.5a23.11,23.11 0,0 0,4.73 -0.5,13.38 13.38,0 0,0 4.27,-1.65 9.42,9.42 0,0 0,3.1 -3,8.52 8.52,0 0,0 1.2,-4.68 9.16,9.16 0,0 0,-0.55 -3.2,7.79 7.79,0 0,0 -1.57,-2.62 8.38,8.38 0,0 0,-2.45 -1.85,10 10,0 0,0 -3.18,-1v-0.1a9.28,9.28 0,0 0,4.43 -2.82,7.42 7.42,0 0,0 1.67,-5 8.34,8.34 0,0 0,-1.15 -4.65,7.88 7.88,0 0,0 -3,-2.73 12.9,12.9 0,0 0,-4.17 -1.3,34.42 34.42,0 0,0 -4.63,-0.32h-13.2ZM165.09,104.6h5.3a10.79,10.79 0,0 1,1.85 0.17,5.77 5.77,0 0,1 1.7,0.58 3.33,3.33 0,0 1,1.23 1.13,3.22 3.22,0 0,1 0.47,1.82 3.63,3.63 0,0 1,-0.42 1.8,3.34 3.34,0 0,1 -1.13,1.2 4.78,4.78 0,0 1,-1.57 0.65,8.16 8.16,0 0,1 -1.78,0.2L165,112.15ZM165.09,118.75h5.9a15.12,15.12 0,0 1,2.05 0.15,7.83 7.83,0 0,1 2,0.55 4,4 0,0 1,1.58 1.17,3.13 3.13,0 0,1 0.62,2 3.71,3.71 0,0 1,-0.47 1.95,4 4,0 0,1 -1.23,1.3 4.78,4.78 0,0 1,-1.67 0.7,8.91 8.91,0 0,1 -1.83,0.2h-7Z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="0"
|
||||
android:startY="66.7"
|
||||
android:endX="185.04"
|
||||
android:endY="66.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>
|
||||
@@ -215,4 +215,10 @@
|
||||
<string name="recommended_tv_title">Recommended TV</string>
|
||||
<string name="no_recommended_tv">No Recommended TV</string>
|
||||
<string name="no_result_found">No more results found</string>
|
||||
|
||||
<string name="attribution_text">This product uses the TMDB API but is not endorsed or certified by TMDB.</string>
|
||||
<string name="tmdb_home_page">"https://www.themoviedb.org"</string>
|
||||
<string name="app_info_label">App Info</string>
|
||||
<string name="changelog_label">Changelog</string>
|
||||
<string name="powered_by_tmdb">Powered by TMDB</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user