Unverified Commit 2bc41c37 authored by Pancor's avatar Pancor Committed by GitHub

Merge branch 'develop-2.x' into feature/save-unfinished-message

parents b47bd9a7 032a72a0
...@@ -13,8 +13,8 @@ android { ...@@ -13,8 +13,8 @@ android {
applicationId "chat.rocket.android" applicationId "chat.rocket.android"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion versions.targetSdk targetSdkVersion versions.targetSdk
versionCode 2007 versionCode 2008
versionName "2.0.0-beta5" versionName "2.0.0-beta6"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission <permission
......
...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.login.presentation ...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.login.presentation
import chat.rocket.android.authentication.presentation.AuthenticationNavigator import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.NetworkHelper
import chat.rocket.android.helper.OauthHelper import chat.rocket.android.helper.OauthHelper
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.* import chat.rocket.android.server.domain.*
...@@ -190,64 +189,60 @@ class LoginPresenter @Inject constructor(private val view: LoginView, ...@@ -190,64 +189,60 @@ class LoginPresenter @Inject constructor(private val view: LoginView,
private fun doAuthentication(loginType: Int) { private fun doAuthentication(loginType: Int) {
launchUI(strategy) { launchUI(strategy) {
if (NetworkHelper.hasInternetAccess()) { view.disableUserInput()
view.disableUserInput() view.showLoading()
view.showLoading() try {
try { val token = retryIO("login") {
val token = retryIO("login") { when (loginType) {
when (loginType) { TYPE_LOGIN_USER_EMAIL -> {
TYPE_LOGIN_USER_EMAIL -> { if (usernameOrEmail.isEmail()) {
if (usernameOrEmail.isEmail()) { client.loginWithEmail(usernameOrEmail, password)
client.loginWithEmail(usernameOrEmail, password) } else {
if (settings.isLdapAuthenticationEnabled()) {
client.loginWithLdap(usernameOrEmail, password)
} else { } else {
if (settings.isLdapAuthenticationEnabled()) { client.login(usernameOrEmail, password)
client.loginWithLdap(usernameOrEmail, password)
} else {
client.login(usernameOrEmail, password)
}
} }
} }
TYPE_LOGIN_CAS -> {
delay(3, TimeUnit.SECONDS)
client.loginWithCas(credentialToken)
}
TYPE_LOGIN_OAUTH -> {
client.loginWithOauth(credentialToken, credentialSecret)
}
else -> {
throw IllegalStateException("Expected TYPE_LOGIN_USER_EMAIL, TYPE_LOGIN_CAS or TYPE_LOGIN_OAUTH")
}
} }
} TYPE_LOGIN_CAS -> {
val username = retryIO("me()") { client.me().username } delay(3, TimeUnit.SECONDS)
if (username != null) { client.loginWithCas(credentialToken)
localRepository.save(LocalRepository.CURRENT_USERNAME_KEY, username) }
saveAccount(username) TYPE_LOGIN_OAUTH -> {
saveToken(token) client.loginWithOauth(credentialToken, credentialSecret)
registerPushToken()
navigator.toChatList()
} else if (loginType == TYPE_LOGIN_OAUTH) {
navigator.toRegisterUsername(token.userId, token.authToken)
}
} catch (exception: RocketChatException) {
when (exception) {
is RocketChatTwoFactorException -> {
navigator.toTwoFA(usernameOrEmail, password)
} }
else -> { else -> {
exception.message?.let { throw IllegalStateException("Expected TYPE_LOGIN_USER_EMAIL, TYPE_LOGIN_CAS or TYPE_LOGIN_OAUTH")
view.showMessage(it) }
}.ifNull { }
view.showGenericErrorMessage() }
} val username = retryIO("me()") { client.me().username }
if (username != null) {
localRepository.save(LocalRepository.CURRENT_USERNAME_KEY, username)
saveAccount(username)
saveToken(token)
registerPushToken()
navigator.toChatList()
} else if (loginType == TYPE_LOGIN_OAUTH) {
navigator.toRegisterUsername(token.userId, token.authToken)
}
} catch (exception: RocketChatException) {
when (exception) {
is RocketChatTwoFactorException -> {
navigator.toTwoFA(usernameOrEmail, password)
}
else -> {
exception.message?.let {
view.showMessage(it)
}.ifNull {
view.showGenericErrorMessage()
} }
} }
} finally {
view.hideLoading()
view.enableUserInput()
} }
} else { } finally {
view.showNoInternetConnection() view.hideLoading()
view.enableUserInput()
} }
} }
} }
......
package chat.rocket.android.authentication.login.presentation package chat.rocket.android.authentication.login.presentation
import chat.rocket.android.authentication.server.presentation.VersionCheckView import chat.rocket.android.authentication.server.presentation.VersionCheckView
import chat.rocket.android.core.behaviours.InternetView
import chat.rocket.android.core.behaviours.LoadingView import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView import chat.rocket.android.core.behaviours.MessageView
interface LoginView : LoadingView, MessageView, InternetView, VersionCheckView { interface LoginView : LoadingView, MessageView, VersionCheckView {
/** /**
* Shows the form view (i.e the username/email and password fields) if it is enabled by the server settings. * Shows the form view (i.e the username/email and password fields) if it is enabled by the server settings.
......
...@@ -105,10 +105,6 @@ class LoginFragment : Fragment(), LoginView { ...@@ -105,10 +105,6 @@ class LoginFragment : Fragment(), LoginView {
view_loading.setVisible(false) view_loading.setVisible(false)
} }
override fun showNoInternetConnection() {
showMessage(R.string.msg_no_internet_connection)
}
override fun showMessage(resId: Int) { override fun showMessage(resId: Int) {
showToast(resId) showToast(resId)
} }
......
...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.registerusername.presentation ...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.registerusername.presentation
import chat.rocket.android.authentication.presentation.AuthenticationNavigator import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.NetworkHelper
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.* import chat.rocket.android.server.domain.*
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
...@@ -40,30 +39,26 @@ class RegisterUsernamePresenter @Inject constructor( ...@@ -40,30 +39,26 @@ class RegisterUsernamePresenter @Inject constructor(
view.alertBlankUsername() view.alertBlankUsername()
} else { } else {
launchUI(strategy) { launchUI(strategy) {
if (NetworkHelper.hasInternetAccess()) { view.showLoading()
view.showLoading() try {
try { val me = retryIO("updateOwnBasicInformation(username = $username)") {
val me = retryIO("updateOwnBasicInformation(username = $username)") { client.updateOwnBasicInformation(username = username)
client.updateOwnBasicInformation(username = username)
}
val registeredUsername = me.username
if (registeredUsername != null) {
saveAccount(registeredUsername)
tokenRepository.save(currentServer, Token(userId, authToken))
registerPushToken()
navigator.toChatList()
}
} catch (exception: RocketChatException) {
exception.message?.let {
view.showMessage(it)
}.ifNull {
view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
} }
} else { val registeredUsername = me.username
view.showNoInternetConnection() if (registeredUsername != null) {
saveAccount(registeredUsername)
tokenRepository.save(currentServer, Token(userId, authToken))
registerPushToken()
navigator.toChatList()
}
} catch (exception: RocketChatException) {
exception.message?.let {
view.showMessage(it)
}.ifNull {
view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
} }
} }
} }
......
package chat.rocket.android.authentication.registerusername.presentation package chat.rocket.android.authentication.registerusername.presentation
import chat.rocket.android.core.behaviours.InternetView
import chat.rocket.android.core.behaviours.LoadingView import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView import chat.rocket.android.core.behaviours.MessageView
interface RegisterUsernameView : LoadingView, MessageView, InternetView { interface RegisterUsernameView : LoadingView, MessageView {
/** /**
* Alerts the user about a blank username. * Alerts the user about a blank username.
......
...@@ -85,10 +85,6 @@ class RegisterUsernameFragment : Fragment(), RegisterUsernameView { ...@@ -85,10 +85,6 @@ class RegisterUsernameFragment : Fragment(), RegisterUsernameView {
showMessage(getString(R.string.msg_generic_error)) showMessage(getString(R.string.msg_generic_error))
} }
override fun showNoInternetConnection() {
showMessage(getString(R.string.msg_no_internet_connection))
}
private fun tintEditTextDrawableStart() { private fun tintEditTextDrawableStart() {
activity?.apply { activity?.apply {
val atDrawable = DrawableHelper.getDrawableFromId(R.drawable.ic_at_black_24dp, this) val atDrawable = DrawableHelper.getDrawableFromId(R.drawable.ic_at_black_24dp, this)
......
...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.server.presentation ...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.server.presentation
import chat.rocket.android.authentication.presentation.AuthenticationNavigator import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.NetworkHelper
import chat.rocket.android.server.domain.GetAccountsInteractor import chat.rocket.android.server.domain.GetAccountsInteractor
import chat.rocket.android.server.domain.RefreshSettingsInteractor import chat.rocket.android.server.domain.RefreshSettingsInteractor
import chat.rocket.android.server.domain.SaveCurrentServerInteractor import chat.rocket.android.server.domain.SaveCurrentServerInteractor
...@@ -29,23 +28,19 @@ class ServerPresenter @Inject constructor(private val view: ServerView, ...@@ -29,23 +28,19 @@ class ServerPresenter @Inject constructor(private val view: ServerView,
return@launchUI return@launchUI
} }
if (NetworkHelper.hasInternetAccess()) { view.showLoading()
view.showLoading() try {
try { refreshSettingsInteractor.refresh(server)
refreshSettingsInteractor.refresh(server) serverInteractor.save(server)
serverInteractor.save(server) navigator.toLogin()
navigator.toLogin() } catch (ex: Exception) {
} catch (ex: Exception) { ex.message?.let {
ex.message?.let { view.showMessage(it)
view.showMessage(it) }.ifNull {
}.ifNull { view.showGenericErrorMessage()
view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
} }
} else { } finally {
view.showNoInternetConnection() view.hideLoading()
} }
} }
} }
......
package chat.rocket.android.authentication.server.presentation package chat.rocket.android.authentication.server.presentation
import chat.rocket.android.core.behaviours.InternetView
import chat.rocket.android.core.behaviours.LoadingView import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView import chat.rocket.android.core.behaviours.MessageView
interface ServerView : LoadingView, MessageView, InternetView { interface ServerView : LoadingView, MessageView {
/** /**
* Shows an invalid server URL message. * Shows an invalid server URL message.
......
...@@ -68,10 +68,6 @@ class ServerFragment : Fragment(), ServerView { ...@@ -68,10 +68,6 @@ class ServerFragment : Fragment(), ServerView {
showMessage(getString(R.string.msg_generic_error)) showMessage(getString(R.string.msg_generic_error))
} }
override fun showNoInternetConnection() {
showMessage(getString(R.string.msg_no_internet_connection))
}
private fun enableUserInput(value: Boolean) { private fun enableUserInput(value: Boolean) {
button_connect.isEnabled = value button_connect.isEnabled = value
text_server_url.isEnabled = value text_server_url.isEnabled = value
......
...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.signup.presentation ...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.signup.presentation
import chat.rocket.android.authentication.presentation.AuthenticationNavigator import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.NetworkHelper
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.* import chat.rocket.android.server.domain.*
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
...@@ -57,31 +56,26 @@ class SignupPresenter @Inject constructor(private val view: SignupView, ...@@ -57,31 +56,26 @@ class SignupPresenter @Inject constructor(private val view: SignupView,
else -> { else -> {
val client = factory.create(server) val client = factory.create(server)
launchUI(strategy) { launchUI(strategy) {
if (NetworkHelper.hasInternetAccess()) { view.showLoading()
view.showLoading() try {
// TODO This function returns a user so should we save it?
try { retryIO("signup") { client.signup(email, name, username, password) }
// TODO This function returns a user so should we save it? // TODO This function returns a user token so should we save it?
retryIO("signup") { client.signup(email, name, username, password) } retryIO("login") { client.login(username, password) }
// TODO This function returns a user token so should we save it? val me = retryIO("me") { client.me() }
retryIO("login") { client.login(username, password) } localRepository.save(LocalRepository.CURRENT_USERNAME_KEY, me.username)
val me = retryIO("me") { client.me() } saveAccount(me)
localRepository.save(LocalRepository.CURRENT_USERNAME_KEY, me.username) registerPushToken()
saveAccount(me) navigator.toChatList()
registerPushToken() } catch (exception: RocketChatException) {
navigator.toChatList() exception.message?.let {
} catch (exception: RocketChatException) { view.showMessage(it)
exception.message?.let { }.ifNull {
view.showMessage(it) view.showGenericErrorMessage()
}.ifNull {
view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
} }
} else { } finally {
view.showNoInternetConnection() view.hideLoading()
} }
} }
} }
......
package chat.rocket.android.authentication.signup.presentation package chat.rocket.android.authentication.signup.presentation
import chat.rocket.android.core.behaviours.InternetView
import chat.rocket.android.core.behaviours.LoadingView import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView import chat.rocket.android.core.behaviours.MessageView
interface SignupView : LoadingView, MessageView, InternetView { interface SignupView : LoadingView, MessageView {
/** /**
* Alerts the user about a blank name. * Alerts the user about a blank name.
......
...@@ -109,10 +109,6 @@ class SignupFragment : Fragment(), SignupView { ...@@ -109,10 +109,6 @@ class SignupFragment : Fragment(), SignupView {
showMessage(getString(R.string.msg_generic_error)) showMessage(getString(R.string.msg_generic_error))
} }
override fun showNoInternetConnection() {
Toast.makeText(activity, getString(R.string.msg_no_internet_connection), Toast.LENGTH_SHORT).show()
}
private fun tintEditTextDrawableStart() { private fun tintEditTextDrawableStart() {
activity?.apply { activity?.apply {
val personDrawable = DrawableHelper.getDrawableFromId(R.drawable.ic_person_black_24dp, this) val personDrawable = DrawableHelper.getDrawableFromId(R.drawable.ic_person_black_24dp, this)
......
...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.twofactor.presentation ...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.twofactor.presentation
import chat.rocket.android.authentication.presentation.AuthenticationNavigator import chat.rocket.android.authentication.presentation.AuthenticationNavigator
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.NetworkHelper
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.* import chat.rocket.android.server.domain.*
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
...@@ -48,33 +47,29 @@ class TwoFAPresenter @Inject constructor(private val view: TwoFAView, ...@@ -48,33 +47,29 @@ class TwoFAPresenter @Inject constructor(private val view: TwoFAView,
else -> { else -> {
launchUI(strategy) { launchUI(strategy) {
val client = factory.create(server) val client = factory.create(server)
if (NetworkHelper.hasInternetAccess()) { view.showLoading()
view.showLoading() try {
try { // The token is saved via the client TokenProvider
// The token is saved via the client TokenProvider val token = retryIO("login") {
val token = retryIO("login") { client.login(usernameOrEmail, password, twoFactorAuthenticationCode)
client.login(usernameOrEmail, password, twoFactorAuthenticationCode) }
} val me = retryIO("me") { client.me() }
val me = retryIO("me") { client.me() } saveAccount(me)
saveAccount(me) tokenRepository.save(server, token)
tokenRepository.save(server, token) registerPushToken()
registerPushToken() navigator.toChatList()
navigator.toChatList() } catch (exception: RocketChatException) {
} catch (exception: RocketChatException) { if (exception is RocketChatAuthException) {
if (exception is RocketChatAuthException) { view.alertInvalidTwoFactorAuthenticationCode()
view.alertInvalidTwoFactorAuthenticationCode() } else {
} else { exception.message?.let {
exception.message?.let { view.showMessage(it)
view.showMessage(it) }.ifNull {
}.ifNull { view.showGenericErrorMessage()
view.showGenericErrorMessage()
}
} }
} finally {
view.hideLoading()
} }
} else { } finally {
view.showNoInternetConnection() view.hideLoading()
} }
} }
} }
......
package chat.rocket.android.authentication.twofactor.presentation package chat.rocket.android.authentication.twofactor.presentation
import chat.rocket.android.core.behaviours.InternetView
import chat.rocket.android.core.behaviours.LoadingView import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView import chat.rocket.android.core.behaviours.MessageView
interface TwoFAView : LoadingView, MessageView, InternetView { interface TwoFAView : LoadingView, MessageView {
/** /**
* Alerts the user about a blank Two Factor Authentication code. * Alerts the user about a blank Two Factor Authentication code.
......
...@@ -91,8 +91,6 @@ class TwoFAFragment : Fragment(), TwoFAView { ...@@ -91,8 +91,6 @@ class TwoFAFragment : Fragment(), TwoFAView {
override fun showGenericErrorMessage() = showMessage(getString(R.string.msg_generic_error)) override fun showGenericErrorMessage() = showMessage(getString(R.string.msg_generic_error))
override fun showNoInternetConnection() = showMessage(getString(R.string.msg_no_internet_connection))
private fun tintEditTextDrawableStart() { private fun tintEditTextDrawableStart() {
activity?.apply { activity?.apply {
val lockDrawable = DrawableHelper.getDrawableFromId(R.drawable.ic_vpn_key_black_24dp, this) val lockDrawable = DrawableHelper.getDrawableFromId(R.drawable.ic_vpn_key_black_24dp, this)
......
package chat.rocket.android.chatroom.ui package chat.rocket.android.chatroom.ui
import android.Manifest
import android.app.Activity import android.app.Activity
import android.content.ClipData import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.Configuration import android.content.res.Configuration
import android.content.pm.PackageManager
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.support.annotation.DrawableRes import android.support.annotation.DrawableRes
import android.support.v4.app.ActivityCompat
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.support.v7.widget.DefaultItemAnimator import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
...@@ -226,10 +230,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -226,10 +230,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
private val layoutChangeListener = View.OnLayoutChangeListener { _, _, _, _, bottom, _, _, _, oldBottom -> private val layoutChangeListener = View.OnLayoutChangeListener { _, _, _, _, bottom, _, _, _, oldBottom ->
val y = oldBottom - bottom val y = oldBottom - bottom
if (y.absoluteValue > 0 && isAdded) { if (Math.abs(y) > 0 && isAdded) {
// if y is positive the keyboard is up else it's down // if y is positive the keyboard is up else it's down
recycler_view.post { recycler_view.post {
if (y > 0 || verticalScrollOffset.get().absoluteValue >= y.absoluteValue) { if (y > 0 || Math.abs(verticalScrollOffset.get()) >= Math.abs(y)) {
recycler_view.scrollBy(0, y) recycler_view.scrollBy(0, y)
} else { } else {
recycler_view.scrollBy(0, verticalScrollOffset.get()) recycler_view.scrollBy(0, verticalScrollOffset.get())
...@@ -437,10 +441,31 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -437,10 +441,31 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
override fun showFileSelection(filter: Array<String>) { override fun showFileSelection(filter: Array<String>) {
val intent = Intent(Intent.ACTION_GET_CONTENT) activity?.let {
intent.type = "*/*" if (ContextCompat.checkSelfPermission(it, Manifest.permission.READ_EXTERNAL_STORAGE)
intent.putExtra(Intent.EXTRA_MIME_TYPES, filter) != PackageManager.PERMISSION_GRANTED) {
startActivityForResult(intent, REQUEST_CODE_FOR_PERFORM_SAF) ActivityCompat.requestPermissions(it,
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
1)
} else {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "*/*"
intent.putExtra(Intent.EXTRA_MIME_TYPES, filter)
startActivityForResult(intent, REQUEST_CODE_FOR_PERFORM_SAF)
}
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
1 -> {
if (!(grantResults.isNotEmpty() && grantResults.first() == PackageManager.PERMISSION_GRANTED)) {
handler.postDelayed({
hideAttachmentOptions()
}, 400)
}
}
}
} }
override fun showInvalidFileSize(fileSize: Int, maxFileSize: Int) { override fun showInvalidFileSize(fileSize: Int, maxFileSize: Int) {
......
...@@ -74,14 +74,17 @@ class ChatRoomsAdapter(private val context: Context, ...@@ -74,14 +74,17 @@ class ChatRoomsAdapter(private val context: Context,
} }
private fun bindAvatar(chatRoom: ChatRoom, drawee: SimpleDraweeView) { private fun bindAvatar(chatRoom: ChatRoom, drawee: SimpleDraweeView) {
val avatarId = if (chatRoom.type is RoomType.DirectMessage) chatRoom.name else "@${chatRoom.name}" if (chatRoom.type is RoomType.DirectMessage) {
drawee.setImageURI(chatRoom.client.url.avatarUrl(avatarId)) drawee.setImageURI(chatRoom.client.url.avatarUrl(chatRoom.name))
} else {
drawee.setImageURI(chatRoom.client.url.avatarUrl(chatRoom.name, true))
}
} }
private fun bindName(chatRoom: ChatRoom, textView: TextView) { private fun bindName(chatRoom: ChatRoom, textView: TextView) {
textView.textContent = chatRoom.name textView.textContent = chatRoom.name
var drawable = when (chatRoom.type) { val drawable = when (chatRoom.type) {
is RoomType.Channel -> { is RoomType.Channel -> {
DrawableHelper.getDrawableFromId(R.drawable.ic_room_channel, context) DrawableHelper.getDrawableFromId(R.drawable.ic_room_channel, context)
} }
......
package chat.rocket.android.core.behaviours
interface InternetView {
fun showNoInternetConnection()
}
\ No newline at end of file
package chat.rocket.android.helper
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.withContext
import java.io.IOException
import java.net.InetSocketAddress
import java.net.Socket
object NetworkHelper {
/**
* Checks whether there is internet access.
*
* The original author of this code is Levit and you can see his answer here: https://stackoverflow.com/a/27312494/4744263
*
* @return true if there is internet access, false otherwise.
*/
suspend fun hasInternetAccess(): Boolean = withContext(CommonPool) {
try {
val socket = Socket()
val inetSocketAddress = InetSocketAddress("8.8.8.8", 53)
socket.connect(inetSocketAddress, 1500)
socket.close()
true
} catch (e: IOException) {
false
}
}
}
\ No newline at end of file
...@@ -25,7 +25,7 @@ class MemberViewModel(private val member: User, private val settings: Map<String ...@@ -25,7 +25,7 @@ class MemberViewModel(private val member: User, private val settings: Map<String
private fun getUserAvatar(): String? { private fun getUserAvatar(): String? {
val username = member.username ?: "?" val username = member.username ?: "?"
return baseUrl?.let { return baseUrl?.let {
baseUrl.avatarUrl(username,"png") baseUrl.avatarUrl(username, format = "png")
} }
} }
......
...@@ -9,10 +9,11 @@ import kotlinx.coroutines.experimental.Job ...@@ -9,10 +9,11 @@ import kotlinx.coroutines.experimental.Job
import kotlinx.coroutines.experimental.channels.Channel import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.launch import kotlinx.coroutines.experimental.launch
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.CopyOnWriteArrayList
class ConnectionManager(internal val client: RocketChatClient) { class ConnectionManager(internal val client: RocketChatClient) {
private val statusChannelList = ArrayList<Channel<State>>() private val statusChannelList = CopyOnWriteArrayList<Channel<State>>()
private val statusChannel = Channel<State>() private val statusChannel = Channel<State>()
private var connectJob: Job? = null private var connectJob: Job? = null
......
...@@ -10,8 +10,13 @@ fun String.removeTrailingSlash(): String { ...@@ -10,8 +10,13 @@ fun String.removeTrailingSlash(): String {
} }
} }
fun String.avatarUrl(avatar: String, format: String = "jpeg") = fun String.avatarUrl(avatar: String, isGroupOrChannel: Boolean = false, format: String = "jpeg"): String {
"${removeTrailingSlash()}/avatar/${avatar.removeTrailingSlash()}?format=$format" return if (isGroupOrChannel) {
"${removeTrailingSlash()}/avatar/%23${avatar.removeTrailingSlash()}?format=$format"
} else {
"${removeTrailingSlash()}/avatar/${avatar.removeTrailingSlash()}?format=$format"
}
}
fun String.serverLogoUrl(favicon: String) = "${removeTrailingSlash()}/$favicon" fun String.serverLogoUrl(favicon: String) = "${removeTrailingSlash()}/$favicon"
......
...@@ -9,10 +9,7 @@ import android.provider.DocumentsContract ...@@ -9,10 +9,7 @@ import android.provider.DocumentsContract
import android.provider.MediaStore import android.provider.MediaStore
import android.provider.OpenableColumns import android.provider.OpenableColumns
import android.webkit.MimeTypeMap import android.webkit.MimeTypeMap
import java.io.FileInputStream import java.io.*
import java.io.FileNotFoundException
import java.io.IOException
import java.io.InputStream
fun Uri.getFileName(context: Context): String? { fun Uri.getFileName(context: Context): String? {
val cursor = context.contentResolver.query(this, null, null, null, null, null) val cursor = context.contentResolver.query(this, null, null, null, null, null)
...@@ -27,16 +24,22 @@ fun Uri.getFileName(context: Context): String? { ...@@ -27,16 +24,22 @@ fun Uri.getFileName(context: Context): String? {
} }
fun Uri.getFileSize(context: Context): Int { fun Uri.getFileSize(context: Context): Int {
val cursor = context.contentResolver.query(this, null, null, null, null, null) var fileSize: String? = null
if (scheme == ContentResolver.SCHEME_CONTENT) {
val fileSize = cursor?.use { try {
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE) val fileInputStream = context.contentResolver.openInputStream(this)
if (cursor.moveToFirst()) { fileSize = fileInputStream.available().toString()
if (!cursor.isNull(sizeIndex)) { } catch (e: Exception) {
return@use cursor.getString(sizeIndex) e.printStackTrace()
} }
} else if (scheme == ContentResolver.SCHEME_FILE) {
val path = this.path
try {
val f = File(path)
fileSize = f.length().toString()
} catch (e: Exception) {
e.printStackTrace()
} }
return@use null
} }
return fileSize?.toIntOrNull() ?: -1 return fileSize?.toIntOrNull() ?: -1
} }
...@@ -46,7 +49,11 @@ fun Uri.getMimeType(context: Context): String { ...@@ -46,7 +49,11 @@ fun Uri.getMimeType(context: Context): String {
context.contentResolver.getType(this) context.contentResolver.getType(this)
} else { } else {
val fileExtension = MimeTypeMap.getFileExtensionFromUrl(toString()) val fileExtension = MimeTypeMap.getFileExtensionFromUrl(toString())
MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension.toLowerCase()) if (fileExtension != null) {
MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension.toLowerCase())
} else {
"application/octet-stream"
}
} }
} }
......
...@@ -10,45 +10,52 @@ ...@@ -10,45 +10,52 @@
android:id="@+id/text_online" android:id="@+id/text_online"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="10dp" android:paddingBottom="8dp"
android:layout_marginEnd="16dp" android:paddingEnd="16dp"
android:layout_marginStart="16dp" android:paddingStart="16dp"
android:layout_marginTop="16dp" android:paddingTop="8dp"
android:drawablePadding="10dp" android:drawablePadding="10dp"
android:drawableStart="@drawable/ic_status_online_24dp" android:drawableStart="@drawable/ic_status_online_24dp"
android:text="@string/action_online" /> android:text="@string/action_online"
android:background="?selectableItemBackground"/>
<TextView <TextView
android:id="@+id/text_away" android:id="@+id/text_away"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="10dp" android:paddingBottom="8dp"
android:layout_marginEnd="16dp" android:paddingEnd="16dp"
android:layout_marginStart="16dp" android:paddingStart="16dp"
android:paddingTop="8dp"
android:drawablePadding="10dp" android:drawablePadding="10dp"
android:drawableStart="@drawable/ic_status_away_24dp" android:drawableStart="@drawable/ic_status_away_24dp"
android:text="@string/action_away" /> android:text="@string/action_away"
android:background="?selectableItemBackground"/>
<TextView <TextView
android:id="@+id/text_busy" android:id="@+id/text_busy"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="10dp" android:paddingBottom="8dp"
android:layout_marginEnd="16dp" android:paddingEnd="16dp"
android:layout_marginStart="16dp" android:paddingStart="16dp"
android:paddingTop="8dp"
android:drawablePadding="10dp" android:drawablePadding="10dp"
android:drawableStart="@drawable/ic_status_busy_24dp" android:drawableStart="@drawable/ic_status_busy_24dp"
android:text="@string/action_busy" /> android:text="@string/action_busy"
android:background="?selectableItemBackground"/>
<TextView <TextView
android:id="@+id/text_invisible" android:id="@+id/text_invisible"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="16dp" android:paddingBottom="8dp"
android:layout_marginEnd="16dp" android:paddingEnd="16dp"
android:layout_marginStart="16dp" android:paddingStart="16dp"
android:paddingTop="8dp"
android:drawablePadding="10dp" android:drawablePadding="10dp"
android:drawableStart="@drawable/ic_status_invisible_24dp" android:drawableStart="@drawable/ic_status_invisible_24dp"
android:text="@string/action_invisible" /> android:text="@string/action_invisible"
android:background="?selectableItemBackground"/>
</LinearLayout> </LinearLayout>
\ No newline at end of file
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
</string-array> </string-array>
<!-- Regular information messages --> <!-- Regular information messages -->
<string name="msg_no_internet_connection">कोई इंटरनेट कनेक्शन नहीं है</string>
<string name="msg_generic_error">क्षमा करें, एक त्रुटि हुई है, कृपया पुनः प्रयास करें</string> <string name="msg_generic_error">क्षमा करें, एक त्रुटि हुई है, कृपया पुनः प्रयास करें</string>
<string name="msg_no_data_to_display">डेटा प्रदर्शित करने के लिए उपलब्ध नहीं हैं</string> <string name="msg_no_data_to_display">डेटा प्रदर्शित करने के लिए उपलब्ध नहीं हैं</string>
<string name="msg_profile_update_successfully">प्रोफ़ाइल सफलतापूर्वक अपडेट हो गया है</string> <string name="msg_profile_update_successfully">प्रोफ़ाइल सफलतापूर्वक अपडेट हो गया है</string>
......
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
</string-array> </string-array>
<!-- Regular information messages --> <!-- Regular information messages -->
<string name="msg_no_internet_connection">Sem conexão à internet</string>
<string name="msg_generic_error">Desculpe, ocorreu um erro, tente novamente</string> <string name="msg_generic_error">Desculpe, ocorreu um erro, tente novamente</string>
<string name="msg_no_data_to_display">Nenhum dado para exibir</string> <string name="msg_no_data_to_display">Nenhum dado para exibir</string>
<string name="msg_profile_update_successfully">Perfil atualizado com sucesso</string> <string name="msg_profile_update_successfully">Perfil atualizado com sucesso</string>
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
</string-array> </string-array>
<!-- Regular information messages --> <!-- Regular information messages -->
<string name="msg_no_internet_connection">No internet connection</string>
<string name="msg_generic_error">Sorry, an error has occurred, please try again</string> <string name="msg_generic_error">Sorry, an error has occurred, please try again</string>
<string name="msg_no_data_to_display">No data to display</string> <string name="msg_no_data_to_display">No data to display</string>
<string name="msg_profile_update_successfully">Profile update successfully</string> <string name="msg_profile_update_successfully">Profile update successfully</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