Commit 86830af9 authored by Filipe de Lima Brito's avatar Filipe de Lima Brito

Added project improvements.

Better app modularization. Processing the draw image in background as well as handling possible errors.
parent 9f240045
...@@ -63,6 +63,8 @@ dependencies { ...@@ -63,6 +63,8 @@ dependencies {
implementation project(':player') implementation project(':player')
implementation project(':emoji') implementation project(':emoji')
implementation project(':draw') implementation project(':draw')
implementation project(':util')
implementation project(':core')
implementation libraries.kotlin implementation libraries.kotlin
implementation libraries.coroutines implementation libraries.coroutines
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="chat.rocket.android"> package="chat.rocket.android">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
...@@ -8,6 +9,7 @@ ...@@ -8,6 +9,7 @@
<application <application
android:name=".app.RocketChatApplication" android:name=".app.RocketChatApplication"
tools:replace="android:name"
android:allowBackup="true" android:allowBackup="true"
android:fullBackupContent="@xml/backup_config" android:fullBackupContent="@xml/backup_config"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
......
...@@ -8,6 +8,7 @@ import chat.rocket.android.infrastructure.LocalRepository ...@@ -8,6 +8,7 @@ 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
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.* import chat.rocket.android.util.extensions.*
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatAuthException import chat.rocket.common.RocketChatAuthException
...@@ -17,7 +18,6 @@ import chat.rocket.common.model.Token ...@@ -17,7 +18,6 @@ import chat.rocket.common.model.Token
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.RocketChatClient import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.rest.* import chat.rocket.core.internal.rest.*
import com.google.android.gms.auth.api.credentials.Credential
import kotlinx.coroutines.experimental.delay import kotlinx.coroutines.experimental.delay
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
......
...@@ -7,7 +7,7 @@ import chat.rocket.android.server.domain.* ...@@ -7,7 +7,7 @@ import chat.rocket.android.server.domain.*
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.registerPushToken import chat.rocket.android.util.extensions.registerPushToken
import chat.rocket.android.util.extensions.serverLogoUrl import chat.rocket.android.util.extensions.serverLogoUrl
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
......
...@@ -3,10 +3,9 @@ package chat.rocket.android.authentication.resetpassword.presentation ...@@ -3,10 +3,9 @@ package chat.rocket.android.authentication.resetpassword.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.server.domain.GetConnectingServerInteractor import chat.rocket.android.server.domain.GetConnectingServerInteractor
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.isEmail import chat.rocket.android.util.extensions.isEmail
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.RocketChatInvalidResponseException import chat.rocket.common.RocketChatInvalidResponseException
......
...@@ -10,10 +10,11 @@ import chat.rocket.android.server.domain.SaveConnectingServerInteractor ...@@ -10,10 +10,11 @@ import chat.rocket.android.server.domain.SaveConnectingServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.server.presentation.CheckServerPresenter import chat.rocket.android.server.presentation.CheckServerPresenter
import chat.rocket.android.util.extensions.isValidUrl import chat.rocket.android.util.extensions.isValidUrl
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import javax.inject.Inject import javax.inject.Inject
class ServerPresenter @Inject constructor(private val view: ServerView, class ServerPresenter @Inject constructor(
private val view: ServerView,
private val strategy: CancelStrategy, private val strategy: CancelStrategy,
private val navigator: AuthenticationNavigator, private val navigator: AuthenticationNavigator,
private val serverInteractor: SaveConnectingServerInteractor, private val serverInteractor: SaveConnectingServerInteractor,
......
...@@ -6,6 +6,7 @@ import chat.rocket.android.infrastructure.LocalRepository ...@@ -6,6 +6,7 @@ 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
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.* import chat.rocket.android.util.extensions.*
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
......
...@@ -7,7 +7,7 @@ import chat.rocket.android.server.domain.* ...@@ -7,7 +7,7 @@ import chat.rocket.android.server.domain.*
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.registerPushToken import chat.rocket.android.util.extensions.registerPushToken
import chat.rocket.android.util.extensions.serverLogoUrl import chat.rocket.android.util.extensions.serverLogoUrl
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
......
...@@ -3,7 +3,6 @@ package chat.rocket.android.chatroom.domain ...@@ -3,7 +3,6 @@ package chat.rocket.android.chatroom.domain
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import chat.rocket.android.util.extensions.* import chat.rocket.android.util.extensions.*
import java.io.File
import javax.inject.Inject import javax.inject.Inject
class UriInteractor @Inject constructor(private val context: Context) { class UriInteractor @Inject constructor(private val context: Context) {
...@@ -34,9 +33,4 @@ class UriInteractor @Inject constructor(private val context: Context) { ...@@ -34,9 +33,4 @@ class UriInteractor @Inject constructor(private val context: Context) {
* Note: It should be an image. * Note: It should be an image.
*/ */
fun getBitmap(uri: Uri) = uri.getBitmpap(context) fun getBitmap(uri: Uri) = uri.getBitmpap(context)
/**
* Returns the Uri from the [File].
*/
fun getUri(file: File) = Uri.fromFile(file)
} }
\ No newline at end of file
package chat.rocket.android.chatroom.presentation package chat.rocket.android.chatroom.presentation
import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import android.os.Environment
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatroom.adapter.AutoCompleteType import chat.rocket.android.chatroom.adapter.AutoCompleteType
import chat.rocket.android.chatroom.adapter.PEOPLE import chat.rocket.android.chatroom.adapter.PEOPLE
...@@ -33,9 +31,9 @@ import chat.rocket.android.server.domain.uploadMimeTypeFilter ...@@ -33,9 +31,9 @@ import chat.rocket.android.server.domain.uploadMimeTypeFilter
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.state import chat.rocket.android.server.infraestructure.state
import chat.rocket.android.util.extension.compressImageAndGetInputStream
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.getCompressFormat import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.launchUI
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
...@@ -77,11 +75,7 @@ import kotlinx.coroutines.experimental.launch ...@@ -77,11 +75,7 @@ import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.withContext import kotlinx.coroutines.experimental.withContext
import org.threeten.bp.Instant import org.threeten.bp.Instant
import timber.log.Timber import timber.log.Timber
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream import java.io.InputStream
import java.io.File
import java.io.FileOutputStream
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
...@@ -172,10 +166,12 @@ class ChatRoomPresenter @Inject constructor( ...@@ -172,10 +166,12 @@ class ChatRoomPresenter @Inject constructor(
try { try {
if (offset == 0L) { if (offset == 0L) {
val localMessages = messagesRepository.getByRoomId(chatRoomId) val localMessages = messagesRepository.getByRoomId(chatRoomId)
val oldMessages = mapper.map(localMessages, RoomUiModel( val oldMessages = mapper.map(
localMessages, RoomUiModel(
roles = chatRoles, roles = chatRoles,
isBroadcast = chatIsBroadcast, isRoom = true isBroadcast = chatIsBroadcast, isRoom = true
)) )
)
if (oldMessages.isNotEmpty()) { if (oldMessages.isNotEmpty()) {
view.showMessages(oldMessages) view.showMessages(oldMessages)
loadMissingMessages() loadMissingMessages()
...@@ -317,10 +313,13 @@ class ChatRoomPresenter @Inject constructor( ...@@ -317,10 +313,13 @@ class ChatRoomPresenter @Inject constructor(
var inputStream: InputStream? = uriInteractor.getInputStream(uri) var inputStream: InputStream? = uriInteractor.getInputStream(uri)
if (mimeType.contains("image")) { if (mimeType.contains("image")) {
compressImage(uri, mimeType)?.let { uriInteractor.getBitmap(uri)?.let {
it.compressImageAndGetInputStream(mimeType)?.let {
inputStream = it inputStream = it
} }
} }
}
retryIO("uploadFile($roomId, $fileName, $mimeType") { retryIO("uploadFile($roomId, $fileName, $mimeType") {
client.uploadFile( client.uploadFile(
roomId, roomId,
...@@ -347,23 +346,45 @@ class ChatRoomPresenter @Inject constructor( ...@@ -347,23 +346,45 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
// Returns an InputStream of a compressed image. fun uploadDrawingImage(roomId: String, byteArray: ByteArray, msg: String) {
private suspend fun compressImage(uri: Uri, mimeType: String): InputStream? { launchUI(strategy) {
var inputStream: InputStream? = null view.showLoading()
try {
uriInteractor.getBitmap(uri)?.let {
withContext(DefaultDispatcher) { withContext(DefaultDispatcher) {
val byteArrayOutputStream = ByteArrayOutputStream() val fileName = UUID.randomUUID().toString() + ".png"
// TODO: Add an option the the app to the user be able to select the quality of the compressed image val fileSize = byteArray.size
val isCompressed = val mimeType = "image/png"
it.compress(it.getCompressFormat(mimeType), 70, byteArrayOutputStream) val maxFileSizeAllowed = settings.uploadMaxFileSize()
if (isCompressed) {
inputStream = ByteArrayInputStream(byteArrayOutputStream.toByteArray()) when {
fileSize > maxFileSizeAllowed -> {
view.showInvalidFileSize(fileSize, maxFileSizeAllowed)
} }
else -> {
retryIO("uploadFile($roomId, $fileName, $mimeType") {
client.uploadFile(
roomId,
fileName,
mimeType,
msg,
description = fileName
) {
byteArray.inputStream()
}
}
}
}
}
} catch (ex: Exception) {
Timber.d(ex, "Error uploading file")
when (ex) {
is RocketChatException -> view.showMessage(ex)
else -> view.showGenericErrorMessage()
}
} finally {
view.hideLoading()
} }
} }
return inputStream
} }
fun sendTyping() { fun sendTyping() {
...@@ -513,7 +534,8 @@ class ChatRoomPresenter @Inject constructor( ...@@ -513,7 +534,8 @@ class ChatRoomPresenter @Inject constructor(
val id = msg.id val id = msg.id
val username = msg.sender?.username ?: "" val username = msg.sender?.username ?: ""
val mention = if (mentionAuthor && currentUsername != username) "@$username" else "" val mention = if (mentionAuthor && currentUsername != username) "@$username" else ""
val room = if (roomTypeOf(roomType) is RoomType.DirectMessage) username else roomName val room =
if (roomTypeOf(roomType) is RoomType.DirectMessage) username else roomName
val chatRoomType = when (roomTypeOf(roomType)) { val chatRoomType = when (roomTypeOf(roomType)) {
is RoomType.DirectMessage -> "direct" is RoomType.DirectMessage -> "direct"
is RoomType.PrivateGroup -> "group" is RoomType.PrivateGroup -> "group"
...@@ -524,10 +546,12 @@ class ChatRoomPresenter @Inject constructor( ...@@ -524,10 +546,12 @@ class ChatRoomPresenter @Inject constructor(
view.showReplyingAction( view.showReplyingAction(
username = getDisplayName(msg.sender), username = getDisplayName(msg.sender),
replyMarkdown = "[ ]($currentServer/$chatRoomType/$room?msg=$id) $mention ", replyMarkdown = "[ ]($currentServer/$chatRoomType/$room?msg=$id) $mention ",
quotedMessage = mapper.map(message, RoomUiModel( quotedMessage = mapper.map(
message, RoomUiModel(
roles = chatRoles, roles = chatRoles,
isBroadcast = chatIsBroadcast isBroadcast = chatIsBroadcast
)).last().preview?.message ?: "" )
).last().preview?.message ?: ""
) )
} }
} }
...@@ -903,12 +927,6 @@ class ChatRoomPresenter @Inject constructor( ...@@ -903,12 +927,6 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
fun getDrawingImageUri(byteArray: ByteArray): Uri {
val bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
val file = saveDrawingImage(bitmap)
return uriInteractor.getUri(file)
}
private suspend fun subscribeTypingStatus() { private suspend fun subscribeTypingStatus() {
launch(CommonPool + strategy.jobs) { launch(CommonPool + strategy.jobs) {
client.subscribeTypingStatus(chatRoomId.toString()) { _, id -> client.subscribeTypingStatus(chatRoomId.toString()) { _, id ->
...@@ -957,9 +975,11 @@ class ChatRoomPresenter @Inject constructor( ...@@ -957,9 +975,11 @@ class ChatRoomPresenter @Inject constructor(
private fun updateMessage(streamedMessage: Message) { private fun updateMessage(streamedMessage: Message) {
launchUI(strategy) { launchUI(strategy) {
val viewModelStreamedMessage = mapper.map(streamedMessage, RoomUiModel( val viewModelStreamedMessage = mapper.map(
streamedMessage, RoomUiModel(
roles = chatRoles, isBroadcast = chatIsBroadcast roles = chatRoles, isBroadcast = chatIsBroadcast
)) )
)
val roomMessages = messagesRepository.getByRoomId(streamedMessage.roomId) val roomMessages = messagesRepository.getByRoomId(streamedMessage.roomId)
val index = roomMessages.indexOfFirst { msg -> msg.id == streamedMessage.id } val index = roomMessages.indexOfFirst { msg -> msg.id == streamedMessage.id }
...@@ -974,17 +994,4 @@ class ChatRoomPresenter @Inject constructor( ...@@ -974,17 +994,4 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
} }
private fun saveDrawingImage(bitmap: Bitmap): File {
val imageDir = "${Environment.DIRECTORY_PICTURES}/Rocket.Chat Images/"
val path = Environment.getExternalStoragePublicDirectory(imageDir)
val file = File(path, UUID.randomUUID().toString()+".png")
path.mkdirs()
file.createNewFile()
val outputStream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.PNG,70, outputStream)
outputStream.flush()
outputStream.close()
return file
}
} }
\ No newline at end of file
package chat.rocket.android.chatroom.presentation package chat.rocket.android.chatroom.presentation
import android.net.Uri
import chat.rocket.android.chatroom.uimodel.BaseUiModel import chat.rocket.android.chatroom.uimodel.BaseUiModel
import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
import chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel import chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel
...@@ -50,13 +49,6 @@ interface ChatRoomView : LoadingView, MessageView { ...@@ -50,13 +49,6 @@ interface ChatRoomView : LoadingView, MessageView {
*/ */
fun showFileSelection(filter: Array<String>?) fun showFileSelection(filter: Array<String>?)
/**
* Uploads a file to a chat room.
*
* @param uri The file URI to send.
*/
fun uploadFile(uri: Uri)
/** /**
* Shows a invalid file message. * Shows a invalid file message.
*/ */
......
...@@ -5,7 +5,6 @@ import android.content.ClipData ...@@ -5,7 +5,6 @@ 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.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
...@@ -35,7 +34,8 @@ import chat.rocket.android.chatroom.uimodel.MessageUiModel ...@@ -35,7 +34,8 @@ import chat.rocket.android.chatroom.uimodel.MessageUiModel
import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
import chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel import chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel
import chat.rocket.android.chatroom.uimodel.suggestion.PeopleSuggestionUiModel import chat.rocket.android.chatroom.uimodel.suggestion.PeopleSuggestionUiModel
import chat.rocket.android.draw.DrawingActivity import chat.rocket.android.draw.main.ui.DRAWING_BYTE_ARRAY_EXTRA_DATA
import chat.rocket.android.draw.main.ui.DrawingActivity
import chat.rocket.android.emoji.ComposerEditText import chat.rocket.android.emoji.ComposerEditText
import chat.rocket.android.emoji.Emoji import chat.rocket.android.emoji.Emoji
import chat.rocket.android.emoji.EmojiKeyboardListener import chat.rocket.android.emoji.EmojiKeyboardListener
...@@ -229,14 +229,18 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -229,14 +229,18 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
if (resultData != null && resultCode == Activity.RESULT_OK) { if (resultData != null && resultCode == Activity.RESULT_OK) {
when(requestCode){ when (requestCode) {
REQUEST_CODE_FOR_PERFORM_SAF -> { REQUEST_CODE_FOR_PERFORM_SAF -> {
uploadFile(resultData.data) presenter.uploadFile(chatRoomId, resultData.data, "")
// TODO Just leaving a blank message that comes with the file for now. In the future lets add the possibility to add a message with the file to be uploaded.
} }
REQUEST_CODE_FOR_DRAW -> { REQUEST_CODE_FOR_DRAW -> {
val result= resultData.getByteArrayExtra("bitmap") presenter.uploadDrawingImage(
val uri = presenter.getDrawingImageUri(result) chatRoomId,
uploadFile(uri) resultData.getByteArrayExtra(DRAWING_BYTE_ARRAY_EXTRA_DATA),
""
)
// TODO Just leaving a blank message that comes with the file for now. In the future lets add the possibility to add a message with the file to be uploaded.
} }
} }
} }
...@@ -486,11 +490,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -486,11 +490,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
} }
override fun uploadFile(uri: Uri) {
// TODO Just leaving a blank message that comes with the file for now. In the future lets add the possibility to add a message with the file to be uploaded.
presenter.uploadFile(chatRoomId, uri, "")
}
override fun showInvalidFileMessage() { override fun showInvalidFileMessage() {
showMessage(getString(R.string.msg_invalid_file)) showMessage(getString(R.string.msg_invalid_file))
} }
...@@ -806,11 +805,12 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -806,11 +805,12 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
activity?.let { activity?.let {
if (!ImageHelper.canWriteToExternalStorage(it)) { if (!ImageHelper.canWriteToExternalStorage(it)) {
ImageHelper.checkWritingPermission(it) ImageHelper.checkWritingPermission(it)
}else{ } else {
val intent = Intent(it, DrawingActivity::class.java) val intent = Intent(it, DrawingActivity::class.java)
startActivityForResult(intent, REQUEST_CODE_FOR_DRAW) startActivityForResult(intent, REQUEST_CODE_FOR_DRAW)
} }
} }
handler.postDelayed({ handler.postDelayed({
hideAttachmentOptions() hideAttachmentOptions()
}, 400) }, 400)
......
...@@ -9,7 +9,7 @@ import chat.rocket.android.server.domain.SettingsRepository ...@@ -9,7 +9,7 @@ import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.useSpecialCharsOnRoom import chat.rocket.android.server.domain.useSpecialCharsOnRoom
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.infraestructure.ConnectionManager import chat.rocket.android.server.infraestructure.ConnectionManager
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
......
...@@ -5,7 +5,7 @@ import chat.rocket.android.main.presentation.MainNavigator ...@@ -5,7 +5,7 @@ import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.members.uimodel.MemberUiModelMapper import chat.rocket.android.members.uimodel.MemberUiModelMapper
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
......
...@@ -14,6 +14,8 @@ import chat.rocket.android.chatroom.ui.ChatRoomActivity ...@@ -14,6 +14,8 @@ import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.chatrooms.di.ChatRoomsFragmentProvider import chat.rocket.android.chatrooms.di.ChatRoomsFragmentProvider
import chat.rocket.android.createchannel.di.CreateChannelProvider import chat.rocket.android.createchannel.di.CreateChannelProvider
import chat.rocket.android.dagger.scope.PerActivity import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.draw.main.di.DrawModule
import chat.rocket.android.draw.main.ui.DrawingActivity
import chat.rocket.android.favoritemessages.di.FavoriteMessagesFragmentProvider import chat.rocket.android.favoritemessages.di.FavoriteMessagesFragmentProvider
import chat.rocket.android.files.di.FilesFragmentProvider import chat.rocket.android.files.di.FilesFragmentProvider
import chat.rocket.android.main.di.MainModule import chat.rocket.android.main.di.MainModule
...@@ -78,4 +80,8 @@ abstract class ActivityBuilder { ...@@ -78,4 +80,8 @@ abstract class ActivityBuilder {
@PerActivity @PerActivity
@ContributesAndroidInjector(modules = [ChangeServerModule::class]) @ContributesAndroidInjector(modules = [ChangeServerModule::class])
abstract fun bindChangeServerActivity(): ChangeServerActivity abstract fun bindChangeServerActivity(): ChangeServerActivity
@PerActivity
@ContributesAndroidInjector(modules = [DrawModule::class])
abstract fun bindDrawingActivity(): DrawingActivity
} }
\ No newline at end of file
...@@ -4,7 +4,7 @@ import chat.rocket.android.chatroom.uimodel.UiModelMapper ...@@ -4,7 +4,7 @@ import chat.rocket.android.chatroom.uimodel.UiModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
......
...@@ -6,7 +6,7 @@ import chat.rocket.android.db.DatabaseManager ...@@ -6,7 +6,7 @@ import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.files.uimodel.FileUiModel import chat.rocket.android.files.uimodel.FileUiModel
import chat.rocket.android.files.uimodel.FileUiModelMapper import chat.rocket.android.files.uimodel.FileUiModelMapper
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
......
package chat.rocket.android.main.di package chat.rocket.android.main.di
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import android.content.Context
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerActivity import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.main.presentation.MainNavigator import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.main.presentation.MainView import chat.rocket.android.main.presentation.MainView
import chat.rocket.android.main.ui.MainActivity import chat.rocket.android.main.ui.MainActivity
...@@ -30,5 +28,6 @@ class MainModule { ...@@ -30,5 +28,6 @@ class MainModule {
fun provideLifecycleOwner(activity: MainActivity): LifecycleOwner = activity fun provideLifecycleOwner(activity: MainActivity): LifecycleOwner = activity
@Provides @Provides
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy = CancelStrategy(owner, jobs) fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy =
CancelStrategy(owner, jobs)
} }
\ No newline at end of file
...@@ -9,7 +9,7 @@ import chat.rocket.android.server.domain.model.Account ...@@ -9,7 +9,7 @@ import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.server.presentation.CheckServerPresenter import chat.rocket.android.server.presentation.CheckServerPresenter
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.registerPushToken import chat.rocket.android.util.extensions.registerPushToken
import chat.rocket.android.util.extensions.serverLogoUrl import chat.rocket.android.util.extensions.serverLogoUrl
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
......
...@@ -5,7 +5,7 @@ import chat.rocket.android.db.DatabaseManager ...@@ -5,7 +5,7 @@ import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.members.uimodel.MemberUiModel import chat.rocket.android.members.uimodel.MemberUiModel
import chat.rocket.android.members.uimodel.MemberUiModelMapper import chat.rocket.android.members.uimodel.MemberUiModelMapper
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
......
...@@ -3,7 +3,7 @@ package chat.rocket.android.mentions.presentention ...@@ -3,7 +3,7 @@ package chat.rocket.android.mentions.presentention
import chat.rocket.android.chatroom.uimodel.UiModelMapper import chat.rocket.android.chatroom.uimodel.UiModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.internal.rest.getMentions import chat.rocket.core.internal.rest.getMentions
......
...@@ -4,7 +4,7 @@ import chat.rocket.android.chatroom.uimodel.UiModelMapper ...@@ -4,7 +4,7 @@ import chat.rocket.android.chatroom.uimodel.UiModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
......
...@@ -4,8 +4,8 @@ import chat.rocket.android.core.behaviours.showMessage ...@@ -4,8 +4,8 @@ import chat.rocket.android.core.behaviours.showMessage
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.launchUI
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
...@@ -15,10 +15,12 @@ import chat.rocket.core.internal.rest.setAvatar ...@@ -15,10 +15,12 @@ import chat.rocket.core.internal.rest.setAvatar
import chat.rocket.core.internal.rest.updateProfile import chat.rocket.core.internal.rest.updateProfile
import javax.inject.Inject import javax.inject.Inject
class ProfilePresenter @Inject constructor(private val view: ProfileView, class ProfilePresenter @Inject constructor(
private val view: ProfileView,
private val strategy: CancelStrategy, private val strategy: CancelStrategy,
serverInteractor: GetCurrentServerInteractor, serverInteractor: GetCurrentServerInteractor,
factory: RocketChatClientFactory) { factory: RocketChatClientFactory
) {
private val serverUrl = serverInteractor.get()!! private val serverUrl = serverInteractor.get()!!
private val client: RocketChatClient = factory.create(serverUrl) private val client: RocketChatClient = factory.create(serverUrl)
private lateinit var myselfId: String private lateinit var myselfId: String
...@@ -55,11 +57,14 @@ class ProfilePresenter @Inject constructor(private val view: ProfileView, ...@@ -55,11 +57,14 @@ class ProfilePresenter @Inject constructor(private val view: ProfileView,
launchUI(strategy) { launchUI(strategy) {
view.showLoading() view.showLoading()
try { try {
if(avatarUrl!="") { if (avatarUrl != "") {
retryIO { client.setAvatar(avatarUrl) } retryIO { client.setAvatar(avatarUrl) }
} }
val user = retryIO { client.updateProfile( val user = retryIO {
userId = myselfId, email = email, name = name, username = username) } client.updateProfile(
userId = myselfId, email = email, name = name, username = username
)
}
view.showProfileUpdateSuccessfullyMessage() view.showProfileUpdateSuccessfullyMessage()
loadUserProfile() loadUserProfile()
} catch (exception: RocketChatException) { } catch (exception: RocketChatException) {
......
...@@ -4,7 +4,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy ...@@ -4,7 +4,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
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.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import javax.inject.Inject import javax.inject.Inject
......
...@@ -5,15 +5,13 @@ import chat.rocket.android.authentication.server.presentation.VersionCheckView ...@@ -5,15 +5,13 @@ import chat.rocket.android.authentication.server.presentation.VersionCheckView
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.VersionInfo import chat.rocket.android.util.VersionInfo
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatInvalidProtocolException import chat.rocket.common.RocketChatInvalidProtocolException
import chat.rocket.common.model.ServerInfo import chat.rocket.common.model.ServerInfo
import chat.rocket.core.RocketChatClient import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.rest.serverInfo import chat.rocket.core.internal.rest.serverInfo
import kotlinx.coroutines.experimental.Deferred
import kotlinx.coroutines.experimental.Job import kotlinx.coroutines.experimental.Job
import kotlinx.coroutines.experimental.async
import timber.log.Timber import timber.log.Timber
abstract class CheckServerPresenter constructor(private val strategy: CancelStrategy, abstract class CheckServerPresenter constructor(private val strategy: CancelStrategy,
...@@ -50,7 +48,7 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra ...@@ -50,7 +48,7 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
} }
} catch (ex: Exception) { } catch (ex: Exception) {
Timber.d(ex, "Error getting server info") Timber.d(ex, "Error getting server info")
when(ex) { when (ex) {
is RocketChatInvalidProtocolException -> { is RocketChatInvalidProtocolException -> {
view.errorInvalidProtocol() view.errorInvalidProtocol()
} }
......
...@@ -3,7 +3,7 @@ package chat.rocket.android.settings.password.presentation ...@@ -3,7 +3,7 @@ package chat.rocket.android.settings.password.presentation
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.core.RocketChatClient import chat.rocket.core.RocketChatClient
......
package chat.rocket.android.util.extensions
import android.graphics.Bitmap
fun Bitmap.getCompressFormat(mimeType: String): Bitmap.CompressFormat {
return when {
mimeType.contains("jpeg") -> Bitmap.CompressFormat.JPEG
mimeType.contains("webp") -> Bitmap.CompressFormat.WEBP
else -> Bitmap.CompressFormat.PNG
}
}
\ No newline at end of file
...@@ -5,8 +5,8 @@ buildscript { ...@@ -5,8 +5,8 @@ buildscript {
repositories { repositories {
google() google()
jcenter() jcenter()
maven { url 'https://maven.fabric.io/public' }
mavenCentral() mavenCentral()
maven { url 'https://maven.fabric.io/public' }
} }
dependencies { dependencies {
......
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion versions.compileSdk
defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
versionCode 1
versionName "1.0.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation libraries.kotlin
implementation libraries.coroutines
implementation libraries.lifecycleExtensions
kapt libraries.lifecycleCompiler
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="chat.rocket.android.core" />
...@@ -5,9 +5,8 @@ import androidx.lifecycle.LifecycleObserver ...@@ -5,9 +5,8 @@ import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.OnLifecycleEvent
import kotlinx.coroutines.experimental.Job import kotlinx.coroutines.experimental.Job
import javax.inject.Inject
class CancelStrategy @Inject constructor(owner: LifecycleOwner, val jobs: Job) : LifecycleObserver { class CancelStrategy(owner: LifecycleOwner, val jobs: Job) : LifecycleObserver {
init { init {
owner.lifecycle.addObserver(this) owner.lifecycle.addObserver(this)
......
<resources>
<string name="app_name">Core</string>
</resources>
...@@ -5,7 +5,7 @@ ext { ...@@ -5,7 +5,7 @@ ext {
targetSdk : 28, targetSdk : 28,
minSdk : 21, minSdk : 21,
buildTools : '28.0.0-rc2', buildTools : '28.0.0-rc2',
kotlin : '1.2.50', kotlin : '1.2.51',
coroutine : '0.23.1', coroutine : '0.23.1',
dokka : '0.9.16', dokka : '0.9.16',
...@@ -22,7 +22,7 @@ ext { ...@@ -22,7 +22,7 @@ ext {
playServices : '15.0.0', playServices : '15.0.0',
firebase : '15.0.0', firebase : '15.0.0',
room : '2.0.0-alpha1', room : '2.0.0-alpha1',
lifecycle : '2.0.0-alpha1', lifecycle : '2.0.0-beta01',
rxKotlin : '2.2.0', rxKotlin : '2.2.0',
rxAndroid : '2.0.2', rxAndroid : '2.0.2',
moshi : '1.6.0', moshi : '1.6.0',
......
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android { android {
compileSdkVersion versions.compileSdk compileSdkVersion versions.compileSdk
buildToolsVersion versions.buildTools buildToolsVersion versions.buildTools
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk targetSdkVersion versions.targetSdk
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
...@@ -18,21 +20,24 @@ android { ...@@ -18,21 +20,24 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
} }
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation libraries.appCompat implementation project(':util')
implementation project(':core')
implementation libraries.kotlin implementation libraries.kotlin
implementation libraries.coroutines
implementation libraries.appCompat
implementation libraries.constraintlayout implementation libraries.constraintlayout
implementation libraries.androidKtx implementation libraries.androidKtx
testImplementation 'junit:junit:4.12' implementation libraries.dagger
androidTestImplementation 'com.android.support.test:runner:1.0.2' implementation libraries.daggerSupport
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' kapt libraries.daggerProcessor
kapt libraries.daggerAndroidApt
} }
\ No newline at end of file
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
\ No newline at end of file
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="chat.rocket.android.draw"> package="chat.rocket.android.draw">
<application> <application android:name=".DrawApplication">
<activity <activity
android:name=".DrawingActivity" android:name=".main.ui.DrawingActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" /> android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
</application> </application>
......
package chat.rocket.android.draw
import chat.rocket.android.draw.dagger.DaggerAppComponent
import dagger.android.AndroidInjector
import dagger.android.support.DaggerApplication
class DrawApplication : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication> =
DaggerAppComponent.builder().create(this)
}
\ No newline at end of file
package chat.rocket.android.draw.dagger
import chat.rocket.android.draw.dagger.module.ActivityBuilderModule
import dagger.Component
import dagger.android.AndroidInjector
import dagger.android.support.AndroidSupportInjectionModule
import dagger.android.support.DaggerApplication
@Component(modules = [AndroidSupportInjectionModule::class, ActivityBuilderModule::class])
interface AppComponent : AndroidInjector<DaggerApplication> {
@Component.Builder
abstract class Builder : AndroidInjector.Builder<DaggerApplication>()
}
\ No newline at end of file
package chat.rocket.android.draw.dagger.module
import chat.rocket.android.draw.main.di.DrawModule
import chat.rocket.android.draw.main.ui.DrawingActivity
import dagger.Module
import dagger.android.ContributesAndroidInjector
@Module
abstract class ActivityBuilderModule {
@ContributesAndroidInjector(modules = [DrawModule::class])
abstract fun contributeDrawingActivityInjector(): DrawingActivity
}
\ No newline at end of file
package chat.rocket.android.draw.main.di
import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.draw.main.presenter.DrawView
import chat.rocket.android.draw.main.ui.DrawingActivity
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.experimental.Job
@Module
class DrawModule {
@Provides
fun provideMainView(activity: DrawingActivity): DrawView = activity
@Provides
fun provideJob() = Job()
@Provides
fun provideLifecycleOwner(activity: DrawingActivity): LifecycleOwner = activity
@Provides
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy =
CancelStrategy(owner, jobs)
}
\ No newline at end of file
package chat.rocket.android.draw.main.presenter
import android.graphics.Bitmap
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.util.extension.compressImageAndGetByteArray
import chat.rocket.android.util.extension.launchUI
import javax.inject.Inject
class DrawPresenter @Inject constructor(
private val view: DrawView,
private val strategy: CancelStrategy
) {
fun processDrawingImage(bitmap: Bitmap) {
launchUI(strategy) {
val byteArray = bitmap.compressImageAndGetByteArray("image/png")
if (byteArray != null) {
view.sendByteArray(byteArray)
} else {
view.showWrongProcessingMessage()
}
}
}
}
\ No newline at end of file
package chat.rocket.android.draw.main.presenter
interface DrawView {
/**
* Sends the [ByteArray] of the processed draw image (compressed).
*/
fun sendByteArray(byteArray: ByteArray)
/**
* Shows a message indicating that something was wrong while processing the draw image.
*/
fun showWrongProcessingMessage()
}
\ No newline at end of file
package chat.rocket.android.draw package chat.rocket.android.draw.main.ui
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Bitmap
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.SeekBar import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity import android.widget.Toast
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import chat.rocket.android.draw.R
import chat.rocket.android.draw.main.presenter.DrawPresenter
import chat.rocket.android.draw.main.presenter.DrawView
import dagger.android.support.DaggerAppCompatActivity
import kotlinx.android.synthetic.main.activity_drawing.* import kotlinx.android.synthetic.main.activity_drawing.*
import kotlinx.android.synthetic.main.color_palette_view.* import kotlinx.android.synthetic.main.color_palette_view.*
import java.io.ByteArrayOutputStream import javax.inject.Inject
class DrawingActivity : AppCompatActivity() { const val DRAWING_BYTE_ARRAY_EXTRA_DATA: String = "chat.rocket.android.DrawingByteArray"
class DrawingActivity : DaggerAppCompatActivity(), DrawView {
@Inject
lateinit var presenter: DrawPresenter
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_drawing) setContentView(R.layout.activity_drawing)
image_close_drawing.setOnClickListener { setupListeners()
finish() setupDrawTools()
colorSelector()
setPaintAlpha()
setPaintWidth()
} }
image_send_drawing.setOnClickListener {
val bStream = ByteArrayOutputStream() override fun sendByteArray(byteArray: ByteArray) {
val bitmap = custom_draw_view.getBitmap() setResult(Activity.RESULT_OK, Intent().putExtra(DRAWING_BYTE_ARRAY_EXTRA_DATA, byteArray))
bitmap.compress(Bitmap.CompressFormat.PNG, 70, bStream)
val byteArray = bStream.toByteArray()
val returnIntent = Intent()
returnIntent.putExtra("bitmap", byteArray)
setResult(Activity.RESULT_OK,returnIntent)
finish() finish()
} }
setUpDrawTools() override fun showWrongProcessingMessage() {
Toast.makeText(this, getText(R.string.msg_wrong_processing_draw_image), Toast.LENGTH_SHORT)
colorSelector() .show()
}
setPaintAlpha() private fun setupListeners() {
image_close_drawing.setOnClickListener { finish() }
setPaintWidth() image_send_drawing.setOnClickListener {
presenter.processDrawingImage(custom_draw_view.getBitmap())
}
} }
private fun setUpDrawTools() { private fun setupDrawTools() {
image_draw_eraser.setOnClickListener { image_draw_eraser.setOnClickListener {
custom_draw_view.clearCanvas() custom_draw_view.clearCanvas()
toggleDrawTools(draw_tools,false) toggleDrawTools(draw_tools, false)
} }
image_draw_width.setOnClickListener { image_draw_width.setOnClickListener {
if (draw_tools.translationY == (56).toPx){ if (draw_tools.translationY == (56).toPx) {
toggleDrawTools(draw_tools,true) toggleDrawTools(draw_tools, true)
}else if (draw_tools.translationY == (0).toPx && seekBar_width.isVisible){ } else if (draw_tools.translationY == (0).toPx && seekBar_width.isVisible) {
toggleDrawTools(draw_tools,false) toggleDrawTools(draw_tools, false)
} }
seekBar_width.isVisible = true seekBar_width.isVisible = true
seekBar_opacity.isVisible = false seekBar_opacity.isVisible = false
draw_color_palette.isVisible = false draw_color_palette.isVisible = false
} }
image_draw_opacity.setOnClickListener { image_draw_opacity.setOnClickListener {
if (draw_tools.translationY == (56).toPx){ if (draw_tools.translationY == (56).toPx) {
toggleDrawTools(draw_tools,true) toggleDrawTools(draw_tools, true)
}else if (draw_tools.translationY == (0).toPx && seekBar_opacity.isVisible){ } else if (draw_tools.translationY == (0).toPx && seekBar_opacity.isVisible) {
toggleDrawTools(draw_tools,false) toggleDrawTools(draw_tools, false)
} }
seekBar_width.isVisible = false seekBar_width.isVisible = false
seekBar_opacity.isVisible = true seekBar_opacity.isVisible = true
draw_color_palette.isVisible = false draw_color_palette.isVisible = false
} }
image_draw_color.setOnClickListener { image_draw_color.setOnClickListener {
if (draw_tools.translationY == (56).toPx){ if (draw_tools.translationY == (56).toPx) {
toggleDrawTools(draw_tools,true) toggleDrawTools(draw_tools, true)
}else if (draw_tools.translationY == (0).toPx && draw_color_palette.isVisible){ } else if (draw_tools.translationY == (0).toPx && draw_color_palette.isVisible) {
toggleDrawTools(draw_tools,false) toggleDrawTools(draw_tools, false)
} }
seekBar_width.isVisible = false seekBar_width.isVisible = false
seekBar_opacity.isVisible = false seekBar_opacity.isVisible = false
draw_color_palette.isVisible = true draw_color_palette.isVisible = true
} }
image_draw_undo.setOnClickListener { image_draw_undo.setOnClickListener {
custom_draw_view.undo() custom_draw_view.undo()
toggleDrawTools(draw_tools,false) toggleDrawTools(draw_tools, false)
} }
image_draw_redo.setOnClickListener { image_draw_redo.setOnClickListener {
custom_draw_view.redo() custom_draw_view.redo()
toggleDrawTools(draw_tools,false) toggleDrawTools(draw_tools, false)
} }
} }
private fun toggleDrawTools(view: View, showView: Boolean = true) { private fun toggleDrawTools(view: View, showView: Boolean = true) {
if (showView){ if (showView) {
view.animate().translationY((0).toPx) view.animate().translationY((0).toPx)
}else{ } else {
view.animate().translationY((56).toPx) view.animate().translationY((56).toPx)
} }
} }
private fun colorSelector() { private fun colorSelector() {
image_color_black.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_black,null))
scaleColorView(image_color_black)
}
image_color_red.setOnClickListener { image_color_red.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_red,null)) custom_draw_view.setColor(
ResourcesCompat.getColor(resources, R.color.color_red, null)
)
scaleColorView(image_color_red) scaleColorView(image_color_red)
} }
image_color_yellow.setOnClickListener { image_color_yellow.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_yellow,null)) custom_draw_view.setColor(
ResourcesCompat.getColor(
resources,
R.color.color_yellow, null
)
)
scaleColorView(image_color_yellow) scaleColorView(image_color_yellow)
} }
image_color_green.setOnClickListener { image_color_green.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_green,null)) custom_draw_view.setColor(
ResourcesCompat.getColor(
resources,
R.color.color_green, null
)
)
scaleColorView(image_color_green) scaleColorView(image_color_green)
} }
image_color_blue.setOnClickListener { image_color_blue.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_blue,null)) custom_draw_view.setColor(
ResourcesCompat.getColor(resources, R.color.color_blue, null)
)
scaleColorView(image_color_blue) scaleColorView(image_color_blue)
} }
image_color_pink.setOnClickListener { image_color_pink.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_pink,null)) custom_draw_view.setColor(
ResourcesCompat.getColor(
resources,
R.color.color_pink, null
)
)
scaleColorView(image_color_pink) scaleColorView(image_color_pink)
} }
image_color_brown.setOnClickListener { image_color_brown.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_brown,null)) custom_draw_view.setColor(
ResourcesCompat.getColor(
resources,
R.color.color_brown, null
)
)
scaleColorView(image_color_brown) scaleColorView(image_color_brown)
} }
} }
...@@ -156,7 +195,7 @@ class DrawingActivity : AppCompatActivity() { ...@@ -156,7 +195,7 @@ class DrawingActivity : AppCompatActivity() {
} }
private fun setPaintWidth() { private fun setPaintWidth() {
seekBar_width.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener{ seekBar_width.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
custom_draw_view.setStrokeWidth(progress.toFloat()) custom_draw_view.setStrokeWidth(progress.toFloat())
} }
...@@ -168,7 +207,7 @@ class DrawingActivity : AppCompatActivity() { ...@@ -168,7 +207,7 @@ class DrawingActivity : AppCompatActivity() {
} }
private fun setPaintAlpha() { private fun setPaintAlpha() {
seekBar_opacity.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener{ seekBar_opacity.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
custom_draw_view.setAlpha(progress) custom_draw_view.setAlpha(progress)
} }
......
...@@ -6,5 +6,4 @@ import java.io.Serializable ...@@ -6,5 +6,4 @@ import java.io.Serializable
interface Action : Serializable { interface Action : Serializable {
fun perform(path: Path) fun perform(path: Path)
} }
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".DrawingActivity"> tools:context=".ui.DrawingActivity">
<chat.rocket.android.draw.widget.CustomDrawView <chat.rocket.android.draw.widget.CustomDrawView
android:id="@+id/custom_draw_view" android:id="@+id/custom_draw_view"
...@@ -17,143 +16,143 @@ ...@@ -17,143 +16,143 @@
android:id="@+id/image_close_drawing" android:id="@+id/image_close_drawing"
android:layout_width="56dp" android:layout_width="56dp"
android:layout_height="56dp" android:layout_height="56dp"
android:background="@color/color_white"
android:foreground="?selectableItemBackgroundBorderless"
android:padding="16dp"
android:src="@drawable/ic_close_black_24dp" android:src="@drawable/ic_close_black_24dp"
android:tint="@color/icon_color" android:tint="@color/icon_color"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent" />
android:background="@color/color_white"
android:foreground="?selectableItemBackgroundBorderless" />
<ImageView <ImageView
android:id="@+id/image_send_drawing" android:id="@+id/image_send_drawing"
android:layout_width="56dp" android:layout_width="56dp"
android:layout_height="56dp" android:layout_height="56dp"
android:src="@drawable/ic_send_black_24dp" android:background="@color/color_white"
android:foreground="?selectableItemBackgroundBorderless"
android:padding="16dp" android:padding="16dp"
android:src="@drawable/ic_send_black_24dp"
android:tint="@color/colorAccent" android:tint="@color/colorAccent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent" />
android:background="@color/color_white"
android:foreground="?selectableItemBackgroundBorderless" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/draw_tools" android:id="@+id/draw_tools"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/color_white" android:background="@color/color_white"
android:elevation="4dp" android:elevation="4dp"
android:translationY="56dp" > android:translationY="56dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView <ImageView
android:id="@+id/image_draw_eraser" android:id="@+id/image_draw_eraser"
android:layout_width="56dp" android:layout_width="56dp"
android:layout_height="56dp" android:layout_height="56dp"
android:src="@drawable/ic_eraser_black_24dp" android:foreground="?selectableItemBackground"
android:padding="16dp" android:padding="16dp"
android:src="@drawable/ic_eraser_black_24dp"
android:tint="@color/icon_color" android:tint="@color/icon_color"
android:foreground="?selectableItemBackground" app:layout_constraintEnd_toStartOf="@id/image_draw_width"
app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/image_draw_width" app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent"/>
<ImageView <ImageView
android:id="@+id/image_draw_width" android:id="@+id/image_draw_width"
android:layout_width="56dp" android:layout_width="56dp"
android:layout_height="56dp" android:layout_height="56dp"
android:src="@drawable/ic_adjust_black_24dp" android:foreground="?selectableItemBackground"
android:padding="16dp" android:padding="16dp"
android:src="@drawable/ic_adjust_black_24dp"
android:tint="@color/icon_color" android:tint="@color/icon_color"
android:foreground="?selectableItemBackground"
app:layout_constraintStart_toEndOf="@id/image_draw_eraser"
app:layout_constraintEnd_toStartOf="@id/image_draw_color" app:layout_constraintEnd_toStartOf="@id/image_draw_color"
app:layout_constraintTop_toTopOf="parent"/> app:layout_constraintStart_toEndOf="@id/image_draw_eraser"
app:layout_constraintTop_toTopOf="parent" />
<ImageView <ImageView
android:id="@+id/image_draw_color" android:id="@+id/image_draw_color"
android:layout_width="56dp" android:layout_width="56dp"
android:layout_height="56dp" android:layout_height="56dp"
android:src="@drawable/ic_color_lens_black_24dp" android:foreground="?selectableItemBackground"
android:padding="16dp" android:padding="16dp"
android:src="@drawable/ic_color_lens_black_24dp"
android:tint="@color/icon_color" android:tint="@color/icon_color"
android:foreground="?selectableItemBackground"
app:layout_constraintStart_toEndOf="@id/image_draw_width"
app:layout_constraintEnd_toStartOf="@id/image_draw_opacity" app:layout_constraintEnd_toStartOf="@id/image_draw_opacity"
app:layout_constraintTop_toTopOf="parent"/> app:layout_constraintStart_toEndOf="@id/image_draw_width"
app:layout_constraintTop_toTopOf="parent" />
<ImageView <ImageView
android:id="@+id/image_draw_opacity" android:id="@+id/image_draw_opacity"
android:layout_width="56dp" android:layout_width="56dp"
android:layout_height="56dp" android:layout_height="56dp"
android:src="@drawable/ic_opacity_black_24dp" android:foreground="?selectableItemBackground"
android:padding="16dp" android:padding="16dp"
android:src="@drawable/ic_opacity_black_24dp"
android:tint="@color/icon_color" android:tint="@color/icon_color"
android:foreground="?selectableItemBackground"
app:layout_constraintStart_toEndOf="@id/image_draw_color"
app:layout_constraintEnd_toStartOf="@id/image_draw_undo" app:layout_constraintEnd_toStartOf="@id/image_draw_undo"
app:layout_constraintTop_toTopOf="parent"/> app:layout_constraintStart_toEndOf="@id/image_draw_color"
app:layout_constraintTop_toTopOf="parent" />
<ImageView <ImageView
android:id="@+id/image_draw_undo" android:id="@+id/image_draw_undo"
android:layout_width="56dp" android:layout_width="56dp"
android:layout_height="56dp" android:layout_height="56dp"
android:src="@drawable/ic_undo_black_24dp" android:foreground="?selectableItemBackground"
android:padding="16dp" android:padding="16dp"
android:src="@drawable/ic_undo_black_24dp"
android:tint="@color/icon_color" android:tint="@color/icon_color"
android:foreground="?selectableItemBackground"
app:layout_constraintStart_toEndOf="@id/image_draw_opacity"
app:layout_constraintEnd_toStartOf="@id/image_draw_redo" app:layout_constraintEnd_toStartOf="@id/image_draw_redo"
app:layout_constraintStart_toEndOf="@id/image_draw_opacity"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<ImageView <ImageView
android:id="@+id/image_draw_redo" android:id="@+id/image_draw_redo"
android:layout_width="56dp" android:layout_width="56dp"
android:layout_height="56dp" android:layout_height="56dp"
android:src="@drawable/ic_redo_black_24dp" android:foreground="?selectableItemBackground"
android:padding="16dp" android:padding="16dp"
android:src="@drawable/ic_redo_black_24dp"
android:tint="@color/icon_color" android:tint="@color/icon_color"
android:foreground="?selectableItemBackground"
app:layout_constraintStart_toEndOf="@id/image_draw_undo"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/image_draw_undo"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<SeekBar <SeekBar
android:id="@+id/seekBar_width" android:id="@+id/seekBar_width"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="56dp" android:layout_height="56dp"
app:layout_constraintStart_toStartOf="parent" android:paddingStart="16dp"
app:layout_constraintEnd_toEndOf="parent" android:paddingEnd="16dp"
app:layout_constraintTop_toBottomOf="@id/image_draw_eraser" android:progress="8"
android:progressTint="@color/colorAccent" android:progressTint="@color/colorAccent"
android:thumbTint="@color/colorAccent" android:thumbTint="@color/colorAccent"
android:progress="8" app:layout_constraintEnd_toEndOf="parent"
android:paddingStart="16dp" app:layout_constraintStart_toStartOf="parent"
android:paddingEnd="16dp" /> app:layout_constraintTop_toBottomOf="@id/image_draw_eraser" />
<SeekBar <SeekBar
android:id="@+id/seekBar_opacity" android:id="@+id/seekBar_opacity"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="56dp" android:layout_height="56dp"
app:layout_constraintStart_toStartOf="parent" android:paddingStart="16dp"
app:layout_constraintEnd_toEndOf="parent" android:paddingEnd="16dp"
app:layout_constraintTop_toBottomOf="@id/image_draw_eraser"
android:progress="100" android:progress="100"
android:progressTint="@color/colorAccent" android:progressTint="@color/colorAccent"
android:thumbTint="@color/colorAccent" android:thumbTint="@color/colorAccent"
android:paddingStart="16dp" app:layout_constraintEnd_toEndOf="parent"
android:paddingEnd="16dp" /> app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/image_draw_eraser" />
<include <include
android:id="@+id/draw_color_palette" android:id="@+id/draw_color_palette"
layout="@layout/color_palette_view" layout="@layout/color_palette_view"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="56dp" android:layout_height="56dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/image_draw_eraser" /> app:layout_constraintTop_toBottomOf="@id/image_draw_eraser" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
......
<resources> <resources>
<string name="app_name">Draw</string> <string name="app_name">Draw</string>
// TODO: Add other translations like we did for the app module.
<string name="msg_wrong_processing_draw_image">Something was wrong while processing the draw image. Please, try again later.</string>
</resources> </resources>
include ':app', ':player', ':emoji', ':draw' //, ':wear' include ':app', ':player', ':emoji', ':draw', ':util', ':core' //, ':wear'
\ No newline at end of file \ No newline at end of file
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion versions.compileSdk
defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
versionCode 1
versionName "1.0.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':core')
implementation libraries.kotlin
implementation libraries.coroutines
implementation libraries.coroutinesAndroid
// TODO This is a dependency from the core module, but the util module are unable to get that dependencies. Check why it is occurring since transitive is enable by default
implementation libraries.lifecycleExtensions
kapt libraries.lifecycleCompiler
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="chat.rocket.android.util" />
package chat.rocket.android.util.extensions package chat.rocket.android.util.extension
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import kotlinx.coroutines.experimental.CoroutineScope import kotlinx.coroutines.experimental.CoroutineScope
......
package chat.rocket.android.util.extension
import android.graphics.Bitmap
import kotlinx.coroutines.experimental.DefaultDispatcher
import kotlinx.coroutines.experimental.withContext
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
/**
* Compress a [Bitmap] image.
*
* @param mimeType The MimeType of what the compressed image should be.
* @return An [InputStream] of a compressed image, otherwise null if the compression couldn't be done.
*/
suspend fun Bitmap.compressImageAndGetInputStream(mimeType: String): InputStream? {
var inputStream: InputStream? = null
withContext(DefaultDispatcher) {
val byteArrayOutputStream = ByteArrayOutputStream()
// TODO: Add an option the the app to the user be able to select the quality of the compressed image
val isCompressed =
this.compress(mimeType.getCompressFormat(), 70, byteArrayOutputStream)
if (isCompressed) {
inputStream = ByteArrayInputStream(byteArrayOutputStream.toByteArray())
}
}
return inputStream
}
/**
* Compress a [Bitmap] image.
*
* @param mimeType The MimeType of what the compressed image should be.
* @return An [ByteArray] of a compressed image, otherwise null if the compression couldn't be done.
*/
suspend fun Bitmap.compressImageAndGetByteArray(mimeType: String): ByteArray? {
var byteArray: ByteArray? = null
withContext(DefaultDispatcher) {
val byteArrayOutputStream = ByteArrayOutputStream()
// TODO: Add an option the the app to the user be able to select the quality of the compressed image
val isCompressed =
this.compress(mimeType.getCompressFormat(), 70, byteArrayOutputStream)
if (isCompressed) {
byteArray = byteArrayOutputStream.toByteArray()
}
}
return byteArray
}
/**
* Gets the [Bitmap.CompressFormat] based on the image MimeType.
* Note: Supported formats are: PNG, JPEG and WEBP.
*/
fun String.getCompressFormat(): Bitmap.CompressFormat {
return when {
this.contains("jpeg") -> Bitmap.CompressFormat.JPEG
this.contains("webp") -> Bitmap.CompressFormat.WEBP
else -> Bitmap.CompressFormat.PNG
}
}
\ No newline at end of file
<resources>
<string name="app_name">Util</string>
</resources>
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