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
f4a743d4
Commit
f4a743d4
authored
Mar 14, 2019
by
Filipe de Lima Brito
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Jitsi SDK
parent
fa0cc587
Changes
98
Hide whitespace changes
Inline
Side-by-side
Showing
98 changed files
with
743 additions
and
503 deletions
+743
-503
build.gradle
app/build.gradle
+31
-23
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+7
-0
AppLifecycleObserver.kt
...main/java/chat/rocket/android/app/AppLifecycleObserver.kt
+3
-7
RocketChatApplication.kt
...ain/java/chat/rocket/android/app/RocketChatApplication.kt
+3
-2
AuthenticationModule.kt
.../rocket/android/authentication/di/AuthenticationModule.kt
+1
-1
LoginOptionsPresenter.kt
...cation/loginoptions/presentation/LoginOptionsPresenter.kt
+3
-3
OnBoardingPresenter.kt
...entication/onboarding/presentation/OnBoardingPresenter.kt
+4
-4
ServerPresenter.kt
...oid/authentication/server/presentation/ServerPresenter.kt
+3
-3
ChatDetailsFragment.kt
...chat/rocket/android/chatdetails/ui/ChatDetailsFragment.kt
+0
-1
Menu.kt
app/src/main/java/chat/rocket/android/chatdetails/ui/Menu.kt
+4
-2
MessageInfoFragmentModule.kt
...t/android/chatinformation/di/MessageInfoFragmentModule.kt
+1
-1
MessageInfoActivity.kt
.../rocket/android/chatinformation/ui/MessageInfoActivity.kt
+0
-1
ChatRoomAdapter.kt
...a/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
+5
-8
MessageReactionsAdapter.kt
...ocket/android/chatroom/adapter/MessageReactionsAdapter.kt
+3
-3
MessageViewHolder.kt
...chat/rocket/android/chatroom/adapter/MessageViewHolder.kt
+6
-1
UrlPreviewViewHolder.kt
...t/rocket/android/chatroom/adapter/UrlPreviewViewHolder.kt
+5
-4
ChatRoomModule.kt
...in/java/chat/rocket/android/chatroom/di/ChatRoomModule.kt
+1
-1
ChatRoomNavigator.kt
...rocket/android/chatroom/presentation/ChatRoomNavigator.kt
+5
-0
ChatRoomPresenter.kt
...rocket/android/chatroom/presentation/ChatRoomPresenter.kt
+19
-21
MessageService.kt
...va/chat/rocket/android/chatroom/service/MessageService.kt
+6
-4
ChatRoomFragment.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
+3
-4
Dialog.kt
app/src/main/java/chat/rocket/android/chatroom/ui/Dialog.kt
+6
-5
BaseUiModel.kt
.../java/chat/rocket/android/chatroom/uimodel/BaseUiModel.kt
+1
-1
MessageUiModel.kt
...va/chat/rocket/android/chatroom/uimodel/MessageUiModel.kt
+0
-1
UiModelMapper.kt
...ava/chat/rocket/android/chatroom/uimodel/UiModelMapper.kt
+9
-9
ChatRoomsPresenter.kt
...cket/android/chatrooms/presentation/ChatRoomsPresenter.kt
+3
-2
ChatRoomsViewModel.kt
.../rocket/android/chatrooms/viewmodel/ChatRoomsViewModel.kt
+10
-10
ActivityBuilder.kt
...java/chat/rocket/android/dagger/module/ActivityBuilder.kt
+6
-0
AppModule.kt
.../main/java/chat/rocket/android/dagger/module/AppModule.kt
+0
-1
LocalModule.kt
...ain/java/chat/rocket/android/dagger/module/LocalModule.kt
+0
-1
DatabaseManager.kt
app/src/main/java/chat/rocket/android/db/DatabaseManager.kt
+12
-11
AndroidPermissionsHelper.kt
...va/chat/rocket/android/helper/AndroidPermissionsHelper.kt
+4
-2
JitsiHelper.kt
app/src/main/java/chat/rocket/android/helper/JitsiHelper.kt
+34
-0
MainModule.kt
app/src/main/java/chat/rocket/android/main/di/MainModule.kt
+1
-1
MainPresenter.kt
...va/chat/rocket/android/main/presentation/MainPresenter.kt
+1
-1
ProfilePresenter.kt
...t/rocket/android/profile/presentation/ProfilePresenter.kt
+3
-3
DirectReplyReceiver.kt
...main/java/chat/rocket/android/push/DirectReplyReceiver.kt
+3
-3
PushManager.kt
app/src/main/java/chat/rocket/android/push/PushManager.kt
+1
-1
ChangeServerModule.kt
.../java/chat/rocket/android/server/di/ChangeServerModule.kt
+1
-2
ChatRoomsInteractor.kt
.../chat/rocket/android/server/domain/ChatRoomsInteractor.kt
+16
-14
RefreshPermissionsInteractor.kt
...ket/android/server/domain/RefreshPermissionsInteractor.kt
+4
-3
RefreshSettingsInteractor.kt
...rocket/android/server/domain/RefreshSettingsInteractor.kt
+8
-5
SettingsRepository.kt
...a/chat/rocket/android/server/domain/SettingsRepository.kt
+4
-0
ConnectionManager.kt
...ocket/android/server/infraestructure/ConnectionManager.kt
+47
-40
DatabaseMessageMapper.kt
...t/android/server/infraestructure/DatabaseMessageMapper.kt
+54
-44
DatabaseMessagesRepository.kt
...roid/server/infraestructure/DatabaseMessagesRepository.kt
+19
-18
CheckServerPresenter.kt
...ocket/android/server/presentation/CheckServerPresenter.kt
+5
-5
ChangeServerActivity.kt
...ava/chat/rocket/android/server/ui/ChangeServerActivity.kt
+0
-1
SettingsFragmentModule.kt
...chat/rocket/android/settings/di/SettingsFragmentModule.kt
+1
-1
PasswordFragmentModule.kt
...et/android/settings/password/di/PasswordFragmentModule.kt
+1
-1
UserDetailsPresenter.kt
.../android/userdetails/presentation/UserDetailsPresenter.kt
+3
-3
IO.kt
app/src/main/java/chat/rocket/android/util/IO.kt
+23
-24
Fragment.kt
...main/java/chat/rocket/android/util/extensions/Fragment.kt
+5
-4
RocketChatClient.kt
...a/chat/rocket/android/util/extensions/RocketChatClient.kt
+3
-3
TransformedLiveData.kt
.../chat/rocket/android/util/livedata/TransformedLiveData.kt
+14
-13
WrappedLiveData.kt
...java/chat/rocket/android/util/livedata/WrappedLiveData.kt
+13
-11
VideoConferencingModule.kt
...t/android/videoconferencing/di/VideoConferencingModule.kt
+33
-0
VideoConferencingPresenter.kt
...videoconferencing/presenter/VideoConferencingPresenter.kt
+61
-0
VideoConferencingView.kt
...roid/videoconferencing/presenter/VideoConferencingView.kt
+13
-0
VideoConferencingActivity.kt
...android/videoconferencing/ui/VideoConferencingActivity.kt
+36
-0
WebViewActivity.kt
...in/java/chat/rocket/android/webview/ui/WebViewActivity.kt
+1
-1
item_message.xml
app/src/main/res/layout/item_message.xml
+10
-0
strings.xml
app/src/main/res/values-de/strings.xml
+1
-0
strings.xml
app/src/main/res/values-es/strings.xml
+1
-0
strings.xml
app/src/main/res/values-fa/strings.xml
+1
-0
strings.xml
app/src/main/res/values-fr/strings.xml
+1
-0
strings.xml
app/src/main/res/values-hi-rIN/strings.xml
+1
-0
strings.xml
app/src/main/res/values-it/strings.xml
+1
-0
strings.xml
app/src/main/res/values-ja/strings.xml
+1
-0
strings.xml
app/src/main/res/values-pt-rBR/strings.xml
+1
-0
strings.xml
app/src/main/res/values-ru-rRU/strings.xml
+1
-0
strings.xml
app/src/main/res/values-tr/strings.xml
+1
-0
strings.xml
app/src/main/res/values-uk/strings.xml
+1
-0
strings.xml
app/src/main/res/values-zh-rCN/strings.xml
+1
-0
strings.xml
app/src/main/res/values/strings.xml
+1
-0
GooglePlayServices.kt
...java/chat/rocket/android/extensions/GooglePlayServices.kt
+3
-1
SmartLockHelper.kt
...c/play/java/chat/rocket/android/helper/SmartLockHelper.kt
+1
-1
CrashlyticsWrapper.kt
.../chat/rocket/android/infrastructure/CrashlyticsWrapper.kt
+21
-14
TokenRegistrationWorker.kt
...hat/rocket/android/push/worker/TokenRegistrationWorker.kt
+1
-1
build.gradle
build.gradle
+4
-4
build.gradle
core/build.gradle
+1
-1
CancelStrategy.kt
...java/chat/rocket/android/core/lifecycle/CancelStrategy.kt
+1
-1
dependencies.gradle
dependencies.gradle
+21
-27
build.gradle
draw/build.gradle
+1
-1
DrawModule.kt
.../main/java/chat/rocket/android/draw/main/di/DrawModule.kt
+1
-1
build.gradle
emoji/build.gradle
+9
-14
EmojiKeyboardPopup.kt
...main/java/chat/rocket/android/emoji/EmojiKeyboardPopup.kt
+4
-3
EmojiParser.kt
emoji/src/main/java/chat/rocket/android/emoji/EmojiParser.kt
+10
-8
EmojiPickerPopup.kt
...c/main/java/chat/rocket/android/emoji/EmojiPickerPopup.kt
+4
-3
EmojiRepository.kt
...rc/main/java/chat/rocket/android/emoji/EmojiRepository.kt
+39
-35
EmojiGlideModule.kt
...va/chat/rocket/android/emoji/internal/EmojiGlideModule.kt
+0
-15
EmojiPagerAdapter.kt
...a/chat/rocket/android/emoji/internal/EmojiPagerAdapter.kt
+10
-10
build.gradle
player/build.gradle
+1
-0
settings.gradle
settings.gradle
+1
-1
TrieNode.kt
...rocket/android/suggestions/strategy/trie/data/TrieNode.kt
+2
-7
build.gradle
util/build.gradle
+1
-1
Coroutines.kt
...ain/java/chat/rocket/android/util/extension/Coroutines.kt
+6
-7
Image.kt
...src/main/java/chat/rocket/android/util/extension/Image.kt
+6
-8
No files found.
app/build.gradle
View file @
f4a743d4
...
@@ -2,7 +2,9 @@ def taskRequests = getGradle().getStartParameter().getTaskRequests().toString()
...
@@ -2,7 +2,9 @@ def taskRequests = getGradle().getStartParameter().getTaskRequests().toString()
def
isPlay
=
!(
taskRequests
.
contains
(
"Foss"
)
||
taskRequests
.
contains
(
"foss"
))
def
isPlay
=
!(
taskRequests
.
contains
(
"Foss"
)
||
taskRequests
.
contains
(
"foss"
))
apply
plugin:
'com.android.application'
apply
plugin:
'com.android.application'
if
(
isPlay
)
{
apply
plugin:
'io.fabric'
}
if
(
isPlay
)
{
apply
plugin:
'io.fabric'
}
apply
plugin:
'kotlin-android'
apply
plugin:
'kotlin-android'
apply
plugin:
'kotlin-android-extensions'
apply
plugin:
'kotlin-android-extensions'
apply
plugin:
'kotlin-kapt'
apply
plugin:
'kotlin-kapt'
...
@@ -16,13 +18,12 @@ android {
...
@@ -16,13 +18,12 @@ android {
applicationId
"chat.rocket.android"
applicationId
"chat.rocket.android"
minSdkVersion
versions
.
minSdk
minSdkVersion
versions
.
minSdk
targetSdkVersion
versions
.
targetSdk
targetSdkVersion
versions
.
targetSdk
versionCode
205
7
versionCode
205
8
versionName
"3.
2
.0"
versionName
"3.
3
.0"
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled
true
multiDexEnabled
true
def
gitSha
=
'git rev-parse --short HEAD'
.
execute
([],
project
.
rootDir
).
text
.
trim
()
def
gitSha
=
'git rev-parse --short HEAD'
.
execute
([],
project
.
rootDir
).
text
.
trim
()
def
buildTime
=
new
GregorianCalendar
().
format
(
"MM-dd-yyyy' 'h:mm:ss a z"
)
buildConfigField
"String"
,
"GIT_SHA"
,
"\"${gitSha}\""
buildConfigField
"String"
,
"GIT_SHA"
,
"\"${gitSha}\""
javaCompileOptions
{
javaCompileOptions
{
...
@@ -30,6 +31,17 @@ android {
...
@@ -30,6 +31,17 @@ android {
arguments
=
[
"room.schemaLocation"
:
"$projectDir/schemas"
.
toString
()]
arguments
=
[
"room.schemaLocation"
:
"$projectDir/schemas"
.
toString
()]
}
}
}
}
// For Jitsi
compileOptions
{
sourceCompatibility
JavaVersion
.
VERSION_1_8
targetCompatibility
JavaVersion
.
VERSION_1_8
}
// For Jitsi
ndk
{
abiFilters
"armeabi-v7a"
,
"x86"
}
}
}
signingConfigs
{
signingConfigs
{
...
@@ -73,7 +85,7 @@ android {
...
@@ -73,7 +85,7 @@ android {
dimension
"type"
dimension
"type"
}
}
// only
foss
// only
FOSS
foss
{
foss
{
dimension
"type"
dimension
"type"
}
}
...
@@ -96,7 +108,7 @@ dependencies {
...
@@ -96,7 +108,7 @@ dependencies {
implementation
project
(
':suggestions'
)
implementation
project
(
':suggestions'
)
implementation
libraries
.
kotlin
implementation
libraries
.
kotlin
implementation
libraries
.
coroutines
implementation
libraries
.
coroutines
Core
implementation
libraries
.
coroutinesAndroid
implementation
libraries
.
coroutinesAndroid
implementation
libraries
.
appCompat
implementation
libraries
.
appCompat
...
@@ -123,6 +135,8 @@ dependencies {
...
@@ -123,6 +135,8 @@ dependencies {
implementation
libraries
.
viewmodelKtx
implementation
libraries
.
viewmodelKtx
implementation
libraries
.
workmanager
implementation
libraries
.
workmanager
implementation
libraries
.
livedataKtx
implementation
libraries
.
rxKotlin
implementation
libraries
.
rxKotlin
implementation
libraries
.
rxAndroid
implementation
libraries
.
rxAndroid
...
@@ -133,25 +147,25 @@ dependencies {
...
@@ -133,25 +147,25 @@ dependencies {
implementation
libraries
.
timber
implementation
libraries
.
timber
implementation
libraries
.
threeTenABP
implementation
libraries
.
threeTenABP
kapt
libraries
.
kotshiCompiler
implementation
libraries
.
kotshiApi
implementation
libraries
.
fresco
implementation
libraries
.
fresco
api
libraries
.
frescoOkHttp
api
libraries
.
frescoOkHttp
implementation
libraries
.
frescoAnimatedGif
implementation
libraries
.
frescoAnimatedGif
implementation
libraries
.
frescoWebP
implementation
libraries
.
frescoWebP
implementation
libraries
.
frescoAnimatedWebP
implementation
libraries
.
frescoAnimatedWebP
implementation
libraries
.
glide
implementation
libraries
.
glideTransformations
kapt
libraries
.
kotshiCompiler
implementation
libraries
.
kotshiApi
implementation
libraries
.
frescoImageViewer
implementation
libraries
.
frescoImageViewer
implementation
libraries
.
markwon
implementation
libraries
.
markwon
implementation
libraries
.
aVLoadingIndicatorView
implementation
libraries
.
aVLoadingIndicatorView
implementation
libraries
.
livedataKtx
implementation
libraries
.
glide
implementation
libraries
.
glideTransformations
implementation
(
libraries
.
jitsi
)
{
transitive
=
true
}
implementation
'com.google.code.findbugs:jsr305:3.0.2'
implementation
'com.google.code.findbugs:jsr305:3.0.2'
...
@@ -159,8 +173,8 @@ dependencies {
...
@@ -159,8 +173,8 @@ dependencies {
playImplementation
libraries
.
fcm
playImplementation
libraries
.
fcm
playImplementation
libraries
.
firebaseAnalytics
playImplementation
libraries
.
firebaseAnalytics
playImplementation
libraries
.
playServicesAuth
playImplementation
libraries
.
playServicesAuth
playImplementation
(
'com.crashlytics.sdk.android:crashlytics:2.9.
5
@aar'
)
{
transitive
=
true
}
playImplementation
(
'com.crashlytics.sdk.android:crashlytics:2.9.
8
@aar'
)
{
transitive
=
true
}
playImplementation
(
'com.crashlytics.sdk.android:answers:1.4.
3
@aar'
)
{
transitive
=
true
}
playImplementation
(
'com.crashlytics.sdk.android:answers:1.4.
6
@aar'
)
{
transitive
=
true
}
testImplementation
libraries
.
junit
testImplementation
libraries
.
junit
testImplementation
libraries
.
truth
testImplementation
libraries
.
truth
...
@@ -168,12 +182,6 @@ dependencies {
...
@@ -168,12 +182,6 @@ dependencies {
androidTestImplementation
libraries
.
espressoIntents
androidTestImplementation
libraries
.
espressoIntents
}
}
kotlin
{
experimental
{
coroutines
"enable"
}
}
androidExtensions
{
androidExtensions
{
experimental
=
true
experimental
=
true
}
}
...
@@ -181,8 +189,8 @@ androidExtensions {
...
@@ -181,8 +189,8 @@ androidExtensions {
// FIXME - build and install the sdk into the app/libs directory
// FIXME - build and install the sdk into the app/libs directory
// We were having some issues with the kapt generated files from the sdk when importing as a module
// We were having some issues with the kapt generated files from the sdk when importing as a module
def
sdk_location
=
project
.
properties
[
'sdk_location'
]
?:
""
def
sdk_location
=
project
.
properties
[
'sdk_location'
]
?:
""
task
compileSdk
(
type:
Exec
)
{
task
compileSdk
(
type:
Exec
)
{
if
(
System
.
getProperty
(
'os.name'
).
toLowerCase
(
Locale
.
ROOT
).
contains
(
'windows'
))
{
if
(
System
.
getProperty
(
'os.name'
).
toLowerCase
(
Locale
.
ROOT
).
contains
(
'windows'
))
{
commandLine
'cmd'
,
'/c'
,
'build-sdk.sh'
,
sdk_location
commandLine
'cmd'
,
'/c'
,
'build-sdk.sh'
,
sdk_location
}
else
{
}
else
{
...
...
app/src/main/AndroidManifest.xml
View file @
f4a743d4
...
@@ -6,6 +6,8 @@
...
@@ -6,6 +6,8 @@
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.VIBRATE"
/>
<uses-permission
android:name=
"android.permission.VIBRATE"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.CAMERA"
/>
<uses-permission
android:name=
"android.permission.RECORD_AUDIO"
/>
<application
<application
android:name=
".app.RocketChatApplication"
android:name=
".app.RocketChatApplication"
...
@@ -73,6 +75,11 @@
...
@@ -73,6 +75,11 @@
android:theme=
"@style/AppTheme"
android:theme=
"@style/AppTheme"
android:windowSoftInputMode=
"adjustResize|stateAlwaysHidden"
/>
android:windowSoftInputMode=
"adjustResize|stateAlwaysHidden"
/>
<activity
android:name=
".videoconferencing.ui.VideoConferencingActivity"
android:theme=
"@style/AppTheme"
android:windowSoftInputMode=
"adjustResize|stateAlwaysHidden"
/>
<activity
<activity
android:name=
".chatroom.ui.ChatRoomActivity"
android:name=
".chatroom.ui.ChatRoomActivity"
android:theme=
"@style/AppTheme"
android:theme=
"@style/AppTheme"
...
...
app/src/main/java/chat/rocket/android/app/AppLifecycleObserver.kt
View file @
f4a743d4
...
@@ -3,15 +3,11 @@ package chat.rocket.android.app
...
@@ -3,15 +3,11 @@ package chat.rocket.android.app
import
androidx.lifecycle.Lifecycle
import
androidx.lifecycle.Lifecycle
import
androidx.lifecycle.LifecycleObserver
import
androidx.lifecycle.LifecycleObserver
import
androidx.lifecycle.OnLifecycleEvent
import
androidx.lifecycle.OnLifecycleEvent
import
chat.rocket.android.server.domain.GetAccountInteractor
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import
chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.model.UserStatus
import
chat.rocket.common.model.UserStatus
import
chat.rocket.core.internal.realtime.setTemporaryStatus
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.launch
import
timber.log.Timber
import
javax.inject.Inject
import
javax.inject.Inject
class
AppLifecycleObserver
@Inject
constructor
(
class
AppLifecycleObserver
@Inject
constructor
(
...
@@ -33,7 +29,7 @@ class AppLifecycleObserver @Inject constructor(
...
@@ -33,7 +29,7 @@ class AppLifecycleObserver @Inject constructor(
}
}
private
fun
changeTemporaryStatus
(
userStatus
:
UserStatus
)
{
private
fun
changeTemporaryStatus
(
userStatus
:
UserStatus
)
{
launch
{
GlobalScope
.
launch
{
serverInteractor
.
get
()
?.
let
{
currentServer
->
serverInteractor
.
get
()
?.
let
{
currentServer
->
factory
.
create
(
currentServer
).
setTemporaryStatus
(
userStatus
)
factory
.
create
(
currentServer
).
setTemporaryStatus
(
userStatus
)
}
}
...
...
app/src/main/java/chat/rocket/android/app/RocketChatApplication.kt
View file @
f4a743d4
...
@@ -37,7 +37,8 @@ import dagger.android.DispatchingAndroidInjector
...
@@ -37,7 +37,8 @@ import dagger.android.DispatchingAndroidInjector
import
dagger.android.HasActivityInjector
import
dagger.android.HasActivityInjector
import
dagger.android.HasBroadcastReceiverInjector
import
dagger.android.HasBroadcastReceiverInjector
import
dagger.android.HasServiceInjector
import
dagger.android.HasServiceInjector
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
timber.log.Timber
import
timber.log.Timber
import
java.lang.ref.WeakReference
import
java.lang.ref.WeakReference
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -174,7 +175,7 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
...
@@ -174,7 +175,7 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
EmojiRepository
.
init
(
this
)
EmojiRepository
.
init
(
this
)
val
currentServer
=
getCurrentServerInteractor
.
get
()
val
currentServer
=
getCurrentServerInteractor
.
get
()
currentServer
?.
let
{
server
->
currentServer
?.
let
{
server
->
launch
{
GlobalScope
.
launch
{
val
client
=
factory
.
create
(
server
)
val
client
=
factory
.
create
(
server
)
EmojiRepository
.
setCurrentServerUrl
(
server
)
EmojiRepository
.
setCurrentServerUrl
(
server
)
val
customEmojiList
=
mutableListOf
<
Emoji
>()
val
customEmojiList
=
mutableListOf
<
Emoji
>()
...
...
app/src/main/java/chat/rocket/android/authentication/di/AuthenticationModule.kt
View file @
f4a743d4
...
@@ -7,7 +7,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
...
@@ -7,7 +7,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.dagger.scope.PerActivity
import
chat.rocket.android.dagger.scope.PerActivity
import
dagger.Module
import
dagger.Module
import
dagger.Provides
import
dagger.Provides
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
@Module
@Module
class
AuthenticationModule
{
class
AuthenticationModule
{
...
...
app/src/main/java/chat/rocket/android/authentication/loginoptions/presentation/LoginOptionsPresenter.kt
View file @
f4a743d4
...
@@ -31,7 +31,7 @@ import chat.rocket.core.internal.rest.loginWithCas
...
@@ -31,7 +31,7 @@ import chat.rocket.core.internal.rest.loginWithCas
import
chat.rocket.core.internal.rest.loginWithOauth
import
chat.rocket.core.internal.rest.loginWithOauth
import
chat.rocket.core.internal.rest.loginWithSaml
import
chat.rocket.core.internal.rest.loginWithSaml
import
chat.rocket.core.internal.rest.me
import
chat.rocket.core.internal.rest.me
import
kotlinx.coroutines.
experimental.
delay
import
kotlinx.coroutines.delay
import
java.util.concurrent.TimeUnit
import
java.util.concurrent.TimeUnit
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -109,11 +109,11 @@ class LoginOptionsPresenter @Inject constructor(
...
@@ -109,11 +109,11 @@ class LoginOptionsPresenter @Inject constructor(
when
(
loginType
)
{
when
(
loginType
)
{
TYPE_LOGIN_OAUTH
->
client
.
loginWithOauth
(
credentialToken
,
credentialSecret
)
TYPE_LOGIN_OAUTH
->
client
.
loginWithOauth
(
credentialToken
,
credentialSecret
)
TYPE_LOGIN_CAS
->
{
TYPE_LOGIN_CAS
->
{
delay
(
3
,
TimeUnit
.
SECONDS
)
delay
(
3
000
)
client
.
loginWithCas
(
credentialToken
)
client
.
loginWithCas
(
credentialToken
)
}
}
TYPE_LOGIN_SAML
->
{
TYPE_LOGIN_SAML
->
{
delay
(
3
,
TimeUnit
.
SECONDS
)
delay
(
3
000
)
client
.
loginWithSaml
(
credentialToken
)
client
.
loginWithSaml
(
credentialToken
)
}
}
TYPE_LOGIN_DEEP_LINK
->
{
TYPE_LOGIN_DEEP_LINK
->
{
...
...
app/src/main/java/chat/rocket/android/authentication/onboarding/presentation/OnBoardingPresenter.kt
View file @
f4a743d4
...
@@ -10,8 +10,8 @@ import chat.rocket.android.server.domain.SaveConnectingServerInteractor
...
@@ -10,8 +10,8 @@ import chat.rocket.android.server.domain.SaveConnectingServerInteractor
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.presentation.CheckServerPresenter
import
chat.rocket.android.server.presentation.CheckServerPresenter
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.extension.launchUI
import
kotlinx.coroutines.
experimental.DefaultDispatcher
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
import
javax.inject.Inject
import
javax.inject.Inject
class
OnBoardingPresenter
@Inject
constructor
(
class
OnBoardingPresenter
@Inject
constructor
(
...
@@ -19,7 +19,7 @@ class OnBoardingPresenter @Inject constructor(
...
@@ -19,7 +19,7 @@ class OnBoardingPresenter @Inject constructor(
private
val
strategy
:
CancelStrategy
,
private
val
strategy
:
CancelStrategy
,
private
val
navigator
:
AuthenticationNavigator
,
private
val
navigator
:
AuthenticationNavigator
,
private
val
serverInteractor
:
SaveConnectingServerInteractor
,
private
val
serverInteractor
:
SaveConnectingServerInteractor
,
private
val
refreshSettingsInteractor
:
RefreshSettingsInteractor
,
refreshSettingsInteractor
:
RefreshSettingsInteractor
,
private
val
getAccountsInteractor
:
GetAccountsInteractor
,
private
val
getAccountsInteractor
:
GetAccountsInteractor
,
val
settingsInteractor
:
GetSettingsInteractor
,
val
settingsInteractor
:
GetSettingsInteractor
,
val
factory
:
RocketChatClientFactory
val
factory
:
RocketChatClientFactory
...
@@ -80,7 +80,7 @@ class OnBoardingPresenter @Inject constructor(
...
@@ -80,7 +80,7 @@ class OnBoardingPresenter @Inject constructor(
}
}
view
.
showLoading
()
view
.
showLoading
()
try
{
try
{
withContext
(
D
efaultDispatcher
)
{
withContext
(
D
ispatchers
.
Default
)
{
setupConnectionInfo
(
serverUrl
)
setupConnectionInfo
(
serverUrl
)
// preparing next fragment before showing it
// preparing next fragment before showing it
...
...
app/src/main/java/chat/rocket/android/authentication/server/presentation/ServerPresenter.kt
View file @
f4a743d4
...
@@ -12,8 +12,8 @@ import chat.rocket.android.server.infraestructure.RocketChatClientFactory
...
@@ -12,8 +12,8 @@ import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.presentation.CheckServerPresenter
import
chat.rocket.android.server.presentation.CheckServerPresenter
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.extensions.isValidUrl
import
chat.rocket.android.util.extensions.isValidUrl
import
kotlinx.coroutines.
experimental.DefaultDispatcher
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
import
javax.inject.Inject
import
javax.inject.Inject
class
ServerPresenter
@Inject
constructor
(
class
ServerPresenter
@Inject
constructor
(
...
@@ -98,7 +98,7 @@ class ServerPresenter @Inject constructor(
...
@@ -98,7 +98,7 @@ class ServerPresenter @Inject constructor(
}
}
view
.
showLoading
()
view
.
showLoading
()
try
{
try
{
withContext
(
D
efaultDispatcher
)
{
withContext
(
D
ispatchers
.
Default
)
{
// preparing next fragment before showing it
// preparing next fragment before showing it
refreshServerAccounts
()
refreshServerAccounts
()
checkEnabledAccounts
(
serverUrl
)
checkEnabledAccounts
(
serverUrl
)
...
...
app/src/main/java/chat/rocket/android/chatdetails/ui/ChatDetailsFragment.kt
View file @
f4a743d4
...
@@ -21,7 +21,6 @@ import chat.rocket.android.chatdetails.viewmodel.ChatDetailsViewModelFactory
...
@@ -21,7 +21,6 @@ import chat.rocket.android.chatdetails.viewmodel.ChatDetailsViewModelFactory
import
chat.rocket.android.chatroom.ui.ChatRoomActivity
import
chat.rocket.android.chatroom.ui.ChatRoomActivity
import
chat.rocket.android.server.domain.CurrentServerRepository
import
chat.rocket.android.server.domain.CurrentServerRepository
import
chat.rocket.android.server.domain.GetSettingsInteractor
import
chat.rocket.android.server.domain.GetSettingsInteractor
import
chat.rocket.android.server.domain.PublicSettings
import
chat.rocket.android.util.extensions.inflate
import
chat.rocket.android.util.extensions.inflate
import
chat.rocket.android.util.extensions.showToast
import
chat.rocket.android.util.extensions.showToast
import
chat.rocket.android.util.extensions.ui
import
chat.rocket.android.util.extensions.ui
...
...
app/src/main/java/chat/rocket/android/chatdetails/ui/Menu.kt
View file @
f4a743d4
...
@@ -5,6 +5,7 @@ import android.view.MenuItem
...
@@ -5,6 +5,7 @@ import android.view.MenuItem
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.server.domain.isJitsiEnabled
import
chat.rocket.android.server.domain.isJitsiEnabled
import
chat.rocket.android.server.domain.isJitsiEnabledForChannels
import
chat.rocket.android.server.domain.isJitsiEnabledForChannels
import
chat.rocket.android.videoconferencing.ui.videoConferencingIntent
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.model.roomTypeOf
...
@@ -38,7 +39,8 @@ internal fun ChatDetailsFragment.setupMenu(menu: Menu) {
...
@@ -38,7 +39,8 @@ internal fun ChatDetailsFragment.setupMenu(menu: Menu) {
MENU_ACTION_FAVORITE_REMOVE_FAVORITE
,
MENU_ACTION_FAVORITE_REMOVE_FAVORITE
,
Menu
.
NONE
,
Menu
.
NONE
,
R
.
string
.
action_favorite
R
.
string
.
action_favorite
).
setIcon
(
R
.
drawable
.
ic_star_border_white_24dp
).
setShowAsAction
(
MenuItem
.
SHOW_AS_ACTION_IF_ROOM
)
).
setIcon
(
R
.
drawable
.
ic_star_border_white_24dp
)
.
setShowAsAction
(
MenuItem
.
SHOW_AS_ACTION_IF_ROOM
)
}
}
}
}
...
@@ -46,6 +48,6 @@ internal fun ChatDetailsFragment.setOnMenuItemClickListener(item: MenuItem) {
...
@@ -46,6 +48,6 @@ internal fun ChatDetailsFragment.setOnMenuItemClickListener(item: MenuItem) {
if
(
item
.
itemId
==
MENU_ACTION_FAVORITE_REMOVE_FAVORITE
)
{
if
(
item
.
itemId
==
MENU_ACTION_FAVORITE_REMOVE_FAVORITE
)
{
presenter
.
toggleFavoriteChatRoom
(
chatRoomId
,
isFavorite
)
presenter
.
toggleFavoriteChatRoom
(
chatRoomId
,
isFavorite
)
}
else
if
(
item
.
itemId
==
MENU_ACTION_VIDEO_CALL
)
{
}
else
if
(
item
.
itemId
==
MENU_ACTION_VIDEO_CALL
)
{
// TODO
startActivity
(
activity
?.
videoConferencingIntent
(
chatRoomId
))
}
}
}
}
app/src/main/java/chat/rocket/android/chatinformation/di/MessageInfoFragmentModule.kt
View file @
f4a743d4
...
@@ -7,7 +7,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
...
@@ -7,7 +7,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.dagger.scope.PerFragment
import
chat.rocket.android.dagger.scope.PerFragment
import
dagger.Module
import
dagger.Module
import
dagger.Provides
import
dagger.Provides
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
@Module
@Module
class
MessageInfoFragmentModule
{
class
MessageInfoFragmentModule
{
...
...
app/src/main/java/chat/rocket/android/chatinformation/ui/MessageInfoActivity.kt
View file @
f4a743d4
...
@@ -24,7 +24,6 @@ fun Context.messageInformationIntent(messageId: String): Intent {
...
@@ -24,7 +24,6 @@ fun Context.messageInformationIntent(messageId: String): Intent {
private
const
val
INTENT_MESSAGE_ID
=
"message_id"
private
const
val
INTENT_MESSAGE_ID
=
"message_id"
class
MessageInfoActivity
:
AppCompatActivity
(),
HasSupportFragmentInjector
{
class
MessageInfoActivity
:
AppCompatActivity
(),
HasSupportFragmentInjector
{
@Inject
@Inject
lateinit
var
fragmentDispatchingAndroidInjector
:
DispatchingAndroidInjector
<
Fragment
>
lateinit
var
fragmentDispatchingAndroidInjector
:
DispatchingAndroidInjector
<
Fragment
>
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
View file @
f4a743d4
...
@@ -6,12 +6,7 @@ import android.view.ViewGroup
...
@@ -6,12 +6,7 @@ import android.view.ViewGroup
import
androidx.recyclerview.widget.RecyclerView
import
androidx.recyclerview.widget.RecyclerView
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.presentation.ChatRoomNavigator
import
chat.rocket.android.chatroom.presentation.ChatRoomNavigator
import
chat.rocket.android.chatroom.uimodel.AttachmentUiModel
import
chat.rocket.android.chatroom.uimodel.*
import
chat.rocket.android.chatroom.uimodel.BaseUiModel
import
chat.rocket.android.chatroom.uimodel.MessageReplyUiModel
import
chat.rocket.android.chatroom.uimodel.MessageUiModel
import
chat.rocket.android.chatroom.uimodel.UrlPreviewUiModel
import
chat.rocket.android.chatroom.uimodel.toViewType
import
chat.rocket.android.emoji.EmojiReactionListener
import
chat.rocket.android.emoji.EmojiReactionListener
import
chat.rocket.android.util.extensions.inflate
import
chat.rocket.android.util.extensions.inflate
import
chat.rocket.android.util.extensions.openTabbedUrl
import
chat.rocket.android.util.extensions.openTabbedUrl
...
@@ -44,8 +39,10 @@ class ChatRoomAdapter(
...
@@ -44,8 +39,10 @@ class ChatRoomAdapter(
MessageViewHolder
(
MessageViewHolder
(
view
,
view
,
actionsListener
,
actionsListener
,
reactionListener
reactionListener
,
)
{
userId
->
navigator
?.
toUserDetails
(
userId
)
}
{
userId
->
navigator
?.
toUserDetails
(
userId
)
},
{
roomId
?.
let
{
navigator
?.
toVideoConferencing
(
it
)
}
}
)
}
}
BaseUiModel
.
ViewType
.
URL_PREVIEW
->
{
BaseUiModel
.
ViewType
.
URL_PREVIEW
->
{
val
view
=
parent
.
inflate
(
R
.
layout
.
message_url_preview
)
val
view
=
parent
.
inflate
(
R
.
layout
.
message_url_preview
)
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/MessageReactionsAdapter.kt
View file @
f4a743d4
...
@@ -13,8 +13,8 @@ import chat.rocket.android.emoji.Emoji
...
@@ -13,8 +13,8 @@ import chat.rocket.android.emoji.Emoji
import
chat.rocket.android.emoji.EmojiKeyboardListener
import
chat.rocket.android.emoji.EmojiKeyboardListener
import
chat.rocket.android.emoji.EmojiPickerPopup
import
chat.rocket.android.emoji.EmojiPickerPopup
import
chat.rocket.android.emoji.EmojiReactionListener
import
chat.rocket.android.emoji.EmojiReactionListener
import
chat.rocket.android.emoji.internal.GlideApp
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.infrastructure.LocalRepository
import
com.bumptech.glide.Glide
import
kotlinx.android.synthetic.main.item_reaction.view.*
import
kotlinx.android.synthetic.main.item_reaction.view.*
import
java.util.concurrent.CopyOnWriteArrayList
import
java.util.concurrent.CopyOnWriteArrayList
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -103,9 +103,9 @@ class MessageReactionsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>()
...
@@ -103,9 +103,9 @@ class MessageReactionsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>()
// The view at index 1 corresponds to the one to display custom emojis which are images.
// The view at index 1 corresponds to the one to display custom emojis which are images.
view_flipper_reaction
.
displayedChild
=
1
view_flipper_reaction
.
displayedChild
=
1
val
glideRequest
=
if
(
reaction
.
url
!!
.
endsWith
(
"gif"
,
true
))
{
val
glideRequest
=
if
(
reaction
.
url
!!
.
endsWith
(
"gif"
,
true
))
{
Glide
App
.
with
(
context
).
asGif
()
Glide
.
with
(
context
).
asGif
()
}
else
{
}
else
{
Glide
App
.
with
(
context
).
asBitmap
()
Glide
.
with
(
context
).
asBitmap
()
}
}
glideRequest
.
load
(
reaction
.
url
).
into
(
image_emoji
)
glideRequest
.
load
(
reaction
.
url
).
into
(
image_emoji
)
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/MessageViewHolder.kt
View file @
f4a743d4
...
@@ -10,6 +10,7 @@ import androidx.core.view.isVisible
...
@@ -10,6 +10,7 @@ import androidx.core.view.isVisible
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.uimodel.MessageUiModel
import
chat.rocket.android.chatroom.uimodel.MessageUiModel
import
chat.rocket.android.emoji.EmojiReactionListener
import
chat.rocket.android.emoji.EmojiReactionListener
import
chat.rocket.core.model.MessageType
import
chat.rocket.core.model.isSystemMessage
import
chat.rocket.core.model.isSystemMessage
import
com.bumptech.glide.load.resource.gif.GifDrawable
import
com.bumptech.glide.load.resource.gif.GifDrawable
import
kotlinx.android.synthetic.main.avatar.view.*
import
kotlinx.android.synthetic.main.avatar.view.*
...
@@ -19,7 +20,8 @@ class MessageViewHolder(
...
@@ -19,7 +20,8 @@ class MessageViewHolder(
itemView
:
View
,
itemView
:
View
,
listener
:
ActionsListener
,
listener
:
ActionsListener
,
reactionListener
:
EmojiReactionListener
?
=
null
,
reactionListener
:
EmojiReactionListener
?
=
null
,
private
val
avatarListener
:
(
String
)
->
Unit
private
val
avatarListener
:
(
String
)
->
Unit
,
private
val
joinVideoCallListener
:
(
View
)
->
Unit
)
:
BaseViewHolder
<
MessageUiModel
>(
itemView
,
listener
,
reactionListener
),
Drawable
.
Callback
{
)
:
BaseViewHolder
<
MessageUiModel
>(
itemView
,
listener
,
reactionListener
),
Drawable
.
Callback
{
init
{
init
{
...
@@ -51,6 +53,9 @@ class MessageViewHolder(
...
@@ -51,6 +53,9 @@ class MessageViewHolder(
text_content
.
text_content
.
text
=
data
.
content
text_content
.
text_content
.
text
=
data
.
content
button_join_video_call
.
isVisible
=
data
.
message
.
type
is
MessageType
.
JitsiCallStarted
button_join_video_call
.
setOnClickListener
{
joinVideoCallListener
(
it
)
}
image_avatar
.
setImageURI
(
data
.
avatar
)
image_avatar
.
setImageURI
(
data
.
avatar
)
text_content
.
setTextColor
(
if
(
data
.
isTemporary
)
Color
.
GRAY
else
Color
.
BLACK
)
text_content
.
setTextColor
(
if
(
data
.
isTemporary
)
Color
.
GRAY
else
Color
.
BLACK
)
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/UrlPreviewViewHolder.kt
View file @
f4a743d4
...
@@ -8,10 +8,11 @@ import chat.rocket.android.util.extensions.content
...
@@ -8,10 +8,11 @@ import chat.rocket.android.util.extensions.content
import
chat.rocket.android.util.extensions.openTabbedUrl
import
chat.rocket.android.util.extensions.openTabbedUrl
import
kotlinx.android.synthetic.main.message_url_preview.view.*
import
kotlinx.android.synthetic.main.message_url_preview.view.*
class
UrlPreviewViewHolder
(
itemView
:
View
,
class
UrlPreviewViewHolder
(
listener
:
ActionsListener
,
itemView
:
View
,
reactionListener
:
EmojiReactionListener
?
=
null
)
listener
:
ActionsListener
,
:
BaseViewHolder
<
UrlPreviewUiModel
>(
itemView
,
listener
,
reactionListener
)
{
reactionListener
:
EmojiReactionListener
?
=
null
)
:
BaseViewHolder
<
UrlPreviewUiModel
>(
itemView
,
listener
,
reactionListener
)
{
init
{
init
{
with
(
itemView
)
{
with
(
itemView
)
{
...
...
app/src/main/java/chat/rocket/android/chatroom/di/ChatRoomModule.kt
View file @
f4a743d4
...
@@ -7,7 +7,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
...
@@ -7,7 +7,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.dagger.scope.PerActivity
import
chat.rocket.android.dagger.scope.PerActivity
import
dagger.Module
import
dagger.Module
import
dagger.Provides
import
dagger.Provides
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
@Module
@Module
class
ChatRoomModule
{
class
ChatRoomModule
{
...
...
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomNavigator.kt
View file @
f4a743d4
...
@@ -13,6 +13,7 @@ import chat.rocket.android.pinnedmessages.ui.TAG_PINNED_MESSAGES_FRAGMENT
...
@@ -13,6 +13,7 @@ import chat.rocket.android.pinnedmessages.ui.TAG_PINNED_MESSAGES_FRAGMENT
import
chat.rocket.android.server.ui.changeServerIntent
import
chat.rocket.android.server.ui.changeServerIntent
import
chat.rocket.android.userdetails.ui.TAG_USER_DETAILS_FRAGMENT
import
chat.rocket.android.userdetails.ui.TAG_USER_DETAILS_FRAGMENT
import
chat.rocket.android.util.extensions.addFragmentBackStack
import
chat.rocket.android.util.extensions.addFragmentBackStack
import
chat.rocket.android.videoconferencing.ui.videoConferencingIntent
class
ChatRoomNavigator
(
internal
val
activity
:
ChatRoomActivity
)
{
class
ChatRoomNavigator
(
internal
val
activity
:
ChatRoomActivity
)
{
...
@@ -22,6 +23,10 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
...
@@ -22,6 +23,10 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
}
}
}
}
fun
toVideoConferencing
(
chatRoomId
:
String
)
{
activity
.
startActivity
(
activity
.
videoConferencingIntent
(
chatRoomId
))
}
fun
toChatRoom
(
fun
toChatRoom
(
chatRoomId
:
String
,
chatRoomId
:
String
,
chatRoomName
:
String
,
chatRoomName
:
String
,
...
...
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
View file @
f4a743d4
...
@@ -53,7 +53,6 @@ import chat.rocket.core.internal.realtime.unsubscribe
...
@@ -53,7 +53,6 @@ import chat.rocket.core.internal.realtime.unsubscribe
import
chat.rocket.core.internal.rest.chatRoomRoles
import
chat.rocket.core.internal.rest.chatRoomRoles
import
chat.rocket.core.internal.rest.commands
import
chat.rocket.core.internal.rest.commands
import
chat.rocket.core.internal.rest.deleteMessage
import
chat.rocket.core.internal.rest.deleteMessage
import
chat.rocket.core.internal.rest.favorite
import
chat.rocket.core.internal.rest.getMembers
import
chat.rocket.core.internal.rest.getMembers
import
chat.rocket.core.internal.rest.history
import
chat.rocket.core.internal.rest.history
import
chat.rocket.core.internal.rest.joinChat
import
chat.rocket.core.internal.rest.joinChat
...
@@ -76,12 +75,11 @@ import chat.rocket.core.model.ChatRoomRole
...
@@ -76,12 +75,11 @@ import chat.rocket.core.model.ChatRoomRole
import
chat.rocket.core.model.Command
import
chat.rocket.core.model.Command
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Room
import
chat.rocket.core.model.Room
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.DefaultDispatcher
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.channels.Channel
import
kotlinx.coroutines.experimental.channels.Channel
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.withContext
import
kotlinx.coroutines.experimental.withContext
import
org.threeten.bp.Instant
import
org.threeten.bp.Instant
import
timber.log.Timber
import
timber.log.Timber
import
java.util.*
import
java.util.*
...
@@ -134,7 +132,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -134,7 +132,7 @@ class ChatRoomPresenter @Inject constructor(
draftKey
=
"${currentServer}_${LocalRepository.DRAFT_KEY}$roomId"
draftKey
=
"${currentServer}_${LocalRepository.DRAFT_KEY}$roomId"
chatRoomId
=
roomId
chatRoomId
=
roomId
chatRoomType
=
roomType
chatRoomType
=
roomType
launch
(
CommonPool
+
strategy
.
jobs
)
{
GlobalScope
.
launch
(
Dispatchers
.
IO
+
strategy
.
jobs
)
{
try
{
try
{
chatRoles
=
if
(
roomTypeOf
(
roomType
)
!
is
RoomType
.
DirectMessage
)
{
chatRoles
=
if
(
roomTypeOf
(
roomType
)
!
is
RoomType
.
DirectMessage
)
{
client
.
chatRoomRoles
(
roomType
=
roomTypeOf
(
roomType
),
roomName
=
roomName
)
client
.
chatRoomRoles
(
roomType
=
roomTypeOf
(
roomType
),
roomName
=
roomName
)
...
@@ -178,7 +176,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -178,7 +176,7 @@ class ChatRoomPresenter @Inject constructor(
}
}
private
suspend
fun
subscribeRoomChanges
()
{
private
suspend
fun
subscribeRoomChanges
()
{
withContext
(
CommonPool
+
strategy
.
jobs
)
{
withContext
(
Dispatchers
.
IO
+
strategy
.
jobs
)
{
chatRoomId
?.
let
{
chatRoomId
?.
let
{
manager
.
addRoomChannel
(
it
,
roomChangesChannel
)
manager
.
addRoomChannel
(
it
,
roomChangesChannel
)
for
(
room
in
roomChangesChannel
)
{
for
(
room
in
roomChangesChannel
)
{
...
@@ -403,7 +401,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -403,7 +401,7 @@ class ChatRoomPresenter @Inject constructor(
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
view
.
showLoading
()
view
.
showLoading
()
try
{
try
{
withContext
(
D
efaultDispatcher
)
{
withContext
(
D
ispatchers
.
Default
)
{
val
fileName
=
uriInteractor
.
getFileName
(
uri
)
?:
uri
.
toString
()
val
fileName
=
uriInteractor
.
getFileName
(
uri
)
?:
uri
.
toString
()
if
(
fileName
.
isEmpty
())
{
if
(
fileName
.
isEmpty
())
{
view
.
showInvalidFileMessage
()
view
.
showInvalidFileMessage
()
...
@@ -441,7 +439,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -441,7 +439,7 @@ class ChatRoomPresenter @Inject constructor(
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
view
.
showLoading
()
view
.
showLoading
()
try
{
try
{
withContext
(
D
efaultDispatcher
)
{
withContext
(
D
ispatchers
.
Default
)
{
val
fileName
=
uriInteractor
.
getFileName
(
uri
)
?:
uri
.
toString
()
val
fileName
=
uriInteractor
.
getFileName
(
uri
)
?:
uri
.
toString
()
val
fileSize
=
uriInteractor
.
getFileSize
(
uri
)
val
fileSize
=
uriInteractor
.
getFileSize
(
uri
)
val
maxFileSizeAllowed
=
settings
.
uploadMaxFileSize
()
val
maxFileSizeAllowed
=
settings
.
uploadMaxFileSize
()
...
@@ -482,7 +480,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -482,7 +480,7 @@ class ChatRoomPresenter @Inject constructor(
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
view
.
showLoading
()
view
.
showLoading
()
try
{
try
{
withContext
(
D
efaultDispatcher
)
{
withContext
(
D
ispatchers
.
Default
)
{
val
fileName
=
UUID
.
randomUUID
().
toString
()
+
".png"
val
fileName
=
UUID
.
randomUUID
().
toString
()
+
".png"
val
fileSize
=
byteArray
.
size
val
fileSize
=
byteArray
.
size
val
mimeType
=
"image/png"
val
mimeType
=
"image/png"
...
@@ -520,7 +518,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -520,7 +518,7 @@ class ChatRoomPresenter @Inject constructor(
}
}
fun
sendTyping
()
{
fun
sendTyping
()
{
launch
(
CommonPool
+
strategy
.
jobs
)
{
GlobalScope
.
launch
(
Dispatchers
.
IO
+
strategy
.
jobs
)
{
if
(
chatRoomId
!=
null
&&
currentLoggedUsername
!=
null
)
{
if
(
chatRoomId
!=
null
&&
currentLoggedUsername
!=
null
)
{
client
.
setTypingStatus
(
chatRoomId
.
toString
(),
currentLoggedUsername
,
true
)
client
.
setTypingStatus
(
chatRoomId
.
toString
(),
currentLoggedUsername
,
true
)
}
}
...
@@ -528,7 +526,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -528,7 +526,7 @@ class ChatRoomPresenter @Inject constructor(
}
}
fun
sendNotTyping
()
{
fun
sendNotTyping
()
{
launch
(
CommonPool
+
strategy
.
jobs
)
{
GlobalScope
.
launch
(
Dispatchers
.
IO
+
strategy
.
jobs
)
{
if
(
chatRoomId
!=
null
&&
currentLoggedUsername
!=
null
)
{
if
(
chatRoomId
!=
null
&&
currentLoggedUsername
!=
null
)
{
client
.
setTypingStatus
(
chatRoomId
.
toString
(),
currentLoggedUsername
,
false
)
client
.
setTypingStatus
(
chatRoomId
.
toString
(),
currentLoggedUsername
,
false
)
}
}
...
@@ -550,11 +548,11 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -550,11 +548,11 @@ class ChatRoomPresenter @Inject constructor(
Timber
.
d
(
"Subscribing to Status changes"
)
Timber
.
d
(
"Subscribing to Status changes"
)
lastState
=
manager
.
state
lastState
=
manager
.
state
manager
.
addStatusChannel
(
stateChannel
)
manager
.
addStatusChannel
(
stateChannel
)
launch
(
CommonPool
+
strategy
.
jobs
)
{
GlobalScope
.
launch
(
Dispatchers
.
IO
+
strategy
.
jobs
)
{
for
(
state
in
stateChannel
)
{
for
(
state
in
stateChannel
)
{
Timber
.
d
(
"Got new state: $state - last: $lastState"
)
Timber
.
d
(
"Got new state: $state - last: $lastState"
)
if
(
state
!=
lastState
)
{
if
(
state
!=
lastState
)
{
launch
(
UI
)
{
launch
(
Dispatchers
.
Main
)
{
view
.
showConnectionState
(
state
)
view
.
showConnectionState
(
state
)
}
}
...
@@ -571,7 +569,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -571,7 +569,7 @@ class ChatRoomPresenter @Inject constructor(
private
fun
subscribeMessages
(
roomId
:
String
)
{
private
fun
subscribeMessages
(
roomId
:
String
)
{
manager
.
subscribeRoomMessages
(
roomId
,
messagesChannel
)
manager
.
subscribeRoomMessages
(
roomId
,
messagesChannel
)
launch
(
CommonPool
+
strategy
.
jobs
)
{
GlobalScope
.
launch
(
Dispatchers
.
IO
+
strategy
.
jobs
)
{
for
(
message
in
messagesChannel
)
{
for
(
message
in
messagesChannel
)
{
Timber
.
d
(
"New message for room ${message.roomId}"
)
Timber
.
d
(
"New message for room ${message.roomId}"
)
updateMessage
(
message
)
updateMessage
(
message
)
...
@@ -580,7 +578,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -580,7 +578,7 @@ class ChatRoomPresenter @Inject constructor(
}
}
private
fun
loadMissingMessages
()
{
private
fun
loadMissingMessages
()
{
launch
(
parent
=
strategy
.
jobs
)
{
GlobalScope
.
launch
(
strategy
.
jobs
)
{
chatRoomId
?.
let
{
chatRoomId
->
chatRoomId
?.
let
{
chatRoomId
->
val
roomType
=
roomTypeOf
(
chatRoomType
)
val
roomType
=
roomTypeOf
(
chatRoomType
)
val
lastSyncDate
=
messagesRepository
.
getLastSyncDate
(
chatRoomId
)
val
lastSyncDate
=
messagesRepository
.
getLastSyncDate
(
chatRoomId
)
...
@@ -924,7 +922,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -924,7 +922,7 @@ class ChatRoomPresenter @Inject constructor(
}
}
// TODO: move this to new interactor or FetchChatRoomsInteractor?
// TODO: move this to new interactor or FetchChatRoomsInteractor?
private
suspend
fun
getChatRoomAsync
(
roomId
:
String
):
ChatRoom
?
=
withContext
(
CommonPool
)
{
private
suspend
fun
getChatRoomAsync
(
roomId
:
String
):
ChatRoom
?
=
withContext
(
Dispatchers
.
IO
)
{
retryDB
(
"getRoom($roomId)"
)
{
retryDB
(
"getRoom($roomId)"
)
{
dbManager
.
chatRoomDao
().
getSync
(
roomId
)
?.
let
{
dbManager
.
chatRoomDao
().
getSync
(
roomId
)
?.
let
{
with
(
it
.
chatRoom
)
{
with
(
it
.
chatRoom
)
{
...
@@ -962,7 +960,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -962,7 +960,7 @@ class ChatRoomPresenter @Inject constructor(
}
}
// TODO: move this to new interactor or FetchChatRoomsInteractor?
// TODO: move this to new interactor or FetchChatRoomsInteractor?
private
suspend
fun
getChatRoomsAsync
(
name
:
String
?
=
null
):
List
<
ChatRoom
>
=
withContext
(
CommonPool
)
{
private
suspend
fun
getChatRoomsAsync
(
name
:
String
?
=
null
):
List
<
ChatRoom
>
=
withContext
(
Dispatchers
.
IO
)
{
retryDB
(
"getAllSync()"
)
{
retryDB
(
"getAllSync()"
)
{
dbManager
.
chatRoomDao
().
getAllSync
().
filter
{
dbManager
.
chatRoomDao
().
getAllSync
().
filter
{
if
(
name
==
null
)
{
if
(
name
==
null
)
{
...
@@ -1192,7 +1190,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -1192,7 +1190,7 @@ class ChatRoomPresenter @Inject constructor(
}
}
private
fun
subscribeTypingStatus
()
{
private
fun
subscribeTypingStatus
()
{
launch
(
CommonPool
+
strategy
.
jobs
)
{
GlobalScope
.
launch
(
Dispatchers
.
IO
+
strategy
.
jobs
)
{
client
.
subscribeTypingStatus
(
chatRoomId
.
toString
())
{
_
,
id
->
client
.
subscribeTypingStatus
(
chatRoomId
.
toString
())
{
_
,
id
->
typingStatusSubscriptionId
=
id
typingStatusSubscriptionId
=
id
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/service/MessageService.kt
View file @
f4a743d4
...
@@ -10,8 +10,9 @@ import chat.rocket.android.server.infraestructure.DatabaseMessagesRepository
...
@@ -10,8 +10,9 @@ import chat.rocket.android.server.infraestructure.DatabaseMessagesRepository
import
chat.rocket.core.internal.rest.sendMessage
import
chat.rocket.core.internal.rest.sendMessage
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Message
import
dagger.android.AndroidInjection
import
dagger.android.AndroidInjection
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
timber.log.Timber
import
timber.log.Timber
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -33,7 +34,7 @@ class MessageService : JobService() {
...
@@ -33,7 +34,7 @@ class MessageService : JobService() {
}
}
override
fun
onStartJob
(
params
:
JobParameters
?):
Boolean
{
override
fun
onStartJob
(
params
:
JobParameters
?):
Boolean
{
launch
(
CommonPool
)
{
GlobalScope
.
launch
(
Dispatchers
.
IO
)
{
getAccountsInteractor
.
get
().
forEach
{
account
->
getAccountsInteractor
.
get
().
forEach
{
account
->
retrySendingMessages
(
params
,
account
.
serverUrl
)
retrySendingMessages
(
params
,
account
.
serverUrl
)
}
}
...
@@ -44,7 +45,8 @@ class MessageService : JobService() {
...
@@ -44,7 +45,8 @@ class MessageService : JobService() {
private
suspend
fun
retrySendingMessages
(
params
:
JobParameters
?,
serverUrl
:
String
)
{
private
suspend
fun
retrySendingMessages
(
params
:
JobParameters
?,
serverUrl
:
String
)
{
val
dbManager
=
dbFactory
.
create
(
serverUrl
)
val
dbManager
=
dbFactory
.
create
(
serverUrl
)
val
messageRepository
=
DatabaseMessagesRepository
(
dbManager
,
DatabaseMessageMapper
(
dbManager
))
val
messageRepository
=
DatabaseMessagesRepository
(
dbManager
,
DatabaseMessageMapper
(
dbManager
))
val
temporaryMessages
=
messageRepository
.
getAllUnsent
()
val
temporaryMessages
=
messageRepository
.
getAllUnsent
()
.
sortedWith
(
compareBy
(
Message
::
timestamp
))
.
sortedWith
(
compareBy
(
Message
::
timestamp
))
if
(
temporaryMessages
.
isNotEmpty
())
{
if
(
temporaryMessages
.
isNotEmpty
())
{
...
...
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
View file @
f4a743d4
...
@@ -15,7 +15,6 @@ import android.text.SpannableStringBuilder
...
@@ -15,7 +15,6 @@ import android.text.SpannableStringBuilder
import
android.view.KeyEvent
import
android.view.KeyEvent
import
android.view.LayoutInflater
import
android.view.LayoutInflater
import
android.view.Menu
import
android.view.Menu
import
android.view.MenuItem
import
android.view.View
import
android.view.View
import
android.view.ViewGroup
import
android.view.ViewGroup
import
android.widget.EditText
import
android.widget.EditText
...
@@ -60,7 +59,6 @@ import chat.rocket.android.emoji.EmojiKeyboardPopup
...
@@ -60,7 +59,6 @@ import chat.rocket.android.emoji.EmojiKeyboardPopup
import
chat.rocket.android.emoji.EmojiParser
import
chat.rocket.android.emoji.EmojiParser
import
chat.rocket.android.emoji.EmojiPickerPopup
import
chat.rocket.android.emoji.EmojiPickerPopup
import
chat.rocket.android.emoji.EmojiReactionListener
import
chat.rocket.android.emoji.EmojiReactionListener
import
chat.rocket.android.emoji.internal.GlideApp
import
chat.rocket.android.emoji.internal.isCustom
import
chat.rocket.android.emoji.internal.isCustom
import
chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import
chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import
chat.rocket.android.helper.ImageHelper
import
chat.rocket.android.helper.ImageHelper
...
@@ -82,6 +80,7 @@ import chat.rocket.android.util.extensions.ui
...
@@ -82,6 +80,7 @@ import chat.rocket.android.util.extensions.ui
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.core.internal.realtime.socket.model.State
import
chat.rocket.core.internal.realtime.socket.model.State
import
com.bumptech.glide.Glide
import
dagger.android.support.AndroidSupportInjection
import
dagger.android.support.AndroidSupportInjection
import
io.reactivex.Observable
import
io.reactivex.Observable
import
io.reactivex.disposables.CompositeDisposable
import
io.reactivex.disposables.CompositeDisposable
...
@@ -679,9 +678,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -679,9 +678,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
view_flipper
.
displayedChild
=
if
(
isCustom
)
1
else
0
view_flipper
.
displayedChild
=
if
(
isCustom
)
1
else
0
if
(
isCustom
&&
url
!=
null
)
{
if
(
isCustom
&&
url
!=
null
)
{
val
glideRequest
=
if
(
url
.
endsWith
(
"gif"
,
true
))
{
val
glideRequest
=
if
(
url
.
endsWith
(
"gif"
,
true
))
{
Glide
App
.
with
(
requireContext
()).
asGif
()
Glide
.
with
(
requireContext
()).
asGif
()
}
else
{
}
else
{
Glide
App
.
with
(
requireContext
()).
asBitmap
()
Glide
.
with
(
requireContext
()).
asBitmap
()
}
}
glideRequest
.
load
(
url
).
into
(
view_flipper
.
emoji_image_view
)
glideRequest
.
load
(
url
).
into
(
view_flipper
.
emoji_image_view
)
...
...
app/src/main/java/chat/rocket/android/chatroom/ui/Dialog.kt
View file @
f4a743d4
...
@@ -4,10 +4,11 @@ import android.graphics.Bitmap
...
@@ -4,10 +4,11 @@ import android.graphics.Bitmap
import
android.graphics.drawable.Drawable
import
android.graphics.drawable.Drawable
import
android.net.Uri
import
android.net.Uri
import
androidx.core.view.isVisible
import
androidx.core.view.isVisible
import
chat.rocket.android.emoji.internal.GlideApp
import
chat.rocket.android.util.extensions.getFileName
import
chat.rocket.android.util.extensions.getFileName
import
chat.rocket.android.util.extensions.getMimeType
import
chat.rocket.android.util.extensions.getMimeType
import
chat.rocket.common.util.ifNull
import
chat.rocket.common.util.ifNull
import
com.bumptech.glide.Glide
import
com.bumptech.glide.request.RequestOptions
import
com.bumptech.glide.request.target.SimpleTarget
import
com.bumptech.glide.request.target.SimpleTarget
import
com.bumptech.glide.request.transition.Transition
import
com.bumptech.glide.request.transition.Transition
...
@@ -25,18 +26,18 @@ fun ChatRoomFragment.showFileAttachmentDialog(uri: Uri) {
...
@@ -25,18 +26,18 @@ fun ChatRoomFragment.showFileAttachmentDialog(uri: Uri) {
when
{
when
{
mimeType
.
startsWith
(
"image"
)
->
{
mimeType
.
startsWith
(
"image"
)
->
{
if
(
mimeType
.
contains
(
"gif"
))
{
if
(
mimeType
.
contains
(
"gif"
))
{
Glide
App
Glide
.
with
(
context
)
.
with
(
context
)
.
asGif
()
.
asGif
()
.
load
(
uri
)
.
load
(
uri
)
.
fitCenter
(
)
.
apply
(
RequestOptions
().
fitCenter
()
)
.
into
(
imagePreview
)
.
into
(
imagePreview
)
}
else
{
}
else
{
Glide
App
Glide
.
with
(
context
)
.
with
(
context
)
.
asBitmap
()
.
asBitmap
()
.
load
(
uri
)
.
load
(
uri
)
.
fitCenter
(
)
.
apply
(
RequestOptions
().
fitCenter
()
)
.
into
(
object
:
SimpleTarget
<
Bitmap
>()
{
.
into
(
object
:
SimpleTarget
<
Bitmap
>()
{
override
fun
onResourceReady
(
override
fun
onResourceReady
(
resource
:
Bitmap
,
resource
:
Bitmap
,
...
...
app/src/main/java/chat/rocket/android/chatroom/uimodel/BaseUiModel.kt
View file @
f4a743d4
...
@@ -30,5 +30,5 @@ interface BaseUiModel<out T> {
...
@@ -30,5 +30,5 @@ interface BaseUiModel<out T> {
internal
fun
Int
.
toViewType
():
BaseUiModel
.
ViewType
{
internal
fun
Int
.
toViewType
():
BaseUiModel
.
ViewType
{
return
BaseUiModel
.
ViewType
.
values
().
firstOrNull
{
it
.
viewType
==
this
}
return
BaseUiModel
.
ViewType
.
values
().
firstOrNull
{
it
.
viewType
==
this
}
?:
throw
InvalidParameterException
(
"Invalid viewType: $this for BaseUiModel.ViewType"
)
?:
throw
InvalidParameterException
(
"Invalid viewType: $this for BaseUiModel.ViewType"
)
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/uimodel/MessageUiModel.kt
View file @
f4a743d4
...
@@ -26,7 +26,6 @@ data class MessageUiModel(
...
@@ -26,7 +26,6 @@ data class MessageUiModel(
)
:
BaseMessageUiModel
<
Message
>
{
)
:
BaseMessageUiModel
<
Message
>
{
override
val
viewType
:
Int
override
val
viewType
:
Int
get
()
=
BaseUiModel
.
ViewType
.
MESSAGE
.
viewType
get
()
=
BaseUiModel
.
ViewType
.
MESSAGE
.
viewType
override
val
layoutId
:
Int
override
val
layoutId
:
Int
get
()
=
R
.
layout
.
item_message
get
()
=
R
.
layout
.
item_message
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/uimodel/UiModelMapper.kt
View file @
f4a743d4
...
@@ -44,8 +44,8 @@ import chat.rocket.core.model.attachment.Attachment
...
@@ -44,8 +44,8 @@ import chat.rocket.core.model.attachment.Attachment
import
chat.rocket.core.model.attachment.Field
import
chat.rocket.core.model.attachment.Field
import
chat.rocket.core.model.isSystemMessage
import
chat.rocket.core.model.isSystemMessage
import
chat.rocket.core.model.url.Url
import
chat.rocket.core.model.url.Url
import
kotlinx.coroutines.
experimental.CommonPool
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
import
okhttp3.HttpUrl
import
okhttp3.HttpUrl
import
java.security.InvalidParameterException
import
java.security.InvalidParameterException
import
java.util.*
import
java.util.*
...
@@ -79,7 +79,7 @@ class UiModelMapper @Inject constructor(
...
@@ -79,7 +79,7 @@ class UiModelMapper @Inject constructor(
message
:
Message
,
message
:
Message
,
roomUiModel
:
RoomUiModel
=
RoomUiModel
(
roles
=
emptyList
(),
isBroadcast
=
true
)
roomUiModel
:
RoomUiModel
=
RoomUiModel
(
roles
=
emptyList
(),
isBroadcast
=
true
)
):
List
<
BaseUiModel
<*
>>
=
):
List
<
BaseUiModel
<*
>>
=
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
return
@withContext
translate
(
message
,
roomUiModel
)
return
@withContext
translate
(
message
,
roomUiModel
)
}
}
...
@@ -88,7 +88,7 @@ class UiModelMapper @Inject constructor(
...
@@ -88,7 +88,7 @@ class UiModelMapper @Inject constructor(
roomUiModel
:
RoomUiModel
=
RoomUiModel
(
roles
=
emptyList
(),
isBroadcast
=
true
),
roomUiModel
:
RoomUiModel
=
RoomUiModel
(
roles
=
emptyList
(),
isBroadcast
=
true
),
asNotReversed
:
Boolean
=
false
asNotReversed
:
Boolean
=
false
):
List
<
BaseUiModel
<*
>>
=
):
List
<
BaseUiModel
<*
>>
=
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
val
list
=
ArrayList
<
BaseUiModel
<*>>(
messages
.
size
)
val
list
=
ArrayList
<
BaseUiModel
<*>>(
messages
.
size
)
messages
.
forEach
{
messages
.
forEach
{
...
@@ -102,7 +102,7 @@ class UiModelMapper @Inject constructor(
...
@@ -102,7 +102,7 @@ class UiModelMapper @Inject constructor(
suspend
fun
map
(
suspend
fun
map
(
readReceipts
:
List
<
ReadReceipt
>
readReceipts
:
List
<
ReadReceipt
>
):
List
<
ReadReceiptViewModel
>
=
withContext
(
CommonPool
)
{
):
List
<
ReadReceiptViewModel
>
=
withContext
(
Dispatchers
.
IO
)
{
val
list
=
arrayListOf
<
ReadReceiptViewModel
>()
val
list
=
arrayListOf
<
ReadReceiptViewModel
>()
readReceipts
.
forEach
{
readReceipts
.
forEach
{
...
@@ -121,7 +121,7 @@ class UiModelMapper @Inject constructor(
...
@@ -121,7 +121,7 @@ class UiModelMapper @Inject constructor(
message
:
Message
,
message
:
Message
,
roomUiModel
:
RoomUiModel
roomUiModel
:
RoomUiModel
):
List
<
BaseUiModel
<*
>>
=
):
List
<
BaseUiModel
<*
>>
=
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
val
list
=
ArrayList
<
BaseUiModel
<*>>()
val
list
=
ArrayList
<
BaseUiModel
<*>>()
getChatRoomAsync
(
message
.
roomId
)
?.
let
{
chatRoom
->
getChatRoomAsync
(
message
.
roomId
)
?.
let
{
chatRoom
->
...
@@ -167,7 +167,7 @@ class UiModelMapper @Inject constructor(
...
@@ -167,7 +167,7 @@ class UiModelMapper @Inject constructor(
}
}
// TODO: move this to new interactor or FetchChatRoomsInteractor?
// TODO: move this to new interactor or FetchChatRoomsInteractor?
private
suspend
fun
getChatRoomAsync
(
roomId
:
String
):
ChatRoom
?
=
withContext
(
CommonPool
)
{
private
suspend
fun
getChatRoomAsync
(
roomId
:
String
):
ChatRoom
?
=
withContext
(
Dispatchers
.
IO
)
{
return
@withContext
dbManager
.
getRoom
(
id
=
roomId
)
?.
let
{
return
@withContext
dbManager
.
getRoom
(
id
=
roomId
)
?.
let
{
with
(
it
.
chatRoom
)
{
with
(
it
.
chatRoom
)
{
ChatRoom
(
ChatRoom
(
...
@@ -212,7 +212,7 @@ class UiModelMapper @Inject constructor(
...
@@ -212,7 +212,7 @@ class UiModelMapper @Inject constructor(
message
:
Message
,
message
:
Message
,
roomUiModel
:
RoomUiModel
roomUiModel
:
RoomUiModel
):
List
<
BaseUiModel
<*
>>
=
):
List
<
BaseUiModel
<*
>>
=
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
val
list
=
ArrayList
<
BaseUiModel
<*>>()
val
list
=
ArrayList
<
BaseUiModel
<*>>()
getChatRoomAsync
(
message
.
roomId
)
?.
let
{
chatRoom
->
getChatRoomAsync
(
message
.
roomId
)
?.
let
{
chatRoom
->
...
@@ -439,7 +439,7 @@ class UiModelMapper @Inject constructor(
...
@@ -439,7 +439,7 @@ class UiModelMapper @Inject constructor(
private
suspend
fun
mapMessage
(
private
suspend
fun
mapMessage
(
message
:
Message
,
message
:
Message
,
chatRoom
:
ChatRoom
chatRoom
:
ChatRoom
):
MessageUiModel
=
withContext
(
CommonPool
)
{
):
MessageUiModel
=
withContext
(
Dispatchers
.
IO
)
{
val
sender
=
getSenderName
(
message
)
val
sender
=
getSenderName
(
message
)
val
time
=
getTime
(
message
.
timestamp
)
val
time
=
getTime
(
message
.
timestamp
)
val
avatar
=
getUserAvatar
(
message
)
val
avatar
=
getUserAvatar
(
message
)
...
...
app/src/main/java/chat/rocket/android/chatrooms/presentation/ChatRoomsPresenter.kt
View file @
f4a743d4
...
@@ -22,11 +22,12 @@ import chat.rocket.common.model.roomTypeOf
...
@@ -22,11 +22,12 @@ import chat.rocket.common.model.roomTypeOf
import
chat.rocket.core.internal.realtime.createDirectMessage
import
chat.rocket.core.internal.realtime.createDirectMessage
import
chat.rocket.core.internal.rest.me
import
chat.rocket.core.internal.rest.me
import
chat.rocket.core.internal.rest.show
import
chat.rocket.core.internal.rest.show
import
kotlinx.coroutines.
experimental.
withTimeout
import
kotlinx.coroutines.withTimeout
import
timber.log.Timber
import
timber.log.Timber
import
javax.inject.Inject
import
javax.inject.Inject
import
javax.inject.Named
import
javax.inject.Named
import
kotlin.coroutines.experimental.suspendCoroutine
import
kotlin.coroutines.resume
import
kotlin.coroutines.suspendCoroutine
class
ChatRoomsPresenter
@Inject
constructor
(
class
ChatRoomsPresenter
@Inject
constructor
(
private
val
view
:
ChatRoomsView
,
private
val
view
:
ChatRoomsView
,
...
...
app/src/main/java/chat/rocket/android/chatrooms/viewmodel/ChatRoomsViewModel.kt
View file @
f4a743d4
...
@@ -20,16 +20,16 @@ import chat.rocket.core.model.SpotlightResult
...
@@ -20,16 +20,16 @@ import chat.rocket.core.model.SpotlightResult
import
com.shopify.livedataktx.distinct
import
com.shopify.livedataktx.distinct
import
com.shopify.livedataktx.map
import
com.shopify.livedataktx.map
import
com.shopify.livedataktx.nonNull
import
com.shopify.livedataktx.nonNull
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.delay
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.experimental.isActive
import
kotlinx.coroutines.delay
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.isActive
import
kotlinx.coroutines.experimental.newSingleThreadContext
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.experimental.withContext
import
kotlinx.coroutines.newSingleThreadContext
import
kotlinx.coroutines.withContext
import
timber.log.Timber
import
timber.log.Timber
import
java.lang.IllegalArgumentException
import
java.lang.IllegalArgumentException
import
kotlin.coroutines.experimental.coroutineContext
import
kotlin.coroutines.coroutineContext
class
ChatRoomsViewModel
(
class
ChatRoomsViewModel
(
private
val
connectionManager
:
ConnectionManager
,
private
val
connectionManager
:
ConnectionManager
,
...
@@ -107,7 +107,7 @@ class ChatRoomsViewModel(
...
@@ -107,7 +107,7 @@ class ChatRoomsViewModel(
}
}
private
fun
fetchRooms
()
{
private
fun
fetchRooms
()
{
launch
{
GlobalScope
.
launch
{
setLoadingState
(
LoadingState
.
Loading
(
repository
.
count
()))
setLoadingState
(
LoadingState
.
Loading
(
repository
.
count
()))
try
{
try
{
interactor
.
refreshChatRooms
()
interactor
.
refreshChatRooms
()
...
@@ -125,7 +125,7 @@ class ChatRoomsViewModel(
...
@@ -125,7 +125,7 @@ class ChatRoomsViewModel(
}
}
private
suspend
fun
setLoadingState
(
state
:
LoadingState
)
{
private
suspend
fun
setLoadingState
(
state
:
LoadingState
)
{
withContext
(
UI
)
{
withContext
(
Dispatchers
.
Main
)
{
loadingState
.
value
=
state
loadingState
.
value
=
state
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/dagger/module/ActivityBuilder.kt
View file @
f4a743d4
...
@@ -37,6 +37,8 @@ import chat.rocket.android.settings.di.SettingsFragmentProvider
...
@@ -37,6 +37,8 @@ import chat.rocket.android.settings.di.SettingsFragmentProvider
import
chat.rocket.android.settings.password.di.PasswordFragmentProvider
import
chat.rocket.android.settings.password.di.PasswordFragmentProvider
import
chat.rocket.android.settings.password.ui.PasswordActivity
import
chat.rocket.android.settings.password.ui.PasswordActivity
import
chat.rocket.android.userdetails.di.UserDetailsFragmentProvider
import
chat.rocket.android.userdetails.di.UserDetailsFragmentProvider
import
chat.rocket.android.videoconferencing.di.VideoConferencingModule
import
chat.rocket.android.videoconferencing.ui.VideoConferencingActivity
import
chat.rocket.android.webview.adminpanel.di.AdminPanelWebViewFragmentProvider
import
chat.rocket.android.webview.adminpanel.di.AdminPanelWebViewFragmentProvider
import
dagger.Module
import
dagger.Module
import
dagger.android.ContributesAndroidInjector
import
dagger.android.ContributesAndroidInjector
...
@@ -103,4 +105,8 @@ abstract class ActivityBuilder {
...
@@ -103,4 +105,8 @@ abstract class ActivityBuilder {
@PerActivity
@PerActivity
@ContributesAndroidInjector
(
modules
=
[
DrawModule
::
class
])
@ContributesAndroidInjector
(
modules
=
[
DrawModule
::
class
])
abstract
fun
bindDrawingActivity
():
DrawingActivity
abstract
fun
bindDrawingActivity
():
DrawingActivity
@PerActivity
@ContributesAndroidInjector
(
modules
=
[
VideoConferencingModule
::
class
])
abstract
fun
bindVideoConferencingActivity
():
VideoConferencingActivity
}
}
app/src/main/java/chat/rocket/android/dagger/module/AppModule.kt
View file @
f4a743d4
...
@@ -63,7 +63,6 @@ import chat.rocket.common.internal.FallbackSealedClassJsonAdapter
...
@@ -63,7 +63,6 @@ import chat.rocket.common.internal.FallbackSealedClassJsonAdapter
import
chat.rocket.common.internal.ISO8601Date
import
chat.rocket.common.internal.ISO8601Date
import
chat.rocket.common.model.TimestampAdapter
import
chat.rocket.common.model.TimestampAdapter
import
chat.rocket.common.util.CalendarISO8601Converter
import
chat.rocket.common.util.CalendarISO8601Converter
import
chat.rocket.common.util.Logger
import
chat.rocket.common.util.NoOpLogger
import
chat.rocket.common.util.NoOpLogger
import
chat.rocket.common.util.PlatformLogger
import
chat.rocket.common.util.PlatformLogger
import
chat.rocket.core.internal.AttachmentAdapterFactory
import
chat.rocket.core.internal.AttachmentAdapterFactory
...
...
app/src/main/java/chat/rocket/android/dagger/module/LocalModule.kt
View file @
f4a743d4
...
@@ -13,7 +13,6 @@ import chat.rocket.common.internal.FallbackSealedClassJsonAdapter
...
@@ -13,7 +13,6 @@ import chat.rocket.common.internal.FallbackSealedClassJsonAdapter
import
chat.rocket.common.internal.ISO8601Date
import
chat.rocket.common.internal.ISO8601Date
import
chat.rocket.common.model.TimestampAdapter
import
chat.rocket.common.model.TimestampAdapter
import
chat.rocket.common.util.CalendarISO8601Converter
import
chat.rocket.common.util.CalendarISO8601Converter
import
chat.rocket.common.util.Logger
import
chat.rocket.common.util.NoOpLogger
import
chat.rocket.common.util.NoOpLogger
import
chat.rocket.common.util.PlatformLogger
import
chat.rocket.common.util.PlatformLogger
import
chat.rocket.core.internal.AttachmentAdapterFactory
import
chat.rocket.core.internal.AttachmentAdapterFactory
...
...
app/src/main/java/chat/rocket/android/db/DatabaseManager.kt
View file @
f4a743d4
...
@@ -33,11 +33,12 @@ import chat.rocket.core.model.Myself
...
@@ -33,11 +33,12 @@ import chat.rocket.core.model.Myself
import
chat.rocket.core.model.Room
import
chat.rocket.core.model.Room
import
chat.rocket.core.model.attachment.Attachment
import
chat.rocket.core.model.attachment.Attachment
import
chat.rocket.core.model.userId
import
chat.rocket.core.model.userId
import
kotlinx.coroutines.experimental.Job
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.experimental.channels.Channel
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.channels.Channel
import
kotlinx.coroutines.experimental.newSingleThreadContext
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.experimental.withContext
import
kotlinx.coroutines.newSingleThreadContext
import
kotlinx.coroutines.withContext
import
timber.log.Timber
import
timber.log.Timber
import
java.util.HashSet
import
java.util.HashSet
import
kotlin.system.measureTimeMillis
import
kotlin.system.measureTimeMillis
...
@@ -69,7 +70,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -69,7 +70,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
fun
start
()
{
fun
start
()
{
dbJob
?.
cancel
()
dbJob
?.
cancel
()
dbJob
=
launch
(
dbContext
)
{
dbJob
=
GlobalScope
.
launch
(
dbContext
)
{
for
(
operation
in
writeChannel
)
{
for
(
operation
in
writeChannel
)
{
doOperation
(
operation
)
doOperation
(
operation
)
}
}
...
@@ -115,7 +116,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -115,7 +116,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
}
}
fun
processUsersBatch
(
users
:
List
<
User
>)
{
fun
processUsersBatch
(
users
:
List
<
User
>)
{
launch
(
dbManagerContext
)
{
GlobalScope
.
launch
(
dbManagerContext
)
{
val
list
=
ArrayList
<
BaseUserEntity
>(
users
.
size
)
val
list
=
ArrayList
<
BaseUserEntity
>(
users
.
size
)
val
time
=
measureTimeMillis
{
val
time
=
measureTimeMillis
{
users
.
forEach
{
user
->
users
.
forEach
{
user
->
...
@@ -133,7 +134,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -133,7 +134,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
* Creates a list of data base operations
* Creates a list of data base operations
*/
*/
fun
processChatRoomsBatch
(
batch
:
List
<
StreamMessage
<
BaseRoom
>>)
{
fun
processChatRoomsBatch
(
batch
:
List
<
StreamMessage
<
BaseRoom
>>)
{
launch
(
dbManagerContext
)
{
GlobalScope
.
launch
(
dbManagerContext
)
{
val
toRemove
=
HashSet
<
String
>()
val
toRemove
=
HashSet
<
String
>()
val
toInsert
=
ArrayList
<
ChatRoomEntity
>(
batch
.
size
/
2
)
val
toInsert
=
ArrayList
<
ChatRoomEntity
>(
batch
.
size
/
2
)
val
toUpdate
=
ArrayList
<
ChatRoomEntity
>(
batch
.
size
)
val
toUpdate
=
ArrayList
<
ChatRoomEntity
>(
batch
.
size
)
...
@@ -165,7 +166,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -165,7 +166,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
}
}
fun
updateSelfUser
(
myself
:
Myself
)
{
fun
updateSelfUser
(
myself
:
Myself
)
{
launch
(
dbManagerContext
)
{
GlobalScope
.
launch
(
dbManagerContext
)
{
val
user
=
retryDB
(
"getUser(${myself.id})"
)
{
userDao
().
getUser
(
myself
.
id
)
}
val
user
=
retryDB
(
"getUser(${myself.id})"
)
{
userDao
().
getUser
(
myself
.
id
)
}
val
entity
=
user
?.
copy
(
val
entity
=
user
?.
copy
(
name
=
myself
.
name
?:
user
.
name
,
name
=
myself
.
name
?:
user
.
name
,
...
@@ -180,14 +181,14 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -180,14 +181,14 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
}
}
fun
processRooms
(
rooms
:
List
<
ChatRoom
>)
{
fun
processRooms
(
rooms
:
List
<
ChatRoom
>)
{
launch
(
dbManagerContext
)
{
GlobalScope
.
launch
(
dbManagerContext
)
{
val
entities
=
rooms
.
map
{
mapChatRoom
(
it
)
}
val
entities
=
rooms
.
map
{
mapChatRoom
(
it
)
}
sendOperation
(
Operation
.
CleanInsertRooms
(
entities
))
sendOperation
(
Operation
.
CleanInsertRooms
(
entities
))
}
}
}
}
fun
processMessagesBatch
(
messages
:
List
<
Message
>):
Job
{
fun
processMessagesBatch
(
messages
:
List
<
Message
>):
Job
{
return
launch
(
dbManagerContext
)
{
return
GlobalScope
.
launch
(
dbManagerContext
)
{
val
list
=
mutableListOf
<
Pair
<
MessageEntity
,
List
<
BaseMessageEntity
>>>()
val
list
=
mutableListOf
<
Pair
<
MessageEntity
,
List
<
BaseMessageEntity
>>>()
messages
.
forEach
{
message
->
messages
.
forEach
{
message
->
val
pair
=
createMessageEntities
(
message
)
val
pair
=
createMessageEntities
(
message
)
...
...
app/src/main/java/chat/rocket/android/helper/AndroidPermissionsHelper.kt
View file @
f4a743d4
...
@@ -11,8 +11,10 @@ object AndroidPermissionsHelper {
...
@@ -11,8 +11,10 @@ object AndroidPermissionsHelper {
const
val
WRITE_EXTERNAL_STORAGE_CODE
=
1
const
val
WRITE_EXTERNAL_STORAGE_CODE
=
1
fun
checkPermission
(
context
:
Context
,
permission
:
String
):
Boolean
{
fun
checkPermission
(
context
:
Context
,
permission
:
String
):
Boolean
{
return
ContextCompat
.
checkSelfPermission
(
context
,
permission
)
==
return
ContextCompat
.
checkSelfPermission
(
PackageManager
.
PERMISSION_GRANTED
context
,
permission
)
==
PackageManager
.
PERMISSION_GRANTED
}
}
fun
requestPermission
(
context
:
Activity
,
permission
:
String
,
requestCode
:
Int
)
{
fun
requestPermission
(
context
:
Activity
,
permission
:
String
,
requestCode
:
Int
)
{
...
...
app/src/main/java/chat/rocket/android/helper/JitsiHelper.kt
0 → 100644
View file @
f4a743d4
package
chat.rocket.android.helper
import
java.net.URL
object
JitsiHelper
{
/**
* Returns the [URL] for the Jitsi video conferencing.
*
* @param isSecureProtocol True if using SSL, false otherwise - from the public settings.
* @param domain The Jitsi domain - from public settings.
* @param prefix The Jitsi prefix - from public settings.
* @param uniqueIdentifier The server unique identifier - from public settings.
* @param chatRoomId The ChatRoom ID where the video conferencing was started.
*/
fun
getJitsiUrl
(
isSecureProtocol
:
Boolean
,
domain
:
String
?,
prefix
:
String
?,
uniqueIdentifier
:
String
?,
chatRoomId
:
String
?
):
URL
=
URL
(
getJitsiProtocol
(
isSecureProtocol
)
+
domain
+
"/"
+
prefix
+
uniqueIdentifier
+
chatRoomId
)
private
fun
getJitsiProtocol
(
isSecureProtocol
:
Boolean
)
=
if
(
isSecureProtocol
)
"https://"
else
"http://"
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/main/di/MainModule.kt
View file @
f4a743d4
...
@@ -8,7 +8,7 @@ import chat.rocket.android.main.presentation.MainView
...
@@ -8,7 +8,7 @@ import chat.rocket.android.main.presentation.MainView
import
chat.rocket.android.main.ui.MainActivity
import
chat.rocket.android.main.ui.MainActivity
import
dagger.Module
import
dagger.Module
import
dagger.Provides
import
dagger.Provides
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
@Module
@Module
class
MainModule
{
class
MainModule
{
...
...
app/src/main/java/chat/rocket/android/main/presentation/MainPresenter.kt
View file @
f4a743d4
...
@@ -37,7 +37,7 @@ import chat.rocket.core.RocketChatClient
...
@@ -37,7 +37,7 @@ import chat.rocket.core.RocketChatClient
import
chat.rocket.core.internal.rest.getCustomEmojis
import
chat.rocket.core.internal.rest.getCustomEmojis
import
chat.rocket.core.internal.rest.me
import
chat.rocket.core.internal.rest.me
import
chat.rocket.core.model.Myself
import
chat.rocket.core.model.Myself
import
kotlinx.coroutines.
experimental.
channels.Channel
import
kotlinx.coroutines.channels.Channel
import
timber.log.Timber
import
timber.log.Timber
import
javax.inject.Inject
import
javax.inject.Inject
...
...
app/src/main/java/chat/rocket/android/profile/presentation/ProfilePresenter.kt
View file @
f4a743d4
...
@@ -27,8 +27,8 @@ import chat.rocket.core.internal.rest.deleteOwnAccount
...
@@ -27,8 +27,8 @@ import chat.rocket.core.internal.rest.deleteOwnAccount
import
chat.rocket.core.internal.rest.resetAvatar
import
chat.rocket.core.internal.rest.resetAvatar
import
chat.rocket.core.internal.rest.setAvatar
import
chat.rocket.core.internal.rest.setAvatar
import
chat.rocket.core.internal.rest.updateProfile
import
chat.rocket.core.internal.rest.updateProfile
import
kotlinx.coroutines.
experimental.DefaultDispatcher
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
import
java.util.*
import
java.util.*
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -180,7 +180,7 @@ class ProfilePresenter @Inject constructor(
...
@@ -180,7 +180,7 @@ class ProfilePresenter @Inject constructor(
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
view
.
showLoading
()
view
.
showLoading
()
try
{
try
{
withContext
(
D
efaultDispatcher
)
{
withContext
(
D
ispatchers
.
Default
)
{
// REMARK: Backend API is only working with a lowercase hash.
// REMARK: Backend API is only working with a lowercase hash.
// https://github.com/RocketChat/Rocket.Chat/issues/12573
// https://github.com/RocketChat/Rocket.Chat/issues/12573
retryIO
{
client
.
deleteOwnAccount
(
password
.
gethash
().
toHex
().
toLowerCase
())
}
retryIO
{
client
.
deleteOwnAccount
(
password
.
gethash
().
toHex
().
toLowerCase
())
}
...
...
app/src/main/java/chat/rocket/android/push/DirectReplyReceiver.kt
View file @
f4a743d4
...
@@ -11,8 +11,8 @@ import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
...
@@ -11,8 +11,8 @@ import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatException
import
chat.rocket.core.internal.rest.sendMessage
import
chat.rocket.core.internal.rest.sendMessage
import
dagger.android.AndroidInjection
import
dagger.android.AndroidInjection
import
kotlinx.coroutines.
experimental.android.UI
import
kotlinx.coroutines.
MainScope
import
kotlinx.coroutines.
experimental.
launch
import
kotlinx.coroutines.launch
import
timber.log.Timber
import
timber.log.Timber
import
java.util.*
import
java.util.*
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -36,7 +36,7 @@ class DirectReplyReceiver : BroadcastReceiver() {
...
@@ -36,7 +36,7 @@ class DirectReplyReceiver : BroadcastReceiver() {
if
(
ACTION_REPLY
==
intent
.
action
)
{
if
(
ACTION_REPLY
==
intent
.
action
)
{
val
message
=
intent
.
getParcelableExtra
<
PushMessage
>(
EXTRA_PUSH_MESSAGE
)
val
message
=
intent
.
getParcelableExtra
<
PushMessage
>(
EXTRA_PUSH_MESSAGE
)
message
?.
let
{
message
?.
let
{
launch
(
UI
)
{
MainScope
().
launch
{
val
notificationId
=
it
.
notificationId
.
toInt
()
val
notificationId
=
it
.
notificationId
.
toInt
()
val
hostname
=
it
.
info
.
host
val
hostname
=
it
.
info
.
host
try
{
try
{
...
...
app/src/main/java/chat/rocket/android/push/PushManager.kt
View file @
f4a743d4
...
@@ -29,7 +29,7 @@ import chat.rocket.common.model.RoomType
...
@@ -29,7 +29,7 @@ import chat.rocket.common.model.RoomType
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.model.roomTypeOf
import
com.squareup.moshi.Json
import
com.squareup.moshi.Json
import
com.squareup.moshi.Moshi
import
com.squareup.moshi.Moshi
import
kotlinx.coroutines.
experimental.
runBlocking
import
kotlinx.coroutines.runBlocking
import
se.ansman.kotshi.JsonSerializable
import
se.ansman.kotshi.JsonSerializable
import
se.ansman.kotshi.KotshiConstructor
import
se.ansman.kotshi.KotshiConstructor
import
timber.log.Timber
import
timber.log.Timber
...
...
app/src/main/java/chat/rocket/android/server/di/ChangeServerModule.kt
View file @
f4a743d4
...
@@ -3,13 +3,12 @@ package chat.rocket.android.server.di
...
@@ -3,13 +3,12 @@ package chat.rocket.android.server.di
import
androidx.lifecycle.LifecycleOwner
import
androidx.lifecycle.LifecycleOwner
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.dagger.scope.PerActivity
import
chat.rocket.android.dagger.scope.PerActivity
import
chat.rocket.android.dagger.scope.PerFragment
import
chat.rocket.android.server.presentation.ChangeServerNavigator
import
chat.rocket.android.server.presentation.ChangeServerNavigator
import
chat.rocket.android.server.presentation.ChangeServerView
import
chat.rocket.android.server.presentation.ChangeServerView
import
chat.rocket.android.server.ui.ChangeServerActivity
import
chat.rocket.android.server.ui.ChangeServerActivity
import
dagger.Module
import
dagger.Module
import
dagger.Provides
import
dagger.Provides
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
@Module
@Module
class
ChangeServerModule
{
class
ChangeServerModule
{
...
...
app/src/main/java/chat/rocket/android/server/domain/ChatRoomsInteractor.kt
View file @
f4a743d4
package
chat.rocket.android.server.domain
package
chat.rocket.android.server.domain
import
chat.rocket.core.model.ChatRoom
import
chat.rocket.core.model.ChatRoom
import
kotlinx.coroutines.
experimental.CommonPool
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
import
javax.inject.Inject
import
javax.inject.Inject
class
ChatRoomsInteractor
@Inject
constructor
(
private
val
repository
:
ChatRoomsRepository
)
{
class
ChatRoomsInteractor
@Inject
constructor
(
private
val
repository
:
ChatRoomsRepository
)
{
...
@@ -23,15 +23,16 @@ class ChatRoomsInteractor @Inject constructor(private val repository: ChatRoomsR
...
@@ -23,15 +23,16 @@ class ChatRoomsInteractor @Inject constructor(private val repository: ChatRoomsR
* @param name The name of chat room to look for or a chat room that contains this name.
* @param name The name of chat room to look for or a chat room that contains this name.
* @return A list of ChatRoom objects with the given name.
* @return A list of ChatRoom objects with the given name.
*/
*/
suspend
fun
getAllByName
(
url
:
String
,
name
:
String
):
List
<
ChatRoom
>
=
withContext
(
CommonPool
)
{
suspend
fun
getAllByName
(
url
:
String
,
name
:
String
):
List
<
ChatRoom
>
=
val
allChatRooms
=
repository
.
get
(
url
)
withContext
(
Dispatchers
.
IO
)
{
if
(
name
.
isEmpty
())
{
val
allChatRooms
=
repository
.
get
(
url
)
return
@withContext
allChatRooms
if
(
name
.
isEmpty
())
{
return
@withContext
allChatRooms
}
return
@withContext
allChatRooms
.
filter
{
it
.
name
.
contains
(
name
,
true
)
}
}
}
return
@withContext
allChatRooms
.
filter
{
it
.
name
.
contains
(
name
,
true
)
}
}
/**
/**
* Get a specific [ChatRoom] by its id.
* Get a specific [ChatRoom] by its id.
...
@@ -40,11 +41,12 @@ class ChatRoomsInteractor @Inject constructor(private val repository: ChatRoomsR
...
@@ -40,11 +41,12 @@ class ChatRoomsInteractor @Inject constructor(private val repository: ChatRoomsR
* @param roomId The id of the room to get.
* @param roomId The id of the room to get.
* @return The [ChatRoom] object or null if we couldn't find any.
* @return The [ChatRoom] object or null if we couldn't find any.
*/
*/
suspend
fun
getById
(
serverUrl
:
String
,
roomId
:
String
):
ChatRoom
?
=
withContext
(
CommonPool
)
{
suspend
fun
getById
(
serverUrl
:
String
,
roomId
:
String
):
ChatRoom
?
=
return
@withContext
repository
.
get
(
serverUrl
).
find
{
withContext
(
Dispatchers
.
IO
)
{
it
.
id
==
roomId
return
@withContext
repository
.
get
(
serverUrl
).
find
{
it
.
id
==
roomId
}
}
}
}
/**
/**
* Get a specific [ChatRoom] by its name.
* Get a specific [ChatRoom] by its name.
...
...
app/src/main/java/chat/rocket/android/server/domain/RefreshPermissionsInteractor.kt
View file @
f4a743d4
...
@@ -3,8 +3,9 @@ package chat.rocket.android.server.domain
...
@@ -3,8 +3,9 @@ package chat.rocket.android.server.domain
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.retryIO
import
chat.rocket.android.util.retryIO
import
chat.rocket.core.internal.rest.permissions
import
chat.rocket.core.internal.rest.permissions
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
timber.log.Timber
import
timber.log.Timber
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -17,7 +18,7 @@ class RefreshPermissionsInteractor @Inject constructor(
...
@@ -17,7 +18,7 @@ class RefreshPermissionsInteractor @Inject constructor(
)
{
)
{
fun
refreshAsync
(
server
:
String
)
{
fun
refreshAsync
(
server
:
String
)
{
launch
(
CommonPool
)
{
GlobalScope
.
launch
(
Dispatchers
.
IO
)
{
try
{
try
{
factory
.
create
(
server
).
let
{
client
->
factory
.
create
(
server
).
let
{
client
->
val
permissions
=
retryIO
(
val
permissions
=
retryIO
(
...
...
app/src/main/java/chat/rocket/android/server/domain/RefreshSettingsInteractor.kt
View file @
f4a743d4
...
@@ -3,9 +3,10 @@ package chat.rocket.android.server.domain
...
@@ -3,9 +3,10 @@ package chat.rocket.android.server.domain
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.retryIO
import
chat.rocket.android.util.retryIO
import
chat.rocket.core.internal.rest.settings
import
chat.rocket.core.internal.rest.settings
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.experimental.withContext
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
import
timber.log.Timber
import
timber.log.Timber
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -18,6 +19,8 @@ class RefreshSettingsInteractor @Inject constructor(
...
@@ -18,6 +19,8 @@ class RefreshSettingsInteractor @Inject constructor(
)
{
)
{
private
var
settingsFilter
=
arrayOf
(
private
var
settingsFilter
=
arrayOf
(
UNIQUE_IDENTIFIER
,
LDAP_ENABLE
,
LDAP_ENABLE
,
CAS_ENABLE
,
CAS_ENABLE
,
CAS_LOGIN_URL
,
CAS_LOGIN_URL
,
...
@@ -70,7 +73,7 @@ class RefreshSettingsInteractor @Inject constructor(
...
@@ -70,7 +73,7 @@ class RefreshSettingsInteractor @Inject constructor(
)
)
suspend
fun
refresh
(
server
:
String
)
{
suspend
fun
refresh
(
server
:
String
)
{
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
factory
.
create
(
server
).
let
{
client
->
factory
.
create
(
server
).
let
{
client
->
val
settings
=
retryIO
(
val
settings
=
retryIO
(
description
=
"settings"
,
description
=
"settings"
,
...
@@ -86,7 +89,7 @@ class RefreshSettingsInteractor @Inject constructor(
...
@@ -86,7 +89,7 @@ class RefreshSettingsInteractor @Inject constructor(
}
}
fun
refreshAsync
(
server
:
String
)
{
fun
refreshAsync
(
server
:
String
)
{
launch
(
CommonPool
)
{
GlobalScope
.
launch
(
Dispatchers
.
IO
)
{
try
{
try
{
refresh
(
server
)
refresh
(
server
)
}
catch
(
ex
:
Exception
)
{
}
catch
(
ex
:
Exception
)
{
...
...
app/src/main/java/chat/rocket/android/server/domain/SettingsRepository.kt
View file @
f4a743d4
...
@@ -5,6 +5,8 @@ import chat.rocket.core.model.Value
...
@@ -5,6 +5,8 @@ import chat.rocket.core.model.Value
typealias
PublicSettings
=
Map
<
String
,
Value
<
Any
>>
typealias
PublicSettings
=
Map
<
String
,
Value
<
Any
>>
const
val
UNIQUE_IDENTIFIER
=
"uniqueID"
// Authentication methods
// Authentication methods
const
val
LDAP_ENABLE
=
"LDAP_Enable"
const
val
LDAP_ENABLE
=
"LDAP_Enable"
const
val
CAS_ENABLE
=
"CAS_enabled"
const
val
CAS_ENABLE
=
"CAS_enabled"
...
@@ -64,6 +66,8 @@ const val MESSAGE_READ_RECEIPT_STORE_USERS = "Message_Read_Receipt_Store_Users"
...
@@ -64,6 +66,8 @@ const val MESSAGE_READ_RECEIPT_STORE_USERS = "Message_Read_Receipt_Store_Users"
* RefreshSettingsInteractor.kt and a extension function to access it.
* RefreshSettingsInteractor.kt and a extension function to access it.
*/
*/
fun
PublicSettings
.
uniqueIdentifier
():
String
?
=
this
[
UNIQUE_IDENTIFIER
]
?.
value
as
String
?
// Authentication
// Authentication
fun
PublicSettings
.
isLdapAuthenticationEnabled
():
Boolean
=
this
[
LDAP_ENABLE
]
?.
value
==
true
fun
PublicSettings
.
isLdapAuthenticationEnabled
():
Boolean
=
this
[
LDAP_ENABLE
]
?.
value
==
true
fun
PublicSettings
.
isCasAuthenticationEnabled
():
Boolean
=
this
[
CAS_ENABLE
]
?.
value
==
true
fun
PublicSettings
.
isCasAuthenticationEnabled
():
Boolean
=
this
[
CAS_ENABLE
]
?.
value
==
true
...
...
app/src/main/java/chat/rocket/android/server/infraestructure/ConnectionManager.kt
View file @
f4a743d4
...
@@ -23,26 +23,31 @@ import chat.rocket.core.internal.rest.chatRooms
...
@@ -23,26 +23,31 @@ import chat.rocket.core.internal.rest.chatRooms
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Myself
import
chat.rocket.core.model.Myself
import
chat.rocket.core.model.Room
import
chat.rocket.core.model.Room
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.experimental.Job
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.channels.Channel
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.experimental.channels.SendChannel
import
kotlinx.coroutines.channels.Channel
import
kotlinx.coroutines.experimental.channels.actor
import
kotlinx.coroutines.channels.SendChannel
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.channels.actor
import
kotlinx.coroutines.experimental.newSingleThreadContext
import
kotlinx.coroutines.isActive
import
kotlinx.coroutines.experimental.selects.select
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.newSingleThreadContext
import
kotlinx.coroutines.selects.select
import
timber.log.Timber
import
timber.log.Timber
import
java.util.concurrent.CopyOnWriteArrayList
import
java.util.concurrent.CopyOnWriteArrayList
import
kotlin.coroutines.
experimental.
CoroutineContext
import
kotlin.coroutines.CoroutineContext
class
ConnectionManager
(
class
ConnectionManager
(
internal
val
client
:
RocketChatClient
,
internal
val
client
:
RocketChatClient
,
private
val
dbManager
:
DatabaseManager
private
val
dbManager
:
DatabaseManager
)
{
)
:
CoroutineScope
{
private
var
connectJob
:
Job
?
=
null
override
val
coroutineContext
:
CoroutineContext
get
()
=
Dispatchers
.
IO
val
statusLiveData
=
MutableLiveData
<
State
>()
val
statusLiveData
=
MutableLiveData
<
State
>()
private
val
statusChannelList
=
CopyOnWriteArrayList
<
Channel
<
State
>>()
private
val
statusChannelList
=
CopyOnWriteArrayList
<
Channel
<
State
>>()
private
val
statusChannel
=
Channel
<
State
>(
Channel
.
CONFLATED
)
private
val
statusChannel
=
Channel
<
State
>(
Channel
.
CONFLATED
)
private
var
connectJob
:
Job
?
=
null
private
val
roomMessagesChannels
=
LinkedHashMap
<
String
,
Channel
<
Message
>>()
private
val
roomMessagesChannels
=
LinkedHashMap
<
String
,
Channel
<
Message
>>()
private
val
userDataChannels
=
ArrayList
<
Channel
<
Myself
>>()
private
val
userDataChannels
=
ArrayList
<
Channel
<
Myself
>>()
...
@@ -60,7 +65,7 @@ class ConnectionManager(
...
@@ -60,7 +65,7 @@ class ConnectionManager(
private
val
messagesContext
=
newSingleThreadContext
(
"messagesContext"
)
private
val
messagesContext
=
newSingleThreadContext
(
"messagesContext"
)
fun
connect
()
{
fun
connect
()
{
if
(
connectJob
?.
isActive
==
true
&&
(
state
!
is
State
.
Disconnected
)
)
{
if
(
connectJob
?.
isActive
==
true
&&
state
!
is
State
.
Disconnected
)
{
Timber
.
d
(
"Already connected, just returning..."
)
Timber
.
d
(
"Already connected, just returning..."
)
return
return
}
}
...
@@ -78,32 +83,31 @@ class ConnectionManager(
...
@@ -78,32 +83,31 @@ class ConnectionManager(
when
(
status
)
{
when
(
status
)
{
is
State
.
Connected
->
{
is
State
.
Connected
->
{
dbManager
.
clearUsersStatus
()
dbManager
.
clearUsersStatus
()
client
.
subscribeSubscriptions
{
_
,
id
->
client
.
subscribeSubscriptions
{
_
,
id
->
Timber
.
d
(
"Subscribed to subscriptions: $id"
)
Timber
.
d
(
"Subscribed to subscriptions: $id"
)
subscriptionId
=
id
subscriptionId
=
id
}
}
client
.
subscribeRooms
{
_
,
id
->
client
.
subscribeRooms
{
_
,
id
->
Timber
.
d
(
"Subscribed to rooms: $id"
)
Timber
.
d
(
"Subscribed to rooms: $id"
)
roomsId
=
id
roomsId
=
id
}
}
client
.
subscribeUserData
{
_
,
id
->
client
.
subscribeUserData
{
_
,
id
->
Timber
.
d
(
"Subscribed to the userData id: $id"
)
Timber
.
d
(
"Subscribed to the userData id: $id"
)
userDataId
=
id
userDataId
=
id
}
}
client
.
subscribeActiveUsers
{
_
,
id
->
client
.
subscribeActiveUsers
{
_
,
id
->
Timber
.
d
(
"Subscribed to the activeUser id: $id"
)
Timber
.
d
(
"Subscribed to the activeUser id: $id"
)
activeUserId
=
id
activeUserId
=
id
}
}
resubscribeRooms
()
resubscribeRooms
()
temporaryStatus
?.
let
{
client
.
setTemporaryStatus
(
it
)
}
temporaryStatus
?.
let
{
status
->
client
.
setTemporaryStatus
(
status
)
}
}
is
State
.
Waiting
->
{
Timber
.
d
(
"Connection in: ${status.seconds}"
)
}
}
is
State
.
Waiting
->
Timber
.
d
(
"Connection in: ${status.seconds}"
)
}
}
statusLiveData
.
postValue
(
status
)
statusLiveData
.
postValue
(
status
)
...
@@ -116,8 +120,9 @@ class ConnectionManager(
...
@@ -116,8 +120,9 @@ class ConnectionManager(
}
}
var
totalBatchedUsers
=
0
var
totalBatchedUsers
=
0
val
userActor
=
createBatchActor
<
User
>(
activeUsersContext
,
parent
=
connectJob
,
val
userActor
=
createBatchActor
<
User
>(
maxSize
=
500
,
maxTime
=
1000
)
{
users
->
activeUsersContext
,
parent
=
connectJob
,
maxSize
=
500
,
maxTime
=
1000
)
{
users
->
totalBatchedUsers
+=
users
.
size
totalBatchedUsers
+=
users
.
size
Timber
.
d
(
"Processing Users batch: ${users.size} - $totalBatchedUsers"
)
Timber
.
d
(
"Processing Users batch: ${users.size} - $totalBatchedUsers"
)
...
@@ -125,8 +130,9 @@ class ConnectionManager(
...
@@ -125,8 +130,9 @@ class ConnectionManager(
dbManager
.
processUsersBatch
(
users
)
dbManager
.
processUsersBatch
(
users
)
}
}
val
roomsActor
=
createBatchActor
<
StreamMessage
<
BaseRoom
>>(
roomsContext
,
parent
=
connectJob
,
val
roomsActor
=
createBatchActor
<
StreamMessage
<
BaseRoom
>>(
maxSize
=
10
)
{
batch
->
roomsContext
,
parent
=
connectJob
,
maxSize
=
10
)
{
batch
->
Timber
.
d
(
"processing Stream batch: ${batch.size} - $batch"
)
Timber
.
d
(
"processing Stream batch: ${batch.size} - $batch"
)
dbManager
.
processChatRoomsBatch
(
batch
)
dbManager
.
processChatRoomsBatch
(
batch
)
...
@@ -135,16 +141,15 @@ class ConnectionManager(
...
@@ -135,16 +141,15 @@ class ConnectionManager(
if
(
it
.
type
==
Type
.
Updated
)
{
if
(
it
.
type
==
Type
.
Updated
)
{
if
(
it
.
data
is
Room
)
{
if
(
it
.
data
is
Room
)
{
val
room
=
it
.
data
as
Room
val
room
=
it
.
data
as
Room
roomsChannels
[
it
.
data
.
id
]
?.
let
{
channel
->
roomsChannels
[
it
.
data
.
id
]
?.
offer
(
room
)
channel
.
offer
(
room
)
}
}
}
}
}
}
}
}
}
val
messagesActor
=
createBatchActor
<
Message
>(
messagesContext
,
parent
=
connectJob
,
val
messagesActor
=
createBatchActor
<
Message
>(
maxSize
=
100
,
maxTime
=
500
)
{
messages
->
messagesContext
,
parent
=
connectJob
,
maxSize
=
100
,
maxTime
=
500
)
{
messages
->
Timber
.
d
(
"Processing Messages batch: ${messages.size}"
)
Timber
.
d
(
"Processing Messages batch: ${messages.size}"
)
dbManager
.
processMessagesBatch
(
messages
.
distinctBy
{
it
.
id
})
dbManager
.
processMessagesBatch
(
messages
.
distinctBy
{
it
.
id
})
...
@@ -157,7 +162,7 @@ class ConnectionManager(
...
@@ -157,7 +162,7 @@ class ConnectionManager(
}
}
// stream-notify-user - ${userId}/rooms-changed
// stream-notify-user - ${userId}/rooms-changed
launch
(
parent
=
connectJob
)
{
launch
{
for
(
room
in
client
.
roomsChannel
)
{
for
(
room
in
client
.
roomsChannel
)
{
Timber
.
d
(
"GOT Room streamed"
)
Timber
.
d
(
"GOT Room streamed"
)
roomsActor
.
send
(
room
)
roomsActor
.
send
(
room
)
...
@@ -170,7 +175,7 @@ class ConnectionManager(
...
@@ -170,7 +175,7 @@ class ConnectionManager(
}
}
// stream-notify-user - ${userId}/subscriptions-changed
// stream-notify-user - ${userId}/subscriptions-changed
launch
(
parent
=
connectJob
)
{
launch
{
for
(
subscription
in
client
.
subscriptionsChannel
)
{
for
(
subscription
in
client
.
subscriptionsChannel
)
{
Timber
.
d
(
"GOT Subscription streamed"
)
Timber
.
d
(
"GOT Subscription streamed"
)
roomsActor
.
send
(
subscription
)
roomsActor
.
send
(
subscription
)
...
@@ -178,7 +183,7 @@ class ConnectionManager(
...
@@ -178,7 +183,7 @@ class ConnectionManager(
}
}
// stream-room-messages - $roomId
// stream-room-messages - $roomId
launch
(
parent
=
connectJob
)
{
launch
{
for
(
message
in
client
.
messagesChannel
)
{
for
(
message
in
client
.
messagesChannel
)
{
Timber
.
d
(
"Received new Message for room ${message.roomId}"
)
Timber
.
d
(
"Received new Message for room ${message.roomId}"
)
messagesActor
.
send
(
message
)
messagesActor
.
send
(
message
)
...
@@ -186,7 +191,7 @@ class ConnectionManager(
...
@@ -186,7 +191,7 @@ class ConnectionManager(
}
}
// userData
// userData
launch
(
parent
=
connectJob
)
{
launch
{
for
(
myself
in
client
.
userDataChannel
)
{
for
(
myself
in
client
.
userDataChannel
)
{
Timber
.
d
(
"Got userData"
)
Timber
.
d
(
"Got userData"
)
dbManager
.
updateSelfUser
(
myself
)
dbManager
.
updateSelfUser
(
myself
)
...
@@ -197,7 +202,7 @@ class ConnectionManager(
...
@@ -197,7 +202,7 @@ class ConnectionManager(
}
}
// activeUsers
// activeUsers
launch
(
parent
=
connectJob
)
{
launch
{
for
(
user
in
client
.
activeUsersChannel
)
{
for
(
user
in
client
.
activeUsersChannel
)
{
userActor
.
send
(
user
)
userActor
.
send
(
user
)
}
}
...
@@ -286,16 +291,18 @@ class ConnectionManager(
...
@@ -286,16 +291,18 @@ class ConnectionManager(
}
}
}
}
private
inline
fun
<
T
>
createBatchActor
(
context
:
CoroutineContext
=
CommonPool
,
private
inline
fun
<
T
>
createBatchActor
(
parent
:
Job
?
=
null
,
context
:
CoroutineContext
=
Dispatchers
.
IO
,
maxSize
:
Int
=
100
,
parent
:
Job
?
=
null
,
maxTime
:
Int
=
500
,
maxSize
:
Int
=
100
,
crossinline
block
:
(
List
<
T
>)
->
Unit
):
SendChannel
<
T
>
{
maxTime
:
Int
=
500
,
return
actor
(
context
,
parent
=
parent
)
{
crossinline
block
:
(
List
<
T
>)
->
Unit
):
SendChannel
<
T
>
{
return
actor
(
context
)
{
val
batch
=
ArrayList
<
T
>(
maxSize
)
val
batch
=
ArrayList
<
T
>(
maxSize
)
var
deadline
=
0L
// deadline for sending this batch to callback block
var
deadline
=
0L
// deadline for sending this batch to callback block
while
(
true
)
{
while
(
true
)
{
// when deadline is reached or size is exceeded, pass the batch to the callback block
// when deadline is reached or size is exceeded, pass the batch to the callback block
val
remainingTime
=
deadline
-
System
.
currentTimeMillis
()
val
remainingTime
=
deadline
-
System
.
currentTimeMillis
()
if
(
batch
.
isNotEmpty
()
&&
remainingTime
<=
0
||
batch
.
size
>=
maxSize
)
{
if
(
batch
.
isNotEmpty
()
&&
remainingTime
<=
0
||
batch
.
size
>=
maxSize
)
{
...
...
app/src/main/java/chat/rocket/android/server/infraestructure/DatabaseMessageMapper.kt
View file @
f4a743d4
...
@@ -14,7 +14,6 @@ import chat.rocket.core.model.Message
...
@@ -14,7 +14,6 @@ import chat.rocket.core.model.Message
import
chat.rocket.core.model.Reactions
import
chat.rocket.core.model.Reactions
import
chat.rocket.core.model.attachment.Attachment
import
chat.rocket.core.model.attachment.Attachment
import
chat.rocket.core.model.attachment.Color
import
chat.rocket.core.model.attachment.Color
import
chat.rocket.core.model.attachment.DEFAULT_COLOR_STR
import
chat.rocket.core.model.attachment.Field
import
chat.rocket.core.model.attachment.Field
import
chat.rocket.core.model.attachment.actions.Action
import
chat.rocket.core.model.attachment.actions.Action
import
chat.rocket.core.model.attachment.actions.ButtonAction
import
chat.rocket.core.model.attachment.actions.ButtonAction
...
@@ -22,8 +21,8 @@ import chat.rocket.core.model.messageTypeOf
...
@@ -22,8 +21,8 @@ import chat.rocket.core.model.messageTypeOf
import
chat.rocket.core.model.url.Meta
import
chat.rocket.core.model.url.Meta
import
chat.rocket.core.model.url.ParsedUrl
import
chat.rocket.core.model.url.ParsedUrl
import
chat.rocket.core.model.url.Url
import
chat.rocket.core.model.url.Url
import
kotlinx.coroutines.
experimental.CommonPool
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
class
DatabaseMessageMapper
(
private
val
dbManager
:
DatabaseManager
)
{
class
DatabaseMessageMapper
(
private
val
dbManager
:
DatabaseManager
)
{
suspend
fun
map
(
message
:
FullMessage
):
Message
?
=
map
(
listOf
(
message
)).
firstOrNull
()
suspend
fun
map
(
message
:
FullMessage
):
Message
?
=
map
(
listOf
(
message
)).
firstOrNull
()
...
@@ -58,7 +57,8 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
...
@@ -58,7 +57,8 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
val
attachments
=
this
.
attachments
?.
let
{
mapAttachments
(
it
).
asReversed
()
}
val
attachments
=
this
.
attachments
?.
let
{
mapAttachments
(
it
).
asReversed
()
}
val
messageType
=
messageTypeOf
(
this
.
message
.
type
)
val
messageType
=
messageTypeOf
(
this
.
message
.
type
)
list
.
add
(
Message
(
list
.
add
(
Message
(
id
=
this
.
message
.
id
,
id
=
this
.
message
.
id
,
roomId
=
this
.
message
.
roomId
,
roomId
=
this
.
message
.
roomId
,
message
=
this
.
message
.
message
,
message
=
this
.
message
.
message
,
...
@@ -82,7 +82,8 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
...
@@ -82,7 +82,8 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
role
=
this
.
message
.
role
,
role
=
this
.
message
.
role
,
synced
=
this
.
message
.
synced
,
synced
=
this
.
message
.
synced
,
unread
=
this
.
message
.
unread
unread
=
this
.
message
.
unread
))
)
)
}
}
}
}
...
@@ -106,13 +107,19 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
...
@@ -106,13 +107,19 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
val
parsedUrl
=
url
.
hostname
?.
let
{
val
parsedUrl
=
url
.
hostname
?.
let
{
ParsedUrl
(
host
=
it
)
ParsedUrl
(
host
=
it
)
}
}
val
meta
=
if
(!
url
.
description
.
isNullOrEmpty
()
||
!
url
.
imageUrl
.
isNullOrEmpty
()
||
!
url
.
title
.
isNullOrEmpty
())
{
val
meta
=
val
raw
=
HashMap
<
String
,
String
>()
if
(!
url
.
description
.
isNullOrEmpty
()
||
!
url
.
imageUrl
.
isNullOrEmpty
()
||
!
url
.
title
.
isNullOrEmpty
())
{
if
(
url
.
description
!=
null
)
raw
[
"ogDescription"
]
=
url
.
description
val
raw
=
HashMap
<
String
,
String
>()
if
(
url
.
title
!=
null
)
raw
[
"ogTitle"
]
=
url
.
title
if
(
url
.
description
!=
null
)
raw
[
"ogDescription"
]
=
url
.
description
if
(
url
.
imageUrl
!=
null
)
raw
[
"ogImage"
]
=
url
.
imageUrl
if
(
url
.
title
!=
null
)
raw
[
"ogTitle"
]
=
url
.
title
Meta
(
title
=
url
.
title
,
description
=
url
.
description
,
imageUrl
=
url
.
imageUrl
,
raw
=
raw
)
if
(
url
.
imageUrl
!=
null
)
raw
[
"ogImage"
]
=
url
.
imageUrl
}
else
null
Meta
(
title
=
url
.
title
,
description
=
url
.
description
,
imageUrl
=
url
.
imageUrl
,
raw
=
raw
)
}
else
null
list
.
add
(
Url
(
url
=
url
.
url
,
meta
=
meta
,
parsedUrl
=
parsedUrl
))
list
.
add
(
Url
(
url
=
url
.
url
,
meta
=
meta
,
parsedUrl
=
parsedUrl
))
}
}
...
@@ -135,7 +142,7 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
...
@@ -135,7 +142,7 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
attachments
.
forEach
{
attachment
->
attachments
.
forEach
{
attachment
->
with
(
attachment
)
{
with
(
attachment
)
{
val
fields
=
if
(
hasFields
)
{
val
fields
=
if
(
hasFields
)
{
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
retryDB
(
"getAttachmentFields(${attachment._id})"
)
{
retryDB
(
"getAttachmentFields(${attachment._id})"
)
{
dbManager
.
messageDao
().
getAttachmentFields
(
attachment
.
_id
)
dbManager
.
messageDao
().
getAttachmentFields
(
attachment
.
_id
)
}
}
...
@@ -144,7 +151,7 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
...
@@ -144,7 +151,7 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
null
null
}
}
val
actions
=
if
(
hasActions
)
{
val
actions
=
if
(
hasActions
)
{
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
retryDB
(
"getAttachmentActions(${attachment._id})"
)
{
retryDB
(
"getAttachmentActions(${attachment._id})"
)
{
dbManager
.
messageDao
().
getAttachmentActions
(
attachment
.
_id
)
dbManager
.
messageDao
().
getAttachmentActions
(
attachment
.
_id
)
}
}
...
@@ -154,33 +161,34 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
...
@@ -154,33 +161,34 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
}
}
val
attachment
=
Attachment
(
val
attachment
=
Attachment
(
title
=
title
,
title
=
title
,
type
=
type
,
type
=
type
,
description
=
description
,
description
=
description
,
authorName
=
authorName
,
authorName
=
authorName
,
text
=
text
,
text
=
text
,
thumbUrl
=
thumbUrl
,
thumbUrl
=
thumbUrl
,
color
=
color
?.
let
{
Color
.
Custom
(
color
)
},
color
=
color
?.
let
{
Color
.
Custom
(
color
)
},
titleLink
=
titleLink
,
titleLink
=
titleLink
,
titleLinkDownload
=
titleLinkDownload
,
titleLinkDownload
=
titleLinkDownload
,
imageUrl
=
imageUrl
,
imageUrl
=
imageUrl
,
imageType
=
imageType
,
imageType
=
imageType
,
imageSize
=
imageSize
,
imageSize
=
imageSize
,
videoUrl
=
videoUrl
,
videoUrl
=
videoUrl
,
videoType
=
videoType
,
videoType
=
videoType
,
videoSize
=
videoSize
,
videoSize
=
videoSize
,
audioUrl
=
audioUrl
,
audioUrl
=
audioUrl
,
audioType
=
audioType
,
audioType
=
audioType
,
audioSize
=
audioSize
,
audioSize
=
audioSize
,
messageLink
=
messageLink
,
messageLink
=
messageLink
,
attachments
=
null
,
// HOW TO MAP THIS
attachments
=
null
,
// HOW TO MAP THIS
timestamp
=
timestamp
,
timestamp
=
timestamp
,
authorIcon
=
authorIcon
,
authorIcon
=
authorIcon
,
authorLink
=
authorLink
,
authorLink
=
authorLink
,
fields
=
fields
,
fields
=
fields
,
fallback
=
fallback
,
fallback
=
fallback
,
buttonAlignment
=
if
(
actions
!=
null
&&
actions
.
isNotEmpty
())
buttonAlignment
?:
"vertical"
else
null
,
buttonAlignment
=
if
(
actions
!=
null
&&
actions
.
isNotEmpty
())
buttonAlignment
actions
=
actions
?:
"vertical"
else
null
,
actions
=
actions
)
)
list
.
add
(
attachment
)
list
.
add
(
attachment
)
}
}
...
@@ -190,9 +198,11 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
...
@@ -190,9 +198,11 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
private
fun
mapAction
(
action
:
AttachmentActionEntity
):
Action
?
{
private
fun
mapAction
(
action
:
AttachmentActionEntity
):
Action
?
{
return
when
(
action
.
type
)
{
return
when
(
action
.
type
)
{
"button"
->
ButtonAction
(
action
.
type
,
action
.
text
,
action
.
url
,
action
.
isWebView
,
"button"
->
ButtonAction
(
action
.
webViewHeightRatio
,
action
.
imageUrl
,
action
.
message
,
action
.
type
,
action
.
text
,
action
.
url
,
action
.
isWebView
,
action
.
isMessageInChatWindow
)
action
.
webViewHeightRatio
,
action
.
imageUrl
,
action
.
message
,
action
.
isMessageInChatWindow
)
else
->
null
else
->
null
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/server/infraestructure/DatabaseMessagesRepository.kt
View file @
f4a743d4
...
@@ -6,41 +6,42 @@ import chat.rocket.android.db.model.MessagesSync
...
@@ -6,41 +6,42 @@ import chat.rocket.android.db.model.MessagesSync
import
chat.rocket.android.server.domain.MessagesRepository
import
chat.rocket.android.server.domain.MessagesRepository
import
chat.rocket.android.util.retryDB
import
chat.rocket.android.util.retryDB
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Message
import
kotlinx.coroutines.
experimental.CommonPool
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
class
DatabaseMessagesRepository
(
class
DatabaseMessagesRepository
(
private
val
dbManager
:
DatabaseManager
,
private
val
dbManager
:
DatabaseManager
,
private
val
mapper
:
DatabaseMessageMapper
private
val
mapper
:
DatabaseMessageMapper
)
:
MessagesRepository
{
)
:
MessagesRepository
{
override
suspend
fun
getById
(
id
:
String
):
Message
?
=
withContext
(
CommonPool
)
{
override
suspend
fun
getById
(
id
:
String
):
Message
?
=
withContext
(
Dispatchers
.
IO
)
{
retryDB
(
"getMessageById($id)"
)
{
retryDB
(
"getMessageById($id)"
)
{
dbManager
.
messageDao
().
getMessageById
(
id
)
?.
let
{
message
->
mapper
.
map
(
message
)
}
dbManager
.
messageDao
().
getMessageById
(
id
)
?.
let
{
message
->
mapper
.
map
(
message
)
}
}
}
}
}
override
suspend
fun
getByRoomId
(
roomId
:
String
):
List
<
Message
>
=
withContext
(
CommonPool
)
{
override
suspend
fun
getByRoomId
(
roomId
:
String
):
List
<
Message
>
=
withContext
(
Dispatchers
.
IO
)
{
// FIXME - investigate how to avoid this distinctBy here, since DAO is returning a lot of
// FIXME - investigate how to avoid this distinctBy here, since DAO is returning a lot of
// duplicate rows (something related to our JOINS and relations on Room)
// duplicate rows (something related to our JOINS and relations on Room)
retryDB
(
"getMessagesByRoomId($roomId)"
)
{
retryDB
(
"getMessagesByRoomId($roomId)"
)
{
dbManager
.
messageDao
().
getMessagesByRoomId
(
roomId
)
dbManager
.
messageDao
().
getMessagesByRoomId
(
roomId
)
.
distinctBy
{
it
.
message
.
message
.
id
}
.
distinctBy
{
it
.
message
.
message
.
id
}
.
let
{
messages
->
.
let
{
messages
->
mapper
.
map
(
messages
)
mapper
.
map
(
messages
)
}
}
}
}
}
}
override
suspend
fun
getRecentMessages
(
roomId
:
String
,
count
:
Long
):
List
<
Message
>
=
withContext
(
CommonPool
)
{
override
suspend
fun
getRecentMessages
(
roomId
:
String
,
count
:
Long
):
List
<
Message
>
=
retryDB
(
"getRecentMessagesByRoomId($roomId, $count)"
)
{
withContext
(
Dispatchers
.
IO
)
{
dbManager
.
messageDao
().
getRecentMessagesByRoomId
(
roomId
,
count
)
retryDB
(
"getRecentMessagesByRoomId($roomId, $count)"
)
{
dbManager
.
messageDao
().
getRecentMessagesByRoomId
(
roomId
,
count
)
.
distinctBy
{
it
.
message
.
message
.
id
}
.
distinctBy
{
it
.
message
.
message
.
id
}
.
let
{
messages
->
.
let
{
messages
->
mapper
.
map
(
messages
)
mapper
.
map
(
messages
)
}
}
}
}
}
}
override
suspend
fun
save
(
message
:
Message
)
{
override
suspend
fun
save
(
message
:
Message
)
{
dbManager
.
processMessagesBatch
(
listOf
(
message
)).
join
()
dbManager
.
processMessagesBatch
(
listOf
(
message
)).
join
()
...
@@ -51,24 +52,24 @@ class DatabaseMessagesRepository(
...
@@ -51,24 +52,24 @@ class DatabaseMessagesRepository(
}
}
override
suspend
fun
removeById
(
id
:
String
)
{
override
suspend
fun
removeById
(
id
:
String
)
{
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
retryDB
(
"delete($id)"
)
{
dbManager
.
messageDao
().
delete
(
id
)
}
retryDB
(
"delete($id)"
)
{
dbManager
.
messageDao
().
delete
(
id
)
}
}
}
}
}
override
suspend
fun
removeByRoomId
(
roomId
:
String
)
{
override
suspend
fun
removeByRoomId
(
roomId
:
String
)
{
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
retryDB
(
"deleteByRoomId($roomId)"
)
{
retryDB
(
"deleteByRoomId($roomId)"
)
{
dbManager
.
messageDao
().
deleteByRoomId
(
roomId
)
dbManager
.
messageDao
().
deleteByRoomId
(
roomId
)
}
}
}
}
}
}
override
suspend
fun
getAllUnsent
():
List
<
Message
>
=
withContext
(
CommonPool
)
{
override
suspend
fun
getAllUnsent
():
List
<
Message
>
=
withContext
(
Dispatchers
.
IO
)
{
retryDB
(
"getUnsentMessages"
)
{
retryDB
(
"getUnsentMessages"
)
{
dbManager
.
messageDao
().
getUnsentMessages
()
dbManager
.
messageDao
().
getUnsentMessages
()
.
distinctBy
{
it
.
message
.
message
.
id
}
.
distinctBy
{
it
.
message
.
message
.
id
}
.
let
{
mapper
.
map
(
it
)
}
.
let
{
mapper
.
map
(
it
)
}
}
}
}
}
...
@@ -76,7 +77,7 @@ class DatabaseMessagesRepository(
...
@@ -76,7 +77,7 @@ class DatabaseMessagesRepository(
dbManager
.
sendOperation
(
Operation
.
SaveLastSync
(
MessagesSync
(
roomId
,
timeMillis
)))
dbManager
.
sendOperation
(
Operation
.
SaveLastSync
(
MessagesSync
(
roomId
,
timeMillis
)))
}
}
override
suspend
fun
getLastSyncDate
(
roomId
:
String
):
Long
?
=
withContext
(
CommonPool
)
{
override
suspend
fun
getLastSyncDate
(
roomId
:
String
):
Long
?
=
withContext
(
Dispatchers
.
IO
)
{
retryDB
(
"getLastSync($roomId)"
)
{
retryDB
(
"getLastSync($roomId)"
)
{
dbManager
.
messageDao
().
getLastSync
(
roomId
)
?.
let
{
it
.
timestamp
}
dbManager
.
messageDao
().
getLastSync
(
roomId
)
?.
let
{
it
.
timestamp
}
}
}
...
...
app/src/main/java/chat/rocket/android/server/presentation/CheckServerPresenter.kt
View file @
f4a743d4
...
@@ -45,10 +45,10 @@ import chat.rocket.core.internal.rest.serverInfo
...
@@ -45,10 +45,10 @@ import chat.rocket.core.internal.rest.serverInfo
import
chat.rocket.core.internal.rest.settingsOauth
import
chat.rocket.core.internal.rest.settingsOauth
import
chat.rocket.core.internal.rest.unregisterPushToken
import
chat.rocket.core.internal.rest.unregisterPushToken
import
chat.rocket.core.model.Myself
import
chat.rocket.core.model.Myself
import
kotlinx.coroutines.
experimental.CommonPool
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.
experimental.
channels.Channel
import
kotlinx.coroutines.channels.Channel
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
import
timber.log.Timber
import
timber.log.Timber
private
const
val
SERVICE_NAME_FACEBOOK
=
"facebook"
private
const
val
SERVICE_NAME_FACEBOOK
=
"facebook"
...
@@ -220,7 +220,7 @@ abstract class CheckServerPresenter constructor(
...
@@ -220,7 +220,7 @@ abstract class CheckServerPresenter constructor(
}
}
removeAccountInteractor
?.
remove
(
currentServer
)
removeAccountInteractor
?.
remove
(
currentServer
)
tokenRepository
?.
remove
(
currentServer
)
tokenRepository
?.
remove
(
currentServer
)
withContext
(
CommonPool
)
{
dbManager
.
logout
()
}
withContext
(
Dispatchers
.
IO
)
{
dbManager
.
logout
()
}
navigator
?.
switchOrAddNewServer
()
navigator
?.
switchOrAddNewServer
()
}
catch
(
ex
:
Exception
)
{
}
catch
(
ex
:
Exception
)
{
Timber
.
e
(
ex
,
"Error cleaning up the session..."
)
Timber
.
e
(
ex
,
"Error cleaning up the session..."
)
...
...
app/src/main/java/chat/rocket/android/server/ui/ChangeServerActivity.kt
View file @
f4a743d4
...
@@ -26,7 +26,6 @@ fun Context.changeServerIntent(serverUrl: String? = null, chatRoomId: String? =
...
@@ -26,7 +26,6 @@ fun Context.changeServerIntent(serverUrl: String? = null, chatRoomId: String? =
class
ChangeServerActivity
:
AppCompatActivity
(),
ChangeServerView
{
class
ChangeServerActivity
:
AppCompatActivity
(),
ChangeServerView
{
@Inject
lateinit
var
presenter
:
ChangeServerPresenter
@Inject
lateinit
var
presenter
:
ChangeServerPresenter
var
progress
:
ProgressDialog
?
=
null
var
progress
:
ProgressDialog
?
=
null
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
...
...
app/src/main/java/chat/rocket/android/settings/di/SettingsFragmentModule.kt
View file @
f4a743d4
...
@@ -7,7 +7,7 @@ import chat.rocket.android.settings.presentation.SettingsView
...
@@ -7,7 +7,7 @@ import chat.rocket.android.settings.presentation.SettingsView
import
chat.rocket.android.settings.ui.SettingsFragment
import
chat.rocket.android.settings.ui.SettingsFragment
import
dagger.Module
import
dagger.Module
import
dagger.Provides
import
dagger.Provides
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
@Module
@Module
class
SettingsFragmentModule
{
class
SettingsFragmentModule
{
...
...
app/src/main/java/chat/rocket/android/settings/password/di/PasswordFragmentModule.kt
View file @
f4a743d4
...
@@ -7,7 +7,7 @@ import chat.rocket.android.settings.password.presentation.PasswordView
...
@@ -7,7 +7,7 @@ import chat.rocket.android.settings.password.presentation.PasswordView
import
chat.rocket.android.settings.password.ui.PasswordFragment
import
chat.rocket.android.settings.password.ui.PasswordFragment
import
dagger.Module
import
dagger.Module
import
dagger.Provides
import
dagger.Provides
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
@Module
@Module
class
PasswordFragmentModule
{
class
PasswordFragmentModule
{
...
...
app/src/main/java/chat/rocket/android/userdetails/presentation/UserDetailsPresenter.kt
View file @
f4a743d4
...
@@ -16,8 +16,8 @@ import chat.rocket.android.util.retryIO
...
@@ -16,8 +16,8 @@ import chat.rocket.android.util.retryIO
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.util.ifNull
import
chat.rocket.common.util.ifNull
import
chat.rocket.core.internal.rest.createDirectMessage
import
chat.rocket.core.internal.rest.createDirectMessage
import
kotlinx.coroutines.
experimental.DefaultDispatcher
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
import
timber.log.Timber
import
timber.log.Timber
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -81,7 +81,7 @@ class UserDetailsPresenter @Inject constructor(
...
@@ -81,7 +81,7 @@ class UserDetailsPresenter @Inject constructor(
try
{
try
{
view
.
showLoading
()
view
.
showLoading
()
withContext
(
D
efaultDispatcher
)
{
withContext
(
D
ispatchers
.
Default
)
{
val
directMessage
=
retryIO
(
"createDirectMessage($username"
)
{
val
directMessage
=
retryIO
(
"createDirectMessage($username"
)
{
client
.
createDirectMessage
(
username
)
client
.
createDirectMessage
(
username
)
}
}
...
...
app/src/main/java/chat/rocket/android/util/IO.kt
View file @
f4a743d4
...
@@ -2,26 +2,25 @@ package chat.rocket.android.util
...
@@ -2,26 +2,25 @@ package chat.rocket.android.util
import
android.database.sqlite.SQLiteDatabaseLockedException
import
android.database.sqlite.SQLiteDatabaseLockedException
import
chat.rocket.common.RocketChatNetworkErrorException
import
chat.rocket.common.RocketChatNetworkErrorException
import
kotlinx.coroutines.experimental.TimeoutCancellationException
import
kotlinx.coroutines.delay
import
kotlinx.coroutines.experimental.delay
import
kotlinx.coroutines.isActive
import
kotlinx.coroutines.experimental.isActive
import
timber.log.Timber
import
timber.log.Timber
import
kotlin.coroutines.
experimental.
coroutineContext
import
kotlin.coroutines.coroutineContext
const
val
DEFAULT_RETRY
=
3
const
val
DEFAULT_RETRY
=
3
private
const
val
DEFAULT_DB_RETRY
=
15
private
const
val
DEFAULT_DB_RETRY
=
15
suspend
fun
<
T
>
retryIO
(
suspend
fun
<
T
>
retryIO
(
description
:
String
=
"<missing description>"
,
description
:
String
=
"<missing description>"
,
times
:
Int
=
DEFAULT_RETRY
,
times
:
Int
=
DEFAULT_RETRY
,
initialDelay
:
Long
=
100
,
// 0.1 second
initialDelay
:
Long
=
100
,
// 0.1 second
maxDelay
:
Long
=
1000
,
// 1 second
maxDelay
:
Long
=
1000
,
// 1 second
factor
:
Double
=
2.0
,
factor
:
Double
=
2.0
,
block
:
suspend
()
->
T
):
T
block
:
suspend
()
->
T
{
):
T
{
var
currentDelay
=
initialDelay
var
currentDelay
=
initialDelay
repeat
(
times
-
1
)
{
currentTry
->
repeat
(
times
-
1
)
{
currentTry
->
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled
"
)
if
(!
coroutineContext
.
isActive
)
throw
Exception
(
"Job canceled when trying to execute retryIO
"
)
try
{
try
{
return
block
()
return
block
()
}
catch
(
e
:
RocketChatNetworkErrorException
)
{
}
catch
(
e
:
RocketChatNetworkErrorException
)
{
...
@@ -29,26 +28,26 @@ suspend fun <T> retryIO(
...
@@ -29,26 +28,26 @@ suspend fun <T> retryIO(
e
.
printStackTrace
()
e
.
printStackTrace
()
}
}
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled
"
)
if
(!
coroutineContext
.
isActive
)
throw
Exception
(
"Job canceled when trying to execute retryIO
"
)
delay
(
currentDelay
)
delay
(
currentDelay
)
currentDelay
=
(
currentDelay
*
factor
).
toLong
().
coerceAtMost
(
maxDelay
)
currentDelay
=
(
currentDelay
*
factor
).
toLong
().
coerceAtMost
(
maxDelay
)
}
}
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled
"
)
if
(!
coroutineContext
.
isActive
)
throw
Exception
(
"Job canceled when trying to execute retryIO
"
)
return
block
()
// last attempt
return
block
()
// last attempt
}
}
suspend
fun
<
T
>
retryDB
(
suspend
fun
<
T
>
retryDB
(
description
:
String
=
"<missing description>"
,
description
:
String
=
"<missing description>"
,
times
:
Int
=
DEFAULT_DB_RETRY
,
times
:
Int
=
DEFAULT_DB_RETRY
,
initialDelay
:
Long
=
100
,
// 0.1 second
initialDelay
:
Long
=
100
,
// 0.1 second
maxDelay
:
Long
=
1500
,
// 1.5 second
maxDelay
:
Long
=
1500
,
// 1.5 second
factor
:
Double
=
1.2
,
factor
:
Double
=
1.2
,
block
:
suspend
()
->
T
):
T
block
:
suspend
()
->
T
{
):
T
{
var
currentDelay
=
initialDelay
var
currentDelay
=
initialDelay
repeat
(
times
-
1
)
{
currentTry
->
repeat
(
times
-
1
)
{
currentTry
->
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled
"
)
if
(!
coroutineContext
.
isActive
)
throw
Exception
(
"Job canceled when trying to execute retryDB
"
)
try
{
try
{
return
block
()
return
block
()
}
catch
(
e
:
SQLiteDatabaseLockedException
)
{
}
catch
(
e
:
SQLiteDatabaseLockedException
)
{
...
@@ -56,11 +55,11 @@ suspend fun <T> retryDB(
...
@@ -56,11 +55,11 @@ suspend fun <T> retryDB(
e
.
printStackTrace
()
e
.
printStackTrace
()
}
}
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled
"
)
if
(!
coroutineContext
.
isActive
)
throw
Exception
(
"Job canceled when trying to execute retryDB
"
)
delay
(
currentDelay
)
delay
(
currentDelay
)
currentDelay
=
(
currentDelay
*
factor
).
toLong
().
coerceAtMost
(
maxDelay
)
currentDelay
=
(
currentDelay
*
factor
).
toLong
().
coerceAtMost
(
maxDelay
)
}
}
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled
"
)
if
(!
coroutineContext
.
isActive
)
throw
Exception
(
"Job canceled when trying to execute retryDB
"
)
return
block
()
// last attempt
return
block
()
// last attempt
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/util/extensions/Fragment.kt
View file @
f4a743d4
...
@@ -3,9 +3,10 @@ package chat.rocket.android.util.extensions
...
@@ -3,9 +3,10 @@ package chat.rocket.android.util.extensions
import
android.os.Looper
import
android.os.Looper
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.FragmentActivity
import
androidx.fragment.app.FragmentActivity
import
kotlinx.coroutines.experimental.Job
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.launch
inline
fun
Fragment
.
ui
(
crossinline
block
:
(
activity
:
FragmentActivity
)
->
Unit
):
Job
?
{
inline
fun
Fragment
.
ui
(
crossinline
block
:
(
activity
:
FragmentActivity
)
->
Unit
):
Job
?
{
// Checking first for activity and view saves us from some synchronyzed and thread local checks
// Checking first for activity and view saves us from some synchronyzed and thread local checks
...
@@ -16,7 +17,7 @@ inline fun Fragment.ui(crossinline block: (activity: FragmentActivity) -> Unit):
...
@@ -16,7 +17,7 @@ inline fun Fragment.ui(crossinline block: (activity: FragmentActivity) -> Unit):
null
null
}
else
{
}
else
{
// Launch a Job on the UI context and check again if the activity and view are still valid
// Launch a Job on the UI context and check again if the activity and view are still valid
launch
(
UI
)
{
GlobalScope
.
launch
(
Dispatchers
.
Main
)
{
if
(
activity
!=
null
&&
view
!=
null
&&
context
!=
null
)
{
if
(
activity
!=
null
&&
view
!=
null
&&
context
!=
null
)
{
block
(
activity
!!
)
block
(
activity
!!
)
}
}
...
...
app/src/main/java/chat/rocket/android/util/extensions/RocketChatClient.kt
View file @
f4a743d4
...
@@ -7,15 +7,15 @@ import chat.rocket.android.util.retryIO
...
@@ -7,15 +7,15 @@ import chat.rocket.android.util.retryIO
import
chat.rocket.core.internal.rest.registerPushToken
import
chat.rocket.core.internal.rest.registerPushToken
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.asString
import
chat.rocket.core.model.asString
import
kotlinx.coroutines.
experimental.CommonPool
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
import
timber.log.Timber
import
timber.log.Timber
suspend
fun
RocketChatClientFactory
.
registerPushToken
(
suspend
fun
RocketChatClientFactory
.
registerPushToken
(
token
:
String
,
token
:
String
,
accounts
:
List
<
Account
>
accounts
:
List
<
Account
>
)
{
)
{
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
accounts
.
forEach
{
account
->
accounts
.
forEach
{
account
->
try
{
try
{
retryIO
(
description
=
"register push token: ${account.serverUrl}"
)
{
retryIO
(
description
=
"register push token: ${account.serverUrl}"
)
{
...
...
app/src/main/java/chat/rocket/android/util/livedata/TransformedLiveData.kt
View file @
f4a743d4
...
@@ -2,28 +2,28 @@ package chat.rocket.android.util.livedata
...
@@ -2,28 +2,28 @@ package chat.rocket.android.util.livedata
import
androidx.lifecycle.LiveData
import
androidx.lifecycle.LiveData
import
androidx.lifecycle.Observer
import
androidx.lifecycle.Observer
import
kotlinx.coroutines.
experimental.CommonPool
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.Job
import
kotlinx.coroutines.
GlobalScope
import
kotlinx.coroutines.
experimental.android.UI
import
kotlinx.coroutines.
Job
import
kotlinx.coroutines.
experimental.
launch
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
import
kotlin.coroutines.
experimental.
CoroutineContext
import
kotlin.coroutines.CoroutineContext
class
TransformedLiveData
<
Source
,
Output
>(
class
TransformedLiveData
<
Source
,
Output
>(
private
val
runContext
:
CoroutineContext
=
CommonPool
,
private
val
runContext
:
CoroutineContext
=
Dispatchers
.
IO
,
private
val
source
:
LiveData
<
Source
>,
private
val
source
:
LiveData
<
Source
>,
private
val
transformation
:
(
Source
?)
->
Output
?
)
private
val
transformation
:
(
Source
?)
->
Output
?
:
LiveData
<
Output
>()
{
)
:
LiveData
<
Output
>()
{
private
var
job
:
Job
?
=
null
private
var
job
:
Job
?
=
null
private
val
observer
=
Observer
<
Source
>
{
source
->
private
val
observer
=
Observer
<
Source
>
{
source
->
job
?.
cancel
()
job
?.
cancel
()
job
=
launch
(
runContext
)
{
job
=
GlobalScope
.
launch
(
runContext
)
{
transformation
(
source
)
?.
let
{
transformed
->
transformation
(
source
)
?.
let
{
transformed
->
// Could have used postValue instead, but using the UI context I can guarantee that
// Could have used postValue instead, but using the UI context I can guarantee that
// a canceled job will never emit values.
// a canceled job will never emit values.
withContext
(
UI
)
{
withContext
(
Dispatchers
.
Main
)
{
value
=
transformed
value
=
transformed
}
}
}
}
...
@@ -41,5 +41,6 @@ class TransformedLiveData<Source, Output>(
...
@@ -41,5 +41,6 @@ class TransformedLiveData<Source, Output>(
}
}
fun
<
Source
,
Output
>
LiveData
<
Source
>.
transform
(
fun
<
Source
,
Output
>
LiveData
<
Source
>.
transform
(
runContext
:
CoroutineContext
=
CommonPool
,
runContext
:
CoroutineContext
=
Dispatchers
.
IO
,
transformation
:
(
Source
?)
->
Output
?)
=
TransformedLiveData
(
runContext
,
this
,
transformation
)
transformation
:
(
Source
?)
->
Output
?
\ No newline at end of file
)
=
TransformedLiveData
(
runContext
,
this
,
transformation
)
\ No newline at end of file
app/src/main/java/chat/rocket/android/util/livedata/WrappedLiveData.kt
View file @
f4a743d4
...
@@ -3,21 +3,22 @@ package chat.rocket.android.util.livedata
...
@@ -3,21 +3,22 @@ package chat.rocket.android.util.livedata
import
androidx.lifecycle.LiveData
import
androidx.lifecycle.LiveData
import
androidx.lifecycle.MutableLiveData
import
androidx.lifecycle.MutableLiveData
import
androidx.lifecycle.Observer
import
androidx.lifecycle.Observer
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.Job
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.Job
import
kotlin.coroutines.experimental.CoroutineContext
import
kotlinx.coroutines.launch
import
kotlin.coroutines.CoroutineContext
class
WrappedLiveData
<
Source
,
Output
>(
class
WrappedLiveData
<
Source
,
Output
>(
private
val
runContext
:
CoroutineContext
=
CommonPool
,
private
val
runContext
:
CoroutineContext
=
Dispatchers
.
IO
,
private
val
source
:
LiveData
<
Source
>,
private
val
source
:
LiveData
<
Source
>,
private
val
transformation
:
suspend
(
Source
?,
MutableLiveData
<
Output
>)
->
Unit
)
private
val
transformation
:
suspend
(
Source
?,
MutableLiveData
<
Output
>)
->
Unit
:
MutableLiveData
<
Output
>()
{
)
:
MutableLiveData
<
Output
>()
{
private
var
job
:
Job
?
=
null
private
var
job
:
Job
?
=
null
private
val
observer
=
Observer
<
Source
>
{
source
->
private
val
observer
=
Observer
<
Source
>
{
source
->
job
?.
cancel
()
job
?.
cancel
()
job
=
launch
(
runContext
)
{
job
=
GlobalScope
.
launch
(
runContext
)
{
transformation
(
source
,
this
@WrappedLiveData
)
transformation
(
source
,
this
@WrappedLiveData
)
}
}
}
}
...
@@ -33,6 +34,7 @@ class WrappedLiveData<Source, Output>(
...
@@ -33,6 +34,7 @@ class WrappedLiveData<Source, Output>(
}
}
fun
<
Source
,
Output
>
LiveData
<
Source
>.
wrap
(
fun
<
Source
,
Output
>
LiveData
<
Source
>.
wrap
(
runContext
:
CoroutineContext
=
CommonPool
,
runContext
:
CoroutineContext
=
Dispatchers
.
IO
,
transformation
:
suspend
(
Source
?,
MutableLiveData
<
Output
>)
->
Unit
)
=
transformation
:
suspend
(
Source
?,
MutableLiveData
<
Output
>)
->
Unit
WrappedLiveData
(
runContext
,
this
,
transformation
)
)
=
\ No newline at end of file
WrappedLiveData
(
runContext
,
this
,
transformation
)
\ No newline at end of file
app/src/main/java/chat/rocket/android/videoconferencing/di/VideoConferencingModule.kt
0 → 100644
View file @
f4a743d4
package
chat.rocket.android.videoconferencing.di
import
androidx.lifecycle.LifecycleOwner
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.dagger.scope.PerActivity
import
chat.rocket.android.videoconferencing.presenter.VideoConferencingView
import
chat.rocket.android.videoconferencing.ui.VideoConferencingActivity
import
dagger.Module
import
dagger.Provides
import
kotlinx.coroutines.Job
@Module
class
VideoConferencingModule
{
@Provides
@PerActivity
fun
provideVideoConferencingView
(
activity
:
VideoConferencingActivity
):
VideoConferencingView
{
return
activity
}
@Provides
@PerActivity
fun
provideJob
()
=
Job
()
@Provides
@PerActivity
fun
provideLifecycleOwner
(
activity
:
VideoConferencingActivity
):
LifecycleOwner
=
activity
@Provides
@PerActivity
fun
provideCancelStrategy
(
owner
:
LifecycleOwner
,
jobs
:
Job
):
CancelStrategy
=
CancelStrategy
(
owner
,
jobs
)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/videoconferencing/presenter/VideoConferencingPresenter.kt
0 → 100644
View file @
f4a743d4
package
chat.rocket.android.videoconferencing.presenter
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.helper.JitsiHelper
import
chat.rocket.android.server.domain.*
import
chat.rocket.android.server.infraestructure.ConnectionManager
import
chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.core.RocketChatClient
import
chat.rocket.core.internal.realtime.updateJitsiTimeout
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
javax.inject.Inject
class
VideoConferencingPresenter
@Inject
constructor
(
private
val
view
:
VideoConferencingView
,
private
val
strategy
:
CancelStrategy
,
private
val
currentServerRepository
:
CurrentServerRepository
,
private
val
connectionManagerFactory
:
ConnectionManagerFactory
,
private
val
settings
:
GetSettingsInteractor
)
{
private
lateinit
var
currentServerUrl
:
String
private
lateinit
var
connectionManager
:
ConnectionManager
private
lateinit
var
client
:
RocketChatClient
private
lateinit
var
publicSettings
:
PublicSettings
private
lateinit
var
chatRoomId
:
String
fun
setup
(
chatRoomId
:
String
)
{
currentServerRepository
.
get
()
?.
let
{
currentServerUrl
=
it
connectionManager
=
connectionManagerFactory
.
create
(
it
)
client
=
connectionManager
.
client
publicSettings
=
settings
.
get
(
it
)
}
this
.
chatRoomId
=
chatRoomId
}
fun
setupVideoConferencing
()
{
launchUI
(
strategy
)
{
with
(
publicSettings
)
{
view
.
startVideoConferencing
(
JitsiHelper
.
getJitsiUrl
(
isJitsiSSL
(),
jitsiDomain
(),
jitsiPrefix
(),
uniqueIdentifier
(),
chatRoomId
)
)
}
client
.
updateJitsiTimeout
(
chatRoomId
)
}
}
private
fun
updateJitsiTimeout
()
{
GlobalScope
.
launch
(
Dispatchers
.
IO
+
strategy
.
jobs
)
{
client
.
updateJitsiTimeout
(
chatRoomId
)
}
}
}
app/src/main/java/chat/rocket/android/videoconferencing/presenter/VideoConferencingView.kt
0 → 100644
View file @
f4a743d4
package
chat.rocket.android.videoconferencing.presenter
import
java.net.URL
interface
VideoConferencingView
{
/**
* Starts the video conferencing.
*
* @param url The video conferencing URL to be loaded.
*/
fun
startVideoConferencing
(
url
:
URL
)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/videoconferencing/ui/VideoConferencingActivity.kt
0 → 100644
View file @
f4a743d4
package
chat.rocket.android.videoconferencing.ui
import
android.content.Context
import
android.content.Intent
import
android.os.Bundle
import
chat.rocket.android.videoconferencing.presenter.VideoConferencingPresenter
import
chat.rocket.android.videoconferencing.presenter.VideoConferencingView
import
dagger.android.AndroidInjection
import
org.jitsi.meet.sdk.JitsiMeetActivity
import
java.net.URL
import
javax.inject.Inject
fun
Context
.
videoConferencingIntent
(
chatRoomId
:
String
):
Intent
=
Intent
(
this
,
VideoConferencingActivity
::
class
.
java
).
putExtra
(
INTENT_CHAT_ROOM_ID
,
chatRoomId
)
private
const
val
INTENT_CHAT_ROOM_ID
=
"chat_room_id"
class
VideoConferencingActivity
:
JitsiMeetActivity
(),
VideoConferencingView
{
@Inject
lateinit
var
presenter
:
VideoConferencingPresenter
private
lateinit
var
chatRoomId
:
String
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
AndroidInjection
.
inject
(
this
)
super
.
onCreate
(
savedInstanceState
)
chatRoomId
=
intent
.
getStringExtra
(
INTENT_CHAT_ROOM_ID
)
requireNotNull
(
chatRoomId
)
{
"no chat_room_id provided in Intent extras"
}
presenter
.
setup
(
chatRoomId
)
presenter
.
setupVideoConferencing
()
}
override
fun
startVideoConferencing
(
url
:
URL
)
=
loadURL
(
url
)
}
app/src/main/java/chat/rocket/android/webview/ui/WebViewActivity.kt
View file @
f4a743d4
...
@@ -31,8 +31,8 @@ class WebViewActivity : AppCompatActivity() {
...
@@ -31,8 +31,8 @@ class WebViewActivity : AppCompatActivity() {
setContentView
(
R
.
layout
.
activity_web_view
)
setContentView
(
R
.
layout
.
activity_web_view
)
webPageUrl
=
intent
.
getStringExtra
(
INTENT_WEB_PAGE_URL
)
webPageUrl
=
intent
.
getStringExtra
(
INTENT_WEB_PAGE_URL
)
toolbarTitle
=
intent
.
getStringExtra
(
TOOLBAR_TITLE
)
requireNotNull
(
webPageUrl
)
{
"no web_page_url provided in Intent extras"
}
requireNotNull
(
webPageUrl
)
{
"no web_page_url provided in Intent extras"
}
toolbarTitle
=
intent
.
getStringExtra
(
TOOLBAR_TITLE
)
setupToolbar
()
setupToolbar
()
}
}
...
...
app/src/main/res/layout/item_message.xml
View file @
f4a743d4
...
@@ -159,6 +159,16 @@
...
@@ -159,6 +159,16 @@
app:layout_constraintTop_toBottomOf=
"@+id/message_header"
app:layout_constraintTop_toBottomOf=
"@+id/message_header"
tools:text=
"This is a multiline chat message from Bertie that will take more than just one line of text. I have sure that everything is amazing!"
/>
tools:text=
"This is a multiline chat message from Bertie that will take more than just one line of text. I have sure that everything is amazing!"
/>
<Button
android:id=
"@+id/button_join_video_call"
android:layout_width=
"200dp"
android:layout_height=
"wrap_content"
android:background=
"@color/colorAccent"
android:text=
"@string/msg_join_video_call"
android:visibility=
"gone"
app:layout_constraintStart_toStartOf=
"@+id/text_content"
app:layout_constraintTop_toBottomOf=
"@+id/text_content"
/>
<include
<include
layout=
"@layout/layout_reactions"
layout=
"@layout/layout_reactions"
android:layout_width=
"0dp"
android:layout_width=
"0dp"
...
...
app/src/main/res/values-de/strings.xml
View file @
f4a743d4
...
@@ -100,6 +100,7 @@
...
@@ -100,6 +100,7 @@
<string
name=
"msg_today"
>
Heute
</string>
<string
name=
"msg_today"
>
Heute
</string>
<string
name=
"msg_message"
>
Nachricht
</string>
<string
name=
"msg_message"
>
Nachricht
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
Dieser Raum ist nur lesen
</string>
<string
name=
"msg_this_room_is_read_only"
>
Dieser Raum ist nur lesen
</string>
<string
name=
"msg_invalid_2fa_code"
>
Falscher 2FA Code
</string>
<string
name=
"msg_invalid_2fa_code"
>
Falscher 2FA Code
</string>
<string
name=
"msg_invalid_file"
>
Falsche Datei
</string>
<string
name=
"msg_invalid_file"
>
Falsche Datei
</string>
...
...
app/src/main/res/values-es/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_today"
>
Hoy
</string>
<string
name=
"msg_today"
>
Hoy
</string>
<string
name=
"msg_message"
>
Mensaje
</string>
<string
name=
"msg_message"
>
Mensaje
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
Esta sala es de solo lectura
</string>
<string
name=
"msg_this_room_is_read_only"
>
Esta sala es de solo lectura
</string>
<string
name=
"msg_invalid_2fa_code"
>
Código 2FA no válido
</string>
<string
name=
"msg_invalid_2fa_code"
>
Código 2FA no válido
</string>
<string
name=
"msg_invalid_file"
>
Archivo inválido
</string>
<string
name=
"msg_invalid_file"
>
Archivo inválido
</string>
...
...
app/src/main/res/values-fa/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_today"
>
امروز
</string>
<string
name=
"msg_today"
>
امروز
</string>
<string
name=
"msg_message"
>
پیام
</string>
<string
name=
"msg_message"
>
پیام
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
این اتاق فقط خواندنی است
</string>
<string
name=
"msg_this_room_is_read_only"
>
این اتاق فقط خواندنی است
</string>
<string
name=
"msg_invalid_2fa_code"
>
Invalid 2FA Code
</string>
<!-- TODO Add translation -->
<string
name=
"msg_invalid_2fa_code"
>
Invalid 2FA Code
</string>
<!-- TODO Add translation -->
<string
name=
"msg_invalid_file"
>
پروندهی نامعتبر
</string>
<string
name=
"msg_invalid_file"
>
پروندهی نامعتبر
</string>
...
...
app/src/main/res/values-fr/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_today"
>
Aujourd\'hui
</string>
<string
name=
"msg_today"
>
Aujourd\'hui
</string>
<string
name=
"msg_message"
>
Message
</string>
<string
name=
"msg_message"
>
Message
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
Ce salon est en lecture seule
</string>
<string
name=
"msg_this_room_is_read_only"
>
Ce salon est en lecture seule
</string>
<string
name=
"msg_invalid_2fa_code"
>
Code 2FA non valide
</string>
<string
name=
"msg_invalid_2fa_code"
>
Code 2FA non valide
</string>
<string
name=
"msg_invalid_file"
>
Fichier non valide
</string>
<string
name=
"msg_invalid_file"
>
Fichier non valide
</string>
...
...
app/src/main/res/values-hi-rIN/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_today"
>
आज
</string>
<string
name=
"msg_today"
>
आज
</string>
<string
name=
"msg_message"
>
संदेश
</string>
<string
name=
"msg_message"
>
संदेश
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
यह रूम केवल पढ़ने के लिए है
</string>
<string
name=
"msg_this_room_is_read_only"
>
यह रूम केवल पढ़ने के लिए है
</string>
<string
name=
"msg_invalid_2fa_code"
>
अमान्य 2FA कोड
</string>
<string
name=
"msg_invalid_2fa_code"
>
अमान्य 2FA कोड
</string>
<string
name=
"msg_invalid_file"
>
अवैध फाइल
</string>
<string
name=
"msg_invalid_file"
>
अवैध फाइल
</string>
...
...
app/src/main/res/values-it/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_today"
>
Oggi
</string>
<string
name=
"msg_today"
>
Oggi
</string>
<string
name=
"msg_message"
>
Messaggio
</string>
<string
name=
"msg_message"
>
Messaggio
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
Questa stanza è di sola lettura
</string>
<string
name=
"msg_this_room_is_read_only"
>
Questa stanza è di sola lettura
</string>
<string
name=
"msg_invalid_2fa_code"
>
Invalido Codice 2FA non valido
</string>
<string
name=
"msg_invalid_2fa_code"
>
Invalido Codice 2FA non valido
</string>
<string
name=
"msg_invalid_file"
>
Documento non valido
</string>
<string
name=
"msg_invalid_file"
>
Documento non valido
</string>
...
...
app/src/main/res/values-ja/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_yesterday"
>
昨日
</string>
<string
name=
"msg_yesterday"
>
昨日
</string>
<string
name=
"msg_message"
>
メッセージ
</string>
<string
name=
"msg_message"
>
メッセージ
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
この部屋は読み取り専用です
</string>
<string
name=
"msg_this_room_is_read_only"
>
この部屋は読み取り専用です
</string>
<string
name=
"msg_invalid_2fa_code"
>
無効な 2FA コード
</string>
<string
name=
"msg_invalid_2fa_code"
>
無効な 2FA コード
</string>
<string
name=
"msg_invalid_file"
>
無効なファイル
</string>
<string
name=
"msg_invalid_file"
>
無効なファイル
</string>
...
...
app/src/main/res/values-pt-rBR/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_today"
>
Hoje
</string>
<string
name=
"msg_today"
>
Hoje
</string>
<string
name=
"msg_message"
>
Mensagem
</string>
<string
name=
"msg_message"
>
Mensagem
</string>
<string
name=
"msg_video_call"
>
Videochamada
</string>
<string
name=
"msg_video_call"
>
Videochamada
</string>
<string
name=
"msg_join_video_call"
>
Entrar na videochamada
</string>
<string
name=
"msg_this_room_is_read_only"
>
Este chat é apenas de leitura
</string>
<string
name=
"msg_this_room_is_read_only"
>
Este chat é apenas de leitura
</string>
<string
name=
"msg_invalid_2fa_code"
>
Código 2FA inválido
</string>
<string
name=
"msg_invalid_2fa_code"
>
Código 2FA inválido
</string>
<string
name=
"msg_invalid_file"
>
Arquivo inválido
</string>
<string
name=
"msg_invalid_file"
>
Arquivo inválido
</string>
...
...
app/src/main/res/values-ru-rRU/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_today"
>
Сегодня
</string>
<string
name=
"msg_today"
>
Сегодня
</string>
<string
name=
"msg_message"
>
Сообщение
</string>
<string
name=
"msg_message"
>
Сообщение
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
Канал только для чтения
</string>
<string
name=
"msg_this_room_is_read_only"
>
Канал только для чтения
</string>
<string
name=
"msg_invalid_2fa_code"
>
Неверный код 2FA
</string>
<string
name=
"msg_invalid_2fa_code"
>
Неверный код 2FA
</string>
<string
name=
"msg_invalid_file"
>
Неверный файл
</string>
<string
name=
"msg_invalid_file"
>
Неверный файл
</string>
...
...
app/src/main/res/values-tr/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_today"
>
Bugün
</string>
<string
name=
"msg_today"
>
Bugün
</string>
<string
name=
"msg_message"
>
Mesaj
</string>
<string
name=
"msg_message"
>
Mesaj
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
Bu oda sadece okunabilir modundadır
</string>
<string
name=
"msg_this_room_is_read_only"
>
Bu oda sadece okunabilir modundadır
</string>
<string
name=
"msg_invalid_2fa_code"
>
Geçersiz 2FA Kodu
</string>
<string
name=
"msg_invalid_2fa_code"
>
Geçersiz 2FA Kodu
</string>
<string
name=
"msg_invalid_file"
>
Geçersiz dosya
</string>
<string
name=
"msg_invalid_file"
>
Geçersiz dosya
</string>
...
...
app/src/main/res/values-uk/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_today"
>
Сьогодні
</string>
<string
name=
"msg_today"
>
Сьогодні
</string>
<string
name=
"msg_message"
>
Повідомлення
</string>
<string
name=
"msg_message"
>
Повідомлення
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
Канал тільки для читання
</string>
<string
name=
"msg_this_room_is_read_only"
>
Канал тільки для читання
</string>
<string
name=
"msg_invalid_2fa_code"
>
Неправильний код 2FA
</string>
<string
name=
"msg_invalid_2fa_code"
>
Неправильний код 2FA
</string>
<string
name=
"msg_invalid_file"
>
Неправильний файл
</string>
<string
name=
"msg_invalid_file"
>
Неправильний файл
</string>
...
...
app/src/main/res/values-zh-rCN/strings.xml
View file @
f4a743d4
...
@@ -97,6 +97,7 @@
...
@@ -97,6 +97,7 @@
<string
name=
"msg_today"
>
今天
</string>
<string
name=
"msg_today"
>
今天
</string>
<string
name=
"msg_message"
>
消息
</string>
<string
name=
"msg_message"
>
消息
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_video_call"
>
Video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<!-- TODO Add translation -->
<string
name=
"msg_this_room_is_read_only"
>
这个频道只读
</string>
<string
name=
"msg_this_room_is_read_only"
>
这个频道只读
</string>
<string
name=
"msg_invalid_2fa_code"
>
无效的2FA码
</string>
<string
name=
"msg_invalid_2fa_code"
>
无效的2FA码
</string>
<string
name=
"msg_invalid_file"
>
无效文件
</string>
<string
name=
"msg_invalid_file"
>
无效文件
</string>
...
...
app/src/main/res/values/strings.xml
View file @
f4a743d4
...
@@ -110,6 +110,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
...
@@ -110,6 +110,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string
name=
"msg_today"
>
Today
</string>
<string
name=
"msg_today"
>
Today
</string>
<string
name=
"msg_message"
>
Message
</string>
<string
name=
"msg_message"
>
Message
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<string
name=
"msg_video_call"
>
Video call
</string>
<string
name=
"msg_join_video_call"
>
Join video call
</string>
<string
name=
"msg_this_room_is_read_only"
>
This room is read only
</string>
<string
name=
"msg_this_room_is_read_only"
>
This room is read only
</string>
<string
name=
"msg_invalid_2fa_code"
>
Invalid 2FA Code
</string>
<string
name=
"msg_invalid_2fa_code"
>
Invalid 2FA Code
</string>
<string
name=
"msg_invalid_file"
>
Invalid file
</string>
<string
name=
"msg_invalid_file"
>
Invalid file
</string>
...
...
app/src/play/java/chat/rocket/android/extensions/GooglePlayServices.kt
View file @
f4a743d4
package
chat.rocket.android.extensions
package
chat.rocket.android.extensions
import
com.google.android.gms.tasks.Task
import
com.google.android.gms.tasks.Task
import
kotlin.coroutines.experimental.suspendCoroutine
import
kotlin.coroutines.resume
import
kotlin.coroutines.resumeWithException
import
kotlin.coroutines.suspendCoroutine
@JvmName
(
"awaitVoid"
)
@JvmName
(
"awaitVoid"
)
suspend
fun
Task
<
Void
>.
await
()
=
suspendCoroutine
<
Unit
>
{
continuation
->
suspend
fun
Task
<
Void
>.
await
()
=
suspendCoroutine
<
Unit
>
{
continuation
->
...
...
app/src/play/java/chat/rocket/android/helper/SmartLockHelper.kt
View file @
f4a743d4
...
@@ -45,7 +45,7 @@ object SmartLockHelper {
...
@@ -45,7 +45,7 @@ object SmartLockHelper {
.
addOnCompleteListener
{
.
addOnCompleteListener
{
when
{
when
{
it
.
isSuccessful
->
{
it
.
isSuccessful
->
{
credential
=
it
.
result
.
credential
credential
=
it
.
result
?
.
credential
}
}
it
.
exception
is
ResolvableApiException
->
{
it
.
exception
is
ResolvableApiException
->
{
val
resolvableApiException
=
(
it
.
exception
as
ResolvableApiException
)
val
resolvableApiException
=
(
it
.
exception
as
ResolvableApiException
)
...
...
app/src/play/java/chat/rocket/android/infrastructure/CrashlyticsWrapper.kt
View file @
f4a743d4
...
@@ -7,16 +7,22 @@ import chat.rocket.android.server.domain.GetCurrentServerInteractor
...
@@ -7,16 +7,22 @@ import chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.domain.GetSettingsInteractor
import
chat.rocket.android.server.domain.GetSettingsInteractor
import
chat.rocket.android.server.domain.SITE_URL
import
chat.rocket.android.server.domain.SITE_URL
import
com.crashlytics.android.Crashlytics
import
com.crashlytics.android.Crashlytics
import
kotlinx.coroutines.
experimental.
runBlocking
import
kotlinx.coroutines.runBlocking
fun
installCrashlyticsWrapper
(
context
:
Application
,
fun
installCrashlyticsWrapper
(
currentServerInteractor
:
GetCurrentServerInteractor
,
context
:
Application
,
settingsInteractor
:
GetSettingsInteractor
,
currentServerInteractor
:
GetCurrentServerInteractor
,
accountRepository
:
AccountsRepository
,
settingsInteractor
:
GetSettingsInteractor
,
localRepository
:
LocalRepository
)
{
accountRepository
:
AccountsRepository
,
localRepository
:
LocalRepository
)
{
if
(
isCrashlyticsEnabled
())
{
if
(
isCrashlyticsEnabled
())
{
Thread
.
setDefaultUncaughtExceptionHandler
(
RocketChatUncaughtExceptionHandler
(
currentServerInteractor
,
Thread
.
setDefaultUncaughtExceptionHandler
(
settingsInteractor
,
accountRepository
,
localRepository
))
RocketChatUncaughtExceptionHandler
(
currentServerInteractor
,
settingsInteractor
,
accountRepository
,
localRepository
)
)
}
}
}
}
...
@@ -25,13 +31,14 @@ private fun isCrashlyticsEnabled(): Boolean {
...
@@ -25,13 +31,14 @@ private fun isCrashlyticsEnabled(): Boolean {
}
}
private
class
RocketChatUncaughtExceptionHandler
(
private
class
RocketChatUncaughtExceptionHandler
(
val
currentServerInteractor
:
GetCurrentServerInteractor
,
val
currentServerInteractor
:
GetCurrentServerInteractor
,
val
settingsInteractor
:
GetSettingsInteractor
,
val
settingsInteractor
:
GetSettingsInteractor
,
val
accountRepository
:
AccountsRepository
,
val
accountRepository
:
AccountsRepository
,
val
localRepository
:
LocalRepository
)
val
localRepository
:
LocalRepository
:
Thread
.
UncaughtExceptionHandler
{
)
:
Thread
.
UncaughtExceptionHandler
{
val
crashlyticsHandler
:
Thread
.
UncaughtExceptionHandler
?
=
Thread
.
getDefaultUncaughtExceptionHandler
()
val
crashlyticsHandler
:
Thread
.
UncaughtExceptionHandler
?
=
Thread
.
getDefaultUncaughtExceptionHandler
()
override
fun
uncaughtException
(
t
:
Thread
,
e
:
Throwable
)
{
override
fun
uncaughtException
(
t
:
Thread
,
e
:
Throwable
)
{
val
currentServer
=
currentServerInteractor
.
get
()
?:
"<unknown>"
val
currentServer
=
currentServerInteractor
.
get
()
?:
"<unknown>"
...
...
app/src/play/java/chat/rocket/android/push/worker/TokenRegistrationWorker.kt
View file @
f4a743d4
...
@@ -9,7 +9,7 @@ import chat.rocket.android.server.infraestructure.RocketChatClientFactory
...
@@ -9,7 +9,7 @@ import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.extensions.registerPushToken
import
chat.rocket.android.util.extensions.registerPushToken
import
chat.rocket.common.util.ifNull
import
chat.rocket.common.util.ifNull
import
com.google.firebase.iid.FirebaseInstanceId
import
com.google.firebase.iid.FirebaseInstanceId
import
kotlinx.coroutines.
experimental.
runBlocking
import
kotlinx.coroutines.runBlocking
import
timber.log.Timber
import
timber.log.Timber
import
javax.inject.Inject
import
javax.inject.Inject
...
...
build.gradle
View file @
f4a743d4
...
@@ -10,12 +10,11 @@ buildscript {
...
@@ -10,12 +10,11 @@ buildscript {
}
}
dependencies
{
dependencies
{
classpath
'com.android.tools.build:gradle:3.
2.1
'
classpath
'com.android.tools.build:gradle:3.
3.2
'
classpath
"org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
classpath
"org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
classpath
"org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}"
classpath
"org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}"
classpath
'com.google.gms:google-services:4.1.0'
classpath
'com.google.gms:google-services:4.2.0'
classpath
'io.fabric.tools:gradle:1.25.4'
classpath
'io.fabric.tools:gradle:1.26.1'
classpath
"com.github.ben-manes:gradle-versions-plugin:0.20.0"
classpath
"com.github.ben-manes:gradle-versions-plugin:0.20.0"
}
}
}
}
...
@@ -26,6 +25,7 @@ allprojects {
...
@@ -26,6 +25,7 @@ allprojects {
jcenter
()
jcenter
()
maven
{
url
"https://oss.sonatype.org/content/repositories/snapshots/"
}
maven
{
url
"https://oss.sonatype.org/content/repositories/snapshots/"
}
maven
{
url
"https://jitpack.io"
}
maven
{
url
"https://jitpack.io"
}
maven
{
url
"https://github.com/jitsi/jitsi-maven-repository/raw/master/releases"
}
}
}
apply
from:
rootProject
.
file
(
'dependencies.gradle'
)
apply
from:
rootProject
.
file
(
'dependencies.gradle'
)
...
...
core/build.gradle
View file @
f4a743d4
...
@@ -29,7 +29,7 @@ dependencies {
...
@@ -29,7 +29,7 @@ dependencies {
implementation
fileTree
(
dir:
'libs'
,
include:
[
'*.jar'
])
implementation
fileTree
(
dir:
'libs'
,
include:
[
'*.jar'
])
implementation
libraries
.
kotlin
implementation
libraries
.
kotlin
implementation
libraries
.
coroutines
implementation
libraries
.
coroutines
Core
implementation
libraries
.
lifecycleExtensions
implementation
libraries
.
lifecycleExtensions
kapt
libraries
.
lifecycleCompiler
kapt
libraries
.
lifecycleCompiler
...
...
core/src/main/java/chat/rocket/android/core/lifecycle/CancelStrategy.kt
View file @
f4a743d4
...
@@ -4,7 +4,7 @@ import androidx.lifecycle.Lifecycle
...
@@ -4,7 +4,7 @@ import androidx.lifecycle.Lifecycle
import
androidx.lifecycle.LifecycleObserver
import
androidx.lifecycle.LifecycleObserver
import
androidx.lifecycle.LifecycleOwner
import
androidx.lifecycle.LifecycleOwner
import
androidx.lifecycle.OnLifecycleEvent
import
androidx.lifecycle.OnLifecycleEvent
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
class
CancelStrategy
(
owner
:
LifecycleOwner
,
val
jobs
:
Job
)
:
LifecycleObserver
{
class
CancelStrategy
(
owner
:
LifecycleOwner
,
val
jobs
:
Job
)
:
LifecycleObserver
{
...
...
dependencies.gradle
View file @
f4a743d4
...
@@ -2,17 +2,17 @@ ext {
...
@@ -2,17 +2,17 @@ ext {
versions
=
[
versions
=
[
// For project configuration
// For project configuration
java
:
JavaVersion
.
VERSION_1_8
,
java
:
JavaVersion
.
VERSION_1_8
,
minSdk
:
21
,
compileSdk
:
28
,
compileSdk
:
28
,
targetSdk
:
28
,
targetSdk
:
28
,
minSdk
:
21
,
buildTools
:
'28.0.3'
,
buildTools
:
'28.0.3'
,
dokka
:
'0.9.16'
,
dokka
:
'0.9.16'
,
// For app
// For app
kotlin
:
'1.
2.7
1'
,
kotlin
:
'1.
3.2
1'
,
coroutine
:
'
0.25.0
'
,
coroutine
:
'
1.1.1
'
,
appCompat
:
'1.0.
0
'
,
appCompat
:
'1.0.
2
'
,
recyclerview
:
'1.0.0'
,
recyclerview
:
'1.0.0'
,
constraintLayout
:
'2.0.0-alpha2'
,
constraintLayout
:
'2.0.0-alpha2'
,
cardview
:
'1.0.0'
,
cardview
:
'1.0.0'
,
...
@@ -21,9 +21,9 @@ ext {
...
@@ -21,9 +21,9 @@ ext {
workmanager
:
'1.0.0-alpha09'
,
workmanager
:
'1.0.0-alpha09'
,
dagger
:
'2.16'
,
dagger
:
'2.16'
,
firebaseCloudMessage
:
'17.3.
0
'
,
firebaseCloudMessage
:
'17.3.
4
'
,
firebaseAnalytics
:
'16.0.
3
'
,
firebaseAnalytics
:
'16.0.
6
'
,
playServices
:
'16.0.0
'
,
playServices
Auth
:
'16.0.1
'
,
exoPlayer
:
'2.8.2'
,
exoPlayer
:
'2.8.2'
,
flexbox
:
'1.1.0'
,
flexbox
:
'1.1.0'
,
material
:
'1.0.0'
,
material
:
'1.0.0'
,
...
@@ -36,8 +36,8 @@ ext {
...
@@ -36,8 +36,8 @@ ext {
rxKotlin
:
'2.3.0'
,
rxKotlin
:
'2.3.0'
,
rxAndroid
:
'2.1.0'
,
rxAndroid
:
'2.1.0'
,
moshi
:
'1.
6
.0'
,
moshi
:
'1.
8
.0'
,
okhttp
:
'3.1
1.0
'
,
okhttp
:
'3.1
2.1
'
,
timber
:
'4.7.1'
,
timber
:
'4.7.1'
,
threeTenABP
:
'1.1.0'
,
threeTenABP
:
'1.1.0'
,
...
@@ -45,18 +45,18 @@ ext {
...
@@ -45,18 +45,18 @@ ext {
fresco
:
'1.10.0'
,
fresco
:
'1.10.0'
,
kotshi
:
'1.0.
4
'
,
kotshi
:
'1.0.
6
'
,
frescoImageViewer
:
'0.5.1'
,
frescoImageViewer
:
'0.5.1'
,
markwon
:
'2.0.0'
,
markwon
:
'2.0.0'
,
aVLoadingIndicatorView:
'2.1.3'
,
aVLoadingIndicatorView:
'2.1.3'
,
glide
:
'4.8.0'
,
glide
:
'4.8.0'
,
glideTransformations
:
'4.0.0'
,
glideTransformations
:
'4.0.0'
,
// For wearable
jitsi
:
'+'
,
// TODO Avoid using + (https://github.com/jitsi/jitsi-meet/issues/3987)
wear
:
'2.3.0'
,
playServicesWearable
:
'15.0.1'
,
supportWearable
:
'27.1.1'
,
// For testing
// For testing
junit
:
'4.12'
,
junit
:
'4.12'
,
...
@@ -66,7 +66,7 @@ ext {
...
@@ -66,7 +66,7 @@ ext {
]
]
libraries
=
[
libraries
=
[
kotlin
:
"org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}"
,
kotlin
:
"org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}"
,
coroutines
:
"org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutine}"
,
coroutines
Core
:
"org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutine}"
,
coroutinesAndroid
:
"org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.coroutine}"
,
coroutinesAndroid
:
"org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.coroutine}"
,
appCompat
:
"androidx.appcompat:appcompat:${versions.appCompat}"
,
appCompat
:
"androidx.appcompat:appcompat:${versions.appCompat}"
,
...
@@ -117,26 +117,20 @@ ext {
...
@@ -117,26 +117,20 @@ ext {
kotshiCompiler
:
"se.ansman.kotshi:compiler:${versions.kotshi}"
,
kotshiCompiler
:
"se.ansman.kotshi:compiler:${versions.kotshi}"
,
frescoImageViewer
:
"com.github.luciofm:FrescoImageViewer:${versions.frescoImageViewer}"
,
frescoImageViewer
:
"com.github.luciofm:FrescoImageViewer:${versions.frescoImageViewer}"
,
glide
:
"com.github.bumptech.glide:glide:${versions.glide}"
,
glideProcessor
:
"com.github.bumptech.glide:compiler:${versions.glide}"
,
glideTransformations
:
"jp.wasabeef:glide-transformations:${versions.glideTransformations}"
,
markwon
:
"ru.noties:markwon:${versions.markwon}"
,
markwon
:
"ru.noties:markwon:${versions.markwon}"
,
aVLoadingIndicatorView:
"com.wang.avi:library:${versions.aVLoadingIndicatorView}"
,
aVLoadingIndicatorView:
"com.wang.avi:library:${versions.aVLoadingIndicatorView}"
,
glide
:
"com.github.bumptech.glide:glide:${versions.glide}"
,
glideTransformations
:
"jp.wasabeef:glide-transformations:${versions.glideTransformations}"
,
jitsi
:
"org.jitsi.react:jitsi-meet-sdk:${versions.jitsi}"
,
// Proprietary libraries
// Proprietary libraries
fcm
:
"com.google.firebase:firebase-messaging:${versions.firebaseCloudMessage}"
,
fcm
:
"com.google.firebase:firebase-messaging:${versions.firebaseCloudMessage}"
,
firebaseAnalytics
:
"com.google.firebase:firebase-core:${versions.firebaseAnalytics}"
,
firebaseAnalytics
:
"com.google.firebase:firebase-core:${versions.firebaseAnalytics}"
,
playServicesAuth
:
"com.google.android.gms:play-services-auth:${versions.playServices}"
,
playServicesAuth
:
"com.google.android.gms:play-services-auth:${versions.playServicesAuth}"
,
// For wearable
wearable
:
"com.google.android.support:wearable:${versions.wear}"
,
playServicesWearable
:
"com.google.android.gms:play-services-wearable:${versions.playServicesWearable}"
,
percentLayout
:
"com.android.support:percent:${versions.supportWearable}"
,
supportWearable
:
"com.android.support:support-v4:${versions.supportWearable}"
,
wearableRecyclerView
:
"com.android.support:recyclerview-v7:${versions.supportWearable}"
,
wearSupport
:
"com.android.support:wear:${versions.supportWearable}"
,
// For testing
// For testing
junit
:
"junit:junit:${versions.junit}"
,
junit
:
"junit:junit:${versions.junit}"
,
...
...
draw/build.gradle
View file @
f4a743d4
...
@@ -51,7 +51,7 @@ dependencies {
...
@@ -51,7 +51,7 @@ dependencies {
implementation
project
(
':util'
)
implementation
project
(
':util'
)
implementation
libraries
.
kotlin
implementation
libraries
.
kotlin
implementation
libraries
.
coroutines
implementation
libraries
.
coroutines
Core
implementation
libraries
.
appCompat
implementation
libraries
.
appCompat
implementation
libraries
.
constraintlayout
implementation
libraries
.
constraintlayout
...
...
draw/src/main/java/chat/rocket/android/draw/main/di/DrawModule.kt
View file @
f4a743d4
...
@@ -6,7 +6,7 @@ import chat.rocket.android.draw.main.presenter.DrawView
...
@@ -6,7 +6,7 @@ import chat.rocket.android.draw.main.presenter.DrawView
import
chat.rocket.android.draw.main.ui.DrawingActivity
import
chat.rocket.android.draw.main.ui.DrawingActivity
import
dagger.Module
import
dagger.Module
import
dagger.Provides
import
dagger.Provides
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
@Module
@Module
class
DrawModule
{
class
DrawModule
{
...
...
emoji/build.gradle
View file @
f4a743d4
...
@@ -5,14 +5,13 @@ apply plugin: 'kotlin-kapt'
...
@@ -5,14 +5,13 @@ apply plugin: 'kotlin-kapt'
android
{
android
{
compileSdkVersion
versions
.
compileSdk
compileSdkVersion
versions
.
compileSdk
buildToolsVersion
'28.0.3'
buildToolsVersion
versions
.
buildTools
defaultConfig
{
defaultConfig
{
minSdkVersion
versions
.
minSdk
minSdkVersion
versions
.
minSdk
targetSdkVersion
versions
.
targetSdk
targetSdkVersion
versions
.
targetSdk
versionCode
1
versionCode
1
versionName
"0.1"
versionName
"0.1"
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
javaCompileOptions
{
javaCompileOptions
{
...
@@ -28,28 +27,24 @@ android {
...
@@ -28,28 +27,24 @@ android {
proguardFiles
getDefaultProguardFile
(
'proguard-android.txt'
),
'proguard-rules.pro'
proguardFiles
getDefaultProguardFile
(
'proguard-android.txt'
),
'proguard-rules.pro'
}
}
}
}
}
}
dependencies
{
dependencies
{
implementation
libraries
.
androidKtx
implementation
libraries
.
appCompat
implementation
libraries
.
kotlin
implementation
libraries
.
kotlin
implementation
libraries
.
coroutines
implementation
libraries
.
coroutines
Core
implementation
libraries
.
coroutinesAndroid
implementation
libraries
.
coroutinesAndroid
implementation
libraries
.
constraintlayout
implementation
libraries
.
appCompat
implementation
libraries
.
recyclerview
implementation
libraries
.
recyclerview
implementation
libraries
.
constraintlayout
implementation
libraries
.
androidKtx
implementation
libraries
.
material
implementation
libraries
.
material
implementation
libraries
.
glide
kapt
libraries
.
glideProcessor
implementation
libraries
.
room
implementation
libraries
.
room
kapt
libraries
.
roomProcessor
kapt
libraries
.
roomProcessor
}
kotlin
{
implementation
libraries
.
glide
experimental
{
coroutines
"enable"
}
}
}
androidExtensions
{
androidExtensions
{
...
...
emoji/src/main/java/chat/rocket/android/emoji/EmojiKeyboardPopup.kt
View file @
f4a743d4
...
@@ -22,8 +22,9 @@ import chat.rocket.android.emoji.internal.EmojiPagerAdapter
...
@@ -22,8 +22,9 @@ import chat.rocket.android.emoji.internal.EmojiPagerAdapter
import
chat.rocket.android.emoji.internal.PREF_EMOJI_SKIN_TONE
import
chat.rocket.android.emoji.internal.PREF_EMOJI_SKIN_TONE
import
com.google.android.material.tabs.TabLayout
import
com.google.android.material.tabs.TabLayout
import
kotlinx.android.synthetic.main.dialog_skin_tone_chooser.view.*
import
kotlinx.android.synthetic.main.dialog_skin_tone_chooser.view.*
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
class
EmojiKeyboardPopup
(
context
:
Context
,
view
:
View
)
:
OverKeyboardPopupWindow
(
context
,
view
)
{
class
EmojiKeyboardPopup
(
context
:
Context
,
view
:
View
)
:
OverKeyboardPopupWindow
(
context
,
view
)
{
private
lateinit
var
viewPager
:
ViewPager
private
lateinit
var
viewPager
:
ViewPager
...
@@ -49,7 +50,7 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow
...
@@ -49,7 +50,7 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow
}
}
override
fun
onViewCreated
(
view
:
View
)
{
override
fun
onViewCreated
(
view
:
View
)
{
launch
(
UI
)
{
GlobalScope
.
launch
(
Dispatchers
.
Main
)
{
setupViewPager
()
setupViewPager
()
setupBottomBar
()
setupBottomBar
()
}
}
...
...
emoji/src/main/java/chat/rocket/android/emoji/EmojiParser.kt
View file @
f4a743d4
...
@@ -8,12 +8,14 @@ import android.text.SpannableString
...
@@ -8,12 +8,14 @@ import android.text.SpannableString
import
android.text.Spanned
import
android.text.Spanned
import
android.text.style.ImageSpan
import
android.text.style.ImageSpan
import
android.util.Log
import
android.util.Log
import
c
hat.rocket.android.emoji.internal.GlideApp
import
c
om.bumptech.glide.Glide
import
com.bumptech.glide.load.engine.DiskCacheStrategy
import
com.bumptech.glide.load.engine.DiskCacheStrategy
import
com.bumptech.glide.load.resource.gif.GifDrawable
import
com.bumptech.glide.load.resource.gif.GifDrawable
import
kotlinx.coroutines.experimental.CommonPool
import
com.bumptech.glide.request.RequestOptions
import
kotlinx.coroutines.experimental.Deferred
import
kotlinx.coroutines.Deferred
import
kotlinx.coroutines.experimental.async
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.async
class
EmojiParser
{
class
EmojiParser
{
...
@@ -85,14 +87,14 @@ class EmojiParser {
...
@@ -85,14 +87,14 @@ class EmojiParser {
emoji
.
url
?.
let
{
url
->
emoji
.
url
?.
let
{
url
->
try
{
try
{
val
glideRequest
=
if
(
url
.
endsWith
(
"gif"
,
true
))
{
val
glideRequest
=
if
(
url
.
endsWith
(
"gif"
,
true
))
{
Glide
App
.
with
(
context
).
asGif
()
Glide
.
with
(
context
).
asGif
()
}
else
{
}
else
{
Glide
App
.
with
(
context
).
asBitmap
()
Glide
.
with
(
context
).
asBitmap
()
}
}
val
futureTarget
=
glideRequest
val
futureTarget
=
glideRequest
.
diskCacheStrategy
(
DiskCacheStrategy
.
ALL
)
.
load
(
url
)
.
load
(
url
)
.
apply
(
RequestOptions
().
diskCacheStrategy
(
DiskCacheStrategy
.
ALL
))
.
submit
(
px
,
px
)
.
submit
(
px
,
px
)
val
range
=
match
.
range
val
range
=
match
.
range
...
@@ -120,7 +122,7 @@ class EmojiParser {
...
@@ -120,7 +122,7 @@ class EmojiParser {
text
:
CharSequence
,
text
:
CharSequence
,
factory
:
Spannable
.
Factory
?
=
null
factory
:
Spannable
.
Factory
?
=
null
):
Deferred
<
CharSequence
>
{
):
Deferred
<
CharSequence
>
{
return
async
(
CommonPool
)
{
parse
(
context
,
text
,
factory
)
}
return
GlobalScope
.
async
(
Dispatchers
.
IO
)
{
parse
(
context
,
text
,
factory
)
}
}
}
}
}
}
}
emoji/src/main/java/chat/rocket/android/emoji/EmojiPickerPopup.kt
View file @
f4a743d4
...
@@ -14,8 +14,9 @@ import chat.rocket.android.emoji.internal.EmojiCategory
...
@@ -14,8 +14,9 @@ import chat.rocket.android.emoji.internal.EmojiCategory
import
chat.rocket.android.emoji.internal.EmojiPagerAdapter
import
chat.rocket.android.emoji.internal.EmojiPagerAdapter
import
chat.rocket.android.emoji.internal.PREF_EMOJI_SKIN_TONE
import
chat.rocket.android.emoji.internal.PREF_EMOJI_SKIN_TONE
import
kotlinx.android.synthetic.main.emoji_picker.*
import
kotlinx.android.synthetic.main.emoji_picker.*
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
class
EmojiPickerPopup
(
context
:
Context
)
:
Dialog
(
context
)
{
class
EmojiPickerPopup
(
context
:
Context
)
:
Dialog
(
context
)
{
...
@@ -29,7 +30,7 @@ class EmojiPickerPopup(context: Context) : Dialog(context) {
...
@@ -29,7 +30,7 @@ class EmojiPickerPopup(context: Context) : Dialog(context) {
setContentView
(
R
.
layout
.
emoji_picker
)
setContentView
(
R
.
layout
.
emoji_picker
)
tabs
.
setupWithViewPager
(
pager_categories
)
tabs
.
setupWithViewPager
(
pager_categories
)
launch
(
UI
)
{
GlobalScope
.
launch
(
Dispatchers
.
Main
)
{
setupViewPager
()
setupViewPager
()
setSize
()
setSize
()
}
}
...
...
emoji/src/main/java/chat/rocket/android/emoji/EmojiRepository.kt
View file @
f4a743d4
...
@@ -10,22 +10,21 @@ import chat.rocket.android.emoji.internal.db.EmojiDatabase
...
@@ -10,22 +10,21 @@ import chat.rocket.android.emoji.internal.db.EmojiDatabase
import
chat.rocket.android.emoji.internal.isCustom
import
chat.rocket.android.emoji.internal.isCustom
import
com.bumptech.glide.Glide
import
com.bumptech.glide.Glide
import
com.bumptech.glide.load.engine.GlideException
import
com.bumptech.glide.load.engine.GlideException
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.experimental.withContext
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
import
org.json.JSONArray
import
org.json.JSONArray
import
org.json.JSONObject
import
org.json.JSONObject
import
java.io.BufferedReader
import
java.io.BufferedReader
import
java.io.InputStream
import
java.io.InputStream
import
java.io.InputStreamReader
import
java.io.InputStreamReader
import
java.io.Reader
import
java.util.*
import
java.util.*
import
java.util.regex.Pattern
import
java.util.regex.Pattern
import
kotlin.collections.ArrayList
import
kotlin.collections.ArrayList
import
kotlin.coroutines.experimental.buildSequence
object
EmojiRepository
{
object
EmojiRepository
{
private
val
FITZPATRICK_REGEX
=
"(.*)_(tone[0-9]):"
.
toRegex
(
RegexOption
.
IGNORE_CASE
)
private
val
FITZPATRICK_REGEX
=
"(.*)_(tone[0-9]):"
.
toRegex
(
RegexOption
.
IGNORE_CASE
)
private
val
shortNameToUnicode
=
HashMap
<
String
,
String
>()
private
val
shortNameToUnicode
=
HashMap
<
String
,
String
>()
private
val
SHORTNAME_PATTERN
=
Pattern
.
compile
(
":([-+\\w]+):"
)
private
val
SHORTNAME_PATTERN
=
Pattern
.
compile
(
":([-+\\w]+):"
)
...
@@ -43,14 +42,19 @@ object EmojiRepository {
...
@@ -43,14 +42,19 @@ object EmojiRepository {
return
if
(
::
currentServerUrl
.
isInitialized
)
currentServerUrl
else
null
return
if
(
::
currentServerUrl
.
isInitialized
)
currentServerUrl
else
null
}
}
fun
load
(
context
:
Context
,
customEmojis
:
List
<
Emoji
>
=
emptyList
(),
path
:
String
=
"emoji.json"
)
{
fun
load
(
launch
(
CommonPool
)
{
context
:
Context
,
customEmojis
:
List
<
Emoji
>
=
emptyList
(),
path
:
String
=
"emoji.json"
)
{
GlobalScope
.
launch
(
Dispatchers
.
IO
)
{
this
@EmojiRepository
.
customEmojis
=
customEmojis
this
@EmojiRepository
.
customEmojis
=
customEmojis
val
allEmojis
=
mutableListOf
<
Emoji
>()
val
allEmojis
=
mutableListOf
<
Emoji
>()
db
=
EmojiDatabase
.
getInstance
(
context
)
db
=
EmojiDatabase
.
getInstance
(
context
)
if
(!
::
cachedTypeface
.
isInitialized
)
{
if
(!
::
cachedTypeface
.
isInitialized
)
{
cachedTypeface
=
Typeface
.
createFromAsset
(
context
.
assets
,
"fonts/emojione-android.ttf"
)
cachedTypeface
=
Typeface
.
createFromAsset
(
context
.
assets
,
"fonts/emojione-android.ttf"
)
}
}
preferences
=
context
.
getSharedPreferences
(
"emoji"
,
Context
.
MODE_PRIVATE
)
preferences
=
context
.
getSharedPreferences
(
"emoji"
,
Context
.
MODE_PRIVATE
)
...
@@ -117,9 +121,7 @@ object EmojiRepository {
...
@@ -117,9 +121,7 @@ object EmojiRepository {
customEmojis
.
forEach
{
customEmojis
.
forEach
{
try
{
try
{
val
future
=
Glide
.
with
(
context
)
val
future
=
Glide
.
with
(
context
).
load
(
it
.
url
).
submit
(
px
,
px
)
.
load
(
it
.
url
)
.
submit
(
px
,
px
)
future
.
get
()
future
.
get
()
}
catch
(
ex
:
Exception
)
{
}
catch
(
ex
:
Exception
)
{
Log
.
d
(
"EmojiRepository"
,
"Error fetching custom emoji ${it.shortname}"
,
ex
)
Log
.
d
(
"EmojiRepository"
,
"Error fetching custom emoji ${it.shortname}"
,
ex
)
...
@@ -132,7 +134,7 @@ object EmojiRepository {
...
@@ -132,7 +134,7 @@ object EmojiRepository {
}
}
private
suspend
fun
saveEmojisToDatabase
(
emojis
:
List
<
Emoji
>)
{
private
suspend
fun
saveEmojisToDatabase
(
emojis
:
List
<
Emoji
>)
{
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
db
.
emojiDao
().
insertAllEmojis
(*
emojis
.
toTypedArray
())
db
.
emojiDao
().
insertAllEmojis
(*
emojis
.
toTypedArray
())
}
}
}
}
...
@@ -146,31 +148,30 @@ object EmojiRepository {
...
@@ -146,31 +148,30 @@ object EmojiRepository {
*
*
* @return All emojis for all categories.
* @return All emojis for all categories.
*/
*/
suspend
fun
getAll
():
List
<
Emoji
>
=
withContext
(
CommonPool
)
{
suspend
fun
getAll
():
List
<
Emoji
>
=
withContext
(
Dispatchers
.
IO
)
{
return
@withContext
db
.
emojiDao
().
loadAllEmojis
()
return
@withContext
db
.
emojiDao
().
loadAllEmojis
()
}
}
internal
suspend
fun
getEmojiSequenceByCategory
(
category
:
EmojiCategory
):
Sequence
<
Emoji
>
{
internal
suspend
fun
getEmojiSequenceByCategory
(
category
:
EmojiCategory
):
Sequence
<
Emoji
>
{
val
list
=
withContext
(
CommonPool
)
{
val
list
=
withContext
(
Dispatchers
.
IO
)
{
db
.
emojiDao
().
loadEmojisByCategory
(
category
.
name
)
db
.
emojiDao
().
loadEmojisByCategory
(
category
.
name
)
}
}
return
buildSequence
{
return
sequence
{
list
.
forEach
{
list
.
forEach
{
yield
(
it
)
}
yield
(
it
)
}
}
}
}
}
internal
suspend
fun
getEmojiSequenceByCategoryAndUrl
(
category
:
EmojiCategory
,
url
:
String
):
Sequence
<
Emoji
>
{
internal
suspend
fun
getEmojiSequenceByCategoryAndUrl
(
val
list
=
withContext
(
CommonPool
)
{
category
:
EmojiCategory
,
url
:
String
):
Sequence
<
Emoji
>
{
val
list
=
withContext
(
Dispatchers
.
IO
)
{
db
.
emojiDao
().
loadEmojisByCategoryAndUrl
(
category
.
name
,
"$url%"
)
db
.
emojiDao
().
loadEmojisByCategoryAndUrl
(
category
.
name
,
"$url%"
)
}
}
return
buildSequence
{
return
sequence
{
list
.
forEach
{
list
.
forEach
{
yield
(
it
)
}
yield
(
it
)
}
}
}
}
}
...
@@ -181,9 +182,10 @@ object EmojiRepository {
...
@@ -181,9 +182,10 @@ object EmojiRepository {
*
*
* @return Emoji given by shortname or null
* @return Emoji given by shortname or null
*/
*/
private
suspend
fun
getEmojiByShortname
(
shortname
:
String
):
Emoji
?
=
withContext
(
CommonPool
)
{
private
suspend
fun
getEmojiByShortname
(
shortname
:
String
):
Emoji
?
=
return
@withContext
db
.
emojiDao
().
loadAllCustomEmojis
().
firstOrNull
()
withContext
(
Dispatchers
.
IO
)
{
}
return
@withContext
db
.
emojiDao
().
loadAllCustomEmojis
().
firstOrNull
()
}
/**
/**
* Add an emoji to the Recents category.
* Add an emoji to the Recents category.
...
@@ -203,9 +205,9 @@ object EmojiRepository {
...
@@ -203,9 +205,9 @@ object EmojiRepository {
}
}
internal
suspend
fun
getCustomEmojisAsync
():
List
<
Emoji
>
{
internal
suspend
fun
getCustomEmojisAsync
():
List
<
Emoji
>
{
return
withContext
(
CommonPool
)
{
return
withContext
(
Dispatchers
.
IO
)
{
db
.
emojiDao
().
loadAllCustomEmojis
().
also
{
db
.
emojiDao
().
loadAllCustomEmojis
().
also
{
this
.
customEmojis
=
it
customEmojis
=
it
}
}
}
}
}
}
...
@@ -217,7 +219,7 @@ object EmojiRepository {
...
@@ -217,7 +219,7 @@ object EmojiRepository {
*
*
* @return All recent emojis ordered by usage.
* @return All recent emojis ordered by usage.
*/
*/
internal
suspend
fun
getRecents
():
List
<
Emoji
>
=
withContext
(
CommonPool
)
{
internal
suspend
fun
getRecents
():
List
<
Emoji
>
=
withContext
(
Dispatchers
.
IO
)
{
val
list
=
mutableListOf
<
Emoji
>()
val
list
=
mutableListOf
<
Emoji
>()
val
recentsJson
=
JSONObject
(
preferences
.
getString
(
PREF_EMOJI_RECENTS
,
"{}"
))
val
recentsJson
=
JSONObject
(
preferences
.
getString
(
PREF_EMOJI_RECENTS
,
"{}"
))
...
@@ -281,11 +283,13 @@ object EmojiRepository {
...
@@ -281,11 +283,13 @@ object EmojiRepository {
if
(!
json
.
has
(
"shortname"
)
||
!
json
.
has
(
"unicode"
))
{
if
(!
json
.
has
(
"shortname"
)
||
!
json
.
has
(
"unicode"
))
{
return
null
return
null
}
}
return
Emoji
(
shortname
=
json
.
getString
(
"shortname"
),
return
Emoji
(
shortname
=
json
.
getString
(
"shortname"
),
unicode
=
json
.
getString
(
"unicode"
),
unicode
=
json
.
getString
(
"unicode"
),
shortnameAlternates
=
buildStringListFromJsonArray
(
json
.
getJSONArray
(
"shortnameAlternates"
)),
shortnameAlternates
=
buildStringListFromJsonArray
(
json
.
getJSONArray
(
"shortnameAlternates"
)),
category
=
json
.
getString
(
"category"
),
category
=
json
.
getString
(
"category"
),
keywords
=
buildStringListFromJsonArray
(
json
.
getJSONArray
(
"keywords"
)))
keywords
=
buildStringListFromJsonArray
(
json
.
getJSONArray
(
"keywords"
))
)
}
}
private
fun
buildStringListFromJsonArray
(
array
:
JSONArray
):
List
<
String
>
{
private
fun
buildStringListFromJsonArray
(
array
:
JSONArray
):
List
<
String
>
{
...
@@ -297,7 +301,7 @@ object EmojiRepository {
...
@@ -297,7 +301,7 @@ object EmojiRepository {
private
fun
inputStreamToString
(
stream
:
InputStream
):
String
{
private
fun
inputStreamToString
(
stream
:
InputStream
):
String
{
val
sb
=
StringBuilder
()
val
sb
=
StringBuilder
()
val
isr
=
InputStreamReader
(
stream
,
Charsets
.
UTF_8
)
val
isr
=
InputStreamReader
(
stream
,
Charsets
.
UTF_8
)
val
br
=
BufferedReader
(
isr
)
val
br
=
BufferedReader
(
isr
as
Reader
?
)
var
read
:
String
?
=
br
.
readLine
()
var
read
:
String
?
=
br
.
readLine
()
while
(
read
!=
null
)
{
while
(
read
!=
null
)
{
sb
.
append
(
read
)
sb
.
append
(
read
)
...
@@ -315,7 +319,7 @@ object EmojiRepository {
...
@@ -315,7 +319,7 @@ object EmojiRepository {
}
}
fun
init
(
context
:
Context
)
{
fun
init
(
context
:
Context
)
{
launch
{
GlobalScope
.
launch
{
db
=
EmojiDatabase
.
getInstance
(
context
)
db
=
EmojiDatabase
.
getInstance
(
context
)
preferences
=
context
.
getSharedPreferences
(
"emoji"
,
Context
.
MODE_PRIVATE
)
preferences
=
context
.
getSharedPreferences
(
"emoji"
,
Context
.
MODE_PRIVATE
)
cachedTypeface
=
Typeface
.
createFromAsset
(
context
.
assets
,
"fonts/emojione-android.ttf"
)
cachedTypeface
=
Typeface
.
createFromAsset
(
context
.
assets
,
"fonts/emojione-android.ttf"
)
...
...
emoji/src/main/java/chat/rocket/android/emoji/internal/EmojiGlideModule.kt
deleted
100644 → 0
View file @
fa0cc587
package
chat.rocket.android.emoji.internal
import
android.content.Context
import
com.bumptech.glide.GlideBuilder
import
com.bumptech.glide.annotation.GlideModule
import
com.bumptech.glide.load.engine.cache.ExternalPreferredCacheDiskCacheFactory
import
com.bumptech.glide.module.AppGlideModule
@GlideModule
class
EmojiGlideModule
:
AppGlideModule
()
{
override
fun
applyOptions
(
context
:
Context
,
builder
:
GlideBuilder
)
{
builder
.
setDiskCache
(
ExternalPreferredCacheDiskCacheFactory
(
context
))
}
}
emoji/src/main/java/chat/rocket/android/emoji/internal/EmojiPagerAdapter.kt
View file @
f4a743d4
...
@@ -14,15 +14,15 @@ import chat.rocket.android.emoji.EmojiParser
...
@@ -14,15 +14,15 @@ import chat.rocket.android.emoji.EmojiParser
import
chat.rocket.android.emoji.EmojiRepository
import
chat.rocket.android.emoji.EmojiRepository
import
chat.rocket.android.emoji.Fitzpatrick
import
chat.rocket.android.emoji.Fitzpatrick
import
chat.rocket.android.emoji.R
import
chat.rocket.android.emoji.R
import
com.bumptech.glide.Glide
import
com.bumptech.glide.load.engine.DiskCacheStrategy
import
com.bumptech.glide.load.engine.DiskCacheStrategy
import
com.bumptech.glide.request.RequestOptions
import
kotlinx.android.synthetic.main.emoji_category_layout.view.*
import
kotlinx.android.synthetic.main.emoji_category_layout.view.*
import
kotlinx.android.synthetic.main.emoji_image_row_item.view.*
import
kotlinx.android.synthetic.main.emoji_image_row_item.view.*
import
kotlinx.android.synthetic.main.emoji_row_item.view.*
import
kotlinx.android.synthetic.main.emoji_row_item.view.*
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.withContext
import
kotlinx.coroutines.experimental.withContext
internal
class
EmojiPagerAdapter
(
private
val
listener
:
EmojiKeyboardListener
)
:
PagerAdapter
()
{
internal
class
EmojiPagerAdapter
(
private
val
listener
:
EmojiKeyboardListener
)
:
PagerAdapter
()
{
...
@@ -44,7 +44,7 @@ internal class EmojiPagerAdapter(private val listener: EmojiKeyboardListener) :
...
@@ -44,7 +44,7 @@ internal class EmojiPagerAdapter(private val listener: EmojiKeyboardListener) :
emoji_recycler_view
.
setRecycledViewPool
(
RecyclerView
.
RecycledViewPool
())
emoji_recycler_view
.
setRecycledViewPool
(
RecyclerView
.
RecycledViewPool
())
container
.
addView
(
view
)
container
.
addView
(
view
)
launch
(
UI
)
{
kotlinx
.
coroutines
.
GlobalScope
.
launch
(
Dispatchers
.
Main
)
{
val
currentServerUrl
=
EmojiRepository
.
getCurrentServerUrl
()
val
currentServerUrl
=
EmojiRepository
.
getCurrentServerUrl
()
val
emojis
=
if
(
category
!=
EmojiCategory
.
RECENTS
)
{
val
emojis
=
if
(
category
!=
EmojiCategory
.
RECENTS
)
{
if
(
category
==
EmojiCategory
.
CUSTOM
)
{
if
(
category
==
EmojiCategory
.
CUSTOM
)
{
...
@@ -111,9 +111,9 @@ internal class EmojiPagerAdapter(private val listener: EmojiKeyboardListener) :
...
@@ -111,9 +111,9 @@ internal class EmojiPagerAdapter(private val listener: EmojiKeyboardListener) :
}
}
suspend
fun
addEmojisFromSequence
(
emojiSequence
:
Sequence
<
Emoji
>)
{
suspend
fun
addEmojisFromSequence
(
emojiSequence
:
Sequence
<
Emoji
>)
{
withContext
(
CommonPool
)
{
withContext
(
Dispatchers
.
IO
)
{
emojiSequence
.
forEachIndexed
{
index
,
emoji
->
emojiSequence
.
forEachIndexed
{
index
,
emoji
->
withContext
(
UI
)
{
withContext
(
Dispatchers
.
Main
)
{
allEmojis
.
add
(
emoji
)
allEmojis
.
add
(
emoji
)
if
(
emoji
.
isDefault
)
{
if
(
emoji
.
isDefault
)
{
emojis
.
add
(
emoji
)
emojis
.
add
(
emoji
)
...
@@ -180,9 +180,9 @@ internal class EmojiPagerAdapter(private val listener: EmojiKeyboardListener) :
...
@@ -180,9 +180,9 @@ internal class EmojiPagerAdapter(private val listener: EmojiKeyboardListener) :
}
}
}
else
{
}
else
{
// Handle custom emoji.
// Handle custom emoji.
Glide
App
.
with
(
context
)
Glide
.
with
(
context
)
.
load
(
emoji
.
url
)
.
load
(
emoji
.
url
)
.
diskCacheStrategy
(
DiskCacheStrategy
.
ALL
)
.
apply
(
RequestOptions
().
diskCacheStrategy
(
DiskCacheStrategy
.
ALL
)
)
.
into
(
emoji_image_view
)
.
into
(
emoji_image_view
)
}
}
...
...
player/build.gradle
View file @
f4a743d4
...
@@ -13,6 +13,7 @@ android {
...
@@ -13,6 +13,7 @@ android {
versionName
"1.0.0"
versionName
"1.0.0"
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
}
}
buildTypes
{
buildTypes
{
release
{
release
{
minifyEnabled
false
minifyEnabled
false
...
...
settings.gradle
View file @
f4a743d4
include
':app'
,
':player'
,
':emoji'
,
':draw'
,
':util'
,
':core'
,
':suggestions'
//, ':wear'
include
':app'
,
':player'
,
':emoji'
,
':draw'
,
':util'
,
':core'
,
':suggestions'
\ No newline at end of file
\ No newline at end of file
suggestions/src/main/java/chat/rocket/android/suggestions/strategy/trie/data/TrieNode.kt
View file @
f4a743d4
package
chat.rocket.android.suggestions.strategy.trie.data
package
chat.rocket.android.suggestions.strategy.trie.data
import
chat.rocket.android.suggestions.model.SuggestionModel
import
chat.rocket.android.suggestions.model.SuggestionModel
import
kotlin.coroutines.experimental.buildSequence
internal
class
TrieNode
(
internal
class
TrieNode
(
internal
var
data
:
Char
,
internal
var
data
:
Char
,
...
@@ -32,17 +31,13 @@ internal class TrieNode(
...
@@ -32,17 +31,13 @@ internal class TrieNode(
return
list
return
list
}
}
fun
getItems
():
Sequence
<
SuggestionModel
>
=
buildS
equence
{
fun
getItems
():
Sequence
<
SuggestionModel
>
=
s
equence
{
if
(
isLeaf
)
{
if
(
isLeaf
)
{
yield
(
item
!!
)
yield
(
item
!!
)
}
}
children
.
forEach
{
node
->
children
.
forEach
{
node
->
yieldAll
(
node
.
value
.
getItems
())
}
node
.
value
.
let
{
yieldAll
(
it
.
getItems
())
}
}
}
}
override
fun
toString
():
String
=
if
(
parent
==
null
)
""
else
"${parent.toString()}$data"
override
fun
toString
():
String
=
if
(
parent
==
null
)
""
else
"${parent.toString()}$data"
...
...
util/build.gradle
View file @
f4a743d4
...
@@ -31,7 +31,7 @@ dependencies {
...
@@ -31,7 +31,7 @@ dependencies {
implementation
project
(
':core'
)
implementation
project
(
':core'
)
implementation
libraries
.
kotlin
implementation
libraries
.
kotlin
implementation
libraries
.
coroutines
implementation
libraries
.
coroutines
Core
implementation
libraries
.
coroutinesAndroid
implementation
libraries
.
coroutinesAndroid
implementation
libraries
.
appCompat
implementation
libraries
.
appCompat
...
...
util/src/main/java/chat/rocket/android/util/extension/Coroutines.kt
View file @
f4a743d4
package
chat.rocket.android.util.extension
package
chat.rocket.android.util.extension
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
kotlinx.coroutines.
experimental.
CoroutineScope
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.
experimental.
Job
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.
experimental.android.UI
import
kotlinx.coroutines.
MainScope
import
kotlinx.coroutines.
experimental.
launch
import
kotlinx.coroutines.launch
/**
/**
* Launches a coroutine on the UI context.
* Launches a coroutine on the UI context.
*
*
* @param strategy a CancelStrategy for canceling the coroutine job
* @param strategy a CancelStrategy for canceling the coroutine job
*/
*/
fun
launchUI
(
strategy
:
CancelStrategy
,
block
:
suspend
CoroutineScope
.()
->
Unit
):
Job
{
fun
launchUI
(
strategy
:
CancelStrategy
,
block
:
suspend
CoroutineScope
.()
->
Unit
):
Job
=
return
launch
(
context
=
UI
,
parent
=
strategy
.
jobs
,
block
=
block
)
MainScope
().
launch
(
context
=
strategy
.
jobs
,
block
=
block
)
}
\ No newline at end of file
util/src/main/java/chat/rocket/android/util/extension/Image.kt
View file @
f4a743d4
...
@@ -6,8 +6,8 @@ import android.os.Environment
...
@@ -6,8 +6,8 @@ import android.os.Environment
import
android.provider.MediaStore
import
android.provider.MediaStore
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.FragmentActivity
import
androidx.fragment.app.FragmentActivity
import
kotlinx.coroutines.
experimental.DefaultDispatcher
import
kotlinx.coroutines.
Dispatchers
import
kotlinx.coroutines.
experimental.
withContext
import
kotlinx.coroutines.withContext
import
java.io.ByteArrayInputStream
import
java.io.ByteArrayInputStream
import
java.io.ByteArrayOutputStream
import
java.io.ByteArrayOutputStream
import
java.io.InputStream
import
java.io.InputStream
...
@@ -25,11 +25,10 @@ import java.util.*
...
@@ -25,11 +25,10 @@ import java.util.*
suspend
fun
Bitmap
.
compressImageAndGetInputStream
(
mimeType
:
String
):
InputStream
?
{
suspend
fun
Bitmap
.
compressImageAndGetInputStream
(
mimeType
:
String
):
InputStream
?
{
var
inputStream
:
InputStream
?
=
null
var
inputStream
:
InputStream
?
=
null
withContext
(
D
efaultDispatcher
)
{
withContext
(
D
ispatchers
.
Default
)
{
val
byteArrayOutputStream
=
ByteArrayOutputStream
()
val
byteArrayOutputStream
=
ByteArrayOutputStream
()
// TODO: Add an option the the app to the user be able to select the quality of the compressed image
// TODO: Add an option the the app to the user be able to select the quality of the compressed image
val
isCompressed
=
val
isCompressed
=
compress
(
mimeType
.
getCompressFormat
(),
70
,
byteArrayOutputStream
)
this
.
compress
(
mimeType
.
getCompressFormat
(),
70
,
byteArrayOutputStream
)
if
(
isCompressed
)
{
if
(
isCompressed
)
{
inputStream
=
ByteArrayInputStream
(
byteArrayOutputStream
.
toByteArray
())
inputStream
=
ByteArrayInputStream
(
byteArrayOutputStream
.
toByteArray
())
}
}
...
@@ -74,10 +73,9 @@ suspend fun Bitmap.getByteArray(
...
@@ -74,10 +73,9 @@ suspend fun Bitmap.getByteArray(
suspend
fun
Bitmap
.
compressImageAndGetByteArray
(
mimeType
:
String
,
quality
:
Int
=
100
):
ByteArray
?
{
suspend
fun
Bitmap
.
compressImageAndGetByteArray
(
mimeType
:
String
,
quality
:
Int
=
100
):
ByteArray
?
{
var
byteArray
:
ByteArray
?
=
null
var
byteArray
:
ByteArray
?
=
null
withContext
(
D
efaultDispatcher
)
{
withContext
(
D
ispatchers
.
Default
)
{
val
byteArrayOutputStream
=
ByteArrayOutputStream
()
val
byteArrayOutputStream
=
ByteArrayOutputStream
()
val
isCompressed
=
val
isCompressed
=
compress
(
mimeType
.
getCompressFormat
(),
quality
,
byteArrayOutputStream
)
this
.
compress
(
mimeType
.
getCompressFormat
(),
quality
,
byteArrayOutputStream
)
if
(
isCompressed
)
{
if
(
isCompressed
)
{
byteArray
=
byteArrayOutputStream
.
toByteArray
()
byteArray
=
byteArrayOutputStream
.
toByteArray
()
}
}
...
...
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