Skip to content

Commit

Permalink
Merge pull request #196 from WideChat/ear_shailesh_dynamicLink
Browse files Browse the repository at this point in the history
Add dynamic link to the invite via another app [originally from Shailesh PR 191]
  • Loading branch information
ear-dev authored Jan 28, 2019
2 parents bde37df + ced393b commit 1237a49
Show file tree
Hide file tree
Showing 31 changed files with 454 additions and 185 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ dependencies {
playImplementation libraries.playServicesAuth
playImplementation('com.crashlytics.sdk.android:crashlytics:2.9.5@aar') { transitive = true }
playImplementation('com.crashlytics.sdk.android:answers:1.4.3@aar') { transitive = true }
playImplementation libraries.dynamiclinks

testImplementation libraries.junit
testImplementation libraries.truth
Expand Down
2 changes: 1 addition & 1 deletion app/google-services.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@
}
],
"configuration_version": "1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package chat.rocket.android.dynamiclinks

import android.content.Context
import android.content.Intent
import android.net.Uri
import javax.inject.Inject

class DynamicLinksForFirebase @Inject constructor(private val context: Context) : DynamicLinks {

override fun getDynamicLink(intent: Intent, deepLinkCallback: (Uri?) -> Unit? ) {
deepLinkCallback(null)
}

override fun createDynamicLink(username: String, server: String, deepLinkCallback: (String?) -> Unit?) {
deepLinkCallback(null)
}
}
11 changes: 4 additions & 7 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<activity
android:name=".authentication.ui.AuthenticationActivity"
android:configChanges="orientation"
android:launchMode="singleInstance"
android:screenOrientation="portrait"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize">
Expand All @@ -41,13 +42,9 @@
<category android:name="android.intent.category.DEFAULT" />

<data
android:host="auth"
android:scheme="rocketchat" />

<data
android:host="go.rocket.chat"
android:path="/auth"
android:host="viasatconnect.page.link"
android:scheme="https" />

</intent-filter>
</activity>

Expand All @@ -58,7 +55,7 @@
<activity
android:name=".main.ui.MainActivity"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"/>

<activity
android:name=".webview.ui.WebViewActivity"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package chat.rocket.android.authentication.domain.model

import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
import timber.log.Timber

// see https://rocket.chat/docs/developer-guides/deeplink/ for documentation

@SuppressLint("ParcelCreator")
@Parcelize
data class DeepLinkInfo(
val url: String,
val userId: String?,
val token: String?,
val rid: String?,
val roomType: String?,
val roomName: String?
) : Parcelable

fun Uri.getDeepLinkInfo(): DeepLinkInfo? {
return if (isAuthenticationDeepLink()) {
val host = getQueryParameter("host")
val url = if (host.startsWith("http")) host else "https://$host"
val userId = getQueryParameter("userId")
val token = getQueryParameter("token")
try {
DeepLinkInfo(url, userId, token, null, null, null)
} catch (ex: Exception) {
Timber.d(ex, "Error parsing auth deeplink")
null
}
} else if (isCustomSchemeRoomLink()) {
val hostValue = getQueryParameter("host")
val url = if (hostValue.startsWith("http")) hostValue else "https://$hostValue"
val rid = getQueryParameter("rid")
val pathValue = getQueryParameter("path")
val pathSplit = pathValue.split("/")
val roomType = pathSplit[0]
val roomName = pathSplit[1]
try {
DeepLinkInfo(url, null, null, rid, roomType, roomName)
} catch (ex: Exception) {
Timber.d(ex, "Error parsing custom scheme room link")
null
}
} else if (isWebSchemeRoomLink()) {
val url = "https://$host"
val pathSplit = path.split("/")
val roomType = pathSplit[1]
val roomName = pathSplit[2]
try {
DeepLinkInfo(url, null, null, null, roomType, roomName)
} catch (ex: Exception) {
Timber.d(ex, "Error parsing login deeplink")
null
}
} else null
}

fun Intent.isSupportedLink(): Boolean {
return (action == Intent.ACTION_VIEW && data != null &&
(data.isDynamicLink() || data.isAuthenticationDeepLink() ||
data.isCustomSchemeRoomLink() || data.isWebSchemeRoomLink()))
}

fun Uri.isDynamicLink(): Boolean {
return (host != null && host.contains("page.link", ignoreCase = true))
}

// Authentication deep link defined here: https://rocket.chat/docs/developer-guides/deeplink/#authentication
private inline fun Uri.isAuthenticationDeepLink(): Boolean {
if (host == "auth")
return true
else if (host == "go.rocket.chat" && path == "/auth")
return true
return false
}

// Custom scheme room deep link defined here: https://rocket.chat/docs/developer-guides/deeplink/#channel--group--dm
private inline fun Uri.isCustomSchemeRoomLink(): Boolean {
if (scheme.startsWith("rocketchat") &&
host == "room")
return true
return false
}

// http(s) scheme deep link not yet documented. Ex: https://viasatconnect.com/direct/testuser1
private inline fun Uri.isWebSchemeRoomLink(): Boolean {
val roomType = path.split("/")[1]
if (scheme.startsWith("http") &&
(roomType == "channel" || roomType == "group" || roomType == "direct"))
return true
return false
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package chat.rocket.android.authentication.loginoptions.presentation

import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.AuthenticationEvent
import chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import chat.rocket.android.authentication.domain.model.DeepLinkInfo
import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.infrastructure.LocalRepository
Expand Down Expand Up @@ -89,7 +89,7 @@ class LoginOptionsPresenter @Inject constructor(
doAuthentication(TYPE_LOGIN_SAML)
}

fun authenticateWithDeepLink(deepLinkInfo: LoginDeepLinkInfo) {
fun authenticateWithDeepLink(deepLinkInfo: DeepLinkInfo) {
val serverUrl = deepLinkInfo.url
setupConnectionInfo(serverUrl)
if (deepLinkInfo.userId != null && deepLinkInfo.token != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import androidx.fragment.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import chat.rocket.android.authentication.domain.model.DeepLinkInfo
import chat.rocket.android.authentication.loginoptions.presentation.LoginOptionsPresenter
import chat.rocket.android.authentication.loginoptions.presentation.LoginOptionsView
import chat.rocket.android.authentication.ui.AuthenticationActivity
Expand Down Expand Up @@ -59,7 +59,6 @@ private const val SAML_SERVICE_BUTTON_COLOR = "saml_service_button_color"
private const val TOTAL_SOCIAL_ACCOUNTS = "total_social_accounts"
private const val IS_LOGIN_FORM_ENABLED = "is_login_form_enabled"
private const val IS_NEW_ACCOUNT_CREATION_ENABLED = "is_new_account_creation_enabled"
private const val DEEP_LINK_INFO = "deep-link-info"

internal const val REQUEST_CODE_FOR_OAUTH = 1
internal const val REQUEST_CODE_FOR_CAS = 2
Expand Down Expand Up @@ -91,7 +90,7 @@ fun newInstance(
totalSocialAccountsEnabled: Int = 0,
isLoginFormEnabled: Boolean,
isNewAccountCreationEnabled: Boolean,
deepLinkInfo: LoginDeepLinkInfo? = null
deepLinkInfo: DeepLinkInfo? = null
): Fragment {
return LoginOptionsFragment().apply {
arguments = Bundle(23).apply {
Expand Down Expand Up @@ -120,7 +119,7 @@ fun newInstance(
putInt(TOTAL_SOCIAL_ACCOUNTS, totalSocialAccountsEnabled)
putBoolean(IS_LOGIN_FORM_ENABLED, isLoginFormEnabled)
putBoolean(IS_NEW_ACCOUNT_CREATION_ENABLED, isNewAccountCreationEnabled)
putParcelable(DEEP_LINK_INFO, deepLinkInfo)
putParcelable(Constants.DEEP_LINK_INFO, deepLinkInfo)
}
}
}
Expand Down Expand Up @@ -155,7 +154,7 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
private var totalSocialAccountsEnabled = 0
private var isLoginFormEnabled = false
private var isNewAccountCreationEnabled = false
private var deepLinkInfo: LoginDeepLinkInfo? = null
private var deepLinkInfo: DeepLinkInfo? = null

// WIDECHAT - replace the RC login screen with our welcome and login buttons view
private var auth_fragment: Int = R.layout.fragment_authentication_widechat_login_options
Expand Down Expand Up @@ -195,7 +194,7 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
totalSocialAccountsEnabled = bundle.getInt(TOTAL_SOCIAL_ACCOUNTS)
isLoginFormEnabled = bundle.getBoolean(IS_LOGIN_FORM_ENABLED)
isNewAccountCreationEnabled = bundle.getBoolean(IS_NEW_ACCOUNT_CREATION_ENABLED)
deepLinkInfo = bundle.getParcelable(DEEP_LINK_INFO)
deepLinkInfo = bundle.getParcelable(Constants.DEEP_LINK_INFO)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,30 @@ package chat.rocket.android.authentication.presentation
import android.content.Intent
import chat.rocket.android.R
import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import chat.rocket.android.authentication.domain.model.DeepLinkInfo
import chat.rocket.android.authentication.ui.AuthenticationActivity
import chat.rocket.android.helper.Constants
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.server.ui.changeServerIntent
import chat.rocket.android.util.extensions.addFragmentBackStack
import chat.rocket.android.util.extensions.toPreviousView
import chat.rocket.android.webview.ui.webViewIntent
import chat.rocket.common.util.ifNull

class AuthenticationNavigator(internal val activity: AuthenticationActivity) {
public var savedDeepLinkInfo: DeepLinkInfo? = null

fun toSignInToYourServer() {
fun saveDeepLinkInfo(deepLinkInfo: DeepLinkInfo) {
savedDeepLinkInfo = deepLinkInfo
}
fun toOnBoarding() {
activity.addFragmentBackStack(ScreenViewEvent.OnBoarding.screenName, R.id.fragment_container) {
chat.rocket.android.authentication.onboarding.ui.newInstance()
}
}
fun toSignInToYourServer(deepLinkInfo: DeepLinkInfo? = null) {
activity.addFragmentBackStack(ScreenViewEvent.Server.screenName, R.id.fragment_container) {
chat.rocket.android.authentication.server.ui.newInstance()
chat.rocket.android.authentication.server.ui.newInstance(deepLinkInfo)
}
}

Expand Down Expand Up @@ -45,7 +56,7 @@ class AuthenticationNavigator(internal val activity: AuthenticationActivity) {
totalSocialAccountsEnabled: Int = 0,
isLoginFormEnabled: Boolean = true,
isNewAccountCreationEnabled: Boolean = true,
deepLinkInfo: LoginDeepLinkInfo? = null
deepLinkInfo: DeepLinkInfo? = null
) {
activity.addFragmentBackStack(
ScreenViewEvent.LoginOptions.screenName,
Expand Down Expand Up @@ -127,13 +138,23 @@ class AuthenticationNavigator(internal val activity: AuthenticationActivity) {
activity.overridePendingTransition(R.anim.slide_up, R.anim.hold)
}

fun toChatList() {
activity.startActivity(Intent(activity, MainActivity::class.java))
fun toChatList(serverUrl: String) {
activity.startActivity(activity.changeServerIntent(serverUrl))
activity.finish()
}

fun toChatList(serverUrl: String) {
activity.startActivity(activity.changeServerIntent(serverUrl))
fun toChatList(passedDeepLinkInfo: DeepLinkInfo? = null) {
val deepLinkInfo = if (passedDeepLinkInfo != null) passedDeepLinkInfo else savedDeepLinkInfo
savedDeepLinkInfo = null

if (deepLinkInfo != null) {
activity.startActivity(Intent(activity, MainActivity::class.java).also {
it.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
it.putExtra(Constants.DEEP_LINK_INFO, deepLinkInfo)
})
} else {
activity.startActivity(Intent(activity, MainActivity::class.java))
}
activity.finish()
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package chat.rocket.android.authentication.presentation

import chat.rocket.android.authentication.domain.model.DeepLinkInfo
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.GetAccountInteractor
Expand Down Expand Up @@ -52,5 +53,9 @@ class AuthenticationPresenter @Inject constructor(
fun privacyPolicy(toolbarTitle: String) =
serverInteractor.get()?.let { navigator.toWebPage(it.privacyPolicyUrl(), toolbarTitle) }

fun saveDeepLinkInfo(deepLinkInfo: DeepLinkInfo) = navigator.saveDeepLinkInfo(deepLinkInfo)
fun toOnBoarding() = navigator.toOnBoarding()
fun toSignInToYourServer(deepLinkInfo: DeepLinkInfo? = null) = navigator.toSignInToYourServer(deepLinkInfo)
fun toChatList() = navigator.toChatList()
fun toChatList(deepLinkInfo: DeepLinkInfo) = navigator.toChatList(deepLinkInfo)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package chat.rocket.android.authentication.server.presentation

import chat.rocket.android.authentication.domain.model.LoginDeepLinkInfo
import chat.rocket.android.authentication.domain.model.DeepLinkInfo
import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.core.behaviours.showMessage
import chat.rocket.android.core.lifecycle.CancelStrategy
Expand Down Expand Up @@ -79,7 +79,7 @@ class ServerPresenter @Inject constructor(
}
}

fun deepLink(deepLinkInfo: LoginDeepLinkInfo) {
fun deepLink(deepLinkInfo: DeepLinkInfo) {
connectToServer(deepLinkInfo.url) {
navigator.toLoginOptions(deepLinkInfo.url, deepLinkInfo = deepLinkInfo)
}
Expand Down
Loading

0 comments on commit 1237a49

Please sign in to comment.