Unverified Commit 117ea19b authored by Filipe de Lima Brito's avatar Filipe de Lima Brito Committed by GitHub

Merge branch 'develop' into feature_1394

parents f5a9ad41 b48db851
......@@ -62,6 +62,7 @@ dependencies {
implementation project(':player')
implementation project(':emoji')
implementation project(':draw')
implementation libraries.kotlin
implementation libraries.coroutines
......
......@@ -3,6 +3,7 @@ package chat.rocket.android.chatroom.domain
import android.content.Context
import android.net.Uri
import chat.rocket.android.util.extensions.*
import java.io.File
import javax.inject.Inject
class UriInteractor @Inject constructor(private val context: Context) {
......@@ -33,4 +34,9 @@ class UriInteractor @Inject constructor(private val context: Context) {
* Note: It should be an image.
*/
fun getBitmap(uri: Uri) = uri.getBitmpap(context)
/**
* Returns the Uri from the [File].
*/
fun getUri(file: File) = Uri.fromFile(file)
}
\ No newline at end of file
package chat.rocket.android.chatroom.presentation
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Environment
import chat.rocket.android.R
import chat.rocket.android.chatroom.adapter.AutoCompleteType
import chat.rocket.android.chatroom.adapter.PEOPLE
......@@ -77,6 +80,8 @@ import timber.log.Timber
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.io.File
import java.io.FileOutputStream
import java.util.*
import javax.inject.Inject
......@@ -898,6 +903,12 @@ class ChatRoomPresenter @Inject constructor(
}
}
fun getDrawingImageUri(byteArray: ByteArray): Uri {
val bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
val file = saveDrawingImage(bitmap)
return uriInteractor.getUri(file)
}
private suspend fun subscribeTypingStatus() {
launch(CommonPool + strategy.jobs) {
client.subscribeTypingStatus(chatRoomId.toString()) { _, id ->
......@@ -963,4 +974,17 @@ class ChatRoomPresenter @Inject constructor(
}
}
}
private fun saveDrawingImage(bitmap: Bitmap): File {
val imageDir = "${Environment.DIRECTORY_PICTURES}/Rocket.Chat Images/"
val path = Environment.getExternalStoragePublicDirectory(imageDir)
val file = File(path, UUID.randomUUID().toString()+".png")
path.mkdirs()
file.createNewFile()
val outputStream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.PNG,70, outputStream)
outputStream.flush()
outputStream.close()
return file
}
}
\ No newline at end of file
......@@ -54,8 +54,9 @@ interface ChatRoomView : LoadingView, MessageView {
* Uploads a file to a chat room.
*
* @param uri The file URI to send.
* @param msg Message to send with attachments
*/
fun uploadFile(uri: Uri)
fun uploadFile(uri: Uri, msg: String)
/**
* Shows a invalid file message.
......
package chat.rocket.android.chatroom.ui
import android.app.Activity
import android.app.AlertDialog
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
......@@ -12,10 +13,14 @@ import android.text.SpannableStringBuilder
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.FrameLayout
import androidx.annotation.DrawableRes
import androidx.core.text.bold
import androidx.core.view.isVisible
......@@ -36,6 +41,7 @@ import chat.rocket.android.chatroom.uimodel.MessageUiModel
import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
import chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel
import chat.rocket.android.chatroom.uimodel.suggestion.PeopleSuggestionUiModel
import chat.rocket.android.draw.DrawingActivity
import chat.rocket.android.emoji.ComposerEditText
import chat.rocket.android.emoji.Emoji
import chat.rocket.android.emoji.EmojiKeyboardListener
......@@ -46,6 +52,7 @@ import chat.rocket.android.emoji.EmojiReactionListener
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.MessageParser
import chat.rocket.android.helper.ImageHelper
import chat.rocket.android.util.extensions.asObservable
import chat.rocket.android.util.extensions.circularRevealOrUnreveal
import chat.rocket.android.util.extensions.fadeIn
......@@ -56,6 +63,8 @@ import chat.rocket.android.util.extensions.rotateBy
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.extensions.getMimeType
import chat.rocket.android.util.extensions.getFileName
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf
import chat.rocket.core.internal.realtime.socket.model.State
......@@ -103,6 +112,7 @@ private const val BUNDLE_CHAT_ROOM_NAME = "chat_room_name"
private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type"
private const val BUNDLE_IS_CHAT_ROOM_READ_ONLY = "is_chat_room_read_only"
private const val REQUEST_CODE_FOR_PERFORM_SAF = 42
private const val REQUEST_CODE_FOR_DRAW = 101
private const val BUNDLE_CHAT_ROOM_LAST_SEEN = "chat_room_last_seen"
private const val BUNDLE_CHAT_ROOM_IS_SUBSCRIBED = "chat_room_is_subscribed"
private const val BUNDLE_CHAT_ROOM_IS_CREATOR = "chat_room_is_creator"
......@@ -227,12 +237,62 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
if (requestCode == REQUEST_CODE_FOR_PERFORM_SAF && resultCode == Activity.RESULT_OK) {
if (resultData != null) {
uploadFile(resultData.data)
if (resultData != null && resultCode == Activity.RESULT_OK) {
when(requestCode){
REQUEST_CODE_FOR_PERFORM_SAF -> {
fileAttachmentDialog(resultData.data)
}
REQUEST_CODE_FOR_DRAW -> {
val result= resultData.getByteArrayExtra("bitmap")
val uri = presenter.getDrawingImageUri(result)
fileAttachmentDialog(uri)
}
}
}
}
private fun fileAttachmentDialog(data: Uri) {
val builder = AlertDialog.Builder(activity)
val dialogView = View.inflate(context, R.layout.file_attachments_dialog, null)
builder.setView(dialogView)
val alertDialog = builder.create()
dialogView?.let {
val imagePreview = it.findViewById<ImageView>(R.id.image_preview)
val sendButton = it.findViewById<Button>(R.id.button_send)
val cancelButton: Button = it.findViewById(R.id.button_cancel)
val description = it.findViewById<EditText>(R.id.text_file_description)
val audioVideoAttachment = it.findViewById<FrameLayout>(R.id.audio_video_attachment)
val textFile = it.findViewById<TextView>(R.id.text_file_name)
activity?.let {
data.getMimeType(it).apply {
when {
this.startsWith("image") -> {
imagePreview.isVisible = true
imagePreview.setImageURI(data)
}
this.startsWith("video") -> {
audioVideoAttachment.isVisible = true
}
else -> {
textFile.isVisible = true
textFile.text = data.getFileName(it)
}
}
}
}
sendButton.setOnClickListener {
uploadFile(data, (citation ?:"") + description.text.toString())
clearMessageComposition()
alertDialog.dismiss()
}
cancelButton.setOnClickListener {
alertDialog.dismiss()
}
}
alertDialog.show()
}
override fun onPrepareOptionsMenu(menu: Menu) {
menu.clear()
......@@ -481,9 +541,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
override fun uploadFile(uri: Uri) {
// TODO Just leaving a blank message that comes with the file for now. In the future lets add the possibility to add a message with the file to be uploaded.
presenter.uploadFile(chatRoomId, uri, "")
override fun uploadFile(uri: Uri, msg: String) {
presenter.uploadFile(chatRoomId, uri, msg)
}
override fun showInvalidFileMessage() {
......@@ -810,6 +869,20 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_add_reaction.setOnClickListener { view ->
openEmojiKeyboardPopup()
}
button_drawing.setOnClickListener {
activity?.let {
if (!ImageHelper.canWriteToExternalStorage(it)) {
ImageHelper.checkWritingPermission(it)
}else{
val intent = Intent(it, DrawingActivity::class.java)
startActivityForResult(intent, REQUEST_CODE_FOR_DRAW)
}
}
handler.postDelayed({
hideAttachmentOptions()
}, 400)
}
}
}
......
......@@ -147,16 +147,16 @@ object ImageHelper {
return true
}
private fun canWriteToExternalStorage(context: Context): Boolean {
fun canWriteToExternalStorage(context: Context): Boolean {
return AndroidPermissionsHelper.checkPermission(
context,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
}
private fun checkWritingPermission(context: Context) {
if (context is ContextThemeWrapper && context.baseContext is Activity) {
val activity = context.baseContext as Activity
fun checkWritingPermission(context: Context) {
if (context is ContextThemeWrapper) {
val activity = if (context.baseContext is Activity) context.baseContext as Activity else context as Activity
AndroidPermissionsHelper.requestPermission(
activity,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
......
<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="#FF1D74F5"
android:pathData="M4.59,6.89c0.7,-0.71 1.4,-1.35 1.71,-1.22 0.5,0.2 0,1.03 -0.3,1.52 -0.25,0.42 -2.86,3.89 -2.86,6.31 0,1.28 0.48,2.34 1.34,2.98 0.75,0.56 1.74,0.73 2.64,0.46 1.07,-0.31 1.95,-1.4 3.06,-2.77 1.21,-1.49 2.83,-3.44 4.08,-3.44 1.63,0 1.65,1.01 1.76,1.79 -3.78,0.64 -5.38,3.67 -5.38,5.37 0,1.7 1.44,3.09 3.21,3.09 1.63,0 4.29,-1.33 4.69,-6.1L21,14.88v-2.5h-2.47c-0.15,-1.65 -1.09,-4.2 -4.03,-4.2 -2.25,0 -4.18,1.91 -4.94,2.84 -0.58,0.73 -2.06,2.48 -2.29,2.72 -0.25,0.3 -0.68,0.84 -1.11,0.84 -0.45,0 -0.72,-0.83 -0.36,-1.92 0.35,-1.09 1.4,-2.86 1.85,-3.52 0.78,-1.14 1.3,-1.92 1.3,-3.28C8.95,3.69 7.31,3 6.44,3 5.12,3 3.97,4 3.72,4.25c-0.36,0.36 -0.66,0.66 -0.88,0.93l1.75,1.71zM13.88,18.55c-0.31,0 -0.74,-0.26 -0.74,-0.72 0,-0.6 0.73,-2.2 2.87,-2.76 -0.3,2.69 -1.43,3.48 -2.13,3.48z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/colorAccent" />
<corners android:radius="4dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="16dp">
<TextView
android:id="@+id/text_dialog_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/msg_upload_file"
style="@style/Base.DialogWindowTitle.AppCompat"
android:layout_margin="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_file_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="@color/colorAccent"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:drawableStart="@drawable/ic_files_24dp"
android:drawablePadding="6dp"
app:layout_constraintTop_toBottomOf="@id/text_dialog_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_margin="16dp"
android:textDirection="locale"
android:visibility="gone"
tools:text="This is a very, very, very long filename, to test how the layout will work on very very very long filenames.pdf" />
<FrameLayout
android:id="@+id/audio_video_attachment"
android:layout_width="0dp"
android:layout_height="150dp"
android:background="@color/colorBlack"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/text_file_name"
android:layout_margin="16dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/exo_controls_play" />
</FrameLayout>
<ImageView
android:id="@+id/image_preview"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintHeight_max="240dp"
app:layout_constrainedHeight="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/audio_video_attachment"
android:layout_margin="16dp"
android:adjustViewBounds="true"
android:visibility="gone"
tools:visibility="visible" />
<EditText
android:id="@+id/text_file_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/image_preview"
android:layout_margin="16dp"
android:hint="@string/msg_file_description" />
<Button
android:id="@+id/button_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_file_description"
android:layout_margin="16dp"
android:background="@drawable/rounded_color_accent"
android:text="@string/msg_send"
android:textColor="@color/colorWhite" />
<Button
android:id="@+id/button_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/text_file_description"
app:layout_constraintEnd_toStartOf="@id/button_send"
android:layout_margin="16dp"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:text="@string/msg_cancel" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
\ No newline at end of file
......@@ -15,4 +15,14 @@
android:gravity="start|center"
android:text="@string/action_files" />
<Button
android:id="@+id/button_drawing"
style="?android:attr/borderlessButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="20dp"
android:drawableStart="@drawable/ic_gesture_black_24dp"
android:gravity="start|center"
android:text="@string/action_drawing" />
</LinearLayout>
\ No newline at end of file
......@@ -39,6 +39,7 @@
<string name="action_away">Ausente</string>
<string name="action_busy">Ocupado</string>
<string name="action_invisible">Invisible</string>
<string name="action_drawing">Dibujo</string>
// TODO: Add proper translation.
<string name="action_save_to_gallery">Save to gallery</string>
......@@ -132,6 +133,9 @@
// TODO: Add proper translation.
<string name="msg_search">Search</string>
<string name="msg_message_copied">Mensaje copiado</string>
<string name="msg_upload_file">Subir archivo</string>
<string name="msg_file_description">Descripción del archivo</string>
<string name="msg_send">enviar</string>
// TODO: Add proper translation.
<string name="msg_delete_message">Delete Message</string>
<string name="msg_delete_description">Are you sure you want to delete this message</string>
......@@ -149,7 +153,6 @@
<string name="msg_member_not_found">Member not found</string>
<string name="msg_channel_created_successfully">Channel created successfully</string>
<!-- System messages -->
<string name="message_room_name_changed">Nombre de la sala cambiado para: %1$s por %2$s</string>
<string name="message_user_added_by">Usuario %1$s añadido por %2$s</string>
......
......@@ -39,6 +39,7 @@
<string name="action_away">Loin</string>
<string name="action_busy">Occupé</string>
<string name="action_invisible">Invisible</string>
<string name="action_drawing">Dessin</string>
// TODO: Add proper translation.
<string name="action_save_to_gallery">Save to gallery</string>
......@@ -132,6 +133,9 @@
// TODO: Add proper translation.
<string name="msg_search">Search</string>
<string name="msg_message_copied">Message copié</string>
<string name="msg_upload_file">Téléverser un fichier</string>
<string name="msg_file_description">Description du fichier</string>
<string name="msg_send">envoyer</string>
// TODO: Add proper translation.
<string name="msg_delete_message">Delete Message</string>
<string name="msg_delete_description">Are you sure you want to delete this message</string>
......
......@@ -15,8 +15,7 @@
<string name="title_password">पासवर्ड बदलें</string>
<string name="title_update_profile">प्रोफ़ाइल अपडेट करें</string>
<string name="title_about">परिचय</string>
// TODO: Add proper translation.
<string name="title_create_channel">Create Channel</string>
<string name="title_create_channel">चैनल बनाएं</string>
<!-- Actions -->
<string name="action_connect">जुडिये</string>
......@@ -27,9 +26,8 @@
<string name="action_search">खोजें</string>
<string name="action_update">अद्यतन करें</string>
<string name="action_settings">सेटिंग्स</string>
// TODO: Add proper translation.
<string name="action_create_channel">Create channel</string>
<string name="action_create">Create</string>
<string name="action_create_channel">चैनल बनाएं</string>
<string name="action_create">बनाएं</string>
<string name="action_logout">लोग आउट करें</string>
<string name="action_files">फ़ाइलें</string>
<string name="action_confirm_password">पासवर्ड परिवर्तन की पुष्टि करें</string>
......@@ -40,6 +38,7 @@
<string name="action_busy">व्यस्त</string>
<string name="action_invisible">अदृश्य</string>
<string name="action_save_to_gallery">गैलरी में सहेजें</string>
<string name="action_drawing">चित्रकारी</string>
<!-- Settings List -->
<string-array name="settings_actions">
......@@ -89,7 +88,7 @@
<string name="msg_preview_video">वीडियो</string>
<string name="msg_preview_audio">ऑडियो</string>
<string name="msg_preview_photo">तस्वीरें</string>
<string name="msg_preview_file">File</string>
<string name="msg_preview_file">फ़ाइल</string>
<string name="msg_unread_messages">अपठित संदेश</string>
<string name="msg_no_messages_yet">अभी तक कोई पोस्ट नहीं</string>
<string name="msg_version">वर्शन %1$s</string>
......@@ -118,26 +117,26 @@
<string name="msg_are_typing">\u0020टाइप कर रहे हैं…</string>
<string name="msg_several_users_are_typing">कई उपयोगकर्ता टाइप कर रहे हैं…</string>
<string name="msg_no_search_found">कोई परिणाम नहीं मिला</string>
// TODO: Add proper translation.
<string name="msg_channel_name">Channel name</string>
// TODO: Add proper translation.
<string name="msg_search">Search</string>
<string name="msg_channel_name">चैनल का नाम</string>
<string name="msg_search">खोजें</string>
<string name="msg_message_copied">संदेश कॉपी किया गया</string>
<string name="msg_upload_file">फाइल अपलोड करें</string>
<string name="msg_file_description">फाइल विवरण</string>
<string name="msg_send">भेजें</string>
<string name="msg_delete_message">संदेश को हटाएं</string>
<string name="msg_delete_description">क्या आप निश्चित रूप से यह संदेश हटाना चाहते हैं</string>
<!-- Create channel messages -->
// TODO: Add proper translation.
<string name="msg_private_channel">Private</string>
<string name="msg_public_channel">Public</string>
<string name="msg_private_channel_description">Only you and invited members can access this channel</string>
<string name="msg_public_channel_description">Everyone can access this channel</string>
<string name="msg_ready_only_channel">Read only channel</string>
<string name="msg_ready_only_channel_description">Only admin can write new messages</string>
<string name="msg_invite_members">Invite members to channel</string>
<string name="msg_member_already_added">You have already selected this user</string>
<string name="msg_member_not_found">Member not found</string>
<string name="msg_channel_created_successfully">Channel created successfully</string>
<string name="msg_private_channel">प्राइवेट</string>
<string name="msg_public_channel">सार्वजनिक</string>
<string name="msg_private_channel_description">केवल आप और आमंत्रित सदस्य ही इस चैनल तक पहुंच सकते हैं</string>
<string name="msg_public_channel_description">हर कोई इस चैनल तक पहुंच सकता है</string>
<string name="msg_ready_only_channel">चैनल केवल पढ़ने के लिए है।</string>
<string name="msg_ready_only_channel_description">केवल एडमिन नए संदेश लिख सकते हैं</string>
<string name="msg_invite_members">सदस्यों को चैनल में आमंत्रित करें</string>
<string name="msg_member_already_added">आपने पहले से ही इस यूजर को चुन चुके है।</string>
<string name="msg_member_not_found">सदस्य नहीं मिला</string>
<string name="msg_channel_created_successfully">चैनल सफलतापूर्वक बनाया गया</string>
<!-- System messages -->
<string name="message_room_name_changed">%2$s ने रूम का नाम बदलकर %1$s किया</string>
......@@ -176,18 +175,16 @@
<string name="permission_starring_not_allowed">तारांकित की अनुमति नहीं है</string>
<!-- Favorite/Unfavorite chat room -->
<!-- TODO Add proper translation-->
<string name="title_favorite_chat">Favorite chat</string>
<string name="title_unfavorite_chat">Unfavorite chat</string>
<string name="title_favorite_chat">पसंदीदा चैट</string>
<string name="title_unfavorite_chat">नापसंद चैट</string>
<!-- Members List -->
<string name="title_members_list">सदस्य</string>
<!-- Mentions -->
<!-- TODO Add proper translation-->
<string name="msg_mentions">Mentions</string>
<string name="msg_no_mention">No mention</string>
<string name="msg_all_the_mentions_appear_here">All the mentions\nappear here</string>
<string name="msg_mentions">ज़िक्र</string>
<string name="msg_no_mention">कोई ज़िक्र नहीं</string>
<string name="msg_all_the_mentions_appear_here">सभी ज़िक्र यहां दिखाई देते हैं</string>
<!-- Pinned Messages -->
<string name="title_pinned_messages">पिन किए गए संदेश</string>
......@@ -233,7 +230,7 @@
<string name="Archive">संग्रहित करें</string>
<string name="Remove_someone_from_room">रूम से किसी को निकालें</string>
<string name="Leave_the_current_channel">मौजूदा चैनल को छोड़ दें</string>
<string name="Displays_action_text">Displays action text</string>
<string name="Displays_action_text">कार्रवाई पाठ प्रदर्शित करता है</string>
<string name="Direct_message_someone">किसी को प्रत्यक्ष संदेश भेजें</string>
<string name="Mute_someone_in_room">रूम में किसी को म्यूट करें</string>
<string name="Unmute_someone_in_room">रूम में किसी को अनम्यूट करें</string>
......@@ -259,7 +256,7 @@
<string name="header_channel">चैनलों</string>
<string name="header_private_groups">निजी समूहों</string>
<string name="header_direct_messages">प्रत्यक्ष संदेश</string>
<string name="header_live_chats">Live Chats</string>
<string name="header_live_chats">लाइव चैट</string>
<string name="header_unknown">अज्ञात</string>
<!--Notifications-->
......
......@@ -37,6 +37,7 @@
<string name="action_away">Ausente</string>
<string name="action_busy">Ocupado</string>
<string name="action_invisible">Invisível</string>
<string name="action_drawing">Desenhando</string>
<string name="action_save_to_gallery">Salvar na galeria</string>
<!-- Settings List -->
......@@ -119,6 +120,9 @@
<string name="msg_channel_name">Nome do chat</string>
<string name="msg_search">Buscar</string>
<string name="msg_message_copied">Mensagem copiada</string>
<string name="msg_upload_file">Subir arquivo</string>
<string name="msg_file_description">Descrição do arquivo</string>
<string name="msg_send">Enviar</string>
// TODO: Add proper translation.
<string name="msg_delete_message">Delete Message</string>
<string name="msg_delete_description">Are you sure you want to delete this message</string>
......
......@@ -116,6 +116,9 @@
<string name="msg_several_users_are_typing">Несколько пользователей печатают…</string>
<string name="msg_no_search_found">Результатов не найдено</string>
<string name="msg_message_copied">Сообщение скопировано</string>
<string name="msg_upload_file">Загрузить файл</string>
<string name="msg_file_description">Описание файла</string>
<string name="msg_send">послать</string>
<string name="msg_delete_message">Удалить сообщение</string>
<string name="msg_delete_description">Вы уверены, что хотите удалить это сообщение?</string>
<string name="msg_channel_name">Название канала</string>
......
......@@ -38,6 +38,7 @@
<string name="action_away">Away</string>
<string name="action_busy">Busy</string>
<string name="action_invisible">Invisible</string>
<string name="action_drawing">Drawing</string>
<string name="action_save_to_gallery">Save to gallery</string>
<!-- Settings List -->
......@@ -119,6 +120,9 @@
<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_upload_file">Upload file</string>
<string name="msg_file_description">File description</string>
<string name="msg_send">Send</string>
<!-- Create channel messages -->
<string name="msg_private_channel">Private</string>
......@@ -131,7 +135,6 @@
<string name="msg_member_already_added">You have already selected this user</string>
<string name="msg_member_not_found">Member not found</string>
<string name="msg_channel_created_successfully">Channel created successfully</string>
<string name="msg_message_copied">Message copied</string>
<string name="msg_delete_message">Delete Message</string>
<string name="msg_delete_description">Are you sure you want to delete this message</string>
......
apply plugin: 'com.android.library'
android {
compileSdkVersion versions.compileSdk
buildToolsVersion versions.buildTools
defaultConfig {
minSdkVersion 21
targetSdkVersion versions.targetSdk
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.kotlin
implementation libraries.constraintlayout
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'
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<?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.app.Activity
import android.content.Intent
import android.content.res.Resources
import android.graphics.Bitmap
import android.os.Bundle
import android.view.View
import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.activity_drawing.*
import kotlinx.android.synthetic.main.color_palette_view.*
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, 70, 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
interface Action : Serializable {
fun perform(path: Path)
}
package chat.rocket.android.draw.widget
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.annotation.ColorInt
import androidx.core.graphics.ColorUtils
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
class Line(val x: Float, val y: Float) : Action {
override fun perform(path: Path) {
path.lineTo(x, y)
}
}
\ No newline at end of file
package chat.rocket.android.draw.widget
import android.graphics.Path
class Move(val x: Float, val y: Float) : Action {
override fun perform(path: Path) {
path.moveTo(x, y)
}
}
\ No newline at end of file
package chat.rocket.android.draw.widget
import android.graphics.Path
import java.io.Serializable
import java.util.*
class MyPath : Path(), Serializable {
val actions = LinkedList<Action>()
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
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)
}
}
\ 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
<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="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 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
<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="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</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"?>
<androidx.constraintlayout.widget.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" />
<androidx.constraintlayout.widget.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" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.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>
include ':app', ':player', ':emoji' //, ':wear'
\ No newline at end of file
include ':app', ':player', ':emoji', ':draw' //, ':wear'
\ 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