Create sub packages.
This commit is contained in:
parent
4c9bed9d8a
commit
d33fbaf89f
15 changed files with 58 additions and 32 deletions
|
|
@ -29,8 +29,9 @@ import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.features.login.impl.changeserver.ChangeServerNode
|
import io.element.android.features.login.impl.changeserver.ChangeServerNode
|
||||||
import io.element.android.features.login.impl.oidc.CustomTabHandler
|
import io.element.android.features.login.impl.oidc.CustomTabAvailabilityChecker
|
||||||
import io.element.android.features.login.impl.oidc.OidcNode
|
import io.element.android.features.login.impl.oidc.customtab.CustomTabHandler
|
||||||
|
import io.element.android.features.login.impl.oidc.webview.OidcNode
|
||||||
import io.element.android.features.login.impl.root.LoginRootNode
|
import io.element.android.features.login.impl.root.LoginRootNode
|
||||||
import io.element.android.libraries.architecture.BackstackNode
|
import io.element.android.libraries.architecture.BackstackNode
|
||||||
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
|
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
|
||||||
|
|
@ -43,6 +44,7 @@ import kotlinx.parcelize.Parcelize
|
||||||
class LoginFlowNode @AssistedInject constructor(
|
class LoginFlowNode @AssistedInject constructor(
|
||||||
@Assisted buildContext: BuildContext,
|
@Assisted buildContext: BuildContext,
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
|
private val customTabAvailabilityChecker: CustomTabAvailabilityChecker,
|
||||||
private val customTabHandler: CustomTabHandler,
|
private val customTabHandler: CustomTabHandler,
|
||||||
) : BackstackNode<LoginFlowNode.NavTarget>(
|
) : BackstackNode<LoginFlowNode.NavTarget>(
|
||||||
backstack = BackStack(
|
backstack = BackStack(
|
||||||
|
|
@ -72,7 +74,8 @@ class LoginFlowNode @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOidcDetails(oidcDetails: OidcDetails) {
|
override fun onOidcDetails(oidcDetails: OidcDetails) {
|
||||||
if (customTabHandler.supportCustomTab()) {
|
if (customTabAvailabilityChecker.supportCustomTab()) {
|
||||||
|
// In this case open a Chrome Custom tab
|
||||||
customTabHandler.open(oidcDetails.url)
|
customTabHandler.open(oidcDetails.url)
|
||||||
} else {
|
} else {
|
||||||
// Fallback to WebView mode
|
// Fallback to WebView mode
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.login.impl.oidc
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.browser.customtabs.CustomTabsClient
|
||||||
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class CustomTabAvailabilityChecker @Inject constructor(
|
||||||
|
@ApplicationContext private val context: Context,
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Return true if the device supports Custom tab, i.e. there is an third party app with
|
||||||
|
* CustomTab support (ex: Chrome, Firefox, etc.).
|
||||||
|
*/
|
||||||
|
fun supportCustomTab(): Boolean {
|
||||||
|
val packageName = CustomTabsClient.getPackageName(context, null)
|
||||||
|
return packageName != null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc
|
package io.element.android.features.login.impl.oidc.customtab
|
||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
@ -22,7 +22,6 @@ import android.net.Uri
|
||||||
import androidx.browser.customtabs.CustomTabsClient
|
import androidx.browser.customtabs.CustomTabsClient
|
||||||
import androidx.browser.customtabs.CustomTabsServiceConnection
|
import androidx.browser.customtabs.CustomTabsServiceConnection
|
||||||
import androidx.browser.customtabs.CustomTabsSession
|
import androidx.browser.customtabs.CustomTabsSession
|
||||||
import io.element.android.features.login.impl.oidc.web.openUrlInChromeCustomTab
|
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -33,15 +32,6 @@ class CustomTabHandler @Inject constructor(
|
||||||
private var customTabsClient: CustomTabsClient? = null
|
private var customTabsClient: CustomTabsClient? = null
|
||||||
private var customTabsServiceConnection: CustomTabsServiceConnection? = null
|
private var customTabsServiceConnection: CustomTabsServiceConnection? = null
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if the device supports Custom tab, i.e. there is an third party app with
|
|
||||||
* CustomTab support (ex: Chrome, Firefox, etc.).
|
|
||||||
*/
|
|
||||||
fun supportCustomTab(): Boolean {
|
|
||||||
val packageName = CustomTabsClient.getPackageName(context, null)
|
|
||||||
return packageName != null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun prepareCustomTab(url: String) {
|
fun prepareCustomTab(url: String) {
|
||||||
val packageName = CustomTabsClient.getPackageName(context, null)
|
val packageName = CustomTabsClient.getPackageName(context, null)
|
||||||
|
|
||||||
|
|
@ -82,6 +72,6 @@ class CustomTabHandler @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun open(url: String) {
|
fun open(url: String) {
|
||||||
openUrlInChromeCustomTab(context, customTabsSession, false, url)
|
context.openUrlInChromeCustomTab(customTabsSession, false, url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc.web
|
package io.element.android.features.login.impl.oidc.customtab
|
||||||
|
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.features.login.api.oidc.OidcAction
|
import io.element.android.features.login.api.oidc.OidcAction
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc.web
|
package io.element.android.features.login.impl.oidc.customtab
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
@ -29,8 +29,7 @@ import androidx.browser.customtabs.CustomTabsSession
|
||||||
* If several compatible browsers are installed, the user will be proposed to choose one.
|
* If several compatible browsers are installed, the user will be proposed to choose one.
|
||||||
* Ref: https://developer.chrome.com/multidevice/android/customtabs.
|
* Ref: https://developer.chrome.com/multidevice/android/customtabs.
|
||||||
*/
|
*/
|
||||||
fun openUrlInChromeCustomTab(
|
fun Context.openUrlInChromeCustomTab(
|
||||||
context: Context,
|
|
||||||
session: CustomTabsSession?,
|
session: CustomTabsSession?,
|
||||||
darkTheme: Boolean,
|
darkTheme: Boolean,
|
||||||
url: String
|
url: String
|
||||||
|
|
@ -58,7 +57,7 @@ fun openUrlInChromeCustomTab(
|
||||||
.apply {
|
.apply {
|
||||||
intent.flags += Intent.FLAG_ACTIVITY_NEW_TASK
|
intent.flags += Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
}
|
}
|
||||||
.launchUrl(context, Uri.parse(url))
|
.launchUrl(this, Uri.parse(url))
|
||||||
} catch (activityNotFoundException: ActivityNotFoundException) {
|
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||||
// TODO context.toast(R.string.error_no_external_application_found)
|
// TODO context.toast(R.string.error_no_external_application_found)
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc
|
package io.element.android.features.login.impl.oidc.webview
|
||||||
|
|
||||||
import io.element.android.features.login.api.oidc.OidcAction
|
import io.element.android.features.login.api.oidc.OidcAction
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc
|
package io.element.android.features.login.impl.oidc.webview
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc
|
package io.element.android.features.login.impl.oidc.webview
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc
|
package io.element.android.features.login.impl.oidc.webview
|
||||||
|
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.matrix.api.auth.OidcDetails
|
import io.element.android.libraries.matrix.api.auth.OidcDetails
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc
|
package io.element.android.features.login.impl.oidc.webview
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc
|
package io.element.android.features.login.impl.oidc.webview
|
||||||
|
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
|
|
@ -27,9 +27,9 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.viewinterop.AndroidView
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
|
import io.element.android.features.login.impl.oidc.OidcUrlParser
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.core.bool.orFalse
|
import io.element.android.libraries.core.bool.orFalse
|
||||||
import io.element.android.libraries.core.bool.orTrue
|
|
||||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc
|
package io.element.android.features.login.impl.oidc.webview
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
|
@ -23,7 +23,6 @@ import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
// TODO Move to a dedicated module
|
|
||||||
class OidcWebViewClient(private val eventListener: WebViewEventListener) : WebViewClient() {
|
class OidcWebViewClient(private val eventListener: WebViewEventListener) : WebViewClient() {
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
@TargetApi(Build.VERSION_CODES.N)
|
||||||
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
|
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc
|
package io.element.android.features.login.impl.oidc.webview
|
||||||
|
|
||||||
interface WebViewEventListener {
|
interface WebViewEventListener {
|
||||||
/**
|
/**
|
||||||
|
|
@ -25,7 +25,7 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import io.element.android.features.login.api.oidc.OidcAction
|
import io.element.android.features.login.api.oidc.OidcAction
|
||||||
import io.element.android.features.login.impl.oidc.web.DefaultOidcActionFlow
|
import io.element.android.features.login.impl.oidc.customtab.DefaultOidcActionFlow
|
||||||
import io.element.android.features.login.impl.util.LoginConstants
|
import io.element.android.features.login.impl.util.LoginConstants
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
|
||||||
package io.element.android.features.login.impl.oidc
|
package io.element.android.features.login.impl.oidc.webview
|
||||||
|
|
||||||
import app.cash.molecule.RecompositionClock
|
import app.cash.molecule.RecompositionClock
|
||||||
import app.cash.molecule.moleculeFlow
|
import app.cash.molecule.moleculeFlow
|
||||||
Loading…
Add table
Add a link
Reference in a new issue