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
95e001cc
Commit
95e001cc
authored
Oct 06, 2017
by
Rafael Kellermann Streit
Committed by
GitHub
Oct 06, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #512 from RocketChat/feature/message-actions
[NEW] Add Reply feature
parents
12247fd5
fe3ac9e8
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
648 additions
and
118 deletions
+648
-118
RocketChatCache.java
app/src/main/java/chat/rocket/android/RocketChatCache.java
+4
-1
AbstractAuthedActivity.java
.../chat/rocket/android/activity/AbstractAuthedActivity.java
+1
-12
MainActivity.java
.../main/java/chat/rocket/android/activity/MainActivity.java
+2
-1
DDPClientWrapper.java
...c/main/java/chat/rocket/android/api/DDPClientWrapper.java
+1
-1
RocketChatAbsoluteUrl.java
...cket/android/fragment/chatroom/RocketChatAbsoluteUrl.java
+4
-0
RoomContract.java
...a/chat/rocket/android/fragment/chatroom/RoomContract.java
+13
-1
RoomFragment.java
...a/chat/rocket/android/fragment/chatroom/RoomFragment.java
+34
-18
RoomPresenter.java
.../chat/rocket/android/fragment/chatroom/RoomPresenter.java
+51
-6
LoginFragment.java
.../rocket/android/fragment/server_config/LoginFragment.java
+1
-1
UserRegistrationDialogFragment.java
...ragment/server_config/UserRegistrationDialogFragment.java
+2
-2
SidebarMainFragment.java
.../rocket/android/fragment/sidebar/SidebarMainFragment.java
+1
-1
MessageFormManager.kt
...ocket/android/layouthelper/chatroom/MessageFormManager.kt
+16
-1
MessagePopup.java
...at/rocket/android/layouthelper/chatroom/MessagePopup.java
+238
-0
PushNotificationHandler.java
...ava/chat/rocket/android/push/PushNotificationHandler.java
+5
-5
RocketChatWebSocketThread.java
...hat/rocket/android/service/RocketChatWebSocketThread.java
+4
-4
AbstractRocketChatCacheObserver.java
...oid/service/internal/AbstractRocketChatCacheObserver.java
+5
-5
MarkDown.java
...main/java/chat/rocket/android/widget/helper/MarkDown.java
+1
-1
MessageFormLayout.java
...chat/rocket/android/widget/message/MessageFormLayout.java
+94
-4
ic_close.xml
...t-chat-android-widgets/src/main/res/drawable/ic_close.xml
+8
-0
ic_reply.xml
...t-chat-android-widgets/src/main/res/drawable/ic_reply.xml
+8
-0
message_composer.xml
...-android-widgets/src/main/res/layout/message_composer.xml
+155
-54
No files found.
app/src/main/java/chat/rocket/android/RocketChatCache.java
View file @
95e001cc
...
...
@@ -172,7 +172,10 @@ public class RocketChatCache {
}
public
Flowable
<
Optional
<
String
>>
getSelectedRoomIdPublisher
()
{
return
getValuePublisher
(
KEY_SELECTED_ROOM_ID
);
return
getValuePublisher
(
KEY_SELECTED_ROOM_ID
)
.
filter
(
Optional:
:
isPresent
)
.
map
(
Optional:
:
get
)
.
map
(
roomValue
->
Optional
.
ofNullable
(
new
JSONObject
(
roomValue
).
optString
(
getSelectedServerHostname
(),
null
)));
}
private
SharedPreferences
getSharedPreferences
()
{
...
...
app/src/main/java/chat/rocket/android/activity/AbstractAuthedActivity.java
View file @
95e001cc
...
...
@@ -6,9 +6,6 @@ import android.support.annotation.Nullable;
import
com.hadisatrio.optional.Optional
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
import
java.util.List
;
import
chat.rocket.android.LaunchUtil
;
...
...
@@ -198,9 +195,8 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
compositeDisposable
.
add
(
rocketChatCache
.
getSelectedRoomIdPublisher
()
.
filter
(
Optional:
:
isPresent
)
.
map
(
Optional:
:
get
)
.
map
(
this
::
convertStringToJsonObject
)
.
map
(
jsonObject
->
jsonObject
.
optString
(
rocketChatCache
.
getSelectedServerHostname
(),
null
))
.
subscribeOn
(
Schedulers
.
io
())
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
subscribe
(
...
...
@@ -209,11 +205,4 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
)
);
}
private
JSONObject
convertStringToJsonObject
(
String
json
)
throws
JSONException
{
if
(
json
==
null
)
{
return
new
JSONObject
();
}
return
new
JSONObject
(
json
);
}
}
app/src/main/java/chat/rocket/android/activity/MainActivity.java
View file @
95e001cc
...
...
@@ -48,7 +48,8 @@ public class MainActivity extends AbstractAuthedActivity implements MainContract
private
SlidingPaneLayout
pane
;
private
MainContract
.
Presenter
presenter
;
protected
int
getLayoutContainerForFragment
()
{
@Override
public
int
getLayoutContainerForFragment
()
{
return
R
.
id
.
activity_main_container
;
}
...
...
app/src/main/java/chat/rocket/android/api/DDPClientWrapper.java
View file @
95e001cc
...
...
@@ -30,7 +30,7 @@ public class DDPClientWrapper {
}
/**
*
create
new API client instance.
*
build
new API client instance.
*/
public
static
DDPClientWrapper
create
(
String
hostname
)
{
return
new
DDPClientWrapper
(
hostname
);
...
...
app/src/main/java/chat/rocket/android/fragment/chatroom/RocketChatAbsoluteUrl.java
View file @
95e001cc
...
...
@@ -29,4 +29,8 @@ public class RocketChatAbsoluteUrl implements AbsoluteUrl {
public
String
getToken
()
{
return
token
;
}
public
String
getBaseUrl
()
{
return
baseUrl
;
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/fragment/chatroom/RoomContract.java
View file @
95e001cc
...
...
@@ -2,11 +2,13 @@ package chat.rocket.android.fragment.chatroom;
import
android.support.annotation.Nullable
;
import
chat.rocket.core.models.User
;
import
java.util.List
;
import
chat.rocket.android.shared.BaseContract
;
import
chat.rocket.android.widget.AbsoluteUrl
;
import
chat.rocket.core.models.Message
;
import
chat.rocket.core.models.Room
;
import
chat.rocket.core.models.User
;
public
interface
RoomContract
{
...
...
@@ -35,6 +37,12 @@ public interface RoomContract {
void
autoloadImages
();
void
manualLoadImages
();
void
onReply
(
AbsoluteUrl
absoluteUrl
,
String
markdown
,
Message
message
);
void
onCopy
(
String
message
);
void
showMessageActions
(
Message
message
);
}
interface
Presenter
extends
BaseContract
.
Presenter
<
View
>
{
...
...
@@ -58,5 +66,9 @@ public interface RoomContract {
void
onMarkAsRead
();
void
refreshRoom
();
void
replyMessage
(
Message
message
);
void
copyMessage
(
Message
message
);
}
}
app/src/main/java/chat/rocket/android/fragment/chatroom/RoomFragment.java
View file @
95e001cc
...
...
@@ -2,6 +2,9 @@ package chat.rocket.android.fragment.chatroom;
import
android.Manifest
;
import
android.app.Activity
;
import
android.content.ClipData
;
import
android.content.ClipboardManager
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.net.Uri
;
import
android.os.Bundle
;
...
...
@@ -26,10 +29,11 @@ import java.util.List;
import
chat.rocket.android.BackgroundLooper
;
import
chat.rocket.android.R
;
import
chat.rocket.android.RocketChatApplication
;
import
chat.rocket.android.activity.MainActivity
;
import
chat.rocket.android.activity.room.RoomActivity
;
import
chat.rocket.android.api.MethodCallHelper
;
import
chat.rocket.android.fragment.chatroom.dialog.FileUploadProgressDialogFragment
;
import
chat.rocket.android.fragment.chatroom.dialog.MessageOptionsDialogFragment
;
import
chat.rocket.android.fragment.sidebar.SidebarMainFragment
;
import
chat.rocket.android.helper.AbsoluteUrlHelper
;
import
chat.rocket.android.helper.FileUploadHelper
;
...
...
@@ -42,6 +46,7 @@ import chat.rocket.android.helper.TextUtils;
import
chat.rocket.android.layouthelper.chatroom.AbstractNewMessageIndicatorManager
;
import
chat.rocket.android.layouthelper.chatroom.MessageFormManager
;
import
chat.rocket.android.layouthelper.chatroom.MessageListAdapter
;
import
chat.rocket.android.layouthelper.chatroom.MessagePopup
;
import
chat.rocket.android.layouthelper.chatroom.ModelListAdapter
;
import
chat.rocket.android.layouthelper.chatroom.PairedMessage
;
import
chat.rocket.android.layouthelper.extra_action.AbstractExtraActionItem
;
...
...
@@ -55,6 +60,7 @@ import chat.rocket.android.renderer.RocketChatUserStatusProvider;
import
chat.rocket.android.service.ConnectivityManager
;
import
chat.rocket.android.service.temp.DeafultTempSpotlightRoomCaller
;
import
chat.rocket.android.service.temp.DefaultTempSpotlightUserCaller
;
import
chat.rocket.android.widget.AbsoluteUrl
;
import
chat.rocket.android.widget.RoomToolbar
;
import
chat.rocket.android.widget.internal.ExtraActionPickerDialogFragment
;
import
chat.rocket.android.widget.message.MessageFormLayout
;
...
...
@@ -90,7 +96,6 @@ import permissions.dispatcher.RuntimePermissions;
public
class
RoomFragment
extends
AbstractChatRoomFragment
implements
OnBackPressListener
,
ExtraActionPickerDialogFragment
.
Callback
,
ModelListAdapter
.
OnItemClickListener
<
PairedMessage
>,
ModelListAdapter
.
OnItemLongClickListener
<
PairedMessage
>,
RoomContract
.
View
{
...
...
@@ -135,7 +140,7 @@ public class RoomFragment extends AbstractChatRoomFragment implements
}
/**
*
create
fragment with roomId.
*
build
fragment with roomId.
*/
public
static
RoomFragment
create
(
String
hostname
,
String
roomId
)
{
Bundle
args
=
new
Bundle
();
...
...
@@ -202,7 +207,6 @@ public class RoomFragment extends AbstractChatRoomFragment implements
messageListAdapter
=
new
MessageListAdapter
(
getContext
(),
hostname
);
messageRecyclerView
.
setAdapter
(
messageListAdapter
);
messageListAdapter
.
setOnItemClickListener
(
this
);
messageListAdapter
.
setOnItemLongClickListener
(
this
);
LinearLayoutManager
linearLayoutManager
=
new
LinearLayoutManager
(
getContext
(),
LinearLayoutManager
.
VERTICAL
,
true
);
...
...
@@ -287,22 +291,9 @@ public class RoomFragment extends AbstractChatRoomFragment implements
super
.
onDestroyView
();
}
@Override
public
void
onItemClick
(
PairedMessage
pairedMessage
)
{
presenter
.
onMessageSelected
(
pairedMessage
.
target
);
}
@Override
public
boolean
onItemLongClick
(
PairedMessage
pairedMessage
)
{
MessageOptionsDialogFragment
messageOptionsDialogFragment
=
MessageOptionsDialogFragment
.
create
(
pairedMessage
.
target
);
messageOptionsDialogFragment
.
setOnMessageOptionSelectedListener
(
message
->
{
messageOptionsDialogFragment
.
dismiss
();
onEditMessage
(
message
);
});
messageOptionsDialogFragment
.
show
(
getChildFragmentManager
(),
"MessageOptionsDialogFragment"
);
presenter
.
onMessageSelected
(
pairedMessage
.
target
);
return
true
;
}
...
...
@@ -659,6 +650,31 @@ public class RoomFragment extends AbstractChatRoomFragment implements
messageListAdapter
.
setAutoloadImages
(
false
);
}
@Override
public
void
onReply
(
AbsoluteUrl
absoluteUrl
,
String
markdown
,
Message
message
)
{
messageFormManager
.
setReply
(
absoluteUrl
,
markdown
,
message
);
}
@Override
public
void
onCopy
(
String
message
)
{
RocketChatApplication
context
=
RocketChatApplication
.
getInstance
();
ClipboardManager
clipboardManager
=
(
ClipboardManager
)
context
.
getSystemService
(
Context
.
CLIPBOARD_SERVICE
);
clipboardManager
.
setPrimaryClip
(
ClipData
.
newPlainText
(
"message"
,
message
));
}
@Override
public
void
showMessageActions
(
Message
message
)
{
Activity
context
=
getActivity
();
if
(
context
!=
null
&&
context
instanceof
MainActivity
)
{
MessagePopup
.
take
(
message
)
.
setReplyAction
(
presenter:
:
replyMessage
)
.
setEditAction
(
this
::
onEditMessage
)
.
setCopyAction
(
msg
->
onCopy
(
message
.
getMessage
()))
.
showWith
(
context
);
}
}
private
void
onEditMessage
(
Message
message
)
{
edittingMessage
=
message
;
messageFormManager
.
setEditMessage
(
message
.
getMessage
());
...
...
app/src/main/java/chat/rocket/android/fragment/chatroom/RoomPresenter.java
View file @
95e001cc
...
...
@@ -6,15 +6,12 @@ import android.support.v4.util.Pair;
import
com.hadisatrio.optional.Optional
;
import
io.reactivex.Single
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.Disposable
;
import
chat.rocket.android.BackgroundLooper
;
import
chat.rocket.android.api.MethodCallHelper
;
import
chat.rocket.android.helper.AbsoluteUrlHelper
;
import
chat.rocket.android.helper.LogIfError
;
import
chat.rocket.android.helper.Logger
;
import
chat.rocket.android.service.ConnectivityManagerApi
;
import
chat.rocket.android.shared.BasePresenter
;
import
chat.rocket.core.SyncState
;
import
chat.rocket.core.interactors.MessageInteractor
;
...
...
@@ -24,7 +21,9 @@ import chat.rocket.core.models.Settings;
import
chat.rocket.core.models.User
;
import
chat.rocket.core.repositories.RoomRepository
;
import
chat.rocket.core.repositories.UserRepository
;
import
chat.rocket.android.service.ConnectivityManagerApi
;
import
io.reactivex.Single
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.Disposable
;
public
class
RoomPresenter
extends
BasePresenter
<
RoomContract
.
View
>
implements
RoomContract
.
Presenter
{
...
...
@@ -36,8 +35,9 @@ public class RoomPresenter extends BasePresenter<RoomContract.View>
private
final
AbsoluteUrlHelper
absoluteUrlHelper
;
private
final
MethodCallHelper
methodCallHelper
;
private
final
ConnectivityManagerApi
connectivityManagerApi
;
private
Room
currentRoom
;
public
RoomPresenter
(
String
roomId
,
public
RoomPresenter
(
String
roomId
,
UserRepository
userRepository
,
MessageInteractor
messageInteractor
,
RoomRepository
roomRepository
,
...
...
@@ -115,6 +115,50 @@ public class RoomPresenter extends BasePresenter<RoomContract.View>
if
(
message
.
getSyncState
()
==
SyncState
.
FAILED
)
{
view
.
showMessageSendFailure
(
message
);
}
if
(
message
.
getType
()
==
null
)
{
// If message is not a system message show applicable actions.
view
.
showMessageActions
(
message
);
}
}
@Override
public
void
replyMessage
(
Message
message
)
{
this
.
absoluteUrlHelper
.
getRocketChatAbsoluteUrl
()
.
cache
()
.
subscribeOn
(
AndroidSchedulers
.
from
(
BackgroundLooper
.
get
()))
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
subscribe
(
serverUrl
->
{
if
(
serverUrl
.
isPresent
())
{
String
baseUrl
=
serverUrl
.
get
().
getBaseUrl
();
view
.
onReply
(
serverUrl
.
get
(),
buildReplyMarkDown
(
baseUrl
,
message
),
message
);
}
},
Logger:
:
report
);
}
@Override
public
void
copyMessage
(
Message
message
)
{
view
.
onCopy
(
message
.
getMessage
());
}
private
String
buildReplyMarkDown
(
String
baseUrl
,
Message
message
)
{
if
(
currentRoom
==
null
||
message
.
getUser
()
==
null
)
{
return
""
;
}
if
(
currentRoom
.
isDirectMessage
())
{
return
String
.
format
(
"[ ](%s/direct/%s?msg=%s) "
,
baseUrl
,
message
.
getUser
().
getUsername
(),
message
.
getId
());
}
else
{
return
String
.
format
(
"[ ](%s/channel/%s?msg=%s) @%s "
,
baseUrl
,
currentRoom
.
getName
(),
message
.
getId
(),
message
.
getUser
().
getUsername
());
}
}
@Override
...
...
@@ -233,6 +277,7 @@ public class RoomPresenter extends BasePresenter<RoomContract.View>
}
private
void
processRoom
(
Room
room
)
{
this
.
currentRoom
=
room
;
view
.
render
(
room
);
if
(
room
.
isDirectMessage
())
{
...
...
app/src/main/java/chat/rocket/android/fragment/server_config/LoginFragment.java
View file @
95e001cc
...
...
@@ -100,7 +100,7 @@ public class LoginFragment extends AbstractServerConfigFragment implements Login
try
{
fragment
=
info
.
fragmentClass
.
newInstance
();
}
catch
(
Exception
exception
)
{
RCLog
.
w
(
exception
,
"failed to
create
new Fragment"
);
RCLog
.
w
(
exception
,
"failed to
build
new Fragment"
);
}
if
(
fragment
!=
null
)
{
Bundle
args
=
new
Bundle
();
...
...
app/src/main/java/chat/rocket/android/fragment/server_config/UserRegistrationDialogFragment.java
View file @
95e001cc
...
...
@@ -30,7 +30,7 @@ public class UserRegistrationDialogFragment extends DialogFragment {
}
/**
*
create
UserRegistrationDialogFragment with auto-detect email/username.
*
build
UserRegistrationDialogFragment with auto-detect email/username.
*/
public
static
UserRegistrationDialogFragment
create
(
String
hostname
,
String
usernameOrEmail
,
String
password
)
{
...
...
@@ -42,7 +42,7 @@ public class UserRegistrationDialogFragment extends DialogFragment {
}
/**
*
create
UserRegistrationDialogFragment.
*
build
UserRegistrationDialogFragment.
*/
public
static
UserRegistrationDialogFragment
create
(
String
hostname
,
String
username
,
String
email
,
...
...
app/src/main/java/chat/rocket/android/fragment/sidebar/SidebarMainFragment.java
View file @
95e001cc
...
...
@@ -67,7 +67,7 @@ public class SidebarMainFragment extends AbstractFragment implements SidebarMain
public
SidebarMainFragment
()
{}
/**
*
create
SidebarMainFragment with hostname.
*
build
SidebarMainFragment with hostname.
*/
public
static
SidebarMainFragment
create
(
String
hostname
)
{
Bundle
args
=
new
Bundle
();
...
...
app/src/main/java/chat/rocket/android/layouthelper/chatroom/MessageFormManager.kt
View file @
95e001cc
package
chat.rocket.android.layouthelper.chatroom
import
chat.rocket.android.widget.AbsoluteUrl
import
chat.rocket.android.widget.message.MessageFormLayout
import
chat.rocket.core.models.Message
class
MessageFormManager
(
private
val
messageFormLayout
:
MessageFormLayout
,
val
callback
:
MessageFormLayout
.
ExtraActionSelectionClickListener
)
{
private
var
sendMessageCallback
:
SendMessageCallback
?
=
null
private
var
replyMarkDown
:
String
=
""
init
{
messageFormLayout
.
setExtraActionSelectionClickListener
(
callback
)
...
...
@@ -31,8 +34,20 @@ class MessageFormManager(private val messageFormLayout: MessageFormLayout, val c
messageFormLayout
.
isEnabled
=
enable
}
fun
setReply
(
absoluteUrl
:
AbsoluteUrl
,
replyMarkDown
:
String
,
message
:
Message
)
{
this
.
replyMarkDown
=
replyMarkDown
messageFormLayout
.
setReplyContent
(
absoluteUrl
,
message
)
messageFormLayout
.
setReplyCancelListener
({
this
.
replyMarkDown
=
""
messageFormLayout
.
clearReplyContent
()
messageFormLayout
.
hideKeyboard
()
})
}
private
fun
sendMessage
(
message
:
String
)
{
sendMessageCallback
?.
onSubmitText
(
message
)
val
finalMessage
=
if
(
replyMarkDown
.
isNotEmpty
())
"$replyMarkDown $message"
else
message
replyMarkDown
=
""
sendMessageCallback
?.
onSubmitText
(
finalMessage
)
}
interface
SendMessageCallback
{
...
...
app/src/main/java/chat/rocket/android/layouthelper/chatroom/MessagePopup.java
0 → 100644
View file @
95e001cc
package
chat
.
rocket
.
android
.
layouthelper
.
chatroom
;
import
android.content.Context
;
import
android.support.annotation.NonNull
;
import
android.support.v4.util.Pair
;
import
android.support.v7.app.AlertDialog
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.android.BackgroundLooper
;
import
chat.rocket.android.RocketChatApplication
;
import
chat.rocket.android.RocketChatCache
;
import
chat.rocket.android.helper.Logger
;
import
chat.rocket.core.interactors.EditMessageInteractor
;
import
chat.rocket.core.interactors.PermissionInteractor
;
import
chat.rocket.core.models.Message
;
import
chat.rocket.core.repositories.MessageRepository
;
import
chat.rocket.core.repositories.PermissionRepository
;
import
chat.rocket.core.repositories.PublicSettingRepository
;
import
chat.rocket.core.repositories.RoomRepository
;
import
chat.rocket.core.repositories.RoomRoleRepository
;
import
chat.rocket.core.repositories.UserRepository
;
import
chat.rocket.persistence.realm.repositories.RealmMessageRepository
;
import
chat.rocket.persistence.realm.repositories.RealmPermissionRepository
;
import
chat.rocket.persistence.realm.repositories.RealmPublicSettingRepository
;
import
chat.rocket.persistence.realm.repositories.RealmRoomRepository
;
import
chat.rocket.persistence.realm.repositories.RealmRoomRoleRepository
;
import
chat.rocket.persistence.realm.repositories.RealmUserRepository
;
import
io.reactivex.Single
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.CompositeDisposable
;
import
io.reactivex.disposables.Disposable
;
public
class
MessagePopup
{
private
static
volatile
MessagePopup
singleton
=
null
;
private
static
final
Action
REPLY_ACTION_INFO
=
new
Action
(
"Reply"
,
null
,
true
);
private
static
final
Action
EDIT_ACTION_INFO
=
new
Action
(
"Edit"
,
null
,
true
);
private
static
final
Action
COPY_ACTION_INFO
=
new
Action
(
"Copy"
,
null
,
true
);
private
final
List
<
Action
>
defaultActions
=
new
ArrayList
<>(
3
);
private
final
List
<
Action
>
otherActions
=
new
ArrayList
<>();
private
Message
message
;
private
CompositeDisposable
compositeDisposable
=
new
CompositeDisposable
();
private
MessagePopup
(
Message
message
)
{
this
.
message
=
message
;
}
private
void
showAvailableActionsOnly
(
Context
context
)
{
RocketChatCache
cache
=
new
RocketChatCache
(
RocketChatApplication
.
getInstance
());
String
hostname
=
cache
.
getSelectedServerHostname
();
EditMessageInteractor
editMessageInteractor
=
getEditMessageInteractor
(
hostname
);
MessageRepository
messageRepository
=
new
RealmMessageRepository
(
hostname
);
Disposable
disposable
=
messageRepository
.
getById
(
singleton
.
message
.
getId
())
.
flatMap
(
it
->
{
if
(!
it
.
isPresent
())
{
return
Single
.
just
(
Pair
.<
Message
,
Boolean
>
create
(
null
,
false
));
}
Message
message
=
it
.
get
();
return
Single
.
zip
(
Single
.
just
(
message
),
editMessageInteractor
.
isAllowed
(
message
),
Pair:
:
create
);
})
.
subscribeOn
(
AndroidSchedulers
.
from
(
BackgroundLooper
.
get
()))
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
subscribe
(
pair
->
{
EDIT_ACTION_INFO
.
allowed
=
pair
.
second
;
List
<
Action
>
allActions
=
singleton
.
defaultActions
;
List
<
Action
>
allowedActions
=
new
ArrayList
<>(
3
);
for
(
int
i
=
0
;
i
<
allActions
.
size
();
i
++)
{
Action
action
=
allActions
.
get
(
i
);
if
(
action
.
allowed
)
{
allowedActions
.
add
(
action
);
}
}
allowedActions
.
addAll
(
singleton
.
otherActions
);
CharSequence
[]
items
=
new
CharSequence
[
allowedActions
.
size
()];
for
(
int
j
=
0
;
j
<
items
.
length
;
j
++)
{
items
[
j
]
=
allowedActions
.
get
(
j
).
actionName
;
}
new
AlertDialog
.
Builder
(
context
)
.
setItems
(
items
,
(
dialog
,
index
)
->
{
Action
action
=
allowedActions
.
get
(
index
);
ActionListener
actionListener
=
action
.
actionListener
;
if
(
actionListener
!=
null
)
{
actionListener
.
execute
(
singleton
.
message
);
}
})
.
setOnCancelListener
(
dialog
->
compositeDisposable
.
clear
())
.
setOnDismissListener
(
dialog1
->
compositeDisposable
.
clear
())
.
setTitle
(
"Message"
)
.
create
()
.
show
();
},
Logger:
:
report
);
compositeDisposable
.
add
(
disposable
);
}
private
void
addDefaultActions
()
{
singleton
.
defaultActions
.
add
(
REPLY_ACTION_INFO
);
singleton
.
defaultActions
.
add
(
EDIT_ACTION_INFO
);
singleton
.
defaultActions
.
add
(
COPY_ACTION_INFO
);
}
public
static
MessagePopup
take
(
Message
message
)
{
if
(
singleton
==
null
)
{
synchronized
(
MessagePopup
.
class
)
{
if
(
singleton
==
null
)
{
singleton
=
new
Builder
(
message
).
build
();
singleton
.
addDefaultActions
();
}
}
}
singleton
.
message
=
message
;
singleton
.
otherActions
.
clear
();
return
singleton
;
}
private
Action
getActionIfExists
(
Action
action
)
{
if
(
singleton
.
otherActions
.
contains
(
action
))
{
return
singleton
.
otherActions
.
get
(
singleton
.
otherActions
.
indexOf
(
action
));
}
if
(
singleton
.
defaultActions
.
contains
(
action
))
{
return
singleton
.
defaultActions
.
get
(
singleton
.
defaultActions
.
indexOf
(
action
));
}
return
null
;
}
public
MessagePopup
addAction
(
@NonNull
CharSequence
actionName
,
ActionListener
actionListener
)
{
List
<
Action
>
actions
=
singleton
.
otherActions
;
Action
newAction
=
new
Action
(
actionName
,
actionListener
,
true
);
Action
existingAction
=
getActionIfExists
(
newAction
);
if
(
existingAction
!=
null
)
{
existingAction
.
actionListener
=
actionListener
;
}
else
{
actions
.
add
(
newAction
);
}
return
singleton
;
}
public
MessagePopup
setReplyAction
(
ActionListener
actionListener
)
{
REPLY_ACTION_INFO
.
actionListener
=
actionListener
;
return
singleton
;
}
public
MessagePopup
setEditAction
(
ActionListener
actionListener
)
{
EDIT_ACTION_INFO
.
actionListener
=
actionListener
;
return
singleton
;
}
public
MessagePopup
setCopyAction
(
ActionListener
actionListener
)
{
COPY_ACTION_INFO
.
actionListener
=
actionListener
;
return
singleton
;
}
public
void
showWith
(
Context
context
)
{
showAvailableActionsOnly
(
context
);
}
private
EditMessageInteractor
getEditMessageInteractor
(
String
hostname
)
{
UserRepository
userRepository
=
new
RealmUserRepository
(
hostname
);
RoomRoleRepository
roomRoleRepository
=
new
RealmRoomRoleRepository
(
hostname
);
PermissionRepository
permissionRepository
=
new
RealmPermissionRepository
(
hostname
);
PermissionInteractor
permissionInteractor
=
new
PermissionInteractor
(
userRepository
,
roomRoleRepository
,
permissionRepository
);
MessageRepository
messageRepository
=
new
RealmMessageRepository
(
hostname
);
RoomRepository
roomRepository
=
new
RealmRoomRepository
(
hostname
);
PublicSettingRepository
publicSettingRepository
=
new
RealmPublicSettingRepository
(
hostname
);
return
new
EditMessageInteractor
(
permissionInteractor
,
userRepository
,
messageRepository
,
roomRepository
,
publicSettingRepository
);
}
private
static
class
Builder
{
private
final
Message
message
;
Builder
(
Message
message
)
{
if
(
message
==
null
)
{
throw
new
IllegalArgumentException
(
"Message must not be null"
);
}
this
.
message
=
message
;
}
public
MessagePopup
build
()
{
Message
message
=
this
.
message
;
return
new
MessagePopup
(
message
);
}
}
public
static
class
Action
{
private
CharSequence
actionName
;
private
ActionListener
actionListener
;
private
boolean
allowed
;
public
Action
(
CharSequence
actionName
,
ActionListener
actionListener
,
boolean
allowed
)
{
this
.
actionName
=
actionName
;
this
.
actionListener
=
actionListener
;
this
.
allowed
=
allowed
;
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
return
true
;
if
(
o
==
null
||
getClass
()
!=
o
.
getClass
())
return
false
;
Action
that
=
(
Action
)
o
;
return
actionName
.
equals
(
that
.
actionName
);
}
@Override
public
int
hashCode
()
{
return
actionName
.
hashCode
();
}
}
public
interface
ActionListener
{
void
execute
(
Message
message
);
}
}
app/src/main/java/chat/rocket/android/push/PushNotificationHandler.java
View file @
95e001cc
...
...
@@ -88,7 +88,7 @@ public class PushNotificationHandler implements PushConstants {
if
((
message
!=
null
&&
message
.
length
()
!=
0
)
||
(
title
!=
null
&&
title
.
length
()
!=
0
))
{
Log
.
d
(
LOG_TAG
,
"
create
notification"
);
Log
.
d
(
LOG_TAG
,
"
build
notification"
);
if
(
title
==
null
||
title
.
isEmpty
())
{
extras
.
putString
(
TITLE
,
getAppName
(
context
));
...
...
@@ -191,7 +191,7 @@ public class PushNotificationHandler implements PushConstants {
private
void
createActions
(
Context
context
,
Bundle
extras
,
NotificationCompat
.
Builder
builder
,
Resources
resources
,
String
packageName
,
int
notId
)
{
Log
.
d
(
LOG_TAG
,
"
create
actions: with in-line"
);
Log
.
d
(
LOG_TAG
,
"
build
actions: with in-line"
);
String
actions
=
extras
.
getString
(
ACTIONS
);
if
(
actions
==
null
)
{
return
;
...
...
@@ -256,7 +256,7 @@ public class PushNotificationHandler implements PushConstants {
RemoteInput
remoteInput
;
if
(
inline
)
{
Log
.
d
(
LOG_TAG
,
"
create
remote input"
);
Log
.
d
(
LOG_TAG
,
"
build
remote input"
);
String
replyLabel
=
"Enter your reply here"
;
remoteInput
=
new
RemoteInput
.
Builder
(
INLINE_REPLY
)
.
setLabel
(
replyLabel
)
...
...
@@ -287,7 +287,7 @@ public class PushNotificationHandler implements PushConstants {
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
KITKAT_WATCH
)
private
void
createActions
(
Context
context
,
Bundle
extras
,
Notification
.
Builder
builder
,
Resources
resources
,
String
packageName
,
int
notId
)
{
Log
.
d
(
LOG_TAG
,
"
create
actions: with in-line"
);
Log
.
d
(
LOG_TAG
,
"
build
actions: with in-line"
);
String
actions
=
extras
.
getString
(
ACTIONS
);
if
(
actions
==
null
)
{
return
;
...
...
@@ -352,7 +352,7 @@ public class PushNotificationHandler implements PushConstants {
android
.
app
.
RemoteInput
remoteInput
;
if
(
inline
)
{
Log
.
d
(
LOG_TAG
,
"
create
remote input"
);
Log
.
d
(
LOG_TAG
,
"
build
remote input"
);
String
replyLabel
=
"Enter your reply here"
;
remoteInput
=
new
android
.
app
.
RemoteInput
.
Builder
(
INLINE_REPLY
)
.
setLabel
(
replyLabel
)
...
...
app/src/main/java/chat/rocket/android/service/RocketChatWebSocketThread.java
View file @
95e001cc
...
...
@@ -109,7 +109,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
}
/**
*
create
new Thread.
*
build
new Thread.
*/
@DebugLog
public
static
Single
<
RocketChatWebSocketThread
>
getStarted
(
Context
appContext
,
String
hostname
)
{
...
...
@@ -241,11 +241,11 @@ public class RocketChatWebSocketThread extends HandlerThread {
private
Single
<
Boolean
>
prepareDDPClient
()
{
// TODO: temporarily replaced checkIfConnectionAlive() call for this single checking if ddpClient is
// null or not. In case it is,
create
a new client, otherwise just keep connecting with existing one.
// null or not. In case it is,
build
a new client, otherwise just keep connecting with existing one.
return
Single
.
just
(
ddpClient
!=
null
)
.
doOnSuccess
(
alive
->
{
if
(!
alive
)
{
RCLog
.
d
(
"DDPClient#
create
"
);
RCLog
.
d
(
"DDPClient#
build
"
);
ddpClient
=
DDPClientWrapper
.
create
(
hostname
);
}
});
...
...
@@ -392,7 +392,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
)
);
}
else
{
// if we don't have any session then just
create
the observers and register normally
// if we don't have any session then just
build
the observers and register normally
createObserversAndRegister
();
}
}
...
...
app/src/main/java/chat/rocket/android/service/internal/AbstractRocketChatCacheObserver.java
View file @
95e001cc
...
...
@@ -4,14 +4,13 @@ import android.content.Context;
import
com.hadisatrio.optional.Optional
;
import
chat.rocket.android.log.RCLog
;
import
io.reactivex.disposables.CompositeDisposable
;
import
chat.rocket.android.RocketChatCache
;
import
chat.rocket.android.helper.TextUtils
;
import
chat.rocket.persistence.realm.models.ddp.RealmRoom
;
import
chat.rocket.persistence.realm.RealmHelper
;
import
chat.rocket.android.log.RCLog
;
import
chat.rocket.android.service.Registrable
;
import
chat.rocket.persistence.realm.RealmHelper
;
import
chat.rocket.persistence.realm.models.ddp.RealmRoom
;
import
io.reactivex.disposables.CompositeDisposable
;
public
abstract
class
AbstractRocketChatCacheObserver
implements
Registrable
{
private
final
Context
context
;
...
...
@@ -50,6 +49,7 @@ public abstract class AbstractRocketChatCacheObserver implements Registrable {
compositeDisposable
.
add
(
new
RocketChatCache
(
context
)
.
getSelectedRoomIdPublisher
()
.
filter
(
Optional:
:
isPresent
)
.
map
(
Optional:
:
get
)
.
subscribe
(
this
::
updateRoomIdWith
,
RCLog:
:
e
)
);
...
...
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/helper/MarkDown.java
View file @
95e001cc
...
...
@@ -51,7 +51,7 @@ public class MarkDown {
private
static
final
Pattern
LINK_PATTERN
=
Pattern
.
compile
(
"\\[([^\\]]+)\\]\\(((?:http|https):\\/\\/[^\\)]+
)\\)"
,
Pattern
.
MULTILINE
);
"\\[(.*?)\\]\\(((https?):\\/\\/[-a-zA-Z0-9+&@#\\/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#\\/%=~_|]?
)\\)"
,
Pattern
.
MULTILINE
);
private
static
void
highlightLink1
(
SpannableString
inputText
)
{
final
Matcher
matcher
=
LINK_PATTERN
.
matcher
(
inputText
);
while
(
matcher
.
find
())
{
...
...
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/MessageFormLayout.java
View file @
95e001cc
...
...
@@ -4,6 +4,7 @@ import android.annotation.TargetApi;
import
android.content.Context
;
import
android.os.Build
;
import
android.os.Bundle
;
import
android.support.annotation.NonNull
;
import
android.support.v13.view.inputmethod.InputContentInfoCompat
;
import
android.text.Editable
;
import
android.text.TextUtils
;
...
...
@@ -15,10 +16,20 @@ import android.view.ViewGroup;
import
android.view.inputmethod.InputMethodManager
;
import
android.widget.EditText
;
import
android.widget.ImageButton
;
import
android.widget.ImageView
;
import
android.widget.LinearLayout
;
import
android.widget.RelativeLayout
;
import
android.widget.TextView
;
import
com.facebook.drawee.view.SimpleDraweeView
;
import
chat.rocket.android.widget.AbsoluteUrl
;
import
chat.rocket.android.widget.R
;
import
chat.rocket.android.widget.helper.DebouncingOnClickListener
;
import
chat.rocket.android.widget.helper.FrescoHelper
;
import
chat.rocket.core.models.Attachment
;
import
chat.rocket.core.models.AttachmentTitle
;
import
chat.rocket.core.models.Message
;
public
class
MessageFormLayout
extends
LinearLayout
{
...
...
@@ -27,6 +38,12 @@ public class MessageFormLayout extends LinearLayout {
private
ImageButton
attachButton
;
private
ImageButton
sendButton
;
private
RelativeLayout
replyBar
;
private
ImageView
replyCancelButton
;
private
SimpleDraweeView
replyThumb
;
private
TextView
replyMessageText
;
private
TextView
replyUsernameText
;
private
ExtraActionSelectionClickListener
extraActionSelectionClickListener
;
private
SubmitTextListener
submitTextListener
;
private
ImageKeyboardEditText
.
OnCommitContentListener
listener
;
...
...
@@ -65,6 +82,12 @@ public class MessageFormLayout extends LinearLayout {
}
});
replyCancelButton
=
composer
.
findViewById
(
R
.
id
.
reply_cancel
);
replyMessageText
=
composer
.
findViewById
(
R
.
id
.
reply_message
);
replyUsernameText
=
composer
.
findViewById
(
R
.
id
.
reply_username
);
replyThumb
=
composer
.
findViewById
(
R
.
id
.
reply_thumb
);
replyBar
=
composer
.
findViewById
(
R
.
id
.
reply_bar
);
sendButton
=
composer
.
findViewById
(
R
.
id
.
button_send
);
sendButton
.
setOnClickListener
(
new
DebouncingOnClickListener
()
{
...
...
@@ -73,6 +96,7 @@ public class MessageFormLayout extends LinearLayout {
String
messageText
=
getText
();
if
(
messageText
.
length
()
>
0
&&
submitTextListener
!=
null
)
{
submitTextListener
.
onSubmitText
(
messageText
);
clearReplyContent
();
}
}
});
...
...
@@ -118,6 +142,20 @@ public class MessageFormLayout extends LinearLayout {
addView
(
composer
);
}
public
void
clearReplyContent
()
{
replyBar
.
setVisibility
(
View
.
GONE
);
replyThumb
.
setVisibility
(
View
.
GONE
);
replyMessageText
.
setText
(
""
);
replyUsernameText
.
setText
(
""
);
}
public
void
showReplyThumb
()
{
replyThumb
.
setVisibility
(
View
.
VISIBLE
);
}
public
void
setReplyCancelListener
(
OnClickListener
onClickListener
)
{
replyCancelButton
.
setOnClickListener
(
onClickListener
);
}
public
EditText
getEditText
()
{
return
(
EditText
)
composer
.
findViewById
(
R
.
id
.
editor
);
}
...
...
@@ -154,10 +192,7 @@ public class MessageFormLayout extends LinearLayout {
if
(
text
.
length
()
>
0
)
{
editor
.
setSelection
(
text
.
length
());
InputMethodManager
inputMethodManager
=
(
InputMethodManager
)
editor
.
getContext
()
.
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
editor
.
requestFocus
();
inputMethodManager
.
showSoftInput
(
editor
,
0
);
requestFocusAndShowKeyboard
();
}
}
});
...
...
@@ -173,6 +208,61 @@ public class MessageFormLayout extends LinearLayout {
this
.
listener
=
listener
;
}
public
void
setReplyContent
(
@NonNull
AbsoluteUrl
absoluteUrl
,
@NonNull
Message
message
)
{
String
text
=
message
.
getMessage
();
replyUsernameText
.
setText
(
message
.
getUser
().
getUsername
());
if
(!
TextUtils
.
isEmpty
(
text
))
{
replyMessageText
.
setText
(
text
);
}
else
{
if
(
message
.
getAttachments
()
!=
null
&&
message
.
getAttachments
().
size
()
>
0
)
{
Attachment
attachment
=
message
.
getAttachments
().
get
(
0
);
AttachmentTitle
attachmentTitle
=
attachment
.
getAttachmentTitle
();
String
imageUrl
=
null
;
if
(
attachment
.
getImageUrl
()
!=
null
)
{
imageUrl
=
absoluteUrl
.
from
(
attachment
.
getImageUrl
());
}
if
(
attachmentTitle
!=
null
)
{
text
=
attachmentTitle
.
getTitle
();
}
if
(
TextUtils
.
isEmpty
(
text
))
{
text
=
"Unknown"
;
}
if
(
imageUrl
!=
null
)
{
FrescoHelper
.
INSTANCE
.
loadImageWithCustomization
(
replyThumb
,
imageUrl
);
showReplyThumb
();
}
replyMessageText
.
setText
(
text
);
}
}
replyBar
.
setVisibility
(
View
.
VISIBLE
);
requestFocusAndShowKeyboard
();
}
public
void
hideKeyboard
()
{
final
EditText
editor
=
getEditor
();
editor
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
InputMethodManager
inputMethodManager
=
(
InputMethodManager
)
editor
.
getContext
()
.
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
inputMethodManager
.
hideSoftInputFromWindow
(
editor
.
getWindowToken
(),
0
);
}
});
}
private
void
requestFocusAndShowKeyboard
()
{
final
EditText
editor
=
getEditor
();
editor
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
InputMethodManager
inputMethodManager
=
(
InputMethodManager
)
editor
.
getContext
()
.
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
editor
.
requestFocus
();
inputMethodManager
.
showSoftInput
(
editor
,
0
);
}
});
}
private
void
animateHide
(
final
View
view
)
{
view
.
animate
().
scaleX
(
0
).
scaleY
(
0
).
setDuration
(
150
).
withEndAction
(
new
Runnable
()
{
@Override
...
...
rocket-chat-android-widgets/src/main/res/drawable/ic_close.xml
0 → 100644
View file @
95e001cc
<!-- drawable/close.xml -->
<vector
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:height=
"24dp"
android:width=
"24dp"
android:viewportWidth=
"24"
android:viewportHeight=
"24"
>
<path
android:fillColor=
"#000"
android:pathData=
"M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"
/>
</vector>
\ No newline at end of file
rocket-chat-android-widgets/src/main/res/drawable/ic_reply.xml
0 → 100644
View file @
95e001cc
<!-- drawable/reply.xml -->
<vector
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:height=
"24dp"
android:width=
"24dp"
android:viewportWidth=
"24"
android:viewportHeight=
"24"
>
<path
android:fillColor=
"#000"
android:pathData=
"M10,9V5L3,12L10,19V14.9C15,14.9 18.5,16.5 21,20C20,15 17,10 10,9Z"
/>
</vector>
\ No newline at end of file
rocket-chat-android-widgets/src/main/res/layout/message_composer.xml
View file @
95e001cc
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:minHeight=
"48dp"
android:background=
"@drawable/top_shadow"
tools:context=
"chat.rocket.android.widget.message.MessageFormLayout"
>
<chat.rocket.android.widget.message.ImageKeyboardEditText
android:id=
"@+id/editor"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"16dp"
android:layout_marginStart=
"16dp"
android:inputType=
"textCapSentences|textMultiLine"
android:hint=
"@string/message_composer_message_hint"
android:textSize=
"14sp"
android:minLines=
"1"
android:maxLines=
"4"
android:background=
"@null"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toLeftOf=
"@+id/container"
app:layout_constraintBottom_toBottomOf=
"parent"
/>
<FrameLayout
android:id=
"@+id/container"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"16dp"
android:layout_marginStart=
"16dp"
android:layout_marginRight=
"16dp"
android:layout_marginEnd=
"16dp"
app:layout_constraintTop_toTopOf=
"@+id/editor"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintLeft_toRightOf=
"@+id/editor"
app:layout_constraintBottom_toBottomOf=
"@+id/editor"
>
<ImageButton
android:id=
"@+id/button_attach"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:tint=
"@color/color_icon_composer"
app:srcCompat=
"@drawable/ic_attach_file_black_24dp"
android:background=
"?attr/selectableItemBackgroundBorderless"
/>
<ImageButton
android:id=
"@+id/button_send"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:tint=
"@color/color_accent"
app:srcCompat=
"@drawable/ic_send_black_24dp"
android:background=
"?attr/selectableItemBackgroundBorderless"
/>
</FrameLayout>
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:fresco=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"@drawable/top_shadow"
android:minHeight=
"48dp"
tools:context=
"chat.rocket.android.widget.message.MessageFormLayout"
>
<RelativeLayout
android:id=
"@+id/reply_bar"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginBottom=
"8dp"
android:layout_marginEnd=
"8dp"
android:layout_marginLeft=
"8dp"
android:layout_marginRight=
"8dp"
android:layout_marginStart=
"8dp"
android:layout_marginTop=
"8dp"
android:visibility=
"gone"
app:layout_constraintBottom_toTopOf=
"@+id/keyboard_container"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:layout_editor_absoluteX=
"8dp"
tools:layout_editor_absoluteY=
"8dp"
tools:visibility=
"visible"
>
<android.support.v7.widget.AppCompatImageView
android:id=
"@+id/reply_icon"
android:layout_width=
"24dp"
android:layout_height=
"24dp"
android:layout_marginRight=
"8dp"
android:layout_marginEnd=
"8dp"
android:layout_centerVertical=
"true"
android:layout_alignParentStart=
"true"
android:layout_alignParentLeft=
"true"
android:adjustViewBounds=
"true"
app:srcCompat=
"@drawable/ic_reply"
app:tint=
"@color/color_accent"
/>
<android.support.v7.widget.AppCompatImageView
android:id=
"@+id/reply_cancel"
android:layout_width=
"24dp"
android:layout_height=
"24dp"
android:layout_marginLeft=
"8dp"
android:layout_marginStart=
"8dp"
android:layout_centerVertical=
"true"
android:layout_alignParentEnd=
"true"
android:layout_alignParentRight=
"true"
android:adjustViewBounds=
"true"
app:srcCompat=
"@drawable/ic_close"
app:tint=
"@color/color_icon_composer"
/>
<TextView
android:id=
"@+id/reply_username"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_alignBaseline=
"@id/reply_username"
android:layout_toLeftOf=
"@+id/reply_cancel"
android:layout_toStartOf=
"@id/reply_cancel"
android:layout_toRightOf=
"@+id/reply_thumb"
android:layout_toEndOf=
"@+id/reply_thumb"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textColor=
"@color/color_accent"
android:textStyle=
"bold"
tools:text=
"jane.doe"
/>
<com.facebook.drawee.view.SimpleDraweeView
android:id=
"@+id/reply_thumb"
android:layout_width=
"32dp"
android:layout_height=
"wrap_content"
android:layout_marginRight=
"4dp"
android:layout_marginEnd=
"4dp"
android:layout_toRightOf=
"@+id/reply_icon"
android:layout_toEndOf=
"@+id/reply_icon"
android:layout_alignBottom=
"@+id/reply_message"
android:layout_alignTop=
"@+id/reply_username"
android:layout_centerVertical=
"true"
android:visibility=
"gone"
fresco:actualImageScaleType=
"fitCenter"
/>
<TextView
android:id=
"@+id/reply_message"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_below=
"@id/reply_username"
android:layout_toLeftOf=
"@+id/reply_cancel"
android:layout_toStartOf=
"@id/reply_cancel"
android:layout_toRightOf=
"@+id/reply_thumb"
android:layout_toEndOf=
"@+id/reply_thumb"
android:ellipsize=
"end"
android:maxLines=
"1"
tools:text=
"Message"
/>
</RelativeLayout>
<android.support.constraint.ConstraintLayout
android:id=
"@+id/keyboard_container"
android:layout_width=
"0dp"
android:layout_height=
"48dp"
android:background=
"@drawable/top_shadow"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/reply_bar"
>
<chat.rocket.android.widget.message.ImageKeyboardEditText
android:id=
"@+id/editor"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"16dp"
android:layout_marginStart=
"16dp"
android:background=
"@null"
android:hint=
"@string/message_composer_message_hint"
android:inputType=
"textCapSentences|textMultiLine"
android:maxLines=
"4"
android:minLines=
"1"
android:textSize=
"14sp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toLeftOf=
"@+id/container"
app:layout_constraintTop_toTopOf=
"parent"
/>
<FrameLayout
android:id=
"@+id/container"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"16dp"
android:layout_marginLeft=
"16dp"
android:layout_marginRight=
"16dp"
android:layout_marginStart=
"16dp"
app:layout_constraintBottom_toBottomOf=
"@+id/editor"
app:layout_constraintLeft_toRightOf=
"@+id/editor"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toTopOf=
"@+id/editor"
>
<ImageButton
android:id=
"@+id/button_attach"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:background=
"?attr/selectableItemBackgroundBorderless"
android:tint=
"@color/color_icon_composer"
app:srcCompat=
"@drawable/ic_attach_file_black_24dp"
/>
<ImageButton
android:id=
"@+id/button_send"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:background=
"?attr/selectableItemBackgroundBorderless"
android:tint=
"@color/color_accent"
app:srcCompat=
"@drawable/ic_send_black_24dp"
/>
</FrameLayout>
</android.support.constraint.ConstraintLayout>
</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