Commit a6877b4e authored by Filipe de Lima Brito's avatar Filipe de Lima Brito

Updates the ServerFragment

parent 62253b1f
......@@ -23,4 +23,5 @@ sealed class ScreenViewEvent(val screenName: String) {
object Settings : ScreenViewEvent("SettingsFragment")
object SignUp : ScreenViewEvent("SignupFragment")
object TwoFa : ScreenViewEvent("TwoFAFragment")
object OnBoarding : ScreenViewEvent("OnBoardingFragment")
}
......@@ -7,6 +7,8 @@ import android.view.ViewGroup
import androidx.core.view.isVisible
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.getLoginDeepLinkInfo
import chat.rocket.android.authentication.onboarding.presentation.OnBoardingPresenter
import chat.rocket.android.authentication.onboarding.presentation.OnBoardingView
......@@ -23,6 +25,8 @@ import javax.inject.Inject
class OnBoardingFragment : Fragment(), OnBoardingView {
@Inject
lateinit var presenter: OnBoardingPresenter
@Inject
lateinit var analyticsManager: AnalyticsManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
......@@ -38,6 +42,8 @@ class OnBoardingFragment : Fragment(), OnBoardingView {
super.onViewCreated(view, savedInstanceState)
setupToobar()
setupOnClickListener()
analyticsManager.logScreenView(ScreenViewEvent.OnBoarding)
}
private fun setupToobar() {
......
......@@ -9,8 +9,8 @@ import chat.rocket.android.server.domain.RefreshSettingsInteractor
import chat.rocket.android.server.domain.SaveConnectingServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.server.presentation.CheckServerPresenter
import chat.rocket.android.util.extensions.isValidUrl
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.isValidUrl
import javax.inject.Inject
class ServerPresenter @Inject constructor(
......@@ -33,10 +33,7 @@ class ServerPresenter @Inject constructor(
}
fun connect(server: String) {
//code that leads to login screen (smart lock will be implemented after this)
connectToServer(server) {
navigator.toLoginOptions(server)
}
connectToServer(server) { navigator.toLoginOptions(server) }
}
private fun connectToServer(server: String, block: () -> Unit) {
......@@ -66,9 +63,6 @@ class ServerPresenter @Inject constructor(
}
fun deepLink(deepLinkInfo: LoginDeepLinkInfo) {
//code that leads to login screen (smart lock will be implemented after this)
connectToServer(deepLinkInfo.url) {
navigator.toLogin(deepLinkInfo)
}
connectToServer(deepLinkInfo.url) { navigator.toLogin(deepLinkInfo) }
}
}
\ No newline at end of file
......@@ -9,4 +9,15 @@ interface ServerView : LoadingView, MessageView, VersionCheckView {
* Shows an invalid server URL message.
*/
fun showInvalidServerUrlMessage()
/**
* Enables the button to connect to the server when the user inputs a valid url.
*/
fun enableButtonConnect()
/**
* Disables the button to connect to the server when the server address entered by the user
* is not a valid url.
*/
fun disableButtonConnect()
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ package chat.rocket.android.authentication.server.presentation
import okhttp3.HttpUrl
interface VersionCheckView {
/**
* Alerts the user about the server version not meeting the recommended server version.
*/
......
package chat.rocket.android.authentication.server.ui
import android.app.AlertDialog
import android.net.Uri
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
......@@ -9,6 +8,9 @@ import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import chat.rocket.android.BuildConfig
......@@ -20,20 +22,23 @@ import chat.rocket.android.authentication.server.presentation.ServerPresenter
import chat.rocket.android.authentication.server.presentation.ServerView
import chat.rocket.android.authentication.ui.AuthenticationActivity
import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.util.extension.asObservable
import chat.rocket.android.util.extensions.hintContent
import chat.rocket.android.util.extensions.ifEmpty
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.isValidUrl
import chat.rocket.android.util.extensions.sanitize
import chat.rocket.android.util.extensions.setLightStatusBar
import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui
import chat.rocket.common.util.ifNull
import dagger.android.support.AndroidSupportInjection
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.app_bar_chat_room.*
import kotlinx.android.synthetic.main.fragment_authentication_server.*
import okhttp3.HttpUrl
import java.util.concurrent.TimeUnit
import javax.inject.Inject
internal const val TAG_SERVER_FRAGMENT = "ServerFragment"
......@@ -44,16 +49,16 @@ class ServerFragment : Fragment(), ServerView {
@Inject
lateinit var analyticsManager: AnalyticsManager
private var deepLinkInfo: LoginDeepLinkInfo? = null
private var protocol = "https://"
private lateinit var serverUrlEditTextDisposable: Disposable
private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
text_server_url.isCursorVisible =
KeyboardHelper.isSoftKeyboardShown(constraint_layout.rootView)
}
private var protocol = "https://"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this)
deepLinkInfo = arguments?.getParcelable(DEEP_LINK_INFO)
}
......@@ -66,13 +71,13 @@ class ServerFragment : Fragment(), ServerView {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
constraint_layout.viewTreeObserver.addOnGlobalLayoutListener(layoutListener)
setupToobar()
setupToolbar()
setupSpinner()
setupOnClickListener()
subscribeEditText()
deepLinkInfo?.let {
val uri = Uri.parse(it.url)
uri?.let { text_server_url.hintContent = it.host }
it.url.toUri().host?.let { host -> text_server_url.hintContent = host }
presenter.deepLink(it)
}
......@@ -82,12 +87,12 @@ class ServerFragment : Fragment(), ServerView {
override fun onDestroyView() {
super.onDestroyView()
constraint_layout.viewTreeObserver.removeOnGlobalLayoutListener(layoutListener)
// reset deep link info, so user can come back and log to another server...
// Reset deep link info, so user can come back and log to another server...
deepLinkInfo = null
constraint_layout.viewTreeObserver.removeOnGlobalLayoutListener(layoutListener)
unsubscribeEditText()
}
private fun setupToobar() {
private fun setupToolbar() {
with(activity as AuthenticationActivity) {
view?.let { setLightStatusBar(it) }
toolbar.isVisible = false
......@@ -111,7 +116,7 @@ class ServerFragment : Fragment(), ServerView {
0 -> protocol = "https://"
1 -> {
protocol = "http://"
showToast(R.string.msg_http_insecure)
showToast(R.string.msg_http_insecure, Toast.LENGTH_LONG)
}
}
}
......@@ -122,20 +127,49 @@ class ServerFragment : Fragment(), ServerView {
}
}
private fun setupOnClickListener() =
ui { _ ->
button_connect.setOnClickListener {
presenter.checkServer("$protocol${text_server_url.textContent.sanitize()}")
}
}
override fun showInvalidServerUrlMessage() =
showMessage(getString(R.string.msg_invalid_server_url))
@SuppressLint("RestrictedApi")
override fun enableButtonConnect() {
context?.let {
button_connect.supportBackgroundTintList = ContextCompat.getColorStateList(
it,
R.color.colorAccent
)
button_connect.isEnabled = true
}
}
@SuppressLint("RestrictedApi")
override fun disableButtonConnect() {
context?.let {
button_connect.supportBackgroundTintList = ContextCompat.getColorStateList(
it,
R.color.colorAuthenticationOnBoardingButtonDisabled
)
button_connect.isEnabled = false
}
}
override fun showLoading() {
ui {
enableUserInput(false)
view_loading.setVisible(true)
disableUserInput()
view_loading.isVisible = true
}
}
override fun hideLoading() {
ui {
view_loading.setVisible(false)
enableUserInput(true)
view_loading.isVisible = false
enableUserInput()
}
}
......@@ -151,51 +185,28 @@ class ServerFragment : Fragment(), ServerView {
}
}
override fun showGenericErrorMessage() {
showMessage(getString(R.string.msg_generic_error))
}
override fun showGenericErrorMessage() = showMessage(getString(R.string.msg_generic_error))
override fun alertNotRecommendedVersion() {
ui {
hideLoading()
AlertDialog.Builder(it)
.setMessage(
getString(
R.string.msg_ver_not_recommended,
BuildConfig.RECOMMENDED_SERVER_VERSION
)
)
.setPositiveButton(R.string.msg_ok) { _, _ ->
performConnect()
}
.create()
.show()
showToast(
getString(R.string.msg_ver_not_recommended, BuildConfig.RECOMMENDED_SERVER_VERSION)
)
performConnect()
}
}
override fun blockAndAlertNotRequiredVersion() {
ui {
hideLoading()
AlertDialog.Builder(it)
.setMessage(
getString(
R.string.msg_ver_not_minimum,
BuildConfig.REQUIRED_SERVER_VERSION
)
)
.setPositiveButton(R.string.msg_ok, null)
.setOnDismissListener {
// reset the deeplink info, so the user can log to another server...
deepLinkInfo = null
}
.create()
.show()
showToast(getString(R.string.msg_ver_not_minimum, BuildConfig.REQUIRED_SERVER_VERSION))
// reset the deeplink info, so the user can log to another server...
deepLinkInfo = null
}
}
override fun versionOk() {
performConnect()
}
override fun versionOk() = performConnect()
override fun errorCheckingServerVersion() {
hideLoading()
......@@ -208,49 +219,58 @@ class ServerFragment : Fragment(), ServerView {
}
override fun updateServerUrl(url: HttpUrl) {
if (activity != null && view != null) {
if (url.scheme() == "https") spinner_server_protocol.setSelection(0) else spinner_server_protocol.setSelection(
1
)
protocol = "${url.scheme()}://"
ui {
if (url.scheme() == "https") {
spinner_server_protocol.setSelection(0)
} else {
spinner_server_protocol.setSelection(1)
}
val serverUrl = url.toString().removePrefix("${url.scheme()}://")
text_server_url.textContent = serverUrl
protocol = "${url.scheme()}://"
text_server_url.textContent = url.toString().removePrefix("${url.scheme()}://")
}
}
private fun performConnect() {
ui {
deepLinkInfo?.let {
presenter.deepLink(it)
deepLinkInfo?.let { loginDeepLinkInfo ->
presenter.deepLink(loginDeepLinkInfo)
}.ifNull {
val url = text_server_url.textContent.ifEmpty(text_server_url.hintContent)
presenter.connect("$protocol${url.sanitize()}")
presenter.connect("$protocol${text_server_url.textContent.sanitize()}")
}
}
}
private fun enableUserInput(value: Boolean) {
button_connect.isEnabled = value
text_server_url.isEnabled = value
private fun subscribeEditText() {
serverUrlEditTextDisposable = text_server_url.asObservable()
.debounce(300, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.filter { t -> t.isNotBlank() }
.subscribe {
if (it.toString().isValidUrl()) {
enableButtonConnect()
} else {
disableButtonConnect()
}
}
}
private fun setupOnClickListener() {
ui {
button_connect.setOnClickListener {
val url = text_server_url.textContent.ifEmpty(text_server_url.hintContent)
presenter.checkServer("$protocol${url.sanitize()}")
}
}
private fun unsubscribeEditText() = serverUrlEditTextDisposable.dispose()
private fun enableUserInput() {
enableButtonConnect()
text_server_url.isEnabled = true
}
private fun disableUserInput() {
disableButtonConnect()
text_server_url.isEnabled = false
}
companion object {
private const val DEEP_LINK_INFO = "DeepLinkInfo"
fun newInstance(deepLinkInfo: LoginDeepLinkInfo?) = ServerFragment().apply {
arguments = Bundle().apply {
putParcelable(DEEP_LINK_INFO, deepLinkInfo)
}
arguments = Bundle().apply { putParcelable(DEEP_LINK_INFO, deepLinkInfo) }
}
}
}
\ No newline at end of file
}
......@@ -226,8 +226,10 @@ class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback
private fun setupRecyclerView() {
ui {
recycler_view.layoutManager =
LinearLayoutManager(context, RecyclerView.VERTICAL, false)
recycler_view.addItemDecoration(DividerItemDecoration(it, DividerItemDecoration.HORIZONTAL))
LinearLayoutManager(context, RecyclerView.VERTICAL, false)
recycler_view.addItemDecoration(
DividerItemDecoration(it, DividerItemDecoration.HORIZONTAL)
)
recycler_view.adapter = adapter
}
}
......
......@@ -14,9 +14,11 @@ import chat.rocket.core.internal.rest.serverInfo
import kotlinx.coroutines.experimental.Job
import timber.log.Timber
abstract class CheckServerPresenter constructor(private val strategy: CancelStrategy,
private val factory: RocketChatClientFactory,
private val view: VersionCheckView) {
abstract class CheckServerPresenter constructor(
private val strategy: CancelStrategy,
private val factory: RocketChatClientFactory,
private val view: VersionCheckView
) {
private lateinit var currentServer: String
private lateinit var client: RocketChatClient
......@@ -49,12 +51,8 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
} catch (ex: Exception) {
Timber.d(ex, "Error getting server info")
when (ex) {
is RocketChatInvalidProtocolException -> {
view.errorInvalidProtocol()
}
else -> {
view.errorCheckingServerVersion()
}
is RocketChatInvalidProtocolException -> view.errorInvalidProtocol()
else -> view.errorCheckingServerVersion()
}
}
}
......@@ -64,6 +62,7 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
val thisServerVersion = serverInfo.version
val isRequiredVersion = isRequiredServerVersion(thisServerVersion)
val isRecommendedVersion = isRecommendedServerVersion(thisServerVersion)
return if (isRequiredVersion) {
if (isRecommendedVersion) {
Timber.i("Your version is nice! (Requires: 0.62.0, Yours: $thisServerVersion)")
......@@ -81,7 +80,10 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
}
private fun isRecommendedServerVersion(version: String): Boolean {
return isMinimumVersion(version, getVersionDistilled(BuildConfig.RECOMMENDED_SERVER_VERSION))
return isMinimumVersion(
version,
getVersionDistilled(BuildConfig.RECOMMENDED_SERVER_VERSION)
)
}
private fun isMinimumVersion(version: String, required: VersionInfo): Boolean {
......@@ -115,12 +117,14 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
val major = getVersionNumber(split, 0)
val minor = getVersionNumber(split, 1)
val update = getVersionNumber(split, 2)
return VersionInfo(
major = major,
minor = minor,
update = update,
release = release,
full = version)
major = major,
minor = minor,
update = update,
release = release,
full = version
)
}
private fun getVersionNumber(split: List<String>, index: Int): Int {
......@@ -133,7 +137,9 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
sealed class Version(val version: String) {
data class VersionOk(private val currentVersion: String) : Version(currentVersion)
data class RecommendedVersionWarning(private val currentVersion: String) : Version(currentVersion)
data class RecommendedVersionWarning(private val currentVersion: String) :
Version(currentVersion)
data class OutOfDateError(private val currentVersion: String) : Version(currentVersion)
}
}
\ No newline at end of file
......@@ -3,5 +3,4 @@
android:shape="oval">
<solid android:color="@color/colorAccent" />
</shape>
\ No newline at end of file
</shape>
......@@ -68,10 +68,12 @@
android:inputType="text|textUri" />
</RelativeLayout>
<Button
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/button_connect"
style="@style/Authentication.Button"
android:layout_marginTop="20dp"
android:backgroundTint="@color/colorAuthenticationOnBoardingButtonDisabled"
android:enabled="false"
android:text="@string/action_connect"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
......
......@@ -24,6 +24,7 @@
<!-- Authentication colors -->
<color name="colorAuthenticationOnBoardingButtonBorder">#FFE1E5E8</color>
<color name="colorAuthenticationOnBoardingButtonDisabled">#FFE1E5E8</color>
<color name="colorAuthenticationOnBoardingChevron">#FFCBCED1</color>
<color name="colorAuthenticationOnBoardingSecondaryText">#FF9EA2A8</color>
......
......@@ -131,7 +131,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string name="msg_no_chat_title">No chat messages</string>
<string name="msg_no_chat_description">Start conversing to see your\nmessages here.</string>
<string name="msg_cancel">CANCEL</string>
<string name="msg_http_insecure">When using HTTP, you\'re connecting to an insecure server. We don\'t recommend you doing that.</string>
<string name="msg_http_insecure">When using HTTP you\'re connecting to an insecure server. We don\'t recommend you doing that.</string>
<string name="msg_error_checking_server_version">An error has occurred while checking your server version, please try again</string>
<string name="msg_invalid_server_protocol">The selected protocol is not accepted by this server, try using HTTPS</string>
<string name="msg_image_saved_successfully">Image has been saved to gallery</string>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment