mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-08 12:42:44 -05:00
move auth to internal webview
This commit is contained in:
@@ -90,6 +90,7 @@ dependencies {
|
||||
implementation "androidx.paging:paging-compose:$compose_paging"
|
||||
implementation "androidx.constraintlayout:constraintlayout-compose:$compose_constraint_layout"
|
||||
implementation "androidx.paging:paging-compose:$compose_paging"
|
||||
implementation "com.google.accompanist:accompanist-webview:0.28.0"
|
||||
|
||||
// material you
|
||||
def monet_compat = "0.4.1"
|
||||
@@ -124,10 +125,10 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
||||
|
||||
// youtube player
|
||||
def player_core = "11.0.1"
|
||||
def chromecast_sender = "0.26"
|
||||
implementation "com.pierfrancescosoffritti.androidyoutubeplayer:core:$player_core"
|
||||
implementation "com.pierfrancescosoffritti.androidyoutubeplayer:chromecast-sender:$chromecast_sender"
|
||||
// def player_core = "11.0.1"
|
||||
// def chromecast_sender = "0.26"
|
||||
// implementation "com.pierfrancescosoffritti.androidyoutubeplayer:core:$player_core"
|
||||
// implementation "com.pierfrancescosoffritti.androidyoutubeplayer:chromecast-sender:$chromecast_sender"
|
||||
|
||||
// markdown
|
||||
def markdown = "0.2.1"
|
||||
|
||||
@@ -446,6 +446,17 @@ class MainActivity : MonetCompatActivity() {
|
||||
)
|
||||
}
|
||||
}
|
||||
composable(
|
||||
route = MainNavItem.WebLinkView.route.plus("/{${NavConstants.WEB_LINK_KEY}}"),
|
||||
arguments = listOf(
|
||||
navArgument(NavConstants.WEB_LINK_KEY) { type = NavType.StringType }
|
||||
)
|
||||
) {
|
||||
val url = it.arguments?.getString(NavConstants.WEB_LINK_KEY)
|
||||
url?.let {
|
||||
WebLinkView(url = url, appNavController = appNavController)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,5 +10,6 @@ sealed class MainNavItem(val route: String) {
|
||||
object DetailView: MainNavItem("detail_route")
|
||||
object SettingsView: MainNavItem("settings_route")
|
||||
object SearchView: MainNavItem("search_route")
|
||||
object WebLinkView: MainNavItem("web_link_route")
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
@@ -8,9 +7,11 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountCircle
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
@@ -56,11 +57,17 @@ fun AccountTab(
|
||||
val currentSessionState = remember { SessionManager.currentSession }
|
||||
val currentSession = currentSessionState.value
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
if (currentSession?.isAuthorized == false) {
|
||||
appBarTitle.value = stringResource(id = R.string.account_not_logged_in)
|
||||
if (doSignInPartTwo) {
|
||||
AccountLoadingView()
|
||||
signInPart2()
|
||||
LaunchedEffect(Unit) {
|
||||
scope.launch {
|
||||
SessionManager.singInPart2()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (currentSession?.isAuthorized == true) {
|
||||
@@ -76,7 +83,8 @@ fun AccountTab(
|
||||
|
||||
appBarActions.value = {
|
||||
AccountDropdownMenu(
|
||||
session = currentSession
|
||||
session = currentSession,
|
||||
appNavController = appNavController
|
||||
)
|
||||
}
|
||||
|
||||
@@ -285,7 +293,7 @@ private fun MediaItemRow(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AccountDropdownMenu(session: SessionManager.Session?) {
|
||||
private fun AccountDropdownMenu(session: SessionManager.Session?, appNavController: NavHostController) {
|
||||
val expanded = remember { mutableStateOf(false) }
|
||||
|
||||
IconButton(
|
||||
@@ -301,7 +309,7 @@ private fun AccountDropdownMenu(session: SessionManager.Session?) {
|
||||
if(session?.isAuthorized == true) {
|
||||
AuthorizedSessionMenuItems(expanded = expanded)
|
||||
} else {
|
||||
NoSessionMenuItems(expanded = expanded)
|
||||
NoSessionMenuItems(expanded = expanded, appNavController = appNavController)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -318,29 +326,21 @@ private fun AuthorizedSessionMenuItems(expanded: MutableState<Boolean>) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NoSessionMenuItems(expanded: MutableState<Boolean>) {
|
||||
private fun NoSessionMenuItems(expanded: MutableState<Boolean>, appNavController: NavHostController) {
|
||||
val context = LocalContext.current
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(id = R.string.action_sign_in)) },
|
||||
onClick = {
|
||||
signInPart1(context)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
SessionManager.signInPart1(context) {
|
||||
appNavController.navigate(MainNavItem.WebLinkView.route.plus("/$it"))
|
||||
}
|
||||
}
|
||||
expanded.value = false
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun signInPart1(context: Context) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
SessionManager.signInPart1(context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun signInPart2() {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
SessionManager.singInPart2()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AuthorizedSessionIcon() {
|
||||
val accountDetails = SessionManager.currentSession.value?.accountDetails?.value
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.owenlejeune.tvtime.ui.screens.main
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebSettings
|
||||
import android.webkit.WebView
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
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.Scaffold
|
||||
import androidx.compose.material3.SmallTopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavController
|
||||
import com.google.accompanist.web.AccompanistWebViewClient
|
||||
import com.google.accompanist.web.WebView
|
||||
import com.google.accompanist.web.rememberWebViewState
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun WebLinkView(
|
||||
url: String,
|
||||
appNavController: NavController
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
SmallTopAppBar(
|
||||
title = {},
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = { appNavController.popBackStack() }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Close,
|
||||
contentDescription = "Close"
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) {
|
||||
Box(modifier = Modifier.padding(it)) {
|
||||
val webViewState = rememberWebViewState(url = url)
|
||||
WebView(
|
||||
state = webViewState,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
client = MYmdbWebClient(),
|
||||
onCreated = {
|
||||
it.settings.javaScriptCanOpenWindowsAutomatically = true
|
||||
it.settings.useWideViewPort = false
|
||||
it.settings.allowContentAccess = true
|
||||
it.settings.blockNetworkImage = false
|
||||
it.settings.blockNetworkLoads = false
|
||||
it.settings.loadsImagesAutomatically = true
|
||||
it.clipToOutline = false
|
||||
it.isNestedScrollingEnabled = true
|
||||
it.settings.displayZoomControls = true
|
||||
it.settings.setSupportZoom(true)
|
||||
it.settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL
|
||||
it.isVerticalScrollBarEnabled = true
|
||||
it.isHorizontalScrollBarEnabled = true
|
||||
it.settings.domStorageEnabled = true
|
||||
it.settings.databaseEnabled = true
|
||||
it.settings.javaScriptEnabled = true
|
||||
it.settings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
|
||||
it.setLayerType(View.LAYER_TYPE_HARDWARE,null)
|
||||
it.postInvalidate()
|
||||
it.isClickable = true
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MYmdbWebClient: AccompanistWebViewClient(), KoinComponent {
|
||||
|
||||
private val context: Context by inject()
|
||||
|
||||
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
|
||||
if (request?.url.toString().contains("tvtime")) {
|
||||
val uri = request!!.url
|
||||
val intent = Intent(Intent.ACTION_VIEW, uri).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
context.startActivity(intent)
|
||||
return true
|
||||
}
|
||||
return super.shouldOverrideUrlLoading(view, request)
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class ItemMoveCallback(private val mAdapter: ItemTouchHelperContract): ItemTouch
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
mAdapter.onRowMoved(viewHolder.bindingAdapterPosition, target.bindingAdapterPosition)
|
||||
mAdapter.onRowMoved(viewHolder.adapterPosition, target.adapterPosition)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -8,4 +8,5 @@ object NavConstants {
|
||||
const val SEARCH_TITLE_KEY = "search_title_key"
|
||||
const val ACCOUNT_KEY = "account_key"
|
||||
const val AUTH_REDIRECT_PAGE = "return"
|
||||
const val WEB_LINK_KEY = "web_link_key"
|
||||
}
|
||||
@@ -27,6 +27,8 @@ import kotlinx.coroutines.withContext
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import org.koin.java.KoinJavaComponent.get
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
object SessionManager: KoinComponent {
|
||||
|
||||
@@ -69,19 +71,20 @@ object SessionManager: KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun signInPart1(context: Context) {
|
||||
suspend fun signInPart1(
|
||||
context: Context,
|
||||
onRedirect: (url: String) -> Unit
|
||||
) {
|
||||
val service = AuthenticationV4Service()
|
||||
val requestTokenResponse = service.createRequestToken(AuthRequestBody(redirect = "app://tvtime.auth.return"))
|
||||
if (requestTokenResponse.isSuccessful) {
|
||||
requestTokenResponse.body()?.let { ctr ->
|
||||
currentSession.value = InProgressSession(ctr.requestToken)
|
||||
val browserIntent = Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse(
|
||||
context.getString(R.string.tmdb_auth_url, ctr.requestToken)
|
||||
)
|
||||
)
|
||||
context.startActivity(browserIntent)
|
||||
val url = context.getString(R.string.tmdb_auth_url, ctr.requestToken)
|
||||
val encodedUrl = URLEncoder.encode(url, StandardCharsets.UTF_8.toString())
|
||||
withContext(Dispatchers.Main) {
|
||||
onRedirect(encodedUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user