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
380d3688
Unverified
Commit
380d3688
authored
Apr 27, 2018
by
Rafael Kellermann Streit
Committed by
GitHub
Apr 27, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1204 from RocketChat/fix/reply-with-username
[FIX] Use username when building replies always
parents
6b2bdf3b
7eaa9971
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
110 additions
and
110 deletions
+110
-110
build.gradle
app/build.gradle
+0
-1
ChatRoomAdapter.kt
...a/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
+8
-8
ChatRoomPresenter.kt
...rocket/android/chatroom/presentation/ChatRoomPresenter.kt
+17
-24
ViewModelMapper.kt
...chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
+44
-45
AppModule.kt
.../main/java/chat/rocket/android/dagger/module/AppModule.kt
+3
-9
MessageParser.kt
...src/main/java/chat/rocket/android/helper/MessageParser.kt
+38
-22
dependencies.gradle
dependencies.gradle
+0
-1
No files found.
app/build.gradle
View file @
380d3688
...
...
@@ -104,7 +104,6 @@ dependencies {
implementation
libraries
.
frescoImageViewer
implementation
libraries
.
markwon
implementation
libraries
.
markwonImageLoader
implementation
libraries
.
sheetMenu
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
View file @
380d3688
...
...
@@ -14,11 +14,11 @@ import timber.log.Timber
import
java.security.InvalidParameterException
class
ChatRoomAdapter
(
private
val
roomType
:
String
,
private
val
roomName
:
String
,
private
val
presenter
:
ChatRoomPresenter
?,
private
val
enableActions
:
Boolean
=
true
,
private
val
reactionListener
:
EmojiReactionListener
?
=
null
private
val
roomType
:
String
,
private
val
roomName
:
String
,
private
val
presenter
:
ChatRoomPresenter
?,
private
val
enableActions
:
Boolean
=
true
,
private
val
reactionListener
:
EmojiReactionListener
?
=
null
)
:
RecyclerView
.
Adapter
<
BaseViewHolder
<*>>()
{
private
val
dataSet
=
ArrayList
<
BaseViewModel
<*>>()
...
...
@@ -175,15 +175,15 @@ class ChatRoomAdapter(
}
}
val
actionsListener
=
object
:
BaseViewHolder
.
ActionsListener
{
private
val
actionsListener
=
object
:
BaseViewHolder
.
ActionsListener
{
override
fun
isActionsEnabled
():
Boolean
=
enableActions
override
fun
onActionSelected
(
item
:
MenuItem
,
message
:
Message
)
{
message
.
apply
{
when
(
item
.
itemId
)
{
R
.
id
.
action_menu_msg_delete
->
presenter
?.
deleteMessage
(
roomId
,
id
)
R
.
id
.
action_menu_msg_quote
->
presenter
?.
citeMessage
(
roomType
,
roomName
,
id
,
false
)
R
.
id
.
action_menu_msg_reply
->
presenter
?.
citeMessage
(
roomType
,
roomName
,
id
,
true
)
R
.
id
.
action_menu_msg_quote
->
presenter
?.
citeMessage
(
roomType
,
id
,
false
)
R
.
id
.
action_menu_msg_reply
->
presenter
?.
citeMessage
(
roomType
,
id
,
true
)
R
.
id
.
action_menu_msg_copy
->
presenter
?.
copyMessage
(
id
)
R
.
id
.
action_menu_msg_edit
->
presenter
?.
editMessage
(
roomId
,
id
,
message
.
message
)
R
.
id
.
action_menu_msg_pin_unpin
->
{
...
...
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
View file @
380d3688
...
...
@@ -31,7 +31,6 @@ import chat.rocket.core.internal.rest.*
import
chat.rocket.core.model.Command
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Myself
import
chat.rocket.core.model.Value
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.experimental.async
...
...
@@ -59,10 +58,11 @@ class ChatRoomPresenter @Inject constructor(
private
val
mapper
:
ViewModelMapper
,
private
val
jobSchedulerInteractor
:
JobSchedulerInteractor
)
{
private
val
currentServer
=
serverInteractor
.
get
()
!!
private
val
manager
=
factory
.
create
(
currentServer
)
private
val
client
=
manager
.
client
private
var
settings
:
Map
<
String
,
Value
<
Any
>>
=
getSettingsInteractor
.
get
(
serverInteractor
.
get
()
!!
)
private
var
settings
:
PublicSettings
=
getSettingsInteractor
.
get
(
serverInteractor
.
get
()
!!
)
private
val
messagesChannel
=
Channel
<
Message
>()
private
var
chatRoomId
:
String
?
=
null
...
...
@@ -194,7 +194,7 @@ class ChatRoomPresenter @Inject constructor(
}
}
catch
(
ex
:
Exception
)
{
Timber
.
d
(
ex
,
"Error uploading file"
)
when
(
ex
)
{
when
(
ex
)
{
is
RocketChatException
->
view
.
showMessage
(
ex
)
else
->
view
.
showGenericErrorMessage
()
}
...
...
@@ -279,7 +279,6 @@ class ChatRoomPresenter @Inject constructor(
// TODO - we need to better treat connection problems here, but no let gaps
// on the messages list
Timber
.
d
(
ex
,
"Error fetching channel history"
)
ex
.
printStackTrace
()
}
}
}
...
...
@@ -326,43 +325,37 @@ class ChatRoomPresenter @Inject constructor(
* Quote or reply a message.
*
* @param roomType The current room type.
* @param roomName The name of the current room.
* @param messageId The id of the message to make citation for.
* @param mentionAuthor true means the citation is a reply otherwise it's a quote.
*/
fun
citeMessage
(
roomType
:
String
,
roomName
:
String
,
messageId
:
String
,
mentionAuthor
:
Boolean
)
{
fun
citeMessage
(
roomType
:
String
,
messageId
:
String
,
mentionAuthor
:
Boolean
)
{
launchUI
(
strategy
)
{
val
message
=
messagesRepository
.
getById
(
messageId
)
val
me
:
Myself
?
=
try
{
retryIO
(
"me()"
)
{
client
.
me
()
}
//TODO: Cache this and use an interactor
}
catch
(
ex
:
Exception
)
{
Timber
.
d
(
ex
,
"Error getting myself info."
)
ex
.
printStackTrace
()
Timber
.
e
(
ex
)
null
}
message
?.
let
{
m
->
val
id
=
m
.
id
val
username
=
m
.
sender
?.
username
val
user
=
"@"
+
if
(
settings
.
useRealName
())
m
.
sender
?.
name
?:
m
.
sender
?.
username
else
m
.
sender
?.
username
val
mention
=
if
(
mentionAuthor
&&
me
?.
username
!=
username
)
user
else
""
val
type
=
roomTypeOf
(
roomType
)
val
room
=
when
(
type
)
{
is
RoomType
.
Channel
->
"channel"
is
RoomType
.
DirectMessage
->
"direct"
is
RoomType
.
PrivateGroup
->
"group"
is
RoomType
.
Livechat
->
"livechat"
is
RoomType
.
Custom
->
"custom"
//TODO: put appropriate callback string here.
}
message
?.
let
{
msg
->
val
id
=
msg
.
id
val
username
=
msg
.
sender
?.
username
?:
""
val
mention
=
if
(
mentionAuthor
&&
me
?.
username
!=
username
)
"@$username"
else
""
val
room
=
if
(
roomTypeOf
(
roomType
)
is
RoomType
.
DirectMessage
)
username
else
roomType
view
.
showReplyingAction
(
username
=
user
,
replyMarkdown
=
"[ ]($currentServer/$room
/$roomName
?msg=$id) $mention "
,
username
=
getDisplayName
(
msg
.
sender
)
,
replyMarkdown
=
"[ ]($currentServer/$room
Type/$room
?msg=$id) $mention "
,
quotedMessage
=
mapper
.
map
(
message
).
last
().
preview
?.
message
?:
""
)
}
}
}
private
fun
getDisplayName
(
user
:
SimpleUser
?):
String
{
val
username
=
user
?.
username
?:
""
return
if
(
settings
.
useRealName
())
user
?.
name
?:
"@$username"
else
"@$username"
}
/**
* Copy message to clipboard.
*
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
View file @
380d3688
...
...
@@ -5,7 +5,6 @@ import android.content.Context
import
android.graphics.Color
import
android.graphics.Typeface
import
android.support.v4.content.ContextCompat
import
android.text.Html
import
android.text.SpannableStringBuilder
import
android.text.style.ForegroundColorSpan
import
android.text.style.StyleSpan
...
...
@@ -32,21 +31,21 @@ import okhttp3.HttpUrl
import
java.security.InvalidParameterException
import
javax.inject.Inject
class
ViewModelMapper
@Inject
constructor
(
private
val
context
:
Context
,
private
val
parser
:
MessageParser
,
private
val
messagesRepository
:
MessagesRepository
,
private
val
getAccountInteractor
:
GetAccountInteractor
,
tokenRepository
:
TokenRepository
,
serverInteractor
:
GetCurrentServer
Interactor
,
getSettingsInteractor
:
GetSettingsInteractor
,
localRepository
:
LocalRepository
)
{
class
ViewModelMapper
@Inject
constructor
(
private
val
context
:
Context
,
private
val
parser
:
MessageParser
,
tokenRepository
:
TokenRepository
,
serverInteractor
:
GetCurrentServerInteractor
,
getSettingsInteractor
:
GetSettings
Interactor
,
localRepository
:
LocalRepository
)
{
private
val
currentServer
=
serverInteractor
.
get
()
!!
private
val
settings
:
Map
<
String
,
Value
<
Any
>>
=
getSettingsInteractor
.
get
(
currentServer
)
private
val
baseUrl
=
settings
.
baseUrl
()
private
val
token
=
tokenRepository
.
get
(
currentServer
)
private
val
currentUsername
:
String
?
=
localRepository
.
get
(
LocalRepository
.
CURRENT_USERNAME_KEY
)
private
val
sec
u
ndaryTextColor
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
colorSecondaryText
)
private
val
sec
o
ndaryTextColor
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
colorSecondaryText
)
suspend
fun
map
(
message
:
Message
):
List
<
BaseViewModel
<*
>>
{
return
translate
(
message
)
...
...
@@ -99,10 +98,10 @@ class ViewModelMapper @Inject constructor(private val context: Context,
val
description
=
url
.
meta
?.
description
return
UrlPreviewViewModel
(
message
,
url
,
message
.
id
,
title
,
hostname
,
description
,
thumb
,
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
url
.
url
))
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
url
.
url
))
}
private
suspend
fun
mapAttachment
(
message
:
Message
,
attachment
:
Attachment
):
BaseViewModel
<
*
>?
{
private
fun
mapAttachment
(
message
:
Message
,
attachment
:
Attachment
):
BaseViewModel
<
*
>?
{
return
when
(
attachment
)
{
is
FileAttachment
->
mapFileAttachment
(
message
,
attachment
)
is
MessageAttachment
->
mapMessageAttachment
(
message
,
attachment
)
...
...
@@ -112,19 +111,19 @@ class ViewModelMapper @Inject constructor(private val context: Context,
}
}
private
suspend
fun
mapColorAttachment
(
message
:
Message
,
attachment
:
ColorAttachment
):
BaseViewModel
<
*
>?
{
private
fun
mapColorAttachment
(
message
:
Message
,
attachment
:
ColorAttachment
):
BaseViewModel
<
*
>?
{
return
with
(
attachment
)
{
val
content
=
stripMessageQuotes
(
message
)
val
id
=
attachmentId
(
message
,
attachment
)
ColorAttachmentViewModel
(
attachmentUrl
=
url
,
id
=
id
,
color
=
color
.
color
,
text
=
text
,
message
=
message
,
rawData
=
attachment
,
messageId
=
message
.
id
,
reactions
=
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
content
.
message
))
text
=
text
,
message
=
message
,
rawData
=
attachment
,
messageId
=
message
.
id
,
reactions
=
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
content
.
message
))
}
}
private
suspend
fun
mapAuthorAttachment
(
message
:
Message
,
attachment
:
AuthorAttachment
):
AuthorAttachmentViewModel
{
private
fun
mapAuthorAttachment
(
message
:
Message
,
attachment
:
AuthorAttachment
):
AuthorAttachmentViewModel
{
return
with
(
attachment
)
{
val
content
=
stripMessageQuotes
(
message
)
...
...
@@ -146,13 +145,13 @@ class ViewModelMapper @Inject constructor(private val context: Context,
val
id
=
attachmentId
(
message
,
attachment
)
AuthorAttachmentViewModel
(
attachmentUrl
=
url
,
id
=
id
,
name
=
authorName
,
icon
=
authorIcon
,
fields
=
fieldsText
,
message
=
message
,
rawData
=
attachment
,
messageId
=
message
.
id
,
reactions
=
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
content
.
message
))
icon
=
authorIcon
,
fields
=
fieldsText
,
message
=
message
,
rawData
=
attachment
,
messageId
=
message
.
id
,
reactions
=
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
content
.
message
))
}
}
private
suspend
fun
mapMessageAttachment
(
message
:
Message
,
attachment
:
MessageAttachment
):
MessageAttachmentViewModel
{
private
fun
mapMessageAttachment
(
message
:
Message
,
attachment
:
MessageAttachment
):
MessageAttachmentViewModel
{
val
attachmentAuthor
=
attachment
.
author
val
time
=
attachment
.
timestamp
?.
let
{
getTime
(
it
)
}
val
attachmentText
=
when
(
attachment
.
attachments
.
orEmpty
().
firstOrNull
())
{
...
...
@@ -163,9 +162,9 @@ class ViewModelMapper @Inject constructor(private val context: Context,
}
val
content
=
stripMessageQuotes
(
message
)
return
MessageAttachmentViewModel
(
message
=
content
,
rawData
=
message
,
messageId
=
message
.
id
,
time
=
time
,
senderName
=
attachmentAuthor
,
content
=
attachmentText
,
isPinned
=
message
.
pinned
,
reactions
=
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
content
.
message
))
messageId
=
message
.
id
,
time
=
time
,
senderName
=
attachmentAuthor
,
content
=
attachmentText
,
isPinned
=
message
.
pinned
,
reactions
=
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
content
.
message
))
}
private
fun
mapFileAttachment
(
message
:
Message
,
attachment
:
FileAttachment
):
BaseViewModel
<
*
>?
{
...
...
@@ -174,14 +173,14 @@ class ViewModelMapper @Inject constructor(private val context: Context,
val
id
=
attachmentId
(
message
,
attachment
)
return
when
(
attachment
)
{
is
ImageAttachment
->
ImageAttachmentViewModel
(
message
,
attachment
,
message
.
id
,
attachmentUrl
,
attachmentTitle
,
id
,
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
context
.
getString
(
R
.
string
.
msg_preview_photo
)))
attachmentUrl
,
attachmentTitle
,
id
,
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
context
.
getString
(
R
.
string
.
msg_preview_photo
)))
is
VideoAttachment
->
VideoAttachmentViewModel
(
message
,
attachment
,
message
.
id
,
attachmentUrl
,
attachmentTitle
,
id
,
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
context
.
getString
(
R
.
string
.
msg_preview_video
)))
attachmentUrl
,
attachmentTitle
,
id
,
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
context
.
getString
(
R
.
string
.
msg_preview_video
)))
is
AudioAttachment
->
AudioAttachmentViewModel
(
message
,
attachment
,
message
.
id
,
attachmentUrl
,
attachmentTitle
,
id
,
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
context
.
getString
(
R
.
string
.
msg_preview_audio
)))
attachmentUrl
,
attachmentTitle
,
id
,
getReactions
(
message
),
preview
=
message
.
copy
(
message
=
context
.
getString
(
R
.
string
.
msg_preview_audio
)))
else
->
null
}
}
...
...
@@ -230,12 +229,12 @@ class ViewModelMapper @Inject constructor(private val context: Context,
val
content
=
getContent
(
stripMessageQuotes
(
message
))
MessageViewModel
(
message
=
stripMessageQuotes
(
message
),
rawData
=
message
,
messageId
=
message
.
id
,
avatar
=
avatar
!!
,
time
=
time
,
senderName
=
sender
,
content
=
content
,
isPinned
=
message
.
pinned
,
reactions
=
getReactions
(
message
),
isFirstUnread
=
false
,
preview
=
preview
,
isTemporary
=
isTemp
)
messageId
=
message
.
id
,
avatar
=
avatar
!!
,
time
=
time
,
senderName
=
sender
,
content
=
content
,
isPinned
=
message
.
pinned
,
reactions
=
getReactions
(
message
),
isFirstUnread
=
false
,
preview
=
preview
,
isTemporary
=
isTemp
)
}
private
suspend
fun
mapMessagePreview
(
message
:
Message
):
Message
{
private
fun
mapMessagePreview
(
message
:
Message
):
Message
{
return
when
(
message
.
isSystemMessage
())
{
false
->
stripMessageQuotes
(
message
)
true
->
message
.
copy
(
message
=
getSystemMessage
(
message
).
toString
())
...
...
@@ -249,11 +248,11 @@ class ViewModelMapper @Inject constructor(private val context: Context,
val
usernames
=
it
.
getUsernames
(
shortname
)
?:
emptyList
()
val
count
=
usernames
.
size
list
.
add
(
ReactionViewModel
(
messageId
=
message
.
id
,
shortname
=
shortname
,
unicode
=
EmojiParser
.
parse
(
shortname
),
count
=
count
,
usernames
=
usernames
)
ReactionViewModel
(
messageId
=
message
.
id
,
shortname
=
shortname
,
unicode
=
EmojiParser
.
parse
(
shortname
),
count
=
count
,
usernames
=
usernames
)
)
}
list
...
...
@@ -261,10 +260,10 @@ class ViewModelMapper @Inject constructor(private val context: Context,
return
reactions
?:
emptyList
()
}
private
suspend
fun
stripMessageQuotes
(
message
:
Message
):
Message
{
private
fun
stripMessageQuotes
(
message
:
Message
):
Message
{
val
baseUrl
=
settings
.
baseUrl
()
return
message
.
copy
(
message
=
message
.
message
.
replace
(
"\\[[^\\]]+\\]\\($baseUrl[^)]+\\)"
.
toRegex
(),
""
).
trim
()
message
=
message
.
message
.
replace
(
"\\[[^\\]]+\\]\\($baseUrl[^)]+\\)"
.
toRegex
(),
""
).
trim
()
)
}
...
...
@@ -276,7 +275,7 @@ class ViewModelMapper @Inject constructor(private val context: Context,
username
?.
let
{
append
(
" "
)
scale
(
0.8f
)
{
color
(
sec
u
ndaryTextColor
)
{
color
(
sec
o
ndaryTextColor
)
{
append
(
"@$username"
)
}
}
...
...
@@ -302,7 +301,7 @@ class ViewModelMapper @Inject constructor(private val context: Context,
private
fun
getTime
(
timestamp
:
Long
)
=
DateTimeHelper
.
getTime
(
DateTimeHelper
.
getLocalDateTime
(
timestamp
))
private
suspend
fun
getContent
(
message
:
Message
):
CharSequence
{
private
fun
getContent
(
message
:
Message
):
CharSequence
{
return
when
(
message
.
isSystemMessage
())
{
true
->
getSystemMessage
(
message
)
false
->
parser
.
renderMarkdown
(
message
,
currentUsername
)
...
...
@@ -325,9 +324,9 @@ class ViewModelMapper @Inject constructor(private val context: Context,
}
val
spannableMsg
=
SpannableStringBuilder
(
content
)
spannableMsg
.
setSpan
(
StyleSpan
(
Typeface
.
ITALIC
),
0
,
spannableMsg
.
length
,
0
)
0
)
spannableMsg
.
setSpan
(
ForegroundColorSpan
(
Color
.
GRAY
),
0
,
spannableMsg
.
length
,
0
)
0
)
return
spannableMsg
}
...
...
app/src/main/java/chat/rocket/android/dagger/module/AppModule.kt
View file @
380d3688
...
...
@@ -48,10 +48,8 @@ import okhttp3.Interceptor
import
okhttp3.OkHttpClient
import
okhttp3.logging.HttpLoggingInterceptor
import
ru.noties.markwon.SpannableConfiguration
import
ru.noties.markwon.il.AsyncDrawableLoader
import
ru.noties.markwon.spans.SpannableTheme
import
timber.log.Timber
import
java.util.concurrent.Executors
import
java.util.concurrent.TimeUnit
import
javax.inject.Singleton
...
...
@@ -264,11 +262,6 @@ class AppModule {
fun
provideConfiguration
(
context
:
Application
,
client
:
OkHttpClient
):
SpannableConfiguration
{
val
res
=
context
.
resources
return
SpannableConfiguration
.
builder
(
context
)
.
asyncDrawableLoader
(
AsyncDrawableLoader
.
builder
()
.
client
(
client
)
.
executorService
(
Executors
.
newCachedThreadPool
())
.
resources
(
res
)
.
build
())
.
theme
(
SpannableTheme
.
builder
()
.
linkColor
(
res
.
getColor
(
R
.
color
.
colorAccent
))
.
build
())
...
...
@@ -277,8 +270,9 @@ class AppModule {
@Provides
@Singleton
fun
provideMessageParser
(
context
:
Application
,
configuration
:
SpannableConfiguration
):
MessageParser
{
return
MessageParser
(
context
,
configuration
)
fun
provideMessageParser
(
context
:
Application
,
configuration
:
SpannableConfiguration
,
serverInteractor
:
GetCurrentServerInteractor
,
settingsInteractor
:
GetSettingsInteractor
):
MessageParser
{
val
url
=
serverInteractor
.
get
()
!!
return
MessageParser
(
context
,
configuration
,
settingsInteractor
.
get
(
url
))
}
@Provides
...
...
app/src/main/java/chat/rocket/android/helper/MessageParser.kt
View file @
380d3688
package
chat.rocket.android.helper
import
android.app.Application
import
android.content.ActivityNotFoundException
import
android.content.Context
import
android.content.Intent
import
android.graphics.Canvas
import
android.graphics.Paint
import
android.graphics.RectF
import
android.net.Uri
import
android.support.customtabs.CustomTabsIntent
import
android.provider.Browser
import
android.support.v4.content.res.ResourcesCompat
import
android.text.Spanned
import
android.text.style.ClickableSpan
...
...
@@ -17,6 +14,8 @@ import android.text.style.ReplacementSpan
import
android.util.Patterns
import
android.view.View
import
chat.rocket.android.R
import
chat.rocket.android.server.domain.PublicSettings
import
chat.rocket.android.server.domain.useRealName
import
chat.rocket.android.widget.emoji.EmojiParser
import
chat.rocket.android.widget.emoji.EmojiRepository
import
chat.rocket.android.widget.emoji.EmojiTypefaceSpan
...
...
@@ -29,10 +28,13 @@ import ru.noties.markwon.Markwon
import
ru.noties.markwon.SpannableBuilder
import
ru.noties.markwon.SpannableConfiguration
import
ru.noties.markwon.renderer.SpannableMarkdownVisitor
import
timber.log.Timber
import
javax.inject.Inject
class
MessageParser
@Inject
constructor
(
val
context
:
Application
,
private
val
configuration
:
SpannableConfiguration
)
{
class
MessageParser
@Inject
constructor
(
private
val
context
:
Application
,
private
val
configuration
:
SpannableConfiguration
,
private
val
settings
:
PublicSettings
)
{
private
val
parser
=
Markwon
.
createParser
()
...
...
@@ -53,7 +55,7 @@ class MessageParser @Inject constructor(val context: Application, private val co
parentNode
.
accept
(
LinkVisitor
(
builder
))
parentNode
.
accept
(
EmojiVisitor
(
configuration
,
builder
))
message
.
mentions
?.
let
{
parentNode
.
accept
(
MentionVisitor
(
context
,
builder
,
it
,
selfUsername
))
parentNode
.
accept
(
MentionVisitor
(
context
,
builder
,
it
,
selfUsername
,
settings
))
}
return
builder
.
text
()
...
...
@@ -62,23 +64,31 @@ class MessageParser @Inject constructor(val context: Application, private val co
// Convert to a lenient markdown consistent with Rocket.Chat web markdown instead of the official specs.
private
fun
toLenientMarkdown
(
text
:
String
):
String
{
return
text
.
trim
().
replace
(
"\\*(.+)\\*"
.
toRegex
())
{
"**${it.groupValues[1].trim()}**"
}
.
replace
(
"\\~(.+)\\~"
.
toRegex
())
{
"~~${it.groupValues[1].trim()}~~"
}
.
replace
(
"\\_(.+)\\_"
.
toRegex
())
{
"_${it.groupValues[1].trim()}_"
}
.
replace
(
"\\~(.+)\\~"
.
toRegex
())
{
"~~${it.groupValues[1].trim()}~~"
}
.
replace
(
"\\_(.+)\\_"
.
toRegex
())
{
"_${it.groupValues[1].trim()}_"
}
}
class
MentionVisitor
(
context
:
Context
,
private
val
builder
:
SpannableBuilder
,
private
val
mentions
:
List
<
SimpleUser
>,
private
val
currentUser
:
String
?)
:
AbstractVisitor
()
{
class
MentionVisitor
(
context
:
Context
,
private
val
builder
:
SpannableBuilder
,
private
val
mentions
:
List
<
SimpleUser
>,
private
val
currentUser
:
String
?,
private
val
settings
:
PublicSettings
)
:
AbstractVisitor
()
{
private
val
othersTextColor
=
ResourcesCompat
.
getColor
(
context
.
resources
,
R
.
color
.
colorAccent
,
context
.
theme
)
private
val
othersBackgroundColor
=
ResourcesCompat
.
getColor
(
context
.
resources
,
android
.
R
.
color
.
transparent
,
context
.
theme
)
private
val
myselfTextColor
=
ResourcesCompat
.
getColor
(
context
.
resources
,
R
.
color
.
white
,
context
.
theme
)
private
val
myselfBackgroundColor
=
ResourcesCompat
.
getColor
(
context
.
resources
,
R
.
color
.
colorAccent
,
context
.
theme
)
private
val
mentionPadding
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
padding_mention
).
toFloat
()
private
val
mentionRadius
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
radius_mention
).
toFloat
()
override
fun
visit
(
t
:
Text
)
{
val
text
=
t
.
literal
val
mentionsList
=
mentions
.
map
{
it
.
username
}.
toMutableList
()
val
mentionsList
=
mentions
.
map
{
if
(
settings
.
useRealName
())
it
.
name
else
it
.
username
?:
""
}.
toMutableList
()
mentionsList
.
add
(
"all"
)
mentionsList
.
add
(
"here"
)
...
...
@@ -90,7 +100,7 @@ class MessageParser @Inject constructor(val context: Application, private val co
val
textColor
=
if
(
mentionMe
)
myselfTextColor
else
othersTextColor
val
backgroundColor
=
if
(
mentionMe
)
myselfBackgroundColor
else
othersBackgroundColor
val
usernameSpan
=
MentionSpan
(
backgroundColor
,
textColor
,
mentionRadius
,
mentionPadding
,
mentionMe
)
mentionMe
)
// Add 1 to end offset to include the @.
val
end
=
offset
+
it
.
length
+
1
builder
.
setSpan
(
usernameSpan
,
offset
,
end
,
0
)
...
...
@@ -101,8 +111,11 @@ class MessageParser @Inject constructor(val context: Application, private val co
}
}
class
EmojiVisitor
(
configuration
:
SpannableConfiguration
,
private
val
builder
:
SpannableBuilder
)
:
SpannableMarkdownVisitor
(
configuration
,
builder
)
{
class
EmojiVisitor
(
configuration
:
SpannableConfiguration
,
private
val
builder
:
SpannableBuilder
)
:
SpannableMarkdownVisitor
(
configuration
,
builder
)
{
override
fun
visit
(
document
:
Document
)
{
val
spannable
=
EmojiParser
.
parse
(
builder
.
text
())
if
(
spannable
is
Spanned
)
{
...
...
@@ -127,7 +140,7 @@ class MessageParser @Inject constructor(val context: Application, private val co
if
(!
link
.
startsWith
(
"@"
)
&&
link
!
in
consumed
)
{
builder
.
setSpan
(
object
:
ClickableSpan
()
{
override
fun
onClick
(
view
:
View
)
{
with
(
view
)
{
with
(
view
)
{
val
tabsbuilder
=
CustomTabsIntent
.
Builder
()
tabsbuilder
.
setToolbarColor
(
ResourcesCompat
.
getColor
(
context
.
resources
,
R
.
color
.
colorPrimary
,
context
.
theme
))
val
customTabsIntent
=
tabsbuilder
.
build
()
...
...
@@ -150,11 +163,14 @@ class MessageParser @Inject constructor(val context: Application, private val co
}
}
class
MentionSpan
(
private
val
backgroundColor
:
Int
,
private
val
textColor
:
Int
,
private
val
radius
:
Float
,
padding
:
Float
,
referSelf
:
Boolean
)
:
ReplacementSpan
()
{
class
MentionSpan
(
private
val
backgroundColor
:
Int
,
private
val
textColor
:
Int
,
private
val
radius
:
Float
,
padding
:
Float
,
referSelf
:
Boolean
)
:
ReplacementSpan
()
{
private
val
padding
:
Float
=
if
(
referSelf
)
padding
else
0F
override
fun
getSize
(
paint
:
Paint
,
...
...
dependencies.gradle
View file @
380d3688
...
...
@@ -91,7 +91,6 @@ ext {
frescoImageViewer
:
"com.github.luciofm:FrescoImageViewer:${versions.frescoImageViewer}"
,
markwon
:
"ru.noties:markwon:${versions.markwon}"
,
markwonImageLoader
:
"ru.noties:markwon-image-loader:${versions.markwon}"
,
sheetMenu
:
"com.github.whalemare:sheetmenu:${versions.sheetMenu}"
,
...
...
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