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
9d8197a7
Commit
9d8197a7
authored
Sep 27, 2017
by
Rafael Kellermann Streit
Committed by
GitHub
Sep 27, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #454 from filipedelimabrito/iss424
[NEW] Room's menu (REST API calls)
parents
16052e46
1860afc3
Changes
49
Hide whitespace changes
Inline
Side-by-side
Showing
49 changed files
with
2312 additions
and
924 deletions
+2312
-924
build.gradle
app/build.gradle
+7
-1
OkHttpHelper.kt
...src/debug/java/chat/rocket/android/helper/OkHttpHelper.kt
+8
-0
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+5
-0
MainActivity.java
.../main/java/chat/rocket/android/activity/MainActivity.java
+0
-1
RoomActivity.kt
...in/java/chat/rocket/android/activity/room/RoomActivity.kt
+43
-0
RestApiHelper.kt
...c/main/java/chat/rocket/android/api/rest/RestApiHelper.kt
+218
-0
RocketChatAbsoluteUrl.java
...cket/android/fragment/chatroom/RocketChatAbsoluteUrl.java
+9
-1
RoomFragment.java
...a/chat/rocket/android/fragment/chatroom/RoomFragment.java
+522
-525
UsersOfRoomDialogFragment.java
...d/fragment/chatroom/dialog/UsersOfRoomDialogFragment.java
+0
-207
RoomListContract.kt
...rocket/android/fragment/chatroom/list/RoomListContract.kt
+134
-0
RoomListFragment.kt
...rocket/android/fragment/chatroom/list/RoomListFragment.kt
+188
-0
RoomListPresenter.kt
...ocket/android/fragment/chatroom/list/RoomListPresenter.kt
+266
-0
EndlessRecyclerViewScrollListener.kt
...ocket/android/helper/EndlessRecyclerViewScrollListener.kt
+111
-0
LoadMoreScrollListener.java
...va/chat/rocket/android/helper/LoadMoreScrollListener.java
+0
-44
LoadMoreScrollListener.kt
...java/chat/rocket/android/helper/LoadMoreScrollListener.kt
+30
-0
UrlHelper.kt
app/src/main/java/chat/rocket/android/helper/UrlHelper.kt
+41
-0
AbstractMessageViewHolder.java
...roid/layouthelper/chatroom/AbstractMessageViewHolder.java
+2
-2
RoomFileListAdapter.kt
...android/layouthelper/chatroom/list/RoomFileListAdapter.kt
+35
-0
RoomMemberListAdapter.kt
...droid/layouthelper/chatroom/list/RoomMemberListAdapter.kt
+69
-0
RoomMessagesAdapter.kt
...android/layouthelper/chatroom/list/RoomMessagesAdapter.kt
+90
-0
RoomUserAdapter.java
...t/android/layouthelper/chatroom/list/RoomUserAdapter.java
+1
-1
RoomUserViewHolder.java
...ndroid/layouthelper/chatroom/list/RoomUserViewHolder.java
+1
-1
ic_close_circle_outline_black_24dp.xml
.../main/res/drawable/ic_close_circle_outline_black_24dp.xml
+11
-0
activity_main.xml
app/src/main/res/layout-w720dp/activity_main.xml
+3
-1
fragment_room.xml
app/src/main/res/layout-w720dp/fragment_room.xml
+0
-12
activity_main.xml
app/src/main/res/layout/activity_main.xml
+3
-1
activity_room.xml
app/src/main/res/layout/activity_room.xml
+26
-0
day.xml
app/src/main/res/layout/day.xml
+30
-0
fragment_room.xml
app/src/main/res/layout/fragment_room.xml
+14
-11
fragment_room_list.xml
app/src/main/res/layout/fragment_room_list.xml
+25
-0
fragment_room_main.xml
app/src/main/res/layout/fragment_room_main.xml
+0
-21
item_room_file.xml
app/src/main/res/layout/item_room_file.xml
+22
-0
item_room_member.xml
app/src/main/res/layout/item_room_member.xml
+67
-0
item_room_message.xml
app/src/main/res/layout/item_room_message.xml
+85
-0
list_item_message_newday.xml
app/src/main/res/layout/list_item_message_newday.xml
+0
-34
list_item_normal_message.xml
app/src/main/res/layout/list_item_normal_message.xml
+1
-1
list_item_system_message.xml
app/src/main/res/layout/list_item_system_message.xml
+1
-1
room_side_menu.xml
app/src/main/res/layout/room_side_menu.xml
+0
-29
menu_room.xml
app/src/main/res/menu/menu_room.xml
+20
-0
colors.xml
app/src/main/res/values/colors.xml
+13
-8
fa_strings.xml
app/src/main/res/values/fa_strings.xml
+0
-9
message_style.xml
app/src/main/res/values/message_style.xml
+27
-0
message_styles.xml
app/src/main/res/values/message_styles.xml
+0
-11
strings.xml
app/src/main/res/values/strings.xml
+17
-0
OkHttpHelper.kt
...c/release/java/chat/rocket/android/helper/OkHttpHelper.kt
+11
-1
RestApiHelperTest.kt
.../kotlin/chat/rocket/android/api/rest/RestApiHelperTest.kt
+110
-0
UrlHelperTest.kt
...c/test/kotlin/chat/rocket/android/helper/UrlHelperTest.kt
+40
-0
build.gradle
build.gradle
+1
-1
User.java
...chat-core/src/main/java/chat/rocket/core/models/User.java
+5
-0
No files found.
app/build.gradle
View file @
9d8197a7
...
...
@@ -7,6 +7,7 @@ repositories {
}
apply
plugin:
'kotlin-android'
apply
plugin:
'kotlin-android-extensions'
apply
plugin:
'me.tatarka.retrolambda'
apply
plugin:
'com.jakewharton.hugo'
apply
plugin:
'com.github.triplet.play'
...
...
@@ -103,7 +104,10 @@ android {
manifest
.
srcFile
'src/release/AndroidManifest.xml'
}
test
.
java
.
srcDirs
+=
'src/test/kotlin'
test
{
test
.
java
.
srcDirs
+=
'src/test/kotlin'
androidTest
.
java
.
srcDirs
+=
'src/androidTest/kotlin'
}
}
}
...
...
@@ -137,6 +141,8 @@ dependencies {
compile
'com.android.support:multidex:1.0.1'
compile
"org.jetbrains.kotlin:kotlin-stdlib-jre7:$rootProject.ext.kotlinVersion"
testCompile
"org.jetbrains.kotlin:kotlin-test:$rootProject.ext.kotlinVersion"
testCompile
"org.jetbrains.kotlin:kotlin-test-junit:$rootProject.ext.kotlinVersion"
compile
"com.google.firebase:firebase-core:$playLibVersion"
compile
"com.google.firebase:firebase-crash:$playLibVersion"
...
...
app/src/debug/java/chat/rocket/android/helper/OkHttpHelper.kt
View file @
9d8197a7
...
...
@@ -10,6 +10,13 @@ import okhttp3.OkHttpClient
object
OkHttpHelper
{
fun
getClient
():
OkHttpClient
{
if
(
httpClient
==
null
)
{
httpClient
=
OkHttpClient
()
}
return
httpClient
?:
throw
AssertionError
(
"httpClient set to null by another thread"
)
}
fun
getClientForUploadFile
():
OkHttpClient
{
if
(
httpClientForUploadFile
==
null
)
{
httpClientForUploadFile
=
OkHttpClient
.
Builder
().
build
()
...
...
@@ -41,6 +48,7 @@ object OkHttpHelper {
return
httpClientForWS
?:
throw
AssertionError
(
"httpClientForWS set to null by another thread"
)
}
private
var
httpClient
:
OkHttpClient
?
=
null
private
var
httpClientForUploadFile
:
OkHttpClient
?
=
null
private
var
httpClientForDownloadFile
:
OkHttpClient
?
=
null
private
var
httpClientForWS
:
OkHttpClient
?
=
null
...
...
app/src/main/AndroidManifest.xml
View file @
9d8197a7
...
...
@@ -32,6 +32,11 @@
</intent-filter>
</activity>
<activity
android:name=
".activity.room.RoomActivity"
android:configChanges=
"orientation|screenSize"
android:windowSoftInputMode=
"adjustResize"
/>
<activity
android:name=
".activity.AddServerActivity"
android:configChanges=
"orientation|screenSize"
...
...
app/src/main/java/chat/rocket/android/activity/MainActivity.java
View file @
9d8197a7
...
...
@@ -48,7 +48,6 @@ public class MainActivity extends AbstractAuthedActivity implements MainContract
private
SlidingPaneLayout
pane
;
private
MainContract
.
Presenter
presenter
;
@Override
protected
int
getLayoutContainerForFragment
()
{
return
R
.
id
.
activity_main_container
;
}
...
...
app/src/main/java/chat/rocket/android/activity/room/RoomActivity.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.activity.room
import
android.os.Bundle
import
android.support.v4.app.Fragment
import
android.support.v7.app.AppCompatActivity
import
chat.rocket.android.R
import
chat.rocket.android.fragment.chatroom.list.RoomListFragment
import
kotlinx.android.synthetic.main.activity_room.*
class
RoomActivity
:
AppCompatActivity
()
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
setContentView
(
R
.
layout
.
activity_room
)
setSupportActionBar
(
toolbar
)
supportActionBar
?.
setDisplayHomeAsUpEnabled
(
true
)
supportActionBar
?.
setDisplayShowHomeEnabled
(
true
)
val
extras
=
intent
.
extras
val
roomListFragment
=
RoomListFragment
.
newInstance
(
extras
.
getInt
(
"actionId"
),
extras
.
getString
(
"roomId"
),
extras
.
getString
(
"roomType"
),
extras
.
getString
(
"hostname"
),
extras
.
getString
(
"token"
),
extras
.
getString
(
"userId"
))
addFragment
(
roomListFragment
,
"roomListFragment"
)
}
override
fun
onSupportNavigateUp
():
Boolean
{
onBackPressed
()
return
true
}
private
fun
addFragment
(
fragment
:
Fragment
,
tag
:
String
)
{
supportFragmentManager
.
beginTransaction
()
.
add
(
R
.
id
.
fragment_container
,
fragment
,
tag
)
.
commit
()
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/api/rest/RestApiHelper.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.api.rest
import
chat.rocket.android.helper.UrlHelper
import
chat.rocket.core.models.Room
import
okhttp3.HttpUrl
import
okhttp3.Request
/**
* Helper class for dealing with Rest API calls.
*
* @see <a href="https://rocket.chat/docs/developer-guides/rest-api">https://rocket.chat/docs/developer-guides/rest-api</a>.
*/
object
RestApiHelper
{
/**
* Returns an OkHttp3 request for pinned messages.
*
* @param roomId The ID of the room.
* @param roomType The type of the room.
* @param hostname The server hostname.
* @param token The token.
* @param userId The user Id.
* @param offset The offset to paging which specifies the first entry to return from a collection.
* @return An OkHttp3 request.
*/
fun
getRequestForPinnedMessages
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
String
):
Request
{
val
parsedHttpUrl
=
HttpUrl
.
parse
(
getEndpointUrlForMessages
(
roomType
,
hostname
))
?.
newBuilder
()
?.
addQueryParameter
(
"roomId"
,
roomId
)
?.
addQueryParameter
(
"query"
,
"{\"pinned\":true}"
)
?.
addQueryParameter
(
"offset"
,
offset
)
?.
build
()
return
Request
.
Builder
()
.
url
(
parsedHttpUrl
)
.
get
()
.
addHeader
(
"X-Auth-Token"
,
token
)
.
addHeader
(
"X-User-Id"
,
userId
)
.
build
()
}
/**
* Returns an OkHttp3 request for favorite messages.
*
* @param roomId The ID of the room.
* @param roomType The type of the room.
* @param hostname The server hostname.
* @param token The token.
* @param userId The user Id.
* @param offset The offset to paging which specifies the first entry to return from a collection.
* @return An OkHttp3 request.
*/
fun
getRequestForFavoriteMessages
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
String
):
Request
{
val
parsedHttpUrl
=
HttpUrl
.
parse
(
getEndpointUrlForMessages
(
roomType
,
hostname
))
?.
newBuilder
()
?.
addQueryParameter
(
"roomId"
,
roomId
)
?.
addQueryParameter
(
"query"
,
"{\"starred._id\":{\"\$in\":[\"$userId\"] } }"
)
?.
addQueryParameter
(
"offset"
,
offset
)
?.
build
()
return
Request
.
Builder
()
.
url
(
parsedHttpUrl
)
.
get
()
.
addHeader
(
"X-Auth-Token"
,
token
)
.
addHeader
(
"X-User-Id"
,
userId
)
.
build
()
}
/**
* Returns an OkHttp3 request for file list.
*
* @param roomId The ID of the room.
* @param roomType The type of the room.
* @param hostname The server hostname.
* @param token The token.
* @param userId The user Id.
* @param offset The offset to paging which specifies the first entry to return from a collection.
* @return An OkHttp3 request.
*/
fun
getRequestForFileList
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
String
):
Request
{
val
parsedHttpUrl
=
HttpUrl
.
parse
(
getEndpointUrlForFileList
(
roomType
,
hostname
))
?.
newBuilder
()
?.
addQueryParameter
(
"roomId"
,
roomId
)
?.
addQueryParameter
(
"offset"
,
offset
)
?.
build
()
return
Request
.
Builder
()
.
url
(
parsedHttpUrl
)
.
get
()
.
addHeader
(
"X-Auth-Token"
,
token
)
.
addHeader
(
"X-User-Id"
,
userId
)
.
build
()
}
/**
* Returns an OkHttp3 request for member list.
*
* @param roomId The ID of the room.
* @param roomType The type of the room.
* @param hostname The server hostname.
* @param token The token.
* @param userId The user Id.
* @param offset The offset to paging which specifies the first entry to return from a collection.
* @return An OkHttp3 request.
*/
fun
getRequestForMemberList
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
String
):
Request
{
val
parsedHttpUrl
=
HttpUrl
.
parse
(
getEndpointUrlForMemberList
(
roomType
,
hostname
))
?.
newBuilder
()
?.
addQueryParameter
(
"roomId"
,
roomId
)
?.
addQueryParameter
(
"offset"
,
offset
)
?.
build
()
return
Request
.
Builder
()
.
url
(
parsedHttpUrl
)
.
get
()
.
addHeader
(
"X-Auth-Token"
,
token
)
.
addHeader
(
"X-User-Id"
,
userId
)
.
build
()
}
/**
* Returns a Rest API endpoint URL for favorite or pinned messages accordingly with the room type and the server hostname.
*
* @param roomType The type of the room.
* @param hostname The server hostname.
* @return A Rest API URL endpoint.
*/
fun
getEndpointUrlForMessages
(
roomType
:
String
,
hostname
:
String
):
String
=
UrlHelper
.
getSafeHostname
(
hostname
)
+
getRestApiUrlForMessages
(
roomType
)
/**
* Returns a Rest API endpoint URL for file list accordingly with the room type and the server hostname.
*
* @param roomType The type of the room.
* @param hostname The server hostname.
* @return A Rest API URL endpoint.
*/
fun
getEndpointUrlForFileList
(
roomType
:
String
,
hostname
:
String
):
String
=
UrlHelper
.
getSafeHostname
(
hostname
)
+
getRestApiUrlForFileList
(
roomType
)
/**
* Returns a Rest API endpoint URL for member list accordingly with the room type and the server hostname.
*
* @param roomType The type of the room.
* @param hostname The server hostname.
* @return A Rest API URL endpoint.
*/
fun
getEndpointUrlForMemberList
(
roomType
:
String
,
hostname
:
String
):
String
=
UrlHelper
.
getSafeHostname
(
hostname
)
+
getRestApiUrlForMemberList
(
roomType
)
/**
* Returns the correspondent Rest API URL accordingly with the room type to get its favorite or pinned messages.
*
* @param roomType The type of the room.
* @return A Rest API URL or null if the room type does not match.
*/
fun
getRestApiUrlForMessages
(
roomType
:
String
):
String
?
{
var
restApiUrl
:
String
?
=
null
when
(
roomType
)
{
Room
.
TYPE_CHANNEL
->
restApiUrl
=
"/api/v1/channels.messages"
Room
.
TYPE_PRIVATE
->
restApiUrl
=
"/api/v1/groups.messages"
Room
.
TYPE_DIRECT_MESSAGE
->
restApiUrl
=
"/api/v1/dm.messages"
}
return
restApiUrl
}
/**
* Returns the correspondent Rest API URL accordingly with the room type to get its file list.
*
* @param roomType The type of the room.
* @return A Rest API URL or null if the room type does not match.
*/
fun
getRestApiUrlForFileList
(
roomType
:
String
):
String
?
{
var
restApiUrl
:
String
?
=
null
when
(
roomType
)
{
Room
.
TYPE_CHANNEL
->
restApiUrl
=
"/api/v1/channels.files"
Room
.
TYPE_PRIVATE
->
restApiUrl
=
"/api/v1/groups.files"
Room
.
TYPE_DIRECT_MESSAGE
->
restApiUrl
=
"/api/v1/dm.files"
}
return
restApiUrl
}
/**
* Returns the correspondent Rest API URL accordingly with the room type to get its members list.
*
* @param roomType The type of the room.
* @return A Rest API URL or null if the room type does not match.
*/
fun
getRestApiUrlForMemberList
(
roomType
:
String
):
String
?
{
var
restApiUrl
:
String
?
=
null
when
(
roomType
)
{
Room
.
TYPE_CHANNEL
->
restApiUrl
=
"/api/v1/channels.members"
Room
.
TYPE_PRIVATE
->
restApiUrl
=
"/api/v1/groups.members"
Room
.
TYPE_DIRECT_MESSAGE
->
restApiUrl
=
"/api/v1/dm.members"
}
return
restApiUrl
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/fragment/chatroom/RocketChatAbsoluteUrl.java
View file @
9d8197a7
...
...
@@ -21,4 +21,12 @@ public class RocketChatAbsoluteUrl implements AbsoluteUrl {
public
String
from
(
String
url
)
{
return
url
.
startsWith
(
"/"
)
?
baseUrl
+
url
+
"?rc_uid="
+
userId
+
"&rc_token="
+
token
:
url
;
}
}
public
String
getUserId
()
{
return
userId
;
}
public
String
getToken
()
{
return
token
;
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/fragment/chatroom/RoomFragment.java
View file @
9d8197a7
...
...
@@ -13,8 +13,6 @@ import android.support.v13.view.inputmethod.InputContentInfoCompat;
import
android.support.v4.app.DialogFragment
;
import
android.support.v4.os.BuildCompat
;
import
android.support.v4.util.Pair
;
import
android.support.v4.view.GravityCompat
;
import
android.support.v4.widget.DrawerLayout
;
import
android.support.v4.widget.SlidingPaneLayout
;
import
android.support.v7.app.AlertDialog
;
import
android.support.v7.widget.LinearLayoutManager
;
...
...
@@ -22,23 +20,20 @@ import android.support.v7.widget.RecyclerView;
import
android.view.View
;
import
com.hadisatrio.optional.Optional
;
import
com.jakewharton.rxbinding2.support.v4.widget.RxDrawerLayout
;
import
java.lang.reflect.Field
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.android.BackgroundLooper
;
import
chat.rocket.android.R
;
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.chatroom.dialog.UsersOfRoomDialogFragment
;
import
chat.rocket.android.fragment.sidebar.SidebarMainFragment
;
import
chat.rocket.android.helper.AbsoluteUrlHelper
;
import
chat.rocket.android.helper.FileUploadHelper
;
import
chat.rocket.android.helper.LoadMoreScrollListener
;
import
chat.rocket.android.helper.Logger
;
import
chat.rocket.android.helper.OnBackPressListener
;
import
chat.rocket.android.helper.RecyclerViewAutoScrollManager
;
import
chat.rocket.android.helper.RecyclerViewScrolledToBottomListener
;
...
...
@@ -52,10 +47,8 @@ import chat.rocket.android.layouthelper.extra_action.AbstractExtraActionItem;
import
chat.rocket.android.layouthelper.extra_action.MessageExtraActionBehavior
;
import
chat.rocket.android.layouthelper.extra_action.upload.AbstractUploadActionItem
;
import
chat.rocket.android.layouthelper.extra_action.upload.AudioUploadActionItem
;
import
chat.rocket.android.layouthelper.extra_action.upload.FileUploadActionItem
;
import
chat.rocket.android.layouthelper.extra_action.upload.ImageUploadActionItem
;
import
chat.rocket.android.layouthelper.extra_action.upload.VideoUploadActionItem
;
import
chat.rocket.android.log.RCLog
;
import
chat.rocket.android.renderer.RocketChatUserStatusProvider
;
import
chat.rocket.android.service.ConnectivityManager
;
import
chat.rocket.android.service.temp.DeafultTempSpotlightRoomCaller
;
...
...
@@ -99,563 +92,567 @@ public class RoomFragment extends AbstractChatRoomFragment implements
ModelListAdapter
.
OnItemLongClickListener
<
PairedMessage
>,
RoomContract
.
View
{
private
static
final
int
DIALOG_ID
=
1
;
private
static
final
String
HOSTNAME
=
"hostname"
;
private
static
final
String
ROOM_ID
=
"roomId"
;
private
static
final
int
DIALOG_ID
=
1
;
private
static
final
String
HOSTNAME
=
"hostname"
;
private
static
final
String
ROOM_ID
=
"roomId"
;
private
String
hostname
;
private
String
roomId
;
private
LoadMoreScrollListener
scrollListener
;
private
MessageFormManager
messageFormManager
;
private
RecyclerView
messageRecyclerView
;
private
RecyclerViewAutoScrollManager
recyclerViewAutoScrollManager
;
protected
AbstractNewMessageIndicatorManager
newMessageIndicatorManager
;
protected
Snackbar
unreadIndicator
;
private
boolean
previousUnreadMessageExists
;
private
MessageListAdapter
messageListAdapter
;
private
AutocompleteManager
autocompleteManager
;
private
List
<
AbstractExtraActionItem
>
extraActionItems
;
private
CompositeDisposable
compositeDisposable
=
new
CompositeDisposable
();
protected
RoomContract
.
Presenter
presenter
;
private
RealmRoomRepository
roomRepository
;
private
RealmUserRepository
userRepository
;
private
MethodCallHelper
methodCallHelper
;
private
AbsoluteUrlHelper
absoluteUrlHelper
;
private
Message
edittingMessage
=
null
;
private
SlidingPaneLayout
pane
;
private
SidebarMainFragment
sidebarFragment
;
public
RoomFragment
()
{}
/**
* create fragment with roomId.
*/
public
static
RoomFragment
create
(
String
hostname
,
String
roomId
)
{
Bundle
args
=
new
Bundle
();
args
.
putString
(
HOSTNAME
,
hostname
);
args
.
putString
(
ROOM_ID
,
roomId
);
RoomFragment
fragment
=
new
RoomFragment
();
fragment
.
setArguments
(
args
);
return
fragment
;
}
@Override
public
void
onCreate
(
@Nullable
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
Bundle
args
=
getArguments
();
hostname
=
args
.
getString
(
HOSTNAME
);
roomId
=
args
.
getString
(
ROOM_ID
);
roomRepository
=
new
RealmRoomRepository
(
hostname
);
MessageInteractor
messageInteractor
=
new
MessageInteractor
(
new
RealmMessageRepository
(
hostname
),
roomRepository
);
userRepository
=
new
RealmUserRepository
(
hostname
);
absoluteUrlHelper
=
new
AbsoluteUrlHelper
(
hostname
,
new
RealmServerInfoRepository
(),
userRepository
,
new
SessionInteractor
(
new
RealmSessionRepository
(
hostname
))
);
methodCallHelper
=
new
MethodCallHelper
(
getContext
(),
hostname
);
presenter
=
new
RoomPresenter
(
roomId
,
userRepository
,
messageInteractor
,
roomRepository
,
absoluteUrlHelper
,
methodCallHelper
,
ConnectivityManager
.
getInstance
(
getContext
())
);
if
(
savedInstanceState
==
null
)
{
presenter
.
loadMessages
();
}
}
@Override
protected
int
getLayout
()
{
return
R
.
layout
.
fragment_room
;
}
@Override
protected
void
onSetupView
()
{
pane
=
getActivity
().
findViewById
(
R
.
id
.
sliding_pane
);
messageRecyclerView
=
rootView
.
findViewById
(
R
.
id
.
messageRecyclerView
);
messageListAdapter
=
new
MessageListAdapter
(
getContext
(),
hostname
);
messageRecyclerView
.
setAdapter
(
messageListAdapter
);
messageListAdapter
.
setOnItemClickListener
(
this
);
messageListAdapter
.
setOnItemLongClickListener
(
this
);
LinearLayoutManager
linearLayoutManager
=
new
LinearLayoutManager
(
getContext
(),
LinearLayoutManager
.
VERTICAL
,
true
);
messageRecyclerView
.
setLayoutManager
(
linearLayoutManager
);
recyclerViewAutoScrollManager
=
new
RecyclerViewAutoScrollManager
(
linearLayoutManager
)
{
@Override
protected
void
onAutoScrollMissed
()
{
if
(
newMessageIndicatorManager
!=
null
)
{
presenter
.
onUnreadCount
();
}
}
};
messageListAdapter
.
registerAdapterDataObserver
(
recyclerViewAutoScrollManager
);
scrollListener
=
new
LoadMoreScrollListener
(
linearLayoutManager
,
40
)
{
@Override
public
void
requestMoreItem
()
{
presenter
.
loadMoreMessages
();
}
};
messageRecyclerView
.
addOnScrollListener
(
scrollListener
);
messageRecyclerView
.
addOnScrollListener
(
new
RecyclerViewScrolledToBottomListener
(
linearLayoutManager
,
1
,
this
::
markAsReadIfNeeded
));
newMessageIndicatorManager
=
new
AbstractNewMessageIndicatorManager
()
{
@Override
protected
void
onShowIndicator
(
int
count
,
boolean
onlyAlreadyShown
)
{
if
((
onlyAlreadyShown
&&
unreadIndicator
!=
null
&&
unreadIndicator
.
isShown
())
||
!
onlyAlreadyShown
)
{
unreadIndicator
=
getUnreadCountIndicatorView
(
count
);
unreadIndicator
.
show
();
}
}
private
String
hostname
;
private
String
token
;
private
String
userId
;
private
String
roomId
;
private
String
roomType
;
private
LoadMoreScrollListener
scrollListener
;
private
MessageFormManager
messageFormManager
;
private
RecyclerView
messageRecyclerView
;
private
RecyclerViewAutoScrollManager
recyclerViewAutoScrollManager
;
protected
AbstractNewMessageIndicatorManager
newMessageIndicatorManager
;
protected
Snackbar
unreadIndicator
;
private
boolean
previousUnreadMessageExists
;
private
MessageListAdapter
messageListAdapter
;
private
AutocompleteManager
autocompleteManager
;
private
List
<
AbstractExtraActionItem
>
extraActionItems
;
private
CompositeDisposable
compositeDisposable
=
new
CompositeDisposable
();
protected
RoomContract
.
Presenter
presenter
;
private
RealmRoomRepository
roomRepository
;
private
RealmUserRepository
userRepository
;
private
MethodCallHelper
methodCallHelper
;
private
AbsoluteUrlHelper
absoluteUrlHelper
;
private
Message
edittingMessage
=
null
;
private
RoomToolbar
toolbar
;
private
SlidingPaneLayout
pane
;
private
SidebarMainFragment
sidebarFragment
;
public
RoomFragment
()
{
}
/**
* create fragment with roomId.
*/
public
static
RoomFragment
create
(
String
hostname
,
String
roomId
)
{
Bundle
args
=
new
Bundle
();
args
.
putString
(
HOSTNAME
,
hostname
);
args
.
putString
(
ROOM_ID
,
roomId
);
RoomFragment
fragment
=
new
RoomFragment
();
fragment
.
setArguments
(
args
);
return
fragment
;
}
@Override
public
void
onCreate
(
@Nullable
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setHasOptionsMenu
(
true
);
@Override
protected
void
onHideIndicator
()
{
if
(
unreadIndicator
!=
null
&&
unreadIndicator
.
isShown
())
{
unreadIndicator
.
dismiss
();
Bundle
args
=
getArguments
();
hostname
=
args
.
getString
(
HOSTNAME
);
roomId
=
args
.
getString
(
ROOM_ID
);
roomRepository
=
new
RealmRoomRepository
(
hostname
);
MessageInteractor
messageInteractor
=
new
MessageInteractor
(
new
RealmMessageRepository
(
hostname
),
roomRepository
);
userRepository
=
new
RealmUserRepository
(
hostname
);
absoluteUrlHelper
=
new
AbsoluteUrlHelper
(
hostname
,
new
RealmServerInfoRepository
(),
userRepository
,
new
SessionInteractor
(
new
RealmSessionRepository
(
hostname
))
);
methodCallHelper
=
new
MethodCallHelper
(
getContext
(),
hostname
);
presenter
=
new
RoomPresenter
(
roomId
,
userRepository
,
messageInteractor
,
roomRepository
,
absoluteUrlHelper
,
methodCallHelper
,
ConnectivityManager
.
getInstance
(
getContext
())
);
if
(
savedInstanceState
==
null
)
{
presenter
.
loadMessages
();
}
}
};
setupSidebar
();
setupSideMenu
();
setupMessageComposer
();
setupMessageActions
();
}
private
void
setupMessageActions
()
{
extraActionItems
=
new
ArrayList
<>(
4
);
// fixed number as of now
extraActionItems
.
add
(
new
ImageUploadActionItem
());
extraActionItems
.
add
(
new
AudioUploadActionItem
());
extraActionItems
.
add
(
new
VideoUploadActionItem
());
extraActionItems
.
add
(
new
FileUploadActionItem
());
}
private
void
scrollToLatestMessage
()
{
if
(
messageRecyclerView
!=
null
)
messageRecyclerView
.
scrollToPosition
(
0
);
}
protected
Snackbar
getUnreadCountIndicatorView
(
int
count
)
{
// TODO: replace with another custom View widget, not to hide message composer.
final
String
caption
=
getResources
().
getQuantityString
(
R
.
plurals
.
fmt_dialog_view_latest_message_title
,
count
,
count
);
return
Snackbar
.
make
(
rootView
,
caption
,
Snackbar
.
LENGTH_LONG
)
.
setAction
(
R
.
string
.
dialog_view_latest_message_action
,
view
->
scrollToLatestMessage
());
}
@Override
public
void
onDestroyView
()
{
RecyclerView
.
Adapter
adapter
=
messageRecyclerView
.
getAdapter
();
if
(
adapter
!=
null
)
adapter
.
unregisterAdapterDataObserver
(
recyclerViewAutoScrollManager
);
compositeDisposable
.
clear
();
if
(
autocompleteManager
!=
null
)
{
autocompleteManager
.
dispose
();
autocompleteManager
=
null
;
}
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"
);
return
true
;
}
private
void
setupSideMenu
()
{
View
sideMenu
=
rootView
.
findViewById
(
R
.
id
.
room_side_menu
);
sideMenu
.
findViewById
(
R
.
id
.
btn_users
).
setOnClickListener
(
view
->
{
UsersOfRoomDialogFragment
.
create
(
roomId
,
hostname
)
.
show
(
getFragmentManager
(),
"UsersOfRoomDialogFragment"
);
closeSideMenuIfNeeded
();
});
DrawerLayout
drawerLayout
=
rootView
.
findViewById
(
R
.
id
.
drawer_layout
);
if
(
drawerLayout
!=
null
&&
pane
!=
null
)
{
compositeDisposable
.
add
(
RxDrawerLayout
.
drawerOpen
(
drawerLayout
,
GravityCompat
.
END
)
.
compose
(
bindToLifecycle
())
.
subscribe
(
opened
->
{
try
{
Field
fieldSlidable
=
pane
.
getClass
().
getDeclaredField
(
"mCanSlide"
);
fieldSlidable
.
setAccessible
(
true
);
fieldSlidable
.
setBoolean
(
pane
,
!
opened
);
}
catch
(
Exception
exception
)
{
RCLog
.
w
(
exception
);
}
@Override
protected
int
getLayout
()
{
return
R
.
layout
.
fragment_room
;
}
@Override
protected
void
onSetupView
()
{
pane
=
getActivity
().
findViewById
(
R
.
id
.
sliding_pane
);
messageRecyclerView
=
rootView
.
findViewById
(
R
.
id
.
messageRecyclerView
);
messageListAdapter
=
new
MessageListAdapter
(
getContext
(),
hostname
);
messageRecyclerView
.
setAdapter
(
messageListAdapter
);
messageListAdapter
.
setOnItemClickListener
(
this
);
messageListAdapter
.
setOnItemLongClickListener
(
this
);
LinearLayoutManager
linearLayoutManager
=
new
LinearLayoutManager
(
getContext
(),
LinearLayoutManager
.
VERTICAL
,
true
);
messageRecyclerView
.
setLayoutManager
(
linearLayoutManager
);
recyclerViewAutoScrollManager
=
new
RecyclerViewAutoScrollManager
(
linearLayoutManager
)
{
@Override
protected
void
onAutoScrollMissed
()
{
if
(
newMessageIndicatorManager
!=
null
)
{
presenter
.
onUnreadCount
();
}
},
Logger:
:
report
)
);
}
}
private
void
setupSidebar
()
{
SlidingPaneLayout
subPane
=
getActivity
().
findViewById
(
R
.
id
.
sub_sliding_pane
);
RoomToolbar
toolbar
=
getActivity
().
findViewById
(
R
.
id
.
activity_main_toolbar
);
sidebarFragment
=
(
SidebarMainFragment
)
getActivity
().
getSupportFragmentManager
().
findFragmentById
(
R
.
id
.
sidebar_fragment_container
);
pane
.
setPanelSlideListener
(
new
SlidingPaneLayout
.
PanelSlideListener
()
{
@Override
public
void
onPanelSlide
(
View
view
,
float
v
)
{
messageFormManager
.
enableComposingText
(
false
);
sidebarFragment
.
clearSearchViewFocus
();
//Ref: ActionBarDrawerToggle#setProgress
toolbar
.
setNavigationIconProgress
(
v
);
}
@Override
public
void
onPanelOpened
(
View
view
)
{
toolbar
.
setNavigationIconVerticalMirror
(
true
);
}
@Override
public
void
onPanelClosed
(
View
view
)
{
messageFormManager
.
enableComposingText
(
true
);
toolbar
.
setNavigationIconVerticalMirror
(
false
);
subPane
.
closePane
();
closeUserActionContainer
();
}
});
toolbar
.
setNavigationOnClickListener
(
view
->
{
if
(
pane
.
isSlideable
()
&&
!
pane
.
isOpen
())
{
pane
.
openPane
();
}
});
}
public
void
closeUserActionContainer
()
{
sidebarFragment
.
closeUserActionContainer
();
}
private
boolean
closeSideMenuIfNeeded
()
{
DrawerLayout
drawerLayout
=
rootView
.
findViewById
(
R
.
id
.
drawer_layout
);
if
(
drawerLayout
!=
null
&&
drawerLayout
.
isDrawerOpen
(
GravityCompat
.
END
))
{
drawerLayout
.
closeDrawer
(
GravityCompat
.
END
);
return
true
;
}
return
false
;
}
private
void
setupMessageComposer
()
{
final
MessageFormLayout
messageFormLayout
=
rootView
.
findViewById
(
R
.
id
.
messageComposer
);
messageFormManager
=
new
MessageFormManager
(
messageFormLayout
,
this
::
showExtraActionSelectionDialog
);
messageFormManager
.
setSendMessageCallback
(
this
::
sendMessage
);
messageFormLayout
.
setEditTextCommitContentListener
(
this
::
onCommitContent
);
autocompleteManager
=
new
AutocompleteManager
(
rootView
.
findViewById
(
R
.
id
.
messageListRelativeLayout
));
autocompleteManager
.
registerSource
(
new
ChannelSource
(
new
AutocompleteChannelInteractor
(
roomRepository
,
new
RealmSpotlightRoomRepository
(
hostname
),
new
DeafultTempSpotlightRoomCaller
(
methodCallHelper
)
),
AndroidSchedulers
.
from
(
BackgroundLooper
.
get
()),
AndroidSchedulers
.
mainThread
()
)
);
Disposable
disposable
=
Single
.
zip
(
absoluteUrlHelper
.
getRocketChatAbsoluteUrl
(),
roomRepository
.
getById
(
roomId
).
first
(
Optional
.
absent
()),
Pair:
:
create
)
.
subscribe
(
pair
->
{
if
(
pair
.
first
.
isPresent
()
&&
pair
.
second
.
isPresent
())
{
autocompleteManager
.
registerSource
(
new
UserSource
(
new
AutocompleteUserInteractor
(
pair
.
second
.
get
(),
userRepository
,
new
RealmMessageRepository
(
hostname
),
new
RealmSpotlightUserRepository
(
hostname
),
new
DefaultTempSpotlightUserCaller
(
methodCallHelper
)
}
};
messageListAdapter
.
registerAdapterDataObserver
(
recyclerViewAutoScrollManager
);
scrollListener
=
new
LoadMoreScrollListener
(
linearLayoutManager
,
40
)
{
@Override
public
void
requestMoreItem
()
{
presenter
.
loadMoreMessages
();
}
};
messageRecyclerView
.
addOnScrollListener
(
scrollListener
);
messageRecyclerView
.
addOnScrollListener
(
new
RecyclerViewScrolledToBottomListener
(
linearLayoutManager
,
1
,
this
::
markAsReadIfNeeded
));
newMessageIndicatorManager
=
new
AbstractNewMessageIndicatorManager
()
{
@Override
protected
void
onShowIndicator
(
int
count
,
boolean
onlyAlreadyShown
)
{
if
((
onlyAlreadyShown
&&
unreadIndicator
!=
null
&&
unreadIndicator
.
isShown
())
||
!
onlyAlreadyShown
)
{
unreadIndicator
=
getUnreadCountIndicatorView
(
count
);
unreadIndicator
.
show
();
}
}
@Override
protected
void
onHideIndicator
()
{
if
(
unreadIndicator
!=
null
&&
unreadIndicator
.
isShown
())
{
unreadIndicator
.
dismiss
();
}
}
};
setupToolbar
();
setupSidebar
();
setupMessageComposer
();
setupMessageActions
();
}
private
void
setupMessageActions
()
{
extraActionItems
=
new
ArrayList
<>(
3
);
// fixed number as of now
extraActionItems
.
add
(
new
ImageUploadActionItem
());
extraActionItems
.
add
(
new
AudioUploadActionItem
());
extraActionItems
.
add
(
new
VideoUploadActionItem
());
}
private
void
scrollToLatestMessage
()
{
if
(
messageRecyclerView
!=
null
)
messageRecyclerView
.
scrollToPosition
(
0
);
}
protected
Snackbar
getUnreadCountIndicatorView
(
int
count
)
{
// TODO: replace with another custom View widget, not to hide message composer.
final
String
caption
=
getResources
().
getQuantityString
(
R
.
plurals
.
fmt_dialog_view_latest_message_title
,
count
,
count
);
return
Snackbar
.
make
(
rootView
,
caption
,
Snackbar
.
LENGTH_LONG
)
.
setAction
(
R
.
string
.
dialog_view_latest_message_action
,
view
->
scrollToLatestMessage
());
}
@Override
public
void
onDestroyView
()
{
RecyclerView
.
Adapter
adapter
=
messageRecyclerView
.
getAdapter
();
if
(
adapter
!=
null
)
adapter
.
unregisterAdapterDataObserver
(
recyclerViewAutoScrollManager
);
compositeDisposable
.
clear
();
if
(
autocompleteManager
!=
null
)
{
autocompleteManager
.
dispose
();
autocompleteManager
=
null
;
}
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"
);
return
true
;
}
private
void
setupToolbar
()
{
toolbar
=
getActivity
().
findViewById
(
R
.
id
.
activity_main_toolbar
);
toolbar
.
getMenu
().
clear
();
toolbar
.
inflateMenu
(
R
.
menu
.
menu_room
);
toolbar
.
setNavigationOnClickListener
(
view
->
{
if
(
pane
.
isSlideable
()
&&
!
pane
.
isOpen
())
{
pane
.
openPane
();
}
});
toolbar
.
setOnMenuItemClickListener
(
menuItem
->
{
switch
(
menuItem
.
getItemId
())
{
case
R
.
id
.
action_pinned_messages
:
showRoomListFragment
(
R
.
id
.
action_pinned_messages
);
break
;
case
R
.
id
.
action_favorite_messages
:
showRoomListFragment
(
R
.
id
.
action_favorite_messages
);
break
;
// case R.id.action_file_list:
// showRoomListFragment(R.id.action_file_list);
// break;
case
R
.
id
.
action_member_list
:
showRoomListFragment
(
R
.
id
.
action_member_list
);
break
;
default
:
return
super
.
onOptionsItemSelected
(
menuItem
);
}
return
true
;
});
}
private
void
setupSidebar
()
{
SlidingPaneLayout
subPane
=
getActivity
().
findViewById
(
R
.
id
.
sub_sliding_pane
);
sidebarFragment
=
(
SidebarMainFragment
)
getActivity
().
getSupportFragmentManager
().
findFragmentById
(
R
.
id
.
sidebar_fragment_container
);
pane
.
setPanelSlideListener
(
new
SlidingPaneLayout
.
PanelSlideListener
()
{
@Override
public
void
onPanelSlide
(
View
view
,
float
v
)
{
messageFormManager
.
enableComposingText
(
false
);
sidebarFragment
.
clearSearchViewFocus
();
//Ref: ActionBarDrawerToggle#setProgress
toolbar
.
setNavigationIconProgress
(
v
);
}
@Override
public
void
onPanelOpened
(
View
view
)
{
toolbar
.
setNavigationIconVerticalMirror
(
true
);
}
@Override
public
void
onPanelClosed
(
View
view
)
{
messageFormManager
.
enableComposingText
(
true
);
toolbar
.
setNavigationIconVerticalMirror
(
false
);
subPane
.
closePane
();
closeUserActionContainer
();
}
});
}
public
void
closeUserActionContainer
()
{
sidebarFragment
.
closeUserActionContainer
();
}
private
void
setupMessageComposer
()
{
final
MessageFormLayout
messageFormLayout
=
rootView
.
findViewById
(
R
.
id
.
messageComposer
);
messageFormManager
=
new
MessageFormManager
(
messageFormLayout
,
this
::
showExtraActionSelectionDialog
);
messageFormManager
.
setSendMessageCallback
(
this
::
sendMessage
);
messageFormLayout
.
setEditTextCommitContentListener
(
this
::
onCommitContent
);
autocompleteManager
=
new
AutocompleteManager
(
rootView
.
findViewById
(
R
.
id
.
messageListRelativeLayout
));
autocompleteManager
.
registerSource
(
new
ChannelSource
(
new
AutocompleteChannelInteractor
(
roomRepository
,
new
RealmSpotlightRoomRepository
(
hostname
),
new
DeafultTempSpotlightRoomCaller
(
methodCallHelper
)
),
pair
.
first
.
get
(),
RocketChatUserStatusProvider
.
INSTANCE
,
AndroidSchedulers
.
from
(
BackgroundLooper
.
get
()),
AndroidSchedulers
.
mainThread
()
)
)
);
Disposable
disposable
=
Single
.
zip
(
absoluteUrlHelper
.
getRocketChatAbsoluteUrl
(),
roomRepository
.
getById
(
roomId
).
first
(
Optional
.
absent
()),
Pair:
:
create
)
.
subscribe
(
pair
->
{
if
(
pair
.
first
.
isPresent
()
&&
pair
.
second
.
isPresent
())
{
autocompleteManager
.
registerSource
(
new
UserSource
(
new
AutocompleteUserInteractor
(
pair
.
second
.
get
(),
userRepository
,
new
RealmMessageRepository
(
hostname
),
new
RealmSpotlightUserRepository
(
hostname
),
new
DefaultTempSpotlightUserCaller
(
methodCallHelper
)
),
pair
.
first
.
get
(),
RocketChatUserStatusProvider
.
INSTANCE
,
AndroidSchedulers
.
from
(
BackgroundLooper
.
get
()),
AndroidSchedulers
.
mainThread
()
)
);
}
},
throwable
->
{
}
);
}
},
Logger:
:
report
compositeDisposable
.
add
(
disposable
);
autocompleteManager
.
bindTo
(
messageFormLayout
.
getEditText
(),
messageFormLayout
);
}
compositeDisposable
.
add
(
disposable
);
autocompleteManager
.
bindTo
(
messageFormLayout
.
getEditText
(),
messageFormLayout
);
}
@Override
public
void
onActivityResult
(
int
requestCode
,
int
resultCode
,
Intent
data
)
{
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
);
if
(
requestCode
!=
AbstractUploadActionItem
.
RC_UPL
||
resultCode
!=
Activity
.
RESULT_OK
)
{
return
;
}
if
(
data
==
null
||
data
.
getData
()
==
null
)
{
return
;
}
uploadFile
(
data
.
getData
());
}
private
void
uploadFile
(
Uri
uri
)
{
String
uplId
=
new
FileUploadHelper
(
getContext
(),
RealmStore
.
get
(
hostname
))
.
requestUploading
(
roomId
,
uri
);
if
(!
TextUtils
.
isEmpty
(
uplId
))
{
FileUploadProgressDialogFragment
.
create
(
hostname
,
roomId
,
uplId
)
.
show
(
getFragmentManager
(),
"FileUploadProgressDialogFragment"
);
}
else
{
// show error.
}
}
private
void
markAsReadIfNeeded
()
{
presenter
.
onMarkAsRead
();
}
@Override
public
void
onResume
()
{
super
.
onResume
();
presenter
.
bindView
(
this
);
closeSideMenuIfNeeded
();
}
@Override
public
void
onPause
()
{
presenter
.
release
();
super
.
onPause
();
}
private
void
showExtraActionSelectionDialog
()
{
final
DialogFragment
fragment
=
ExtraActionPickerDialogFragment
.
create
(
new
ArrayList
<>(
extraActionItems
));
fragment
.
setTargetFragment
(
this
,
DIALOG_ID
);
fragment
.
show
(
getFragmentManager
(),
"ExtraActionPickerDialogFragment"
);
}
@Override
public
void
onItemSelected
(
int
itemId
)
{
for
(
AbstractExtraActionItem
extraActionItem
:
extraActionItems
)
{
if
(
extraActionItem
.
getItemId
()
==
itemId
)
{
RoomFragmentPermissionsDispatcher
.
onExtraActionSelectedWithCheck
(
RoomFragment
.
this
,
extraActionItem
);
return
;
}
}
}
@Override
public
boolean
onBackPressed
()
{
if
(
edittingMessage
!=
null
)
{
edittingMessage
=
null
;
messageFormManager
.
clearComposingText
();
return
true
;
}
return
closeSideMenuIfNeeded
();
}
@Override
public
void
onRequestPermissionsResult
(
int
requestCode
,
@NonNull
String
[]
permissions
,
@NonNull
int
[]
grantResults
)
{
super
.
onRequestPermissionsResult
(
requestCode
,
permissions
,
grantResults
);
RoomFragmentPermissionsDispatcher
.
onRequestPermissionsResult
(
this
,
requestCode
,
grantResults
);
}
@NeedsPermission
(
Manifest
.
permission
.
READ_EXTERNAL_STORAGE
)
protected
void
onExtraActionSelected
(
MessageExtraActionBehavior
action
)
{
action
.
handleItemSelectedOnFragment
(
RoomFragment
.
this
);
}
private
boolean
onCommitContent
(
InputContentInfoCompat
inputContentInfo
,
int
flags
,
Bundle
opts
,
String
[]
supportedMimeTypes
)
{
boolean
supported
=
false
;
for
(
final
String
mimeType
:
supportedMimeTypes
)
{
if
(
inputContentInfo
.
getDescription
().
hasMimeType
(
mimeType
))
{
supported
=
true
;
break
;
}
}
if
(!
supported
)
{
return
false
;
}
if
(
BuildCompat
.
isAtLeastNMR1
()
&&
(
flags
&
InputConnectionCompat
.
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
)
!=
0
)
{
try
{
inputContentInfo
.
requestPermission
();
}
catch
(
Exception
e
)
{
Logger
.
report
(
e
);
return
false
;
}
@Override
public
void
onActivityResult
(
int
requestCode
,
int
resultCode
,
Intent
data
)
{
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
);
if
(
requestCode
!=
AbstractUploadActionItem
.
RC_UPL
||
resultCode
!=
Activity
.
RESULT_OK
)
{
return
;
}
if
(
data
==
null
||
data
.
getData
()
==
null
)
{
return
;
}
uploadFile
(
data
.
getData
());
}
Uri
linkUri
=
inputContentInfo
.
getLinkUri
();
if
(
linkUri
==
null
)
{
return
false
;
private
void
uploadFile
(
Uri
uri
)
{
String
uplId
=
new
FileUploadHelper
(
getContext
(),
RealmStore
.
get
(
hostname
))
.
requestUploading
(
roomId
,
uri
);
if
(!
TextUtils
.
isEmpty
(
uplId
))
{
FileUploadProgressDialogFragment
.
create
(
hostname
,
roomId
,
uplId
)
.
show
(
getFragmentManager
(),
"FileUploadProgressDialogFragment"
);
}
else
{
// show error.
}
}
sendMessage
(
linkUri
.
toString
());
private
void
markAsReadIfNeeded
()
{
presenter
.
onMarkAsRead
();
}
try
{
inputContentInfo
.
releasePermission
();
}
catch
(
Exception
e
)
{
Logger
.
report
(
e
);
@Override
public
void
onResume
()
{
super
.
onResume
();
presenter
.
bindView
(
this
);
}
return
true
;
}
@Override
public
void
onPause
()
{
presenter
.
release
();
super
.
onPause
();
}
private
void
sendMessage
(
String
messageText
)
{
if
(
edittingMessage
==
null
)
{
presenter
.
sendMessage
(
messageText
);
}
else
{
presenter
.
updateMessage
(
edittingMessage
,
messageText
);
private
void
showExtraActionSelectionDialog
(
)
{
final
DialogFragment
fragment
=
ExtraActionPickerDialogFragment
.
create
(
new
ArrayList
<>(
extraActionItems
)
);
fragment
.
setTargetFragment
(
this
,
DIALOG_ID
);
fragment
.
show
(
getFragmentManager
(),
"ExtraActionPickerDialogFragment"
);
}
}
@Override
public
void
setupWith
(
RocketChatAbsoluteUrl
rocketChatAbsoluteUrl
)
{
messageListAdapter
.
setAbsoluteUrl
(
rocketChatAbsoluteUrl
);
}
@Override
public
void
onItemSelected
(
int
itemId
)
{
for
(
AbstractExtraActionItem
extraActionItem
:
extraActionItems
)
{
if
(
extraActionItem
.
getItemId
()
==
itemId
)
{
RoomFragmentPermissionsDispatcher
.
onExtraActionSelectedWithCheck
(
RoomFragment
.
this
,
extraActionItem
);
return
;
}
}
}
@Override
public
void
render
(
Room
room
)
{
setToolbarTitle
(
room
.
getName
());
@Override
public
boolean
onBackPressed
()
{
if
(
edittingMessage
!=
null
)
{
edittingMessage
=
null
;
messageFormManager
.
clearComposingText
();
}
return
false
;
}
boolean
unreadMessageExists
=
room
.
isAlert
();
if
(
newMessageIndicatorManager
!=
null
&&
previousUnreadMessageExists
&&
!
unreadMessageExists
)
{
newMessageIndicatorManager
.
reset
();
@Override
public
void
onRequestPermissionsResult
(
int
requestCode
,
@NonNull
String
[]
permissions
,
@NonNull
int
[]
grantResults
)
{
super
.
onRequestPermissionsResult
(
requestCode
,
permissions
,
grantResults
);
RoomFragmentPermissionsDispatcher
.
onRequestPermissionsResult
(
this
,
requestCode
,
grantResults
);
}
previousUnreadMessageExists
=
unreadMessageExists
;
if
(
room
.
isChannel
())
{
showToolbarPublicChannelIcon
();
return
;
@NeedsPermission
(
Manifest
.
permission
.
READ_EXTERNAL_STORAGE
)
protected
void
onExtraActionSelected
(
MessageExtraActionBehavior
action
)
{
action
.
handleItemSelectedOnFragment
(
RoomFragment
.
this
)
;
}
if
(
room
.
isPrivate
())
{
showToolbarPrivateChannelIcon
();
private
boolean
onCommitContent
(
InputContentInfoCompat
inputContentInfo
,
int
flags
,
Bundle
opts
,
String
[]
supportedMimeTypes
)
{
boolean
supported
=
false
;
for
(
final
String
mimeType
:
supportedMimeTypes
)
{
if
(
inputContentInfo
.
getDescription
().
hasMimeType
(
mimeType
))
{
supported
=
true
;
break
;
}
}
if
(!
supported
)
{
return
false
;
}
if
(
BuildCompat
.
isAtLeastNMR1
()
&&
(
flags
&
InputConnectionCompat
.
INPUT_CONTENT_GRANT_READ_URI_PERMISSION
)
!=
0
)
{
try
{
inputContentInfo
.
requestPermission
();
}
catch
(
Exception
e
)
{
return
false
;
}
}
Uri
linkUri
=
inputContentInfo
.
getLinkUri
();
if
(
linkUri
==
null
)
{
return
false
;
}
sendMessage
(
linkUri
.
toString
());
try
{
inputContentInfo
.
releasePermission
();
}
catch
(
Exception
e
)
{
}
return
true
;
}
private
void
sendMessage
(
String
messageText
)
{
if
(
edittingMessage
==
null
)
{
presenter
.
sendMessage
(
messageText
);
}
else
{
presenter
.
updateMessage
(
edittingMessage
,
messageText
);
}
}
@Override
public
void
setupWith
(
RocketChatAbsoluteUrl
rocketChatAbsoluteUrl
)
{
token
=
rocketChatAbsoluteUrl
.
getToken
();
userId
=
rocketChatAbsoluteUrl
.
getUserId
();
messageListAdapter
.
setAbsoluteUrl
(
rocketChatAbsoluteUrl
);
}
@Override
public
void
render
(
Room
room
)
{
roomType
=
room
.
getType
();
setToolbarTitle
(
room
.
getName
());
boolean
unreadMessageExists
=
room
.
isAlert
();
if
(
newMessageIndicatorManager
!=
null
&&
previousUnreadMessageExists
&&
!
unreadMessageExists
)
{
newMessageIndicatorManager
.
reset
();
}
previousUnreadMessageExists
=
unreadMessageExists
;
if
(
room
.
isChannel
())
{
showToolbarPublicChannelIcon
();
return
;
}
if
(
room
.
isPrivate
())
{
showToolbarPrivateChannelIcon
();
}
if
(
room
.
isLivechat
())
{
showToolbarLivechatChannelIcon
();
}
}
if
(
room
.
isLivechat
())
{
showToolbarLivechatChannelIcon
();
@Override
public
void
showUserStatus
(
User
user
)
{
showToolbarUserStatuslIcon
(
user
.
getStatus
());
}
}
@Override
public
void
showUserStatus
(
User
user
)
{
showToolbarUserStatuslIcon
(
user
.
getStatus
());
}
@Override
public
void
updateHistoryState
(
boolean
hasNext
,
boolean
isLoaded
)
{
if
(
messageRecyclerView
==
null
||
!(
messageRecyclerView
.
getAdapter
()
instanceof
MessageListAdapter
))
{
return
;
}
@Override
public
void
updateHistoryState
(
boolean
hasNext
,
boolean
isLoaded
)
{
if
(
messageRecyclerView
==
null
||
!(
messageRecyclerView
.
getAdapter
()
instanceof
MessageListAdapter
))
{
return
;
MessageListAdapter
adapter
=
(
MessageListAdapter
)
messageRecyclerView
.
getAdapter
();
if
(
isLoaded
)
{
scrollListener
.
setLoadingDone
();
}
adapter
.
updateFooter
(
hasNext
,
isLoaded
);
}
MessageListAdapter
adapter
=
(
MessageListAdapter
)
messageRecyclerView
.
getAdapter
();
if
(
isLoaded
)
{
scrollListener
.
setLoadingDone
();
@Override
public
void
onMessageSendSuccessfully
()
{
scrollToLatestMessage
();
messageFormManager
.
onMessageSend
();
edittingMessage
=
null
;
}
adapter
.
updateFooter
(
hasNext
,
isLoaded
);
}
@Override
public
void
onMessageSendSuccessfully
()
{
scrollToLatestMessage
();
messageFormManager
.
onMessageSend
();
edittingMessage
=
null
;
}
@Override
public
void
showUnreadCount
(
int
count
)
{
newMessageIndicatorManager
.
updateNewMessageCount
(
count
);
}
@Override
public
void
showUnreadCount
(
int
count
)
{
newMessageIndicatorManager
.
updateNewMessageCount
(
count
);
}
@Override
public
void
showMessages
(
List
<
Message
>
messages
)
{
if
(
messageListAdapter
==
null
)
{
return
;
}
messageListAdapter
.
updateData
(
messages
);
}
@Override
public
void
showMessages
(
List
<
Message
>
messages
)
{
if
(
messageListAdapter
==
null
)
{
return
;
@Override
public
void
showMessageSendFailure
(
Message
message
)
{
new
AlertDialog
.
Builder
(
getContext
())
.
setPositiveButton
(
R
.
string
.
resend
,
(
dialog
,
which
)
->
presenter
.
resendMessage
(
message
))
.
setNegativeButton
(
android
.
R
.
string
.
cancel
,
null
)
.
setNeutralButton
(
R
.
string
.
discard
,
(
dialog
,
which
)
->
presenter
.
deleteMessage
(
message
))
.
show
();
}
messageListAdapter
.
updateData
(
messages
);
}
@Override
public
void
showMessageSendFailure
(
Message
message
)
{
new
AlertDialog
.
Builder
(
getContext
())
.
setPositiveButton
(
R
.
string
.
resend
,
(
dialog
,
which
)
->
presenter
.
resendMessage
(
message
))
.
setNegativeButton
(
android
.
R
.
string
.
cancel
,
null
)
.
setNeutralButton
(
R
.
string
.
discard
,
(
dialog
,
which
)
->
presenter
.
deleteMessage
(
message
))
.
show
();
}
@Override
public
void
autoloadImages
()
{
messageListAdapter
.
setAutoloadImages
(
true
);
}
@Override
public
void
autol
oadImages
()
{
messageListAdapter
.
setAutoloadImages
(
tru
e
);
}
@Override
public
void
manualL
oadImages
()
{
messageListAdapter
.
setAutoloadImages
(
fals
e
);
}
@Override
public
void
manualLoadImages
()
{
messageListAdapter
.
setAutoloadImages
(
false
);
}
private
void
onEditMessage
(
Message
message
)
{
edittingMessage
=
message
;
messageFormManager
.
setEditMessage
(
message
.
getMessage
()
);
}
private
void
onEditMessage
(
Message
message
)
{
edittingMessage
=
message
;
messageFormManager
.
setEditMessage
(
message
.
getMessage
());
}
private
void
showRoomListFragment
(
int
actionId
)
{
Intent
intent
=
new
Intent
(
getActivity
(),
RoomActivity
.
class
).
putExtra
(
"actionId"
,
actionId
)
.
putExtra
(
"roomId"
,
roomId
)
.
putExtra
(
"roomType"
,
roomType
)
.
putExtra
(
"hostname"
,
hostname
)
.
putExtra
(
"token"
,
token
)
.
putExtra
(
"userId"
,
userId
);
startActivity
(
intent
);
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/fragment/chatroom/dialog/UsersOfRoomDialogFragment.java
deleted
100644 → 0
View file @
16052e46
package
chat
.
rocket
.
android
.
fragment
.
chatroom
.
dialog
;
import
android.os.Bundle
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
android.support.v7.widget.GridLayoutManager
;
import
android.support.v7.widget.RecyclerView
;
import
android.view.View
;
import
android.widget.TextView
;
import
com.hadisatrio.optional.Optional
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.CompositeDisposable
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.android.BackgroundLooper
;
import
chat.rocket.android.R
;
import
chat.rocket.android.fragment.chatroom.RocketChatAbsoluteUrl
;
import
chat.rocket.android.helper.AbsoluteUrlHelper
;
import
chat.rocket.android.helper.LogIfError
;
import
chat.rocket.android.helper.Logger
;
import
chat.rocket.android.layouthelper.chatroom.dialog.RoomUserAdapter
;
import
chat.rocket.android.log.RCLog
;
import
chat.rocket.core.SyncState
;
import
chat.rocket.core.interactors.SessionInteractor
;
import
chat.rocket.persistence.realm.models.internal.GetUsersOfRoomsProcedure
;
import
chat.rocket.persistence.realm.RealmObjectObserver
;
import
chat.rocket.android.service.ConnectivityManager
;
import
chat.rocket.persistence.realm.repositories.RealmServerInfoRepository
;
import
chat.rocket.persistence.realm.repositories.RealmSessionRepository
;
import
chat.rocket.persistence.realm.repositories.RealmUserRepository
;
/**
* Dialog to show members in a room.
*/
public
class
UsersOfRoomDialogFragment
extends
AbstractChatRoomDialogFragment
{
private
String
hostname
;
private
RealmObjectObserver
<
GetUsersOfRoomsProcedure
>
procedureObserver
;
private
int
previousSyncState
;
private
CompositeDisposable
compositeDisposable
=
new
CompositeDisposable
();
public
UsersOfRoomDialogFragment
()
{
}
/**
* create UsersOfRoomDialogFragment with required parameters.
*/
public
static
UsersOfRoomDialogFragment
create
(
String
roomId
,
String
hostname
)
{
Bundle
args
=
new
Bundle
();
args
.
putString
(
"hostname"
,
hostname
);
args
.
putString
(
"roomId"
,
roomId
);
UsersOfRoomDialogFragment
fragment
=
new
UsersOfRoomDialogFragment
();
fragment
.
setArguments
(
args
);
return
fragment
;
}
@Override
public
void
onCreate
(
@Nullable
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
procedureObserver
=
realmHelper
.
createObjectObserver
(
realm
->
realm
.
where
(
GetUsersOfRoomsProcedure
.
class
).
equalTo
(
"roomId"
,
roomId
))
.
setOnUpdateListener
(
this
::
onUpdateGetUsersOfRoomProcedure
);
previousSyncState
=
SyncState
.
NOT_SYNCED
;
if
(
savedInstanceState
==
null
)
{
requestGetUsersOfRoom
();
}
}
@Override
protected
void
handleArgs
(
@NonNull
Bundle
args
)
{
super
.
handleArgs
(
args
);
hostname
=
args
.
getString
(
"hostname"
);
}
@Override
protected
int
getLayout
()
{
return
R
.
layout
.
dialog_users_of_room
;
}
@Override
protected
void
onSetupDialog
()
{
AbsoluteUrlHelper
absoluteUrlHelper
=
new
AbsoluteUrlHelper
(
hostname
,
new
RealmServerInfoRepository
(),
new
RealmUserRepository
(
hostname
),
new
SessionInteractor
(
new
RealmSessionRepository
(
hostname
))
);
compositeDisposable
.
add
(
absoluteUrlHelper
.
getRocketChatAbsoluteUrl
()
.
subscribeOn
(
AndroidSchedulers
.
from
(
BackgroundLooper
.
get
()))
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
subscribe
(
this
::
setupView
,
Logger:
:
report
)
);
}
private
void
setupView
(
Optional
<
RocketChatAbsoluteUrl
>
rocketChatAbsoluteUrlOptional
)
{
compositeDisposable
.
clear
();
if
(!
rocketChatAbsoluteUrlOptional
.
isPresent
())
{
return
;
}
RecyclerView
recyclerView
=
(
RecyclerView
)
getDialog
().
findViewById
(
R
.
id
.
recyclerview
);
recyclerView
.
setLayoutManager
(
new
GridLayoutManager
(
getContext
(),
2
));
recyclerView
.
setAdapter
(
new
RoomUserAdapter
(
getContext
(),
realmHelper
,
rocketChatAbsoluteUrlOptional
.
get
(),
hostname
));
}
private
void
requestGetUsersOfRoom
()
{
realmHelper
.
executeTransaction
(
realm
->
{
realm
.
createOrUpdateObjectFromJson
(
GetUsersOfRoomsProcedure
.
class
,
new
JSONObject
()
.
put
(
"roomId"
,
roomId
)
.
put
(
"syncstate"
,
SyncState
.
NOT_SYNCED
)
.
put
(
"showAll"
,
true
));
return
null
;
}).
onSuccessTask
(
task
->
{
ConnectivityManager
.
getInstance
(
getContext
().
getApplicationContext
())
.
keepAliveServer
();
return
task
;
}).
continueWith
(
new
LogIfError
());
}
@Override
public
void
onResume
()
{
super
.
onResume
();
procedureObserver
.
sub
();
}
@Override
public
void
onPause
()
{
procedureObserver
.
unsub
();
super
.
onPause
();
}
private
void
onUpdateGetUsersOfRoomProcedure
(
GetUsersOfRoomsProcedure
procedure
)
{
if
(
procedure
==
null
)
{
return
;
}
int
syncState
=
procedure
.
getSyncState
();
if
(
previousSyncState
!=
syncState
)
{
onSyncStateUpdated
(
syncState
);
previousSyncState
=
syncState
;
}
if
(
syncState
==
SyncState
.
SYNCED
)
{
onRenderTotalCount
(
procedure
.
getTotal
());
try
{
JSONArray
array
=
new
JSONArray
(
procedure
.
getRecords
());
ArrayList
<
String
>
users
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
array
.
length
();
i
++)
{
Object
userObject
=
array
.
get
(
i
);
if
(
userObject
instanceof
JSONObject
)
{
JSONObject
user
=
(
JSONObject
)
userObject
;
users
.
add
(
user
.
getString
(
"username"
));
}
else
{
users
.
add
((
String
)
userObject
);
}
}
onRenderUsers
(
users
);
}
catch
(
JSONException
exception
)
{
RCLog
.
e
(
exception
);
}
}
}
/**
* called only if prevSyncstate != newSyncstate.
*/
private
void
onSyncStateUpdated
(
int
newSyncState
)
{
boolean
show
=
newSyncState
==
SyncState
.
NOT_SYNCED
||
newSyncState
==
SyncState
.
SYNCING
;
getDialog
().
findViewById
(
R
.
id
.
waiting
).
setVisibility
(
show
?
View
.
VISIBLE
:
View
.
GONE
);
}
/**
* called only if syncstate = SYNCED.
*/
private
void
onRenderTotalCount
(
long
total
)
{
TextView
userCount
=
(
TextView
)
getDialog
().
findViewById
(
R
.
id
.
room_user_count
);
userCount
.
setText
(
getResources
().
getQuantityString
(
R
.
plurals
.
fmt_room_user_count
,
(
int
)
total
,
total
));
}
/**
* called only if syncstate = SYNCED.
*/
private
void
onRenderUsers
(
List
<
String
>
usernames
)
{
RecyclerView
recyclerView
=
(
RecyclerView
)
getDialog
().
findViewById
(
R
.
id
.
recyclerview
);
if
(
recyclerView
!=
null
&&
recyclerView
.
getAdapter
()
instanceof
RoomUserAdapter
)
{
((
RoomUserAdapter
)
recyclerView
.
getAdapter
()).
setUsernames
(
usernames
);
}
}
}
app/src/main/java/chat/rocket/android/fragment/chatroom/list/RoomListContract.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.fragment.chatroom.list
import
chat.rocket.core.models.Message
import
chat.rocket.core.models.User
/**
* Created by Filipe de Lima Brito (filipedelimabrito@gmail.com) on 9/22/17.
*/
interface
RoomListContract
{
interface
View
{
/**
* Shows a pinned message list of a room.
*
* @param dataSet The pinned message data set to show.
* @param total The total number of pinned messages.
*/
fun
showPinnedMessages
(
dataSet
:
ArrayList
<
Message
>,
total
:
String
)
/**
* Shows a favorite message list of a room.
*
* @param dataSet The favorite message data set to show.
* @param total The total number of favorite messages.
*/
fun
showFavoriteMessages
(
dataSet
:
ArrayList
<
Message
>,
total
:
String
)
/**
* Shows a file list of a room.
*
* @param dataSet The file data set to show.
* @param total The total number of files.
*/
fun
showFileList
(
dataSet
:
ArrayList
<
String
>,
total
:
String
)
/**
* Shows a list of members of a room.
*
* @param dataSet The member data set to show.
* @param total The total number of members.
*/
fun
showMemberList
(
dataSet
:
ArrayList
<
User
>,
total
:
String
)
/**
* Shows a message (e.g. An error or successful message after a request).
*
* @param message The message to show.
*/
fun
showMessage
(
message
:
String
)
/**
* Shows a waiting view whenever a (long) process is taken.
*
* @param shouldShow The Boolean value that indicates whether the view should be showed.
*/
fun
showWaitingView
(
shouldShow
:
Boolean
)
}
interface
Presenter
{
/**
* Requests the pinned messages of a room.
*
* @param roomId The room ID to process the request.
* @param roomType The room type to process the request.
* @param hostname The server hostname to process the request.
* @param token The token to process the request.
* @param userId The user ID to process the request.
* @param offset The offset to process the request.
*/
fun
requestPinnedMessages
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
Int
)
/**
* Requests the favorite messages of a room.
*
* @param roomId The room ID to process the request.
* @param roomType The room type to process the request.
* @param hostname The server hostname to process the request.
* @param token The token to process the request.
* @param userId The user ID to process the request.
* @param offset The offset to process the request.
*/
fun
requestFavoriteMessages
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
Int
)
/**
* Requests the file list of a room.
*
* @param roomId The room ID to process the request.
* @param roomType The room type to process the request.
* @param hostname The server hostname to process the request.
* @param token The token to process the request.
* @param userId The user ID to process the request.
* @param offset The offset to process the request.
*/
fun
requestFileList
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
Int
)
/**
* Requests the member list of a room.
*
* @param roomId The room ID to process the request.
* @param roomType The room type to process the request.
* @param hostname The server hostname to process the request.
* @param token The token to process the request.
* @param userId The user ID to process the request.
* @param offset The offset to process the request.
*/
fun
requestMemberList
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
Int
)
/**
* Immediately cancels any running request.
*/
fun
cancelRequest
()
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/fragment/chatroom/list/RoomListFragment.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.fragment.chatroom.list
import
android.os.Bundle
import
android.support.v4.app.Fragment
import
android.support.v7.widget.LinearLayoutManager
import
android.support.v7.widget.RecyclerView
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
chat.rocket.android.R
import
chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import
chat.rocket.android.layouthelper.chatroom.list.RoomMemberListAdapter
import
chat.rocket.android.layouthelper.chatroom.list.RoomMessagesAdapter
import
chat.rocket.core.models.Message
import
chat.rocket.core.models.User
import
kotlinx.android.synthetic.main.fragment_room_list.*
import
java.util.*
/**
* Created by Filipe de Lima Brito (filipedelimabrito@gmail.com) on 9/22/17.
*/
class
RoomListFragment
:
Fragment
(),
RoomListContract
.
View
{
companion
object
{
fun
newInstance
(
actionId
:
Int
,
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
):
RoomListFragment
{
val
args
=
Bundle
()
args
.
putInt
(
"actionId"
,
actionId
)
args
.
putString
(
"roomId"
,
roomId
)
args
.
putString
(
"roomType"
,
roomType
)
args
.
putString
(
"hostname"
,
hostname
)
args
.
putString
(
"token"
,
token
)
args
.
putString
(
"userId"
,
userId
)
val
roomFileListDialogFragment
=
RoomListFragment
()
roomFileListDialogFragment
.
arguments
=
args
return
roomFileListDialogFragment
}
}
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
activity
.
title
=
""
actionId
=
arguments
.
getInt
(
"actionId"
)
roomId
=
arguments
.
getString
(
"roomId"
)
roomType
=
arguments
.
getString
(
"roomType"
)
hostname
=
arguments
.
getString
(
"hostname"
)
token
=
arguments
.
getString
(
"token"
)
userId
=
arguments
.
getString
(
"userId"
)
}
override
fun
onCreateView
(
inflater
:
LayoutInflater
?,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?):
View
?
=
inflater
?.
inflate
(
R
.
layout
.
fragment_room_list
,
container
,
false
)
override
fun
onViewCreated
(
view
:
View
?,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
presenter
=
RoomListPresenter
(
context
,
this
)
}
override
fun
onResume
()
{
super
.
onResume
()
if
(!
isDataRequested
)
{
requestData
(
0
)
isDataRequested
=
true
}
}
override
fun
onPause
()
{
super
.
onPause
()
presenter
.
cancelRequest
()
}
private
fun
requestData
(
offset
:
Int
)
{
when
(
actionId
)
{
R
.
id
.
action_pinned_messages
->
{
presenter
.
requestPinnedMessages
(
roomId
,
roomType
,
hostname
,
token
,
userId
,
offset
)
}
R
.
id
.
action_favorite_messages
->
{
presenter
.
requestFavoriteMessages
(
roomId
,
roomType
,
hostname
,
token
,
userId
,
offset
)
}
R
.
id
.
action_member_list
->
{
presenter
.
requestMemberList
(
roomId
,
roomType
,
hostname
,
token
,
userId
,
offset
)
}
}
}
override
fun
showPinnedMessages
(
dataSet
:
ArrayList
<
Message
>,
total
:
String
)
{
activity
.
title
=
getString
(
R
.
string
.
fragment_room_list_pinned_message_title
,
total
)
if
(
recyclerView
.
adapter
==
null
)
{
recyclerView
.
adapter
=
RoomMessagesAdapter
(
dataSet
,
hostname
,
context
)
val
linearLayoutManager
=
LinearLayoutManager
(
context
,
LinearLayoutManager
.
VERTICAL
,
false
)
recyclerView
.
layoutManager
=
linearLayoutManager
if
(
dataSet
.
size
>=
50
)
{
recyclerView
.
addOnScrollListener
(
object
:
EndlessRecyclerViewScrollListener
(
linearLayoutManager
)
{
override
fun
onLoadMore
(
page
:
Int
,
totalItemsCount
:
Int
,
recyclerView
:
RecyclerView
?)
{
loadNextDataFromApi
(
page
)
}
})
}
}
else
{
(
recyclerView
.
adapter
as
RoomMessagesAdapter
).
addDataSet
(
dataSet
)
}
}
override
fun
showFavoriteMessages
(
dataSet
:
ArrayList
<
Message
>,
total
:
String
)
{
activity
.
title
=
getString
(
R
.
string
.
fragment_room_list_favorite_message_title
,
total
)
if
(
recyclerView
.
adapter
==
null
)
{
recyclerView
.
adapter
=
RoomMessagesAdapter
(
dataSet
,
hostname
,
context
)
val
linearLayoutManager
=
LinearLayoutManager
(
context
,
LinearLayoutManager
.
VERTICAL
,
false
)
recyclerView
.
layoutManager
=
linearLayoutManager
if
(
dataSet
.
size
>=
50
)
{
recyclerView
.
addOnScrollListener
(
object
:
EndlessRecyclerViewScrollListener
(
linearLayoutManager
)
{
override
fun
onLoadMore
(
page
:
Int
,
totalItemsCount
:
Int
,
recyclerView
:
RecyclerView
?)
{
loadNextDataFromApi
(
page
)
}
})
}
}
else
{
(
recyclerView
.
adapter
as
RoomMessagesAdapter
).
addDataSet
(
dataSet
)
}
}
// TODO (after REST api fixes)
override
fun
showFileList
(
dataSet
:
ArrayList
<
String
>,
total
:
String
)
{}
override
fun
showMemberList
(
dataSet
:
ArrayList
<
User
>,
total
:
String
)
{
activity
.
title
=
getString
(
R
.
string
.
fragment_room_list_member_list_title
,
total
)
if
(
recyclerView
.
adapter
==
null
)
{
recyclerView
.
adapter
=
RoomMemberListAdapter
(
dataSet
,
hostname
,
context
)
val
linearLayoutManager
=
LinearLayoutManager
(
context
,
LinearLayoutManager
.
VERTICAL
,
false
)
recyclerView
.
layoutManager
=
linearLayoutManager
if
(
dataSet
.
size
>=
50
)
{
recyclerView
.
addOnScrollListener
(
object
:
EndlessRecyclerViewScrollListener
(
linearLayoutManager
)
{
override
fun
onLoadMore
(
page
:
Int
,
totalItemsCount
:
Int
,
recyclerView
:
RecyclerView
?)
{
loadNextDataFromApi
(
page
)
}
})
}
}
else
{
(
recyclerView
.
adapter
as
RoomMemberListAdapter
).
addDataSet
(
dataSet
)
}
}
override
fun
showMessage
(
message
:
String
)
{
messageText
.
text
=
message
messageText
.
visibility
=
View
.
VISIBLE
}
override
fun
showWaitingView
(
shouldShow
:
Boolean
)
{
if
(
shouldShow
)
{
waitingView
.
visibility
=
View
.
VISIBLE
}
else
{
waitingView
.
visibility
=
View
.
GONE
}
}
private
fun
loadNextDataFromApi
(
page
:
Int
)
{
requestData
(
page
*
50
)
}
private
var
actionId
:
Int
=
0
private
lateinit
var
roomId
:
String
private
lateinit
var
roomType
:
String
private
lateinit
var
hostname
:
String
private
lateinit
var
token
:
String
private
lateinit
var
userId
:
String
private
lateinit
var
presenter
:
RoomListContract
.
Presenter
private
var
isDataRequested
:
Boolean
=
false
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/fragment/chatroom/list/RoomListPresenter.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.fragment.chatroom.list
import
android.content.Context
import
android.os.Handler
import
chat.rocket.android.R
import
chat.rocket.android.api.rest.RestApiHelper
import
chat.rocket.android.helper.OkHttpHelper
import
chat.rocket.core.SyncState
import
chat.rocket.core.models.Message
import
chat.rocket.core.models.User
import
okhttp3.Call
import
okhttp3.Callback
import
okhttp3.Response
import
org.json.JSONObject
import
java.io.IOException
import
java.sql.Timestamp
/**
* Created by Filipe de Lima Brito (filipedelimabrito@gmail.com) on 9/22/17.
*/
class
RoomListPresenter
(
val
context
:
Context
,
val
view
:
RoomListContract
.
View
)
:
RoomListContract
.
Presenter
{
override
fun
requestPinnedMessages
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
Int
)
{
view
.
showWaitingView
(
true
)
OkHttpHelper
.
getClient
()
.
newCall
(
RestApiHelper
.
getRequestForPinnedMessages
(
roomId
,
roomType
,
hostname
,
token
,
userId
,
offset
.
toString
()))
.
enqueue
(
object
:
Callback
{
override
fun
onFailure
(
call
:
Call
,
e
:
IOException
)
{
if
(!
call
.
isCanceled
)
{
val
message
=
e
.
message
if
(
message
!=
null
)
{
showErrorMessage
(
message
)
}
}
}
@Throws
(
IOException
::
class
)
override
fun
onResponse
(
call
:
Call
,
response
:
Response
)
{
if
(
response
.
isSuccessful
)
{
val
result
=
response
.
body
()
?.
string
()
if
(
result
!=
null
)
{
handleMessagesJson
(
result
,
true
)
}
}
else
{
showErrorMessage
(
response
.
message
())
}
}
})
}
override
fun
requestFavoriteMessages
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
Int
)
{
view
.
showWaitingView
(
true
)
OkHttpHelper
.
getClient
()
.
newCall
(
RestApiHelper
.
getRequestForFavoriteMessages
(
roomId
,
roomType
,
hostname
,
token
,
userId
,
offset
.
toString
()))
.
enqueue
(
object
:
Callback
{
override
fun
onFailure
(
call
:
Call
,
e
:
IOException
)
{
if
(!
call
.
isCanceled
)
{
val
message
=
e
.
message
if
(
message
!=
null
)
{
showErrorMessage
(
message
)
}
}
}
@Throws
(
IOException
::
class
)
override
fun
onResponse
(
call
:
Call
,
response
:
Response
)
{
if
(
response
.
isSuccessful
)
{
val
result
=
response
.
body
()
?.
string
()
if
(
result
!=
null
)
{
handleMessagesJson
(
result
,
false
)
}
}
else
{
showErrorMessage
(
response
.
message
())
}
}
})
}
// TODO (after the REST api fixes)
override
fun
requestFileList
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
Int
)
{}
override
fun
requestMemberList
(
roomId
:
String
,
roomType
:
String
,
hostname
:
String
,
token
:
String
,
userId
:
String
,
offset
:
Int
)
{
view
.
showWaitingView
(
true
)
OkHttpHelper
.
getClient
()
.
newCall
(
RestApiHelper
.
getRequestForMemberList
(
roomId
,
roomType
,
hostname
,
token
,
userId
,
offset
.
toString
()))
.
enqueue
(
object
:
Callback
{
override
fun
onFailure
(
call
:
Call
,
e
:
IOException
)
{
if
(!
call
.
isCanceled
)
{
val
message
=
e
.
message
if
(
message
!=
null
)
{
showErrorMessage
(
message
)
}
}
}
@Throws
(
IOException
::
class
)
override
fun
onResponse
(
call
:
Call
,
response
:
Response
)
{
if
(
response
.
isSuccessful
)
{
val
result
=
response
.
body
()
?.
string
()
if
(
result
!=
null
)
{
handleMembersJson
(
result
)
}
}
else
{
showErrorMessage
(
response
.
message
())
}
}
})
}
override
fun
cancelRequest
()
{
OkHttpHelper
.
getClient
().
dispatcher
().
cancelAll
()
}
private
fun
handleMessagesJson
(
json
:
String
,
isPinnedMessage
:
Boolean
)
{
val
jSONObject
=
JSONObject
(
json
)
val
messagesJSONArray
=
jSONObject
.
getJSONArray
(
"messages"
)
val
total
=
messagesJSONArray
.
length
()
val
dataSet
=
ArrayList
<
Message
>(
total
)
(
0
until
total
).
mapTo
(
dataSet
)
{
val
messageJsonObject
=
messagesJSONArray
.
getJSONObject
(
it
)
val
userJsonObject
=
messageJsonObject
.
getJSONObject
(
"u"
)
val
timestampString
=
messageJsonObject
.
optString
(
"ts"
)
val
timestamp
=
if
(
timestampString
.
isBlank
())
{
0
}
else
{
Timestamp
.
valueOf
(
timestampString
.
replace
(
"T"
,
" "
).
replace
(
"Z"
,
""
)).
time
}
val
editedAtString
=
messageJsonObject
.
optString
(
"_updatedAt"
)
val
editedAt
=
if
(
editedAtString
.
isBlank
())
{
0
}
else
{
Timestamp
.
valueOf
(
editedAtString
.
replace
(
"T"
,
" "
).
replace
(
"Z"
,
""
)).
time
}
Message
.
builder
()
.
setId
(
messageJsonObject
.
optString
(
"_id"
))
.
setRoomId
(
messageJsonObject
.
optString
(
"rid"
))
.
setMessage
(
messageJsonObject
.
optString
(
"msg"
))
.
setUser
(
getUserFromJsonObject
(
userJsonObject
))
.
setTimestamp
(
timestamp
)
.
setEditedAt
(
editedAt
)
.
setGroupable
(
messageJsonObject
.
optBoolean
(
"groupable"
))
.
setSyncState
(
SyncState
.
SYNCED
)
.
build
()
}
if
(
dataSet
.
isEmpty
()
&&
!
hasItem
)
{
showEmptyViewMessage
(
context
.
getString
(
R
.
string
.
fragment_room_list_no_favorite_message_to_show
))
}
else
{
if
(
dataSet
.
isNotEmpty
())
{
hasItem
=
true
if
(
isPinnedMessage
)
{
showPinnedMessageList
(
dataSet
,
jSONObject
.
optString
(
"total"
))
}
else
{
showFavoriteMessageList
(
dataSet
,
jSONObject
.
optString
(
"total"
))
}
}
}
}
private
fun
handleMembersJson
(
json
:
String
)
{
val
jsonObject
=
JSONObject
(
json
)
val
membersJsonArray
=
jsonObject
.
getJSONArray
(
"members"
)
val
total
=
membersJsonArray
.
length
()
val
dataSet
=
ArrayList
<
User
>(
total
)
(
0
until
total
).
mapTo
(
dataSet
)
{
getUserFromJsonObject
(
membersJsonArray
.
getJSONObject
(
it
))
}
if
(
dataSet
.
isEmpty
()
&&
!
hasItem
)
{
showEmptyViewMessage
(
context
.
getString
(
R
.
string
.
fragment_room_list_no_member_list_to_show
))
}
else
{
if
(
dataSet
.
isNotEmpty
())
{
hasItem
=
true
showMemberList
(
dataSet
,
jsonObject
.
optString
(
"total"
))
}
}
}
private
fun
getUserFromJsonObject
(
jsonObject
:
JSONObject
):
User
{
return
User
.
builder
()
.
setId
(
jsonObject
.
optString
(
"_id"
))
.
setName
(
jsonObject
.
optString
(
"name"
))
.
setUsername
(
jsonObject
.
optString
(
"username"
))
.
setStatus
(
jsonObject
.
optString
(
"status"
))
.
setUtcOffset
(
jsonObject
.
optLong
(
"utcOffset"
).
toDouble
())
.
build
()
}
private
fun
showPinnedMessageList
(
dataSet
:
ArrayList
<
Message
>,
total
:
String
)
{
mainHandler
.
post
{
view
.
showWaitingView
(
false
)
view
.
showPinnedMessages
(
dataSet
,
total
)
}
}
private
fun
showFavoriteMessageList
(
dataSet
:
ArrayList
<
Message
>,
total
:
String
)
{
mainHandler
.
post
{
view
.
showWaitingView
(
false
)
view
.
showFavoriteMessages
(
dataSet
,
total
)
}
}
private
fun
showMemberList
(
dataSet
:
ArrayList
<
User
>,
total
:
String
)
{
mainHandler
.
post
{
view
.
showWaitingView
(
false
)
view
.
showMemberList
(
dataSet
,
total
)
}
}
private
fun
showEmptyViewMessage
(
message
:
String
)
{
mainHandler
.
post
{
view
.
showWaitingView
(
false
)
view
.
showMessage
(
message
)
}
}
private
fun
showErrorMessage
(
message
:
String
)
{
mainHandler
.
post
{
view
.
showWaitingView
(
false
)
view
.
showMessage
(
context
.
getString
(
R
.
string
.
fragment_room_list_could_not_load_your_request
,
message
))
}
}
private
val
mainHandler
=
Handler
(
context
.
mainLooper
)
private
var
hasItem
:
Boolean
=
false
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/helper/EndlessRecyclerViewScrollListener.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.helper
import
android.support.v7.widget.GridLayoutManager
import
android.support.v7.widget.LinearLayoutManager
import
android.support.v7.widget.RecyclerView
import
android.support.v7.widget.StaggeredGridLayoutManager
/**
* Created by Filipe de Lima Brito (filipedelimabrito@gmail.com) on 9/21/17.
* Source info: https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews-and-RecyclerView
*/
abstract
class
EndlessRecyclerViewScrollListener
:
RecyclerView
.
OnScrollListener
{
private
var
visibleThreshold
=
5
// The minimum amount of items to have below of the current scroll position before loading more.
private
var
currentPage
=
0
// The current offset index of data loaded
private
var
previousTotalItemCount
=
0
// The total number of items in the dataset after the last load
private
var
loading
=
true
// True if we are still waiting for the last set of data to load.
private
val
startingPageIndex
=
0
// Sets the starting page index
private
var
layoutManager
:
RecyclerView
.
LayoutManager
constructor
(
layoutManager
:
LinearLayoutManager
)
{
this
.
layoutManager
=
layoutManager
}
constructor
(
layoutManager
:
GridLayoutManager
)
{
this
.
layoutManager
=
layoutManager
visibleThreshold
*=
layoutManager
.
spanCount
}
constructor
(
layoutManager
:
StaggeredGridLayoutManager
)
{
this
.
layoutManager
=
layoutManager
visibleThreshold
*=
layoutManager
.
spanCount
}
private
fun
getLastVisibleItem
(
lastVisibleItemPositions
:
IntArray
):
Int
{
var
maxSize
=
0
for
(
i
in
lastVisibleItemPositions
.
indices
)
{
if
(
i
==
0
)
{
maxSize
=
lastVisibleItemPositions
[
i
]
}
else
if
(
lastVisibleItemPositions
[
i
]
>
maxSize
)
{
maxSize
=
lastVisibleItemPositions
[
i
]
}
}
return
maxSize
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
override
fun
onScrolled
(
view
:
RecyclerView
?,
dx
:
Int
,
dy
:
Int
)
{
var
lastVisibleItemPosition
=
0
val
totalItemCount
=
layoutManager
.
itemCount
when
(
layoutManager
)
{
is
StaggeredGridLayoutManager
->
{
val
lastVisibleItemPositions
=
(
layoutManager
as
StaggeredGridLayoutManager
).
findLastVisibleItemPositions
(
null
)
// get maximum element within the list
lastVisibleItemPosition
=
getLastVisibleItem
(
lastVisibleItemPositions
)
}
is
GridLayoutManager
->
lastVisibleItemPosition
=
(
layoutManager
as
GridLayoutManager
).
findLastVisibleItemPosition
()
is
LinearLayoutManager
->
lastVisibleItemPosition
=
(
layoutManager
as
LinearLayoutManager
).
findLastVisibleItemPosition
()
}
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
// threshold should reflect how many total columns there are too
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if
(
totalItemCount
<
previousTotalItemCount
)
{
this
.
currentPage
=
this
.
startingPageIndex
this
.
previousTotalItemCount
=
totalItemCount
if
(
totalItemCount
==
0
)
{
this
.
loading
=
true
}
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if
(
loading
&&
totalItemCount
>
previousTotalItemCount
)
{
loading
=
false
previousTotalItemCount
=
totalItemCount
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
// threshold should reflect how many total columns there are too
if
(!
loading
&&
lastVisibleItemPosition
+
visibleThreshold
>
totalItemCount
)
{
currentPage
++
onLoadMore
(
currentPage
,
totalItemCount
,
view
)
loading
=
true
}
}
// Call this method whenever performing new searches
fun
resetState
()
{
this
.
currentPage
=
this
.
startingPageIndex
this
.
previousTotalItemCount
=
0
this
.
loading
=
true
}
// Defines the process for actually loading more data based on page
abstract
fun
onLoadMore
(
page
:
Int
,
totalItemsCount
:
Int
,
recyclerView
:
RecyclerView
?)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/helper/LoadMoreScrollListener.java
deleted
100644 → 0
View file @
16052e46
package
chat
.
rocket
.
android
.
helper
;
import
android.support.v7.widget.LinearLayoutManager
;
import
android.support.v7.widget.RecyclerView
;
@SuppressWarnings
(
"PMD.AbstractNaming"
)
public
abstract
class
LoadMoreScrollListener
extends
RecyclerView
.
OnScrollListener
{
private
final
LinearLayoutManager
layoutManager
;
private
final
int
loadThreshold
;
private
boolean
isLoading
;
/**
* constructor. loadThreshold is better to set to 0.4 * total.
*/
public
LoadMoreScrollListener
(
LinearLayoutManager
layoutManager
,
int
loadThreshold
)
{
this
.
layoutManager
=
layoutManager
;
this
.
loadThreshold
=
loadThreshold
;
setLoadingDone
();
}
@Override
public
void
onScrolled
(
RecyclerView
recyclerView
,
int
deltaX
,
int
deltaY
)
{
super
.
onScrolled
(
recyclerView
,
deltaX
,
deltaY
);
final
int
visibleItemCount
=
recyclerView
.
getChildCount
();
final
int
totalItemCount
=
layoutManager
.
getItemCount
();
final
int
firstVisibleItem
=
layoutManager
.
findFirstVisibleItemPosition
();
if
(!
isLoading
&&
firstVisibleItem
+
visibleItemCount
>=
totalItemCount
-
loadThreshold
&&
visibleItemCount
<
totalItemCount
&&
deltaY
<
0
)
{
isLoading
=
true
;
requestMoreItem
();
}
}
public
void
setLoadingDone
()
{
isLoading
=
false
;
}
public
abstract
void
requestMoreItem
();
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/helper/LoadMoreScrollListener.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.helper
import
android.support.v7.widget.LinearLayoutManager
import
android.support.v7.widget.RecyclerView
abstract
class
LoadMoreScrollListener
(
private
val
layoutManager
:
LinearLayoutManager
,
private
val
visibleThreshold
:
Int
)
:
RecyclerView
.
OnScrollListener
()
{
private
var
isLoading
:
Boolean
=
false
override
fun
onScrolled
(
recyclerView
:
RecyclerView
,
deltaX
:
Int
,
deltaY
:
Int
)
{
super
.
onScrolled
(
recyclerView
,
deltaX
,
deltaY
)
val
visibleItemCount
=
recyclerView
.
childCount
val
totalItemCount
=
layoutManager
.
itemCount
val
firstVisibleItem
=
layoutManager
.
findFirstVisibleItemPosition
()
if
(!
isLoading
&&
(
firstVisibleItem
+
visibleItemCount
)
>=
(
totalItemCount
-
visibleThreshold
)
&&
visibleItemCount
<
totalItemCount
&&
deltaY
<
0
)
{
isLoading
=
true
requestMoreItem
()
}
}
fun
setLoadingDone
()
{
isLoading
=
false
}
abstract
fun
requestMoreItem
()
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/helper/UrlHelper.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.helper
object
UrlHelper
{
/**
* Returns an URI whit no scheme (HTTP or HTTPS)
*
* @param uri The URI.
* @return The URI whit no scheme (HTTP or HTTPS)
*/
fun
removeUriScheme
(
uri
:
String
)
=
uri
.
replace
(
"http://"
,
""
).
replace
(
"https://"
,
""
)
/**
* Returns the hostname with the security protocol (scheme) HTTPS.
*
* @param hostname The hostname.
* @return The hostname with the security protocol (scheme) HTTPS.
*/
fun
getSafeHostname
(
hostname
:
String
):
String
=
"https://"
+
hostname
.
replace
(
"http://"
,
""
).
replace
(
"https://"
,
""
)
/**
* Returns an URL with no spaces and inverted slashes.
*
* @param url The URL.
* @return The URL with no spaces and inverted slashes.
*/
fun
getUrl
(
url
:
String
)
=
url
.
replace
(
" "
,
"%20"
).
replace
(
"\\"
,
""
)
/**
* Returns an URL for a file.
*
* @param path The path to the file.
* @param userId The user ID.
* @param token The token.
* @return The URL for a file
*/
fun
getUrlForFile
(
path
:
String
,
userId
:
String
,
token
:
String
):
String
=
"https://"
+
removeUriScheme
(
getUrl
(
path
))
+
"?rc_uid=$userId"
+
"&rc_token=$token"
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/layouthelper/chatroom/AbstractMessageViewHolder.java
View file @
9d8197a7
...
...
@@ -34,8 +34,8 @@ public abstract class AbstractMessageViewHolder extends ModelViewHolder<PairedMe
subUsername
=
itemView
.
findViewById
(
R
.
id
.
sub_username
);
timestamp
=
itemView
.
findViewById
(
R
.
id
.
timestamp
);
userAndTimeContainer
=
itemView
.
findViewById
(
R
.
id
.
user_and_timestamp_container
);
newDayContainer
=
itemView
.
findViewById
(
R
.
id
.
newday_c
ontainer
);
newDayText
=
itemView
.
findViewById
(
R
.
id
.
newday_text
);
newDayContainer
=
itemView
.
findViewById
(
R
.
id
.
dayC
ontainer
);
newDayText
=
itemView
.
findViewById
(
R
.
id
.
day
);
this
.
absoluteUrl
=
absoluteUrl
;
this
.
hostname
=
hostname
;
}
...
...
app/src/main/java/chat/rocket/android/layouthelper/chatroom/list/RoomFileListAdapter.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.layouthelper.chatroom.list
import
android.support.v7.widget.RecyclerView
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
chat.rocket.android.R
import
chat.rocket.android.widget.message.RocketChatMessageLayout
import
kotlinx.android.synthetic.main.item_room_file.view.*
/**
* Created by Filipe de Lima Brito (filipedelimabrito@gmail.com) on 9/22/17.
*/
class
RoomFileListAdapter
(
private
var
dataSet
:
List
<
String
>)
:
RecyclerView
.
Adapter
<
RoomFileListAdapter
.
ViewHolder
>()
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
ViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
item_room_file
,
parent
,
false
)
return
ViewHolder
(
view
)
}
override
fun
onBindViewHolder
(
holder
:
ViewHolder
,
position
:
Int
)
{
holder
.
fileNameLink
.
setText
(
dataSet
[
position
])
}
override
fun
getItemCount
():
Int
=
dataSet
.
size
fun
setDataSet
(
dataSet
:
List
<
String
>)
{
this
.
dataSet
=
dataSet
notifyDataSetChanged
()
}
class
ViewHolder
(
itemView
:
View
)
:
RecyclerView
.
ViewHolder
(
itemView
)
{
val
fileNameLink
:
RocketChatMessageLayout
=
itemView
.
fileLink
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/layouthelper/chatroom/list/RoomMemberListAdapter.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.layouthelper.chatroom.list
import
android.content.Context
import
android.graphics.drawable.Drawable
import
android.support.graphics.drawable.VectorDrawableCompat
import
android.support.v7.widget.RecyclerView
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.widget.ImageView
import
android.widget.TextView
import
chat.rocket.android.R
import
chat.rocket.android.widget.RocketChatAvatar
import
chat.rocket.android.widget.helper.AvatarHelper
import
chat.rocket.android.widget.helper.DrawableHelper
import
chat.rocket.core.models.User
import
kotlinx.android.synthetic.main.item_room_member.view.*
/**
* Created by Filipe de Lima Brito (filipedelimabrito@gmail.com) on 9/22/17.
*/
class
RoomMemberListAdapter
(
private
var
dataSet
:
List
<
User
>,
private
val
hostname
:
String
,
private
val
context
:
Context
)
:
RecyclerView
.
Adapter
<
RoomMemberListAdapter
.
ViewHolder
>()
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
ViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
item_room_member
,
parent
,
false
)
return
ViewHolder
(
view
)
}
override
fun
onBindViewHolder
(
holder
:
ViewHolder
,
position
:
Int
)
{
val
user
=
dataSet
[
position
]
holder
.
name
.
text
=
user
.
name
val
userStatusDrawable
:
Drawable
?
=
VectorDrawableCompat
.
create
(
context
.
resources
,
chat
.
rocket
.
android
.
widget
.
R
.
drawable
.
ic_user_status_black_24dp
,
null
)
DrawableHelper
.
wrapDrawable
(
userStatusDrawable
)
when
(
user
.
status
)
{
User
.
STATUS_ONLINE
->
DrawableHelper
.
tintDrawable
(
userStatusDrawable
,
context
,
chat
.
rocket
.
android
.
widget
.
R
.
color
.
color_user_status_online
)
User
.
STATUS_BUSY
->
DrawableHelper
.
tintDrawable
(
userStatusDrawable
,
context
,
chat
.
rocket
.
android
.
widget
.
R
.
color
.
color_user_status_busy
)
User
.
STATUS_AWAY
->
DrawableHelper
.
tintDrawable
(
userStatusDrawable
,
context
,
chat
.
rocket
.
android
.
widget
.
R
.
color
.
color_user_status_away
)
User
.
STATUS_OFFLINE
->
DrawableHelper
.
tintDrawable
(
userStatusDrawable
,
context
,
chat
.
rocket
.
android
.
widget
.
R
.
color
.
color_user_status_offline
)
}
holder
.
status
.
setImageDrawable
(
userStatusDrawable
)
val
username
=
user
.
username
if
(
username
!=
null
)
{
holder
.
username
.
text
=
context
.
getString
(
R
.
string
.
username
,
username
)
val
placeholderDrawable
=
AvatarHelper
.
getTextDrawable
(
username
,
holder
.
userAvatar
.
context
)
holder
.
userAvatar
.
loadImage
(
AvatarHelper
.
getUri
(
hostname
,
username
),
placeholderDrawable
)
}
else
{
holder
.
userAvatar
.
visibility
=
View
.
GONE
holder
.
username
.
visibility
=
View
.
GONE
}
}
override
fun
getItemCount
():
Int
=
dataSet
.
size
fun
addDataSet
(
dataSet
:
List
<
User
>)
{
val
previousDataSetSize
=
this
.
dataSet
.
size
this
.
dataSet
+=
dataSet
notifyItemRangeInserted
(
previousDataSetSize
,
dataSet
.
size
)
}
class
ViewHolder
(
itemView
:
View
)
:
RecyclerView
.
ViewHolder
(
itemView
)
{
val
userAvatar
:
RocketChatAvatar
=
itemView
.
userAvatar
val
name
:
TextView
=
itemView
.
name
val
status
:
ImageView
=
itemView
.
status
val
username
:
TextView
=
itemView
.
username
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/layouthelper/chatroom/list/RoomMessagesAdapter.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.layouthelper.chatroom.list
import
android.content.Context
import
android.support.v7.widget.RecyclerView
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.widget.TextView
import
chat.rocket.android.R
import
chat.rocket.android.helper.DateTime
import
chat.rocket.android.widget.RocketChatAvatar
import
chat.rocket.android.widget.helper.AvatarHelper
import
chat.rocket.android.widget.message.RocketChatMessageAttachmentsLayout
import
chat.rocket.android.widget.message.RocketChatMessageLayout
import
chat.rocket.android.widget.message.RocketChatMessageUrlsLayout
import
chat.rocket.core.models.Message
import
kotlinx.android.synthetic.main.day.view.*
import
kotlinx.android.synthetic.main.item_room_message.view.*
/**
* Created by Filipe de Lima Brito (filipedelimabrito@gmail.com) on 9/22/17.
*/
class
RoomMessagesAdapter
(
private
var
dataSet
:
List
<
Message
>,
private
val
hostname
:
String
,
private
val
context
:
Context
)
:
RecyclerView
.
Adapter
<
RoomMessagesAdapter
.
ViewHolder
>()
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
ViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
item_room_message
,
parent
,
false
)
return
ViewHolder
(
view
)
}
override
fun
onBindViewHolder
(
holder
:
ViewHolder
,
position
:
Int
)
{
val
message
=
dataSet
[
position
]
holder
.
newDay
.
text
=
DateTime
.
fromEpocMs
(
message
.
timestamp
,
DateTime
.
Format
.
DATE
)
val
user
=
message
.
user
if
(
user
!=
null
)
{
if
(
user
.
name
.
isNullOrBlank
())
{
holder
.
name
.
visibility
=
View
.
GONE
}
else
{
holder
.
name
.
text
=
message
.
user
?.
name
}
val
username
=
user
.
username
if
(
username
!=
null
)
{
val
placeholderDrawable
=
AvatarHelper
.
getTextDrawable
(
username
,
holder
.
userAvatar
.
context
)
holder
.
userAvatar
.
loadImage
(
AvatarHelper
.
getUri
(
hostname
,
username
),
placeholderDrawable
)
holder
.
username
.
text
=
context
.
getString
(
R
.
string
.
username
,
username
)
}
else
{
holder
.
userAvatar
.
visibility
=
View
.
GONE
holder
.
username
.
visibility
=
View
.
GONE
}
}
holder
.
messageBody
.
setText
(
message
.
message
)
val
webContents
=
message
.
webContents
if
(
webContents
==
null
||
webContents
.
isEmpty
())
{
holder
.
messageUrl
.
visibility
=
View
.
GONE
}
else
{
holder
.
messageUrl
.
setUrls
(
message
.
webContents
,
true
)
}
val
attachments
=
message
.
attachments
if
(
attachments
==
null
||
attachments
.
isEmpty
())
{
holder
.
messageAttachment
.
visibility
=
View
.
GONE
}
else
{
// holder.messageAttachment.setAbsoluteUrl(absoluteUrl)
// holder.messageAttachment.setAttachments(attachments, true)
// holder.messageAttachment.visibility = View.VISIBLE
}
}
override
fun
getItemCount
():
Int
=
dataSet
.
size
fun
addDataSet
(
dataSet
:
List
<
Message
>)
{
val
previousDataSetSize
=
this
.
dataSet
.
size
this
.
dataSet
+=
dataSet
notifyItemRangeInserted
(
previousDataSetSize
,
dataSet
.
size
)
}
class
ViewHolder
(
itemView
:
View
)
:
RecyclerView
.
ViewHolder
(
itemView
)
{
val
newDay
:
TextView
=
itemView
.
day
val
userAvatar
:
RocketChatAvatar
=
itemView
.
userAvatar
val
username
:
TextView
=
itemView
.
username
val
name
:
TextView
=
itemView
.
name
val
messageBody
:
RocketChatMessageLayout
=
itemView
.
messageBody
val
messageUrl
:
RocketChatMessageUrlsLayout
=
itemView
.
messageUrl
val
messageAttachment
:
RocketChatMessageAttachmentsLayout
=
itemView
.
messageAttachment
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/layouthelper/chatroom/
dialog
/RoomUserAdapter.java
→
app/src/main/java/chat/rocket/android/layouthelper/chatroom/
list
/RoomUserAdapter.java
View file @
9d8197a7
package
chat
.
rocket
.
android
.
layouthelper
.
chatroom
.
dialog
;
package
chat
.
rocket
.
android
.
layouthelper
.
chatroom
.
list
;
import
android.content.Context
;
import
android.support.v7.widget.RecyclerView
;
...
...
app/src/main/java/chat/rocket/android/layouthelper/chatroom/
dialog
/RoomUserViewHolder.java
→
app/src/main/java/chat/rocket/android/layouthelper/chatroom/
list
/RoomUserViewHolder.java
View file @
9d8197a7
package
chat
.
rocket
.
android
.
layouthelper
.
chatroom
.
dialog
;
package
chat
.
rocket
.
android
.
layouthelper
.
chatroom
.
list
;
import
android.support.v7.widget.RecyclerView
;
import
android.view.View
;
...
...
app/src/main/res/drawable/ic_close_circle_outline_black_24dp.xml
0 → 100644
View file @
9d8197a7
<!-- drawable/close_circle_outline.xml -->
<vector
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:width=
"24dp"
android:height=
"24dp"
android:viewportHeight=
"24"
android:viewportWidth=
"24"
>
<path
android:fillColor=
"#FF000000"
android:pathData=
"M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2C6.47,2 2,6.47 2,12C2,17.53 6.47,22 12,22C17.53,22 22,17.53 22,12C22,6.47 17.53,2 12,2M14.59,8L12,10.59L9.41,8L8,9.41L10.59,12L8,14.59L9.41,16L12,13.41L14.59,16L16,14.59L13.41,12L16,9.41L14.59,8Z"
/>
</vector>
\ No newline at end of file
app/src/main/res/layout-w720dp/activity_main.xml
View file @
9d8197a7
...
...
@@ -17,7 +17,9 @@
<chat.rocket.android.widget.RoomToolbar
android:id=
"@+id/activity_main_toolbar"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
/>
android:layout_height=
"wrap_content"
app:theme=
"@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme=
"@style/ThemeOverlay.AppCompat.Light"
/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
...
...
app/src/main/res/layout-w720dp/fragment_room.xml
deleted
100644 → 0
View file @
16052e46
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"horizontal"
tools:context=
"chat.rocket.android.fragment.chatroom.RoomFragment"
>
<include
layout=
"@layout/fragment_room_main"
/>
<include
layout=
"@layout/room_side_menu"
/>
</LinearLayout>
\ No newline at end of file
app/src/main/res/layout/activity_main.xml
View file @
9d8197a7
...
...
@@ -18,7 +18,9 @@
<chat.rocket.android.widget.RoomToolbar
android:id=
"@+id/activity_main_toolbar"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
/>
android:layout_height=
"wrap_content"
app:theme=
"@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme=
"@style/ThemeOverlay.AppCompat.Light"
/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
...
...
app/src/main/res/layout/activity_room.xml
0 → 100644
View file @
9d8197a7
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
tools:context=
"chat.rocket.android.activity.room.RoomActivity"
>
<android.support.design.widget.AppBarLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
<android.support.v7.widget.Toolbar
android:id=
"@+id/toolbar"
android:layout_width=
"match_parent"
android:layout_height=
"?attr/actionBarSize"
app:theme=
"@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme=
"@style/ThemeOverlay.AppCompat.Light"
/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id=
"@+id/fragment_container"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
</LinearLayout>
\ No newline at end of file
app/src/main/res/layout/day.xml
0 → 100644
View file @
9d8197a7
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:id=
"@+id/dayContainer"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:gravity=
"center_vertical"
android:orientation=
"horizontal"
>
<View
android:layout_width=
"0px"
android:layout_height=
"1dp"
android:layout_weight=
"1"
android:background=
"@color/colorDivider"
/>
<TextView
android:id=
"@+id/day"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"16dp"
android:layout_marginRight=
"16dp"
android:textAppearance=
"@style/TextAppearance.RocketChat.Message.Day"
tools:text=
"2016/01/23"
/>
<View
android:layout_width=
"0px"
android:layout_height=
"1dp"
android:layout_weight=
"1"
android:background=
"@color/colorDivider"
/>
</LinearLayout>
\ No newline at end of file
app/src/main/res/layout/fragment_room.xml
View file @
9d8197a7
<?xml version="1.0" encoding="utf-8"?>
<
android.support.v4.widget.Drawer
Layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
<
Relative
Layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:id=
"@+id/
drawer_l
ayout"
android:id=
"@+id/
messageListRelativeL
ayout"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@android:color/white"
tools:context=
"chat.rocket.android.fragment.chatroom.RoomFragment"
>
<include
layout=
"@layout/fragment_room_main"
/>
<FrameLayout
<android.support.v7.widget.RecyclerView
android:id=
"@+id/messageRecyclerView"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"end"
android:clickable=
"true"
android:theme=
"@style/AppTheme.Dark"
>
android:scrollbars=
"vertical"
android:layout_above=
"@+id/messageComposer"
/>
<include
layout=
"@layout/room_side_menu"
/>
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
\ No newline at end of file
<chat.rocket.android.widget.message.MessageFormLayout
android:id=
"@+id/messageComposer"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_alignParentBottom=
"true"
android:theme=
"@style/Theme.AppCompat.Light"
/>
</RelativeLayout>
\ No newline at end of file
app/src/main/res/layout/fragment_room_list.xml
0 → 100644
View file @
9d8197a7
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<chat.rocket.android.widget.WaitingView
android:id=
"@+id/waitingView"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_centerInParent=
"true"
/>
<TextView
android:id=
"@+id/messageText"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_centerInParent=
"true"
android:visibility=
"gone"
/>
<android.support.v7.widget.RecyclerView
android:id=
"@+id/recyclerView"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:scrollbars=
"vertical"
/>
</RelativeLayout>
\ No newline at end of file
app/src/main/res/layout/fragment_room_main.xml
deleted
100644 → 0
View file @
16052e46
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:id=
"@+id/messageListRelativeLayout"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@android:color/white"
>
<android.support.v7.widget.RecyclerView
android:id=
"@+id/messageRecyclerView"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:scrollbars=
"vertical"
android:layout_above=
"@+id/messageComposer"
/>
<chat.rocket.android.widget.message.MessageFormLayout
android:id=
"@+id/messageComposer"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_alignParentBottom=
"true"
android:theme=
"@style/Theme.AppCompat.Light"
/>
</RelativeLayout>
\ No newline at end of file
app/src/main/res/layout/item_room_file.xml
0 → 100644
View file @
9d8197a7
<?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:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:padding=
"@dimen/margin_16"
>
<chat.rocket.android.widget.message.RocketChatMessageLayout
android:id=
"@+id/fileLink"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"@dimen/margin_16"
android:layout_marginStart=
"@dimen/margin_16"
/>
<View
android:layout_width=
"0dp"
android:layout_height=
"1dp"
android:layout_weight=
"1"
android:background=
"@color/colorDivider"
android:layout_marginTop=
"@dimen/margin_8"
app:layout_constraintTop_toBottomOf=
"@+id/fileLink"
/>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/item_room_member.xml
0 → 100644
View file @
9d8197a7
<?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:paddingTop=
"@dimen/margin_16"
android:paddingRight=
"@dimen/margin_16"
android:paddingStart=
"@dimen/margin_16"
android:paddingLeft=
"@dimen/margin_16"
android:paddingEnd=
"@dimen/margin_16"
>
<chat.rocket.android.widget.RocketChatAvatar
android:id=
"@+id/userAvatar"
android:layout_width=
"40dp"
android:layout_height=
"40dp"
android:layout_marginTop=
"4dp"
app:layout_constraintTop_toTopOf=
"parent"
/>
<android.support.constraint.ConstraintLayout
android:id=
"@+id/container"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"@dimen/margin_16"
android:layout_marginStart=
"@dimen/margin_16"
app:layout_constraintLeft_toRightOf=
"@+id/userAvatar"
>
<ImageView
android:id=
"@+id/status"
android:layout_width=
"8dp"
android:layout_height=
"8dp"
app:layout_constraintTop_toTopOf=
"@+id/name"
app:layout_constraintBottom_toBottomOf=
"@+id/name"
app:srcCompat=
"@drawable/ic_user_status_black_24dp"
/>
<TextView
android:id=
"@+id/name"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"4dp"
android:layout_marginStart=
"4dp"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textAppearance=
"@style/TextAppearance.RocketChat.Message.Name"
app:layout_constraintLeft_toRightOf=
"@+id/status"
tools:text=
"John Doe"
/>
<TextView
android:id=
"@+id/username"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textAppearance=
"@style/TextAppearance.RocketChat.Message.Username"
app:layout_constraintTop_toBottomOf=
"@+id/name"
app:layout_constraintLeft_toLeftOf=
"@+id/name"
tools:text=
"\@john.doe"
/>
</android.support.constraint.ConstraintLayout>
<View
android:layout_width=
"0dp"
android:layout_height=
"1dp"
android:layout_weight=
"1"
android:background=
"@color/colorDivider"
android:layout_marginTop=
"20dp"
app:layout_constraintTop_toBottomOf=
"@+id/container"
/>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/item_room_message.xml
0 → 100644
View file @
9d8197a7
<?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:paddingRight=
"@dimen/margin_16"
android:paddingStart=
"@dimen/margin_16"
android:paddingLeft=
"@dimen/margin_16"
android:paddingEnd=
"@dimen/margin_16"
android:paddingBottom=
"@dimen/margin_16"
>
<include
android:id=
"@+id/dayLayout"
layout=
"@layout/day"
/>
<chat.rocket.android.widget.RocketChatAvatar
android:id=
"@+id/userAvatar"
android:layout_width=
"40dp"
android:layout_height=
"40dp"
android:layout_marginTop=
"20dp"
app:layout_constraintTop_toBottomOf=
"@+id/dayLayout"
/>
<android.support.constraint.ConstraintLayout
android:id=
"@+id/userContainer"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"@dimen/margin_16"
android:layout_marginLeft=
"@dimen/margin_16"
android:layout_marginStart=
"@dimen/margin_16"
app:layout_constraintTop_toBottomOf=
"@+id/dayLayout"
app:layout_constraintLeft_toRightOf=
"@+id/userAvatar"
>
<TextView
android:id=
"@+id/name"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textAppearance=
"@style/TextAppearance.RocketChat.Message.Name"
tools:text=
"John Doe"
/>
<TextView
android:id=
"@+id/username"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textAppearance=
"@style/TextAppearance.RocketChat.Message.Username"
app:layout_constraintLeft_toLeftOf=
"@+id/name"
app:layout_constraintTop_toBottomOf=
"@+id/name"
tools:text=
"\@john.doe"
/>
</android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout
android:id=
"@+id/messageContainer"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"10dp"
android:layout_marginLeft=
"@dimen/margin_16"
android:layout_marginStart=
"@dimen/margin_16"
app:layout_constraintTop_toBottomOf=
"@+id/userContainer"
app:layout_constraintLeft_toRightOf=
"@+id/userAvatar"
app:layout_constraintRight_toRightOf=
"parent"
>
<chat.rocket.android.widget.message.RocketChatMessageLayout
android:id=
"@+id/messageBody"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
/>
<chat.rocket.android.widget.message.RocketChatMessageUrlsLayout
android:id=
"@+id/messageUrl"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
app:layout_constraintLeft_toLeftOf=
"@+id/messageBody"
app:layout_constraintTop_toBottomOf=
"@+id/messageBody"
/>
<chat.rocket.android.widget.message.RocketChatMessageAttachmentsLayout
android:id=
"@+id/messageAttachment"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
app:layout_constraintLeft_toLeftOf=
"@+id/messageUrl"
app:layout_constraintTop_toBottomOf=
"@+id/messageUrl"
/>
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/list_item_message_newday.xml
deleted
100644 → 0
View file @
16052e46
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:id=
"@+id/newday_container"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_margin=
"16dp"
android:gravity=
"center_vertical"
android:orientation=
"horizontal"
>
<View
android:layout_width=
"0px"
android:layout_height=
"1dp"
android:layout_weight=
"1"
android:background=
"@color/newday_color"
/>
<TextView
android:id=
"@+id/newday_text"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"16dp"
android:layout_marginRight=
"16dp"
android:textColor=
"@color/newday_text_color"
android:textSize=
"8sp"
android:textStyle=
"bold"
tools:text=
"2016/01/23"
/>
<View
android:layout_width=
"0px"
android:layout_height=
"1dp"
android:layout_weight=
"1"
android:background=
"@color/newday_color"
/>
</LinearLayout>
\ No newline at end of file
app/src/main/res/layout/list_item_normal_message.xml
View file @
9d8197a7
...
...
@@ -7,7 +7,7 @@
android:orientation=
"vertical"
android:theme=
"@style/AppTheme"
>
<include
layout=
"@layout/
list_item_message_new
day"
/>
<include
layout=
"@layout/day"
/>
<FrameLayout
android:layout_width=
"match_parent"
...
...
app/src/main/res/layout/list_item_system_message.xml
View file @
9d8197a7
...
...
@@ -7,7 +7,7 @@
android:orientation=
"vertical"
android:theme=
"@style/AppTheme"
>
<include
layout=
"@layout/
list_item_message_new
day"
/>
<include
layout=
"@layout/day"
/>
<FrameLayout
android:layout_width=
"match_parent"
...
...
app/src/main/res/layout/room_side_menu.xml
deleted
100644 → 0
View file @
16052e46
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:id=
"@+id/room_side_menu"
android:layout_width=
"48dp"
android:layout_height=
"match_parent"
android:layout_gravity=
"end"
android:orientation=
"vertical"
>
<io.github.yusukeiwaki.android.widget.FontAwesomeButton
android:layout_width=
"48dp"
android:layout_height=
"48dp"
android:enabled=
"false"
android:text=
"@string/fa_search"
android:textSize=
"24dp"
/>
<io.github.yusukeiwaki.android.widget.FontAwesomeButton
android:id=
"@+id/btn_users"
android:layout_width=
"48dp"
android:layout_height=
"48dp"
android:text=
"@string/fa_users"
android:textSize=
"24dp"
/>
<io.github.yusukeiwaki.android.widget.FontAwesomeButton
android:layout_width=
"48dp"
android:layout_height=
"48dp"
android:enabled=
"false"
android:text=
"@string/fa_at"
android:textSize=
"24dp"
/>
</LinearLayout>
\ No newline at end of file
app/src/main/res/menu/menu_room.xml
0 → 100644
View file @
9d8197a7
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
>
<item
android:id=
"@+id/action_pinned_messages"
android:title=
"@string/menu_pinned_messages"
app:showAsAction=
"never"
/>
<item
android:id=
"@+id/action_favorite_messages"
android:title=
"@string/menu_favorite_messages"
app:showAsAction=
"never"
/>
<!--<item android:id="@+id/action_file_list"-->
<!--android:title="@string/menu_file_list"-->
<!--app:showAsAction="never" />-->
<item
android:id=
"@+id/action_member_list"
android:title=
"@string/menu_member_list"
app:showAsAction=
"never"
/>
</menu>
\ No newline at end of file
app/src/main/res/values/colors.xml
View file @
9d8197a7
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color
name=
"colorPrimary"
>
#044b76
</color>
<color
name=
"colorPrimaryDark"
>
#FF04436a
</color>
<color
name=
"colorAccent"
>
#FF2D91FA
</color>
<color
name=
"colorAccentLight"
>
#FF6CB1FA
</color>
<color
name=
"colorAccentDark"
>
#FF287DD7
</color>
<color
name=
"colorAccent_a40"
>
#662D91FA
</color>
<color
name=
"textColorLink"
>
#008ce3
</color>
<color
name=
"colorRed400"
>
#FFEF5350
</color>
<color
name=
"colorPrimary"
>
#044b76
</color>
<color
name=
"colorPrimaryDark"
>
#FF04436a
</color>
<color
name=
"colorAccent"
>
#FF2D91FA
</color>
<color
name=
"colorAccentLight"
>
#FF6CB1FA
</color>
<color
name=
"colorAccentDark"
>
#FF287DD7
</color>
<color
name=
"colorAccent_a40"
>
#662D91FA
</color>
<color
name=
"textColorLink"
>
#008ce3
</color>
<color
name=
"colorRed400"
>
#FFEF5350
</color>
<color
name=
"colorPrimaryTextDark"
>
#DE000000
</color>
<color
name=
"colorSecondaryTextDark"
>
#8A000000
</color>
<color
name=
"colorDivider"
>
#1F000000
</color>
</resources>
\ No newline at end of file
app/src/main/res/values/fa_strings.xml
View file @
9d8197a7
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string
name=
"fa_chevron_down"
translatable=
"false"
>

</string>
<string
name=
"fa_twitter"
translatable=
"false"
>

</string>
<string
name=
"fa_github"
translatable=
"false"
>

</string>
<string
name=
"fa_google"
translatable=
"false"
>

</string>
<string
name=
"fa_facebook_official"
translatable=
"false"
>

</string>
<string
name=
"fa_plus"
translatable=
"false"
>

</string>
<string
name=
"fa_sign_out"
translatable=
"false"
>

</string>
<string
name=
"fa_search"
translatable=
"false"
>

</string>
<string
name=
"fa_users"
translatable=
"false"
>

</string>
<string
name=
"fa_at"
translatable=
"false"
>

</string>
</resources>
\ No newline at end of file
app/src/main/res/values/message_style.xml
0 → 100644
View file @
9d8197a7
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style
name=
"TextAppearance.RocketChat.Message.Day"
parent=
"TextAppearance.AppCompat"
>
<item
name=
"android:textSize"
>
12sp
</item>
<item
name=
"android:textColor"
>
@color/colorPrimaryTextDark
</item>
</style>
<style
name=
"TextAppearance.RocketChat.Message.SubUsername"
parent=
"TextAppearance.AppCompat.Body1"
>
<item
name=
"android:textColor"
>
#5f000000
</item>
</style>
<style
name=
"TextAppearance.RocketChat.Message.Name"
parent=
"TextAppearance.AppCompat.Body1"
>
<item
name=
"android:textColor"
>
@color/colorPrimaryTextDark
</item>
<item
name=
"android:fontFamily"
>
sans-serif-condensed
</item>
<item
name=
"android:textSize"
>
16sp
</item>
<item
name=
"android:maxLines"
>
1
</item>
<item
name=
"android:ellipsize"
>
end
</item>
</style>
<style
name=
"TextAppearance.RocketChat.Message.Username"
parent=
"TextAppearance.AppCompat.Body2"
>
<item
name=
"android:textColor"
>
@color/colorSecondaryTextDark
</item>
<item
name=
"android:fontFamily"
>
sans-serif-condensed
</item>
<item
name=
"android:textSize"
>
14sp
</item>
<item
name=
"android:maxLines"
>
1
</item>
<item
name=
"android:ellipsize"
>
end
</item>
</style>
</resources>
\ No newline at end of file
app/src/main/res/values/message_styles.xml
deleted
100644 → 0
View file @
16052e46
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color
name=
"newday_color"
>
#e0e0e0
</color>
<color
name=
"newday_text_color"
>
#444444
</color>
<style
name=
"TextAppearance.RocketChat.Message.Username"
parent=
"TextAppearance.AppCompat.Body2"
>
<item
name=
"android:textColor"
>
#bb000000
</item>
</style>
<style
name=
"TextAppearance.RocketChat.Message.SubUsername"
parent=
"TextAppearance.AppCompat.Body1"
>
<item
name=
"android:textColor"
>
#5f000000
</item>
</style>
</resources>
\ No newline at end of file
app/src/main/res/values/strings.xml
View file @
9d8197a7
...
...
@@ -13,6 +13,16 @@
<string
name=
"dialog_add_channel_private"
>
private
</string>
<string
name=
"dialog_add_channel_read_only"
>
read only
</string>
<string
name=
"fragment_room_list_pinned_message_title"
>
Pinned Messages (%s)
</string>
<string
name=
"fragment_room_list_favorite_message_title"
>
Favorite Messages (%s)
</string>
<string
name=
"fragment_room_list_file_list_title"
>
File list (%s)
</string>
<string
name=
"fragment_room_list_member_list_title"
>
Member list (%s)
</string>
<string
name=
"fragment_room_list_could_not_load_your_request"
>
Could not load your request.\nResponse was: %s
</string>
<string
name=
"fragment_room_list_no_pinned_message_to_show"
>
No pinned message to show
</string>
<string
name=
"fragment_room_list_no_favorite_message_to_show"
>
No favorite message to show
</string>
<string
name=
"fragment_room_list_no_file_list_to_show"
>
No file list to show
</string>
<string
name=
"fragment_room_list_no_member_list_to_show"
>
No member list to show
</string>
<string
name=
"start_of_conversation"
>
Start of conversation
</string>
<string
name=
"users_of_room_title"
>
Members List
</string>
<plurals
name=
"fmt_room_user_count"
>
...
...
@@ -36,6 +46,7 @@
<string
name=
"dialog_user_registration_email"
>
Email
</string>
<string
name=
"dialog_user_registration_username"
>
Username
</string>
<string
name=
"sub_username"
>
\@%s
</string>
<string
name=
"username"
>
\@%s
</string>
<string
name=
"dialog_user_registration_password"
>
Password
</string>
<string
name=
"fragment_home_welcome_message"
>
Welcome to Rocket.Chat.Android\nSelect a channel from the drawer.
</string>
<string
name=
"fragment_input_hostname_hostname"
>
Hostname
</string>
...
...
@@ -68,5 +79,11 @@
<string
name=
"edit_message"
>
Edit message
</string>
<string
name=
"message_options_no_message_info"
>
Ooops. Something\'s up!
</string>
<string
name=
"message_options_no_permissions_info"
>
You have no permissions
</string>
<string
name=
"menu_pinned_messages"
>
Pinned messages
</string>
<string
name=
"menu_favorite_messages"
>
Favorite messages
</string>
<string
name=
"menu_file_list"
>
File list
</string>
<string
name=
"menu_member_list"
>
Member list
</string>
<string
name=
"add_new_team"
>
Add new Team
</string>
</resources>
app/src/release/java/chat/rocket/android/helper/OkHttpHelper.kt
View file @
9d8197a7
...
...
@@ -9,6 +9,13 @@ import okhttp3.OkHttpClient
object
OkHttpHelper
{
fun
getClient
():
OkHttpClient
{
if
(
httpClient
==
null
)
{
httpClient
=
OkHttpClient
()
}
return
httpClient
?:
throw
AssertionError
(
"httpClient set to null by another thread"
)
}
fun
getClientForUploadFile
():
OkHttpClient
{
if
(
httpClientForUploadFile
==
null
)
{
httpClientForUploadFile
=
OkHttpClient
.
Builder
().
build
()
...
...
@@ -19,6 +26,8 @@ object OkHttpHelper {
fun
getClientForDownloadFile
(
context
:
Context
):
OkHttpClient
{
if
(
httpClientForDownloadFile
==
null
)
{
httpClientForDownloadFile
=
OkHttpClient
.
Builder
()
.
followRedirects
(
true
)
.
followSslRedirects
(
true
)
.
addInterceptor
(
CookieInterceptor
(
DefaultCookieProvider
(
RocketChatCache
(
context
))))
.
build
()
}
...
...
@@ -37,7 +46,8 @@ object OkHttpHelper {
return
httpClientForWS
?:
throw
AssertionError
(
"httpClientForWS set to null by another thread"
)
}
private
var
httpClient
:
OkHttpClient
?
=
null
private
var
httpClientForUploadFile
:
OkHttpClient
?
=
null
private
var
httpClientForDownloadFile
:
OkHttpClient
?
=
null
private
var
httpClientForWS
:
OkHttpClient
?
=
null
}
\ No newline at end of file
}
app/src/test/kotlin/chat/rocket/android/api/rest/RestApiHelperTest.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.api.rest
import
chat.rocket.core.models.Room
import
org.junit.Test
import
kotlin.test.assertEquals
class
RestApiHelperTest
{
@Test
fun
getEndpointUrlForMessagesTest
()
{
assertEquals
(
"https://demo.rocket.chat/api/v1/channels.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_CHANNEL
,
"demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/groups.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_PRIVATE
,
"demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/dm.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_DIRECT_MESSAGE
,
"demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/channels.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_CHANNEL
,
"https://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/groups.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_PRIVATE
,
"https://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/dm.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_DIRECT_MESSAGE
,
"https://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/channels.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_CHANNEL
,
"http://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/groups.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_PRIVATE
,
"http://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/dm.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_DIRECT_MESSAGE
,
"http://demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/channels.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_CHANNEL
,
"www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/groups.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_PRIVATE
,
"www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/dm.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_DIRECT_MESSAGE
,
"www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/channels.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_CHANNEL
,
"https://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/groups.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_PRIVATE
,
"https://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/dm.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_DIRECT_MESSAGE
,
"https://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/channels.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_CHANNEL
,
"http://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/groups.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_PRIVATE
,
"http://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/dm.messages"
,
RestApiHelper
.
getEndpointUrlForMessages
(
Room
.
TYPE_DIRECT_MESSAGE
,
"http://www.demo.rocket.chat"
))
}
@Test
fun
getEndpointUrlForFileListTest
()
{
assertEquals
(
"https://demo.rocket.chat/api/v1/channels.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_CHANNEL
,
"demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/groups.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_PRIVATE
,
"demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/dm.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/channels.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_CHANNEL
,
"https://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/groups.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_PRIVATE
,
"https://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/dm.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"https://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/channels.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_CHANNEL
,
"http://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/groups.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_PRIVATE
,
"http://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/dm.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"http://demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/channels.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_CHANNEL
,
"www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/groups.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_PRIVATE
,
"www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/dm.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/channels.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_CHANNEL
,
"https://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/groups.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_PRIVATE
,
"https://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/dm.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"https://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/channels.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_CHANNEL
,
"http://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/groups.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_PRIVATE
,
"http://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/dm.files"
,
RestApiHelper
.
getEndpointUrlForFileList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"http://www.demo.rocket.chat"
))
}
@Test
fun
getEndpointUrlForMemberListTest
()
{
assertEquals
(
"https://demo.rocket.chat/api/v1/channels.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_CHANNEL
,
"demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/groups.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_PRIVATE
,
"demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/dm.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/channels.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_CHANNEL
,
"https://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/groups.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_PRIVATE
,
"https://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/dm.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"https://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/channels.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_CHANNEL
,
"http://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/groups.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_PRIVATE
,
"http://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat/api/v1/dm.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"http://demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/channels.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_CHANNEL
,
"www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/groups.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_PRIVATE
,
"www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/dm.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/channels.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_CHANNEL
,
"https://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/groups.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_PRIVATE
,
"https://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/dm.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"https://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/channels.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_CHANNEL
,
"http://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/groups.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_PRIVATE
,
"http://www.demo.rocket.chat"
))
assertEquals
(
"https://www.demo.rocket.chat/api/v1/dm.members"
,
RestApiHelper
.
getEndpointUrlForMemberList
(
Room
.
TYPE_DIRECT_MESSAGE
,
"http://www.demo.rocket.chat"
))
}
@Test
fun
getRestApiUrlForMessagesTest
()
{
assertEquals
(
"/api/v1/channels.messages"
,
RestApiHelper
.
getRestApiUrlForMessages
(
Room
.
TYPE_CHANNEL
))
assertEquals
(
"/api/v1/groups.messages"
,
RestApiHelper
.
getRestApiUrlForMessages
(
Room
.
TYPE_PRIVATE
))
assertEquals
(
"/api/v1/dm.messages"
,
RestApiHelper
.
getRestApiUrlForMessages
(
Room
.
TYPE_DIRECT_MESSAGE
))
}
@Test
fun
getRestApiUrlForFileListTest
()
{
assertEquals
(
"/api/v1/channels.files"
,
RestApiHelper
.
getRestApiUrlForFileList
(
Room
.
TYPE_CHANNEL
))
assertEquals
(
"/api/v1/groups.files"
,
RestApiHelper
.
getRestApiUrlForFileList
(
Room
.
TYPE_PRIVATE
))
assertEquals
(
"/api/v1/dm.files"
,
RestApiHelper
.
getRestApiUrlForFileList
(
Room
.
TYPE_DIRECT_MESSAGE
))
}
@Test
fun
getRestApiUrlForMemberListTest
()
{
assertEquals
(
"/api/v1/channels.members"
,
RestApiHelper
.
getRestApiUrlForMemberList
(
Room
.
TYPE_CHANNEL
))
assertEquals
(
"/api/v1/groups.members"
,
RestApiHelper
.
getRestApiUrlForMemberList
(
Room
.
TYPE_PRIVATE
))
assertEquals
(
"/api/v1/dm.members"
,
RestApiHelper
.
getRestApiUrlForMemberList
(
Room
.
TYPE_DIRECT_MESSAGE
))
}
}
\ No newline at end of file
app/src/test/kotlin/chat/rocket/android/helper/UrlHelperTest.kt
0 → 100644
View file @
9d8197a7
package
chat.rocket.android.helper
import
org.junit.Test
import
kotlin.test.assertEquals
class
UrlHelperTest
{
@Test
fun
removeUriSchemeTest
()
{
assertEquals
(
"demo.rocket.chat"
,
UrlHelper
.
removeUriScheme
(
"https://demo.rocket.chat"
))
assertEquals
(
"demo.rocket.chat"
,
UrlHelper
.
removeUriScheme
(
"http://demo.rocket.chat"
))
assertEquals
(
"demo.rocket.chat"
,
UrlHelper
.
removeUriScheme
(
"demo.rocket.chat"
))
}
@Test
fun
getSafeHostnameTest
()
{
assertEquals
(
"https://demo.rocket.chat"
,
UrlHelper
.
getSafeHostname
(
"https://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat"
,
UrlHelper
.
getSafeHostname
(
"http://demo.rocket.chat"
))
assertEquals
(
"https://demo.rocket.chat"
,
UrlHelper
.
getSafeHostname
(
"demo.rocket.chat"
))
}
@Test
fun
getUrlTest
()
{
assertEquals
(
"https://demo.rocket.chat/GENERAL/file.txt"
,
UrlHelper
.
getUrl
(
"https://demo.rocket.chat/GENERAL/file.txt"
))
assertEquals
(
"http://demo.rocket.chat/GENERAL/file.txt"
,
UrlHelper
.
getUrl
(
"http://demo.rocket.chat/GENERAL/file.txt"
))
assertEquals
(
"demo.rocket.chat/GENERAL/file.txt"
,
UrlHelper
.
getUrl
(
"demo.rocket.chat/GENERAL/file.txt"
))
assertEquals
(
"demo.rocket.chat/GENERAL/a%20sample%20file.txt"
,
UrlHelper
.
getUrl
(
"demo.rocket.chat/GENERAL/a sample file.txt"
))
assertEquals
(
"demo.rocket.chat/GENERAL/file.txt"
,
UrlHelper
.
getUrl
(
"demo.rocket.chat\\/GENERAL\\/file.txt"
))
}
@Test
fun
getUrlForFileTest
()
{
assertEquals
(
"https://demo.rocket.chat/GENERAL/file.txt?rc_uid=userId&rc_token=token"
,
UrlHelper
.
getUrlForFile
(
"https://demo.rocket.chat/GENERAL/file.txt"
,
"userId"
,
"token"
))
assertEquals
(
"https://demo.rocket.chat/GENERAL/file.txt?rc_uid=userId&rc_token=token"
,
UrlHelper
.
getUrlForFile
(
"http://demo.rocket.chat/GENERAL/file.txt"
,
"userId"
,
"token"
))
assertEquals
(
"https://demo.rocket.chat/GENERAL/file.txt?rc_uid=userId&rc_token=token"
,
UrlHelper
.
getUrlForFile
(
"demo.rocket.chat/GENERAL/file.txt"
,
"userId"
,
"token"
))
assertEquals
(
"https://demo.rocket.chat/GENERAL/a%20sample%20file.txt?rc_uid=userId&rc_token=token"
,
UrlHelper
.
getUrlForFile
(
"demo.rocket.chat/GENERAL/a sample file.txt"
,
"userId"
,
"token"
))
assertEquals
(
"https://demo.rocket.chat/GENERAL/file.txt?rc_uid=userId&rc_token=token"
,
UrlHelper
.
getUrlForFile
(
"demo.rocket.chat\\/GENERAL\\/file.txt"
,
"userId"
,
"token"
))
}
}
\ No newline at end of file
build.gradle
View file @
9d8197a7
...
...
@@ -22,7 +22,7 @@ ext {
buildToolsVersion
=
"26.0.0"
supportLibraryVersion
=
"25.4.0"
constraintLayoutVersion
=
"1.0.2"
kotlinVersion
=
"1.1.4-
2
"
kotlinVersion
=
"1.1.4-
3
"
okHttpVersion
=
"3.9.0"
}
...
...
rocket-chat-core/src/main/java/chat/rocket/core/models/User.java
View file @
9d8197a7
...
...
@@ -15,6 +15,9 @@ public abstract class User {
public
abstract
String
getId
();
@Nullable
public
abstract
String
getName
();
@Nullable
public
abstract
String
getUsername
();
...
...
@@ -38,6 +41,8 @@ public abstract class User {
public
abstract
Builder
setId
(
String
id
);
public
abstract
Builder
setName
(
String
name
);
public
abstract
Builder
setUsername
(
String
username
);
public
abstract
Builder
setStatus
(
String
status
);
...
...
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