mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-11 14:22:55 -05:00
add basis for onboarding flow and some more theming options
This commit is contained in:
@@ -13,15 +13,25 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.TVTime"
|
||||
android:usesCleartextTraffic="true">
|
||||
|
||||
<activity android:name=".AppRoutingActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.TVTime">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".OnboardingActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.TVTime" />
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.TVTime"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.owenlejeune.tvtime
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.owenlejeune.tvtime.extensions.launchActivity
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
class AppRoutingActivity: AppCompatActivity() {
|
||||
|
||||
private val preferences: AppPreferences by inject()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (preferences.firstLaunch) {
|
||||
launchActivity(OnboardingActivity::class.java)
|
||||
} else {
|
||||
launchActivity(MainActivity::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.owenlejeune.tvtime
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.animation.rememberSplineBasedDecay
|
||||
import androidx.compose.foundation.Image
|
||||
@@ -37,9 +36,9 @@ import com.owenlejeune.tvtime.ui.components.SearchFab
|
||||
import com.owenlejeune.tvtime.ui.navigation.BottomNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavGraph
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaDetailView
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.PersonDetailView
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaDetailView
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.PersonDetailView
|
||||
import com.owenlejeune.tvtime.ui.theme.TVTimeTheme
|
||||
import com.owenlejeune.tvtime.utils.KeyboardManager
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
|
||||
156
app/src/main/java/com/owenlejeune/tvtime/OnboardingActivity.kt
Normal file
156
app/src/main/java/com/owenlejeune/tvtime/OnboardingActivity.kt
Normal file
@@ -0,0 +1,156 @@
|
||||
package com.owenlejeune.tvtime
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowForward
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
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
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.accompanist.pager.*
|
||||
import com.kieronquinn.monetcompat.app.MonetCompatActivity
|
||||
import com.owenlejeune.tvtime.extensions.launchActivity
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.screens.onboarding.OnboardingPage
|
||||
import com.owenlejeune.tvtime.ui.theme.TVTimeTheme
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
class OnboardingActivity: MonetCompatActivity() {
|
||||
|
||||
private val preferences: AppPreferences by inject()
|
||||
|
||||
private lateinit var pagerState: PagerState
|
||||
private lateinit var coroutineScope: CoroutineScope
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
lifecycleScope.launchWhenCreated {
|
||||
monet.awaitMonetReady()
|
||||
setContent {
|
||||
TVTimeTheme(monetCompat = monet) {
|
||||
OnboardingUi()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun OnboardingUi() {
|
||||
pagerState = rememberPagerState()
|
||||
coroutineScope = rememberCoroutineScope()
|
||||
|
||||
Column(
|
||||
modifier = Modifier.background(color = MaterialTheme.colorScheme.background)
|
||||
) {
|
||||
HorizontalPager(
|
||||
state = pagerState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
// .background(MaterialTheme.colorScheme.primary),
|
||||
count = OnboardingPage.values().size,
|
||||
userScrollEnabled = false
|
||||
) { page ->
|
||||
OnboardingPageUi(page = OnboardingPage[page])
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(all = 12.dp)
|
||||
) {
|
||||
HorizontalPagerIndicator(
|
||||
pagerState = pagerState,
|
||||
modifier = Modifier
|
||||
.align(Alignment.Center)
|
||||
.padding(16.dp),
|
||||
activeColor = MaterialTheme.colorScheme.secondary
|
||||
)
|
||||
|
||||
val isLastPage = pagerState.currentPage == OnboardingPage.values().size - 1
|
||||
Button(
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
shape = CircleShape,
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun OnboardingPageUi(page: OnboardingPage) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
page.image?.let {
|
||||
Image(
|
||||
painter = painterResource(id = it),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(200.dp),
|
||||
colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.secondary)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
}
|
||||
Text(
|
||||
text = stringResource(id = page.title),
|
||||
fontSize = 28.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = stringResource(id = page.description),
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 14.sp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
page.additionalContent(this@OnboardingActivity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (pagerState.currentPage == 0) {
|
||||
finish()
|
||||
} else {
|
||||
coroutineScope.launch {
|
||||
pagerState.animateScrollToPage(pagerState.currentPage - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,9 @@ import com.kieronquinn.monetcompat.core.MonetCompat
|
||||
import com.owenlejeune.tvtime.di.modules.appModule
|
||||
import com.owenlejeune.tvtime.di.modules.networkModule
|
||||
import com.owenlejeune.tvtime.di.modules.preferencesModule
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import dev.kdrag0n.monet.factory.ColorSchemeFactory
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.android.ext.koin.androidLogger
|
||||
import org.koin.core.context.startKoin
|
||||
@@ -13,6 +16,8 @@ import org.koin.core.logger.Level
|
||||
|
||||
class TvTimeApplication: Application() {
|
||||
|
||||
private val preferences: AppPreferences by inject()
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
@@ -30,6 +35,12 @@ class TvTimeApplication: Application() {
|
||||
}
|
||||
|
||||
MonetCompat.enablePaletteCompat()
|
||||
MonetCompat.chromaMultiplier = preferences.chromaMultiplier
|
||||
|
||||
MonetCompat.wallpaperColorPicker = {
|
||||
val userPickedColor = preferences.selectedColor
|
||||
it?.firstOrNull { color -> color == userPickedColor } ?: it?.firstOrNull()
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Stetho.initializeWithDefaults(this)
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.owenlejeune.tvtime.api.tmdb.api.v3.deserializer
|
||||
|
||||
import com.google.gson.*
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.KnownFor
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import java.lang.reflect.Type
|
||||
|
||||
class KnownForDeserializer: JsonDeserializer<KnownFor> {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class DetailCast(
|
||||
@SerializedName("id") val id: Int,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class DetailCrew(
|
||||
@SerializedName("id") val id: Int,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class KnowForTv(
|
||||
backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
abstract class KnownFor(
|
||||
@SerializedName("backdrop_path") val backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class KnownForMovie(
|
||||
backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class MarkAsFavoriteBody(
|
||||
@SerializedName("media_type") val mediaType: MediaViewType,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class WatchlistBody(
|
||||
@SerializedName("media_type") val mediaType: MediaViewType,
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.google.gson.*
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v4.model.ListItem
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v4.model.ListMovie
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v4.model.ListTv
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import java.lang.reflect.Type
|
||||
|
||||
class ListItemDeserializer: JsonDeserializer<ListItem> {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class AddToListBody(
|
||||
@SerializedName("items") val items: List<AddToListBodyItem>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class DeleteListItemsBody(
|
||||
@SerializedName("media_id") val id: Int,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
abstract class ListItem(
|
||||
@SerializedName("backdrop_path") val backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class ListItemStatusResponse(
|
||||
statusMessage: String,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class ListMovie(
|
||||
backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class ListTv(
|
||||
backdropPath: String?,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.owenlejeune.tvtime.api.tmdb.api.v4.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
|
||||
class UpdateListItemBody(
|
||||
@SerializedName("items") val items: List<UpdateListItemBodyItem>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.owenlejeune.tvtime.extensions
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.geometry.Size
|
||||
@@ -39,4 +40,10 @@ private fun getWindowSizeClass(windowDpSize: DpSize): WindowSizeClass = when {
|
||||
windowDpSize.width < 600.dp -> WindowSizeClass.Compact
|
||||
windowDpSize.width < 840.dp -> WindowSizeClass.Medium
|
||||
else -> WindowSizeClass.Expanded
|
||||
}
|
||||
|
||||
fun <T> Activity.launchActivity(activity: Class<T>) {
|
||||
val intent = Intent(this, activity)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package com.owenlejeune.tvtime.preferences
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import com.kieronquinn.monetcompat.core.MonetCompat
|
||||
import com.owenlejeune.tvtime.BuildConfig
|
||||
|
||||
class AppPreferences(context: Context) {
|
||||
|
||||
@@ -13,6 +15,11 @@ class AppPreferences(context: Context) {
|
||||
private val HIDE_TITLE = "hide_title"
|
||||
private val GUEST_SESSION = "guest_session_id"
|
||||
private val AUTHORIZED_SESSION = "authorized_session_id"
|
||||
private val FIRST_LAUNCH = "first_launch"
|
||||
private val FIRST_LAUNCH_TESTING = "first_launch_testing"
|
||||
private val CHROMA_MULTIPLIER = "chroma_multiplier"
|
||||
private val USE_SYSTEM_COLORS = "use_system_colors"
|
||||
private val SELECTED_COLOR = "selected_color"
|
||||
}
|
||||
|
||||
private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE)
|
||||
@@ -37,6 +44,26 @@ class AppPreferences(context: Context) {
|
||||
// get() = preferences.getBoolean(USE_PREFERENCES, false)
|
||||
// set(value) { preferences.put(USE_PREFERENCES, value) }
|
||||
|
||||
var firstLaunchTesting: Boolean
|
||||
get() = preferences.getBoolean(FIRST_LAUNCH_TESTING, false)
|
||||
set(value) { preferences.put(FIRST_LAUNCH_TESTING, value) }
|
||||
|
||||
var firstLaunch: Boolean
|
||||
get() = if (BuildConfig.DEBUG) firstLaunchTesting else preferences.getBoolean(FIRST_LAUNCH, true)
|
||||
set(value) { preferences.put(FIRST_LAUNCH, value) }
|
||||
|
||||
var useSystemColors: Boolean
|
||||
get() = preferences.getBoolean(USE_SYSTEM_COLORS, true)
|
||||
set(value) { preferences.put(USE_SYSTEM_COLORS, value) }
|
||||
|
||||
var chromaMultiplier: Double
|
||||
get() = preferences.getFloat(CHROMA_MULTIPLIER, MonetCompat.chromaMultiplier.toFloat()).toDouble()
|
||||
set(value) { preferences.put(CHROMA_MULTIPLIER, value) }
|
||||
|
||||
var selectedColor: Int
|
||||
get() = preferences.getInt(SELECTED_COLOR, Int.MAX_VALUE)
|
||||
set(value) { preferences.put(SELECTED_COLOR, value) }
|
||||
|
||||
private fun SharedPreferences.put(key: String, value: Any?) {
|
||||
edit().apply {
|
||||
when (value) {
|
||||
@@ -44,12 +71,16 @@ class AppPreferences(context: Context) {
|
||||
is Int -> putInt(key, value)
|
||||
is Long -> putLong(key, value)
|
||||
is Float -> putFloat(key, value)
|
||||
is Double -> putFloat(key, value.toFloat())
|
||||
is String -> putString(key, value)
|
||||
else -> throw UnsupportedTypeError()
|
||||
}
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
class UnsupportedTypeError: Exception()
|
||||
|
||||
// private fun <T> SharedPreferences.get(key: String, java: Class<T>): T {
|
||||
//
|
||||
// }
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.owenlejeune.tvtime.ui.components
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.SliderDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -73,4 +75,41 @@ fun SwitchPreference(
|
||||
@Composable
|
||||
private fun SwitchPreferencePreview() {
|
||||
SwitchPreference("Title", true, subtitleText = "Subtitle")
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SliderPreference(
|
||||
modifier: Modifier = Modifier,
|
||||
titleText: String,
|
||||
value: Float,
|
||||
onValueChangeFinished: (Float) -> Unit ,
|
||||
titleTextColor: Color = MaterialTheme.colorScheme.onBackground,
|
||||
disabledTextColor: Color = MaterialTheme.colorScheme.outline,
|
||||
enabled: Boolean = true
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.wrapContentHeight()
|
||||
.padding(all = 8.dp)
|
||||
) {
|
||||
val titleColor = if (enabled) titleTextColor else disabledTextColor
|
||||
Text(text = titleText, style = MaterialTheme.typography.titleLarge, color = titleColor, fontSize = 20.sp)
|
||||
|
||||
var sliderValue by remember { mutableStateOf(value) }
|
||||
|
||||
Slider(
|
||||
modifier = Modifier.fillMaxWidth().padding(start = 8.dp),
|
||||
value = sliderValue,
|
||||
onValueChange = { sliderValue = it },
|
||||
enabled = enabled,
|
||||
valueRange = 0f..100f,
|
||||
onValueChangeFinished = {
|
||||
onValueChangeFinished(sliderValue)
|
||||
},
|
||||
colors = SliderDefaults.colors(
|
||||
thumbColor = MaterialTheme.colorScheme.primary,
|
||||
activeTrackColor = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,7 @@ import androidx.compose.material.Card
|
||||
import androidx.compose.material.OutlinedTextField
|
||||
import androidx.compose.material.TextFieldDefaults
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Error
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Visibility
|
||||
import androidx.compose.material.icons.filled.VisibilityOff
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
@@ -65,6 +62,7 @@ import androidx.core.text.HtmlCompat
|
||||
import coil.compose.AsyncImage
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import com.google.accompanist.flowlayout.FlowRow
|
||||
import com.kieronquinn.monetcompat.core.MonetCompat
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.AuthorDetails
|
||||
import com.owenlejeune.tvtime.ui.theme.RatingSelected
|
||||
@@ -924,4 +922,40 @@ fun TimeoutSnackbar(
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CenteredIconCircle(
|
||||
size: Dp,
|
||||
backgroundColor: Color,
|
||||
iconTint: Color,
|
||||
icon: ImageVector,
|
||||
contentDescription: String?,
|
||||
showIcon: Boolean = true,
|
||||
onClick: () -> Unit = {}
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(size)
|
||||
.clip(CircleShape)
|
||||
.background(color = backgroundColor)
|
||||
.clickable {
|
||||
onClick()
|
||||
}
|
||||
) {
|
||||
if (showIcon) {
|
||||
Column(
|
||||
modifier = Modifier.size(size),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = contentDescription,
|
||||
modifier = Modifier.size(size / 2),
|
||||
tint = iconTint
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.navigation.NavHostController
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.*
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.tabs.bottom.AccountTabContent
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.AccountTabContent
|
||||
import com.owenlejeune.tvtime.utils.ResourceUtils
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import org.koin.core.component.inject
|
||||
|
||||
@@ -5,8 +5,8 @@ import androidx.navigation.NavHostController
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePageResponse
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.tabs.bottom.MediaTabContent
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaTabContent
|
||||
import com.owenlejeune.tvtime.utils.ResourceUtils
|
||||
import org.koin.core.component.inject
|
||||
import retrofit2.Response
|
||||
|
||||
@@ -9,11 +9,9 @@ import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.navArgument
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaDetailView
|
||||
import com.owenlejeune.tvtime.ui.screens.MainAppView
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.PersonDetailView
|
||||
import com.owenlejeune.tvtime.ui.screens.tabs.bottom.*
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaDetailView
|
||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.main.*
|
||||
|
||||
object NavConstants {
|
||||
const val ID_KEY = "id_key"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.tabs.bottom
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.clickable
|
||||
@@ -12,7 +12,6 @@ import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -29,8 +28,7 @@ import com.owenlejeune.tvtime.ui.components.*
|
||||
import com.owenlejeune.tvtime.ui.navigation.AccountTabNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.ListFetchFun
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.tabs.top.ScrollableTabs
|
||||
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.ScrollableTabs
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.tabs.bottom
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import androidx.compose.animation.rememberSplineBasedDecay
|
||||
import androidx.compose.foundation.Image
|
||||
@@ -1,17 +1,13 @@
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.animation.core.LinearOutSlowInEasing
|
||||
import androidx.compose.animation.core.keyframes
|
||||
import androidx.compose.animation.core.spring
|
||||
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.Delete
|
||||
import androidx.compose.material.icons.filled.Send
|
||||
@@ -29,7 +25,6 @@ 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.unit.IntSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavController
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.tabs.bottom
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -16,8 +16,7 @@ import com.owenlejeune.tvtime.ui.components.PosterGrid
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun
|
||||
import com.owenlejeune.tvtime.ui.navigation.MediaTabNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import com.owenlejeune.tvtime.ui.screens.tabs.top.Tabs
|
||||
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.Tabs
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.tabs.bottom
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@@ -14,7 +14,6 @@ import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.PeopleService
|
||||
import com.owenlejeune.tvtime.ui.components.PeoplePosterGrid
|
||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||
import com.owenlejeune.tvtime.ui.screens.MediaViewType
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -0,0 +1,296 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material.icons.filled.ResetTv
|
||||
import androidx.compose.material.icons.filled.RestartAlt
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.Icon
|
||||
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.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.kieronquinn.monetcompat.core.MonetCompat
|
||||
import com.owenlejeune.tvtime.BuildConfig
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.*
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import dev.kdrag0n.monet.factory.ColorSchemeFactory
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.java.KoinJavaComponent.get
|
||||
|
||||
@Composable
|
||||
fun SettingsTab(preferences: AppPreferences = get(AppPreferences::class.java)) {
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(start = 8.dp, top = 8.dp, bottom = 8.dp, end = 24.dp)
|
||||
.verticalScroll(scrollState)
|
||||
) {
|
||||
// val usePreferences = remember { mutableStateOf(preferences.usePreferences) }
|
||||
// TopLevelSwitch(
|
||||
// text = "Enable Preferences",
|
||||
// checkedState = usePreferences,
|
||||
// onCheckChanged = { isChecked ->
|
||||
// usePreferences.value = isChecked
|
||||
// preferences.usePreferences = isChecked
|
||||
// }
|
||||
// )
|
||||
//
|
||||
// Column(
|
||||
// modifier = Modifier
|
||||
// .fillMaxWidth()
|
||||
// .wrapContentHeight()
|
||||
// .padding(start = 8.dp, top = 8.dp, bottom = 8.dp, end = 24.dp)
|
||||
// .verticalScroll()
|
||||
// ) {
|
||||
PreferenceHeading(text = stringResource(R.string.preference_heading_search))
|
||||
|
||||
val persistentSearch = remember { mutableStateOf(preferences.persistentSearch) }
|
||||
SwitchPreference(
|
||||
titleText = stringResource(R.string.preferences_persistent_search_title),
|
||||
subtitleText = stringResource(R.string.preferences_persistent_search_subtitle),
|
||||
checkState = persistentSearch.value,
|
||||
onCheckedChange = { isChecked ->
|
||||
persistentSearch.value = isChecked
|
||||
preferences.persistentSearch = isChecked
|
||||
}
|
||||
)
|
||||
|
||||
val hideTitle = remember { mutableStateOf(preferences.hideTitle) }
|
||||
SwitchPreference(
|
||||
titleText = stringResource(R.string.preferences_hide_heading_title),
|
||||
subtitleText = stringResource(R.string.preferences_hide_heading_subtitle),
|
||||
checkState = hideTitle.value,
|
||||
onCheckedChange = { isChecked ->
|
||||
hideTitle.value = isChecked
|
||||
preferences.hideTitle = isChecked
|
||||
},
|
||||
enabled = persistentSearch.value
|
||||
)
|
||||
|
||||
PreferenceHeading(text = stringResource(id = R.string.preference_heading_design))
|
||||
|
||||
val isSystemColorsSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
|
||||
if (isSystemColorsSupported) {
|
||||
val useSystemColors = remember { mutableStateOf(preferences.useSystemColors) }
|
||||
SwitchPreference(
|
||||
titleText = stringResource(id = R.string.preference_system_colors_heading),
|
||||
checkState = useSystemColors.value,
|
||||
onCheckedChange = { isChecked ->
|
||||
useSystemColors.value = isChecked
|
||||
preferences.useSystemColors = isChecked
|
||||
MonetCompat.useSystemColorsOnAndroid12 = isChecked
|
||||
MonetCompat.getInstance().updateMonetColors()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
SliderPreference(
|
||||
titleText = stringResource(id = R.string.preference_chroma_factor_heading),
|
||||
value = preferences.chromaMultiplier.toFloat() * 50f,
|
||||
onValueChangeFinished = { value ->
|
||||
with((value / 50f).toDouble()) {
|
||||
preferences.chromaMultiplier = this
|
||||
MonetCompat.chromaMultiplier = this
|
||||
}
|
||||
MonetCompat.getInstance().updateMonetColors()
|
||||
},
|
||||
enabled = if (isSystemColorsSupported) !preferences.useSystemColors else true
|
||||
)
|
||||
|
||||
val showWallpaperPicker = remember { mutableStateOf(false) }
|
||||
val wallpaperPickerModifier = if (isSystemColorsSupported && preferences.useSystemColors) {
|
||||
Modifier
|
||||
} else {
|
||||
Modifier.clickable { showWallpaperPicker.value = true }
|
||||
}
|
||||
Text(
|
||||
text = stringResource(id = R.string.preference_wallpaper_color_heading),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
fontSize = 20.sp,
|
||||
color = if (isSystemColorsSupported && preferences.useSystemColors) {
|
||||
MaterialTheme.colorScheme.outline
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onBackground
|
||||
},
|
||||
modifier = wallpaperPickerModifier
|
||||
.padding(start = 8.dp)
|
||||
)
|
||||
if (showWallpaperPicker.value) {
|
||||
WallpaperPicker(showPopup = showWallpaperPicker)
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Divider(modifier = Modifier.padding(start = 8.dp, top = 20.dp))
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 8.dp, top = 20.dp),
|
||||
text = stringResource(R.string.preferences_debug_title),
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
DebugOptions()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WallpaperPicker(
|
||||
showPopup: MutableState<Boolean>,
|
||||
preference: AppPreferences = get(AppPreferences::class.java)
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val wallpaperColors = remember { mutableStateOf<List<Int>>(emptyList()) }
|
||||
val selectedWallpaperColor = remember { mutableStateOf(0) }
|
||||
LaunchedEffect(true) {
|
||||
val colors = MonetCompat.getInstance().getAvailableWallpaperColors() ?: emptyList()
|
||||
if (colors.isEmpty()) {
|
||||
Toast.makeText(context, context.getString(R.string.preference_no_wallpaper_colors), Toast.LENGTH_SHORT).show()
|
||||
showPopup.value = false
|
||||
|
||||
}
|
||||
wallpaperColors.value = colors
|
||||
selectedWallpaperColor.value = MonetCompat.getInstance().getSelectedWallpaperColor() ?: 0
|
||||
}
|
||||
|
||||
if (wallpaperColors.value.isNotEmpty() && selectedWallpaperColor.value != 0) {
|
||||
val colorCircleSize = 50.dp
|
||||
AlertDialog(
|
||||
modifier = Modifier.padding(12.dp),
|
||||
title = { Text(text = stringResource(id = R.string.preference_wallpaper_color_heading)) },
|
||||
text = {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(colorCircleSize)
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly
|
||||
) {
|
||||
wallpaperColors.value.forEach {
|
||||
CenteredIconCircle(
|
||||
size = colorCircleSize,
|
||||
backgroundColor = Color(it),
|
||||
iconTint = Color.White,
|
||||
icon = Icons.Filled.Check,
|
||||
contentDescription = null,
|
||||
showIcon = it == selectedWallpaperColor.value,
|
||||
onClick = {
|
||||
if (it != selectedWallpaperColor.value) {
|
||||
preference.selectedColor = it
|
||||
MonetCompat
|
||||
.getInstance()
|
||||
.updateMonetColors()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
CenteredIconCircle(
|
||||
size = colorCircleSize,
|
||||
backgroundColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||
iconTint = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||
icon = Icons.Filled.RestartAlt,
|
||||
contentDescription = null,
|
||||
onClick = {
|
||||
if (preference.selectedColor != Int.MAX_VALUE) {
|
||||
preference.selectedColor = Int.MAX_VALUE
|
||||
MonetCompat.getInstance().updateMonetColors()
|
||||
} else {
|
||||
Toast.makeText(context, context.getString(R.string.preference_wallpaper_color_default_selected), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showPopup.value = false }) {
|
||||
Text(text = stringResource(id = R.string.action_cancel))
|
||||
}
|
||||
},
|
||||
confirmButton = {},
|
||||
onDismissRequest = { showPopup.value = false }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DebugOptions(preferences: AppPreferences = get(AppPreferences::class.java)) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val firstLaunchTesting = remember { mutableStateOf(preferences.firstLaunchTesting) }
|
||||
SwitchPreference(
|
||||
titleText = "Always show onboarding flow",
|
||||
subtitleText = "Show onboarding flow on each launch",
|
||||
checkState = firstLaunchTesting.value,
|
||||
onCheckedChange = { isChecked ->
|
||||
firstLaunchTesting.value = isChecked
|
||||
preferences.firstLaunchTesting = isChecked
|
||||
}
|
||||
)
|
||||
|
||||
val shouldShowPalette = remember { mutableStateOf(false) }
|
||||
Text(
|
||||
text = "Show material palette",
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp, vertical = 12.dp)
|
||||
.clickable(
|
||||
onClick = {
|
||||
shouldShowPalette.value = true
|
||||
}
|
||||
)
|
||||
)
|
||||
if (shouldShowPalette.value) {
|
||||
AlertDialog(
|
||||
modifier = Modifier.padding(12.dp),
|
||||
title = { Text(text = "Palette") },
|
||||
text = { PaletteView() },
|
||||
dismissButton = {
|
||||
TextButton(onClick = { shouldShowPalette.value = false }) {
|
||||
Text("Dismiss")
|
||||
}
|
||||
},
|
||||
confirmButton = {},
|
||||
onDismissRequest = { shouldShowPalette.value = false }
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = "Clear session",
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp, vertical = 12.dp)
|
||||
.clickable(
|
||||
onClick = {
|
||||
preferences.guestSessionId = ""
|
||||
SessionManager.clearSession {
|
||||
Toast
|
||||
.makeText(context, "Cleared session: $it", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.tabs.top
|
||||
package com.owenlejeune.tvtime.ui.screens.main.tabs.top
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.onboarding
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.owenlejeune.tvtime.R
|
||||
|
||||
sealed class OnboardingPage(
|
||||
@StringRes val title: Int,
|
||||
@StringRes val description: Int,
|
||||
@DrawableRes val image: Int? = null,
|
||||
val additionalContent: @Composable (AppCompatActivity) -> Unit = {}
|
||||
) {
|
||||
|
||||
companion object {
|
||||
fun values() = listOf(ExamplePage)
|
||||
|
||||
operator fun get(i: Int) = values()[i]
|
||||
}
|
||||
|
||||
object ExamplePage: OnboardingPage(
|
||||
R.string.app_name,
|
||||
R.string.example_page_desc,
|
||||
R.drawable.ic_launcher_foreground
|
||||
)
|
||||
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.tabs.bottom
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Switch
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
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.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.owenlejeune.tvtime.BuildConfig
|
||||
import com.owenlejeune.tvtime.R
|
||||
import com.owenlejeune.tvtime.di.modules.preferencesModule
|
||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||
import com.owenlejeune.tvtime.ui.components.*
|
||||
import com.owenlejeune.tvtime.utils.SessionManager
|
||||
import org.koin.java.KoinJavaComponent.get
|
||||
|
||||
@Composable
|
||||
fun SettingsTab(preferences: AppPreferences = get(AppPreferences::class.java)) {
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
Column(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(start = 8.dp, top = 8.dp, bottom = 8.dp, end = 24.dp)
|
||||
.verticalScroll(scrollState)
|
||||
) {
|
||||
// val usePreferences = remember { mutableStateOf(preferences.usePreferences) }
|
||||
// TopLevelSwitch(
|
||||
// text = "Enable Preferences",
|
||||
// checkedState = usePreferences,
|
||||
// onCheckChanged = { isChecked ->
|
||||
// usePreferences.value = isChecked
|
||||
// preferences.usePreferences = isChecked
|
||||
// }
|
||||
// )
|
||||
//
|
||||
// Column(
|
||||
// modifier = Modifier
|
||||
// .fillMaxWidth()
|
||||
// .wrapContentHeight()
|
||||
// .padding(start = 8.dp, top = 8.dp, bottom = 8.dp, end = 24.dp)
|
||||
// .verticalScroll()
|
||||
// ) {
|
||||
PreferenceHeading(text = stringResource(R.string.preference_heading_search))
|
||||
|
||||
val persistentSearch = remember { mutableStateOf(preferences.persistentSearch) }
|
||||
SwitchPreference(
|
||||
titleText = stringResource(R.string.preferences_persistent_search_title),
|
||||
subtitleText = stringResource(R.string.preferences_persistent_search_subtitle),
|
||||
checkState = persistentSearch.value,
|
||||
onCheckedChange = { isChecked ->
|
||||
persistentSearch.value = isChecked
|
||||
preferences.persistentSearch = isChecked
|
||||
}
|
||||
)
|
||||
|
||||
val hideTitle = remember { mutableStateOf(preferences.hideTitle) }
|
||||
SwitchPreference(
|
||||
titleText = stringResource(R.string.preferences_hide_heading_title),
|
||||
subtitleText = stringResource(R.string.preferences_hide_heading_subtitle),
|
||||
checkState = hideTitle.value,
|
||||
onCheckedChange = { isChecked ->
|
||||
hideTitle.value = isChecked
|
||||
preferences.hideTitle = isChecked
|
||||
},
|
||||
enabled = persistentSearch.value
|
||||
)
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 8.dp, top = 20.dp),
|
||||
text = stringResource(R.string.preferences_debug_title),
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
DebugOptions()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DebugOptions(preferences: AppPreferences = get(AppPreferences::class.java)) {
|
||||
val context = LocalContext.current
|
||||
val shouldShowPalette = remember { mutableStateOf(false) }
|
||||
Text(
|
||||
text = "Show material palette",
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp, vertical = 12.dp)
|
||||
.clickable(
|
||||
onClick = {
|
||||
shouldShowPalette.value = true
|
||||
}
|
||||
)
|
||||
)
|
||||
if (shouldShowPalette.value) {
|
||||
PaletteDialog(shouldShowPalette)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = "Clear session",
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp, vertical = 12.dp)
|
||||
.clickable(
|
||||
onClick = {
|
||||
preferences.guestSessionId = ""
|
||||
SessionManager.clearSession {
|
||||
Toast.makeText(context, "Cleared session: $it", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PaletteDialog(showDialog: MutableState<Boolean>) {
|
||||
AlertDialog(
|
||||
modifier = Modifier.padding(12.dp),
|
||||
title = { Text(text = "Palette") },
|
||||
text = { PaletteView() },
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showDialog.value = false }) {
|
||||
Text("Dismiss")
|
||||
}
|
||||
},
|
||||
confirmButton = {},
|
||||
onDismissRequest = { showDialog.value = false }
|
||||
)
|
||||
}
|
||||
@@ -54,6 +54,12 @@
|
||||
<string name="preferences_hide_heading_title">Expanded search bar</string>
|
||||
<string name="preferences_hide_heading_subtitle">Keep search bar expanded at all times</string>
|
||||
<string name="preferences_debug_title">Developer options</string>
|
||||
<string name="preference_heading_design">Design</string>
|
||||
<string name="preference_system_colors_heading">Use system colors</string>
|
||||
<string name="preference_chroma_factor_heading">Saturation</string>
|
||||
<string name="preference_wallpaper_color_heading">Wallpaper Color Picker</string>
|
||||
<string name="preference_no_wallpaper_colors">Unavailable for the current wallpaper or your current settings</string>
|
||||
<string name="preference_wallpaper_color_default_selected">Wallpaper color already set to default</string>
|
||||
|
||||
<!-- video type -->
|
||||
<string name="video_type_clip">Clips</string>
|
||||
@@ -104,4 +110,8 @@
|
||||
|
||||
<!-- intent routes -->
|
||||
<string name="intent_route_auth_return">tvtime.auth.return</string>
|
||||
|
||||
<!-- onboarding -->
|
||||
<string name="get_started">Get started</string>
|
||||
<string name="example_page_desc">This is an example</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user