Commit 7b220038 authored by Divyanshu Bhargava's avatar Divyanshu Bhargava

Merge branch 'android-draw-new' into android-draw

# Conflicts:
#	app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
parents b250364f 23df6281
...@@ -53,6 +53,7 @@ dependencies { ...@@ -53,6 +53,7 @@ dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation project(':player') implementation project(':player')
implementation project(':draw')
implementation libraries.kotlin implementation libraries.kotlin
implementation libraries.coroutines implementation libraries.coroutines
......
package chat.rocket.android.authentication.server.presentation package chat.rocket.android.authentication.server.presentation
import okhttp3.HttpUrl
interface VersionCheckView { interface VersionCheckView {
/** /**
* Alerts the user about the server version not meeting the recommended server version. * Alerts the user about the server version not meeting the recommended server version.
...@@ -26,4 +28,9 @@ interface VersionCheckView { ...@@ -26,4 +28,9 @@ interface VersionCheckView {
* Alters the user this protocol is invalid. This is optional. * Alters the user this protocol is invalid. This is optional.
*/ */
fun errorInvalidProtocol() {} fun errorInvalidProtocol() {}
/**
* Updates the server URL after a URL redirection
*/
fun updateServerUrl(url: HttpUrl) {}
} }
\ No newline at end of file
...@@ -20,6 +20,7 @@ import chat.rocket.android.util.extensions.* ...@@ -20,6 +20,7 @@ import chat.rocket.android.util.extensions.*
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_server.* import kotlinx.android.synthetic.main.fragment_authentication_server.*
import okhttp3.HttpUrl
import javax.inject.Inject import javax.inject.Inject
class ServerFragment : Fragment(), ServerView { class ServerFragment : Fragment(), ServerView {
...@@ -41,6 +42,7 @@ class ServerFragment : Fragment(), ServerView { ...@@ -41,6 +42,7 @@ class ServerFragment : Fragment(), ServerView {
} }
private var protocol = "https://" private var protocol = "https://"
private var ignoreChange = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -72,22 +74,27 @@ class ServerFragment : Fragment(), ServerView { ...@@ -72,22 +74,27 @@ class ServerFragment : Fragment(), ServerView {
protocol = "https://" protocol = "https://"
} }
1 -> { 1 -> {
ui{ if (ignoreChange) {
AlertDialog.Builder(it) protocol = "http://"
.setTitle(R.string.msg_warning) } else {
.setMessage(R.string.msg_http_insecure) ui {
.setPositiveButton(R.string.msg_proceed) { _, _ -> AlertDialog.Builder(it)
protocol = "http://" .setTitle(R.string.msg_warning)
} .setMessage(R.string.msg_http_insecure)
.setNegativeButton(R.string.msg_cancel) { _, _ -> .setPositiveButton(R.string.msg_proceed) { _, _ ->
text_server_protocol.setSelection(0) protocol = "http://"
} }
.setCancelable(false) .setNegativeButton(R.string.msg_cancel) { _, _ ->
.create() text_server_protocol.setSelection(0)
.show() }
.setCancelable(false)
.create()
.show()
}
} }
} }
} }
ignoreChange = false
} }
override fun onNothingSelected(parent: AdapterView<*>?) { override fun onNothingSelected(parent: AdapterView<*>?) {
...@@ -174,13 +181,23 @@ class ServerFragment : Fragment(), ServerView { ...@@ -174,13 +181,23 @@ class ServerFragment : Fragment(), ServerView {
showMessage(R.string.msg_invalid_server_protocol) showMessage(R.string.msg_invalid_server_protocol)
} }
override fun updateServerUrl(url: HttpUrl) {
if (activity != null && view != null) {
if (url.scheme() == "https") text_server_protocol.setSelection(0) else text_server_protocol.setSelection(1)
protocol = "${url.scheme()}://"
val serverUrl = url.toString().removePrefix("${url.scheme()}://")
text_server_url.textContent = serverUrl
}
}
private fun performConnect() { private fun performConnect() {
ui { ui {
deepLinkInfo?.let { deepLinkInfo?.let {
presenter.deepLink(it) presenter.deepLink(it)
}.ifNull { }.ifNull {
val url = text_server_url.textContent.ifEmpty(text_server_url.hintContent) val url = text_server_url.textContent.ifEmpty(text_server_url.hintContent)
presenter.connect("${protocol}${url.sanitize()}") presenter.connect("$protocol${url.sanitize()}")
} }
} }
} }
......
...@@ -18,13 +18,12 @@ import com.google.android.flexbox.FlexboxLayoutManager ...@@ -18,13 +18,12 @@ import com.google.android.flexbox.FlexboxLayoutManager
import ru.whalemare.sheetmenu.extension.inflate import ru.whalemare.sheetmenu.extension.inflate
import ru.whalemare.sheetmenu.extension.toList import ru.whalemare.sheetmenu.extension.toList
abstract class BaseViewHolder<T : BaseViewModel<*>>( abstract class BaseViewHolder<T : BaseViewModel<*>>(
itemView: View, itemView: View,
private val listener: ActionsListener, private val listener: ActionsListener,
var reactionListener: EmojiReactionListener? = null var reactionListener: EmojiReactionListener? = null
) : RecyclerView.ViewHolder(itemView), ) : RecyclerView.ViewHolder(itemView),
MenuItem.OnMenuItemClickListener { MenuItem.OnMenuItemClickListener {
var data: T? = null var data: T? = null
init { init {
...@@ -78,14 +77,21 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>( ...@@ -78,14 +77,21 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>(
private val onClickListener = { view: View -> private val onClickListener = { view: View ->
if (data?.message?.isSystemMessage() == false) { if (data?.message?.isSystemMessage() == false) {
val menuItems = view.context.inflate(R.menu.message_actions).toList() data?.message?.let {
menuItems.find { it.itemId == R.id.action_menu_msg_pin_unpin }?.apply { val menuItems = view.context.inflate(R.menu.message_actions).toList()
val isPinned = data?.message?.pinned ?: false menuItems.find { it.itemId == R.id.action_message_unpin }?.apply {
setTitle(if (isPinned) R.string.action_msg_unpin else R.string.action_msg_pin) setTitle(if (it.pinned) R.string.action_msg_unpin else R.string.action_msg_pin)
isChecked = isPinned isChecked = it.pinned
}
menuItems.find { it.itemId == R.id.action_message_star }?.apply {
val isStarred = it.starred?.isNotEmpty() ?: false
setTitle(if (isStarred) R.string.action_msg_unstar else R.string.action_msg_star)
isChecked = isStarred
}
val adapter = ActionListAdapter(menuItems, this@BaseViewHolder)
BottomSheetMenu(adapter).show(view.context)
} }
val adapter = ActionListAdapter(menuItems, this@BaseViewHolder)
BottomSheetMenu(adapter).show(view.context)
} }
} }
......
...@@ -181,25 +181,39 @@ class ChatRoomAdapter( ...@@ -181,25 +181,39 @@ class ChatRoomAdapter(
} }
private val actionsListener = object : BaseViewHolder.ActionsListener { private val actionsListener = object : BaseViewHolder.ActionsListener {
override fun isActionsEnabled(): Boolean = enableActions override fun isActionsEnabled(): Boolean = enableActions
override fun onActionSelected(item: MenuItem, message: Message) { override fun onActionSelected(item: MenuItem, message: Message) {
message.apply { message.apply {
when (item.itemId) { when (item.itemId) {
R.id.action_menu_msg_delete -> presenter?.deleteMessage(roomId, id) R.id.action_message_reply -> {
R.id.action_menu_msg_quote -> presenter?.citeMessage(roomType, id, false) presenter?.citeMessage(roomType, id, true)
R.id.action_menu_msg_reply -> presenter?.citeMessage(roomType, id, true) }
R.id.action_menu_msg_copy -> presenter?.copyMessage(id) R.id.action_message_quote -> {
R.id.action_menu_msg_edit -> presenter?.editMessage(roomId, id, message.message) presenter?.citeMessage(roomType, id, false)
R.id.action_menu_msg_pin_unpin -> { }
with(item) { R.id.action_message_copy -> {
if (!isChecked) { presenter?.copyMessage(id)
presenter?.pinMessage(id) }
} else { R.id.action_message_edit -> {
presenter?.unpinMessage(id) presenter?.editMessage(roomId, id, message.message)
} }
R.id.action_message_star -> {
if (!item.isChecked) {
presenter?.starMessage(id)
} else {
presenter?.unstarMessage(id)
}
}
R.id.action_message_unpin -> {
if (!item.isChecked) {
presenter?.pinMessage(id)
} else {
presenter?.unpinMessage(id)
} }
} }
R.id.action_message_delete -> presenter?.deleteMessage(roomId, id)
R.id.action_menu_msg_react -> presenter?.showReactions(id) R.id.action_menu_msg_react -> presenter?.showReactions(id)
else -> TODO("Not implemented") else -> TODO("Not implemented")
} }
......
...@@ -3,6 +3,7 @@ package chat.rocket.android.chatroom.adapter ...@@ -3,6 +3,7 @@ package chat.rocket.android.chatroom.adapter
import android.graphics.Color import android.graphics.Color
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.view.View import android.view.View
import androidx.core.view.isVisible
import chat.rocket.android.chatroom.viewmodel.MessageViewModel import chat.rocket.android.chatroom.viewmodel.MessageViewModel
import chat.rocket.android.util.extensions.setVisible import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.widget.emoji.EmojiReactionListener import chat.rocket.android.widget.emoji.EmojiReactionListener
...@@ -35,10 +36,9 @@ class MessageViewHolder( ...@@ -35,10 +36,9 @@ class MessageViewHolder(
text_content.setTextColor( text_content.setTextColor(
if (data.isTemporary) Color.GRAY else Color.BLACK if (data.isTemporary) Color.GRAY else Color.BLACK
) )
if (!data.message.isSystemMessage() && data.message.editedBy != null){ data.message.let {
text_edit_indicator.setVisible(true) text_edit_indicator.isVisible = it.isSystemMessage() && it.editedBy != null
}else{ image_star_indicator.isVisible = it.starred?.isNotEmpty() ?: false
text_edit_indicator.setVisible(false)
} }
} }
} }
......
...@@ -29,6 +29,8 @@ import chat.rocket.common.model.roomTypeOf ...@@ -29,6 +29,8 @@ import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.internal.realtime.setTypingStatus import chat.rocket.core.internal.realtime.setTypingStatus
import chat.rocket.core.internal.realtime.socket.model.State import chat.rocket.core.internal.realtime.socket.model.State
import chat.rocket.core.internal.realtime.subscribeTypingStatus
import chat.rocket.core.internal.realtime.unsubscribe
import chat.rocket.core.internal.rest.* import chat.rocket.core.internal.rest.*
import chat.rocket.core.model.Command import chat.rocket.core.model.Command
import chat.rocket.core.model.Message import chat.rocket.core.model.Message
...@@ -70,8 +72,11 @@ class ChatRoomPresenter @Inject constructor( ...@@ -70,8 +72,11 @@ class ChatRoomPresenter @Inject constructor(
private var chatRoomId: String? = null private var chatRoomId: String? = null
private var chatRoomType: String? = null private var chatRoomType: String? = null
private val stateChannel = Channel<State>() private val stateChannel = Channel<State>()
private var typingStatusSubscriptionId: String? = null
private var lastState = manager.state private var lastState = manager.state
private var typingStatusList = arrayListOf<String>()
fun setupChatRoom() { fun setupChatRoom() {
launchUI(strategy) { launchUI(strategy) {
...@@ -115,6 +120,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -115,6 +120,7 @@ class ChatRoomPresenter @Inject constructor(
view.hideLoading() view.hideLoading()
} }
subscribeTypingStatus()
if (offset == 0L) { if (offset == 0L) {
subscribeState() subscribeState()
} }
...@@ -152,6 +158,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -152,6 +158,7 @@ class ChatRoomPresenter @Inject constructor(
groupable = false, groupable = false,
parseUrls = false, parseUrls = false,
pinned = false, pinned = false,
starred = emptyList(),
mentions = emptyList(), mentions = emptyList(),
reactions = null, reactions = null,
senderAlias = null, senderAlias = null,
...@@ -160,9 +167,24 @@ class ChatRoomPresenter @Inject constructor( ...@@ -160,9 +167,24 @@ class ChatRoomPresenter @Inject constructor(
urls = null, urls = null,
isTemporary = true isTemporary = true
) )
messagesRepository.save(newMessage) try {
view.showNewMessage(mapper.map(newMessage)) val message = client.sendMessage(id, chatRoomId, text)
client.sendMessage(id, chatRoomId, text) messagesRepository.save(newMessage)
view.showNewMessage(mapper.map(newMessage))
message
} catch (ex: Exception) {
// Ok, not very beautiful, but the backend sends us a not valid response
// When someone sends a message on a read-only channel, so we just ignore it
// and show a generic error message
// TODO - remove the generic message when we implement :userId:/message subscription
if (ex is IllegalStateException) {
Timber.d(ex, "Probably a read-only problem...")
view.showGenericErrorMessage()
} else {
// some other error, just rethrow it...
throw ex
}
}
} else { } else {
client.updateMessage(chatRoomId, messageId, text) client.updateMessage(chatRoomId, messageId, text)
} }
...@@ -311,14 +333,6 @@ class ChatRoomPresenter @Inject constructor( ...@@ -311,14 +333,6 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
fun unsubscribeMessages(chatRoomId: String) {
manager.removeStatusChannel(stateChannel)
manager.unsubscribeRoomMessages(chatRoomId)
// All messages during the subscribed period are assumed to be read,
// and lastSeen is updated as the time when the user leaves the room
markRoomAsRead(chatRoomId)
}
/** /**
* Delete the message with the given id. * Delete the message with the given id.
* *
...@@ -416,6 +430,34 @@ class ChatRoomPresenter @Inject constructor( ...@@ -416,6 +430,34 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
fun starMessage(messageId: String) {
launchUI(strategy) {
if (!permissions.allowedMessageStarring()) {
view.showMessage(R.string.permission_starring_not_allowed)
return@launchUI
}
try {
retryIO("starMessage($messageId)") { client.starMessage(messageId) }
} catch (e: RocketChatException) {
Timber.e(e)
}
}
}
fun unstarMessage(messageId: String) {
launchUI(strategy) {
if (!permissions.allowedMessageStarring()) {
view.showMessage(R.string.permission_starring_not_allowed)
return@launchUI
}
try {
retryIO("unstarMessage($messageId)") { client.unstarMessage(messageId) }
} catch (e: RocketChatException) {
Timber.e(e)
}
}
}
fun pinMessage(messageId: String) { fun pinMessage(messageId: String) {
launchUI(strategy) { launchUI(strategy) {
if (!permissions.allowedMessagePinning()) { if (!permissions.allowedMessagePinning()) {
...@@ -636,6 +678,57 @@ class ChatRoomPresenter @Inject constructor( ...@@ -636,6 +678,57 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
fun disconnect() {
unsubscribeTypingStatus()
if (chatRoomId != null) {
unsubscribeMessages(chatRoomId.toString())
}
}
private suspend fun subscribeTypingStatus() {
client.subscribeTypingStatus(chatRoomId.toString()) { _, id ->
typingStatusSubscriptionId = id
}
for (typingStatus in client.typingStatusChannel) {
processTypingStatus(typingStatus)
}
}
private fun processTypingStatus(typingStatus: Pair<String, Boolean>) {
if (!typingStatusList.any { username -> username == typingStatus.first }) {
if (typingStatus.second) {
typingStatusList.add(typingStatus.first)
}
} else {
typingStatusList.find { username -> username == typingStatus.first }?.let {
typingStatusList.remove(it)
if (typingStatus.second) {
typingStatusList.add(typingStatus.first)
}
}
}
if (typingStatusList.isNotEmpty()) {
view.showTypingStatus(typingStatusList)
} else {
view.hideTypingStatusView()
}
}
private fun unsubscribeTypingStatus() {
typingStatusSubscriptionId?.let {
client.unsubscribe(it)
}
}
private fun unsubscribeMessages(chatRoomId: String) {
manager.removeStatusChannel(stateChannel)
manager.unsubscribeRoomMessages(chatRoomId)
// All messages during the subscribed period are assumed to be read,
// and lastSeen is updated as the time when the user leaves the room
markRoomAsRead(chatRoomId)
}
private fun updateMessage(streamedMessage: Message) { private fun updateMessage(streamedMessage: Message) {
launchUI(strategy) { launchUI(strategy) {
val viewModelStreamedMessage = mapper.map(streamedMessage) val viewModelStreamedMessage = mapper.map(streamedMessage)
...@@ -652,4 +745,4 @@ class ChatRoomPresenter @Inject constructor( ...@@ -652,4 +745,4 @@ class ChatRoomPresenter @Inject constructor(
} }
} }
} }
} }
\ No newline at end of file
...@@ -25,6 +25,18 @@ interface ChatRoomView : LoadingView, MessageView { ...@@ -25,6 +25,18 @@ interface ChatRoomView : LoadingView, MessageView {
*/ */
fun sendMessage(text: String) fun sendMessage(text: String)
/**
* Shows the username(s) of the user(s) who is/are typing in the chat room.
*
* @param usernameList The list of username to show.
*/
fun showTypingStatus(usernameList: ArrayList<String>)
/**
* Hides the typing status view.
*/
fun hideTypingStatusView()
/** /**
* Perform file selection with the mime type [filter] * Perform file selection with the mime type [filter]
*/ */
......
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.app.Dialog
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.Resources
import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.Environment
import android.os.Handler import android.os.Handler
import android.support.annotation.DrawableRes import android.support.annotation.DrawableRes
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.support.v4.content.res.ResourcesCompat
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
import android.view.* import android.view.*
import android.widget.ImageView
import android.widget.SeekBar
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatroom.adapter.* import chat.rocket.android.chatroom.adapter.*
import chat.rocket.android.chatroom.presentation.ChatRoomPresenter import chat.rocket.android.chatroom.presentation.ChatRoomPresenter
...@@ -31,7 +23,6 @@ import chat.rocket.android.chatroom.viewmodel.MessageViewModel ...@@ -31,7 +23,6 @@ import chat.rocket.android.chatroom.viewmodel.MessageViewModel
import chat.rocket.android.chatroom.viewmodel.suggestion.ChatRoomSuggestionViewModel import chat.rocket.android.chatroom.viewmodel.suggestion.ChatRoomSuggestionViewModel
import chat.rocket.android.chatroom.viewmodel.suggestion.CommandSuggestionViewModel import chat.rocket.android.chatroom.viewmodel.suggestion.CommandSuggestionViewModel
import chat.rocket.android.chatroom.viewmodel.suggestion.PeopleSuggestionViewModel import chat.rocket.android.chatroom.viewmodel.suggestion.PeopleSuggestionViewModel
import chat.rocket.android.helper.AndroidPermissionsHelper
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.helper.KeyboardHelper import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.MessageParser import chat.rocket.android.helper.MessageParser
...@@ -41,16 +32,11 @@ import chat.rocket.core.internal.realtime.socket.model.State ...@@ -41,16 +32,11 @@ import chat.rocket.core.internal.realtime.socket.model.State
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.color_palette_view.*
import kotlinx.android.synthetic.main.drawing_view.*
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.fragment_chat_room.* import kotlinx.android.synthetic.main.fragment_chat_room.*
import kotlinx.android.synthetic.main.message_attachment_options.* import kotlinx.android.synthetic.main.message_attachment_options.*
import kotlinx.android.synthetic.main.message_composer.* import kotlinx.android.synthetic.main.message_composer.*
import kotlinx.android.synthetic.main.message_list.* import kotlinx.android.synthetic.main.message_list.*
import java.io.File
import java.io.FileOutputStream
import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import javax.inject.Inject import javax.inject.Inject
...@@ -645,218 +631,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -645,218 +631,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_add_reaction.setOnClickListener { view -> button_add_reaction.setOnClickListener { view ->
openEmojiKeyboardPopup() openEmojiKeyboardPopup()
} }
button_drawing.setOnClickListener{
showDrawingView()
handler.postDelayed({
hideAttachmentOptions()
}, 400)
}
}
}
private fun showDrawingView() {
val drawDialog = Dialog(activity,R.style.DrawingDialogStyle)
drawDialog.setContentView(R.layout.drawing_view)
drawDialog.apply {
colorSelector(drawDialog)
setClickListner(drawDialog)
setPaintWidth(drawDialog)
setPaintAlpha(drawDialog)
}
drawDialog.show()
}
private fun setClickListner(drawDialog: Dialog) {
drawDialog.apply {
image_send_drawing.setOnClickListener {
if (!canWriteToExternalStorage()) {
checkWritingPermission()
}else{
val bitmap = custom_draw_view.getBitmap()
val uri = saveImage(bitmap)
if (uri != null) {
uploadFile(uri)
}
drawDialog.dismiss()
}
}
image_close_drawing.setOnClickListener {
drawDialog.dismiss()
}
image_draw_eraser.setOnClickListener {
custom_draw_view.clearCanvas()
toggleDrawTools(draw_tools,false)
}
image_draw_width.setOnClickListener {
if (draw_tools.translationY == (56).toPx){
toggleDrawTools(draw_tools,true)
}else if (draw_tools.translationY == (0).toPx && seekBar_width.isVisible()){
toggleDrawTools(draw_tools,false)
}
seekBar_width.setVisible(true)
seekBar_opacity.setVisible(false)
draw_color_palette.setVisible(false)
}
image_draw_opacity.setOnClickListener {
if (draw_tools.translationY == (56).toPx){
toggleDrawTools(draw_tools,true)
}else if (draw_tools.translationY == (0).toPx && seekBar_opacity.isVisible()){
toggleDrawTools(draw_tools,false)
}
seekBar_width.setVisible(false)
seekBar_opacity.setVisible(true)
draw_color_palette.setVisible(false)
}
image_draw_color.setOnClickListener {
if (draw_tools.translationY == (56).toPx){
toggleDrawTools(draw_tools,true)
}else if (draw_tools.translationY == (0).toPx && draw_color_palette.isVisible()){
toggleDrawTools(draw_tools,false)
}
seekBar_width.setVisible(false)
seekBar_opacity.setVisible(false)
draw_color_palette.setVisible(true)
}
image_draw_undo.setOnClickListener {
custom_draw_view.undo()
toggleDrawTools(draw_tools,false)
}
image_draw_redo.setOnClickListener {
custom_draw_view.redo()
toggleDrawTools(draw_tools,false)
}
}
}
private fun setPaintWidth(drawDialog: Dialog) {
drawDialog.apply {
seekBar_width.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
custom_draw_view.setStrokeWidth(progress.toFloat())
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
}
}
private fun setPaintAlpha(drawDialog: Dialog) {
drawDialog.apply {
seekBar_opacity.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
custom_draw_view.setAlpha(progress)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
}
}
private fun colorSelector(drawDialog: Dialog) {
drawDialog.apply {
image_color_black.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.black,null))
scaleColorView(drawDialog,image_color_black)
}
image_color_red.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_red,null))
scaleColorView(drawDialog,image_color_red)
}
image_color_yellow.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_yellow,null))
scaleColorView(drawDialog,image_color_yellow)
}
image_color_green.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_green,null))
scaleColorView(drawDialog,image_color_green)
}
image_color_blue.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_blue,null))
scaleColorView(drawDialog,image_color_blue)
}
image_color_pink.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_pink,null))
scaleColorView(drawDialog,image_color_pink)
}
image_color_brown.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_brown,null))
scaleColorView(drawDialog,image_color_brown)
}
}
}
private fun scaleColorView(drawDialog: Dialog, view: ImageView) {
drawDialog.apply {
//reset scale of all views
image_color_black.scaleX = 1f
image_color_black.scaleY = 1f
image_color_red.scaleX = 1f
image_color_red.scaleY = 1f
image_color_yellow.scaleX = 1f
image_color_yellow.scaleY = 1f
image_color_green.scaleX = 1f
image_color_green.scaleY = 1f
image_color_blue.scaleX = 1f
image_color_blue.scaleY = 1f
image_color_pink.scaleX = 1f
image_color_pink.scaleY = 1f
image_color_brown.scaleX = 1f
image_color_brown.scaleY = 1f
//set scale of selected view
view.scaleX = 1.5f
view.scaleY = 1.5f
}
}
private fun toggleDrawTools(view: View, showView: Boolean = true) {
if (showView){
view.animate().translationY((0).toPx)
}else{
view.animate().translationY((56).toPx)
}
}
val Int.toPx: Float
get() = (this * Resources.getSystem().displayMetrics.density)
private fun saveImage(bitmap: Bitmap): Uri? {
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,100,outputStream)
outputStream.flush()
outputStream.close()
return Uri.fromFile(file)
}
private fun canWriteToExternalStorage(): Boolean {
return context?.let { AndroidPermissionsHelper.checkPermission(it, Manifest.permission.WRITE_EXTERNAL_STORAGE) }!!
}
private fun checkWritingPermission() {
activity?.let {
AndroidPermissionsHelper.requestPermission(it,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
AndroidPermissionsHelper.WRITE_EXTERNAL_STORAGE_CODE)
} }
} }
......
...@@ -7,8 +7,10 @@ import chat.rocket.android.util.extensions.setVisible ...@@ -7,8 +7,10 @@ import chat.rocket.android.util.extensions.setVisible
/** /**
* An adapter for bottomsheet menu that lists all the actions that could be taken over a chat message. * An adapter for bottomsheet menu that lists all the actions that could be taken over a chat message.
*/ */
class ActionListAdapter(menuItems: List<MenuItem> = emptyList(), callback: MenuItem.OnMenuItemClickListener) : class ActionListAdapter(
ListBottomSheetAdapter(menuItems = menuItems, callback = callback) { menuItems: List<MenuItem> = emptyList(),
callback: MenuItem.OnMenuItemClickListener
) : ListBottomSheetAdapter(menuItems = menuItems, callback = callback) {
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = menuItems[position] val item = menuItems[position]
...@@ -25,7 +27,11 @@ class ActionListAdapter(menuItems: List<MenuItem> = emptyList(), callback: MenuI ...@@ -25,7 +27,11 @@ class ActionListAdapter(menuItems: List<MenuItem> = emptyList(), callback: MenuI
callback?.onMenuItemClick(item) callback?.onMenuItemClick(item)
} }
val deleteTextColor = holder.itemView.context.resources.getColor(R.color.red) val deleteTextColor = holder.itemView.context.resources.getColor(R.color.red)
val color = if (item.itemId == R.id.action_menu_msg_delete) deleteTextColor else textColors.get(item.itemId) val color = if (item.itemId == R.id.action_message_delete) {
deleteTextColor
} else {
textColors.get(item.itemId)
}
holder.textTitle.setTextColor(color) holder.textTitle.setTextColor(color)
} }
} }
\ No newline at end of file
...@@ -325,6 +325,8 @@ class ViewModelMapper @Inject constructor( ...@@ -325,6 +325,8 @@ class ViewModelMapper @Inject constructor(
is MessageType.MessagePinned -> context.getString(R.string.message_pinned) is MessageType.MessagePinned -> context.getString(R.string.message_pinned)
is MessageType.UserMuted -> context.getString(R.string.message_muted, message.message, message.sender?.username) is MessageType.UserMuted -> context.getString(R.string.message_muted, message.message, message.sender?.username)
is MessageType.UserUnMuted -> context.getString(R.string.message_unmuted, message.message, message.sender?.username) is MessageType.UserUnMuted -> context.getString(R.string.message_unmuted, message.message, message.sender?.username)
is MessageType.SubscriptionRoleAdded -> context.getString(R.string.message_role_add, message.message, message.role, message.sender?.username)
is MessageType.SubscriptionRoleRemoved -> context.getString(R.string.message_role_removed, message.message, message.role, message.sender?.username)
else -> { else -> {
throw InvalidParameterException("Invalid message type: ${message.type}") throw InvalidParameterException("Invalid message type: ${message.type}")
} }
......
...@@ -211,7 +211,8 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -211,7 +211,8 @@ class ChatRoomsPresenter @Inject constructor(
userMentions = null, userMentions = null,
groupMentions = 0L, groupMentions = 0L,
lastMessage = null, lastMessage = null,
client = client client = client,
broadcast = false
) )
} }
} }
...@@ -244,7 +245,8 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -244,7 +245,8 @@ class ChatRoomsPresenter @Inject constructor(
userMentions = null, userMentions = null,
groupMentions = 0L, groupMentions = 0L,
lastMessage = it.lastMessage, lastMessage = it.lastMessage,
client = client client = client,
broadcast = it.broadcast
) )
} }
} }
...@@ -335,7 +337,8 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -335,7 +337,8 @@ class ChatRoomsPresenter @Inject constructor(
userMentions = it.userMentions, userMentions = it.userMentions,
groupMentions = it.groupMentions, groupMentions = it.groupMentions,
lastMessage = it.lastMessage, lastMessage = it.lastMessage,
client = client client = client,
broadcast = it.broadcast
) )
chatRoomsList.add(newRoom) chatRoomsList.add(newRoom)
} }
...@@ -478,7 +481,8 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -478,7 +481,8 @@ class ChatRoomsPresenter @Inject constructor(
userMentions = userMentions, userMentions = userMentions,
groupMentions = groupMentions, groupMentions = groupMentions,
lastMessage = room.lastMessage, lastMessage = room.lastMessage,
client = client client = client,
broadcast = broadcast
) )
removeRoom(room.id, chatRooms) removeRoom(room.id, chatRooms)
chatRooms.add(newRoom) chatRooms.add(newRoom)
...@@ -517,7 +521,8 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -517,7 +521,8 @@ class ChatRoomsPresenter @Inject constructor(
userMentions = subscription.userMentions, userMentions = subscription.userMentions,
groupMentions = subscription.groupMentions, groupMentions = subscription.groupMentions,
lastMessage = lastMessage, lastMessage = lastMessage,
client = client client = client,
broadcast = broadcast
) )
removeRoom(subscription.roomId, chatRooms) removeRoom(subscription.roomId, chatRooms)
chatRooms.add(newRoom) chatRooms.add(newRoom)
...@@ -591,7 +596,8 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -591,7 +596,8 @@ class ChatRoomsPresenter @Inject constructor(
userMentions = it.userMentions, userMentions = it.userMentions,
groupMentions = it.groupMentions, groupMentions = it.groupMentions,
lastMessage = it.lastMessage, lastMessage = it.lastMessage,
client = client client = client,
broadcast = it.broadcast
) )
getChatRoomsInteractor.remove(currentServer, it) getChatRoomsInteractor.remove(currentServer, it)
......
...@@ -14,6 +14,7 @@ import android.support.v7.widget.SearchView ...@@ -14,6 +14,7 @@ import android.support.v7.widget.SearchView
import android.view.* import android.view.*
import android.widget.CheckBox import android.widget.CheckBox
import android.widget.RadioGroup import android.widget.RadioGroup
import androidx.core.view.isVisible
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatrooms.presentation.ChatRoomsPresenter import chat.rocket.android.chatrooms.presentation.ChatRoomsPresenter
import chat.rocket.android.chatrooms.presentation.ChatRoomsView import chat.rocket.android.chatrooms.presentation.ChatRoomsView
...@@ -166,11 +167,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -166,11 +167,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
/*val diff = async(CommonPool) { /*val diff = async(CommonPool) {
DiffUtil.calculateDiff(RoomsDiffCallback(adapter.baseAdapter.dataSet, newDataSet)) DiffUtil.calculateDiff(RoomsDiffCallback(adapter.baseAdapter.dataSet, newDataSet))
}.await()*/ }.await()*/
if (newDataSet.isEmpty()) { text_no_search.isVisible = newDataSet.isEmpty()
text_no_search.visibility = View.VISIBLE
}else{
text_no_search.visibility = View.GONE
}
if (isActive) { if (isActive) {
adapter.baseAdapter.updateRooms(newDataSet) adapter.baseAdapter.updateRooms(newDataSet)
// TODO - fix crash to re-enable diff.dispatchUpdatesTo(adapter) // TODO - fix crash to re-enable diff.dispatchUpdatesTo(adapter)
......
...@@ -8,7 +8,7 @@ import chat.rocket.android.server.infraestructure.RocketChatClientFactory ...@@ -8,7 +8,7 @@ import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extensions.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.getRoomPinnedMessages import chat.rocket.core.internal.rest.getPinnedMessages
import chat.rocket.core.model.isSystemMessage import chat.rocket.core.model.isSystemMessage
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
...@@ -37,7 +37,7 @@ class PinnedMessagesPresenter @Inject constructor( ...@@ -37,7 +37,7 @@ class PinnedMessagesPresenter @Inject constructor(
chatRoom?.let { room -> chatRoom?.let { room ->
view.showLoading() view.showLoading()
val pinnedMessages = val pinnedMessages =
client.getRoomPinnedMessages(roomId, room.type, pinnedMessagesListOffset) client.getPinnedMessages(roomId, room.type, pinnedMessagesListOffset)
pinnedMessagesListOffset = pinnedMessages.offset.toInt() pinnedMessagesListOffset = pinnedMessages.offset.toInt()
val messageList = mapper.map(pinnedMessages.result.filterNot { it.isSystemMessage() }) val messageList = mapper.map(pinnedMessages.result.filterNot { it.isSystemMessage() })
view.showPinnedMessages(messageList) view.showPinnedMessages(messageList)
......
...@@ -291,7 +291,7 @@ class PushManager @Inject constructor( ...@@ -291,7 +291,7 @@ class PushManager @Inject constructor(
.setLabel(replyTextHint) .setLabel(replyTextHint)
.build() .build()
val pendingIntent = getReplyPendingIntent(pushMessage) val pendingIntent = getReplyPendingIntent(pushMessage)
val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_reply_black_24px, replyTextHint, pendingIntent) val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_action_message_reply_24dp, replyTextHint, pendingIntent)
.addRemoteInput(replyRemoteInput) .addRemoteInput(replyRemoteInput)
.setAllowGeneratedReplies(true) .setAllowGeneratedReplies(true)
.build() .build()
......
...@@ -32,20 +32,25 @@ class PermissionsInteractor @Inject constructor( ...@@ -32,20 +32,25 @@ class PermissionsInteractor @Inject constructor(
} }
/** /**
* Check whether user is allowed to delete a message. * Check whether the user is allowed to delete a message.
*/ */
fun allowedMessageDeleting() = publicSettings()?.allowedMessageDeleting() ?: false fun allowedMessageDeleting() = publicSettings()?.allowedMessageDeleting() ?: false
/** /**
* Checks whether user is allowed to edit a message. * Checks whether the user is allowed to edit a message.
*/ */
fun allowedMessageEditing() = publicSettings()?.allowedMessageEditing() ?: false fun allowedMessageEditing() = publicSettings()?.allowedMessageEditing() ?: false
/** /**
* Checks whether user is allowed to pin a message to a channel. * Checks whether the user is allowed to pin a message to a channel.
*/ */
fun allowedMessagePinning() = publicSettings()?.allowedMessagePinning() ?: false fun allowedMessagePinning() = publicSettings()?.allowedMessagePinning() ?: false
/**
* Checks whether the user is allowed to star a message.
*/
fun allowedMessageStarring() = publicSettings()?.allowedMessageStarring() ?: false
/** /**
* Checks whether should show deleted message status. * Checks whether should show deleted message status.
*/ */
......
...@@ -24,7 +24,7 @@ class RefreshSettingsInteractor @Inject constructor( ...@@ -24,7 +24,7 @@ class RefreshSettingsInteractor @Inject constructor(
FAVORITE_ROOMS, UPLOAD_STORAGE_TYPE, UPLOAD_MAX_FILE_SIZE, UPLOAD_WHITELIST_MIMETYPES, FAVORITE_ROOMS, UPLOAD_STORAGE_TYPE, UPLOAD_MAX_FILE_SIZE, UPLOAD_WHITELIST_MIMETYPES,
HIDE_USER_JOIN, HIDE_USER_LEAVE, HIDE_USER_JOIN, HIDE_USER_LEAVE,
HIDE_TYPE_AU, HIDE_MUTE_UNMUTE, HIDE_TYPE_RU, ALLOW_MESSAGE_DELETING, HIDE_TYPE_AU, HIDE_MUTE_UNMUTE, HIDE_TYPE_RU, ALLOW_MESSAGE_DELETING,
ALLOW_MESSAGE_EDITING, ALLOW_MESSAGE_PINNING, SHOW_DELETED_STATUS, SHOW_EDITED_STATUS, ALLOW_MESSAGE_EDITING, ALLOW_MESSAGE_PINNING, ALLOW_MESSAGE_STARRING, SHOW_DELETED_STATUS, SHOW_EDITED_STATUS,
WIDE_TILE_310, STORE_LAST_MESSAGE) WIDE_TILE_310, STORE_LAST_MESSAGE)
suspend fun refresh(server: String) { suspend fun refresh(server: String) {
......
...@@ -49,6 +49,7 @@ const val ALLOW_MESSAGE_EDITING = "Message_AllowEditing" ...@@ -49,6 +49,7 @@ const val ALLOW_MESSAGE_EDITING = "Message_AllowEditing"
const val SHOW_DELETED_STATUS = "Message_ShowDeletedStatus" const val SHOW_DELETED_STATUS = "Message_ShowDeletedStatus"
const val SHOW_EDITED_STATUS = "Message_ShowEditedStatus" const val SHOW_EDITED_STATUS = "Message_ShowEditedStatus"
const val ALLOW_MESSAGE_PINNING = "Message_AllowPinning" const val ALLOW_MESSAGE_PINNING = "Message_AllowPinning"
const val ALLOW_MESSAGE_STARRING = "Message_AllowStarring"
const val STORE_LAST_MESSAGE = "Store_Last_Message" const val STORE_LAST_MESSAGE = "Store_Last_Message"
/* /*
...@@ -83,6 +84,7 @@ fun PublicSettings.wideTile(): String? = this[WIDE_TILE_310]?.value as String? ...@@ -83,6 +84,7 @@ fun PublicSettings.wideTile(): String? = this[WIDE_TILE_310]?.value as String?
fun PublicSettings.showDeletedStatus(): Boolean = this[SHOW_DELETED_STATUS]?.value == true fun PublicSettings.showDeletedStatus(): Boolean = this[SHOW_DELETED_STATUS]?.value == true
fun PublicSettings.showEditedStatus(): Boolean = this[SHOW_EDITED_STATUS]?.value == true fun PublicSettings.showEditedStatus(): Boolean = this[SHOW_EDITED_STATUS]?.value == true
fun PublicSettings.allowedMessagePinning(): Boolean = this[ALLOW_MESSAGE_PINNING]?.value == true fun PublicSettings.allowedMessagePinning(): Boolean = this[ALLOW_MESSAGE_PINNING]?.value == true
fun PublicSettings.allowedMessageStarring(): Boolean = this[ALLOW_MESSAGE_STARRING]?.value == true
fun PublicSettings.allowedMessageEditing(): Boolean = this[ALLOW_MESSAGE_EDITING]?.value == true fun PublicSettings.allowedMessageEditing(): Boolean = this[ALLOW_MESSAGE_EDITING]?.value == true
fun PublicSettings.allowedMessageDeleting(): Boolean = this[ALLOW_MESSAGE_DELETING]?.value == true fun PublicSettings.allowedMessageDeleting(): Boolean = this[ALLOW_MESSAGE_DELETING]?.value == true
......
...@@ -110,7 +110,6 @@ class ConnectionManager(internal val client: RocketChatClient) { ...@@ -110,7 +110,6 @@ class ConnectionManager(internal val client: RocketChatClient) {
Timber.d("Received new Message for room ${message.roomId}") Timber.d("Received new Message for room ${message.roomId}")
val channel = roomMessagesChannels[message.roomId] val channel = roomMessagesChannels[message.roomId]
channel?.send(message) channel?.send(message)
} }
} }
...@@ -131,6 +130,7 @@ class ConnectionManager(internal val client: RocketChatClient) { ...@@ -131,6 +130,7 @@ class ConnectionManager(internal val client: RocketChatClient) {
} }
} }
} }
client.connect() client.connect()
// Broadcast initial state... // Broadcast initial state...
......
...@@ -8,6 +8,7 @@ import chat.rocket.android.util.VersionInfo ...@@ -8,6 +8,7 @@ import chat.rocket.android.util.VersionInfo
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extensions.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.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.Deferred
...@@ -26,7 +27,13 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra ...@@ -26,7 +27,13 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
try { try {
currentServer = serverUrl currentServer = serverUrl
client = factory.create(currentServer) client = factory.create(currentServer)
val version = checkServerVersion(serverUrl).await() val serverInfo = retryIO(description = "serverInfo", times = 5) {
client.serverInfo()
}
if (serverInfo.redirected) {
view.updateServerUrl(serverInfo.url)
}
val version = checkServerVersion(serverInfo)
when (version) { when (version) {
is Version.VersionOk -> { is Version.VersionOk -> {
Timber.i("Your version is nice! (Requires: 0.62.0, Yours: ${version.version})") Timber.i("Your version is nice! (Requires: 0.62.0, Yours: ${version.version})")
...@@ -55,23 +62,19 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra ...@@ -55,23 +62,19 @@ abstract class CheckServerPresenter constructor(private val strategy: CancelStra
} }
} }
internal fun checkServerVersion(serverUrl: String): Deferred<Version> { private fun checkServerVersion(serverInfo: ServerInfo): Version {
currentServer = serverUrl val thisServerVersion = serverInfo.version
return async { val isRequiredVersion = isRequiredServerVersion(thisServerVersion)
val serverInfo = retryIO(description = "serverInfo", times = 5) { client.serverInfo() } val isRecommendedVersion = isRecommendedServerVersion(thisServerVersion)
val thisServerVersion = serverInfo.version return if (isRequiredVersion) {
val isRequiredVersion = isRequiredServerVersion(thisServerVersion) if (isRecommendedVersion) {
val isRecommendedVersion = isRecommendedServerVersion(thisServerVersion) Timber.i("Your version is nice! (Requires: 0.62.0, Yours: $thisServerVersion)")
if (isRequiredVersion) { Version.VersionOk(thisServerVersion)
if (isRecommendedVersion) {
Timber.i("Your version is nice! (Requires: 0.62.0, Yours: $thisServerVersion)")
return@async Version.VersionOk(thisServerVersion)
} else {
return@async Version.RecommendedVersionWarning(thisServerVersion)
}
} else { } else {
return@async Version.OutOfDateError(thisServerVersion) Version.RecommendedVersionWarning(thisServerVersion)
} }
} else {
Version.OutOfDateError(thisServerVersion)
} }
} }
......
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportHeight="24.0"
android:viewportHeight="24.0"> android:viewportWidth="24.0">
<path
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z" <path
android:fillColor="@color/actionMenuColor"/> android:fillColor="@color/actionMenuColor"
</vector> android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z" />
</vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportHeight="24.0"
android:viewportHeight="24.0"> android:viewportWidth="24.0">
<path <path
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z" android:fillColor="#FF0000"
android:fillColor="#FF0000"/> android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z" />
</vector> </vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportHeight="24.0"
android:viewportHeight="24.0"> android:viewportWidth="24.0">
<path <path
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" android:fillColor="@color/actionMenuColor"
android:fillColor="@color/actionMenuColor"/> android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" />
</vector> </vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="@color/actionMenuColor"
android:pathData="M16,12V4H17V2H7V4H8V12L6,14V16H11.2V22H12.8V16H18V14L16,12Z" />
</vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="@color/actionMenuColor"
android:pathData="M6,17h3l2,-4L11,7L5,7v6h3zM14,17h3l2,-4L19,7h-6v6h3z" />
</vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="@color/actionMenuColor"
android:pathData="M10,9V5l-7,7 7,7v-4.1c5,0 8.5,1.6 11,5.1 -1,-5 -4,-10 -11,-11z" />
</vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportHeight="24.0"
android:viewportHeight="24.0"> android:viewportWidth="24.0">
<path <path
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z" android:fillColor="@color/actionMenuColor"
android:fillColor="@color/actionMenuColor"/> android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z" />
</vector> </vector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportWidth="197.218"
android:viewportHeight="197.218"
android:width="197.218dp"
android:height="197.218dp">
<group
android:translateX="-570.396"
android:translateY="-306.782">
<path
android:pathData="M704.445 306.782l-6.785 6.785c-6.084 6.084 -7.622 14.712 -4.309 21.871l-44.068 35.44 -3.086 -3.086c-7.889 -7.889 -19.525 -7.889 -27.414 0l-8.944 8.953 87.821 87.811 8.934 -8.933c7.899 -7.899 7.899 -19.525 0 -27.433l-3.076 -3.077 36.051 -44.68c6.824 2.466 14.367 1.036 20.037 -4.624l8.008 -5.858 -63.169 -63.169zm-66.867 116.487l-67.182 66.857 0 13.874 13.864 0 66.867 -67.182 -13.549 -13.549z"
android:fillColor="@color/actionMenuColor"
/>
</group>
</vector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout <android.support.constraint.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:id="@+id/root_layout" android:id="@+id/root_layout"
...@@ -12,23 +11,23 @@ ...@@ -12,23 +11,23 @@
android:id="@+id/view_loading" android:id="@+id/view_loading"
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_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone" android:visibility="gone"
app:indicatorColor="@color/black" app:indicatorColor="@color/black"
app:indicatorName="BallPulseIndicator" app:indicatorName="BallPulseIndicator"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" /> tools:visibility="visible" />
<FrameLayout <FrameLayout
android:id="@+id/message_list_container" android:id="@+id/message_list_container"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toTopOf="@id/text_typing_status"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/layout_message_composer"> app:layout_constraintTop_toTopOf="parent">
<include <include
android:id="@+id/layout_message_list" android:id="@+id/layout_message_list"
...@@ -44,52 +43,65 @@ ...@@ -44,52 +43,65 @@
android:layout_height="100dp" android:layout_height="100dp"
android:src="@drawable/ic_chat_black_24dp" android:src="@drawable/ic_chat_black_24dp"
android:tint="@color/icon_grey" android:tint="@color/icon_grey"
app:layout_constraintStart_toStartOf="parent" android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/text_chat_title"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/text_chat_title"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
android:visibility="gone"
tools:visibility="visible" /> tools:visibility="visible" />
<TextView <TextView
android:id="@+id/text_chat_title" android:id="@+id/text_chat_title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/msg_no_chat_title" android:text="@string/msg_no_chat_title"
app:layout_constraintStart_toStartOf="parent" android:textColor="@color/colorSecondaryText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/image_chat_icon"
app:layout_constraintBottom_toTopOf="@id/text_chat_description"
android:textSize="20sp" android:textSize="20sp"
android:layout_marginTop="24dp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="@color/colorSecondaryText"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible"/> app:layout_constraintBottom_toTopOf="@id/text_chat_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/image_chat_icon"
tools:visibility="visible" />
<TextView <TextView
android:id="@+id/text_chat_description" android:id="@+id/text_chat_description"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/msg_no_chat_description"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/text_chat_title"
app:layout_constraintBottom_toTopOf="@id/layout_message_composer"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:text="@string/msg_no_chat_description"
android:textAlignment="center" android:textAlignment="center"
android:textSize="16sp"
android:textColor="@color/colorSecondaryTextLight" android:textColor="@color/colorSecondaryTextLight"
android:textSize="16sp"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible"/> app:layout_constraintBottom_toTopOf="@id/layout_message_composer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text_chat_title"
tools:visibility="visible" />
<chat.rocket.android.widget.autocompletion.ui.SuggestionsView <chat.rocket.android.widget.autocompletion.ui.SuggestionsView
android:id="@+id/suggestions_view" android:id="@+id/suggestions_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@color/suggestion_background_color"
app:layout_constraintBottom_toTopOf="@id/layout_message_composer" />
<TextView
android:id="@+id/text_typing_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:maxLines="2"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/layout_message_composer" app:layout_constraintBottom_toTopOf="@id/layout_message_composer"
android:background="@color/suggestion_background_color" /> app:layout_constraintEnd_toStartOf="parent" />
<include <include
android:id="@+id/layout_message_composer" android:id="@+id/layout_message_composer"
...@@ -102,18 +114,18 @@ ...@@ -102,18 +114,18 @@
android:id="@+id/view_dim" android:id="@+id/view_dim"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_constraintBottom_toTopOf="@id/layout_message_composer"
android:background="@color/colorDim" android:background="@color/colorDim"
android:visibility="gone" /> android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/layout_message_composer" />
<include <include
android:id="@+id/layout_message_attachment_options" android:id="@+id/layout_message_attachment_options"
layout="@layout/message_attachment_options" layout="@layout/message_attachment_options"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/layout_message_composer"
android:layout_margin="5dp" android:layout_margin="5dp"
android:visibility="gone" /> android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/layout_message_composer" />
<TextView <TextView
android:id="@+id/connection_status_text" android:id="@+id/connection_status_text"
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
android:id="@+id/iv_pin_icon" android:id="@+id/iv_pin_icon"
android:layout_width="100dp" android:layout_width="100dp"
android:layout_height="100dp" android:layout_height="100dp"
android:src="@drawable/ic_pin_black_24dp" android:src="@drawable/ic_action_message_pin_24dp"
android:tint="@color/icon_grey" android:tint="@color/icon_grey"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
......
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground" android:background="?android:attr/selectableItemBackground"
android:clickable="true" android:clickable="true"
android:paddingStart="@dimen/screen_edge_left_and_right_padding" android:focusable="true"
android:paddingEnd="@dimen/screen_edge_left_and_right_padding"
android:paddingTop="@dimen/message_item_top_and_bottom_padding"
android:paddingBottom="@dimen/message_item_top_and_bottom_padding" android:paddingBottom="@dimen/message_item_top_and_bottom_padding"
android:focusable="true"> android:paddingEnd="@dimen/screen_edge_left_and_right_padding"
android:paddingStart="@dimen/screen_edge_left_and_right_padding"
android:paddingTop="@dimen/message_item_top_and_bottom_padding">
<include <include
android:id="@+id/layout_avatar" android:id="@+id/layout_avatar"
...@@ -20,36 +20,39 @@ ...@@ -20,36 +20,39 @@
android:layout_height="40dp" android:layout_height="40dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/new_messages_notif" /> app:layout_constraintTop_toBottomOf="@+id/new_messages_notif" />
<LinearLayout <LinearLayout
android:id="@+id/new_messages_notif" android:id="@+id/new_messages_notif"
tools:visibility="visible"
android:visibility="gone"
android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible">
<View <View
android:layout_gravity="center"
android:layout_height="1dp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_height="1dp"
android:layout_gravity="center"
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:background="@color/red"/> android:layout_weight="1"
android:background="@color/red" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:text="@string/msg_unread_messages"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/msg_unread_messages"
android:textColor="@color/red" /> android:textColor="@color/red" />
<View <View
android:layout_gravity="center"
android:layout_height="1dp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_height="1dp"
android:layout_gravity="center"
android:layout_marginStart="4dp" android:layout_marginStart="4dp"
android:background="@color/red"/> android:layout_weight="1"
android:background="@color/red" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
...@@ -58,8 +61,8 @@ ...@@ -58,8 +61,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:orientation="horizontal" android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@id/new_messages_notif" app:layout_constraintLeft_toRightOf="@+id/layout_avatar"
app:layout_constraintLeft_toRightOf="@+id/layout_avatar"> app:layout_constraintTop_toBottomOf="@+id/new_messages_notif">
<TextView <TextView
android:id="@+id/text_sender" android:id="@+id/text_sender"
...@@ -80,11 +83,22 @@ ...@@ -80,11 +83,22 @@
android:id="@+id/text_edit_indicator" android:id="@+id/text_edit_indicator"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/msg_edited"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:text="@string/msg_edited"
android:textStyle="italic" android:textStyle="italic"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible" /> tools:visibility="visible" />
<ImageView
android:id="@+id/image_star_indicator"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginTop="2dp"
android:src="@drawable/ic_action_message_star_24dp"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout> </LinearLayout>
<TextView <TextView
...@@ -94,12 +108,13 @@ ...@@ -94,12 +108,13 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="2dp" android:layout_marginBottom="2dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
app:layout_constraintLeft_toLeftOf="@id/top_container" app:layout_constraintLeft_toLeftOf="@+id/top_container"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/top_container" app:layout_constraintTop_toBottomOf="@+id/top_container"
tools:text="This is a multiline chat message from Bertie that will take more than just one line of text. I have sure that everything is amazing!" /> tools:text="This is a multiline chat message from Bertie that will take more than just one line of text. I have sure that everything is amazing!" />
<include layout="@layout/layout_reactions" <include
layout="@layout/layout_reactions"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="@+id/text_content" app:layout_constraintEnd_toEndOf="@+id/text_content"
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/common_actions"> <item
<item android:id="@+id/action_message_reply"
android:id="@+id/action_menu_msg_reply" android:icon="@drawable/ic_action_message_reply_24dp"
android:icon="@drawable/ic_reply_black_24px" android:title="@string/action_msg_reply" />
android:title="@string/action_msg_reply" />
<item
<item android:id="@+id/action_message_quote"
android:id="@+id/action_menu_msg_quote" android:icon="@drawable/ic_action_message_quote_24dp"
android:icon="@drawable/ic_quote_black_24px" android:title="@string/action_msg_quote" />
android:title="@string/action_msg_quote" />
<item
<item android:id="@+id/action_message_copy"
android:id="@+id/action_menu_msg_edit" android:icon="@drawable/ic_action_message_copy_24dp"
android:icon="@drawable/ic_edit_black_24px" android:title="@string/action_msg_copy" />
android:title="@string/action_msg_edit" />
<item
<item android:id="@+id/action_menu_msg_react"
android:id="@+id/action_menu_msg_copy" android:icon="@drawable/ic_add_reaction"
android:icon="@drawable/ic_content_copy_black_24px" android:title="@string/action_msg_add_reaction" />
android:title="@string/action_msg_copy" />
<!--<item-->
<item <!--android:id="@+id/action_menu_msg_share"-->
android:id="@+id/action_menu_msg_react" <!--andrtextIconicon="@drawable/ic_share_black_24px"-->
android:icon="@drawable/ic_add_reaction" <!--android:title="@string/action_msg_share" />-->
android:title="@string/action_msg_add_reaction" />
<item
<!--<item--> android:id="@+id/action_message_star"
<!--android:id="@+id/action_menu_msg_share"--> android:icon="@drawable/ic_action_message_star_24dp"
<!--andrtextIconicon="@drawable/ic_share_black_24px"--> android:title="@string/action_msg_star" />
<!--android:title="@string/action_msg_share" />-->
<item
<item android:id="@+id/action_message_unpin"
android:id="@+id/action_menu_msg_pin_unpin" android:icon="@drawable/ic_action_message_pin_24dp"
android:icon="@drawable/ic_pin_black_24dp" android:title="@string/action_msg_pin" />
android:title="@string/action_msg_pin" />
<item
<!--<item--> android:id="@+id/action_message_edit"
<!--android:id="@+id/action_menu_msg_star"--> android:icon="@drawable/ic_action_message_edit_24dp"
<!--andrtextIconicon="@drawable/ic_star_black_24px"--> android:title="@string/action_msg_edit" />
<!--android:title="@string/action_msg_star" />-->
</group> <item
android:id="@+id/action_message_delete"
<group android:id="@+id/dangerous_actions"> android:icon="@drawable/ic_action_message_delete_24dp"
<item android:title="@string/action_msg_delete" />
android:id="@+id/action_menu_msg_delete"
android:icon="@drawable/ic_delete_black_24px"
android:title="@string/action_msg_delete" />
</group>
</menu> </menu>
\ No newline at end of file
...@@ -112,6 +112,14 @@ ...@@ -112,6 +112,14 @@
<string name="msg_no_chat_title">Sin mensajes de chat</string> <string name="msg_no_chat_title">Sin mensajes de chat</string>
<string name="msg_no_chat_description">Comience a conversar para ver\nsus mensajes aquí.</string> <string name="msg_no_chat_description">Comience a conversar para ver\nsus mensajes aquí.</string>
<string name="msg_edited">(editado)</string> <string name="msg_edited">(editado)</string>
// TODO: Add proper translation.
<string name="msg_and">\u0020and\u0020</string>
// TODO: Add proper translation.
<string name="msg_is_typing">\u0020is typing…</string>
// TODO: Add proper translation.
<string name="msg_are_typing">\u0020are typing…</string>
// TODO: Add proper translation.
<string name="msg_several_users_are_typing">Several users are typing…</string>
<string name="msg_no_search_found">No se han encontrado resultados</string> <string name="msg_no_search_found">No se han encontrado resultados</string>
<!-- System messages --> <!-- System messages -->
...@@ -125,6 +133,8 @@ ...@@ -125,6 +133,8 @@
<string name="message_pinned">Fijado una mensaje:</string> <string name="message_pinned">Fijado una mensaje:</string>
<string name="message_muted">Usuario %1$s silenciado por %2$s</string> <string name="message_muted">Usuario %1$s silenciado por %2$s</string>
<string name="message_unmuted">Usuario %1$s no silenciado por %2$s</string> <string name="message_unmuted">Usuario %1$s no silenciado por %2$s</string>
<string name="message_role_add">%1$s fue establecido %2$s por %3$s</string>
<string name="message_role_removed">%1$s ya no es %2$s por %3$s</string>
<!-- Message actions --> <!-- Message actions -->
<string name="action_msg_reply">Respuesta</string> <string name="action_msg_reply">Respuesta</string>
...@@ -135,6 +145,8 @@ ...@@ -135,6 +145,8 @@
<string name="action_msg_pin">Fijar mensaje</string> <string name="action_msg_pin">Fijar mensaje</string>
<string name="action_msg_unpin">Soltar mensaje</string> <string name="action_msg_unpin">Soltar mensaje</string>
<string name="action_msg_star">Star mensaje</string> <string name="action_msg_star">Star mensaje</string>
// TODO: Add proper translation.
<string name="action_msg_unstar">Unstar Message</string>
<string name="action_msg_share">Compartir</string> <string name="action_msg_share">Compartir</string>
<string name="action_title_editing">Edición de mensaje</string> <string name="action_title_editing">Edición de mensaje</string>
<string name="action_msg_add_reaction">Añadir una reacción</string> <string name="action_msg_add_reaction">Añadir una reacción</string>
...@@ -143,6 +155,8 @@ ...@@ -143,6 +155,8 @@
<string name="permission_editing_not_allowed">La edición no és permitida</string> <string name="permission_editing_not_allowed">La edición no és permitida</string>
<string name="permission_deleting_not_allowed">Eliminar no és permitido</string> <string name="permission_deleting_not_allowed">Eliminar no és permitido</string>
<string name="permission_pinning_not_allowed">Fijar no és permitido</string> <string name="permission_pinning_not_allowed">Fijar no és permitido</string>
// TODO: Add proper translation.
<string name="permission_starring_not_allowed">Starring is not allowed</string>
<!-- Members List --> <!-- Members List -->
<string name="title_members_list">Lista de miembros</string> <string name="title_members_list">Lista de miembros</string>
......
...@@ -112,6 +112,14 @@ ...@@ -112,6 +112,14 @@
<string name="msg_no_chat_title">Aucun message de discussion</string> <string name="msg_no_chat_title">Aucun message de discussion</string>
<string name="msg_no_chat_description">Commencez à converser pour voir\nvos messages ici.</string> <string name="msg_no_chat_description">Commencez à converser pour voir\nvos messages ici.</string>
<string name="msg_edited">(édité)</string> <string name="msg_edited">(édité)</string>
// TODO: Add proper translation.
<string name="msg_and">\u0020and\u0020</string>
// TODO: Add proper translation.
<string name="msg_is_typing">\u0020is typing…</string>
// TODO: Add proper translation.
<string name="msg_are_typing">\u0020are typing…</string>
// TODO: Add proper translation.
<string name="msg_several_users_are_typing">Several users are typing…</string>
<string name="msg_no_search_found">Aucun résultat trouvé</string> <string name="msg_no_search_found">Aucun résultat trouvé</string>
<!-- System messages --> <!-- System messages -->
...@@ -125,6 +133,8 @@ ...@@ -125,6 +133,8 @@
<string name="message_pinned">Épinglé un message:</string> <string name="message_pinned">Épinglé un message:</string>
<string name="message_muted">Utilisateur %1$s mis en sourdine par %2$s</string> <string name="message_muted">Utilisateur %1$s mis en sourdine par %2$s</string>
<string name="message_unmuted">Utilisateur %1$s non muté par %2$s</string> <string name="message_unmuted">Utilisateur %1$s non muté par %2$s</string>
<string name="message_role_add">%1$s a été défini %2$s par %3$s</string>
<string name="message_role_removed">%1$s is no longer %2$s par %3$s</string>
<!-- Message actions --> <!-- Message actions -->
<string name="action_msg_reply">Répondre</string> <string name="action_msg_reply">Répondre</string>
...@@ -134,7 +144,10 @@ ...@@ -134,7 +144,10 @@
<string name="action_msg_delete">Effacer</string> <string name="action_msg_delete">Effacer</string>
<string name="action_msg_pin">Épingle message</string> <string name="action_msg_pin">Épingle message</string>
<string name="action_msg_unpin">Enlever message</string> <string name="action_msg_unpin">Enlever message</string>
// TODO: Add proper translation.
<string name="action_msg_star">Star message</string> <string name="action_msg_star">Star message</string>
// TODO: Add proper translation.
<string name="action_msg_unstar">Unstar Message</string>
<string name="action_msg_share">Partager</string> <string name="action_msg_share">Partager</string>
<string name="action_title_editing">Modification du message</string> <string name="action_title_editing">Modification du message</string>
<string name="action_msg_add_reaction">Ajouter une réaction</string> <string name="action_msg_add_reaction">Ajouter une réaction</string>
...@@ -143,6 +156,8 @@ ...@@ -143,6 +156,8 @@
<string name="permission_editing_not_allowed">L\'édition n\'est pas autorisée</string> <string name="permission_editing_not_allowed">L\'édition n\'est pas autorisée</string>
<string name="permission_deleting_not_allowed">La suppression n\'est pas autorisée</string> <string name="permission_deleting_not_allowed">La suppression n\'est pas autorisée</string>
<string name="permission_pinning_not_allowed">L\'épinglage n\'est pas autorisé</string> <string name="permission_pinning_not_allowed">L\'épinglage n\'est pas autorisé</string>
// TODO: Add proper translation.
<string name="permission_starring_not_allowed">Starring is not allowed</string>
<!-- Members List --> <!-- Members List -->
<string name="title_members_list">Liste des membres</string> <string name="title_members_list">Liste des membres</string>
......
...@@ -114,6 +114,14 @@ ...@@ -114,6 +114,14 @@
<string name="msg_no_chat_title">कोई चैट संदेश नहीं</string> <string name="msg_no_chat_title">कोई चैट संदेश नहीं</string>
<string name="msg_no_chat_description">यहां अपने संदेश देखने के लिए\nबातचीत शुरू करें।</string> <string name="msg_no_chat_description">यहां अपने संदेश देखने के लिए\nबातचीत शुरू करें।</string>
<string name="msg_edited">(संपादित)</string> <string name="msg_edited">(संपादित)</string>
// TODO: Add proper translation.
<string name="msg_and">\u0020and\u0020</string>
// TODO: Add proper translation.
<string name="msg_is_typing">\u0020is typing…</string>
// TODO: Add proper translation.
<string name="msg_are_typing">\u0020are typing…</string>
// TODO: Add proper translation.
<string name="msg_several_users_are_typing">Several users are typing…</string>
<string name="msg_no_search_found">कोई परिणाम नहीं मिला</string> <string name="msg_no_search_found">कोई परिणाम नहीं मिला</string>
<!-- System messages --> <!-- System messages -->
...@@ -127,6 +135,8 @@ ...@@ -127,6 +135,8 @@
<string name="message_pinned">एक संदेश पिन किया:</string> <string name="message_pinned">एक संदेश पिन किया:</string>
<string name="message_muted">उपयोगकर्ता %1$s %2$s द्वारा म्यूट किया गया</string> <string name="message_muted">उपयोगकर्ता %1$s %2$s द्वारा म्यूट किया गया</string>
<string name="message_unmuted">उपयोगकर्ता %1$s %2$s द्वारा अनम्यूट किया गया</string> <string name="message_unmuted">उपयोगकर्ता %1$s %2$s द्वारा अनम्यूट किया गया</string>
<string name="message_role_add">%1$s %3$s द्वारा %2$s सेट किया गया था</string>
<string name="message_role_removed">%1$s अब %3$s द्वारा %2$s नहीं है</string>
<!-- Message actions --> <!-- Message actions -->
<string name="action_msg_reply">जवाब दें</string> <string name="action_msg_reply">जवाब दें</string>
...@@ -137,6 +147,8 @@ ...@@ -137,6 +147,8 @@
<string name="action_msg_pin">संदेश को पिन करें</string> <string name="action_msg_pin">संदेश को पिन करें</string>
<string name="action_msg_unpin">संदेश को पिन से हटाएँ</string> <string name="action_msg_unpin">संदेश को पिन से हटाएँ</string>
<string name="action_msg_star">संदेश को स्टार करें</string> <string name="action_msg_star">संदेश को स्टार करें</string>
// TODO: Add proper translation.
<string name="action_msg_unstar">Unstar Message</string>
<string name="action_msg_share">शेयर करें</string> <string name="action_msg_share">शेयर करें</string>
<string name="action_title_editing">संपादन संदेश</string> <string name="action_title_editing">संपादन संदेश</string>
<string name="action_msg_add_reaction">प्रतिक्रिया जोड़ें</string> <string name="action_msg_add_reaction">प्रतिक्रिया जोड़ें</string>
...@@ -145,6 +157,8 @@ ...@@ -145,6 +157,8 @@
<string name="permission_editing_not_allowed">संपादन की अनुमति नहीं है</string> <string name="permission_editing_not_allowed">संपादन की अनुमति नहीं है</string>
<string name="permission_deleting_not_allowed">हटाने की अनुमति नहीं है</string> <string name="permission_deleting_not_allowed">हटाने की अनुमति नहीं है</string>
<string name="permission_pinning_not_allowed">पिनि करने की अनुमति नहीं है</string> <string name="permission_pinning_not_allowed">पिनि करने की अनुमति नहीं है</string>
// TODO: Add proper translation.
<string name="permission_starring_not_allowed">Starring is not allowed</string>
<!-- Members List --> <!-- Members List -->
<string name="title_members_list">सदस्यों की सूची</string> <string name="title_members_list">सदस्यों की सूची</string>
......
...@@ -108,6 +108,10 @@ ...@@ -108,6 +108,10 @@
<string name="msg_image_saved_successfully">Imagem salva na galeria</string> <string name="msg_image_saved_successfully">Imagem salva na galeria</string>
<string name="msg_image_saved_failed">Falha ao salvar a imagem</string> <string name="msg_image_saved_failed">Falha ao salvar a imagem</string>
<string name="msg_edited">(editado)</string> <string name="msg_edited">(editado)</string>
<string name="msg_and">\u0020e\u0020</string>
<string name="msg_is_typing">\u0020está digitando…</string>
<string name="msg_are_typing">\u0020estão digitando…</string>
<string name="msg_several_users_are_typing">Vários usuários estão digitando…</string>
<string name="msg_no_search_found">nenhum resultado encontrado</string> <string name="msg_no_search_found">nenhum resultado encontrado</string>
<!-- System messages --> <!-- System messages -->
...@@ -121,6 +125,8 @@ ...@@ -121,6 +125,8 @@
<string name="message_pinned">Pinou uma mensagem:</string> <string name="message_pinned">Pinou uma mensagem:</string>
<string name="message_muted">Usuário %1$s entrou no modo mudo por %2$s</string> <string name="message_muted">Usuário %1$s entrou no modo mudo por %2$s</string>
<string name="message_unmuted">Usuário %1$s saiu do modo mudo por %2$s</string> <string name="message_unmuted">Usuário %1$s saiu do modo mudo por %2$s</string>
<string name="message_role_add">%1$s foi definido %2$s por %3$s</string>
<string name="message_role_removed">%1$s não é mais %2$s por %3$s</string>
<!-- Message actions --> <!-- Message actions -->
<string name="action_msg_reply">Responder</string> <string name="action_msg_reply">Responder</string>
...@@ -131,6 +137,7 @@ ...@@ -131,6 +137,7 @@
<string name="action_msg_pin">Pinar mensagem</string> <string name="action_msg_pin">Pinar mensagem</string>
<string name="action_msg_unpin">Despinar mensagem</string> <string name="action_msg_unpin">Despinar mensagem</string>
<string name="action_msg_star">Favoritar mensagem</string> <string name="action_msg_star">Favoritar mensagem</string>
<string name="action_msg_unstar">Desfavoritar messagem</string>
<string name="action_msg_share">Compartilhar</string> <string name="action_msg_share">Compartilhar</string>
<string name="action_title_editing">Editando mensagem</string> <string name="action_title_editing">Editando mensagem</string>
<string name="action_msg_add_reaction">Adicionar reação</string> <string name="action_msg_add_reaction">Adicionar reação</string>
...@@ -139,6 +146,7 @@ ...@@ -139,6 +146,7 @@
<string name="permission_editing_not_allowed">Edição não permitida</string> <string name="permission_editing_not_allowed">Edição não permitida</string>
<string name="permission_deleting_not_allowed">Remoção não permitida</string> <string name="permission_deleting_not_allowed">Remoção não permitida</string>
<string name="permission_pinning_not_allowed">Pinagem não permitida</string> <string name="permission_pinning_not_allowed">Pinagem não permitida</string>
<string name="permission_starring_not_allowed">Favoritar não permitido</string>
<!-- Members List --> <!-- Members List -->
<string name="title_members_list">Lista de Membros</string> <string name="title_members_list">Lista de Membros</string>
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
<string name="action_away">Away</string> <string name="action_away">Away</string>
<string name="action_busy">Busy</string> <string name="action_busy">Busy</string>
<string name="action_invisible">Invisible</string> <string name="action_invisible">Invisible</string>
<string name="action_drawing">Drawing</string>
<!-- Settings List --> <!-- Settings List -->
<string-array name="settings_actions"> <string-array name="settings_actions">
...@@ -131,6 +132,7 @@ ...@@ -131,6 +132,7 @@
<string name="action_msg_pin">Pin Message</string> <string name="action_msg_pin">Pin Message</string>
<string name="action_msg_unpin">Unpin Message</string> <string name="action_msg_unpin">Unpin Message</string>
<string name="action_msg_star">Star Message</string> <string name="action_msg_star">Star Message</string>
<string name="action_msg_unstar">Unstar Message</string>
<string name="action_msg_share">Share</string> <string name="action_msg_share">Share</string>
<string name="action_title_editing">Editing Message</string> <string name="action_title_editing">Editing Message</string>
<string name="action_msg_add_reaction">Add reaction</string> <string name="action_msg_add_reaction">Add reaction</string>
...@@ -139,6 +141,8 @@ ...@@ -139,6 +141,8 @@
<string name="permission_editing_not_allowed">Editing is not allowed</string> <string name="permission_editing_not_allowed">Editing is not allowed</string>
<string name="permission_deleting_not_allowed">Deleting is not allowed</string> <string name="permission_deleting_not_allowed">Deleting is not allowed</string>
<string name="permission_pinning_not_allowed">Pinning is not allowed</string> <string name="permission_pinning_not_allowed">Pinning is not allowed</string>
// TODO: Add proper translation.
<string name="permission_starring_not_allowed">Starring is not allowed</string>
<!-- Members List --> <!-- Members List -->
<string name="title_members_list">Members List</string> <string name="title_members_list">Members List</string>
......
...@@ -109,6 +109,10 @@ ...@@ -109,6 +109,10 @@
<string name="msg_image_saved_successfully">Image has been saved to gallery</string> <string name="msg_image_saved_successfully">Image has been saved to gallery</string>
<string name="msg_image_saved_failed">Failed to save image</string> <string name="msg_image_saved_failed">Failed to save image</string>
<string name="msg_edited">(edited)</string> <string name="msg_edited">(edited)</string>
<string name="msg_and">\u0020and\u0020</string>
<string name="msg_is_typing">\u0020is typing…</string>
<string name="msg_are_typing">\u0020are typing…</string>
<string name="msg_several_users_are_typing">Several users are typing…</string>
<string name="msg_no_search_found">No result found</string> <string name="msg_no_search_found">No result found</string>
<!-- System messages --> <!-- System messages -->
...@@ -122,6 +126,8 @@ ...@@ -122,6 +126,8 @@
<string name="message_pinned">Pinned a message:</string> <string name="message_pinned">Pinned a message:</string>
<string name="message_muted">User %1$s muted by %2$s</string> <string name="message_muted">User %1$s muted by %2$s</string>
<string name="message_unmuted">User %1$s unmuted by %2$s</string> <string name="message_unmuted">User %1$s unmuted by %2$s</string>
<string name="message_role_add">%1$s was set %2$s by %3$s</string>
<string name="message_role_removed">%1$s is no longer %2$s by %3$s</string>
<!-- Message actions --> <!-- Message actions -->
<string name="action_msg_reply">Reply</string> <string name="action_msg_reply">Reply</string>
...@@ -132,6 +138,7 @@ ...@@ -132,6 +138,7 @@
<string name="action_msg_pin">Pin Message</string> <string name="action_msg_pin">Pin Message</string>
<string name="action_msg_unpin">Unpin Message</string> <string name="action_msg_unpin">Unpin Message</string>
<string name="action_msg_star">Star Message</string> <string name="action_msg_star">Star Message</string>
<string name="action_msg_unstar">Unstar Message</string>
<string name="action_msg_share">Share</string> <string name="action_msg_share">Share</string>
<string name="action_title_editing">Editing Message</string> <string name="action_title_editing">Editing Message</string>
<string name="action_msg_add_reaction">Add reaction</string> <string name="action_msg_add_reaction">Add reaction</string>
...@@ -140,6 +147,7 @@ ...@@ -140,6 +147,7 @@
<string name="permission_editing_not_allowed">Editing is not allowed</string> <string name="permission_editing_not_allowed">Editing is not allowed</string>
<string name="permission_deleting_not_allowed">Deleting is not allowed</string> <string name="permission_deleting_not_allowed">Deleting is not allowed</string>
<string name="permission_pinning_not_allowed">Pinning is not allowed</string> <string name="permission_pinning_not_allowed">Pinning is not allowed</string>
<string name="permission_starring_not_allowed">Starring is not allowed</string>
<!-- Members List --> <!-- Members List -->
<string name="title_members_list">Members List</string> <string name="title_members_list">Members List</string>
......
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.2.31'
apply from: rootProject.file('dependencies.gradle') apply from: rootProject.file('dependencies.gradle')
repositories { repositories {
...@@ -19,7 +21,7 @@ buildscript { ...@@ -19,7 +21,7 @@ buildscript {
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" }
} }
allprojects { allprojects {
...@@ -35,4 +37,4 @@ allprojects { ...@@ -35,4 +37,4 @@ allprojects {
task clean(type: Delete) { task clean(type: Delete) {
delete rootProject.buildDir delete rootProject.buildDir
} }
\ No newline at end of file
apply plugin: 'com.android.library'
android {
compileSdkVersion 27
defaultConfig {
minSdkVersion 21
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation libraries.appCompat
implementation libraries.constraintLayout
implementation libraries.kotlin
implementation libraries.androidKtx
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
# 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
package chat.rocket.android.draw;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("chat.rocket.android.draw.test", appContext.getPackageName());
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="chat.rocket.android.draw">
<application>
<activity
android:name=".DrawingActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
</application>
</manifest>
\ No newline at end of file
package chat.rocket.android.draw
import android.content.res.Resources
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v4.content.res.ResourcesCompat
import android.view.View
import android.widget.SeekBar
import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.activity_drawing.*
import kotlinx.android.synthetic.main.color_palette_view.*
import android.content.Intent
import android.graphics.Bitmap
import android.app.Activity
import java.io.ByteArrayOutputStream
class DrawingActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_drawing)
image_close_drawing.setOnClickListener {
finish()
}
image_send_drawing.setOnClickListener {
val bStream = ByteArrayOutputStream()
val bitmap = custom_draw_view.getBitmap()
bitmap.compress(Bitmap.CompressFormat.PNG, 100, bStream)
val byteArray = bStream.toByteArray()
val returnIntent = Intent()
returnIntent.putExtra("bitmap", byteArray)
setResult(Activity.RESULT_OK,returnIntent)
finish()
}
setUpDrawTools()
colorSelector()
setPaintAlpha()
setPaintWidth()
}
private fun setUpDrawTools() {
image_draw_eraser.setOnClickListener {
custom_draw_view.clearCanvas()
toggleDrawTools(draw_tools,false)
}
image_draw_width.setOnClickListener {
if (draw_tools.translationY == (56).toPx){
toggleDrawTools(draw_tools,true)
}else if (draw_tools.translationY == (0).toPx && seekBar_width.isVisible){
toggleDrawTools(draw_tools,false)
}
seekBar_width.isVisible = true
seekBar_opacity.isVisible = false
draw_color_palette.isVisible = false
}
image_draw_opacity.setOnClickListener {
if (draw_tools.translationY == (56).toPx){
toggleDrawTools(draw_tools,true)
}else if (draw_tools.translationY == (0).toPx && seekBar_opacity.isVisible){
toggleDrawTools(draw_tools,false)
}
seekBar_width.isVisible = false
seekBar_opacity.isVisible = true
draw_color_palette.isVisible = false
}
image_draw_color.setOnClickListener {
if (draw_tools.translationY == (56).toPx){
toggleDrawTools(draw_tools,true)
}else if (draw_tools.translationY == (0).toPx && draw_color_palette.isVisible){
toggleDrawTools(draw_tools,false)
}
seekBar_width.isVisible = false
seekBar_opacity.isVisible = false
draw_color_palette.isVisible = true
}
image_draw_undo.setOnClickListener {
custom_draw_view.undo()
toggleDrawTools(draw_tools,false)
}
image_draw_redo.setOnClickListener {
custom_draw_view.redo()
toggleDrawTools(draw_tools,false)
}
}
private fun toggleDrawTools(view: View, showView: Boolean = true) {
if (showView){
view.animate().translationY((0).toPx)
}else{
view.animate().translationY((56).toPx)
}
}
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 {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_red,null))
scaleColorView(image_color_red)
}
image_color_yellow.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_yellow,null))
scaleColorView(image_color_yellow)
}
image_color_green.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_green,null))
scaleColorView(image_color_green)
}
image_color_blue.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_blue,null))
scaleColorView(image_color_blue)
}
image_color_pink.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_pink,null))
scaleColorView(image_color_pink)
}
image_color_brown.setOnClickListener {
custom_draw_view.setColor(ResourcesCompat.getColor(resources, R.color.color_brown,null))
scaleColorView(image_color_brown)
}
}
private fun scaleColorView(view: View) {
//reset scale of all views
image_color_black.scaleX = 1f
image_color_black.scaleY = 1f
image_color_red.scaleX = 1f
image_color_red.scaleY = 1f
image_color_yellow.scaleX = 1f
image_color_yellow.scaleY = 1f
image_color_green.scaleX = 1f
image_color_green.scaleY = 1f
image_color_blue.scaleX = 1f
image_color_blue.scaleY = 1f
image_color_pink.scaleX = 1f
image_color_pink.scaleY = 1f
image_color_brown.scaleX = 1f
image_color_brown.scaleY = 1f
//set scale of selected view
view.scaleX = 1.5f
view.scaleY = 1.5f
}
private fun setPaintWidth() {
seekBar_width.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
custom_draw_view.setStrokeWidth(progress.toFloat())
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
}
private fun setPaintAlpha() {
seekBar_opacity.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
custom_draw_view.setAlpha(progress)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
}
private val Int.toPx: Float
get() = (this * Resources.getSystem().displayMetrics.density)
}
package chat.rocket.android.draw.widget
import android.graphics.Path
import java.io.Serializable
import java.io.Writer
interface Action : Serializable {
fun perform(path: Path)
fun perform(writer: Writer)
}
package chat.rocket.android.draw.widget
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import java.util.*
import android.support.v4.graphics.ColorUtils
import android.support.annotation.ColorInt
class CustomDrawView(context: Context, attrs: AttributeSet) : View(context, attrs) {
var mPaths = LinkedHashMap<MyPath, PaintOptions>()
private var mLastPaths = LinkedHashMap<MyPath, PaintOptions>()
private var mUndonePaths = LinkedHashMap<MyPath, PaintOptions>()
private var mPaint = Paint()
private var mPath = MyPath()
private var mPaintOptions = PaintOptions()
private var mCurX = 0f
private var mCurY = 0f
private var mStartX = 0f
private var mStartY = 0f
private var mIsSaving = false
private var mIsStrokeWidthBarEnabled = false
init {
mPaint.apply {
color = mPaintOptions.color
style = Paint.Style.STROKE
strokeJoin = Paint.Join.ROUND
strokeCap = Paint.Cap.ROUND
strokeWidth = mPaintOptions.strokeWidth
isAntiAlias = true
}
}
fun undo() {
if (mPaths.isEmpty() && mLastPaths.isNotEmpty()) {
mPaths = mLastPaths.clone() as LinkedHashMap<MyPath, PaintOptions>
mLastPaths.clear()
invalidate()
return
}
if (mPaths.isEmpty()) {
return
}
val lastPath = mPaths.values.lastOrNull()
val lastKey = mPaths.keys.lastOrNull()
mPaths.remove(lastKey)
if (lastPath != null && lastKey != null) {
mUndonePaths[lastKey] = lastPath
}
invalidate()
}
fun redo() {
if (mUndonePaths.keys.isEmpty()) {
return
}
val lastKey = mUndonePaths.keys.last()
addPath(lastKey, mUndonePaths.values.last())
mUndonePaths.remove(lastKey)
invalidate()
}
fun setColor(newColor: Int) {
@ColorInt
val alphaColor = ColorUtils.setAlphaComponent(newColor, mPaintOptions.alpha)
mPaintOptions.color = alphaColor
if (mIsStrokeWidthBarEnabled) {
invalidate()
}
}
fun setAlpha(newAlpha: Int) {
val alpha = (newAlpha*255)/100
mPaintOptions.alpha = alpha
setColor(mPaintOptions.color)
}
fun setStrokeWidth(newStrokeWidth: Float) {
mPaintOptions.strokeWidth = newStrokeWidth
if (mIsStrokeWidthBarEnabled) {
invalidate()
}
}
fun getBitmap(): Bitmap {
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.drawColor(Color.WHITE)
mIsSaving = true
draw(canvas)
mIsSaving = false
return bitmap
}
fun addPath(path: MyPath, options: PaintOptions) {
mPaths[path] = options
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
for ((key, value) in mPaths) {
changePaint(value)
canvas.drawPath(key, mPaint)
}
changePaint(mPaintOptions)
canvas.drawPath(mPath, mPaint)
}
private fun changePaint(paintOptions: PaintOptions) {
mPaint.color = paintOptions.color
mPaint.strokeWidth = paintOptions.strokeWidth
}
fun clearCanvas() {
mLastPaths = mPaths.clone() as LinkedHashMap<MyPath, PaintOptions>
mPath.reset()
mPaths.clear()
invalidate()
}
private fun actionDown(x: Float, y: Float) {
mPath.reset()
mPath.moveTo(x, y)
mCurX = x
mCurY = y
}
private fun actionMove(x: Float, y: Float) {
mPath.quadTo(mCurX, mCurY, (x + mCurX) / 2, (y + mCurY) / 2)
mCurX = x
mCurY = y
}
private fun actionUp() {
mPath.lineTo(mCurX, mCurY)
// draw a dot on click
if (mStartX == mCurX && mStartY == mCurY) {
mPath.lineTo(mCurX, mCurY + 2)
mPath.lineTo(mCurX + 1, mCurY + 2)
mPath.lineTo(mCurX + 1, mCurY)
}
mPaths.put(mPath, mPaintOptions)
mPath = MyPath()
mPaintOptions = PaintOptions(mPaintOptions.color, mPaintOptions.strokeWidth, mPaintOptions.alpha)
}
override fun onTouchEvent(event: MotionEvent): Boolean {
val x = event.x
val y = event.y
when (event.action) {
MotionEvent.ACTION_DOWN -> {
mStartX = x
mStartY = y
actionDown(x, y)
mUndonePaths.clear()
}
MotionEvent.ACTION_MOVE -> actionMove(x, y)
MotionEvent.ACTION_UP -> actionUp()
}
invalidate()
return true
}
}
\ No newline at end of file
package chat.rocket.android.draw.widget
import android.graphics.Path
import java.io.Writer
import java.security.InvalidParameterException
class Line(val x: Float, val y: Float) : Action {
override fun perform(path: Path) {
path.lineTo(x, y)
}
override fun perform(writer: Writer) {
writer.write("L$x,$y")
}
}
\ No newline at end of file
package chat.rocket.android.draw.widget
import android.graphics.Path
import java.io.Writer
import java.security.InvalidParameterException
class Move(val x: Float, val y: Float) : Action {
override fun perform(path: Path) {
path.moveTo(x, y)
}
override fun perform(writer: Writer) {
writer.write("M$x,$y")
}
}
\ No newline at end of file
package chat.rocket.android.draw.widget
import android.graphics.Path
import java.io.ObjectInputStream
import java.io.Serializable
import java.util.*
class MyPath : Path(), Serializable {
val actions = LinkedList<Action>()
private fun readObject(inputStream: ObjectInputStream) {
inputStream.defaultReadObject()
val copiedActions = actions.map { it }
copiedActions.forEach {
it.perform(this)
}
}
override fun reset() {
actions.clear()
super.reset()
}
override fun moveTo(x: Float, y: Float) {
actions.add(Move(x, y))
super.moveTo(x, y)
}
override fun lineTo(x: Float, y: Float) {
actions.add(Line(x, y))
super.lineTo(x, y)
}
override fun quadTo(x1: Float, y1: Float, x2: Float, y2: Float) {
actions.add(Quad(x1, y1, x2, y2))
super.quadTo(x1, y1, x2, y2)
}
}
\ No newline at end of file
package chat.rocket.android.draw.widget
import android.graphics.Color
data class PaintOptions(var color: Int = Color.BLACK, var strokeWidth: Float = 8f, var alpha: Int = 255)
package chat.rocket.android.draw.widget
import android.graphics.Path
import java.io.Writer
class Quad(private val x1: Float, private val y1: Float, private val x2: Float, private val y2: Float) : Action {
override fun perform(path: Path) {
path.quadTo(x1, y1, x2, y2)
}
override fun perform(writer: Writer) {
writer.write("Q$x1,$y1 $x2,$y2")
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/color_black" />
<corners android:radius="50dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/color_blue" />
<corners android:radius="50dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/color_brown" />
<corners android:radius="50dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/color_green" />
<corners android:radius="50dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/color_pink" />
<corners android:radius="50dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/color_red" />
<corners android:radius="50dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/color_yellow" />
<corners android:radius="50dp" />
</shape>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C6.49,2 2,6.49 2,12s4.49,10 10,10 10,-4.49 10,-10S17.51,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM15,12c0,1.66 -1.34,3 -3,3s-3,-1.34 -3,-3 1.34,-3 3,-3 3,1.34 3,3z"/>
</vector>
\ No newline at end of file
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path
android:pathData="M10,9V5l-7,7 7,7v-4.1c5,0 8.5,1.6 11,5.1 -1,-5 -4,-10 -11,-11z" android:fillColor="#FF000000"
android:fillColor="@color/actionMenuColor"/> android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector> </vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9c0.83,0 1.5,-0.67 1.5,-1.5 0,-0.39 -0.15,-0.74 -0.39,-1.01 -0.23,-0.26 -0.38,-0.61 -0.38,-0.99 0,-0.83 0.67,-1.5 1.5,-1.5L16,16c2.76,0 5,-2.24 5,-5 0,-4.42 -4.03,-8 -9,-8zM6.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S5.67,9 6.5,9 8,9.67 8,10.5 7.33,12 6.5,12zM9.5,8C8.67,8 8,7.33 8,6.5S8.67,5 9.5,5s1.5,0.67 1.5,1.5S10.33,8 9.5,8zM14.5,8c-0.83,0 -1.5,-0.67 -1.5,-1.5S13.67,5 14.5,5s1.5,0.67 1.5,1.5S15.33,8 14.5,8zM17.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S16.67,9 17.5,9s1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/>
</vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M15.14,3C14.63,3 14.12,3.2 13.73,3.59L2.59,14.73C1.81,15.5 1.81,16.77 2.59,17.56L5.03,20H12.69L21.41,11.27C22.2,10.5 22.2,9.23 21.41,8.44L16.56,3.59C16.17,3.2 15.65,3 15.14,3M17,18L15,20H22V18"/>
</vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M17.66,8L12,2.35 6.34,8C4.78,9.56 4,11.64 4,13.64s0.78,4.11 2.34,5.67 3.61,2.35 5.66,2.35 4.1,-0.79 5.66,-2.35S20,15.64 20,13.64 19.22,9.56 17.66,8zM6,14c0.01,-2 0.62,-3.27 1.76,-4.4L12,5.27l4.24,4.38C17.38,10.77 17.99,12 18,14H6z"/>
</vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M18.4,10.6C16.55,8.99 14.15,8 11.5,8c-4.65,0 -8.58,3.03 -9.96,7.22L3.9,16c1.05,-3.19 4.05,-5.5 7.6,-5.5 1.95,0 3.73,0.72 5.12,1.88L13,16h9V7l-3.6,3.6z"/>
</vector>
\ No newline at end of file
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path
android:pathData="M6,17h3l2,-4L11,7L5,7v6h3zM14,17h3l2,-4L19,7h-6v6h3z" android:fillColor="#FF000000"
android:fillColor="@color/actionMenuColor"/> android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector> </vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12.5,8c-2.65,0 -5.05,0.99 -6.9,2.6L2,7v9h9l-3.62,-3.62c1.39,-1.16 3.16,-1.88 5.12,-1.88 3.54,0 6.55,2.31 7.6,5.5l2.37,-0.78C21.08,11.03 17.15,8 12.5,8z"/>
</vector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DrawingActivity">
<chat.rocket.android.draw.widget.CustomDrawView
android:id="@+id/custom_draw_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_white" />
<ImageView
android:id="@+id/image_close_drawing"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/ic_close_black_24dp"
android:tint="@color/icon_color"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="@color/color_white"
android:foreground="?selectableItemBackgroundBorderless" />
<ImageView
android:id="@+id/image_send_drawing"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/ic_send_black_24dp"
android:padding="16dp"
android:tint="@color/colorAccent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="@color/color_white"
android:foreground="?selectableItemBackgroundBorderless" />
<android.support.constraint.ConstraintLayout
android:id="@+id/draw_tools"
android:layout_width="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:elevation="4dp"
android:translationY="56dp" >
<ImageView
android:id="@+id/image_draw_eraser"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/ic_eraser_black_24dp"
android:padding="16dp"
android:tint="@color/icon_color"
android:foreground="?selectableItemBackground"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/image_draw_width"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/image_draw_width"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/ic_adjust_black_24dp"
android:padding="16dp"
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_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/image_draw_color"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/ic_color_lens_black_24dp"
android:padding="16dp"
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_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/image_draw_opacity"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/ic_opacity_black_24dp"
android:padding="16dp"
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_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/image_draw_undo"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/ic_undo_black_24dp"
android:padding="16dp"
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_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/image_draw_redo"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/ic_redo_black_24dp"
android:padding="16dp"
android:tint="@color/icon_color"
android:foreground="?selectableItemBackground"
app:layout_constraintStart_toEndOf="@id/image_draw_undo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<SeekBar
android:id="@+id/seekBar_width"
android:layout_width="0dp"
android:layout_height="56dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/image_draw_eraser"
android:progressTint="@color/colorAccent"
android:thumbTint="@color/colorAccent"
android:progress="8"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<SeekBar
android:id="@+id/seekBar_opacity"
android:layout_width="0dp"
android:layout_height="56dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/image_draw_eraser"
android:progress="100"
android:progressTint="@color/colorAccent"
android:thumbTint="@color/colorAccent"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<include
android:id="@+id/draw_color_palette"
layout="@layout/color_palette_view"
android:layout_width="0dp"
android:layout_height="56dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/image_draw_eraser" />
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/image_color_black"
android:layout_width="48dp"
android:layout_height="match_parent"
android:src="@drawable/circle_black"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:scaleY="1.5"
android:scaleX="1.5"/>
<ImageView
android:id="@+id/image_color_red"
android:layout_width="48dp"
android:layout_height="match_parent"
android:src="@drawable/circle_red"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="12dp"
android:paddingEnd="12dp" />
<ImageView
android:id="@+id/image_color_yellow"
android:layout_width="48dp"
android:layout_height="match_parent"
android:src="@drawable/circle_yellow"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="12dp"
android:paddingEnd="12dp" />
<ImageView
android:id="@+id/image_color_green"
android:layout_width="48dp"
android:layout_height="match_parent"
android:src="@drawable/circle_green"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="12dp"
android:paddingEnd="12dp" />
<ImageView
android:id="@+id/image_color_blue"
android:layout_width="48dp"
android:layout_height="match_parent"
android:src="@drawable/circle_blue"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="12dp"
android:paddingEnd="12dp" />
<ImageView
android:id="@+id/image_color_pink"
android:layout_width="48dp"
android:layout_height="match_parent"
android:src="@drawable/circle_pink"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="12dp"
android:paddingEnd="12dp" />
<ImageView
android:id="@+id/image_color_brown"
android:layout_width="48dp"
android:layout_height="match_parent"
android:src="@drawable/circle_brown"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="12dp"
android:paddingEnd="12dp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorAccent">FF1976D2</color>
<color name="icon_color">#C2C2C2</color>
<color name="color_white">#FFFFFF</color>
<color name="color_black">#000</color>
<color name="color_red">#FF5252</color>
<color name="color_yellow">#FFEB3B</color>
<color name="color_green">#00C853</color>
<color name="color_blue">#00B0FF</color>
<color name="color_pink">#D500F9</color>
<color name="color_brown">#8D6E63</color>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">Draw</string>
</resources>
package chat.rocket.android.draw;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
include ':app', ':player' include ':app', ':player', ':draw'
\ No newline at end of file \ No newline at end of file
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