Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
AloqaIM-Android
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
AloqaIM-Android
Commits
ff7ed148
Commit
ff7ed148
authored
Mar 16, 2018
by
Leonardo Aramaki
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Show default messages for different types of quotes with attachments
parent
102d920b
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
21 additions
and
72 deletions
+21
-72
ActionSnackbar.kt
...in/java/chat/rocket/android/chatroom/ui/ActionSnackbar.kt
+0
-3
ViewModelMapper.kt
...chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
+9
-43
MessageParser.kt
...src/main/java/chat/rocket/android/helper/MessageParser.kt
+4
-7
quote.xml
app/src/main/res/drawable/quote.xml
+0
-10
item_message_attachment.xml
app/src/main/res/layout/item_message_attachment.xml
+2
-9
strings.xml
app/src/main/res/values-pt-rBR/strings.xml
+3
-0
strings.xml
app/src/main/res/values/strings.xml
+3
-0
No files found.
app/src/main/java/chat/rocket/android/chatroom/ui/ActionSnackbar.kt
View file @
ff7ed148
package
chat.rocket.android.chatroom.ui
package
chat.rocket.android.chatroom.ui
import
android.graphics.drawable.Drawable
import
android.support.design.widget.BaseTransientBottomBar
import
android.support.design.widget.BaseTransientBottomBar
import
android.support.v4.view.ViewCompat
import
android.support.v4.view.ViewCompat
import
android.text.Spannable
import
android.text.Spannable
...
@@ -28,7 +27,6 @@ class ActionSnackbar : BaseTransientBottomBar<ActionSnackbar> {
...
@@ -28,7 +27,6 @@ class ActionSnackbar : BaseTransientBottomBar<ActionSnackbar> {
actionSnackbar
.
cancelView
=
view
.
findViewById
(
R
.
id
.
image_view_action_cancel_quote
)
as
ImageView
actionSnackbar
.
cancelView
=
view
.
findViewById
(
R
.
id
.
image_view_action_cancel_quote
)
as
ImageView
actionSnackbar
.
duration
=
BaseTransientBottomBar
.
LENGTH_INDEFINITE
actionSnackbar
.
duration
=
BaseTransientBottomBar
.
LENGTH_INDEFINITE
val
spannable
=
Markwon
.
markdown
(
context
,
content
).
trim
()
val
spannable
=
Markwon
.
markdown
(
context
,
content
).
trim
()
actionSnackbar
.
marginDrawable
=
context
.
getDrawable
(
R
.
drawable
.
quote
)
actionSnackbar
.
messageTextView
.
content
=
spannable
actionSnackbar
.
messageTextView
.
content
=
spannable
return
actionSnackbar
return
actionSnackbar
}
}
...
@@ -38,7 +36,6 @@ class ActionSnackbar : BaseTransientBottomBar<ActionSnackbar> {
...
@@ -38,7 +36,6 @@ class ActionSnackbar : BaseTransientBottomBar<ActionSnackbar> {
lateinit
var
cancelView
:
View
lateinit
var
cancelView
:
View
private
lateinit
var
messageTextView
:
TextView
private
lateinit
var
messageTextView
:
TextView
private
lateinit
var
titleTextView
:
TextView
private
lateinit
var
titleTextView
:
TextView
private
lateinit
var
marginDrawable
:
Drawable
var
text
:
String
=
""
var
text
:
String
=
""
set
(
value
)
{
set
(
value
)
{
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
View file @
ff7ed148
...
@@ -23,7 +23,6 @@ import chat.rocket.core.model.url.Url
...
@@ -23,7 +23,6 @@ import chat.rocket.core.model.url.Url
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.withContext
import
kotlinx.coroutines.experimental.withContext
import
okhttp3.HttpUrl
import
okhttp3.HttpUrl
import
timber.log.Timber
import
java.security.InvalidParameterException
import
java.security.InvalidParameterException
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -96,8 +95,13 @@ class ViewModelMapper @Inject constructor(private val context: Context,
...
@@ -96,8 +95,13 @@ class ViewModelMapper @Inject constructor(private val context: Context,
private
fun
mapMessageAttachment
(
message
:
Message
,
attachment
:
MessageAttachment
):
MessageAttachmentViewModel
{
private
fun
mapMessageAttachment
(
message
:
Message
,
attachment
:
MessageAttachment
):
MessageAttachmentViewModel
{
val
attachmentAuthor
=
attachment
.
author
!!
val
attachmentAuthor
=
attachment
.
author
!!
val
attachmentText
=
attachment
.
text
?:
""
val
time
=
getTime
(
attachment
.
timestamp
!!
)
val
time
=
getTime
(
attachment
.
timestamp
!!
)
val
attachmentText
=
when
(
attachment
.
attachments
.
orEmpty
().
firstOrNull
())
{
is
ImageAttachment
->
context
.
getString
(
R
.
string
.
msg_quote_photo
)
is
VideoAttachment
->
context
.
getString
(
R
.
string
.
msg_quote_video
)
is
AudioAttachment
->
context
.
getString
(
R
.
string
.
msg_quote_audio
)
else
->
attachment
.
text
?:
""
}
return
MessageAttachmentViewModel
(
message
=
getMessageWithoutQuoteMarkdown
(
message
),
rawData
=
message
,
return
MessageAttachmentViewModel
(
message
=
getMessageWithoutQuoteMarkdown
(
message
),
rawData
=
message
,
messageId
=
message
.
id
,
time
=
time
,
senderName
=
attachmentAuthor
,
messageId
=
message
.
id
,
time
=
time
,
senderName
=
attachmentAuthor
,
...
@@ -159,27 +163,7 @@ class ViewModelMapper @Inject constructor(private val context: Context,
...
@@ -159,27 +163,7 @@ class ViewModelMapper @Inject constructor(private val context: Context,
val
time
=
getTime
(
message
.
timestamp
)
val
time
=
getTime
(
message
.
timestamp
)
val
avatar
=
getUserAvatar
(
message
)
val
avatar
=
getUserAvatar
(
message
)
val
baseUrl
=
settings
.
baseUrl
()
val
content
=
getContent
(
context
,
getMessageWithoutQuoteMarkdown
(
message
))
var
quote
:
Message
?
=
null
val
urls
=
ArrayList
<
Url
>()
message
.
urls
?.
let
{
if
(
it
.
isEmpty
())
return
@let
for
(
url
in
it
)
{
urls
.
add
(
url
)
baseUrl
?.
let
{
val
quoteUrl
=
HttpUrl
.
parse
(
url
.
url
)
val
serverUrl
=
HttpUrl
.
parse
(
baseUrl
)
if
(
quoteUrl
!=
null
&&
serverUrl
!=
null
)
{
quote
=
makeQuote
(
quoteUrl
,
serverUrl
)
?.
let
{
getMessageWithoutQuoteMarkdown
(
it
)
}
}
}
}
}
val
content
=
getContent
(
context
,
getMessageWithoutQuoteMarkdown
(
message
),
quote
)
MessageViewModel
(
message
=
getMessageWithoutQuoteMarkdown
(
message
),
rawData
=
message
,
MessageViewModel
(
message
=
getMessageWithoutQuoteMarkdown
(
message
),
rawData
=
message
,
messageId
=
message
.
id
,
avatar
=
avatar
!!
,
time
=
time
,
senderName
=
sender
,
messageId
=
message
.
id
,
avatar
=
avatar
!!
,
time
=
time
,
senderName
=
sender
,
content
=
content
,
isPinned
=
message
.
pinned
,
reactions
=
getReactions
(
message
),
content
=
content
,
isPinned
=
message
.
pinned
,
reactions
=
getReactions
(
message
),
...
@@ -236,29 +220,11 @@ class ViewModelMapper @Inject constructor(private val context: Context,
...
@@ -236,29 +220,11 @@ class ViewModelMapper @Inject constructor(private val context: Context,
private
fun
getTime
(
timestamp
:
Long
)
=
DateTimeHelper
.
getTime
(
DateTimeHelper
.
getLocalDateTime
(
timestamp
))
private
fun
getTime
(
timestamp
:
Long
)
=
DateTimeHelper
.
getTime
(
DateTimeHelper
.
getLocalDateTime
(
timestamp
))
private
fun
makeQuote
(
quoteUrl
:
HttpUrl
,
serverUrl
:
HttpUrl
):
Message
?
{
private
suspend
fun
getContent
(
context
:
Context
,
message
:
Message
):
CharSequence
{
if
(
quoteUrl
.
host
()
==
serverUrl
.
host
())
{
val
msgIdToQuote
=
quoteUrl
.
queryParameter
(
"msg"
)
Timber
.
d
(
"Will quote message Id: $msgIdToQuote"
)
return
if
(
msgIdToQuote
!=
null
)
messagesRepository
.
getById
(
msgIdToQuote
)
else
null
}
return
null
}
private
suspend
fun
getContent
(
context
:
Context
,
message
:
Message
,
quote
:
Message
?):
CharSequence
{
return
when
(
message
.
isSystemMessage
())
{
return
when
(
message
.
isSystemMessage
())
{
true
->
getSystemMessage
(
message
,
context
)
true
->
getSystemMessage
(
message
,
context
)
false
->
getNormalMessage
(
message
,
quote
)
false
->
parser
.
renderMarkdown
(
message
,
currentUsername
)
}
}
private
suspend
fun
getNormalMessage
(
message
:
Message
,
quote
:
Message
?):
CharSequence
{
var
quoteViewModel
:
MessageViewModel
?
=
null
if
(
quote
!=
null
)
{
val
quoteMessage
:
Message
=
quote
quoteViewModel
=
mapMessage
(
quoteMessage
)
}
}
return
parser
.
renderMarkdown
(
message
,
quoteViewModel
,
currentUsername
)
}
}
private
fun
getSystemMessage
(
message
:
Message
,
context
:
Context
):
CharSequence
{
private
fun
getSystemMessage
(
message
:
Message
,
context
:
Context
):
CharSequence
{
...
...
app/src/main/java/chat/rocket/android/helper/MessageParser.kt
View file @
ff7ed148
...
@@ -16,7 +16,6 @@ import android.text.style.ReplacementSpan
...
@@ -16,7 +16,6 @@ import android.text.style.ReplacementSpan
import
android.util.Patterns
import
android.util.Patterns
import
android.view.View
import
android.view.View
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.viewmodel.MessageViewModel
import
chat.rocket.android.widget.emoji.EmojiParser
import
chat.rocket.android.widget.emoji.EmojiParser
import
chat.rocket.android.widget.emoji.EmojiRepository
import
chat.rocket.android.widget.emoji.EmojiRepository
import
chat.rocket.android.widget.emoji.EmojiTypefaceSpan
import
chat.rocket.android.widget.emoji.EmojiTypefaceSpan
...
@@ -40,19 +39,18 @@ class MessageParser @Inject constructor(val context: Application, private val co
...
@@ -40,19 +39,18 @@ class MessageParser @Inject constructor(val context: Application, private val co
* Render a markdown text message to Spannable.
* Render a markdown text message to Spannable.
*
*
* @param message The [Message] object we're interested on rendering.
* @param message The [Message] object we're interested on rendering.
* @param quote An optional [MessageViewModel] to be quoted.
* @param selfUsername This user username.
* @param selfUsername This user username.
*
*
* @return A Spannable with the parsed markdown.
* @return A Spannable with the parsed markdown.
*/
*/
fun
renderMarkdown
(
message
:
Message
,
quote
:
MessageViewModel
?
=
null
,
selfUsername
:
String
?
=
null
):
CharSequence
{
fun
renderMarkdown
(
message
:
Message
,
selfUsername
:
String
?
=
null
):
CharSequence
{
val
text
=
message
.
message
val
text
=
message
.
message
val
builder
=
SpannableBuilder
()
val
builder
=
SpannableBuilder
()
val
content
=
EmojiRepository
.
shortnameToUnicode
(
text
,
true
)
val
content
=
EmojiRepository
.
shortnameToUnicode
(
text
,
true
)
val
parentNode
=
parser
.
parse
(
toLenientMarkdown
(
content
))
val
parentNode
=
parser
.
parse
(
toLenientMarkdown
(
content
))
parentNode
.
accept
(
SpannableMarkdownVisitor
(
configuration
,
builder
))
parentNode
.
accept
(
SpannableMarkdownVisitor
(
configuration
,
builder
))
parentNode
.
accept
(
LinkVisitor
(
builder
))
parentNode
.
accept
(
LinkVisitor
(
builder
))
parentNode
.
accept
(
EmojiVisitor
(
builder
,
configuration
))
parentNode
.
accept
(
EmojiVisitor
(
configuration
,
builder
))
message
.
mentions
?.
let
{
message
.
mentions
?.
let
{
parentNode
.
accept
(
MentionVisitor
(
context
,
builder
,
it
,
selfUsername
))
parentNode
.
accept
(
MentionVisitor
(
context
,
builder
,
it
,
selfUsername
))
}
}
...
@@ -102,15 +100,14 @@ class MessageParser @Inject constructor(val context: Application, private val co
...
@@ -102,15 +100,14 @@ class MessageParser @Inject constructor(val context: Application, private val co
}
}
}
}
class
EmojiVisitor
(
private
val
builder
:
SpannableBuilder
,
configuration
:
SpannableConfiguration
)
class
EmojiVisitor
(
configuration
:
SpannableConfiguration
,
private
val
builder
:
SpannableBuilder
)
:
SpannableMarkdownVisitor
(
configuration
,
builder
)
{
:
SpannableMarkdownVisitor
(
configuration
,
builder
)
{
override
fun
visit
(
document
:
Document
)
{
override
fun
visit
(
document
:
Document
)
{
val
spannable
=
EmojiParser
.
parse
(
builder
.
text
())
val
spannable
=
EmojiParser
.
parse
(
builder
.
text
())
if
(
spannable
is
Spanned
)
{
if
(
spannable
is
Spanned
)
{
val
spans
=
spannable
.
getSpans
(
0
,
spannable
.
length
,
EmojiTypefaceSpan
::
class
.
java
)
val
spans
=
spannable
.
getSpans
(
0
,
spannable
.
length
,
EmojiTypefaceSpan
::
class
.
java
)
spans
.
forEach
{
spans
.
forEach
{
builder
.
setSpan
(
it
,
spannable
.
getSpanStart
(
it
),
builder
.
setSpan
(
it
,
spannable
.
getSpanStart
(
it
),
spannable
.
getSpanEnd
(
it
),
0
)
spannable
.
getSpanEnd
(
it
),
0
)
}
}
}
}
}
}
...
...
app/src/main/res/drawable/quote.xml
deleted
100644 → 0
View file @
102d920b
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"rectangle"
>
<solid
android:color=
"@color/darkGray"
/>
<size
android:width=
"4dp"
android:height=
"4dp"
/>
</shape>
\ No newline at end of file
app/src/main/res/layout/item_message_attachment.xml
View file @
ff7ed148
...
@@ -18,7 +18,7 @@
...
@@ -18,7 +18,7 @@
android:layout_height=
"0dp"
android:layout_height=
"0dp"
android:layout_marginStart=
"56dp"
android:layout_marginStart=
"56dp"
android:background=
"@drawable/quote_vertical_bar"
android:background=
"@drawable/quote_vertical_bar"
app:layout_constraintBottom_to
BottomOf=
"parent
"
app:layout_constraintBottom_to
TopOf=
"@+id/recycler_view_reactions
"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
app:layout_constraintTop_toTopOf=
"parent"
/>
...
@@ -64,14 +64,7 @@
...
@@ -64,14 +64,7 @@
layout=
"@layout/layout_reactions"
layout=
"@layout/layout_reactions"
android:layout_width=
"0dp"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:visibility=
"gone"
app:layout_constraintStart_toStartOf=
"@+id/quote_bar"
app:layout_constraintStart_toStartOf=
"@+id/text_content"
app:layout_constraintTop_toBottomOf=
"@+id/text_content"
/>
app:layout_constraintTop_toBottomOf=
"@+id/text_content"
/>
<android.support.constraint.Guideline
android:id=
"@+id/guideline"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:orientation=
"horizontal"
app:layout_constraintGuide_begin=
"20dp"
/>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
app/src/main/res/values-pt-rBR/strings.xml
View file @
ff7ed148
...
@@ -69,6 +69,9 @@
...
@@ -69,6 +69,9 @@
<string
name=
"msg_new_password"
>
Informe a nova senha
</string>
<string
name=
"msg_new_password"
>
Informe a nova senha
</string>
<string
name=
"msg_confirm_password"
>
Confirme a nova senha
</string>
<string
name=
"msg_confirm_password"
>
Confirme a nova senha
</string>
<string
name=
"msg_unread_messages"
>
Mensagens não lidas
</string>
<string
name=
"msg_unread_messages"
>
Mensagens não lidas
</string>
<string
name=
"msg_quote_video"
>
Vídeo
</string>
<string
name=
"msg_quote_audio"
>
Audio
</string>
<string
name=
"msg_quote_photo"
>
Foto
</string>
<!-- System messages -->
<!-- System messages -->
<string
name=
"message_room_name_changed"
>
Nome da sala alterado para: %1$s por %2$s
</string>
<string
name=
"message_room_name_changed"
>
Nome da sala alterado para: %1$s por %2$s
</string>
...
...
app/src/main/res/values/strings.xml
View file @
ff7ed148
...
@@ -70,6 +70,9 @@
...
@@ -70,6 +70,9 @@
<string
name=
"msg_new_password"
>
Enter New Password
</string>
<string
name=
"msg_new_password"
>
Enter New Password
</string>
<string
name=
"msg_confirm_password"
>
Confirm New Password
</string>
<string
name=
"msg_confirm_password"
>
Confirm New Password
</string>
<string
name=
"msg_unread_messages"
>
Unread messages
</string>
<string
name=
"msg_unread_messages"
>
Unread messages
</string>
<string
name=
"msg_quote_video"
>
Video
</string>
<string
name=
"msg_quote_audio"
>
Audio
</string>
<string
name=
"msg_quote_photo"
>
Photo
</string>
<!-- System messages -->
<!-- System messages -->
<string
name=
"message_room_name_changed"
>
Room name changed to: %1$s by %2$s
</string>
<string
name=
"message_room_name_changed"
>
Room name changed to: %1$s by %2$s
</string>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment