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
1182d85f
Unverified
Commit
1182d85f
authored
Jun 06, 2018
by
Filipe de Lima Brito
Committed by
GitHub
Jun 06, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1345 from RocketChat/release/2.3.0-hotfix1
[FIX] 2.3.0 hotfix1
parents
5a9f819f
2f8a6f1d
Changes
23
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
442 additions
and
31 deletions
+442
-31
build.gradle
app/build.gradle
+2
-2
AuthenticationModule.kt
.../rocket/android/authentication/di/AuthenticationModule.kt
+1
-0
LoginPresenter.kt
...droid/authentication/login/presentation/LoginPresenter.kt
+5
-2
RegisterUsernamePresenter.kt
...egisterusername/presentation/RegisterUsernamePresenter.kt
+3
-1
ResetPasswordPresenter.kt
...tion/resetpassword/presentation/ResetPasswordPresenter.kt
+2
-1
ServerPresenter.kt
...oid/authentication/server/presentation/ServerPresenter.kt
+2
-2
SignupPresenter.kt
...oid/authentication/signup/presentation/SignupPresenter.kt
+3
-1
TwoFAPresenter.kt
...d/authentication/twofactor/presentation/TwoFAPresenter.kt
+3
-1
AuthenticationActivity.kt
...ocket/android/authentication/ui/AuthenticationActivity.kt
+11
-8
ChatRoomFragmentModule.kt
...chat/rocket/android/chatroom/di/ChatRoomFragmentModule.kt
+3
-3
ChatRoomFragmentProvider.kt
...at/rocket/android/chatroom/di/ChatRoomFragmentProvider.kt
+2
-0
ViewModelMapper.kt
...chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
+2
-0
ChatRoomsFragmentProvider.kt
.../rocket/android/chatrooms/di/ChatRoomsFragmentProvider.kt
+2
-0
AppModule.kt
.../main/java/chat/rocket/android/dagger/module/AppModule.kt
+17
-5
ForAuthentication.kt
...chat/rocket/android/dagger/qualifier/ForAuthentication.kt
+11
-0
FavoriteMessagesFragmentProvider.kt
...d/favoritemessages/di/FavoriteMessagesFragmentProvider.kt
+2
-0
PinnedMessagesFragmentProvider.kt
...droid/pinnedmessages/di/PinnedMessagesFragmentProvider.kt
+2
-0
GetConnectingServerInteractor.kt
...et/android/server/domain/GetConnectingServerInteractor.kt
+14
-0
SaveConnectingServerInteractor.kt
...t/android/server/domain/SaveConnectingServerInteractor.kt
+10
-0
SharedPrefsConnectingServerRepository.kt
.../infraestructure/SharedPrefsConnectingServerRepository.kt
+23
-0
HttpLoggingInterceptor.kt
...n/java/chat/rocket/android/util/HttpLoggingInterceptor.kt
+307
-0
Ui.kt
app/src/main/java/chat/rocket/android/util/extensions/Ui.kt
+9
-4
View.kt
...src/main/java/chat/rocket/android/util/extensions/View.kt
+6
-1
No files found.
app/build.gradle
View file @
1182d85f
...
...
@@ -13,8 +13,8 @@ android {
applicationId
"chat.rocket.android"
minSdkVersion
21
targetSdkVersion
versions
.
targetSdk
versionCode
202
4
versionName
"2.3.
0
"
versionCode
202
5
versionName
"2.3.
1
"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled
true
}
...
...
app/src/main/java/chat/rocket/android/authentication/di/AuthenticationModule.kt
View file @
1182d85f
...
...
@@ -2,6 +2,7 @@ package chat.rocket.android.authentication.di
import
chat.rocket.android.authentication.presentation.AuthenticationNavigator
import
chat.rocket.android.authentication.ui.AuthenticationActivity
import
chat.rocket.android.dagger.qualifier.ForAuthentication
import
chat.rocket.android.dagger.scope.PerActivity
import
dagger.Module
import
dagger.Provides
...
...
app/src/main/java/chat/rocket/android/authentication/login/presentation/LoginPresenter.kt
View file @
1182d85f
...
...
@@ -41,12 +41,13 @@ class LoginPresenter @Inject constructor(
private
val
localRepository
:
LocalRepository
,
private
val
getAccountsInteractor
:
GetAccountsInteractor
,
private
val
settingsInteractor
:
GetSettingsInteractor
,
serverInteractor
:
GetCurrentServerInteractor
,
serverInteractor
:
GetConnectingServerInteractor
,
private
val
saveCurrentServer
:
SaveCurrentServerInteractor
,
private
val
saveAccountInteractor
:
SaveAccountInteractor
,
private
val
factory
:
RocketChatClientFactory
)
{
// TODO - we should validate the current server when opening the app, and have a nonnull get()
private
va
l
currentServer
=
serverInteractor
.
get
()
!!
private
va
r
currentServer
=
serverInteractor
.
get
()
!!
private
lateinit
var
client
:
RocketChatClient
private
lateinit
var
settings
:
PublicSettings
private
lateinit
var
usernameOrEmail
:
String
...
...
@@ -103,6 +104,7 @@ class LoginPresenter @Inject constructor(
}
private
fun
setupConnectionInfo
(
serverUrl
:
String
)
{
currentServer
=
serverUrl
client
=
factory
.
create
(
serverUrl
)
settings
=
settingsInteractor
.
get
(
serverUrl
)
}
...
...
@@ -325,6 +327,7 @@ class LoginPresenter @Inject constructor(
val
username
=
retryIO
(
"me()"
)
{
client
.
me
().
username
}
if
(
username
!=
null
)
{
localRepository
.
save
(
LocalRepository
.
CURRENT_USERNAME_KEY
,
username
)
saveCurrentServer
.
save
(
currentServer
)
saveAccount
(
username
)
saveToken
(
token
)
registerPushToken
()
...
...
app/src/main/java/chat/rocket/android/authentication/registerusername/presentation/RegisterUsernamePresenter.kt
View file @
1182d85f
...
...
@@ -27,7 +27,8 @@ class RegisterUsernamePresenter @Inject constructor(
private
val
factory
:
RocketChatClientFactory
,
private
val
saveAccountInteractor
:
SaveAccountInteractor
,
private
val
getAccountsInteractor
:
GetAccountsInteractor
,
serverInteractor
:
GetCurrentServerInteractor
,
serverInteractor
:
GetConnectingServerInteractor
,
private
val
saveCurrentServer
:
SaveCurrentServerInteractor
,
settingsInteractor
:
GetSettingsInteractor
)
{
private
val
currentServer
=
serverInteractor
.
get
()
!!
...
...
@@ -47,6 +48,7 @@ class RegisterUsernamePresenter @Inject constructor(
val
registeredUsername
=
me
.
username
if
(
registeredUsername
!=
null
)
{
saveAccount
(
registeredUsername
)
saveCurrentServer
.
save
(
currentServer
)
tokenRepository
.
save
(
currentServer
,
Token
(
userId
,
authToken
))
registerPushToken
()
navigator
.
toChatList
()
...
...
app/src/main/java/chat/rocket/android/authentication/resetpassword/presentation/ResetPasswordPresenter.kt
View file @
1182d85f
...
...
@@ -2,6 +2,7 @@ package chat.rocket.android.authentication.resetpassword.presentation
import
chat.rocket.android.authentication.presentation.AuthenticationNavigator
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.server.domain.GetConnectingServerInteractor
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.extensions.isEmail
...
...
@@ -19,7 +20,7 @@ class ResetPasswordPresenter @Inject constructor(
private
val
strategy
:
CancelStrategy
,
private
val
navigator
:
AuthenticationNavigator
,
factory
:
RocketChatClientFactory
,
serverInteractor
:
GetC
urrent
ServerInteractor
serverInteractor
:
GetC
onnecting
ServerInteractor
)
{
private
val
currentServer
=
serverInteractor
.
get
()
!!
private
val
client
:
RocketChatClient
=
factory
.
create
(
currentServer
)
...
...
app/src/main/java/chat/rocket/android/authentication/server/presentation/ServerPresenter.kt
View file @
1182d85f
...
...
@@ -6,7 +6,7 @@ import chat.rocket.android.core.behaviours.showMessage
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.server.domain.GetAccountsInteractor
import
chat.rocket.android.server.domain.RefreshSettingsInteractor
import
chat.rocket.android.server.domain.SaveC
urrent
ServerInteractor
import
chat.rocket.android.server.domain.SaveC
onnecting
ServerInteractor
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.presentation.CheckServerPresenter
import
chat.rocket.android.util.extensions.isValidUrl
...
...
@@ -16,7 +16,7 @@ import javax.inject.Inject
class
ServerPresenter
@Inject
constructor
(
private
val
view
:
ServerView
,
private
val
strategy
:
CancelStrategy
,
private
val
navigator
:
AuthenticationNavigator
,
private
val
serverInteractor
:
SaveC
urrent
ServerInteractor
,
private
val
serverInteractor
:
SaveC
onnecting
ServerInteractor
,
private
val
refreshSettingsInteractor
:
RefreshSettingsInteractor
,
private
val
getAccountsInteractor
:
GetAccountsInteractor
,
factory
:
RocketChatClientFactory
...
...
app/src/main/java/chat/rocket/android/authentication/signup/presentation/SignupPresenter.kt
View file @
1182d85f
...
...
@@ -22,7 +22,8 @@ class SignupPresenter @Inject constructor(
private
val
strategy
:
CancelStrategy
,
private
val
navigator
:
AuthenticationNavigator
,
private
val
localRepository
:
LocalRepository
,
private
val
serverInteractor
:
GetCurrentServerInteractor
,
private
val
serverInteractor
:
GetConnectingServerInteractor
,
private
val
saveCurrentServerInteractor
:
SaveCurrentServerInteractor
,
private
val
factory
:
RocketChatClientFactory
,
private
val
saveAccountInteractor
:
SaveAccountInteractor
,
private
val
getAccountsInteractor
:
GetAccountsInteractor
,
...
...
@@ -60,6 +61,7 @@ class SignupPresenter @Inject constructor(
// TODO This function returns a user token so should we save it?
retryIO
(
"login"
)
{
client
.
login
(
username
,
password
)
}
val
me
=
retryIO
(
"me"
)
{
client
.
me
()
}
saveCurrentServerInteractor
.
save
(
currentServer
)
localRepository
.
save
(
LocalRepository
.
CURRENT_USERNAME_KEY
,
me
.
username
)
saveAccount
(
me
)
registerPushToken
()
...
...
app/src/main/java/chat/rocket/android/authentication/twofactor/presentation/TwoFAPresenter.kt
View file @
1182d85f
...
...
@@ -25,7 +25,8 @@ class TwoFAPresenter @Inject constructor(private val view: TwoFAView,
private
val
navigator
:
AuthenticationNavigator
,
private
val
tokenRepository
:
TokenRepository
,
private
val
localRepository
:
LocalRepository
,
private
val
serverInteractor
:
GetCurrentServerInteractor
,
private
val
serverInteractor
:
GetConnectingServerInteractor
,
private
val
saveCurrentServerInteractor
:
SaveCurrentServerInteractor
,
private
val
factory
:
RocketChatClientFactory
,
private
val
saveAccountInteractor
:
SaveAccountInteractor
,
private
val
getAccountsInteractor
:
GetAccountsInteractor
,
...
...
@@ -55,6 +56,7 @@ class TwoFAPresenter @Inject constructor(private val view: TwoFAView,
}
val
me
=
retryIO
(
"me"
)
{
client
.
me
()
}
saveAccount
(
me
)
saveCurrentServerInteractor
.
save
(
currentServer
)
tokenRepository
.
save
(
server
,
token
)
registerPushToken
()
navigator
.
toChatList
()
...
...
app/src/main/java/chat/rocket/android/authentication/ui/AuthenticationActivity.kt
View file @
1182d85f
...
...
@@ -32,17 +32,25 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
setContentView
(
R
.
layout
.
activity_authentication
)
setTheme
(
R
.
style
.
AuthenticationTheme
)
super
.
onCreate
(
savedInstanceState
)
}
override
fun
onStart
()
{
super
.
onStart
()
val
deepLinkInfo
=
intent
.
getLoginDeepLinkInfo
()
launch
(
UI
+
job
)
{
val
newServer
=
intent
.
getBooleanExtra
(
INTENT_ADD_NEW_SERVER
,
false
)
// if we got authenticateWithDeepLink information, pass true to newServer also
presenter
.
loadCredentials
(
newServer
||
deepLinkInfo
!=
null
)
{
authenticated
->
if
(!
authenticated
)
{
showServerInput
(
savedInstanceState
,
deepLinkInfo
)
showServerInput
(
deepLinkInfo
)
}
}
}
}
override
fun
onStop
()
{
job
.
cancel
()
super
.
onStop
()
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
...
...
@@ -53,17 +61,12 @@ class AuthenticationActivity : AppCompatActivity(), HasSupportFragmentInjector {
}
}
override
fun
onDestroy
()
{
job
.
cancel
()
super
.
onDestroy
()
}
override
fun
supportFragmentInjector
():
AndroidInjector
<
Fragment
>
{
return
fragmentDispatchingAndroidInjector
}
fun
showServerInput
(
savedInstanceState
:
Bundle
?,
deepLinkInfo
:
LoginDeepLinkInfo
?)
{
addFragment
(
"ServerFragment"
,
R
.
id
.
fragment_container
)
{
fun
showServerInput
(
deepLinkInfo
:
LoginDeepLinkInfo
?)
{
addFragment
(
"ServerFragment"
,
R
.
id
.
fragment_container
,
allowStateLoss
=
true
)
{
ServerFragment
.
newInstance
(
deepLinkInfo
)
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/di/ChatRoomFragmentModule.kt
View file @
1182d85f
package
chat.rocket.android.chatroom.di
import
android.arch.lifecycle.LifecycleOwner
import
chat.rocket.android.chatroom.presentation.ChatRoomNavigator
import
chat.rocket.android.chatroom.presentation.ChatRoomView
import
chat.rocket.android.chatroom.ui.ChatRoomActivity
import
chat.rocket.android.chatroom.ui.ChatRoomFragment
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.dagger.scope.PerFragment
...
...
@@ -12,20 +10,22 @@ import dagger.Provides
import
kotlinx.coroutines.experimental.Job
@Module
@PerFragment
class
ChatRoomFragmentModule
{
@Provides
@PerFragment
fun
chatRoomView
(
frag
:
ChatRoomFragment
):
ChatRoomView
{
return
frag
}
@Provides
@PerFragment
fun
provideLifecycleOwner
(
frag
:
ChatRoomFragment
):
LifecycleOwner
{
return
frag
}
@Provides
@PerFragment
fun
provideCancelStrategy
(
owner
:
LifecycleOwner
,
jobs
:
Job
):
CancelStrategy
{
return
CancelStrategy
(
owner
,
jobs
)
}
...
...
app/src/main/java/chat/rocket/android/chatroom/di/ChatRoomFragmentProvider.kt
View file @
1182d85f
package
chat.rocket.android.chatroom.di
import
chat.rocket.android.chatroom.ui.ChatRoomFragment
import
chat.rocket.android.dagger.scope.PerFragment
import
dagger.Module
import
dagger.android.ContributesAndroidInjector
...
...
@@ -8,5 +9,6 @@ import dagger.android.ContributesAndroidInjector
abstract
class
ChatRoomFragmentProvider
{
@ContributesAndroidInjector
(
modules
=
[
ChatRoomFragmentModule
::
class
])
@PerFragment
abstract
fun
provideChatRoomFragment
():
ChatRoomFragment
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
View file @
1182d85f
...
...
@@ -14,6 +14,7 @@ import androidx.core.text.color
import
androidx.core.text.scale
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.domain.MessageReply
import
chat.rocket.android.dagger.scope.PerFragment
import
chat.rocket.android.helper.MessageHelper
import
chat.rocket.android.helper.MessageParser
import
chat.rocket.android.infrastructure.LocalRepository
...
...
@@ -47,6 +48,7 @@ import okhttp3.HttpUrl
import
java.security.InvalidParameterException
import
javax.inject.Inject
@PerFragment
class
ViewModelMapper
@Inject
constructor
(
private
val
context
:
Context
,
private
val
parser
:
MessageParser
,
...
...
app/src/main/java/chat/rocket/android/chatrooms/di/ChatRoomsFragmentProvider.kt
View file @
1182d85f
package
chat.rocket.android.chatrooms.di
import
chat.rocket.android.chatrooms.ui.ChatRoomsFragment
import
chat.rocket.android.dagger.scope.PerFragment
import
dagger.Module
import
dagger.android.ContributesAndroidInjector
...
...
@@ -8,5 +9,6 @@ import dagger.android.ContributesAndroidInjector
abstract
class
ChatRoomsFragmentProvider
{
@ContributesAndroidInjector
(
modules
=
[
ChatRoomsFragmentModule
::
class
])
@PerFragment
abstract
fun
provideChatRoomsFragment
():
ChatRoomsFragment
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/dagger/module/AppModule.kt
View file @
1182d85f
...
...
@@ -14,6 +14,7 @@ import chat.rocket.android.app.RocketChatDatabase
import
chat.rocket.android.authentication.infraestructure.SharedPreferencesMultiServerTokenRepository
import
chat.rocket.android.authentication.infraestructure.SharedPreferencesTokenRepository
import
chat.rocket.android.chatroom.service.MessageService
import
chat.rocket.android.dagger.qualifier.ForAuthentication
import
chat.rocket.android.dagger.qualifier.ForMessages
import
chat.rocket.android.helper.MessageParser
import
chat.rocket.android.infrastructure.LocalRepository
...
...
@@ -23,6 +24,7 @@ import chat.rocket.android.push.PushManager
import
chat.rocket.android.server.domain.*
import
chat.rocket.android.server.infraestructure.*
import
chat.rocket.android.util.AppJsonAdapterFactory
import
chat.rocket.android.util.HttpLoggingInterceptor
import
chat.rocket.android.util.TimberLogger
import
chat.rocket.common.internal.FallbackSealedClassJsonAdapter
import
chat.rocket.common.internal.ISO8601Date
...
...
@@ -42,7 +44,6 @@ import dagger.Module
import
dagger.Provides
import
kotlinx.coroutines.experimental.Job
import
okhttp3.OkHttpClient
import
okhttp3.logging.HttpLoggingInterceptor
import
ru.noties.markwon.SpannableConfiguration
import
ru.noties.markwon.spans.SpannableTheme
import
timber.log.Timber
...
...
@@ -54,7 +55,9 @@ class AppModule {
@Provides
@Singleton
fun
provideRocketChatClient
(
okHttpClient
:
OkHttpClient
,
repository
:
TokenRepository
,
logger
:
PlatformLogger
):
RocketChatClient
{
fun
provideRocketChatClient
(
okHttpClient
:
OkHttpClient
,
repository
:
TokenRepository
,
logger
:
PlatformLogger
):
RocketChatClient
{
return
RocketChatClient
.
create
{
httpClient
=
okHttpClient
tokenRepository
=
repository
...
...
@@ -68,7 +71,8 @@ class AppModule {
@Provides
@Singleton
fun
provideRocketChatDatabase
(
context
:
Application
):
RocketChatDatabase
{
return
Room
.
databaseBuilder
(
context
.
applicationContext
,
RocketChatDatabase
::
class
.
java
,
"rocketchat-db"
).
build
()
return
Room
.
databaseBuilder
(
context
.
applicationContext
,
RocketChatDatabase
::
class
.
java
,
"rocketchat-db"
).
build
()
}
@Provides
...
...
@@ -91,8 +95,10 @@ class AppModule {
@Provides
@Singleton
fun
provideHttpLoggingInterceptor
():
HttpLoggingInterceptor
{
val
interceptor
=
HttpLoggingInterceptor
(
HttpLoggingInterceptor
.
Logger
{
message
->
val
interceptor
=
HttpLoggingInterceptor
(
object
:
HttpLoggingInterceptor
.
Logger
{
override
fun
log
(
message
:
String
)
{
Timber
.
d
(
message
)
}
})
if
(
BuildConfig
.
DEBUG
)
{
interceptor
.
level
=
HttpLoggingInterceptor
.
Level
.
BODY
...
...
@@ -168,6 +174,12 @@ class AppModule {
return
SharedPrefsCurrentServerRepository
(
prefs
)
}
@Provides
@ForAuthentication
fun
provideConnectingServerRepository
(
prefs
:
SharedPreferences
):
CurrentServerRepository
{
return
SharedPrefsConnectingServerRepository
(
prefs
)
}
@Provides
@Singleton
fun
provideSettingsRepository
(
localRepository
:
LocalRepository
):
SettingsRepository
{
...
...
app/src/main/java/chat/rocket/android/dagger/qualifier/ForAuthentication.kt
0 → 100644
View file @
1182d85f
package
chat.rocket.android.dagger.qualifier
import
javax.inject.Qualifier
/**
* Created by luciofm on 4/14/18.
*/
@Qualifier
@Retention
(
AnnotationRetention
.
RUNTIME
)
annotation
class
ForAuthentication
\ No newline at end of file
app/src/main/java/chat/rocket/android/favoritemessages/di/FavoriteMessagesFragmentProvider.kt
View file @
1182d85f
package
chat.rocket.android.chatroom.di
import
chat.rocket.android.dagger.scope.PerFragment
import
chat.rocket.android.favoritemessages.ui.FavoriteMessagesFragment
import
dagger.Module
import
dagger.android.ContributesAndroidInjector
...
...
@@ -8,5 +9,6 @@ import dagger.android.ContributesAndroidInjector
abstract
class
FavoriteMessagesFragmentProvider
{
@ContributesAndroidInjector
(
modules
=
[
FavoriteMessagesFragmentModule
::
class
])
@PerFragment
abstract
fun
provideFavoriteMessageFragment
():
FavoriteMessagesFragment
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/pinnedmessages/di/PinnedMessagesFragmentProvider.kt
View file @
1182d85f
package
chat.rocket.android.pinnedmessages.di
import
chat.rocket.android.chatroom.di.PinnedMessagesFragmentModule
import
chat.rocket.android.dagger.scope.PerFragment
import
chat.rocket.android.pinnedmessages.ui.PinnedMessagesFragment
import
dagger.Module
import
dagger.android.ContributesAndroidInjector
...
...
@@ -9,5 +10,6 @@ import dagger.android.ContributesAndroidInjector
abstract
class
PinnedMessagesFragmentProvider
{
@ContributesAndroidInjector
(
modules
=
[
PinnedMessagesFragmentModule
::
class
])
@PerFragment
abstract
fun
providePinnedMessageFragment
():
PinnedMessagesFragment
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/server/domain/GetConnectingServerInteractor.kt
0 → 100644
View file @
1182d85f
package
chat.rocket.android.server.domain
import
chat.rocket.android.dagger.qualifier.ForAuthentication
import
javax.inject.Inject
class
GetConnectingServerInteractor
@Inject
constructor
(
@ForAuthentication
private
val
repository
:
CurrentServerRepository
)
{
fun
get
():
String
?
=
repository
.
get
()
fun
clear
()
{
repository
.
clear
()
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/server/domain/SaveConnectingServerInteractor.kt
0 → 100644
View file @
1182d85f
package
chat.rocket.android.server.domain
import
chat.rocket.android.dagger.qualifier.ForAuthentication
import
javax.inject.Inject
class
SaveConnectingServerInteractor
@Inject
constructor
(
@ForAuthentication
private
val
repository
:
CurrentServerRepository
)
{
fun
save
(
url
:
String
)
=
repository
.
save
(
url
)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/server/infraestructure/SharedPrefsConnectingServerRepository.kt
0 → 100644
View file @
1182d85f
package
chat.rocket.android.server.infraestructure
import
android.content.SharedPreferences
import
chat.rocket.android.server.domain.CurrentServerRepository
class
SharedPrefsConnectingServerRepository
(
private
val
preferences
:
SharedPreferences
)
:
CurrentServerRepository
{
override
fun
save
(
url
:
String
)
{
preferences
.
edit
().
putString
(
CONNECTING_SERVER_KEY
,
url
).
apply
()
}
override
fun
get
():
String
?
{
return
preferences
.
getString
(
CONNECTING_SERVER_KEY
,
null
)
}
companion
object
{
private
const
val
CONNECTING_SERVER_KEY
=
"connecting_server"
}
override
fun
clear
()
{
preferences
.
edit
().
remove
(
CONNECTING_SERVER_KEY
).
apply
()
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/util/HttpLoggingInterceptor.kt
0 → 100644
View file @
1182d85f
package
chat.rocket.android.util
import
okhttp3.Headers
import
okhttp3.Interceptor
import
okhttp3.MediaType
import
okhttp3.OkHttpClient
import
okhttp3.Response
import
okhttp3.internal.http.HttpHeaders
import
okhttp3.internal.platform.Platform
import
okhttp3.internal.platform.Platform.INFO
import
okio.Buffer
import
okio.GzipSource
import
java.io.EOFException
import
java.io.IOException
import
java.nio.charset.Charset
import
java.util.concurrent.TimeUnit
/**
* An OkHttp interceptor which logs request and response information. Can be applied as an
* [application interceptor][OkHttpClient.interceptors] or as a [ ][OkHttpClient.networkInterceptors].
*
* The format of the logs created by
* this class should not be considered stable and may change slightly between releases. If you need
* a stable logging format, use your own interceptor.
*/
class
HttpLoggingInterceptor
constructor
(
private
val
logger
:
Logger
)
:
Interceptor
{
@Volatile
internal
var
level
=
Level
.
NONE
enum
class
Level
{
/** No logs. */
NONE
,
/**
* Logs request and response lines.
*
*
* Example:
* <pre>`--> POST /greeting http/1.1 (3-byte body)
*
* <-- 200 OK (22ms, 6-byte body)
`</pre> *
*/
BASIC
,
/**
* Logs request and response lines and their respective headers.
*
*
* Example:
* <pre>`--> POST /greeting http/1.1
* Host: example.com
* Content-Type: plain/text
* Content-Length: 3
* --> END POST
*
* <-- 200 OK (22ms)
* Content-Type: plain/text
* Content-Length: 6
* <-- END HTTP
`</pre> *
*/
HEADERS
,
/**
* Logs request and response lines and their respective headers and bodies (if present).
*
*
* Example:
* <pre>`--> POST /greeting http/1.1
* Host: example.com
* Content-Type: plain/text
* Content-Length: 3
*
* Hi?
* --> END POST
*
* <-- 200 OK (22ms)
* Content-Type: plain/text
* Content-Length: 6
*
* Hello!
* <-- END HTTP
`</pre> *
*/
BODY
}
interface
Logger
{
fun
log
(
message
:
String
)
}
/** Change the level at which this interceptor logs. */
fun
setLevel
(
level
:
Level
):
HttpLoggingInterceptor
{
this
.
level
=
level
return
this
}
fun
getLevel
():
Level
{
return
level
}
@Throws
(
IOException
::
class
)
override
fun
intercept
(
chain
:
Interceptor
.
Chain
):
Response
{
val
level
=
this
.
level
val
request
=
chain
.
request
()
if
(
level
==
Level
.
NONE
)
{
return
chain
.
proceed
(
request
)
}
val
logBody
=
level
==
Level
.
BODY
val
logHeaders
=
logBody
||
level
==
Level
.
HEADERS
val
requestBody
=
request
.
body
()
val
hasRequestBody
=
requestBody
!=
null
val
connection
=
chain
.
connection
()
var
requestStartMessage
=
(
"--> ${request.method()} ${request.url()}"
+
if
(
connection
!=
null
)
" "
+
connection
.
protocol
()
else
""
)
if
(!
logHeaders
&&
hasRequestBody
)
{
requestStartMessage
+=
" (${requestBody!!.contentLength()}-byte body)"
}
logger
.
log
(
requestStartMessage
)
if
(
logHeaders
)
{
if
(
hasRequestBody
)
{
// Request body headers are only present when installed as a network interceptor. Force
// them to be included (when available) so there values are known.
if
(
requestBody
!!
.
contentType
()
!=
null
)
{
logger
.
log
(
"Content-Type: ${requestBody.contentType()!!}"
)
}
if
(
requestBody
.
contentLength
()
!=
-
1L
)
{
logger
.
log
(
"Content-Length: ${requestBody.contentLength()}"
)
}
}
val
headers
=
request
.
headers
()
var
i
=
0
val
count
=
headers
.
size
()
while
(
i
<
count
)
{
val
name
=
headers
.
name
(
i
)
// Skip headers from the request body as they are explicitly logged above.
if
(!
"Content-Type"
.
equals
(
name
,
ignoreCase
=
true
)
&&
!
"Content-Length"
.
equals
(
name
,
ignoreCase
=
true
))
{
if
(
"X-Auth-Token"
.
equals
(
name
,
ignoreCase
=
true
))
{
logger
.
log
(
"$name: ${skipAuthToken(headers.value(i).length)}"
)
}
else
{
logger
.
log
(
"$name: ${headers.value(i)}"
)
}
}
i
++
}
if
(!
logBody
||
!
hasRequestBody
)
{
logger
.
log
(
"--> END ${request.method()}"
)
}
else
if
(
bodyHasUnknownEncoding
(
request
.
headers
()))
{
logger
.
log
(
"--> END ${request.method()} (encoded body omitted)"
)
}
else
if
(
isMultipart
(
requestBody
?.
contentType
()))
{
//requestBody?.contentType()?.toString()?.contains("multipart/form-data", ignoreCase = true)) {
logger
.
log
(
"--> END ${request.method()} (multipart body omitted)"
)
}
else
if
(
hasRequestBody
)
{
val
buffer
=
Buffer
()
requestBody
!!
.
writeTo
(
buffer
)
var
charset
:
Charset
?
=
UTF8
val
contentType
=
requestBody
.
contentType
()
if
(
contentType
!=
null
)
{
charset
=
contentType
.
charset
(
UTF8
)
}
logger
.
log
(
""
)
if
(
isPlaintext
(
buffer
))
{
logger
.
log
(
buffer
.
readString
(
charset
!!
))
logger
.
log
(
"--> END "
+
request
.
method
()
+
" ("
+
requestBody
.
contentLength
()
+
"-byte body)"
)
}
else
{
logger
.
log
(
"--> END "
+
request
.
method
()
+
" (binary "
+
requestBody
.
contentLength
()
+
"-byte body omitted)"
)
}
}
}
val
startNs
=
System
.
nanoTime
()
val
response
:
Response
try
{
response
=
chain
.
proceed
(
request
)
}
catch
(
e
:
Exception
)
{
logger
.
log
(
"<-- HTTP FAILED: $e"
)
throw
e
}
val
tookMs
=
TimeUnit
.
NANOSECONDS
.
toMillis
(
System
.
nanoTime
()
-
startNs
)
val
responseBody
=
response
.
body
()
val
contentLength
=
responseBody
!!
.
contentLength
()
val
bodySize
=
if
(
contentLength
!=
-
1L
)
contentLength
.
toString
()
+
"-byte"
else
"unknown-length"
val
responseStr
=
if
(
response
.
message
().
isEmpty
())
""
else
" ${response.message()}"
logger
.
log
(
"<-- ${response.code()}$responseStr ${response.request().url()}"
+
" ("
+
tookMs
+
"ms"
+
(
if
(!
logHeaders
)
", $bodySize body"
else
""
)
+
')'
.
toString
())
if
(
logHeaders
)
{
val
headers
=
response
.
headers
()
var
i
=
0
val
count
=
headers
.
size
()
while
(
i
<
count
)
{
logger
.
log
(
headers
.
name
(
i
)
+
": "
+
headers
.
value
(
i
))
i
++
}
if
(!
logBody
||
!
HttpHeaders
.
hasBody
(
response
))
{
logger
.
log
(
"<-- END HTTP"
)
}
else
if
(
bodyHasUnknownEncoding
(
response
.
headers
()))
{
logger
.
log
(
"<-- END HTTP (encoded body omitted)"
)
}
else
{
val
source
=
responseBody
.
source
()
source
.
request
(
java
.
lang
.
Long
.
MAX_VALUE
)
// Buffer the entire body.
var
buffer
=
source
.
buffer
()
var
gzippedLength
:
Long
?
=
null
if
(
headers
.
get
(
"Content-Encoding"
)
?.
equals
(
"gzip"
,
ignoreCase
=
true
)
==
true
)
{
gzippedLength
=
buffer
.
size
()
var
gzippedResponseBody
:
GzipSource
?
=
null
try
{
gzippedResponseBody
=
GzipSource
(
buffer
.
clone
())
buffer
=
Buffer
()
buffer
.
writeAll
(
gzippedResponseBody
)
}
finally
{
if
(
gzippedResponseBody
!=
null
)
{
gzippedResponseBody
.
close
()
}
}
}
var
charset
:
Charset
?
=
UTF8
val
contentType
=
responseBody
.
contentType
()
if
(
contentType
!=
null
)
{
charset
=
contentType
.
charset
(
UTF8
)
}
if
(!
isPlaintext
(
buffer
))
{
logger
.
log
(
""
)
logger
.
log
(
"<-- END HTTP (binary "
+
buffer
.
size
()
+
"-byte body omitted)"
)
return
response
}
if
(
contentLength
!=
0L
)
{
logger
.
log
(
""
)
logger
.
log
(
buffer
.
clone
().
readString
(
charset
!!
))
}
if
(
gzippedLength
!=
null
)
{
logger
.
log
(
"<-- END HTTP ("
+
buffer
.
size
()
+
"-byte, "
+
gzippedLength
+
"-gzipped-byte body)"
)
}
else
{
logger
.
log
(
"<-- END HTTP ("
+
buffer
.
size
()
+
"-byte body)"
)
}
}
}
return
response
}
private
fun
isMultipart
(
contentType
:
MediaType
?):
Boolean
{
return
contentType
?.
let
{
contentType
.
toString
().
contains
(
"multipart/form-data"
)
}
?:
false
}
private
fun
skipAuthToken
(
length
:
Int
):
String
{
val
builder
=
StringBuilder
(
length
)
for
(
i
in
1
..
length
)
builder
.
append
(
"X"
)
return
builder
.
toString
()
}
private
fun
bodyHasUnknownEncoding
(
headers
:
Headers
):
Boolean
{
val
contentEncoding
=
headers
.
get
(
"Content-Encoding"
)
return
(
contentEncoding
!=
null
&&
!
contentEncoding
.
equals
(
"identity"
,
ignoreCase
=
true
)
&&
!
contentEncoding
.
equals
(
"gzip"
,
ignoreCase
=
true
))
}
companion
object
{
private
val
UTF8
=
Charset
.
forName
(
"UTF-8"
)
/**
* Returns true if the body in question probably contains human readable text. Uses a small sample
* of code points to detect unicode control characters commonly used in binary file signatures.
*/
internal
fun
isPlaintext
(
buffer
:
Buffer
):
Boolean
{
try
{
val
prefix
=
Buffer
()
val
byteCount
=
if
(
buffer
.
size
()
<
64
)
buffer
.
size
()
else
64
buffer
.
copyTo
(
prefix
,
0
,
byteCount
)
for
(
i
in
0
..
15
)
{
if
(
prefix
.
exhausted
())
{
break
}
val
codePoint
=
prefix
.
readUtf8CodePoint
()
if
(
Character
.
isISOControl
(
codePoint
)
&&
!
Character
.
isWhitespace
(
codePoint
))
{
return
false
}
}
return
true
}
catch
(
e
:
EOFException
)
{
return
false
// Truncated UTF-8 sequence.
}
}
}
}
app/src/main/java/chat/rocket/android/util/extensions/Ui.kt
View file @
1182d85f
...
...
@@ -31,11 +31,16 @@ fun View.isVisible(): Boolean {
fun
ViewGroup
.
inflate
(
@LayoutRes
resource
:
Int
,
attachToRoot
:
Boolean
=
false
):
View
=
LayoutInflater
.
from
(
context
).
inflate
(
resource
,
this
,
attachToRoot
)
fun
AppCompatActivity
.
addFragment
(
tag
:
String
,
layoutId
:
Int
,
newInstance
:
()
->
Fragment
)
{
fun
AppCompatActivity
.
addFragment
(
tag
:
String
,
layoutId
:
Int
,
allowStateLoss
:
Boolean
=
false
,
newInstance
:
()
->
Fragment
)
{
val
fragment
=
supportFragmentManager
.
findFragmentByTag
(
tag
)
?:
newInstance
()
supportFragmentManager
.
beginTransaction
()
val
transaction
=
supportFragmentManager
.
beginTransaction
()
.
replace
(
layoutId
,
fragment
,
tag
)
.
commit
()
if
(
allowStateLoss
)
{
transaction
.
commitAllowingStateLoss
()
}
else
{
transaction
.
commit
()
}
}
fun
AppCompatActivity
.
addFragmentBackStack
(
...
...
app/src/main/java/chat/rocket/android/util/extensions/View.kt
View file @
1182d85f
...
...
@@ -5,12 +5,17 @@ import android.support.customtabs.CustomTabsIntent
import
android.support.v4.content.res.ResourcesCompat
import
android.view.View
import
chat.rocket.android.R
import
timber.log.Timber
fun
View
.
openTabbedUrl
(
url
:
Uri
)
{
with
(
this
)
{
val
tabsbuilder
=
CustomTabsIntent
.
Builder
()
tabsbuilder
.
setToolbarColor
(
ResourcesCompat
.
getColor
(
context
.
resources
,
R
.
color
.
colorPrimary
,
context
.
theme
))
val
customTabsIntent
=
tabsbuilder
.
build
()
try
{
customTabsIntent
.
launchUrl
(
context
,
url
)
}
catch
(
ex
:
Exception
)
{
Timber
.
d
(
ex
,
"Unable to launch URL"
)
}
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment