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
349f73a3
Commit
349f73a3
authored
Apr 18, 2017
by
Tiago Cunha
Committed by
GitHub
Apr 18, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into feature/2fa
parents
1a41bf56
825b0b9f
Changes
67
Hide whitespace changes
Inline
Side-by-side
Showing
67 changed files
with
2465 additions
and
282 deletions
+2465
-282
build.gradle
app/build.gradle
+2
-2
BackgroundLooper.java
app/src/main/java/chat/rocket/android/BackgroundLooper.java
+2
-3
MethodCallHelper.java
...c/main/java/chat/rocket/android/api/MethodCallHelper.java
+38
-0
RoomFragment.java
...a/chat/rocket/android/fragment/chatroom/RoomFragment.java
+96
-9
AbsoluteUrlHelper.java
...in/java/chat/rocket/android/helper/AbsoluteUrlHelper.java
+1
-2
RocketChatUserStatusProvider.java
...rocket/android/renderer/RocketChatUserStatusProvider.java
+40
-0
UserRenderer.java
.../main/java/chat/rocket/android/renderer/UserRenderer.java
+1
-13
DeafultTempSpotlightRoomCaller.java
.../android/service/temp/DeafultTempSpotlightRoomCaller.java
+18
-0
DefaultTempSpotlightUserCaller.java
.../android/service/temp/DefaultTempSpotlightUserCaller.java
+18
-0
fragment_room_main.xml
app/src/main/res/layout/fragment_room_main.xml
+1
-0
Migration.java
...rc/main/java/chat/rocket/persistence/realm/Migration.java
+23
-2
RealmStore.java
...c/main/java/chat/rocket/persistence/realm/RealmStore.java
+3
-1
RocketChatPersistenceRealm.java
.../rocket/persistence/realm/RocketChatPersistenceRealm.java
+1
-9
RealmSpotlightRoom.java
...cket/persistence/realm/models/ddp/RealmSpotlightRoom.java
+51
-0
RealmSpotlightUser.java
...cket/persistence/realm/models/ddp/RealmSpotlightUser.java
+62
-0
RealmRepository.java
...ocket/persistence/realm/repositories/RealmRepository.java
+10
-0
RealmRoomRepository.java
...t/persistence/realm/repositories/RealmRoomRepository.java
+59
-0
RealmSpotlightRoomRepository.java
...ence/realm/repositories/RealmSpotlightRoomRepository.java
+63
-0
RealmSpotlightUserRepository.java
...ence/realm/repositories/RealmSpotlightUserRepository.java
+65
-0
RealmUserRepository.java
...t/persistence/realm/repositories/RealmUserRepository.java
+47
-0
build.gradle
rocket-chat-android-widgets/build.gradle
+7
-0
IconProvider.java
.../java/chat/rocket/android/widget/helper/IconProvider.java
+25
-0
UserStatusProvider.java
...chat/rocket/android/widget/helper/UserStatusProvider.java
+9
-0
ImageKeyboardEditText.java
.../rocket/android/widget/message/ImageKeyboardEditText.java
+2
-10
MessageFormLayout.java
...chat/rocket/android/widget/message/MessageFormLayout.java
+7
-1
AutocompleteAdapter.java
...roid/widget/message/autocomplete/AutocompleteAdapter.java
+64
-0
AutocompleteItem.java
...android/widget/message/autocomplete/AutocompleteItem.java
+9
-0
AutocompleteManager.java
...roid/widget/message/autocomplete/AutocompleteManager.java
+267
-0
AutocompleteSource.java
...droid/widget/message/autocomplete/AutocompleteSource.java
+50
-0
AutocompleteViewHolder.java
...d/widget/message/autocomplete/AutocompleteViewHolder.java
+19
-0
ChannelAdapter.java
...d/widget/message/autocomplete/channel/ChannelAdapter.java
+19
-0
ChannelItem.java
...roid/widget/message/autocomplete/channel/ChannelItem.java
+28
-0
ChannelSource.java
...id/widget/message/autocomplete/channel/ChannelSource.java
+111
-0
ChannelViewHolder.java
...idget/message/autocomplete/channel/ChannelViewHolder.java
+49
-0
UserAdapter.java
...android/widget/message/autocomplete/user/UserAdapter.java
+19
-0
UserItem.java
...et/android/widget/message/autocomplete/user/UserItem.java
+39
-0
UserSource.java
.../android/widget/message/autocomplete/user/UserSource.java
+115
-0
UserViewHolder.java
...roid/widget/message/autocomplete/user/UserViewHolder.java
+128
-0
autocomplete_background.xml
...widgets/src/main/res/drawable/autocomplete_background.xml
+16
-0
autocomplete_box.xml
...-android-widgets/src/main/res/layout/autocomplete_box.xml
+18
-0
autocomplete_channel_view.xml
...widgets/src/main/res/layout/autocomplete_channel_view.xml
+29
-0
autocomplete_user_view.xml
...id-widgets/src/main/res/layout/autocomplete_user_view.xml
+34
-0
strings.xml
rocket-chat-android-widgets/src/main/res/values/strings.xml
+2
-0
build.gradle
rocket-chat-core/build.gradle
+10
-6
SortDirection.java
...at-core/src/main/java/chat/rocket/core/SortDirection.java
+6
-0
AutocompleteChannelInteractor.kt
.../rocket/core/interactors/AutocompleteChannelInteractor.kt
+76
-0
AutocompleteUserInteractor.kt
...hat/rocket/core/interactors/AutocompleteUserInteractor.kt
+93
-0
CanCreateRoomInteractor.java
...chat/rocket/core/interactors/CanCreateRoomInteractor.java
+0
-28
CanCreateRoomInteractor.kt
...a/chat/rocket/core/interactors/CanCreateRoomInteractor.kt
+24
-0
MessageInteractor.java
.../java/chat/rocket/core/interactors/MessageInteractor.java
+0
-91
MessageInteractor.kt
...in/java/chat/rocket/core/interactors/MessageInteractor.kt
+79
-0
RoomInteractor.java
...ain/java/chat/rocket/core/interactors/RoomInteractor.java
+0
-42
RoomInteractor.kt
.../main/java/chat/rocket/core/interactors/RoomInteractor.kt
+45
-0
SessionInteractor.java
.../java/chat/rocket/core/interactors/SessionInteractor.java
+0
-63
SessionInteractor.kt
...in/java/chat/rocket/core/interactors/SessionInteractor.kt
+59
-0
UserInteractor.java
...ain/java/chat/rocket/core/interactors/UserInteractor.java
+21
-0
SpotlightRoom.java
.../src/main/java/chat/rocket/core/models/SpotlightRoom.java
+41
-0
SpotlightUser.java
.../src/main/java/chat/rocket/core/models/SpotlightUser.java
+37
-0
RoomRepository.java
...in/java/chat/rocket/core/repositories/RoomRepository.java
+5
-0
SpotlightRoomRepository.java
...hat/rocket/core/repositories/SpotlightRoomRepository.java
+12
-0
SpotlightUserRepository.java
...hat/rocket/core/repositories/SpotlightUserRepository.java
+12
-0
UserRepository.java
...in/java/chat/rocket/core/repositories/UserRepository.java
+4
-0
TempSpotlightRoomCaller.java
...n/java/chat/rocket/core/temp/TempSpotlightRoomCaller.java
+6
-0
TempSpotlightUserCaller.java
...n/java/chat/rocket/core/temp/TempSpotlightUserCaller.java
+6
-0
Pair.java
...-chat-core/src/main/java/chat/rocket/core/utils/Pair.java
+82
-0
Triple.java
...hat-core/src/main/java/chat/rocket/core/utils/Triple.java
+38
-0
AutocompleteChannelInteractorTest.java
...t/core/interactors/AutocompleteChannelInteractorTest.java
+142
-0
No files found.
app/build.gradle
View file @
349f73a3
...
...
@@ -33,8 +33,8 @@ android {
applicationId
"chat.rocket.android"
minSdkVersion
16
targetSdkVersion
25
versionCode
17
versionName
"1.0.
8
"
versionCode
20
versionName
"1.0.
10
"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
vectorDrawables
.
useSupportLibrary
=
true
...
...
app/src/main/java/chat/rocket/android/BackgroundLooper.java
View file @
349f73a3
package
chat
.
rocket
.
android
;
import
android.os.HandlerThread
;
import
android.os.Looper
;
import
android.os.Process
;
...
...
@@ -11,8 +10,8 @@ public class BackgroundLooper {
public
static
Looper
get
()
{
if
(
handlerThread
==
null
)
{
handlerThread
=
new
HandlerThread
(
"BackgroundHandlerThread"
,
Process
.
THREAD_PRIORITY_BACKGROUND
);
handlerThread
=
new
HandlerThread
(
"BackgroundHandlerThread"
,
Process
.
THREAD_PRIORITY_BACKGROUND
);
handlerThread
.
start
();
}
...
...
app/src/main/java/chat/rocket/android/api/MethodCallHelper.java
View file @
349f73a3
...
...
@@ -16,6 +16,8 @@ import chat.rocket.persistence.realm.models.ddp.RealmPublicSetting;
import
chat.rocket.core.SyncState
;
import
chat.rocket.persistence.realm.models.ddp.RealmMessage
;
import
chat.rocket.persistence.realm.models.ddp.RealmRoom
;
import
chat.rocket.persistence.realm.models.ddp.RealmSpotlightRoom
;
import
chat.rocket.persistence.realm.models.ddp.RealmSpotlightUser
;
import
chat.rocket.persistence.realm.models.internal.MethodCall
;
import
chat.rocket.persistence.realm.models.internal.RealmSession
;
import
chat.rocket.persistence.realm.RealmHelper
;
...
...
@@ -372,6 +374,42 @@ public class MethodCallHelper {
});
}
public
Task
<
Void
>
searchSpotlightUsers
(
String
term
)
{
return
searchSpotlight
(
RealmSpotlightUser
.
class
,
"users"
,
term
);
}
public
Task
<
Void
>
searchSpotlightRooms
(
String
term
)
{
return
searchSpotlight
(
RealmSpotlightRoom
.
class
,
"rooms"
,
term
);
}
private
Task
<
Void
>
searchSpotlight
(
Class
clazz
,
String
key
,
String
term
)
{
return
call
(
"spotlight"
,
TIMEOUT_MS
,
()
->
new
JSONArray
()
.
put
(
term
)
.
put
(
JSONObject
.
NULL
)
.
put
(
new
JSONObject
().
put
(
key
,
true
)))
.
onSuccessTask
(
CONVERT_TO_JSON_OBJECT
)
.
onSuccessTask
(
task
->
{
final
JSONObject
result
=
task
.
getResult
();
if
(!
result
.
has
(
key
))
{
return
null
;
}
Object
items
=
result
.
get
(
key
);
if
(!(
items
instanceof
JSONArray
))
{
return
null
;
}
return
realmHelper
.
executeTransaction
(
realm
->
{
realm
.
delete
(
clazz
);
realm
.
createOrUpdateAllFromJson
(
clazz
,
(
JSONArray
)
items
);
return
null
;
});
});
}
protected
interface
ParamBuilder
{
JSONArray
buildParam
()
throws
JSONException
;
...
...
app/src/main/java/chat/rocket/android/fragment/chatroom/RoomFragment.java
View file @
349f73a3
package
chat
.
rocket
.
android
.
fragment
.
chatroom
;
import
android.Manifest
;
import
android.annotation.SuppressLint
;
import
android.app.Activity
;
import
android.content.Intent
;
import
android.net.Uri
;
...
...
@@ -13,6 +12,7 @@ import android.support.v13.view.inputmethod.InputConnectionCompat;
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
;
...
...
@@ -20,12 +20,20 @@ import android.support.v7.app.AlertDialog;
import
android.support.v7.widget.LinearLayoutManager
;
import
android.support.v7.widget.RecyclerView
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
com.fernandocejas.arrow.optional.Optional
;
import
com.jakewharton.rxbinding2.support.v4.widget.RxDrawerLayout
;
import
io.reactivex.Single
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.CompositeDisposable
;
import
io.reactivex.disposables.Disposable
;
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.api.MethodCallHelper
;
import
chat.rocket.android.fragment.chatroom.dialog.FileUploadProgressDialogFragment
;
...
...
@@ -49,6 +57,14 @@ import chat.rocket.android.layouthelper.extra_action.upload.AudioUploadActionIte
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.temp.DeafultTempSpotlightRoomCaller
;
import
chat.rocket.android.service.temp.DefaultTempSpotlightUserCaller
;
import
chat.rocket.android.widget.message.autocomplete.AutocompleteManager
;
import
chat.rocket.android.widget.message.autocomplete.channel.ChannelSource
;
import
chat.rocket.android.widget.message.autocomplete.user.UserSource
;
import
chat.rocket.core.interactors.AutocompleteChannelInteractor
;
import
chat.rocket.core.interactors.AutocompleteUserInteractor
;
import
chat.rocket.core.interactors.MessageInteractor
;
import
chat.rocket.core.interactors.SessionInteractor
;
import
chat.rocket.core.models.Message
;
...
...
@@ -57,6 +73,8 @@ import chat.rocket.persistence.realm.repositories.RealmMessageRepository;
import
chat.rocket.persistence.realm.repositories.RealmRoomRepository
;
import
chat.rocket.persistence.realm.repositories.RealmServerInfoRepository
;
import
chat.rocket.persistence.realm.repositories.RealmSessionRepository
;
import
chat.rocket.persistence.realm.repositories.RealmSpotlightRoomRepository
;
import
chat.rocket.persistence.realm.repositories.RealmSpotlightUserRepository
;
import
chat.rocket.persistence.realm.repositories.RealmUserRepository
;
import
chat.rocket.android.layouthelper.chatroom.ModelListAdapter
;
import
chat.rocket.persistence.realm.RealmStore
;
...
...
@@ -87,11 +105,19 @@ public class RoomFragment extends AbstractChatRoomFragment
protected
Snackbar
unreadIndicator
;
private
boolean
previousUnreadMessageExists
;
private
MessageListAdapter
adapter
;
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
;
public
RoomFragment
()
{
}
...
...
@@ -117,29 +143,31 @@ public class RoomFragment extends AbstractChatRoomFragment
hostname
=
args
.
getString
(
HOSTNAME
);
roomId
=
args
.
getString
(
ROOM_ID
);
RealmRoomRepository
roomRepository
=
new
RealmRoomRepository
(
hostname
);
roomRepository
=
new
RealmRoomRepository
(
hostname
);
MessageInteractor
messageInteractor
=
new
MessageInteractor
(
new
RealmMessageRepository
(
hostname
),
roomRepository
);
RealmUserRepository
userRepository
=
new
RealmUserRepository
(
hostname
);
userRepository
=
new
RealmUserRepository
(
hostname
);
AbsoluteUrlHelper
absoluteUrlHelper
=
new
AbsoluteUrlHelper
(
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
,
new
MethodCallHelper
(
getContext
(),
hostname
)
,
methodCallHelper
,
ConnectivityManager
.
getInstance
(
getContext
())
);
...
...
@@ -238,6 +266,14 @@ public class RoomFragment extends AbstractChatRoomFragment
adapter
.
unregisterAdapterDataObserver
(
autoScrollManager
);
}
}
compositeDisposable
.
clear
();
if
(
autocompleteManager
!=
null
)
{
autocompleteManager
.
dispose
();
autocompleteManager
=
null
;
}
super
.
onDestroyView
();
}
...
...
@@ -246,7 +282,6 @@ public class RoomFragment extends AbstractChatRoomFragment
presenter
.
onMessageSelected
(
pairedMessage
.
target
);
}
@SuppressLint
(
"RxLeakedSubscription"
)
private
void
setupSideMenu
()
{
View
sideMenu
=
rootView
.
findViewById
(
R
.
id
.
room_side_menu
);
sideMenu
.
findViewById
(
R
.
id
.
btn_users
).
setOnClickListener
(
view
->
{
...
...
@@ -258,7 +293,7 @@ public class RoomFragment extends AbstractChatRoomFragment
DrawerLayout
drawerLayout
=
(
DrawerLayout
)
rootView
.
findViewById
(
R
.
id
.
drawer_layout
);
SlidingPaneLayout
pane
=
(
SlidingPaneLayout
)
getActivity
().
findViewById
(
R
.
id
.
sliding_pane
);
if
(
drawerLayout
!=
null
&&
pane
!=
null
)
{
RxDrawerLayout
.
drawerOpen
(
drawerLayout
,
GravityCompat
.
END
)
compositeDisposable
.
add
(
RxDrawerLayout
.
drawerOpen
(
drawerLayout
,
GravityCompat
.
END
)
.
compose
(
bindToLifecycle
())
.
subscribe
(
opened
->
{
...
...
@@ -271,7 +306,8 @@ public class RoomFragment extends AbstractChatRoomFragment
}
},
Logger:
:
report
);
)
);
}
}
...
...
@@ -290,7 +326,58 @@ public class RoomFragment extends AbstractChatRoomFragment
messageFormManager
=
new
MessageFormManager
(
messageFormLayout
,
this
::
showExtraActionSelectionDialog
);
messageFormManager
.
setSendMessageCallback
(
this
::
sendMessage
);
messageFormLayout
.
setEditTextContentListener
(
this
::
onCommitContent
);
messageFormLayout
.
setEditTextCommitContentListener
(
this
::
onCommitContent
);
autocompleteManager
=
new
AutocompleteManager
((
ViewGroup
)
rootView
.
findViewById
(
R
.
id
.
message_list_root
));
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
)
),
pair
.
first
.
get
(),
RocketChatUserStatusProvider
.
getInstance
(),
AndroidSchedulers
.
from
(
BackgroundLooper
.
get
()),
AndroidSchedulers
.
mainThread
()
)
);
}
},
throwable
->
{
}
);
compositeDisposable
.
add
(
disposable
);
autocompleteManager
.
bindTo
(
messageFormLayout
.
getEditText
(),
messageFormLayout
);
}
@Override
...
...
app/src/main/java/chat/rocket/android/helper/AbsoluteUrlHelper.java
View file @
349f73a3
...
...
@@ -38,8 +38,7 @@ public class AbsoluteUrlHelper {
.
filter
(
Optional:
:
isPresent
)
.
map
(
Optional:
:
get
),
(
info
,
user
,
session
)
->
Optional
.
of
(
new
RocketChatAbsoluteUrl
(
info
,
user
,
session
info
,
user
,
session
))
)
.
first
(
Optional
.
absent
());
...
...
app/src/main/java/chat/rocket/android/renderer/RocketChatUserStatusProvider.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
renderer
;
import
android.support.annotation.DrawableRes
;
import
chat.rocket.android.R
;
import
chat.rocket.android.widget.helper.UserStatusProvider
;
import
chat.rocket.core.models.User
;
public
class
RocketChatUserStatusProvider
implements
UserStatusProvider
{
private
static
RocketChatUserStatusProvider
instance
;
private
RocketChatUserStatusProvider
()
{
}
public
static
RocketChatUserStatusProvider
getInstance
()
{
if
(
instance
==
null
)
{
instance
=
new
RocketChatUserStatusProvider
();
}
return
instance
;
}
@Override
@DrawableRes
public
int
getStatusResId
(
String
status
)
{
if
(
User
.
STATUS_ONLINE
.
equals
(
status
))
{
return
R
.
drawable
.
userstatus_online
;
}
else
if
(
User
.
STATUS_AWAY
.
equals
(
status
))
{
return
R
.
drawable
.
userstatus_away
;
}
else
if
(
User
.
STATUS_BUSY
.
equals
(
status
))
{
return
R
.
drawable
.
userstatus_busy
;
}
else
if
(
User
.
STATUS_OFFLINE
.
equals
(
status
))
{
return
R
.
drawable
.
userstatus_offline
;
}
// unknown status is rendered as "offline" status.
return
R
.
drawable
.
userstatus_offline
;
}
}
app/src/main/java/chat/rocket/android/renderer/UserRenderer.java
View file @
349f73a3
...
...
@@ -4,7 +4,6 @@ import android.content.Context;
import
android.widget.ImageView
;
import
android.widget.TextView
;
import
chat.rocket.android.R
;
import
chat.rocket.android.helper.Avatar
;
import
chat.rocket.android.helper.TextUtils
;
import
chat.rocket.android.widget.AbsoluteUrl
;
...
...
@@ -56,18 +55,7 @@ public class UserRenderer extends AbstractRenderer<User> {
}
String
status
=
object
.
getStatus
();
if
(
User
.
STATUS_ONLINE
.
equals
(
status
))
{
imageView
.
setImageResource
(
R
.
drawable
.
userstatus_online
);
}
else
if
(
User
.
STATUS_AWAY
.
equals
(
status
))
{
imageView
.
setImageResource
(
R
.
drawable
.
userstatus_away
);
}
else
if
(
User
.
STATUS_BUSY
.
equals
(
status
))
{
imageView
.
setImageResource
(
R
.
drawable
.
userstatus_busy
);
}
else
if
(
User
.
STATUS_OFFLINE
.
equals
(
status
))
{
imageView
.
setImageResource
(
R
.
drawable
.
userstatus_offline
);
}
else
{
// unknown status is rendered as "offline" status.
imageView
.
setImageResource
(
R
.
drawable
.
userstatus_offline
);
}
imageView
.
setImageResource
(
RocketChatUserStatusProvider
.
getInstance
().
getStatusResId
(
status
));
return
this
;
}
...
...
app/src/main/java/chat/rocket/android/service/temp/DeafultTempSpotlightRoomCaller.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
service
.
temp
;
import
chat.rocket.android.api.MethodCallHelper
;
import
chat.rocket.core.temp.TempSpotlightRoomCaller
;
public
class
DeafultTempSpotlightRoomCaller
implements
TempSpotlightRoomCaller
{
private
final
MethodCallHelper
methodCallHelper
;
public
DeafultTempSpotlightRoomCaller
(
MethodCallHelper
methodCallHelper
)
{
this
.
methodCallHelper
=
methodCallHelper
;
}
@Override
public
void
search
(
String
term
)
{
methodCallHelper
.
searchSpotlightRooms
(
term
);
}
}
app/src/main/java/chat/rocket/android/service/temp/DefaultTempSpotlightUserCaller.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
service
.
temp
;
import
chat.rocket.android.api.MethodCallHelper
;
import
chat.rocket.core.temp.TempSpotlightUserCaller
;
public
class
DefaultTempSpotlightUserCaller
implements
TempSpotlightUserCaller
{
private
final
MethodCallHelper
methodCallHelper
;
public
DefaultTempSpotlightUserCaller
(
MethodCallHelper
methodCallHelper
)
{
this
.
methodCallHelper
=
methodCallHelper
;
}
@Override
public
void
search
(
String
term
)
{
methodCallHelper
.
searchSpotlightUsers
(
term
);
}
}
app/src/main/res/layout/fragment_room_main.xml
View file @
349f73a3
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:id=
"@+id/message_list_root"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
...
...
persistence-realm/src/main/java/chat/rocket/persistence/realm/Migration.java
View file @
349f73a3
package
chat
.
rocket
.
persistence
.
realm
;
import
io.realm.DynamicRealm
;
import
io.realm.FieldAttribute
;
import
io.realm.RealmMigration
;
import
io.realm.RealmObjectSchema
;
import
io.realm.RealmSchema
;
import
chat.rocket.persistence.realm.models.ddp.RealmSpotlightRoom
;
import
chat.rocket.persistence.realm.models.ddp.RealmSpotlightUser
;
public
class
Migration
implements
RealmMigration
{
@Override
public
void
migrate
(
DynamicRealm
dynamicRealm
,
long
oldVersion
,
long
newVersion
)
{
...
...
@@ -12,11 +16,28 @@ public class Migration implements RealmMigration {
RealmSchema
schema
=
dynamicRealm
.
getSchema
();
if
(
oldVersion
==
0
)
{
RealmObjectSchema
roomSchema
=
schema
.
get
(
"RealmRoom"
);
// NOOP
oldVersion
++;
}
if
(
oldVersion
==
1
)
{
schema
.
create
(
"RealmSpotlightUser"
)
.
addField
(
RealmSpotlightUser
.
Columns
.
ID
,
String
.
class
,
FieldAttribute
.
PRIMARY_KEY
)
.
addField
(
RealmSpotlightUser
.
Columns
.
USERNAME
,
String
.
class
)
.
addField
(
RealmSpotlightUser
.
Columns
.
STATUS
,
String
.
class
);
roomSchema
.
addField
(
"f"
,
boolean
.
class
);
schema
.
create
(
"RealmSpotlightRoom"
)
.
addField
(
RealmSpotlightRoom
.
Columns
.
ID
,
String
.
class
,
FieldAttribute
.
PRIMARY_KEY
)
.
addField
(
RealmSpotlightRoom
.
Columns
.
NAME
,
String
.
class
)
.
addField
(
RealmSpotlightRoom
.
Columns
.
TYPE
,
String
.
class
);
oldVersion
++;
}
if
(
oldVersion
==
2
)
{
RealmObjectSchema
roomSchema
=
schema
.
get
(
"RealmSpotlightUser"
);
roomSchema
.
addField
(
RealmSpotlightUser
.
Columns
.
NAME
,
String
.
class
);
}
}
}
persistence-realm/src/main/java/chat/rocket/persistence/realm/RealmStore.java
View file @
349f73a3
...
...
@@ -14,7 +14,9 @@ public class RealmStore {
return
new
RealmConfiguration
.
Builder
()
.
name
(
name
+
".realm"
)
.
modules
(
new
RocketChatLibraryModule
())
.
deleteRealmIfMigrationNeeded
().
build
();
.
migration
(
new
Migration
())
.
schemaVersion
(
3
)
.
build
();
}
public
static
void
put
(
String
name
)
{
...
...
persistence-realm/src/main/java/chat/rocket/persistence/realm/RocketChatPersistenceRealm.java
View file @
349f73a3
...
...
@@ -4,19 +4,11 @@ import android.content.Context;
import
io.realm.Realm
;
import
io.realm.RealmConfiguration
;
import
chat.rocket.persistence.realm.modules.RocketChatLibraryModule
;
public
class
RocketChatPersistenceRealm
{
public
static
void
init
(
Context
context
)
{
Realm
.
init
(
context
);
Realm
.
setDefaultConfiguration
(
new
RealmConfiguration
.
Builder
()
.
name
(
"rocket.chat.persistence.realm"
)
.
modules
(
new
RocketChatLibraryModule
())
.
schemaVersion
(
1
)
.
migration
(
new
Migration
())
.
build
());
Realm
.
setDefaultConfiguration
(
new
RealmConfiguration
.
Builder
().
build
());
}
}
persistence-realm/src/main/java/chat/rocket/persistence/realm/models/ddp/RealmSpotlightRoom.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
persistence
.
realm
.
models
.
ddp
;
import
io.realm.RealmObject
;
import
io.realm.annotations.PrimaryKey
;
import
chat.rocket.core.models.SpotlightRoom
;
public
class
RealmSpotlightRoom
extends
RealmObject
{
public
interface
Columns
{
String
ID
=
"_id"
;
String
NAME
=
"name"
;
String
TYPE
=
"t"
;
}
@PrimaryKey
private
String
_id
;
private
String
name
;
private
String
t
;
public
String
getId
()
{
return
_id
;
}
public
void
setId
(
String
_id
)
{
this
.
_id
=
_id
;
}
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getType
()
{
return
t
;
}
public
void
setType
(
String
t
)
{
this
.
t
=
t
;
}
public
SpotlightRoom
asSpotlightRoom
()
{
return
SpotlightRoom
.
builder
()
.
setId
(
_id
)
.
setName
(
name
)
.
setType
(
t
)
.
build
();
}
}
persistence-realm/src/main/java/chat/rocket/persistence/realm/models/ddp/RealmSpotlightUser.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
persistence
.
realm
.
models
.
ddp
;
import
io.realm.RealmObject
;
import
io.realm.annotations.PrimaryKey
;
import
chat.rocket.core.models.SpotlightUser
;
public
class
RealmSpotlightUser
extends
RealmObject
{
public
interface
Columns
{
String
ID
=
"_id"
;
String
USERNAME
=
"username"
;
String
NAME
=
"name"
;
String
STATUS
=
"status"
;
}
@PrimaryKey
private
String
_id
;
private
String
username
;
private
String
name
;
private
String
status
;
public
String
getId
()
{
return
_id
;
}
public
void
setId
(
String
_id
)
{
this
.
_id
=
_id
;
}
public
String
getUsername
()
{
return
username
;
}
public
void
setUsername
(
String
username
)
{
this
.
username
=
username
;
}
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getStatus
()
{
return
status
;
}
public
void
setStatus
(
String
status
)
{
this
.
status
=
status
;
}
public
SpotlightUser
asSpotlightUser
()
{
return
SpotlightUser
.
builder
()
.
setId
(
_id
)
.
setUsername
(
username
)
.
setName
(
name
)
.
setStatus
(
status
)
.
build
();
}
}
persistence-realm/src/main/java/chat/rocket/persistence/realm/repositories/RealmRepository.java
View file @
349f73a3
...
...
@@ -3,6 +3,10 @@ package chat.rocket.persistence.realm.repositories;
import
android.os.Handler
;
import
android.os.Looper
;
import
io.realm.Realm
;
import
io.realm.RealmObject
;
import
io.realm.RealmResults
;
import
java.util.List
;
public
class
RealmRepository
{
...
...
@@ -12,4 +16,10 @@ public class RealmRepository {
}
new
Handler
(
looper
).
post
(
realm:
:
close
);
}
protected
<
T
extends
RealmObject
>
List
<
T
>
safeSubList
(
RealmResults
<
T
>
realmObjects
,
int
fromIndex
,
int
toIndex
)
{
return
realmObjects
.
subList
(
Math
.
max
(
0
,
fromIndex
),
Math
.
min
(
realmObjects
.
size
(),
toIndex
));
}
}
persistence-realm/src/main/java/chat/rocket/persistence/realm/repositories/RealmRoomRepository.java
View file @
349f73a3
...
...
@@ -6,11 +6,14 @@ import com.fernandocejas.arrow.optional.Optional;
import
io.reactivex.Flowable
;
import
io.reactivex.Single
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.realm.Case
;
import
io.realm.Realm
;
import
io.realm.RealmResults
;
import
io.realm.Sort
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.core.SortDirection
;
import
chat.rocket.core.models.Room
;
import
chat.rocket.core.models.RoomHistoryState
;
import
chat.rocket.core.repositories.RoomRepository
;
...
...
@@ -141,6 +144,50 @@ public class RealmRoomRepository extends RealmRepository implements RoomReposito
});
}
@Override
public
Flowable
<
List
<
Room
>>
getSortedLikeName
(
String
name
,
SortDirection
direction
,
int
limit
)
{
return
Flowable
.
defer
(()
->
Flowable
.
using
(
()
->
new
Pair
<>(
RealmStore
.
getRealm
(
hostname
),
Looper
.
myLooper
()),
pair
->
RxJavaInterop
.
toV2Flowable
(
pair
.
first
.
where
(
RealmRoom
.
class
)
.
like
(
RealmRoom
.
NAME
,
"*"
+
name
+
"*"
,
Case
.
INSENSITIVE
)
.
beginGroup
()
.
equalTo
(
RealmRoom
.
TYPE
,
RealmRoom
.
TYPE_CHANNEL
)
.
or
()
.
equalTo
(
RealmRoom
.
TYPE
,
RealmRoom
.
TYPE_PRIVATE
)
.
endGroup
()
.
findAllSorted
(
RealmRoom
.
NAME
,
direction
.
equals
(
SortDirection
.
ASC
)
?
Sort
.
ASCENDING
:
Sort
.
DESCENDING
)
.
asObservable
()),
pair
->
close
(
pair
.
first
,
pair
.
second
)
)
.
unsubscribeOn
(
AndroidSchedulers
.
from
(
Looper
.
myLooper
()))
.
filter
(
roomSubscriptions
->
roomSubscriptions
!=
null
&&
roomSubscriptions
.
isLoaded
()
&&
roomSubscriptions
.
isValid
())
.
map
(
realmRooms
->
toList
(
safeSubList
(
realmRooms
,
0
,
limit
))));
}
@Override
public
Flowable
<
List
<
Room
>>
getLatestSeen
(
int
limit
)
{
return
Flowable
.
defer
(()
->
Flowable
.
using
(
()
->
new
Pair
<>(
RealmStore
.
getRealm
(
hostname
),
Looper
.
myLooper
()),
pair
->
RxJavaInterop
.
toV2Flowable
(
pair
.
first
.
where
(
RealmRoom
.
class
)
.
beginGroup
()
.
equalTo
(
RealmRoom
.
TYPE
,
RealmRoom
.
TYPE_CHANNEL
)
.
or
()
.
equalTo
(
RealmRoom
.
TYPE
,
RealmRoom
.
TYPE_PRIVATE
)
.
endGroup
()
.
findAllSorted
(
RealmRoom
.
LAST_SEEN
,
Sort
.
ASCENDING
)
.
asObservable
()),
pair
->
close
(
pair
.
first
,
pair
.
second
)
)
.
unsubscribeOn
(
AndroidSchedulers
.
from
(
Looper
.
myLooper
()))
.
filter
(
roomSubscriptions
->
roomSubscriptions
!=
null
&&
roomSubscriptions
.
isLoaded
()
&&
roomSubscriptions
.
isValid
())
.
map
(
realmRooms
->
toList
(
safeSubList
(
realmRooms
,
0
,
limit
))));
}
private
List
<
Room
>
toList
(
RealmResults
<
RealmRoom
>
realmRooms
)
{
int
total
=
realmRooms
.
size
();
...
...
@@ -152,4 +199,16 @@ public class RealmRoomRepository extends RealmRepository implements RoomReposito
return
roomList
;
}
private
List
<
Room
>
toList
(
List
<
RealmRoom
>
realmRooms
)
{
int
total
=
realmRooms
.
size
();
final
List
<
Room
>
roomList
=
new
ArrayList
<>(
total
);
for
(
int
i
=
0
;
i
<
total
;
i
++)
{
roomList
.
add
(
realmRooms
.
get
(
i
).
asRoom
());
}
return
roomList
;
}
}
persistence-realm/src/main/java/chat/rocket/persistence/realm/repositories/RealmSpotlightRoomRepository.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
persistence
.
realm
.
repositories
;
import
android.os.Looper
;
import
android.support.v4.util.Pair
;
import
io.reactivex.Flowable
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.realm.Case
;
import
io.realm.Sort
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.core.SortDirection
;
import
chat.rocket.core.models.SpotlightRoom
;
import
chat.rocket.core.repositories.SpotlightRoomRepository
;
import
chat.rocket.persistence.realm.RealmStore
;
import
chat.rocket.persistence.realm.models.ddp.RealmRoom
;
import
chat.rocket.persistence.realm.models.ddp.RealmSpotlightRoom
;
import
hu.akarnokd.rxjava.interop.RxJavaInterop
;
public
class
RealmSpotlightRoomRepository
extends
RealmRepository
implements
SpotlightRoomRepository
{
private
final
String
hostname
;
public
RealmSpotlightRoomRepository
(
String
hostname
)
{
this
.
hostname
=
hostname
;
}
@Override
public
Flowable
<
List
<
SpotlightRoom
>>
getSuggestionsFor
(
String
name
,
SortDirection
direction
,
int
limit
)
{
return
Flowable
.
defer
(()
->
Flowable
.
using
(
()
->
new
Pair
<>(
RealmStore
.
getRealm
(
hostname
),
Looper
.
myLooper
()),
pair
->
RxJavaInterop
.
toV2Flowable
(
pair
.
first
.
where
(
RealmSpotlightRoom
.
class
)
.
like
(
RealmSpotlightRoom
.
Columns
.
NAME
,
"*"
+
name
+
"*"
,
Case
.
INSENSITIVE
)
.
beginGroup
()
.
equalTo
(
RealmSpotlightRoom
.
Columns
.
TYPE
,
RealmRoom
.
TYPE_CHANNEL
)
.
or
()
.
equalTo
(
RealmSpotlightRoom
.
Columns
.
TYPE
,
RealmRoom
.
TYPE_PRIVATE
)
.
endGroup
()
.
findAllSorted
(
RealmSpotlightRoom
.
Columns
.
NAME
,
direction
.
equals
(
SortDirection
.
ASC
)
?
Sort
.
ASCENDING
:
Sort
.
DESCENDING
)
.
asObservable
()),
pair
->
close
(
pair
.
first
,
pair
.
second
)
)
.
unsubscribeOn
(
AndroidSchedulers
.
from
(
Looper
.
myLooper
()))
.
filter
(
it
->
it
!=
null
&&
it
.
isLoaded
()
&&
it
.
isValid
())
.
map
(
realmSpotlightRooms
->
toList
(
safeSubList
(
realmSpotlightRooms
,
0
,
limit
))));
}
private
List
<
SpotlightRoom
>
toList
(
List
<
RealmSpotlightRoom
>
realmSpotlightRooms
)
{
int
total
=
realmSpotlightRooms
.
size
();
final
List
<
SpotlightRoom
>
spotlightRooms
=
new
ArrayList
<>(
total
);
for
(
int
i
=
0
;
i
<
total
;
i
++)
{
spotlightRooms
.
add
(
realmSpotlightRooms
.
get
(
i
).
asSpotlightRoom
());
}
return
spotlightRooms
;
}
}
persistence-realm/src/main/java/chat/rocket/persistence/realm/repositories/RealmSpotlightUserRepository.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
persistence
.
realm
.
repositories
;
import
android.os.Looper
;
import
android.support.v4.util.Pair
;
import
io.reactivex.Flowable
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.realm.Case
;
import
io.realm.Sort
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.core.SortDirection
;
import
chat.rocket.core.models.SpotlightUser
;
import
chat.rocket.core.repositories.SpotlightUserRepository
;
import
chat.rocket.persistence.realm.RealmStore
;
import
chat.rocket.persistence.realm.models.ddp.RealmSpotlightUser
;
import
hu.akarnokd.rxjava.interop.RxJavaInterop
;
public
class
RealmSpotlightUserRepository
extends
RealmRepository
implements
SpotlightUserRepository
{
private
final
String
hostname
;
public
RealmSpotlightUserRepository
(
String
hostname
)
{
this
.
hostname
=
hostname
;
}
@Override
public
Flowable
<
List
<
SpotlightUser
>>
getSuggestionsFor
(
String
name
,
SortDirection
direction
,
int
limit
)
{
return
Flowable
.
defer
(()
->
Flowable
.
using
(
()
->
new
Pair
<>(
RealmStore
.
getRealm
(
hostname
),
Looper
.
myLooper
()),
pair
->
RxJavaInterop
.
toV2Flowable
(
pair
.
first
.
where
(
RealmSpotlightUser
.
class
)
.
beginGroup
()
.
like
(
RealmSpotlightUser
.
Columns
.
USERNAME
,
"*"
+
name
+
"*"
,
Case
.
INSENSITIVE
)
.
isNull
(
RealmSpotlightUser
.
Columns
.
NAME
)
.
endGroup
()
.
or
()
.
beginGroup
()
.
like
(
RealmSpotlightUser
.
Columns
.
NAME
,
"*"
+
name
+
"*"
,
Case
.
INSENSITIVE
)
.
isNotNull
(
RealmSpotlightUser
.
Columns
.
USERNAME
)
.
endGroup
()
.
findAllSorted
(
RealmSpotlightUser
.
Columns
.
USERNAME
,
direction
.
equals
(
SortDirection
.
ASC
)
?
Sort
.
ASCENDING
:
Sort
.
DESCENDING
)
.
asObservable
()),
pair
->
close
(
pair
.
first
,
pair
.
second
)
)
.
unsubscribeOn
(
AndroidSchedulers
.
from
(
Looper
.
myLooper
()))
.
filter
(
it
->
it
!=
null
&&
it
.
isLoaded
()
&&
it
.
isValid
())
.
map
(
realmSpotlightUsers
->
toList
(
safeSubList
(
realmSpotlightUsers
,
0
,
limit
))));
}
private
List
<
SpotlightUser
>
toList
(
List
<
RealmSpotlightUser
>
realmSpotlightUsers
)
{
int
total
=
realmSpotlightUsers
.
size
();
final
List
<
SpotlightUser
>
spotlightUsers
=
new
ArrayList
<>(
total
);
for
(
int
i
=
0
;
i
<
total
;
i
++)
{
spotlightUsers
.
add
(
realmSpotlightUsers
.
get
(
i
).
asSpotlightUser
());
}
return
spotlightUsers
;
}
}
persistence-realm/src/main/java/chat/rocket/persistence/realm/repositories/RealmUserRepository.java
View file @
349f73a3
...
...
@@ -5,8 +5,13 @@ import android.support.v4.util.Pair;
import
com.fernandocejas.arrow.optional.Optional
;
import
io.reactivex.Flowable
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.realm.Case
;
import
io.realm.RealmResults
;
import
io.realm.Sort
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.core.SortDirection
;
import
chat.rocket.core.models.User
;
import
chat.rocket.core.repositories.UserRepository
;
import
chat.rocket.persistence.realm.RealmStore
;
...
...
@@ -43,4 +48,46 @@ public class RealmUserRepository extends RealmRepository implements UserReposito
return
Optional
.<
User
>
absent
();
}));
}
@Override
public
Flowable
<
List
<
User
>>
getSortedLikeName
(
String
name
,
SortDirection
direction
,
int
limit
)
{
return
Flowable
.
defer
(()
->
Flowable
.
using
(
()
->
new
Pair
<>(
RealmStore
.
getRealm
(
hostname
),
Looper
.
myLooper
()),
pair
->
RxJavaInterop
.
toV2Flowable
(
pair
.
first
.
where
(
RealmUser
.
class
)
.
like
(
RealmUser
.
USERNAME
,
"*"
+
name
+
"*"
,
Case
.
INSENSITIVE
)
.
findAllSorted
(
RealmUser
.
USERNAME
,
direction
.
equals
(
SortDirection
.
ASC
)
?
Sort
.
ASCENDING
:
Sort
.
DESCENDING
)
.
asObservable
()),
pair
->
close
(
pair
.
first
,
pair
.
second
)
)
.
unsubscribeOn
(
AndroidSchedulers
.
from
(
Looper
.
myLooper
()))
.
filter
(
realmUsers
->
realmUsers
!=
null
&&
realmUsers
.
isLoaded
()
&&
realmUsers
.
isValid
())
.
map
(
realmUsers
->
toList
(
safeSubList
(
realmUsers
,
0
,
limit
))));
}
private
List
<
User
>
toList
(
RealmResults
<
RealmUser
>
realmUsers
)
{
int
total
=
realmUsers
.
size
();
final
List
<
User
>
userList
=
new
ArrayList
<>(
total
);
for
(
int
i
=
0
;
i
<
total
;
i
++)
{
userList
.
add
(
realmUsers
.
get
(
i
).
asUser
());
}
return
userList
;
}
private
List
<
User
>
toList
(
List
<
RealmUser
>
realmUsers
)
{
int
total
=
realmUsers
.
size
();
final
List
<
User
>
userList
=
new
ArrayList
<>(
total
);
for
(
int
i
=
0
;
i
<
total
;
i
++)
{
userList
.
add
(
realmUsers
.
get
(
i
).
asUser
());
}
return
userList
;
}
}
rocket-chat-android-widgets/build.gradle
View file @
349f73a3
...
...
@@ -32,6 +32,7 @@ android {
ext
{
supportVersion
=
'25.2.0'
frescoVersion
=
'1.1.0'
rxbindingVersion
=
'2.0.0'
}
dependencies
{
...
...
@@ -39,6 +40,8 @@ dependencies {
compile
"com.android.support:support-annotations:$supportVersion"
compile
"com.android.support:appcompat-v7:$supportVersion"
compile
"com.android.support:recyclerview-v7:$supportVersion"
compile
"com.android.support:cardview-v7:$supportVersion"
compile
"com.android.support:support-v13:$supportVersion"
compile
"com.android.support:design:$supportVersion"
...
...
@@ -58,5 +61,9 @@ dependencies {
compile
'com.caverock:androidsvg:1.2.1'
compile
"com.jakewharton.rxbinding2:rxbinding:$rxbindingVersion"
compile
"com.jakewharton.rxbinding2:rxbinding-support-v4:$rxbindingVersion"
testCompile
'junit:junit:4.12'
testCompile
"org.mockito:mockito-core:2.7.19"
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/helper/IconProvider.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
helper
;
import
android.support.annotation.StringRes
;
import
java.util.HashMap
;
import
chat.rocket.android.widget.R
;
public
class
IconProvider
{
private
static
HashMap
<
String
,
Integer
>
ICON_TABLE
=
new
HashMap
<
String
,
Integer
>()
{
{
put
(
"c"
,
R
.
string
.
fa_hashtag
);
put
(
"p"
,
R
.
string
.
fa_lock
);
put
(
"d"
,
R
.
string
.
fa_at
);
}
};
@StringRes
public
static
int
getIcon
(
String
type
)
{
if
(
ICON_TABLE
.
containsKey
(
type
))
{
return
ICON_TABLE
.
get
(
type
);
}
return
ICON_TABLE
.
get
(
"c"
);
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/helper/UserStatusProvider.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
helper
;
import
android.support.annotation.DrawableRes
;
public
interface
UserStatusProvider
{
@DrawableRes
int
getStatusResId
(
String
status
);
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/ImageKeyboardEditText.java
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
;
import
android.annotation.TargetApi
;
import
android.content.Context
;
import
android.os.Build
;
import
android.os.Bundle
;
import
android.support.v13.view.inputmethod.EditorInfoCompat
;
import
android.support.v13.view.inputmethod.InputConnectionCompat
;
import
android.support.v13.view.inputmethod.InputContentInfoCompat
;
import
android.support.v7.widget.AppCompatEditText
;
import
android.util.AttributeSet
;
import
android.view.inputmethod.EditorInfo
;
import
android.view.inputmethod.InputConnection
;
import
android.widget.EditText
;
public
class
ImageKeyboardEditText
extends
EditText
{
public
class
ImageKeyboardEditText
extends
AppCompat
EditText
{
private
final
String
[]
mimeTypes
=
{
"image/gif"
};
...
...
@@ -43,12 +41,6 @@ public class ImageKeyboardEditText extends EditText {
super
(
context
,
attrs
,
defStyleAttr
);
}
@TargetApi
(
Build
.
VERSION_CODES
.
LOLLIPOP
)
public
ImageKeyboardEditText
(
Context
context
,
AttributeSet
attrs
,
int
defStyleAttr
,
int
defStyleRes
)
{
super
(
context
,
attrs
,
defStyleAttr
,
defStyleRes
);
}
@Override
public
InputConnection
onCreateInputConnection
(
EditorInfo
editorInfo
)
{
final
InputConnection
inputConnection
=
super
.
onCreateInputConnection
(
editorInfo
);
...
...
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/MessageFormLayout.java
View file @
349f73a3
...
...
@@ -12,6 +12,7 @@ import android.util.AttributeSet;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.EditText
;
import
android.widget.LinearLayout
;
import
android.widget.TextView
;
...
...
@@ -115,6 +116,10 @@ public class MessageFormLayout extends LinearLayout {
addView
(
composer
);
}
public
EditText
getEditText
()
{
return
(
EditText
)
composer
.
findViewById
(
R
.
id
.
editor
);
}
public
void
setExtraActionSelectionClickListener
(
ExtraActionSelectionClickListener
extraActionSelectionClickListener
)
{
this
.
extraActionSelectionClickListener
=
extraActionSelectionClickListener
;
...
...
@@ -153,7 +158,8 @@ public class MessageFormLayout extends LinearLayout {
composer
.
findViewById
(
R
.
id
.
btn_submit
).
setEnabled
(
enabled
);
}
public
void
setEditTextContentListener
(
ImageKeyboardEditText
.
OnCommitContentListener
listener
)
{
public
void
setEditTextCommitContentListener
(
ImageKeyboardEditText
.
OnCommitContentListener
listener
)
{
this
.
listener
=
listener
;
}
...
...
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/AutocompleteAdapter.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
;
import
android.support.v7.widget.RecyclerView
;
import
android.view.ViewGroup
;
import
java.util.ArrayList
;
import
java.util.List
;
public
abstract
class
AutocompleteAdapter
<
I
extends
AutocompleteItem
,
H
extends
AutocompleteViewHolder
<
I
>>
extends
RecyclerView
.
Adapter
<
H
>
{
private
static
final
int
TYPE_EMPTY
=
0
;
private
static
final
int
TYPE_ITEM
=
1
;
private
List
<
I
>
autocompleteItems
=
new
ArrayList
<>();
protected
AutocompleteViewHolder
.
OnClickListener
<
I
>
onClickListener
;
public
void
setAutocompleteItems
(
List
<
I
>
autocompleteItems
)
{
this
.
autocompleteItems
.
clear
();
this
.
autocompleteItems
.
addAll
(
autocompleteItems
);
notifyDataSetChanged
();
}
public
H
onCreateViewHolder
(
ViewGroup
parent
,
int
viewType
)
{
H
holder
=
getViewHolder
(
parent
);
if
(
viewType
==
TYPE_EMPTY
)
{
holder
.
showAsEmpty
();
}
return
holder
;
}
@Override
public
void
onBindViewHolder
(
H
holder
,
int
position
)
{
if
(
getItemViewType
(
position
)
==
TYPE_EMPTY
)
{
return
;
}
holder
.
bind
(
autocompleteItems
.
get
(
position
));
}
@Override
public
int
getItemCount
()
{
int
count
=
autocompleteItems
.
size
();
if
(
count
==
0
)
{
return
1
;
}
return
count
;
}
@Override
public
int
getItemViewType
(
int
position
)
{
if
(
autocompleteItems
.
size
()
==
0
)
{
return
TYPE_EMPTY
;
}
return
TYPE_ITEM
;
}
public
abstract
H
getViewHolder
(
ViewGroup
parent
);
public
void
setOnClickListener
(
AutocompleteViewHolder
.
OnClickListener
<
I
>
onClickListener
)
{
this
.
onClickListener
=
onClickListener
;
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/AutocompleteItem.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
;
import
android.support.annotation.NonNull
;
public
interface
AutocompleteItem
{
@NonNull
String
getSuggestion
();
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/AutocompleteManager.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
;
import
android.support.v7.widget.LinearLayoutManager
;
import
android.support.v7.widget.RecyclerView
;
import
android.util.TypedValue
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.view.ViewTreeObserver
;
import
android.widget.EditText
;
import
android.widget.RelativeLayout
;
import
com.jakewharton.rxbinding2.widget.RxTextView
;
import
com.jakewharton.rxbinding2.widget.TextViewAfterTextChangeEvent
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.annotations.NonNull
;
import
io.reactivex.disposables.CompositeDisposable
;
import
io.reactivex.disposables.Disposable
;
import
io.reactivex.functions.Consumer
;
import
io.reactivex.functions.Function
;
import
io.reactivex.internal.util.AppendOnlyLinkedArrayList
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
chat.rocket.android.widget.R
;
public
class
AutocompleteManager
{
private
final
Map
<
String
,
AutocompleteSource
>
autocompleteSourceMap
=
new
HashMap
<>();
private
AutocompleteSource
currentSource
;
private
Disposable
afterTextChangeDisposable
;
private
CompositeDisposable
sourceDisposable
=
new
CompositeDisposable
();
private
EditText
editText
;
private
String
text
;
private
int
fromIndex
;
private
int
toIndex
;
private
final
View
contentHolder
;
private
final
RecyclerView
recyclerView
;
private
float
contentHolderInitialY
;
private
final
float
yOffset
;
private
final
AutocompleteSource
.
OnAutocompleteSelected
onAutocompleteSelected
=
new
AutocompleteSource
.
OnAutocompleteSelected
()
{
@Override
public
void
onSelected
(
String
autocompleteSuggestion
)
{
replaceSelected
(
autocompleteSuggestion
);
}
};
public
AutocompleteManager
(
ViewGroup
parent
)
{
contentHolder
=
LayoutInflater
.
from
(
parent
.
getContext
()).
inflate
(
R
.
layout
.
autocomplete_box
,
parent
,
false
);
contentHolder
.
setVisibility
(
View
.
GONE
);
recyclerView
=
(
RecyclerView
)
contentHolder
.
findViewById
(
R
.
id
.
autocomplete_list
);
recyclerView
.
setLayoutManager
(
new
LinearLayoutManager
(
parent
.
getContext
()));
parent
.
addView
(
contentHolder
);
yOffset
=
TypedValue
.
applyDimension
(
TypedValue
.
COMPLEX_UNIT_DIP
,
32
,
contentHolder
.
getContext
().
getResources
().
getDisplayMetrics
()
);
}
public
void
registerSource
(
AutocompleteSource
autocompleteSource
)
{
autocompleteSourceMap
.
put
(
autocompleteSource
.
getTrigger
(),
autocompleteSource
);
}
public
void
bindTo
(
EditText
editText
,
View
anchor
)
{
this
.
editText
=
editText
;
if
(
contentHolder
.
getLayoutParams
()
instanceof
RelativeLayout
.
LayoutParams
)
{
RelativeLayout
.
LayoutParams
layoutParams
=
(
RelativeLayout
.
LayoutParams
)
contentHolder
.
getLayoutParams
();
layoutParams
.
addRule
(
RelativeLayout
.
ABOVE
,
anchor
.
getId
());
contentHolder
.
getViewTreeObserver
().
addOnGlobalLayoutListener
(
new
ViewTreeObserver
.
OnGlobalLayoutListener
()
{
@Override
public
void
onGlobalLayout
()
{
contentHolderInitialY
=
contentHolder
.
getY
();
animateHide
();
contentHolder
.
getViewTreeObserver
().
removeOnGlobalLayoutListener
(
this
);
}
});
}
afterTextChangeDisposable
=
RxTextView
.
afterTextChangeEvents
(
editText
)
.
debounce
(
300
,
TimeUnit
.
MILLISECONDS
)
.
filter
(
new
AppendOnlyLinkedArrayList
.
NonThrowingPredicate
<
TextViewAfterTextChangeEvent
>()
{
@Override
public
boolean
test
(
TextViewAfterTextChangeEvent
textViewAfterTextChangeEvent
)
{
return
textViewAfterTextChangeEvent
.
editable
()
!=
null
;
}
})
.
map
(
new
Function
<
TextViewAfterTextChangeEvent
,
String
>()
{
@Override
public
String
apply
(
@NonNull
TextViewAfterTextChangeEvent
textViewAfterTextChangeEvent
)
throws
Exception
{
//noinspection ConstantConditions
return
textViewAfterTextChangeEvent
.
editable
().
toString
();
}
})
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
doOnNext
(
new
Consumer
<
String
>()
{
@Override
public
void
accept
(
@NonNull
String
s
)
throws
Exception
{
// let's do stateful things
tryToAutocomplete
(
s
);
}
})
.
subscribe
();
}
public
void
dispose
()
{
if
(
afterTextChangeDisposable
!=
null
)
{
afterTextChangeDisposable
.
dispose
();
afterTextChangeDisposable
=
null
;
}
editText
=
null
;
cleanState
();
}
private
void
tryToAutocomplete
(
String
text
)
{
if
(
editText
==
null
)
{
cleanState
();
return
;
}
final
int
selectionStart
=
editText
.
getSelectionStart
();
final
int
selectionEnd
=
editText
.
getSelectionEnd
();
if
(
selectionStart
!=
selectionEnd
)
{
// selecting text
cleanState
();
return
;
}
final
String
toCompleteText
=
getToCompleteText
(
text
,
selectionStart
);
final
AutocompleteSource
source
=
getSource
(
toCompleteText
);
if
(
source
==
null
)
{
cleanState
();
return
;
}
// render and stuff
if
(
source
!=
currentSource
)
{
cleanState
();
currentSource
=
source
;
// set adapter on something
recyclerView
.
setAdapter
(
currentSource
.
getAdapter
());
currentSource
.
setOnAutocompleteSelected
(
onAutocompleteSelected
);
}
this
.
text
=
text
;
animateShow
();
sourceDisposable
.
clear
();
sourceDisposable
.
add
(
currentSource
.
loadList
(
toCompleteText
));
}
private
void
cleanState
()
{
animateHide
();
sourceDisposable
.
clear
();
text
=
null
;
if
(
currentSource
!=
null
)
{
currentSource
.
dispose
();
currentSource
=
null
;
}
}
private
String
getToCompleteText
(
String
text
,
int
cursorPosition
)
{
if
(
text
==
null
||
text
.
length
()
==
0
||
cursorPosition
<
0
||
cursorPosition
>
text
.
length
())
{
return
""
;
}
final
String
[]
textParts
=
text
.
split
(
" "
);
int
currentPos
=
0
;
for
(
String
textPart
:
textParts
)
{
int
currentLength
=
currentPos
+
textPart
.
length
();
if
(
cursorPosition
>=
currentPos
&&
cursorPosition
<=
currentLength
)
{
fromIndex
=
currentPos
;
toIndex
=
cursorPosition
;
return
textPart
.
substring
(
0
,
cursorPosition
-
currentPos
);
}
currentPos
=
currentLength
+
1
;
}
return
""
;
}
private
AutocompleteSource
getSource
(
String
toCompleteText
)
{
if
(
toCompleteText
==
null
||
toCompleteText
.
length
()
==
0
)
{
return
null
;
}
final
String
trigger
=
toCompleteText
.
substring
(
0
,
1
);
return
autocompleteSourceMap
.
get
(
trigger
);
}
private
void
replaceSelected
(
String
autocompleteSuggestion
)
{
final
String
preText
=
text
.
substring
(
0
,
fromIndex
);
final
String
postText
=
text
.
substring
(
toIndex
);
StringBuilder
stringBuilder
=
new
StringBuilder
(
text
.
length
()
+
autocompleteSuggestion
.
length
());
stringBuilder
.
append
(
preText
)
.
append
(
autocompleteSuggestion
)
.
append
(
' '
);
final
int
selectionPos
=
stringBuilder
.
length
();
stringBuilder
.
append
(
postText
);
editText
.
setText
(
stringBuilder
.
toString
());
editText
.
setSelection
(
selectionPos
);
}
private
void
animateHide
()
{
contentHolder
.
animate
().
cancel
();
contentHolder
.
animate
()
.
alpha
(
0
)
.
translationY
(
contentHolderInitialY
+
yOffset
)
.
setDuration
(
150
)
.
withEndAction
(
new
Runnable
()
{
@Override
public
void
run
()
{
contentHolder
.
setVisibility
(
View
.
GONE
);
}
});
}
private
void
animateShow
()
{
contentHolder
.
animate
().
cancel
();
contentHolder
.
animate
()
.
alpha
(
1
)
.
translationY
(
contentHolderInitialY
)
.
setDuration
(
150
)
.
withStartAction
(
new
Runnable
()
{
@Override
public
void
run
()
{
contentHolder
.
setVisibility
(
View
.
VISIBLE
);
}
});
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/AutocompleteSource.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
;
import
android.support.annotation.NonNull
;
import
io.reactivex.disposables.Disposable
;
public
abstract
class
AutocompleteSource
<
A
extends
AutocompleteAdapter
,
I
extends
AutocompleteItem
>
{
protected
A
adapter
;
private
AutocompleteSource
.
OnAutocompleteSelected
autocompleteSelected
;
private
AutocompleteViewHolder
.
OnClickListener
autocompleteListener
=
new
AutocompleteViewHolder
.
OnClickListener
<
I
>()
{
@Override
public
void
onClick
(
I
autocompleteItem
)
{
if
(
autocompleteSelected
!=
null
)
{
autocompleteSelected
.
onSelected
(
getAutocompleteSuggestion
(
autocompleteItem
));
}
}
};
@NonNull
public
abstract
String
getTrigger
();
@NonNull
public
A
getAdapter
()
{
if
(
adapter
==
null
)
{
adapter
=
createAdapter
();
adapter
.
setOnClickListener
(
autocompleteListener
);
}
return
adapter
;
}
@NonNull
public
abstract
Disposable
loadList
(
String
text
);
public
abstract
void
dispose
();
public
void
setOnAutocompleteSelected
(
AutocompleteSource
.
OnAutocompleteSelected
autocompleteSelected
)
{
this
.
autocompleteSelected
=
autocompleteSelected
;
}
protected
abstract
A
createAdapter
();
protected
abstract
String
getAutocompleteSuggestion
(
I
autocompleteItem
);
public
interface
OnAutocompleteSelected
{
void
onSelected
(
String
autocompleteSuggestion
);
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/AutocompleteViewHolder.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
;
import
android.support.v7.widget.RecyclerView
;
import
android.view.View
;
public
abstract
class
AutocompleteViewHolder
<
I
extends
AutocompleteItem
>
extends
RecyclerView
.
ViewHolder
{
public
AutocompleteViewHolder
(
View
itemView
)
{
super
(
itemView
);
}
public
abstract
void
bind
(
I
autocompleteItem
);
public
abstract
void
showAsEmpty
();
public
interface
OnClickListener
<
I
extends
AutocompleteItem
>
{
void
onClick
(
I
autocompleteItem
);
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/channel/ChannelAdapter.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
.
channel
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
chat.rocket.android.widget.R
;
import
chat.rocket.android.widget.message.autocomplete.AutocompleteAdapter
;
public
class
ChannelAdapter
extends
AutocompleteAdapter
<
ChannelItem
,
ChannelViewHolder
>
{
@Override
public
ChannelViewHolder
getViewHolder
(
ViewGroup
parent
)
{
View
view
=
LayoutInflater
.
from
(
parent
.
getContext
())
.
inflate
(
R
.
layout
.
autocomplete_channel_view
,
parent
,
false
);
return
new
ChannelViewHolder
(
view
,
onClickListener
);
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/channel/ChannelItem.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
.
channel
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.StringRes
;
import
chat.rocket.android.widget.helper.IconProvider
;
import
chat.rocket.android.widget.message.autocomplete.AutocompleteItem
;
import
chat.rocket.core.models.SpotlightRoom
;
public
class
ChannelItem
implements
AutocompleteItem
{
private
final
SpotlightRoom
spotlightRoom
;
public
ChannelItem
(
@NonNull
SpotlightRoom
spotlightRoom
)
{
this
.
spotlightRoom
=
spotlightRoom
;
}
@NonNull
@Override
public
String
getSuggestion
()
{
return
spotlightRoom
.
getName
();
}
@StringRes
public
int
getIcon
()
{
return
IconProvider
.
getIcon
(
spotlightRoom
.
getType
());
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/channel/ChannelSource.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
.
channel
;
import
android.support.annotation.NonNull
;
import
io.reactivex.Flowable
;
import
io.reactivex.Scheduler
;
import
io.reactivex.disposables.Disposable
;
import
io.reactivex.functions.Consumer
;
import
io.reactivex.functions.Function
;
import
org.reactivestreams.Publisher
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.android.widget.message.autocomplete.AutocompleteSource
;
import
chat.rocket.core.interactors.AutocompleteChannelInteractor
;
import
chat.rocket.core.models.SpotlightRoom
;
public
class
ChannelSource
extends
AutocompleteSource
<
ChannelAdapter
,
ChannelItem
>
{
private
final
AutocompleteChannelInteractor
autocompleteChannelInteractor
;
private
final
Scheduler
bgScheduler
;
private
final
Scheduler
fgScheduler
;
public
ChannelSource
(
AutocompleteChannelInteractor
autocompleteChannelInteractor
,
Scheduler
bgScheduler
,
Scheduler
fgScheduler
)
{
this
.
autocompleteChannelInteractor
=
autocompleteChannelInteractor
;
this
.
bgScheduler
=
bgScheduler
;
this
.
fgScheduler
=
fgScheduler
;
}
@NonNull
@Override
public
String
getTrigger
()
{
return
"#"
;
}
@NonNull
@Override
public
Disposable
loadList
(
String
text
)
{
return
Flowable
.
just
(
text
)
.
map
(
new
Function
<
String
,
String
>()
{
@Override
public
String
apply
(
@io
.
reactivex
.
annotations
.
NonNull
String
s
)
throws
Exception
{
return
s
.
substring
(
1
);
}
})
.
flatMap
(
new
Function
<
String
,
Publisher
<
List
<
SpotlightRoom
>>>()
{
@Override
public
Publisher
<
List
<
SpotlightRoom
>>
apply
(
@io
.
reactivex
.
annotations
.
NonNull
String
s
)
throws
Exception
{
return
autocompleteChannelInteractor
.
getSuggestionsFor
(
s
);
}
})
.
distinctUntilChanged
()
.
map
(
new
Function
<
List
<
SpotlightRoom
>,
List
<
ChannelItem
>>()
{
@Override
public
List
<
ChannelItem
>
apply
(
@io
.
reactivex
.
annotations
.
NonNull
List
<
SpotlightRoom
>
spotlightRooms
)
throws
Exception
{
return
toChannelItemList
(
spotlightRooms
);
}
})
.
subscribeOn
(
bgScheduler
)
.
observeOn
(
fgScheduler
)
.
subscribe
(
new
Consumer
<
List
<
ChannelItem
>>()
{
@Override
public
void
accept
(
@io
.
reactivex
.
annotations
.
NonNull
List
<
ChannelItem
>
channelItems
)
throws
Exception
{
if
(
adapter
!=
null
)
{
adapter
.
setAutocompleteItems
(
channelItems
);
}
}
},
new
Consumer
<
Throwable
>()
{
@Override
public
void
accept
(
@io
.
reactivex
.
annotations
.
NonNull
Throwable
throwable
)
throws
Exception
{
}
}
);
}
@Override
public
void
dispose
()
{
adapter
=
null
;
}
@Override
protected
ChannelAdapter
createAdapter
()
{
return
new
ChannelAdapter
();
}
@Override
protected
String
getAutocompleteSuggestion
(
ChannelItem
autocompleteItem
)
{
return
getTrigger
()
+
autocompleteItem
.
getSuggestion
();
}
private
List
<
ChannelItem
>
toChannelItemList
(
List
<
SpotlightRoom
>
spotlightRooms
)
{
int
size
=
spotlightRooms
.
size
();
List
<
ChannelItem
>
channelItems
=
new
ArrayList
<>(
size
);
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
channelItems
.
add
(
new
ChannelItem
(
spotlightRooms
.
get
(
i
)));
}
return
channelItems
;
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/channel/ChannelViewHolder.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
.
channel
;
import
android.view.View
;
import
android.widget.TextView
;
import
chat.rocket.android.widget.R
;
import
chat.rocket.android.widget.message.autocomplete.AutocompleteViewHolder
;
public
class
ChannelViewHolder
extends
AutocompleteViewHolder
<
ChannelItem
>
{
private
final
TextView
titleTextView
;
private
final
TextView
iconTextView
;
public
ChannelViewHolder
(
View
itemView
,
final
AutocompleteViewHolder
.
OnClickListener
<
ChannelItem
>
onClickListener
)
{
super
(
itemView
);
titleTextView
=
(
TextView
)
itemView
.
findViewById
(
R
.
id
.
title
);
iconTextView
=
(
TextView
)
itemView
.
findViewById
(
R
.
id
.
icon
);
itemView
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
if
(
onClickListener
!=
null
)
{
onClickListener
.
onClick
((
ChannelItem
)
v
.
getTag
());
}
}
});
}
@Override
public
void
bind
(
ChannelItem
channelItem
)
{
itemView
.
setTag
(
channelItem
);
if
(
titleTextView
!=
null
)
{
titleTextView
.
setText
(
channelItem
.
getSuggestion
());
}
if
(
iconTextView
!=
null
)
{
iconTextView
.
setText
(
channelItem
.
getIcon
());
}
}
@Override
public
void
showAsEmpty
()
{
iconTextView
.
setVisibility
(
View
.
GONE
);
titleTextView
.
setText
(
R
.
string
.
no_channel_found
);
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/user/UserAdapter.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
.
user
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
chat.rocket.android.widget.R
;
import
chat.rocket.android.widget.message.autocomplete.AutocompleteAdapter
;
public
class
UserAdapter
extends
AutocompleteAdapter
<
UserItem
,
UserViewHolder
>
{
@Override
public
UserViewHolder
getViewHolder
(
ViewGroup
parent
)
{
View
view
=
LayoutInflater
.
from
(
parent
.
getContext
())
.
inflate
(
R
.
layout
.
autocomplete_user_view
,
parent
,
false
);
return
new
UserViewHolder
(
view
,
onClickListener
);
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/user/UserItem.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
.
user
;
import
android.support.annotation.DrawableRes
;
import
android.support.annotation.NonNull
;
import
chat.rocket.android.widget.AbsoluteUrl
;
import
chat.rocket.android.widget.helper.UserStatusProvider
;
import
chat.rocket.android.widget.message.autocomplete.AutocompleteItem
;
import
chat.rocket.core.models.SpotlightUser
;
public
class
UserItem
implements
AutocompleteItem
{
private
final
SpotlightUser
user
;
private
final
AbsoluteUrl
absoluteUrl
;
private
final
UserStatusProvider
userStatusProvider
;
public
UserItem
(
@NonNull
SpotlightUser
user
,
AbsoluteUrl
absoluteUrl
,
UserStatusProvider
userStatusProvider
)
{
this
.
user
=
user
;
this
.
absoluteUrl
=
absoluteUrl
;
this
.
userStatusProvider
=
userStatusProvider
;
}
@NonNull
@Override
public
String
getSuggestion
()
{
//noinspection ConstantConditions
return
user
.
getUsername
();
}
public
AbsoluteUrl
getAbsoluteUrl
()
{
return
absoluteUrl
;
}
@DrawableRes
public
int
getStatusResId
()
{
return
userStatusProvider
.
getStatusResId
(
user
.
getStatus
());
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/user/UserSource.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
.
user
;
import
android.support.annotation.NonNull
;
import
io.reactivex.Flowable
;
import
io.reactivex.Scheduler
;
import
io.reactivex.disposables.Disposable
;
import
io.reactivex.functions.Consumer
;
import
io.reactivex.functions.Function
;
import
org.reactivestreams.Publisher
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.android.widget.AbsoluteUrl
;
import
chat.rocket.android.widget.helper.UserStatusProvider
;
import
chat.rocket.android.widget.message.autocomplete.AutocompleteSource
;
import
chat.rocket.core.interactors.AutocompleteUserInteractor
;
import
chat.rocket.core.models.SpotlightUser
;
public
class
UserSource
extends
AutocompleteSource
<
UserAdapter
,
UserItem
>
{
private
final
AutocompleteUserInteractor
autocompleteUserInteractor
;
private
final
AbsoluteUrl
absoluteUrl
;
private
final
UserStatusProvider
userStatusProvider
;
private
final
Scheduler
bgScheduler
;
private
final
Scheduler
fgScheduler
;
public
UserSource
(
AutocompleteUserInteractor
autocompleteUserInteractor
,
AbsoluteUrl
absoluteUrl
,
UserStatusProvider
userStatusProvider
,
Scheduler
bgScheduler
,
Scheduler
fgScheduler
)
{
this
.
autocompleteUserInteractor
=
autocompleteUserInteractor
;
this
.
absoluteUrl
=
absoluteUrl
;
this
.
userStatusProvider
=
userStatusProvider
;
this
.
bgScheduler
=
bgScheduler
;
this
.
fgScheduler
=
fgScheduler
;
}
@NonNull
@Override
public
String
getTrigger
()
{
return
"@"
;
}
@NonNull
@Override
public
Disposable
loadList
(
String
text
)
{
return
Flowable
.
just
(
text
)
.
map
(
new
Function
<
String
,
String
>()
{
@Override
public
String
apply
(
@io
.
reactivex
.
annotations
.
NonNull
String
s
)
throws
Exception
{
return
s
.
substring
(
1
);
}
})
.
flatMap
(
new
Function
<
String
,
Publisher
<
List
<
SpotlightUser
>>>()
{
@Override
public
Publisher
<
List
<
SpotlightUser
>>
apply
(
@io
.
reactivex
.
annotations
.
NonNull
String
s
)
throws
Exception
{
return
autocompleteUserInteractor
.
getSuggestionsFor
(
s
);
}
})
.
distinctUntilChanged
()
.
map
(
new
Function
<
List
<
SpotlightUser
>,
List
<
UserItem
>>()
{
@Override
public
List
<
UserItem
>
apply
(
@io
.
reactivex
.
annotations
.
NonNull
List
<
SpotlightUser
>
users
)
throws
Exception
{
return
toUserItemList
(
users
);
}
})
.
subscribeOn
(
bgScheduler
)
.
observeOn
(
fgScheduler
)
.
subscribe
(
new
Consumer
<
List
<
UserItem
>>()
{
@Override
public
void
accept
(
@io
.
reactivex
.
annotations
.
NonNull
List
<
UserItem
>
userItems
)
throws
Exception
{
if
(
adapter
!=
null
)
{
adapter
.
setAutocompleteItems
(
userItems
);
}
}
},
new
Consumer
<
Throwable
>()
{
@Override
public
void
accept
(
@io
.
reactivex
.
annotations
.
NonNull
Throwable
throwable
)
throws
Exception
{
}
}
);
}
@Override
public
void
dispose
()
{
adapter
=
null
;
}
@Override
protected
UserAdapter
createAdapter
()
{
return
new
UserAdapter
();
}
@Override
protected
String
getAutocompleteSuggestion
(
UserItem
autocompleteItem
)
{
return
getTrigger
()
+
autocompleteItem
.
getSuggestion
();
}
private
List
<
UserItem
>
toUserItemList
(
List
<
SpotlightUser
>
users
)
{
int
size
=
users
.
size
();
List
<
UserItem
>
userItems
=
new
ArrayList
<>(
size
);
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
userItems
.
add
(
new
UserItem
(
users
.
get
(
i
),
absoluteUrl
,
userStatusProvider
));
}
return
userItems
;
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/user/UserViewHolder.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
.
user
;
import
android.content.Context
;
import
android.graphics.Typeface
;
import
android.graphics.drawable.Drawable
;
import
android.text.TextUtils
;
import
android.view.View
;
import
android.widget.ImageView
;
import
android.widget.TextView
;
import
com.amulyakhare.textdrawable.TextDrawable
;
import
java.io.UnsupportedEncodingException
;
import
java.net.URLEncoder
;
import
chat.rocket.android.widget.AbsoluteUrl
;
import
chat.rocket.android.widget.R
;
import
chat.rocket.android.widget.RocketChatAvatar
;
import
chat.rocket.android.widget.message.autocomplete.AutocompleteViewHolder
;
public
class
UserViewHolder
extends
AutocompleteViewHolder
<
UserItem
>
{
private
static
final
int
[]
COLORS
=
new
int
[]{
0xFFF44336
,
0xFFE91E63
,
0xFF9C27B0
,
0xFF673AB7
,
0xFF3F51B5
,
0xFF2196F3
,
0xFF03A9F4
,
0xFF00BCD4
,
0xFF009688
,
0xFF4CAF50
,
0xFF8BC34A
,
0xFFCDDC39
,
0xFFFFC107
,
0xFFFF9800
,
0xFFFF5722
,
0xFF795548
,
0xFF9E9E9E
,
0xFF607D8B
};
private
final
TextView
titleTextView
;
private
final
RocketChatAvatar
avatar
;
private
final
ImageView
status
;
public
UserViewHolder
(
View
itemView
,
final
AutocompleteViewHolder
.
OnClickListener
<
UserItem
>
onClickListener
)
{
super
(
itemView
);
titleTextView
=
(
TextView
)
itemView
.
findViewById
(
R
.
id
.
title
);
avatar
=
(
RocketChatAvatar
)
itemView
.
findViewById
(
R
.
id
.
avatar
);
status
=
(
ImageView
)
itemView
.
findViewById
(
R
.
id
.
status
);
itemView
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
public
void
onClick
(
View
v
)
{
if
(
onClickListener
!=
null
)
{
onClickListener
.
onClick
((
UserItem
)
v
.
getTag
());
}
}
});
}
@Override
public
void
bind
(
UserItem
userItem
)
{
itemView
.
setTag
(
userItem
);
final
String
suggestion
=
userItem
.
getSuggestion
();
if
(
titleTextView
!=
null
)
{
titleTextView
.
setText
(
suggestion
);
}
if
(
avatar
!=
null
)
{
avatar
.
loadImage
(
getImageUrl
(
suggestion
,
userItem
.
getAbsoluteUrl
()),
getTextDrawable
(
itemView
.
getContext
(),
suggestion
)
);
}
if
(
status
!=
null
)
{
status
.
setImageResource
(
userItem
.
getStatusResId
());
}
}
@Override
public
void
showAsEmpty
()
{
status
.
setVisibility
(
View
.
GONE
);
avatar
.
setVisibility
(
View
.
GONE
);
titleTextView
.
setText
(
R
.
string
.
no_user_found
);
}
private
String
getImageUrl
(
String
username
,
AbsoluteUrl
absoluteUrl
)
{
//from Rocket.Chat:packages/rocketchat-ui/lib/avatar.coffee
//REMARK! this is often SVG image! (see: Rocket.Chat:server/startup/avatar.coffee)
try
{
final
String
avatarUrl
=
"/avatar/"
+
URLEncoder
.
encode
(
username
,
"UTF-8"
)
+
".jpg"
;
if
(
absoluteUrl
==
null
)
{
return
avatarUrl
;
}
return
absoluteUrl
.
from
(
avatarUrl
);
}
catch
(
UnsupportedEncodingException
exception
)
{
return
null
;
}
}
private
Drawable
getTextDrawable
(
Context
context
,
String
username
)
{
if
(
username
==
null
)
{
return
null
;
}
int
round
=
(
int
)
(
4
*
context
.
getResources
().
getDisplayMetrics
().
density
);
return
TextDrawable
.
builder
()
.
beginConfig
()
.
useFont
(
Typeface
.
SANS_SERIF
)
.
endConfig
()
.
buildRoundRect
(
getInitialsForUser
(
username
),
getColorForUser
(
username
),
round
);
}
private
int
getColorForUser
(
String
username
)
{
return
COLORS
[
username
.
length
()
%
COLORS
.
length
];
}
private
String
getInitialsForUser
(
String
username
)
{
String
name
=
username
.
replaceAll
(
"[^A-Za-z0-9]"
,
"."
)
.
replaceAll
(
"\\.+"
,
"."
)
.
replaceAll
(
"(^\\.)|(\\.$)"
,
""
);
String
[]
initials
=
name
.
split
(
"\\."
);
if
(
initials
.
length
>=
2
)
{
return
(
firstChar
(
initials
[
0
])
+
firstChar
(
initials
[
initials
.
length
-
1
])).
toUpperCase
();
}
else
{
String
name2
=
name
.
replaceAll
(
"[^A-Za-z0-9]"
,
""
);
return
(
name2
.
length
()
<
2
)
?
name2
:
name2
.
substring
(
0
,
2
).
toUpperCase
();
}
}
private
static
String
firstChar
(
String
str
)
{
return
TextUtils
.
isEmpty
(
str
)
?
""
:
str
.
substring
(
0
,
1
);
}
}
rocket-chat-android-widgets/src/main/res/drawable/autocomplete_background.xml
0 → 100644
View file @
349f73a3
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<item>
<shape
android:shape=
"rectangle"
>
<solid
android:color=
"@android:color/darker_gray"
/>
</shape>
</item>
<item
android:bottom=
"1dp"
>
<shape
android:shape=
"rectangle"
>
<solid
android:color=
"@android:color/white"
/>
</shape>
</item>
</layer-list>
\ No newline at end of file
rocket-chat-android-widgets/src/main/res/layout/autocomplete_box.xml
0 → 100644
View file @
349f73a3
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:orientation=
"vertical"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginRight=
"8dp"
android:layout_marginLeft=
"8dp"
android:layout_marginBottom=
"-8dp"
app:cardCornerRadius=
"4dp"
app:contentPadding=
"4dp"
>
<android.support.v7.widget.RecyclerView
android:id=
"@+id/autocomplete_list"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
/>
</android.support.v7.widget.CardView>
\ No newline at end of file
rocket-chat-android-widgets/src/main/res/layout/autocomplete_channel_view.xml
0 → 100644
View file @
349f73a3
<?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:orientation=
"horizontal"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"@android:color/white"
android:gravity=
"center_vertical"
android:paddingLeft=
"16dp"
android:paddingRight=
"16dp"
android:paddingTop=
"8dp"
android:paddingBottom=
"8dp"
>
<io.github.yusukeiwaki.android.widget.FontAwesomeTextView
android:id=
"@+id/icon"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_marginEnd=
"8dp"
android:layout_marginRight=
"8dp"
tools:text=
"#"
/>
<TextView
android:id=
"@+id/title"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
tools:text=
"YOLO"
/>
</LinearLayout>
\ No newline at end of file
rocket-chat-android-widgets/src/main/res/layout/autocomplete_user_view.xml
0 → 100644
View file @
349f73a3
<?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:orientation=
"horizontal"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"@android:color/white"
android:gravity=
"center_vertical"
android:paddingLeft=
"16dp"
android:paddingRight=
"16dp"
android:paddingTop=
"8dp"
android:paddingBottom=
"8dp"
>
<ImageView
android:id=
"@+id/status"
android:layout_width=
"8dp"
android:layout_height=
"8dp"
android:layout_marginEnd=
"8dp"
android:layout_marginRight=
"8dp"
/>
<chat.rocket.android.widget.RocketChatAvatar
android:id=
"@+id/avatar"
android:layout_width=
"16dp"
android:layout_height=
"16dp"
android:layout_marginEnd=
"8dp"
android:layout_marginRight=
"8dp"
/>
<TextView
android:id=
"@+id/title"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
tools:text=
"YOLO"
/>
</LinearLayout>
\ No newline at end of file
rocket-chat-android-widgets/src/main/res/values/strings.xml
View file @
349f73a3
...
...
@@ -2,4 +2,6 @@
<resources>
<string
name=
"message_composer_message_hint"
>
Message
</string>
<string
name=
"click_to_load"
>
Click to load
</string>
<string
name=
"no_channel_found"
>
No channel found
</string>
<string
name=
"no_user_found"
>
No user found
</string>
</resources>
\ No newline at end of file
rocket-chat-core/build.gradle
View file @
349f73a3
plugins
{
id
"net.ltgt.apt"
version
"0.9"
id
"me.tatarka.retrolambda"
version
"3.5.0"
id
"org.jetbrains.kotlin.jvm"
version
"1.1.1"
}
apply
plugin:
'idea'
...
...
@@ -9,6 +8,8 @@ apply plugin: 'java'
dependencies
{
compile
fileTree
(
dir:
'libs'
,
include:
[
'*.jar'
])
compile
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.1.1'
compile
'com.google.code.findbugs:jsr305:3.0.1'
compile
'io.reactivex.rxjava2:rxjava:2.0.6'
...
...
@@ -16,9 +17,12 @@ dependencies {
compile
'com.fernandocejas:arrow:1.0.0'
compile
'com.google.auto.value:auto-value:1.3'
apt
'com.google.auto.value:auto-value:1.3'
apt
'com.gabrielittner.auto.value:auto-value-with:1.0.0'
kapt
'com.google.auto.value:auto-value:1.3'
kapt
'com.gabrielittner.auto.value:auto-value-with:1.0.0'
testCompile
'junit:junit:4.12'
testCompile
"org.mockito:mockito-core:2.7.19"
}
sourceCompatibility
=
"1.
8
"
targetCompatibility
=
"1.
8
"
sourceCompatibility
=
"1.
7
"
targetCompatibility
=
"1.
7
"
rocket-chat-core/src/main/java/chat/rocket/core/SortDirection.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
core
;
public
enum
SortDirection
{
ASC
,
DESC
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/AutocompleteChannelInteractor.kt
0 → 100644
View file @
349f73a3
package
chat.rocket.core.interactors
import
io.reactivex.Flowable
import
java.util.ArrayList
import
chat.rocket.core.SortDirection
import
chat.rocket.core.models.Room
import
chat.rocket.core.models.SpotlightRoom
import
chat.rocket.core.repositories.RoomRepository
import
chat.rocket.core.repositories.SpotlightRoomRepository
import
chat.rocket.core.temp.TempSpotlightRoomCaller
import
chat.rocket.core.utils.Pair
import
chat.rocket.core.utils.Triple
import
io.reactivex.functions.BiFunction
import
io.reactivex.functions.Function3
class
AutocompleteChannelInteractor
(
private
val
roomRepository
:
RoomRepository
,
private
val
spotlightRoomRepository
:
SpotlightRoomRepository
,
private
val
tempSpotlightRoomCaller
:
TempSpotlightRoomCaller
)
{
fun
getSuggestionsFor
(
name
:
String
):
Flowable
<
List
<
SpotlightRoom
>>
{
return
Flowable
.
zip
<
String
,
List
<
SpotlightRoom
>,
List
<
SpotlightRoom
>,
Triple
<
String
,
List
<
SpotlightRoom
>,
List
<
SpotlightRoom
>>>(
Flowable
.
just
(
name
),
roomRepository
.
getLatestSeen
(
5
).
map
{
toSpotlightRooms
(
it
)
},
roomRepository
.
getSortedLikeName
(
name
,
SortDirection
.
DESC
,
5
).
map
{
toSpotlightRooms
(
it
)
},
Function3
{
a
,
b
,
c
->
Triple
.
create
(
a
,
b
,
c
)
}
)
.
flatMap
{
triple
->
if
(
triple
.
first
.
isEmpty
())
{
return
@flatMap
Flowable
.
just
(
triple
.
second
)
}
val
spotlightRooms
=
ArrayList
<
SpotlightRoom
>()
spotlightRooms
.
addAll
(
triple
.
second
.
filter
{
it
.
name
.
contains
(
triple
.
first
,
true
)
})
spotlightRooms
.
addAll
(
triple
.
third
)
val
workedList
=
spotlightRooms
.
distinct
().
take
(
5
)
if
(
workedList
.
size
==
5
)
{
return
@flatMap
Flowable
.
just
<
List
<
SpotlightRoom
>>(
workedList
)
}
tempSpotlightRoomCaller
.
search
(
triple
.
first
)
spotlightRoomRepository
.
getSuggestionsFor
(
triple
.
first
,
SortDirection
.
DESC
,
5
)
.
withLatestFrom
<
List
<
SpotlightRoom
>,
Pair
<
List
<
SpotlightRoom
>,
List
<
SpotlightRoom
>>>(
Flowable
.
just
(
workedList
),
BiFunction
{
a
,
b
->
Pair
.
create
(
a
,
b
)
}
)
.
map
{
pair
->
val
spotlightRooms1
=
ArrayList
<
SpotlightRoom
>()
spotlightRooms1
.
addAll
(
pair
.
second
)
spotlightRooms1
.
addAll
(
pair
.
first
)
return
@map
spotlightRooms1
.
distinct
().
take
(
5
)
}
}
}
private
fun
toSpotlightRooms
(
rooms
:
List
<
Room
>):
List
<
SpotlightRoom
>
{
val
size
=
rooms
.
size
val
spotlightRooms
=
ArrayList
<
SpotlightRoom
>(
size
)
for
(
i
in
0
..
size
-
1
)
{
val
room
=
rooms
[
i
]
spotlightRooms
.
add
(
SpotlightRoom
.
builder
()
.
setId
(
room
.
id
)
.
setName
(
room
.
name
)
.
setType
(
room
.
type
)
.
build
())
}
return
spotlightRooms
}
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/AutocompleteUserInteractor.kt
0 → 100644
View file @
349f73a3
package
chat.rocket.core.interactors
import
chat.rocket.core.SortDirection
import
chat.rocket.core.models.Message
import
chat.rocket.core.models.Room
import
chat.rocket.core.models.SpotlightUser
import
chat.rocket.core.models.User
import
chat.rocket.core.repositories.MessageRepository
import
chat.rocket.core.repositories.SpotlightUserRepository
import
chat.rocket.core.repositories.UserRepository
import
chat.rocket.core.temp.TempSpotlightUserCaller
import
chat.rocket.core.utils.Triple
import
io.reactivex.Flowable
import
io.reactivex.functions.Function3
import
java.util.ArrayList
class
AutocompleteUserInteractor
(
private
val
room
:
Room
,
private
val
userRepository
:
UserRepository
,
private
val
messageRepository
:
MessageRepository
,
private
val
spotlightUserRepository
:
SpotlightUserRepository
,
private
val
tempSpotlightUserCaller
:
TempSpotlightUserCaller
)
{
private
val
groupMentions
=
listOf
(
SpotlightUser
.
builder
().
setId
(
"all"
).
setUsername
(
"all"
).
setStatus
(
"online"
).
build
(),
SpotlightUser
.
builder
().
setId
(
"here"
).
setUsername
(
"here"
).
setStatus
(
"online"
).
build
()
)
fun
getSuggestionsFor
(
name
:
String
):
Flowable
<
List
<
SpotlightUser
>>
{
return
Flowable
.
zip
<
String
,
List
<
Message
>,
List
<
SpotlightUser
>,
Triple
<
String
,
List
<
Message
>,
List
<
SpotlightUser
>>>(
Flowable
.
just
(
name
),
messageRepository
.
getAllFrom
(
room
),
userRepository
.
getSortedLikeName
(
name
,
SortDirection
.
DESC
,
5
).
map
{
it
.
toSpotlightUsers
()
},
Function3
{
a
,
b
,
c
->
Triple
.
create
(
a
,
b
,
c
)
}
)
.
flatMap
{
triple
->
val
recentUsers
=
triple
.
second
.
takeUsers
(
5
).
toSpotlightUsers
()
if
(
triple
.
first
.
isEmpty
())
{
return
@flatMap
Flowable
.
just
(
recentUsers
+
groupMentions
)
}
val
workedUsers
=
(
recentUsers
.
filter
{
it
.
username
.
contains
(
triple
.
first
,
true
)
}
+
triple
.
third
).
distinct
().
take
(
5
)
if
(
workedUsers
.
size
==
5
)
{
return
@flatMap
Flowable
.
just
(
workedUsers
+
groupMentions
.
filter
{
it
.
username
.
contains
(
triple
.
first
,
true
)
})
}
tempSpotlightUserCaller
.
search
(
triple
.
first
)
spotlightUserRepository
.
getSuggestionsFor
(
triple
.
first
,
SortDirection
.
DESC
,
5
)
.
withLatestFrom
<
List
<
SpotlightUser
>,
List
<
SpotlightUser
>,
Triple
<
List
<
SpotlightUser
>,
List
<
SpotlightUser
>,
List
<
SpotlightUser
>>>(
Flowable
.
just
(
workedUsers
),
Flowable
.
just
(
groupMentions
.
filter
{
it
.
username
.
contains
(
triple
.
first
,
true
)
}),
Function3
{
a
,
b
,
c
->
Triple
.
create
(
a
,
b
,
c
)
}
)
.
map
{
triple
->
val
spotlightUsers
=
triple
.
first
+
triple
.
second
return
@map
spotlightUsers
.
distinct
().
take
(
5
)
+
triple
.
third
}
}
}
}
fun
List
<
User
>.
toSpotlightUsers
():
List
<
SpotlightUser
>
{
val
size
=
this
.
size
val
spotlightUsers
=
ArrayList
<
SpotlightUser
>(
size
)
for
(
i
in
0
..
size
-
1
)
{
val
user
=
this
[
i
]
spotlightUsers
.
add
(
SpotlightUser
.
builder
()
.
setId
(
user
.
id
)
.
setUsername
(
user
.
username
)
.
setStatus
(
user
.
status
)
.
build
())
}
return
spotlightUsers
}
fun
List
<
Message
>.
takeUsers
(
n
:
Int
):
List
<
User
>
{
val
users
=
ArrayList
<
User
>()
this
.
forEach
{
if
(
it
.
user
!=
null
&&
!
users
.
contains
(
it
.
user
!!
))
{
users
.
add
(
it
.
user
!!
)
if
(
users
.
size
==
n
)
{
return
@forEach
}
}
}
return
users
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/CanCreateRoomInteractor.java
deleted
100644 → 0
View file @
1a41bf56
package
chat
.
rocket
.
core
.
interactors
;
import
io.reactivex.Flowable
;
import
io.reactivex.Single
;
import
chat.rocket.core.repositories.UserRepository
;
public
class
CanCreateRoomInteractor
{
private
final
UserRepository
userRepository
;
private
final
SessionInteractor
sessionInteractor
;
public
CanCreateRoomInteractor
(
UserRepository
userRepository
,
SessionInteractor
sessionInteractor
)
{
this
.
userRepository
=
userRepository
;
this
.
sessionInteractor
=
sessionInteractor
;
}
public
Single
<
Boolean
>
canCreate
(
String
roomId
)
{
return
Flowable
.
zip
(
userRepository
.
getCurrent
(),
sessionInteractor
.
getDefault
(),
Flowable
.
just
(
roomId
),
(
user
,
session
,
room
)
->
user
!=
null
&&
session
!=
null
&&
room
!=
null
)
.
first
(
false
);
}
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/CanCreateRoomInteractor.kt
0 → 100644
View file @
349f73a3
package
chat.rocket.core.interactors
import
chat.rocket.core.models.Session
import
chat.rocket.core.models.User
import
io.reactivex.Flowable
import
io.reactivex.Single
import
chat.rocket.core.repositories.UserRepository
import
com.fernandocejas.arrow.optional.Optional
import
io.reactivex.functions.Function3
class
CanCreateRoomInteractor
(
private
val
userRepository
:
UserRepository
,
private
val
sessionInteractor
:
SessionInteractor
)
{
fun
canCreate
(
roomId
:
String
):
Single
<
Boolean
>
{
return
Flowable
.
zip
<
Optional
<
User
>,
Optional
<
Session
>,
String
,
Boolean
>(
userRepository
.
current
,
sessionInteractor
.
getDefault
(),
Flowable
.
just
(
roomId
),
Function3
{
user
,
session
,
room
->
user
.
isPresent
&&
session
.
isPresent
&&
room
!=
null
}
)
.
first
(
false
)
}
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/MessageInteractor.java
deleted
100644 → 0
View file @
1a41bf56
package
chat
.
rocket
.
core
.
interactors
;
import
com.fernandocejas.arrow.optional.Optional
;
import
io.reactivex.Flowable
;
import
io.reactivex.Single
;
import
java.util.List
;
import
java.util.UUID
;
import
chat.rocket.core.SyncState
;
import
chat.rocket.core.models.Message
;
import
chat.rocket.core.models.Room
;
import
chat.rocket.core.models.RoomHistoryState
;
import
chat.rocket.core.models.User
;
import
chat.rocket.core.repositories.MessageRepository
;
import
chat.rocket.core.repositories.RoomRepository
;
public
class
MessageInteractor
{
private
final
MessageRepository
messageRepository
;
private
final
RoomRepository
roomRepository
;
public
MessageInteractor
(
MessageRepository
messageRepository
,
RoomRepository
roomRepository
)
{
this
.
messageRepository
=
messageRepository
;
this
.
roomRepository
=
roomRepository
;
}
public
Single
<
Boolean
>
loadMessages
(
Room
room
)
{
final
RoomHistoryState
roomHistoryState
=
RoomHistoryState
.
builder
()
.
setRoomId
(
room
.
getRoomId
())
.
setSyncState
(
SyncState
.
NOT_SYNCED
)
.
setCount
(
100
)
.
setReset
(
true
)
.
setComplete
(
false
)
.
setTimestamp
(
0
)
.
build
();
return
roomRepository
.
setHistoryState
(
roomHistoryState
);
}
public
Single
<
Boolean
>
loadMoreMessages
(
Room
room
)
{
return
roomRepository
.
getHistoryStateByRoomId
(
room
.
getRoomId
())
.
filter
(
Optional:
:
isPresent
)
.
map
(
Optional:
:
get
)
.
filter
(
roomHistoryState
->
{
int
syncState
=
roomHistoryState
.
getSyncState
();
return
!
roomHistoryState
.
isComplete
()
&&
(
syncState
==
SyncState
.
SYNCED
||
syncState
==
SyncState
.
FAILED
);
})
.
map
(
Optional:
:
of
)
.
first
(
Optional
.
absent
())
.
flatMap
(
historyStateOptional
->
{
if
(!
historyStateOptional
.
isPresent
())
{
return
Single
.
just
(
false
);
}
return
roomRepository
.
setHistoryState
(
historyStateOptional
.
get
().
withSyncState
(
SyncState
.
NOT_SYNCED
));
});
}
public
Single
<
Boolean
>
send
(
Room
destination
,
User
sender
,
String
messageText
)
{
final
Message
message
=
Message
.
builder
()
.
setId
(
UUID
.
randomUUID
().
toString
())
.
setSyncState
(
SyncState
.
NOT_SYNCED
)
.
setTimestamp
(
System
.
currentTimeMillis
())
.
setRoomId
(
destination
.
getRoomId
())
.
setMessage
(
messageText
)
.
setGroupable
(
false
)
.
setUser
(
sender
)
.
build
();
return
messageRepository
.
save
(
message
);
}
public
Single
<
Boolean
>
resend
(
Message
message
,
User
sender
)
{
return
messageRepository
.
save
(
message
.
withSyncState
(
SyncState
.
NOT_SYNCED
)
.
withUser
(
sender
));
}
public
Single
<
Boolean
>
delete
(
Message
message
)
{
return
messageRepository
.
delete
(
message
);
}
public
Single
<
Integer
>
unreadCountFor
(
Room
room
,
User
user
)
{
return
messageRepository
.
unreadCountFor
(
room
,
user
);
}
public
Flowable
<
List
<
Message
>>
getAllFrom
(
Room
room
)
{
return
messageRepository
.
getAllFrom
(
room
);
}
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/MessageInteractor.kt
0 → 100644
View file @
349f73a3
package
chat.rocket.core.interactors
import
com.fernandocejas.arrow.optional.Optional
import
io.reactivex.Flowable
import
io.reactivex.Single
import
java.util.UUID
import
chat.rocket.core.SyncState
import
chat.rocket.core.models.Message
import
chat.rocket.core.models.Room
import
chat.rocket.core.models.RoomHistoryState
import
chat.rocket.core.models.User
import
chat.rocket.core.repositories.MessageRepository
import
chat.rocket.core.repositories.RoomRepository
class
MessageInteractor
(
private
val
messageRepository
:
MessageRepository
,
private
val
roomRepository
:
RoomRepository
)
{
fun
loadMessages
(
room
:
Room
):
Single
<
Boolean
>
{
val
roomHistoryState
=
RoomHistoryState
.
builder
()
.
setRoomId
(
room
.
roomId
)
.
setSyncState
(
SyncState
.
NOT_SYNCED
)
.
setCount
(
100
)
.
setReset
(
true
)
.
setComplete
(
false
)
.
setTimestamp
(
0
)
.
build
()
return
roomRepository
.
setHistoryState
(
roomHistoryState
)
}
fun
loadMoreMessages
(
room
:
Room
):
Single
<
Boolean
>
{
return
roomRepository
.
getHistoryStateByRoomId
(
room
.
roomId
)
.
filter
{
it
.
isPresent
}
.
map
{
it
.
get
()
}
.
filter
{
roomHistoryState
->
val
syncState
=
roomHistoryState
.
syncState
!
roomHistoryState
.
isComplete
&&
(
syncState
==
SyncState
.
SYNCED
||
syncState
==
SyncState
.
FAILED
)
}
.
map
{
Optional
.
of
(
it
)
}
.
first
(
Optional
.
absent
())
.
flatMap
{
historyStateOptional
->
if
(!
historyStateOptional
.
isPresent
)
{
return
@flatMap
Single
.
just
(
false
)
}
roomRepository
.
setHistoryState
(
historyStateOptional
.
get
().
withSyncState
(
SyncState
.
NOT_SYNCED
))
}
}
fun
send
(
destination
:
Room
,
sender
:
User
,
messageText
:
String
):
Single
<
Boolean
>
{
val
message
=
Message
.
builder
()
.
setId
(
UUID
.
randomUUID
().
toString
())
.
setSyncState
(
SyncState
.
NOT_SYNCED
)
.
setTimestamp
(
System
.
currentTimeMillis
())
.
setRoomId
(
destination
.
roomId
)
.
setMessage
(
messageText
)
.
setGroupable
(
false
)
.
setUser
(
sender
)
.
build
()
return
messageRepository
.
save
(
message
)
}
fun
resend
(
message
:
Message
,
sender
:
User
):
Single
<
Boolean
>
{
return
messageRepository
.
save
(
message
.
withSyncState
(
SyncState
.
NOT_SYNCED
).
withUser
(
sender
))
}
fun
delete
(
message
:
Message
):
Single
<
Boolean
>
{
return
messageRepository
.
delete
(
message
)
}
fun
unreadCountFor
(
room
:
Room
,
user
:
User
):
Single
<
Int
>
{
return
messageRepository
.
unreadCountFor
(
room
,
user
)
}
fun
getAllFrom
(
room
:
Room
):
Flowable
<
List
<
Message
>>
{
return
messageRepository
.
getAllFrom
(
room
)
}
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/RoomInteractor.java
deleted
100644 → 0
View file @
1a41bf56
package
chat
.
rocket
.
core
.
interactors
;
import
io.reactivex.Flowable
;
import
java.util.List
;
import
chat.rocket.core.models.Room
;
import
chat.rocket.core.repositories.RoomRepository
;
public
class
RoomInteractor
{
private
final
RoomRepository
roomRepository
;
public
RoomInteractor
(
RoomRepository
roomRepository
)
{
this
.
roomRepository
=
roomRepository
;
}
public
Flowable
<
Integer
>
getTotalUnreadMentionsCount
()
{
return
roomRepository
.
getAll
()
.
flatMap
(
rooms
->
Flowable
.
fromIterable
(
rooms
)
.
filter
(
room
->
room
.
isOpen
()
&&
room
.
isAlert
())
.
map
(
Room:
:
getUnread
)
.
defaultIfEmpty
(
0
)
.
reduce
((
unreadCount
,
unreadCount2
)
->
unreadCount
+
unreadCount2
)
.
toFlowable
());
}
public
Flowable
<
Long
>
getTotalUnreadRoomsCount
()
{
return
roomRepository
.
getAll
()
.
flatMap
(
rooms
->
Flowable
.
fromIterable
(
rooms
)
.
filter
(
room
->
room
.
isOpen
()
&&
room
.
isAlert
())
.
count
()
.
toFlowable
());
}
public
Flowable
<
List
<
Room
>>
getOpenRooms
()
{
return
roomRepository
.
getAll
()
.
flatMap
(
rooms
->
Flowable
.
fromIterable
(
rooms
)
.
filter
(
Room:
:
isOpen
)
.
toList
()
.
toFlowable
());
}
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/RoomInteractor.kt
0 → 100644
View file @
349f73a3
package
chat.rocket.core.interactors
import
io.reactivex.Flowable
import
chat.rocket.core.SortDirection
import
chat.rocket.core.models.Room
import
chat.rocket.core.repositories.RoomRepository
class
RoomInteractor
(
private
val
roomRepository
:
RoomRepository
)
{
fun
getTotalUnreadMentionsCount
():
Flowable
<
Int
>
{
return
roomRepository
.
all
.
flatMap
{
rooms
->
Flowable
.
fromIterable
(
rooms
)
.
filter
{
room
->
room
.
isOpen
&&
room
.
isAlert
}
.
map
{
it
.
unread
}
.
defaultIfEmpty
(
0
)
.
reduce
{
unreadCount
,
unreadCount2
->
unreadCount
+
unreadCount2
}
.
toFlowable
()
}
}
fun
getTotalUnreadRoomsCount
():
Flowable
<
Long
>
{
return
roomRepository
.
all
.
flatMap
{
rooms
->
Flowable
.
fromIterable
(
rooms
)
.
filter
{
room
->
room
.
isOpen
&&
room
.
isAlert
}
.
count
()
.
toFlowable
()
}
}
fun
getOpenRooms
():
Flowable
<
List
<
Room
>>
{
return
roomRepository
.
all
.
flatMap
{
rooms
->
Flowable
.
fromIterable
(
rooms
)
.
filter
{
it
.
isOpen
}
.
toList
()
.
toFlowable
()
}
}
fun
getRoomsWithNameLike
(
name
:
String
):
Flowable
<
List
<
Room
>>
{
return
roomRepository
.
getSortedLikeName
(
name
,
SortDirection
.
DESC
,
5
)
}
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/SessionInteractor.java
deleted
100644 → 0
View file @
1a41bf56
package
chat
.
rocket
.
core
.
interactors
;
import
com.fernandocejas.arrow.optional.Optional
;
import
io.reactivex.Flowable
;
import
io.reactivex.Single
;
import
chat.rocket.core.models.Session
;
import
chat.rocket.core.repositories.SessionRepository
;
public
class
SessionInteractor
{
private
static
final
int
DEFAULT_ID
=
0
;
private
final
SessionRepository
sessionRepository
;
public
SessionInteractor
(
SessionRepository
sessionRepository
)
{
this
.
sessionRepository
=
sessionRepository
;
}
public
Flowable
<
Optional
<
Session
>>
getDefault
()
{
return
sessionRepository
.
getById
(
DEFAULT_ID
);
}
public
Flowable
<
Session
.
State
>
getSessionState
()
{
return
getDefault
()
.
map
(
sessionOptional
->
getStateFrom
(
sessionOptional
.
orNull
()));
}
public
Single
<
Boolean
>
retryLogin
()
{
return
getDefault
()
.
filter
(
Optional:
:
isPresent
)
.
map
(
Optional:
:
get
)
.
filter
(
session
->
session
.
getToken
()
!=
null
&&
(!
session
.
isTokenVerified
()
||
session
.
getError
()
!=
null
))
.
map
(
session
->
Optional
.
of
(
session
.
withTokenVerified
(
false
).
withError
(
null
)))
.
first
(
Optional
.
absent
())
.
flatMap
(
sessionOptional
->
{
if
(!
sessionOptional
.
isPresent
())
{
return
Single
.
just
(
false
);
}
return
sessionRepository
.
save
(
sessionOptional
.
get
());
});
}
private
Session
.
State
getStateFrom
(
Session
session
)
{
if
(
session
==
null
)
{
return
Session
.
State
.
UNAVAILABLE
;
}
final
String
token
=
session
.
getToken
();
if
(
token
==
null
||
token
.
length
()
==
0
)
{
return
Session
.
State
.
UNAVAILABLE
;
}
final
String
error
=
session
.
getError
();
if
(
error
==
null
||
error
.
length
()
==
0
)
{
return
Session
.
State
.
VALID
;
}
return
Session
.
State
.
INVALID
;
}
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/SessionInteractor.kt
0 → 100644
View file @
349f73a3
package
chat.rocket.core.interactors
import
com.fernandocejas.arrow.optional.Optional
import
io.reactivex.Flowable
import
io.reactivex.Single
import
chat.rocket.core.models.Session
import
chat.rocket.core.repositories.SessionRepository
class
SessionInteractor
(
private
val
sessionRepository
:
SessionRepository
)
{
companion
object
{
private
val
DEFAULT_ID
=
0
}
fun
getDefault
():
Flowable
<
Optional
<
Session
>>
{
return
sessionRepository
.
getById
(
DEFAULT_ID
)
}
fun
getSessionState
():
Flowable
<
Session
.
State
>
{
return
getDefault
()
.
map
{
sessionOptional
->
getStateFrom
(
sessionOptional
.
orNull
())
}
}
fun
retryLogin
():
Single
<
Boolean
>
{
return
getDefault
()
.
filter
{
it
.
isPresent
}
.
map
{
it
.
get
()
}
.
filter
{
session
->
session
.
token
!=
null
&&
(!
session
.
isTokenVerified
||
session
.
error
!=
null
)
}
.
map
{
session
->
Optional
.
of
(
session
.
withTokenVerified
(
false
).
withError
(
null
))
}
.
first
(
Optional
.
absent
())
.
flatMap
{
sessionOptional
->
if
(!
sessionOptional
.
isPresent
)
{
return
@flatMap
Single
.
just
(
false
)
}
sessionRepository
.
save
(
sessionOptional
.
get
())
}
}
private
fun
getStateFrom
(
session
:
Session
?):
Session
.
State
{
if
(
session
==
null
)
{
return
Session
.
State
.
UNAVAILABLE
}
val
token
=
session
.
token
if
(
token
==
null
||
token
.
isEmpty
())
{
return
Session
.
State
.
UNAVAILABLE
}
val
error
=
session
.
error
if
(
error
==
null
||
error
.
isEmpty
())
{
return
Session
.
State
.
VALID
}
return
Session
.
State
.
INVALID
}
}
rocket-chat-core/src/main/java/chat/rocket/core/interactors/UserInteractor.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
core
.
interactors
;
import
io.reactivex.Flowable
;
import
java.util.List
;
import
chat.rocket.core.SortDirection
;
import
chat.rocket.core.models.User
;
import
chat.rocket.core.repositories.UserRepository
;
public
class
UserInteractor
{
private
final
UserRepository
userRepository
;
public
UserInteractor
(
UserRepository
userRepository
)
{
this
.
userRepository
=
userRepository
;
}
public
Flowable
<
List
<
User
>>
getUserAutocompleteSuggestions
(
String
name
)
{
return
userRepository
.
getSortedLikeName
(
name
,
SortDirection
.
DESC
,
5
);
}
}
rocket-chat-core/src/main/java/chat/rocket/core/models/SpotlightRoom.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
core
.
models
;
import
com.google.auto.value.AutoValue
;
@AutoValue
public
abstract
class
SpotlightRoom
{
public
abstract
String
getId
();
public
abstract
String
getName
();
public
abstract
String
getType
();
public
boolean
isChannel
()
{
return
Room
.
TYPE_CHANNEL
.
equals
(
getType
());
}
public
boolean
isPrivate
()
{
return
Room
.
TYPE_PRIVATE
.
equals
(
getType
());
}
public
boolean
isDirectMessage
()
{
return
Room
.
TYPE_DIRECT_MESSAGE
.
equals
(
getType
());
}
public
static
Builder
builder
()
{
return
new
AutoValue_SpotlightRoom
.
Builder
();
}
@AutoValue
.
Builder
public
abstract
static
class
Builder
{
public
abstract
Builder
setId
(
String
id
);
public
abstract
Builder
setName
(
String
name
);
public
abstract
Builder
setType
(
String
type
);
public
abstract
SpotlightRoom
build
();
}
}
rocket-chat-core/src/main/java/chat/rocket/core/models/SpotlightUser.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
core
.
models
;
import
com.google.auto.value.AutoValue
;
import
javax.annotation.Nullable
;
@AutoValue
public
abstract
class
SpotlightUser
{
public
abstract
String
getId
();
public
abstract
String
getUsername
();
@Nullable
public
abstract
String
getName
();
@Nullable
public
abstract
String
getStatus
();
public
static
Builder
builder
()
{
return
new
AutoValue_SpotlightUser
.
Builder
();
}
@AutoValue
.
Builder
public
abstract
static
class
Builder
{
public
abstract
Builder
setId
(
String
id
);
public
abstract
Builder
setUsername
(
String
username
);
public
abstract
Builder
setName
(
String
name
);
public
abstract
Builder
setStatus
(
String
status
);
public
abstract
SpotlightUser
build
();
}
}
rocket-chat-core/src/main/java/chat/rocket/core/repositories/RoomRepository.java
View file @
349f73a3
...
...
@@ -5,6 +5,7 @@ import io.reactivex.Flowable;
import
io.reactivex.Single
;
import
java.util.List
;
import
chat.rocket.core.SortDirection
;
import
chat.rocket.core.models.Room
;
import
chat.rocket.core.models.RoomHistoryState
;
...
...
@@ -17,4 +18,8 @@ public interface RoomRepository {
Flowable
<
Optional
<
RoomHistoryState
>>
getHistoryStateByRoomId
(
String
roomId
);
Single
<
Boolean
>
setHistoryState
(
RoomHistoryState
roomHistoryState
);
Flowable
<
List
<
Room
>>
getSortedLikeName
(
String
name
,
SortDirection
direction
,
int
limit
);
Flowable
<
List
<
Room
>>
getLatestSeen
(
int
limit
);
}
rocket-chat-core/src/main/java/chat/rocket/core/repositories/SpotlightRoomRepository.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
core
.
repositories
;
import
io.reactivex.Flowable
;
import
java.util.List
;
import
chat.rocket.core.SortDirection
;
import
chat.rocket.core.models.SpotlightRoom
;
public
interface
SpotlightRoomRepository
{
Flowable
<
List
<
SpotlightRoom
>>
getSuggestionsFor
(
String
name
,
SortDirection
direction
,
int
limit
);
}
rocket-chat-core/src/main/java/chat/rocket/core/repositories/SpotlightUserRepository.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
core
.
repositories
;
import
io.reactivex.Flowable
;
import
java.util.List
;
import
chat.rocket.core.SortDirection
;
import
chat.rocket.core.models.SpotlightUser
;
public
interface
SpotlightUserRepository
{
Flowable
<
List
<
SpotlightUser
>>
getSuggestionsFor
(
String
name
,
SortDirection
direction
,
int
limit
);
}
rocket-chat-core/src/main/java/chat/rocket/core/repositories/UserRepository.java
View file @
349f73a3
...
...
@@ -3,9 +3,13 @@ package chat.rocket.core.repositories;
import
com.fernandocejas.arrow.optional.Optional
;
import
io.reactivex.Flowable
;
import
java.util.List
;
import
chat.rocket.core.SortDirection
;
import
chat.rocket.core.models.User
;
public
interface
UserRepository
{
Flowable
<
Optional
<
User
>>
getCurrent
();
Flowable
<
List
<
User
>>
getSortedLikeName
(
String
name
,
SortDirection
direction
,
int
limit
);
}
rocket-chat-core/src/main/java/chat/rocket/core/temp/TempSpotlightRoomCaller.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
core
.
temp
;
public
interface
TempSpotlightRoomCaller
{
void
search
(
String
term
);
}
rocket-chat-core/src/main/java/chat/rocket/core/temp/TempSpotlightUserCaller.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
core
.
temp
;
public
interface
TempSpotlightUserCaller
{
void
search
(
String
term
);
}
rocket-chat-core/src/main/java/chat/rocket/core/utils/Pair.java
0 → 100644
View file @
349f73a3
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/util/Pair.java
package
chat
.
rocket
.
core
.
utils
;
/**
* Container to ease passing around a tuple of two objects. This object provides a sensible
* implementation of equals(), returning true if equals() is true on each of the contained
* objects.
*/
public
class
Pair
<
F
,
S
>
{
public
final
F
first
;
public
final
S
second
;
/**
* Constructor for a Pair.
* @param first the first object in the Pair
* @param second the second object in the pair
*/
public
Pair
(
F
first
,
S
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
/**
* Checks the two objects for equality by delegating to their respective
* {@link Object#equals(Object)} methods.
* @param o the {@link Pair} to which this one is to be checked for equality
* @return true if the underlying objects of the Pair are both considered equal
*/
@Override
public
boolean
equals
(
Object
o
)
{
if
(!(
o
instanceof
Pair
))
{
return
false
;
}
Pair
<?,
?>
p
=
(
Pair
<?,
?>)
o
;
return
equals
(
p
.
first
,
first
)
&&
equals
(
p
.
second
,
second
);
}
/**
* Compute a hash code using the hash codes of the underlying objects
* @return a hashcode of the Pair
*/
@Override
public
int
hashCode
()
{
return
(
first
==
null
?
0
:
first
.
hashCode
())
^
(
second
==
null
?
0
:
second
.
hashCode
());
}
@Override
public
String
toString
()
{
return
"Pair{"
+
String
.
valueOf
(
first
)
+
" "
+
String
.
valueOf
(
second
)
+
"}"
;
}
private
boolean
equals
(
Object
var0
,
Object
var1
)
{
return
var0
==
var1
||
var0
!=
null
&&
var0
.
equals
(
var1
);
}
/**
* Convenience method for creating an appropriately typed pair.
* @param a the first object in the Pair
* @param b the second object in the pair
* @return a Pair that is templatized with the types of a and b
*/
public
static
<
A
,
B
>
Pair
<
A
,
B
>
create
(
A
a
,
B
b
)
{
return
new
Pair
<
A
,
B
>(
a
,
b
);
}
}
\ No newline at end of file
rocket-chat-core/src/main/java/chat/rocket/core/utils/Triple.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
core
.
utils
;
public
class
Triple
<
F
,
S
,
T
>
{
public
final
F
first
;
public
final
S
second
;
public
final
T
third
;
public
Triple
(
F
first
,
S
second
,
T
third
)
{
this
.
first
=
first
;
this
.
second
=
second
;
this
.
third
=
third
;
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(!(
o
instanceof
Triple
))
{
return
false
;
}
Triple
<?,
?,
?>
t
=
(
Triple
<?,
?,
?>)
o
;
return
equals
(
t
.
first
,
first
)
&&
equals
(
t
.
second
,
second
)
&&
equals
(
t
.
third
,
third
);
}
@Override
public
int
hashCode
()
{
return
(
first
==
null
?
0
:
first
.
hashCode
())
^
(
second
==
null
?
0
:
second
.
hashCode
())
^
(
third
==
null
?
0
:
third
.
hashCode
());
}
private
boolean
equals
(
Object
var0
,
Object
var1
)
{
return
var0
==
var1
||
var0
!=
null
&&
var0
.
equals
(
var1
);
}
public
static
<
A
,
B
,
C
>
Triple
<
A
,
B
,
C
>
create
(
A
a
,
B
b
,
C
c
)
{
return
new
Triple
<
A
,
B
,
C
>(
a
,
b
,
c
);
}
}
rocket-chat-core/src/test/java/chat/rocket/core/interactors/AutocompleteChannelInteractorTest.java
0 → 100644
View file @
349f73a3
package
chat
.
rocket
.
core
.
interactors
;
import
static
org
.
mockito
.
Mockito
.*;
import
io.reactivex.Flowable
;
import
io.reactivex.subscribers.TestSubscriber
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.Mock
;
import
org.mockito.junit.MockitoJUnitRunner
;
import
java.util.ArrayList
;
import
java.util.List
;
import
chat.rocket.core.SortDirection
;
import
chat.rocket.core.models.Room
;
import
chat.rocket.core.models.SpotlightRoom
;
import
chat.rocket.core.repositories.RoomRepository
;
import
chat.rocket.core.repositories.SpotlightRoomRepository
;
import
chat.rocket.core.temp.TempSpotlightRoomCaller
;
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
AutocompleteChannelInteractorTest
{
@Mock
RoomRepository
roomRepository
;
@Mock
SpotlightRoomRepository
spotlightRoomRepository
;
@Mock
TempSpotlightRoomCaller
tempSpotlightRoomCaller
;
private
AutocompleteChannelInteractor
autocompleteChannelInteractor
;
@Before
public
void
setUp
()
{
autocompleteChannelInteractor
=
new
AutocompleteChannelInteractor
(
roomRepository
,
spotlightRoomRepository
,
tempSpotlightRoomCaller
);
}
@Test
public
void
getSuggestionsForEmptyStringReturnLatestSeenOnly
()
throws
Exception
{
List
<
Room
>
rooms
=
new
ArrayList
<>();
rooms
.
add
(
getRoom
(
"id1"
,
"Name1"
,
"c"
));
when
(
roomRepository
.
getLatestSeen
(
anyInt
())).
thenReturn
(
Flowable
.
just
(
rooms
));
rooms
=
new
ArrayList
<>();
rooms
.
add
(
getRoom
(
"id2"
,
"Name2"
,
"c"
));
when
(
roomRepository
.
getSortedLikeName
(
anyString
(),
any
(
SortDirection
.
class
),
anyInt
()))
.
thenReturn
(
Flowable
.
just
(
rooms
));
TestSubscriber
<
List
<
SpotlightRoom
>>
testSubscriber
=
new
TestSubscriber
<>();
autocompleteChannelInteractor
.
getSuggestionsFor
(
""
).
subscribe
(
testSubscriber
);
List
<
SpotlightRoom
>
spotlightRooms
=
new
ArrayList
<>();
spotlightRooms
.
add
(
getSpotlightRoom
(
"id1"
,
"Name1"
,
"c"
));
testSubscriber
.
assertResult
(
spotlightRooms
);
}
@Test
public
void
getSuggestionsForNonEmptyStringReturnLatestSeenAndFromRooms
()
throws
Exception
{
List
<
Room
>
rooms
=
new
ArrayList
<>();
rooms
.
add
(
getRoom
(
"id1"
,
"Name1"
,
"c"
));
rooms
.
add
(
getRoom
(
"id1.1"
,
"Ame1.1"
,
"c"
));
when
(
roomRepository
.
getLatestSeen
(
anyInt
())).
thenReturn
(
Flowable
.
just
(
rooms
));
rooms
=
new
ArrayList
<>();
rooms
.
add
(
getRoom
(
"id1"
,
"Name1"
,
"c"
));
rooms
.
add
(
getRoom
(
"id2"
,
"Name2"
,
"c"
));
rooms
.
add
(
getRoom
(
"id3"
,
"Name3"
,
"c"
));
rooms
.
add
(
getRoom
(
"id4"
,
"Name4"
,
"c"
));
rooms
.
add
(
getRoom
(
"id5"
,
"Name5"
,
"c"
));
when
(
roomRepository
.
getSortedLikeName
(
anyString
(),
any
(
SortDirection
.
class
),
anyInt
()))
.
thenReturn
(
Flowable
.
just
(
rooms
));
TestSubscriber
<
List
<
SpotlightRoom
>>
testSubscriber
=
new
TestSubscriber
<>();
autocompleteChannelInteractor
.
getSuggestionsFor
(
"N"
).
subscribe
(
testSubscriber
);
List
<
SpotlightRoom
>
spotlightRooms
=
new
ArrayList
<>();
spotlightRooms
.
add
(
getSpotlightRoom
(
"id1"
,
"Name1"
,
"c"
));
spotlightRooms
.
add
(
getSpotlightRoom
(
"id2"
,
"Name2"
,
"c"
));
spotlightRooms
.
add
(
getSpotlightRoom
(
"id3"
,
"Name3"
,
"c"
));
spotlightRooms
.
add
(
getSpotlightRoom
(
"id4"
,
"Name4"
,
"c"
));
spotlightRooms
.
add
(
getSpotlightRoom
(
"id5"
,
"Name5"
,
"c"
));
testSubscriber
.
assertResult
(
spotlightRooms
);
}
@Test
public
void
getSuggestionsForMayGetFromNetwork
()
throws
Exception
{
List
<
Room
>
rooms
=
new
ArrayList
<>();
rooms
.
add
(
getRoom
(
"id1"
,
"Name1"
,
"c"
));
rooms
.
add
(
getRoom
(
"id1.1"
,
"Ame1.1"
,
"c"
));
when
(
roomRepository
.
getLatestSeen
(
anyInt
())).
thenReturn
(
Flowable
.
just
(
rooms
));
rooms
=
new
ArrayList
<>();
rooms
.
add
(
getRoom
(
"id1"
,
"Name1"
,
"c"
));
rooms
.
add
(
getRoom
(
"id2"
,
"Name2"
,
"c"
));
when
(
roomRepository
.
getSortedLikeName
(
anyString
(),
any
(
SortDirection
.
class
),
anyInt
()))
.
thenReturn
(
Flowable
.
just
(
rooms
));
List
<
SpotlightRoom
>
spotlightRooms
=
new
ArrayList
<>();
spotlightRooms
.
add
(
getSpotlightRoom
(
"id3"
,
"Name3"
,
"c"
));
when
(
spotlightRoomRepository
.
getSuggestionsFor
(
anyString
(),
any
(
SortDirection
.
class
),
anyInt
()))
.
thenReturn
(
Flowable
.
just
(
spotlightRooms
));
TestSubscriber
<
List
<
SpotlightRoom
>>
testSubscriber
=
new
TestSubscriber
<>();
autocompleteChannelInteractor
.
getSuggestionsFor
(
"N"
).
subscribe
(
testSubscriber
);
verify
(
tempSpotlightRoomCaller
,
times
(
1
)).
search
(
anyString
());
spotlightRooms
=
new
ArrayList
<>();
spotlightRooms
.
add
(
getSpotlightRoom
(
"id1"
,
"Name1"
,
"c"
));
spotlightRooms
.
add
(
getSpotlightRoom
(
"id2"
,
"Name2"
,
"c"
));
spotlightRooms
.
add
(
getSpotlightRoom
(
"id3"
,
"Name3"
,
"c"
));
testSubscriber
.
assertResult
(
spotlightRooms
);
}
private
Room
getRoom
(
String
id
,
String
name
,
String
type
)
{
Room
room
=
mock
(
Room
.
class
);
when
(
room
.
getId
()).
thenReturn
(
id
);
when
(
room
.
getName
()).
thenReturn
(
name
);
when
(
room
.
getType
()).
thenReturn
(
type
);
return
room
;
}
private
SpotlightRoom
getSpotlightRoom
(
String
id
,
String
name
,
String
type
)
{
return
SpotlightRoom
.
builder
()
.
setId
(
id
).
setName
(
name
).
setType
(
type
).
build
();
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment