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
5163405f
Commit
5163405f
authored
May 10, 2018
by
Leonardo Aramaki
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement broadcast reply MessageReplyViewHolder and related classes
parent
a1963cc2
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
169 additions
and
15 deletions
+169
-15
ChatRoomAdapter.kt
...a/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
+20
-1
MessageReplyViewHolder.kt
...rocket/android/chatroom/adapter/MessageReplyViewHolder.kt
+29
-0
MessageReply.kt
.../java/chat/rocket/android/chatroom/domain/MessageReply.kt
+5
-0
ChatRoomPresenter.kt
...rocket/android/chatroom/presentation/ChatRoomPresenter.kt
+9
-8
BaseViewModel.kt
...a/chat/rocket/android/chatroom/viewmodel/BaseViewModel.kt
+2
-1
MessageReplyViewModel.kt
...ocket/android/chatroom/viewmodel/MessageReplyViewModel.kt
+20
-0
ViewModelMapper.kt
...chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
+29
-5
Message.kt
.../main/java/chat/rocket/android/util/extensions/Message.kt
+8
-0
message_reply_button_bg.xml
app/src/main/res/drawable/message_reply_button_bg.xml
+10
-0
item_message_reply.xml
app/src/main/res/layout/item_message_reply.xml
+37
-0
No files found.
app/src/main/java/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
View file @
5163405f
...
@@ -5,7 +5,19 @@ import android.view.MenuItem
...
@@ -5,7 +5,19 @@ import android.view.MenuItem
import
android.view.ViewGroup
import
android.view.ViewGroup
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.presentation.ChatRoomPresenter
import
chat.rocket.android.chatroom.presentation.ChatRoomPresenter
import
chat.rocket.android.chatroom.viewmodel.*
import
chat.rocket.android.chatroom.viewmodel.AudioAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.AuthorAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.BaseFileAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.BaseViewModel
import
chat.rocket.android.chatroom.viewmodel.ColorAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.GenericFileAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.ImageAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.MessageAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.MessageReplyViewModel
import
chat.rocket.android.chatroom.viewmodel.MessageViewModel
import
chat.rocket.android.chatroom.viewmodel.UrlPreviewViewModel
import
chat.rocket.android.chatroom.viewmodel.VideoAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.toViewType
import
chat.rocket.android.util.extensions.inflate
import
chat.rocket.android.util.extensions.inflate
import
chat.rocket.android.widget.emoji.EmojiReactionListener
import
chat.rocket.android.widget.emoji.EmojiReactionListener
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Message
...
@@ -65,6 +77,12 @@ class ChatRoomAdapter(
...
@@ -65,6 +77,12 @@ class ChatRoomAdapter(
val
view
=
parent
.
inflate
(
R
.
layout
.
item_file_attachment
)
val
view
=
parent
.
inflate
(
R
.
layout
.
item_file_attachment
)
GenericFileAttachmentViewHolder
(
view
,
actionsListener
,
reactionListener
)
GenericFileAttachmentViewHolder
(
view
,
actionsListener
,
reactionListener
)
}
}
BaseViewModel
.
ViewType
.
MESSAGE_REPLY
->
{
val
view
=
parent
.
inflate
(
R
.
layout
.
item_message_reply
)
MessageReplyViewHolder
(
view
,
actionsListener
,
reactionListener
)
{
permalink
->
}
}
else
->
{
else
->
{
throw
InvalidParameterException
(
"TODO - implement for ${viewType.toViewType()}"
)
throw
InvalidParameterException
(
"TODO - implement for ${viewType.toViewType()}"
)
}
}
...
@@ -107,6 +125,7 @@ class ChatRoomAdapter(
...
@@ -107,6 +125,7 @@ class ChatRoomAdapter(
is
AuthorAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
AuthorAttachmentViewModel
)
is
AuthorAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
AuthorAttachmentViewModel
)
is
ColorAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
ColorAttachmentViewModel
)
is
ColorAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
ColorAttachmentViewModel
)
is
GenericFileAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
GenericFileAttachmentViewModel
)
is
GenericFileAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
GenericFileAttachmentViewModel
)
is
MessageReplyViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
MessageReplyViewModel
)
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/MessageReplyViewHolder.kt
0 → 100644
View file @
5163405f
package
chat.rocket.android.chatroom.adapter
import
android.view.View
import
android.widget.Toast
import
chat.rocket.android.chatroom.viewmodel.MessageReplyViewModel
import
chat.rocket.android.widget.emoji.EmojiReactionListener
import
kotlinx.android.synthetic.main.item_message_reply.view.*
class
MessageReplyViewHolder
(
itemView
:
View
,
listener
:
ActionsListener
,
reactionListener
:
EmojiReactionListener
?
=
null
,
private
val
replyCallback
:
(
permalink
:
String
)
->
Unit
)
:
BaseViewHolder
<
MessageReplyViewModel
>(
itemView
,
listener
,
reactionListener
)
{
init
{
with
(
itemView
)
{
setupActionMenu
(
itemView
)
}
}
override
fun
bindViews
(
data
:
MessageReplyViewModel
)
{
with
(
itemView
)
{
button_message_reply
.
setOnClickListener
{
replyCallback
.
invoke
(
data
.
rawData
.
permalink
)
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/domain/MessageReply.kt
0 → 100644
View file @
5163405f
package
chat.rocket.android.chatroom.domain
data class
MessageReply
(
val
permalink
:
String
)
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
View file @
5163405f
...
@@ -96,16 +96,17 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -96,16 +96,17 @@ class ChatRoomPresenter @Inject constructor(
private
var
chatRoomId
:
String
?
=
null
private
var
chatRoomId
:
String
?
=
null
private
var
chatRoomType
:
String
?
=
null
private
var
chatRoomType
:
String
?
=
null
private
var
chatIsBroadcast
:
Boolean
=
false
private
val
stateChannel
=
Channel
<
State
>()
private
val
stateChannel
=
Channel
<
State
>()
private
var
lastState
=
manager
.
state
private
var
lastState
=
manager
.
state
fun
setupChatRoom
(
roomId
:
String
)
{
fun
setupChatRoom
(
roomId
:
String
)
{
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
val
canPost
=
permissions
.
canPostToReadOnlyChannels
()
val
canPost
=
permissions
.
canPostToReadOnlyChannels
()
val
broadcastChannel
=
getChatRoomsInteractor
.
getById
(
currentServer
,
roomId
)
?.
run
{
chatIsBroadcast
=
getChatRoomsInteractor
.
getById
(
currentServer
,
roomId
)
?.
run
{
broadcast
broadcast
}
?:
false
}
?:
false
view
.
onRoomUpdated
(
canPost
,
broadcastChannel
)
view
.
onRoomUpdated
(
canPost
,
chatIsBroadcast
)
}
}
}
}
...
@@ -117,7 +118,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -117,7 +118,7 @@ class ChatRoomPresenter @Inject constructor(
try
{
try
{
if
(
offset
==
0L
)
{
if
(
offset
==
0L
)
{
val
localMessages
=
messagesRepository
.
getByRoomId
(
chatRoomId
)
val
localMessages
=
messagesRepository
.
getByRoomId
(
chatRoomId
)
val
oldMessages
=
mapper
.
map
(
localMessages
)
val
oldMessages
=
mapper
.
map
(
localMessages
,
chatIsBroadcast
)
if
(
oldMessages
.
isNotEmpty
())
{
if
(
oldMessages
.
isNotEmpty
())
{
view
.
showMessages
(
oldMessages
)
view
.
showMessages
(
oldMessages
)
loadMissingMessages
()
loadMissingMessages
()
...
@@ -156,7 +157,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -156,7 +157,7 @@ class ChatRoomPresenter @Inject constructor(
client
.
messages
(
chatRoomId
,
roomTypeOf
(
chatRoomType
),
offset
,
30
).
result
client
.
messages
(
chatRoomId
,
roomTypeOf
(
chatRoomType
),
offset
,
30
).
result
}
}
messagesRepository
.
saveAll
(
messages
)
messagesRepository
.
saveAll
(
messages
)
val
allMessages
=
mapper
.
map
(
messages
)
val
allMessages
=
mapper
.
map
(
messages
,
chatIsBroadcast
)
view
.
showMessages
(
allMessages
)
view
.
showMessages
(
allMessages
)
}
}
...
@@ -192,7 +193,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -192,7 +193,7 @@ class ChatRoomPresenter @Inject constructor(
try
{
try
{
val
message
=
client
.
sendMessage
(
id
,
chatRoomId
,
text
)
val
message
=
client
.
sendMessage
(
id
,
chatRoomId
,
text
)
messagesRepository
.
save
(
newMessage
)
messagesRepository
.
save
(
newMessage
)
view
.
showNewMessage
(
mapper
.
map
(
newMessage
))
view
.
showNewMessage
(
mapper
.
map
(
newMessage
,
chatIsBroadcast
))
message
message
}
catch
(
ex
:
Exception
)
{
}
catch
(
ex
:
Exception
)
{
// Ok, not very beautiful, but the backend sends us a not valid response
// Ok, not very beautiful, but the backend sends us a not valid response
...
@@ -333,7 +334,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -333,7 +334,7 @@ class ChatRoomPresenter @Inject constructor(
Timber
.
d
(
"History: $messages"
)
Timber
.
d
(
"History: $messages"
)
if
(
messages
.
result
.
isNotEmpty
())
{
if
(
messages
.
result
.
isNotEmpty
())
{
val
models
=
mapper
.
map
(
messages
.
result
)
val
models
=
mapper
.
map
(
messages
.
result
,
chatIsBroadcast
)
messagesRepository
.
saveAll
(
messages
.
result
)
messagesRepository
.
saveAll
(
messages
.
result
)
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
...
@@ -415,7 +416,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -415,7 +416,7 @@ class ChatRoomPresenter @Inject constructor(
view
.
showReplyingAction
(
view
.
showReplyingAction
(
username
=
getDisplayName
(
msg
.
sender
),
username
=
getDisplayName
(
msg
.
sender
),
replyMarkdown
=
"[ ]($currentServer/$roomType/$room?msg=$id) $mention "
,
replyMarkdown
=
"[ ]($currentServer/$roomType/$room?msg=$id) $mention "
,
quotedMessage
=
mapper
.
map
(
message
).
last
().
preview
?.
message
?:
""
quotedMessage
=
mapper
.
map
(
message
,
chatIsBroadcast
).
last
().
preview
?.
message
?:
""
)
)
}
}
}
}
...
@@ -682,7 +683,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -682,7 +683,7 @@ class ChatRoomPresenter @Inject constructor(
private
fun
updateMessage
(
streamedMessage
:
Message
)
{
private
fun
updateMessage
(
streamedMessage
:
Message
)
{
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
val
viewModelStreamedMessage
=
mapper
.
map
(
streamedMessage
)
val
viewModelStreamedMessage
=
mapper
.
map
(
streamedMessage
,
chatIsBroadcast
)
val
roomMessages
=
messagesRepository
.
getByRoomId
(
streamedMessage
.
roomId
)
val
roomMessages
=
messagesRepository
.
getByRoomId
(
streamedMessage
.
roomId
)
val
index
=
roomMessages
.
indexOfFirst
{
msg
->
msg
.
id
==
streamedMessage
.
id
}
val
index
=
roomMessages
.
indexOfFirst
{
msg
->
msg
.
id
==
streamedMessage
.
id
}
if
(
index
>
-
1
)
{
if
(
index
>
-
1
)
{
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/BaseViewModel.kt
View file @
5163405f
...
@@ -24,7 +24,8 @@ interface BaseViewModel<out T> {
...
@@ -24,7 +24,8 @@ interface BaseViewModel<out T> {
MESSAGE_ATTACHMENT
(
6
),
MESSAGE_ATTACHMENT
(
6
),
AUTHOR_ATTACHMENT
(
7
),
AUTHOR_ATTACHMENT
(
7
),
COLOR_ATTACHMENT
(
8
),
COLOR_ATTACHMENT
(
8
),
GENERIC_FILE_ATTACHMENT
(
9
)
GENERIC_FILE_ATTACHMENT
(
9
),
MESSAGE_REPLY
(
10
)
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/MessageReplyViewModel.kt
0 → 100644
View file @
5163405f
package
chat.rocket.android.chatroom.viewmodel
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.domain.MessageReply
import
chat.rocket.core.model.Message
data class
MessageReplyViewModel
(
override
val
rawData
:
MessageReply
,
override
val
messageId
:
String
,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?,
override
var
preview
:
Message
?,
override
var
isTemporary
:
Boolean
=
false
,
override
val
message
:
Message
)
:
BaseViewModel
<
MessageReply
>
{
override
val
viewType
:
Int
get
()
=
BaseViewModel
.
ViewType
.
MESSAGE_REPLY
.
viewType
override
val
layoutId
:
Int
get
()
=
R
.
layout
.
item_message_reply
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
View file @
5163405f
...
@@ -13,6 +13,7 @@ import androidx.core.text.buildSpannedString
...
@@ -13,6 +13,7 @@ import androidx.core.text.buildSpannedString
import
androidx.core.text.color
import
androidx.core.text.color
import
androidx.core.text.scale
import
androidx.core.text.scale
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.domain.MessageReply
import
chat.rocket.android.helper.MessageParser
import
chat.rocket.android.helper.MessageParser
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.server.domain.*
import
chat.rocket.android.server.domain.*
...
@@ -47,21 +48,21 @@ class ViewModelMapper @Inject constructor(
...
@@ -47,21 +48,21 @@ class ViewModelMapper @Inject constructor(
private
val
currentUsername
:
String
?
=
localRepository
.
get
(
LocalRepository
.
CURRENT_USERNAME_KEY
)
private
val
currentUsername
:
String
?
=
localRepository
.
get
(
LocalRepository
.
CURRENT_USERNAME_KEY
)
private
val
secondaryTextColor
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
colorSecondaryText
)
private
val
secondaryTextColor
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
colorSecondaryText
)
suspend
fun
map
(
message
:
Message
):
List
<
BaseViewModel
<*
>>
{
suspend
fun
map
(
message
:
Message
,
onBroadcastChannel
:
Boolean
=
false
):
List
<
BaseViewModel
<*
>>
{
return
translate
(
message
)
return
translate
(
message
,
onBroadcastChannel
)
}
}
suspend
fun
map
(
messages
:
List
<
Message
>):
List
<
BaseViewModel
<*
>>
=
withContext
(
CommonPool
)
{
suspend
fun
map
(
messages
:
List
<
Message
>
,
onBroadcastChannel
:
Boolean
=
false
):
List
<
BaseViewModel
<*
>>
=
withContext
(
CommonPool
)
{
val
list
=
ArrayList
<
BaseViewModel
<*>>(
messages
.
size
)
val
list
=
ArrayList
<
BaseViewModel
<*>>(
messages
.
size
)
messages
.
forEach
{
messages
.
forEach
{
list
.
addAll
(
translate
(
it
))
list
.
addAll
(
translate
(
it
,
onBroadcastChannel
))
}
}
return
@withContext
list
return
@withContext
list
}
}
private
suspend
fun
translate
(
message
:
Message
):
List
<
BaseViewModel
<*
>>
=
withContext
(
CommonPool
)
{
private
suspend
fun
translate
(
message
:
Message
,
onBroadcastChannel
:
Boolean
):
List
<
BaseViewModel
<*
>>
=
withContext
(
CommonPool
)
{
val
list
=
ArrayList
<
BaseViewModel
<*>>()
val
list
=
ArrayList
<
BaseViewModel
<*>>()
message
.
urls
?.
forEach
{
message
.
urls
?.
forEach
{
...
@@ -86,9 +87,32 @@ class ViewModelMapper @Inject constructor(
...
@@ -86,9 +87,32 @@ class ViewModelMapper @Inject constructor(
list
[
i
].
nextDownStreamMessage
=
next
list
[
i
].
nextDownStreamMessage
=
next
}
}
if
(
onBroadcastChannel
)
{
val
replyViewModel
=
mapMessageReply
(
message
)
list
.
first
().
nextDownStreamMessage
=
replyViewModel
list
.
add
(
0
,
replyViewModel
)
}
return
@withContext
list
return
@withContext
list
}
}
private
fun
mapMessageReply
(
message
:
Message
):
MessageReplyViewModel
{
val
messageReply
=
MessageReply
(
permalink
=
makePermalink
(
message
))
return
MessageReplyViewModel
(
messageId
=
message
.
id
,
isTemporary
=
false
,
reactions
=
emptyList
(),
message
=
message
,
preview
=
mapMessagePreview
(
message
),
rawData
=
messageReply
,
nextDownStreamMessage
=
null
)
}
private
fun
makePermalink
(
message
:
Message
):
String
{
return
"[ ]($currentServer/direct/${message.sender?.username}?msg=${message.id}) "
}
private
fun
mapUrl
(
message
:
Message
,
url
:
Url
):
BaseViewModel
<
*
>?
{
private
fun
mapUrl
(
message
:
Message
,
url
:
Url
):
BaseViewModel
<
*
>?
{
if
(
url
.
ignoreParse
||
url
.
meta
==
null
)
return
null
if
(
url
.
ignoreParse
||
url
.
meta
==
null
)
return
null
...
...
app/src/main/java/chat/rocket/android/util/extensions/Message.kt
0 → 100644
View file @
5163405f
package
chat.rocket.android.util.extensions
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.isSystemMessage
fun
Message
.
isBroadcastReplyAvailable
(
isBroadcastChannel
:
Boolean
):
Boolean
{
return
(
isTemporary
==
false
)
&&
!
isSystemMessage
()
&&
isBroadcastChannel
}
\ No newline at end of file
app/src/main/res/drawable/message_reply_button_bg.xml
0 → 100644
View file @
5163405f
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"rectangle"
>
<solid
android:color=
"@android:color/white"
/>
<corners
android:radius=
"4dp"
/>
<stroke
android:color=
"#1D74F5"
android:width=
"2dp"
/>
</shape>
\ No newline at end of file
app/src/main/res/layout/item_message_reply.xml
0 → 100644
View file @
5163405f
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:id=
"@+id/message_container"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"?android:attr/selectableItemBackground"
android:clickable=
"true"
android:focusable=
"true"
android:paddingBottom=
"@dimen/message_item_top_and_bottom_padding"
android:paddingEnd=
"@dimen/screen_edge_left_and_right_padding"
android:paddingStart=
"@dimen/screen_edge_left_and_right_padding"
android:paddingTop=
"@dimen/message_item_top_and_bottom_padding"
>
<Button
android:id=
"@+id/button_message_reply"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginBottom=
"2dp"
android:layout_marginTop=
"5dp"
android:layout_marginStart=
"56dp"
android:background=
"@drawable/message_reply_button_bg"
android:text=
"@string/action_msg_reply"
android:textAllCaps=
"false"
android:textColor=
"#1D74F5"
android:textSize=
"14sp"
app:layout_constraintLeft_toLeftOf=
"parent"
/>
<include
layout=
"@layout/layout_reactions"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
app:layout_constraintEnd_toEndOf=
"@+id/button_message_reply"
app:layout_constraintStart_toStartOf=
"@+id/button_message_reply"
app:layout_constraintTop_toBottomOf=
"@+id/button_message_reply"
/>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
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