Commit 99cc983d authored by Filipe de Lima Brito's avatar Filipe de Lima Brito

Merge branch 'develop' of github.com:RocketChat/Rocket.Chat.Android into new/answers-analytics

parents d9845702 b404ba00
...@@ -64,7 +64,7 @@ jobs: ...@@ -64,7 +64,7 @@ jobs:
- store_artifacts: - store_artifacts:
path: app/build/reports/ path: app/build/reports/
destination: reports destination: reports
build-apk: build-play-apk:
docker: docker:
- image: circleci/android:api-27-alpha - image: circleci/android:api-27-alpha
environment: environment:
...@@ -93,7 +93,40 @@ jobs: ...@@ -93,7 +93,40 @@ jobs:
- run: - run:
name: Build APK name: Build APK
command: | command: |
./gradlew assembleRelease --info --console=plain --stacktrace ./gradlew assemblePlayRelease --info --console=plain --stacktrace
- store_artifacts:
path: app/build/outputs/apk
destination: apks
build-foss-apk:
docker:
- image: circleci/android:api-27-alpha
environment:
JVM_OPTS: -Xmx3200m
steps:
- checkout
- run:
name: restore files from ENV
command: |
echo $ROCKET_JKS_BASE64 | base64 --decode > Rocket.jks
echo $ROCKET_PLAY_JSON | base64 --decode > app/rocket-chat.json
- run:
name: checkout Rocket.Chat.Kotlin.SDK
command: git clone https://github.com/RocketChat/Rocket.Chat.Kotlin.SDK.git ../Rocket.Chat.Kotlin.SDK
- restore_cache:
key: kotlin-sdk-{{ .Revision }}
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}-{{ checksum "player/build.gradle" }}
- run:
name: Download Dependencies
command: ./gradlew androidDependencies --quiet --console=plain
- save_cache:
paths:
- ~/.gradle
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}-{{ checksum "player/build.gradle" }}
- run:
name: Build APK
command: |
./gradlew assembleFossRelease --info --console=plain --stacktrace
- store_artifacts: - store_artifacts:
path: app/build/outputs/apk path: app/build/outputs/apk
destination: apks destination: apks
...@@ -112,6 +145,9 @@ workflows: ...@@ -112,6 +145,9 @@ workflows:
- develop - develop
- develop-2.x - develop-2.x
- master - master
- build-apk: - build-play-apk:
requires:
- build-kotlin-sdk
- build-foss-apk:
requires: requires:
- build-kotlin-sdk - build-kotlin-sdk
#!/bin/bash #!/bin/bash
CURRENT_DIR=$(pwd) CURRENT_DIR=$(pwd)
# The SDK dir should be 2 directories up in the tree, so we use dirname 2 times
# to get the common parent dir of the SDK and the app
GIT=$(which git) GIT=$(which git)
cd ../..
tmp=$(pwd) if [ "$#" -eq 1 ] && [ ! -z "$1" ]; then
SDK_DIR="$tmp/Rocket.Chat.Kotlin.SDK" # if in an argument is given this is the (relative) path to SDK_DIR
cd "${CURRENT_DIR}" SDK_DIR=$(readlink -f $1)
else
# The SDK dir should be 2 directories up in the tree, so we use dirname 2 times
# to get the common parent dir of the SDK and the app
cd ../..
tmp=$(pwd)
SDK_DIR="$tmp/Rocket.Chat.Kotlin.SDK"
cd "${CURRENT_DIR}"
fi
echo "CURRENT DIR: $CURRENT_DIR" echo "CURRENT DIR: $CURRENT_DIR"
echo "SDK DIR: $SDK_DIR" echo "SDK DIR: $SDK_DIR"
...@@ -99,4 +105,4 @@ cp -v "${SDK_DIR}"/core/build/libs/core-0.1-SNAPSHOT.jar "${CURRENT_DIR}"/libs/c ...@@ -99,4 +105,4 @@ cp -v "${SDK_DIR}"/core/build/libs/core-0.1-SNAPSHOT.jar "${CURRENT_DIR}"/libs/c
echo "$SHA" > "${SDK_DIR}"/.last_commit_hash echo "$SHA" > "${SDK_DIR}"/.last_commit_hash
exit 0 exit 0
\ No newline at end of file
def taskRequests = getGradle().getStartParameter().getTaskRequests().toString()
def isPlay = !(taskRequests.contains("Foss") || taskRequests.contains("foss"))
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
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'
...@@ -17,6 +20,10 @@ android { ...@@ -17,6 +20,10 @@ android {
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 buildTime = new GregorianCalendar().format("MM-dd-yyyy' 'h:mm:ss a z")
buildConfigField "String", "GIT_SHA", "\"${gitSha}\""
javaCompileOptions { javaCompileOptions {
annotationProcessorOptions { annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
...@@ -57,6 +64,20 @@ android { ...@@ -57,6 +64,20 @@ android {
} }
} }
flavorDimensions "type"
productFlavors {
// includes proprietary libs
play {
dimension "type"
}
// only foss
foss {
dimension "type"
}
}
packagingOptions { packagingOptions {
exclude 'META-INF/core.kotlin_module' exclude 'META-INF/core.kotlin_module'
exclude 'META-INF/main.kotlin_module' exclude 'META-INF/main.kotlin_module'
...@@ -88,6 +109,7 @@ dependencies { ...@@ -88,6 +109,7 @@ dependencies {
implementation libraries.daggerSupport implementation libraries.daggerSupport
kapt libraries.daggerProcessor kapt libraries.daggerProcessor
kapt libraries.daggerAndroidApt kapt libraries.daggerAndroidApt
implementation libraries.fcm implementation libraries.fcm
implementation libraries.firebaseAnalytics implementation libraries.firebaseAnalytics
implementation libraries.playServicesAuth implementation libraries.playServicesAuth
...@@ -126,7 +148,10 @@ dependencies { ...@@ -126,7 +148,10 @@ dependencies {
implementation "com.github.luciofm:livedata-ktx:b1e8bbc25a" implementation "com.github.luciofm:livedata-ktx:b1e8bbc25a"
implementation('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') { playImplementation libraries.fcm
playImplementation libraries.playServicesAuth
playImplementation('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') {
transitive = true transitive = true
} }
...@@ -152,13 +177,16 @@ androidExtensions { ...@@ -152,13 +177,16 @@ 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'] ?: ""
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' commandLine 'cmd', '/c', 'build-sdk.sh', sdk_location
} else { } else {
commandLine './build-sdk.sh' commandLine './build-sdk.sh', sdk_location
} }
} }
preBuild.dependsOn compileSdk preBuild.dependsOn compileSdk
if (isPlay) {
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'
}
package chat.rocket.android.dagger.module
import chat.rocket.android.chatroom.di.MessageServiceProvider
import chat.rocket.android.chatroom.service.MessageService
import dagger.Module
import dagger.android.ContributesAndroidInjector
@Module abstract class ServiceBuilder {
@ContributesAndroidInjector(modules = [MessageServiceProvider::class])
abstract fun bindMessageService(): MessageService
}
package chat.rocket.android.helper
import android.app.Activity
import android.content.Intent
import androidx.fragment.app.FragmentActivity
fun FragmentActivity.saveCredentials(id: String, password: String) {
}
fun Activity.requestStoredCredentials(): Pair<String, String>? = null
fun getCredentials(data: Intent): Pair<String, String>? = null
fun hasCredentialsSupport() = false
\ No newline at end of file
package chat.rocket.android.helper
import timber.log.Timber
import android.util.Log
class CrashlyticsTree : Timber.Tree() {
override fun log(priority: Int, tag: String?, message: String, throwable: Throwable?) {
Log.println(priority, tag, message)
if (throwable != null) {
Log.e(tag,throwable.toString())
}
}
}
package chat.rocket.android.push
class FirebaseTokenService {
}
\ No newline at end of file
package chat.rocket.android.util
import android.content.Context
fun setupFabric(context: Context) {
//Do absolutely nothing
}
package chat.rocket.android.util
import chat.rocket.android.main.presentation.MainPresenter
fun refreshFCMToken(presenter: MainPresenter) {
//Do absolutely nothing
}
fun invalidateFirebaseToken(token: String) {
//Do absolutely nothing
}
\ No newline at end of file
...@@ -95,23 +95,6 @@ ...@@ -95,23 +95,6 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<service
android:name=".push.FirebaseTokenService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service
android:name=".push.FirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service <service
android:name=".chatroom.service.MessageService" android:name=".chatroom.service.MessageService"
android:exported="true" android:exported="true"
...@@ -122,4 +105,4 @@ ...@@ -122,4 +105,4 @@
android:value="12ac6e94f850aaffcdff52001af77ca415d06a43" /> android:value="12ac6e94f850aaffcdff52001af77ca415d06a43" />
</application> </application>
</manifest> </manifest>
\ No newline at end of file
...@@ -4,6 +4,7 @@ import android.os.Bundle ...@@ -4,6 +4,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import chat.rocket.android.BuildConfig import chat.rocket.android.BuildConfig
import chat.rocket.android.R import chat.rocket.android.R
...@@ -30,8 +31,9 @@ class AboutFragment : Fragment() { ...@@ -30,8 +31,9 @@ class AboutFragment : Fragment() {
} }
private fun setupViews() { private fun setupViews() {
text_version_name.text = getString(R.string.msg_version, BuildConfig.VERSION_NAME) text_version_name.text = BuildConfig.VERSION_NAME
text_build_number.text = getString(R.string.msg_build, BuildConfig.VERSION_CODE) text_build_number.text = getString(R.string.msg_build, BuildConfig.VERSION_CODE,
BuildConfig.GIT_SHA, BuildConfig.FLAVOR)
} }
private fun setupToolbar() { private fun setupToolbar() {
......
...@@ -22,6 +22,9 @@ class AppLifecycleObserver @Inject constructor( ...@@ -22,6 +22,9 @@ class AppLifecycleObserver @Inject constructor(
@OnLifecycleEvent(Lifecycle.Event.ON_START) @OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onEnterForeground() { fun onEnterForeground() {
changeTemporaryStatus(UserStatus.Online()) changeTemporaryStatus(UserStatus.Online())
serverInteractor.get()?.let { currentServer ->
factory.create(currentServer).resetReconnectionTimer()
}
} }
@OnLifecycleEvent(Lifecycle.Event.ON_STOP) @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
......
...@@ -13,16 +13,13 @@ import chat.rocket.android.dagger.DaggerAppComponent ...@@ -13,16 +13,13 @@ import chat.rocket.android.dagger.DaggerAppComponent
import chat.rocket.android.dagger.qualifier.ForMessages import chat.rocket.android.dagger.qualifier.ForMessages
import chat.rocket.android.helper.CrashlyticsTree import chat.rocket.android.helper.CrashlyticsTree
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.installCrashlyticsWrapper
import chat.rocket.android.server.domain.AccountsRepository import chat.rocket.android.server.domain.AccountsRepository
import chat.rocket.android.server.domain.GetCurrentServerInteractor 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 chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.emoji.EmojiRepository import chat.rocket.android.emoji.EmojiRepository
import com.crashlytics.android.Crashlytics import chat.rocket.android.util.setupFabric
import com.crashlytics.android.answers.Answers
import com.crashlytics.android.core.CrashlyticsCore
import com.facebook.drawee.backends.pipeline.DraweeConfig import com.facebook.drawee.backends.pipeline.DraweeConfig
import com.facebook.drawee.backends.pipeline.Fresco import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.imagepipeline.core.ImagePipelineConfig import com.facebook.imagepipeline.core.ImagePipelineConfig
...@@ -32,7 +29,6 @@ import dagger.android.DispatchingAndroidInjector ...@@ -32,7 +29,6 @@ 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 io.fabric.sdk.android.Fabric
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
...@@ -90,7 +86,7 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje ...@@ -90,7 +86,7 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
AndroidThreeTen.init(this) AndroidThreeTen.init(this)
EmojiRepository.load(this) EmojiRepository.load(this)
setupFabric() setupFabric(this)
setupFresco() setupFresco()
setupTimber() setupTimber()
...@@ -126,25 +122,6 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje ...@@ -126,25 +122,6 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
} }
} }
private fun setupFabric() {
val core = CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()
Fabric.with(
this,
Crashlytics.Builder()
.core(core) // For Crashlytics
.answers(Answers()) // For Answers
.build()
)
installCrashlyticsWrapper(
this@RocketChatApplication,
getCurrentServerInteractor,
settingsInteractor,
accountRepository,
localRepository
)
}
private fun setupFresco() { private fun setupFresco() {
Fresco.initialize(this, imagePipelineConfig, draweeConfig) Fresco.initialize(this, imagePipelineConfig, draweeConfig)
} }
...@@ -180,4 +157,4 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje ...@@ -180,4 +157,4 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
private fun LocalRepository.needOldMessagesCleanUp() = getBoolean(CLEANUP_OLD_MESSAGES_NEEDED, true) private fun LocalRepository.needOldMessagesCleanUp() = getBoolean(CLEANUP_OLD_MESSAGES_NEEDED, true)
private fun LocalRepository.setOldMessagesCleanedUp() = save(CLEANUP_OLD_MESSAGES_NEEDED, false) private fun LocalRepository.setOldMessagesCleanedUp() = save(CLEANUP_OLD_MESSAGES_NEEDED, false)
private const val CLEANUP_OLD_MESSAGES_NEEDED = "CLEANUP_OLD_MESSAGES_NEEDED" private const val CLEANUP_OLD_MESSAGES_NEEDED = "CLEANUP_OLD_MESSAGES_NEEDED"
\ No newline at end of file
...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.login.presentation ...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.login.presentation
import chat.rocket.android.core.behaviours.LoadingView import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView import chat.rocket.android.core.behaviours.MessageView
import com.google.android.gms.auth.api.credentials.Credential
interface LoginView : LoadingView, MessageView { interface LoginView : LoadingView, MessageView {
......
...@@ -31,13 +31,14 @@ import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_SECRET ...@@ -31,13 +31,14 @@ import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_SECRET
import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_TOKEN import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_TOKEN
import chat.rocket.android.webview.oauth.ui.oauthWebViewIntent import chat.rocket.android.webview.oauth.ui.oauthWebViewIntent
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import com.google.android.gms.auth.api.credentials.*
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_log_in.* import kotlinx.android.synthetic.main.fragment_authentication_log_in.*
import javax.inject.Inject import javax.inject.Inject
internal const val TAG_LOGIN_FRAGMENT = "LoginFragment" internal const val TAG_LOGIN_FRAGMENT = "LoginFragment"
internal const val REQUEST_CODE_FOR_SIGN_IN_REQUIRED = 1
internal const val REQUEST_CODE_FOR_MULTIPLE_ACCOUNTS_RESOLUTION = 2
internal const val REQUEST_CODE_FOR_SAVE_RESOLUTION = 3
internal const val REQUEST_CODE_FOR_CAS = 4 internal const val REQUEST_CODE_FOR_CAS = 4
internal const val REQUEST_CODE_FOR_SAML = 5 internal const val REQUEST_CODE_FOR_SAML = 5
internal const val REQUEST_CODE_FOR_OAUTH = 6 internal const val REQUEST_CODE_FOR_OAUTH = 6
...@@ -51,7 +52,6 @@ class LoginFragment : Fragment(), LoginView { ...@@ -51,7 +52,6 @@ class LoginFragment : Fragment(), LoginView {
} }
private var isGlobalLayoutListenerSetUp = false private var isGlobalLayoutListenerSetUp = false
private var deepLinkInfo: LoginDeepLinkInfo? = null private var deepLinkInfo: LoginDeepLinkInfo? = null
private val credentialsClient by lazy { Credentials.getClient(requireActivity()) }
companion object { companion object {
private const val DEEP_LINK_INFO = "DeepLinkInfo" private const val DEEP_LINK_INFO = "DeepLinkInfo"
...@@ -89,6 +89,10 @@ class LoginFragment : Fragment(), LoginView { ...@@ -89,6 +89,10 @@ class LoginFragment : Fragment(), LoginView {
presenter.setupView() presenter.setupView()
} }
if (!hasCredentialsSupport()) {
image_key.isVisible = false
}
AnswersEvent.logScreenView(TAG_LOGIN_FRAGMENT) AnswersEvent.logScreenView(TAG_LOGIN_FRAGMENT)
} }
...@@ -105,13 +109,15 @@ class LoginFragment : Fragment(), LoginView { ...@@ -105,13 +109,15 @@ class LoginFragment : Fragment(), LoginView {
if (data != null) { if (data != null) {
when (requestCode) { when (requestCode) {
REQUEST_CODE_FOR_MULTIPLE_ACCOUNTS_RESOLUTION -> { REQUEST_CODE_FOR_MULTIPLE_ACCOUNTS_RESOLUTION -> {
onCredentialRetrieved(data.getParcelableExtra(Credential.EXTRA_KEY)) getCredentials(data)?.let {
onCredentialRetrieved(it.first, it.second)
}
} }
REQUEST_CODE_FOR_SIGN_IN_REQUIRED -> { REQUEST_CODE_FOR_SIGN_IN_REQUIRED -> {
//use the hints to autofill sign in forms to reduce the info to be filled. getCredentials(data)?.let { credential ->
val credential: Credential = data.getParcelableExtra(Credential.EXTRA_KEY) text_username_or_email.setText(credential.first)
text_username_or_email.setText(credential.id) text_password.setText(credential.second)
text_password.setText(credential.password) }
} }
REQUEST_CODE_FOR_SAVE_RESOLUTION -> { REQUEST_CODE_FOR_SAVE_RESOLUTION -> {
showMessage(getString(R.string.message_credentials_saved_successfully)) showMessage(getString(R.string.message_credentials_saved_successfully))
...@@ -159,19 +165,19 @@ class LoginFragment : Fragment(), LoginView { ...@@ -159,19 +165,19 @@ class LoginFragment : Fragment(), LoginView {
private fun requestStoredCredentials() { private fun requestStoredCredentials() {
activity?.let { activity?.let {
SmartLockHelper.requestStoredCredentials(credentialsClient, it)?.let { it.requestStoredCredentials()?.let { credentials ->
onCredentialRetrieved(it) onCredentialRetrieved(credentials.first, credentials.second)
} }
} }
} }
private fun onCredentialRetrieved(credential: Credential) { private fun onCredentialRetrieved(id: String, password: String) {
presenter.authenticateWithUserAndPassword(credential.id, credential.password.toString()) presenter.authenticateWithUserAndPassword(id, password)
} }
override fun saveSmartLockCredentials(id: String, password: String) { override fun saveSmartLockCredentials(id: String, password: String) {
activity?.let { activity?.let {
SmartLockHelper.save(credentialsClient, it, id, password) it.saveCredentials(id, password)
} }
} }
......
...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.signup.presentation ...@@ -2,7 +2,6 @@ package chat.rocket.android.authentication.signup.presentation
import chat.rocket.android.core.behaviours.LoadingView import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView import chat.rocket.android.core.behaviours.MessageView
import com.google.android.gms.auth.api.credentials.Credential
interface SignupView : LoadingView, MessageView { interface SignupView : LoadingView, MessageView {
......
...@@ -16,11 +16,10 @@ import chat.rocket.android.R.string.message_credentials_saved_successfully ...@@ -16,11 +16,10 @@ import chat.rocket.android.R.string.message_credentials_saved_successfully
import chat.rocket.android.authentication.signup.presentation.SignupPresenter import chat.rocket.android.authentication.signup.presentation.SignupPresenter
import chat.rocket.android.authentication.signup.presentation.SignupView import chat.rocket.android.authentication.signup.presentation.SignupView
import chat.rocket.android.helper.KeyboardHelper import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.SmartLockHelper
import chat.rocket.android.helper.TextHelper import chat.rocket.android.helper.TextHelper
import chat.rocket.android.helper.saveCredentials
import chat.rocket.android.util.extensions.* import chat.rocket.android.util.extensions.*
import chat.rocket.android.util.helper.AnswersEvent import chat.rocket.android.util.helper.AnswersEvent
import com.google.android.gms.auth.api.credentials.Credentials
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_sign_up.* import kotlinx.android.synthetic.main.fragment_authentication_sign_up.*
import javax.inject.Inject import javax.inject.Inject
...@@ -159,9 +158,7 @@ class SignupFragment : Fragment(), SignupView { ...@@ -159,9 +158,7 @@ class SignupFragment : Fragment(), SignupView {
} }
override fun saveSmartLockCredentials(id: String, password: String) { override fun saveSmartLockCredentials(id: String, password: String) {
activity?.let { activity?.saveCredentials(id, password)
SmartLockHelper.save(Credentials.getClient(it), it, id, password)
}
} }
private fun tintEditTextDrawableStart() { private fun tintEditTextDrawableStart() {
......
...@@ -220,7 +220,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -220,7 +220,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
AlertDialog.Builder(context) AlertDialog.Builder(context)
.setTitle(R.string.dialog_sort_title) .setTitle(R.string.dialog_sort_title)
.setView(dialogLayout) .setView(dialogLayout)
.setPositiveButton("Done") { dialog, _ -> .setPositiveButton(R.string.dialog_button_done) { dialog, _ ->
invalidateQueryOnSearch() invalidateQueryOnSearch()
updateSort() updateSort()
dialog.dismiss() dialog.dismiss()
......
...@@ -165,7 +165,7 @@ class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback ...@@ -165,7 +165,7 @@ class CreateChannelFragment : Fragment(), CreateChannelView, ActionMode.Callback
override fun prepareToShowChatList() { override fun prepareToShowChatList() {
with(activity as MainActivity) { with(activity as MainActivity) {
setCheckedNavDrawerItem(R.id.action_chat_rooms) setCheckedNavDrawerItem(R.id.menu_action_chats)
openDrawer() openDrawer()
getDrawerLayout().postDelayed(1000) { getDrawerLayout().postDelayed(1000) {
closeDrawer() closeDrawer()
......
...@@ -2,7 +2,6 @@ package chat.rocket.android.helper ...@@ -2,7 +2,6 @@ package chat.rocket.android.helper
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.SettingsRepository import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.common.model.SimpleUser import chat.rocket.common.model.SimpleUser
...@@ -12,43 +11,13 @@ import javax.inject.Inject ...@@ -12,43 +11,13 @@ import javax.inject.Inject
class UserHelper @Inject constructor( class UserHelper @Inject constructor(
private val localRepository: LocalRepository, private val localRepository: LocalRepository,
private val getCurrentServerInteractor: GetCurrentServerInteractor, private val getCurrentServerInteractor: GetCurrentServerInteractor,
settingsRepository: SettingsRepository private val settingsRepository: SettingsRepository
) { ) {
private val settings: PublicSettings = settingsRepository.get(getCurrentServerInteractor.get()!!)
/**
* Return the display name for the given [user].
* If setting 'Use_Real_Name' is true then the real name will be given, or else
* the username without the '@' is yielded. The fallback for any case is the username, which
* could be null.
*/
fun displayName(user: User): String? {
return if (settings.useRealName()) user.name ?: user.username else user.username
}
fun displayName(user: SimpleUser): String {
return if (settings.useRealName()) user.name ?: user.username ?: "" else user.username ?: ""
}
/**
* Return current logged user's display name.
*
* @see displayName
*/
fun displayName(): String? {
user()?.let {
return displayName(it)
}
return null
}
/** /**
* Return current logged [User]. * Return current logged [User].
*/ */
fun user(): User? { fun user(): User? = getCurrentServerInteractor.get()?.let { localRepository.getCurrentUser(it) }
return localRepository.getCurrentUser(serverUrl())
}
/** /**
* Return the username for the current logged [User]. * Return the username for the current logged [User].
...@@ -56,13 +25,20 @@ class UserHelper @Inject constructor( ...@@ -56,13 +25,20 @@ class UserHelper @Inject constructor(
fun username(): String? = localRepository.get(LocalRepository.CURRENT_USERNAME_KEY, null) fun username(): String? = localRepository.get(LocalRepository.CURRENT_USERNAME_KEY, null)
/** /**
* Whether current [User] is admin on the current server. * Return the display name for the given [user].
* If setting 'Use_Real_Name' is true then the real name will be given, otherwise the username
* without the '@' is yielded.
*/ */
fun isAdmin(): Boolean { fun displayName(user: SimpleUser) = getCurrentServerInteractor.get()?.let {
return user()?.roles?.find { it.equals("admin", ignoreCase = true) } != null if (settingsRepository.get(it).useRealName()) {
} user.name
} else {
user.username
}
}.orEmpty()
private fun serverUrl(): String { /**
return getCurrentServerInteractor.get()!! * Whether current [User] is admin on the current server.
} */
} fun isAdmin(): Boolean = user()?.roles?.find { it.equals("admin", true) } != null
\ No newline at end of file }
...@@ -14,6 +14,7 @@ import chat.rocket.android.server.ui.changeServerIntent ...@@ -14,6 +14,7 @@ import chat.rocket.android.server.ui.changeServerIntent
import chat.rocket.android.settings.ui.SettingsFragment import chat.rocket.android.settings.ui.SettingsFragment
import chat.rocket.android.settings.ui.TAG_SETTINGS_FRAGMENT import chat.rocket.android.settings.ui.TAG_SETTINGS_FRAGMENT
import chat.rocket.android.util.extensions.addFragment import chat.rocket.android.util.extensions.addFragment
import chat.rocket.android.webview.adminpanel.ui.AdminPanelWebViewFragment
class MainNavigator(internal val activity: MainActivity) { class MainNavigator(internal val activity: MainActivity) {
...@@ -41,6 +42,12 @@ class MainNavigator(internal val activity: MainActivity) { ...@@ -41,6 +42,12 @@ class MainNavigator(internal val activity: MainActivity) {
} }
} }
fun toAdminPanel(webPageUrl: String, userToken: String) {
activity.addFragment("AdminPanelWebViewFragment", R.id.fragment_container) {
AdminPanelWebViewFragment.newInstance(webPageUrl, userToken)
}
}
fun toChatRoom( fun toChatRoom(
chatRoomId: String, chatRoomId: String,
chatRoomName: String, chatRoomName: String,
......
...@@ -11,6 +11,7 @@ import chat.rocket.android.server.domain.GetCurrentServerInteractor ...@@ -11,6 +11,7 @@ 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.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.RefreshSettingsInteractor import chat.rocket.android.server.domain.RefreshSettingsInteractor
import chat.rocket.android.server.domain.RefreshPermissionsInteractor
import chat.rocket.android.server.domain.RemoveAccountInteractor import chat.rocket.android.server.domain.RemoveAccountInteractor
import chat.rocket.android.server.domain.SaveAccountInteractor import chat.rocket.android.server.domain.SaveAccountInteractor
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
...@@ -20,6 +21,7 @@ import chat.rocket.android.server.infraestructure.ConnectionManagerFactory ...@@ -20,6 +21,7 @@ import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
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 chat.rocket.android.util.extensions.adminPanelUrl
import chat.rocket.android.util.extensions.registerPushToken import chat.rocket.android.util.extensions.registerPushToken
import chat.rocket.android.util.extensions.serverLogoUrl import chat.rocket.android.util.extensions.serverLogoUrl
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
...@@ -45,6 +47,7 @@ class MainPresenter @Inject constructor( ...@@ -45,6 +47,7 @@ class MainPresenter @Inject constructor(
private val tokenRepository: TokenRepository, private val tokenRepository: TokenRepository,
private val serverInteractor: GetCurrentServerInteractor, private val serverInteractor: GetCurrentServerInteractor,
private val refreshSettingsInteractor: RefreshSettingsInteractor, private val refreshSettingsInteractor: RefreshSettingsInteractor,
private val refreshPermissionsInteractor: RefreshPermissionsInteractor,
private val localRepository: LocalRepository, private val localRepository: LocalRepository,
private val navHeaderMapper: NavHeaderUiModelMapper, private val navHeaderMapper: NavHeaderUiModelMapper,
private val saveAccountInteractor: SaveAccountInteractor, private val saveAccountInteractor: SaveAccountInteractor,
...@@ -61,7 +64,6 @@ class MainPresenter @Inject constructor( ...@@ -61,7 +64,6 @@ class MainPresenter @Inject constructor(
private val dbManager = dbManagerFactory.create(currentServer) private val dbManager = dbManagerFactory.create(currentServer)
private val client: RocketChatClient = factory.create(currentServer) private val client: RocketChatClient = factory.create(currentServer)
private var settings: PublicSettings = getSettingsInteractor.get(serverInteractor.get()!!) private var settings: PublicSettings = getSettingsInteractor.get(serverInteractor.get()!!)
private val userDataChannel = Channel<Myself>() private val userDataChannel = Channel<Myself>()
fun toChatList(chatRoomId: String? = null) = navigator.toChatList(chatRoomId) fun toChatList(chatRoomId: String? = null) = navigator.toChatList(chatRoomId)
...@@ -70,6 +72,10 @@ class MainPresenter @Inject constructor( ...@@ -70,6 +72,10 @@ class MainPresenter @Inject constructor(
fun toSettings() = navigator.toSettings() fun toSettings() = navigator.toSettings()
fun toAdminPanel() = tokenRepository.get(currentServer)?.let {
navigator.toAdminPanel(currentServer.adminPanelUrl(), it.authToken)
}
fun toCreateChannel() = navigator.toCreateChannel() fun toCreateChannel() = navigator.toCreateChannel()
fun loadServerAccounts() { fun loadServerAccounts() {
...@@ -153,6 +159,7 @@ class MainPresenter @Inject constructor( ...@@ -153,6 +159,7 @@ class MainPresenter @Inject constructor(
fun connect() { fun connect() {
refreshSettingsInteractor.refreshAsync(currentServer) refreshSettingsInteractor.refreshAsync(currentServer)
refreshPermissionsInteractor.refreshAsync(currentServer)
manager.connect() manager.connect()
} }
......
...@@ -5,10 +5,9 @@ import android.app.Activity ...@@ -5,10 +5,9 @@ import android.app.Activity
import android.app.AlertDialog import android.app.AlertDialog
import android.app.ProgressDialog import android.app.ProgressDialog
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.MenuItem
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
...@@ -19,15 +18,16 @@ import chat.rocket.android.main.adapter.Selector ...@@ -19,15 +18,16 @@ import chat.rocket.android.main.adapter.Selector
import chat.rocket.android.main.presentation.MainPresenter import chat.rocket.android.main.presentation.MainPresenter
import chat.rocket.android.main.presentation.MainView import chat.rocket.android.main.presentation.MainView
import chat.rocket.android.main.uimodel.NavHeaderUiModel import chat.rocket.android.main.uimodel.NavHeaderUiModel
import chat.rocket.android.server.domain.PermissionsInteractor
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.ui.INTENT_CHAT_ROOM_ID import chat.rocket.android.server.ui.INTENT_CHAT_ROOM_ID
import chat.rocket.android.util.extensions.fadeIn import chat.rocket.android.util.extensions.fadeIn
import chat.rocket.android.util.extensions.fadeOut import chat.rocket.android.util.extensions.fadeOut
import chat.rocket.android.util.extensions.rotateBy import chat.rocket.android.util.extensions.rotateBy
import chat.rocket.android.util.extensions.showToast import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.invalidateFirebaseToken
import chat.rocket.android.util.refreshFCMToken
import chat.rocket.common.model.UserStatus import chat.rocket.common.model.UserStatus
import com.google.firebase.iid.FirebaseInstanceId
import com.google.firebase.messaging.FirebaseMessaging
import dagger.android.AndroidInjection import dagger.android.AndroidInjection
import dagger.android.AndroidInjector import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector import dagger.android.DispatchingAndroidInjector
...@@ -51,6 +51,8 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector, ...@@ -51,6 +51,8 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector,
lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment> lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
@Inject @Inject
lateinit var presenter: MainPresenter lateinit var presenter: MainPresenter
@Inject
lateinit var permissions: PermissionsInteractor
private var isFragmentAdded: Boolean = false private var isFragmentAdded: Boolean = false
private var expanded = false private var expanded = false
private val headerLayout by lazy { view_navigation.getHeaderView(0) } private val headerLayout by lazy { view_navigation.getHeaderView(0) }
...@@ -63,13 +65,7 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector, ...@@ -63,13 +65,7 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector,
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
launch(CommonPool) { launch(CommonPool) {
try { refreshFCMToken(presenter)
val token = FirebaseInstanceId.getInstance().token
Timber.d("FCM token: $token")
presenter.refreshToken(token)
} catch (ex: Exception) {
Timber.d(ex, "Missing play services...")
}
} }
chatRoomId = intent.getStringExtra(INTENT_CHAT_ROOM_ID) chatRoomId = intent.getStringExtra(INTENT_CHAT_ROOM_ID)
...@@ -172,9 +168,9 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector, ...@@ -172,9 +168,9 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector,
} }
headerLayout.image_avatar.setOnClickListener { headerLayout.image_avatar.setOnClickListener {
view_navigation.menu.findItem(R.id.action_profile).isChecked = true view_navigation.menu.findItem(R.id.menu_action_profile).isChecked = true
presenter.toUserProfile() presenter.toUserProfile()
drawer_layout.closeDrawer(Gravity.START) drawer_layout.closeDrawer(GravityCompat.START)
} }
} }
...@@ -211,7 +207,7 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector, ...@@ -211,7 +207,7 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector,
} }
override fun invalidateToken(token: String) = override fun invalidateToken(token: String) =
FirebaseInstanceId.getInstance().deleteToken(token, FirebaseMessaging.INSTANCE_ID_SCOPE) invalidateFirebaseToken(token)
override fun showMessage(resId: Int) = showToast(resId) override fun showMessage(resId: Int) = showToast(resId)
...@@ -224,37 +220,20 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector, ...@@ -224,37 +220,20 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector,
} }
fun setupNavigationView() { fun setupNavigationView() {
view_navigation.setNavigationItemSelectedListener { menuItem -> with (view_navigation.menu) {
menuItem.isChecked = true clear()
setupMenu(this)
}
view_navigation.setNavigationItemSelectedListener {
it.isChecked = true
closeDrawer() closeDrawer()
onNavDrawerItemSelected(menuItem) onNavDrawerItemSelected(it)
true true
} }
toolbar.setNavigationIcon(R.drawable.ic_menu_white_24dp) toolbar.setNavigationIcon(R.drawable.ic_menu_white_24dp)
toolbar.setNavigationOnClickListener { toolbar.setNavigationOnClickListener { openDrawer() }
openDrawer()
}
}
private fun onNavDrawerItemSelected(menuItem: MenuItem) {
when (menuItem.itemId) {
R.id.action_chat_rooms -> {
presenter.toChatList()
}
R.id.action_profile -> {
presenter.toUserProfile()
}
R.id.action_channel -> {
presenter.toCreateChannel()
}
R.id.action_settings -> {
presenter.toSettings()
}
R.id.action_logout -> {
presenter.logout()
}
}
} }
fun setAvatar(avatarUrl: String) { fun setAvatar(avatarUrl: String) {
...@@ -263,9 +242,9 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector, ...@@ -263,9 +242,9 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector,
fun getDrawerLayout(): DrawerLayout = drawer_layout fun getDrawerLayout(): DrawerLayout = drawer_layout
fun openDrawer() = drawer_layout.openDrawer(Gravity.START) fun openDrawer() = drawer_layout.openDrawer(GravityCompat.START)
fun closeDrawer() = drawer_layout.closeDrawer(Gravity.START) fun closeDrawer() = drawer_layout.closeDrawer(GravityCompat.START)
fun setCheckedNavDrawerItem(@IdRes item: Int) = view_navigation.setCheckedItem(item) fun setCheckedNavDrawerItem(@IdRes item: Int) = view_navigation.setCheckedItem(item)
......
package chat.rocket.android.main.ui
import android.view.Menu
import android.view.MenuItem
import chat.rocket.android.R
internal fun MainActivity.setupMenu(menu: Menu) {
with(menu) {
add(
R.id.menu_section_one,
R.id.menu_action_chats,
Menu.NONE,
R.string.title_chats
).setIcon(R.drawable.ic_chat_bubble_black_24dp)
.isChecked = true
add(
R.id.menu_section_one,
R.id.menu_action_create_channel,
Menu.NONE,
R.string.action_create_channel
).setIcon(R.drawable.ic_create_black_24dp)
add(
R.id.menu_section_two,
R.id.menu_action_profile,
Menu.NONE,
R.string.title_profile
).setIcon(R.drawable.ic_person_black_24dp)
add(
R.id.menu_section_two,
R.id.menu_action_settings,
Menu.NONE,
R.string.title_settings
).setIcon(R.drawable.ic_settings_black_24dp)
if (permissions.canSeeTheAdminPanel()) {
add(
R.id.menu_section_two,
R.id.menu_action_admin_panel,
Menu.NONE,
R.string.title_admin_panel
).setIcon(R.drawable.ic_settings_black_24dp)
}
add(
R.id.menu_section_three,
R.id.menu_action_logout,
Menu.NONE,
R.string.action_logout
).setIcon(R.drawable.ic_logout_black_24dp)
setGroupCheckable(R.id.menu_section_one, true, true)
setGroupCheckable(R.id.menu_section_two, true, true)
setGroupCheckable(R.id.menu_section_three, true, true)
}
}
internal fun MainActivity.onNavDrawerItemSelected(menuItem: MenuItem) {
when (menuItem.itemId) {
R.id.menu_action_chats-> presenter.toChatList()
R.id.menu_action_create_channel -> presenter.toCreateChannel()
R.id.menu_action_profile -> presenter.toUserProfile()
R.id.menu_action_settings -> presenter.toSettings()
R.id.menu_action_admin_panel -> presenter.toAdminPanel()
R.id.menu_action_logout -> presenter.logout()
}
}
package chat.rocket.android.server.domain package chat.rocket.android.server.domain
import chat.rocket.android.helper.UserHelper import chat.rocket.android.helper.UserHelper
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.core.model.Permission
import javax.inject.Inject import javax.inject.Inject
// Creating rooms // Creating rooms
const val CREATE_PUBLIC_CHANNELS = "create-c" private const val CREATE_PUBLIC_CHANNELS = "create-c"
const val CREATE_DIRECT_MESSAGES = "create-d" private const val CREATE_DIRECT_MESSAGES = "create-d"
const val CREATE_PRIVATE_CHANNELS = "create-p" private const val CREATE_PRIVATE_CHANNELS = "create-p"
// Messages // Messages
const val DELETE_MESSAGE = "delete-message" private const val DELETE_MESSAGE = "delete-message"
const val FORCE_DELETE_MESSAGE = "force-delete-message" private const val FORCE_DELETE_MESSAGE = "force-delete-message"
const val EDIT_MESSAGE = "edit-message" private const val EDIT_MESSAGE = "edit-message"
const val PIN_MESSAGE = "pin-message" private const val PIN_MESSAGE = "pin-message"
const val POST_READONLY = "post-readonly" private const val POST_READONLY = "post-readonly"
private const val VIEW_STATISTICS = "view-statistics"
private const val VIEW_ROOM_ADMINISTRATION = "view-room-administration"
private const val VIEW_USER_ADMINISTRATION = "view-user-administration"
private const val VIEW_PRIVILEGED_SETTING = "view-privileged-setting"
class PermissionsInteractor @Inject constructor( class PermissionsInteractor @Inject constructor(
private val settingsRepository: SettingsRepository, private val settingsRepository: SettingsRepository,
...@@ -23,14 +26,8 @@ class PermissionsInteractor @Inject constructor( ...@@ -23,14 +26,8 @@ class PermissionsInteractor @Inject constructor(
private val getCurrentServerInteractor: GetCurrentServerInteractor, private val getCurrentServerInteractor: GetCurrentServerInteractor,
private val userHelper: UserHelper private val userHelper: UserHelper
) { ) {
private fun publicSettings(): PublicSettings? = settingsRepository.get(currentServerUrl()!!) private fun publicSettings(): PublicSettings? = settingsRepository.get(currentServerUrl()!!)
fun saveAll(permissions: List<Permission>) {
val url = currentServerUrl()!!
permissions.forEach { permissionsRepository.save(url, it) }
}
/** /**
* Check whether the user is allowed to delete a message. * Check whether the user is allowed to delete a message.
*/ */
...@@ -71,6 +68,28 @@ class PermissionsInteractor @Inject constructor( ...@@ -71,6 +68,28 @@ class PermissionsInteractor @Inject constructor(
} == true || userHelper.isAdmin() } == true || userHelper.isAdmin()
} }
fun canSeeTheAdminPanel(): Boolean {
currentServerUrl()?.let { serverUrl ->
val viewStatistics =
permissionsRepository.get(serverUrl, VIEW_STATISTICS)
val viewRoomAdministration =
permissionsRepository.get(serverUrl, VIEW_ROOM_ADMINISTRATION)
val viewUserAdministration =
permissionsRepository.get(serverUrl, VIEW_USER_ADMINISTRATION)
val viewPrivilegedSetting =
permissionsRepository.get(serverUrl, VIEW_PRIVILEGED_SETTING)
userHelper.user()?.roles?.let { userRolesList ->
return viewStatistics?.roles?.any { userRolesList.contains(it) } == true ||
viewRoomAdministration?.roles?.any { userRolesList.contains(it) } == true ||
viewUserAdministration?.roles?.any { userRolesList.contains(it) } == true ||
viewPrivilegedSetting?.roles?.any { userRolesList.contains(it) } == true
}
}
return false
}
private fun currentServerUrl(): String? { private fun currentServerUrl(): String? {
return getCurrentServerInteractor.get() return getCurrentServerInteractor.get()
} }
......
...@@ -5,20 +5,20 @@ import chat.rocket.core.model.Permission ...@@ -5,20 +5,20 @@ import chat.rocket.core.model.Permission
interface PermissionsRepository { interface PermissionsRepository {
/** /**
* Store [permission] locally. * Stores a list of [Permission] locally.
* *
* @param url The server url from where we're interest to store the permission. * @param url The server url to store the permission.
* @param permission The permission to store. * @param permissionList The permission list to store.
*/ */
fun save(url: String, permission: Permission) fun save(url: String, permissionList: List<Permission>)
/** /**
* Get permission given by the [permissionId] and for the server [url]. * Gets permission given by the [permissionId] and for the server [url].
* *
* @param url The server url from where we're interested on getting the permissions. * @param url The server url to get the permissions from.
* @param permissionId the id of the permission to get. * @param permissionId the ID of the permission to get.
* *
* @return The interested [Permission] or null if not found. * @return The [Permission] or null if not found.
*/ */
fun get(url: String, permissionId: String): Permission? fun get(url: String, permissionId: String): Permission?
} }
\ No newline at end of file
package chat.rocket.android.server.domain
import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.retryIO
import chat.rocket.core.internal.rest.permissions
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.launch
import timber.log.Timber
import javax.inject.Inject
/**
* This class reloads the current logged server permission whenever its used.
*/
class RefreshPermissionsInteractor @Inject constructor(
private val factory: RocketChatClientFactory,
private val repository: PermissionsRepository
) {
fun refreshAsync(server: String) {
launch(CommonPool) {
try {
factory.create(server).let { client ->
val permissions = retryIO(
description = "permissions",
times = 5,
maxDelay = 5000,
initialDelay = 300
) {
client.permissions()
}
repository.save(server, permissions)
}
} catch (ex: Exception) {
Timber.e(ex, "Error refreshing permissions for: $server")
}
}
}
}
\ No newline at end of file
...@@ -9,6 +9,9 @@ import kotlinx.coroutines.experimental.withContext ...@@ -9,6 +9,9 @@ import kotlinx.coroutines.experimental.withContext
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
/**
* This class reloads the current logged server settings whenever needed.
*/
class RefreshSettingsInteractor @Inject constructor( class RefreshSettingsInteractor @Inject constructor(
private val factory: RocketChatClientFactory, private val factory: RocketChatClientFactory,
private val repository: SettingsRepository private val repository: SettingsRepository
......
package chat.rocket.android.server.domain
import chat.rocket.core.model.Value
import javax.inject.Inject
class SaveSettingsInteractor @Inject constructor(private val repository: SettingsRepository) {
fun save(url: String, settings: Map<String, Value<Any>>) = repository.save(url, settings)
}
\ No newline at end of file
...@@ -193,6 +193,14 @@ class ConnectionManager( ...@@ -193,6 +193,14 @@ class ConnectionManager(
client.setTemporaryStatus(userStatus) client.setTemporaryStatus(userStatus)
} }
fun resetReconnectionTimer() {
// if we are waiting to reconnect, immediately try to reconnect
// and reset the reconnection counter
if (client.state is State.Waiting) {
client.connect(resetCounter = true)
}
}
private fun resubscribeRooms() { private fun resubscribeRooms() {
roomMessagesChannels.toList().map { (roomId, channel) -> roomMessagesChannels.toList().map { (roomId, channel) ->
client.subscribeRoomMessages(roomId) { _, id -> client.subscribeRoomMessages(roomId) { _, id ->
......
...@@ -9,11 +9,12 @@ class SharedPreferencesPermissionsRepository( ...@@ -9,11 +9,12 @@ class SharedPreferencesPermissionsRepository(
private val localRepository: LocalRepository, private val localRepository: LocalRepository,
moshi: Moshi moshi: Moshi
) : PermissionsRepository { ) : PermissionsRepository {
private val adapter = moshi.adapter(Permission::class.java) private val adapter = moshi.adapter(Permission::class.java)
override fun save(url: String, permission: Permission) { override fun save(url: String, permissionList: List<Permission>) {
localRepository.save(getPermissionKey(url, permission.id), adapter.toJson(permission)) for (permission in permissionList) {
localRepository.save(getPermissionKey(url, permission.id), adapter.toJson(permission))
}
} }
override fun get(url: String, permissionId: String): Permission? { override fun get(url: String, permissionId: String): Permission? {
......
...@@ -51,6 +51,8 @@ fun String.termsOfServiceUrl() = "${removeTrailingSlash()}/terms-of-service" ...@@ -51,6 +51,8 @@ fun String.termsOfServiceUrl() = "${removeTrailingSlash()}/terms-of-service"
fun String.privacyPolicyUrl() = "${removeTrailingSlash()}/privacy-policy" fun String.privacyPolicyUrl() = "${removeTrailingSlash()}/privacy-policy"
fun String.adminPanelUrl() = "${removeTrailingSlash()}/admin/info?layout=embedded"
fun String.isValidUrl(): Boolean = Patterns.WEB_URL.matcher(this).matches() fun String.isValidUrl(): Boolean = Patterns.WEB_URL.matcher(this).matches()
fun String.parseColor(): Int { fun String.parseColor(): Int {
......
package chat.rocket.android.webview.adminpanel.ui
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.util.extensions.inflate
import kotlinx.android.synthetic.main.fragment_admin_panel_web_view.*
private const val BUNDLE_WEB_PAGE_URL = "web_page_url"
private const val BUNDLE_USER_TOKEN = "user_token"
class AdminPanelWebViewFragment : Fragment() {
private lateinit var webPageUrl: String
private lateinit var userToken: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val bundle = arguments
if (bundle != null) {
webPageUrl = bundle.getString(BUNDLE_WEB_PAGE_URL)
userToken = bundle.getString(BUNDLE_USER_TOKEN)
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = container?.inflate(R.layout.fragment_admin_panel_web_view)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupToolbar()
setupWebView()
}
private fun setupToolbar() {
(activity as AppCompatActivity?)?.supportActionBar?.title =
getString(R.string.title_admin_panel)
}
@SuppressLint("SetJavaScriptEnabled")
private fun setupWebView() {
with(web_view.settings) {
javaScriptEnabled = true
domStorageEnabled = true
}
web_view.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
view_loading.hide()
web_view.evaluateJavascript("Meteor.loginWithToken('$userToken', function() { })") {}
}
}
web_view.loadUrl(webPageUrl)
}
companion object {
fun newInstance(webPageUrl: String, userToken: String) = AdminPanelWebViewFragment().apply {
arguments = Bundle(2).apply {
putString(BUNDLE_WEB_PAGE_URL, webPageUrl)
putString(BUNDLE_USER_TOKEN, userToken)
}
}
}
}
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:viewportWidth="24.0"> android:viewportHeight="24.0">
<path <path
android:fillColor="#FF000000" android:fillColor="#FF000000"
android:pathData="M10.09,15.59L11.5,17l5,-5 -5,-5 -1.41,1.41L12.67,11H3v2h9.67l-2.58,2.59zM19,3H5c-1.11,0 -2,0.9 -2,2v4h2V5h14v14H5v-4H3v4c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z" /> android:pathData="M10.09,15.59L11.5,17l5,-5 -5,-5 -1.41,1.41L12.67,11H3v2h9.67l-2.58,2.59zM19,3H5c-1.11,0 -2,0.9 -2,2v4h2V5h14v14H5v-4H3v4c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z" />
</vector> </vector>
\ No newline at end of file
...@@ -33,8 +33,7 @@ ...@@ -33,8 +33,7 @@
android:id="@+id/view_navigation" android:id="@+id/view_navigation"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
app:headerLayout="@layout/nav_header" app:headerLayout="@layout/nav_header" />
app:menu="@menu/navigation" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/accounts_list" android:id="@+id/accounts_list"
......
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image_app_name" app:layout_constraintTop_toBottomOf="@+id/image_app_name"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:textColor="@color/colorSecondaryText" /> android:textColor="@color/colorSecondaryText"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"/>
<TextView <TextView
android:id="@+id/text_build_number" android:id="@+id/text_build_number"
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".webview.adminpanel.ui.AdminPanelWebViewFragment">
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.wang.avi.AVLoadingIndicatorView
android:id="@+id/view_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:indicatorColor="@color/colorBlack"
app:indicatorName="BallPulseIndicator"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
android:src="@drawable/ic_vpn_key_black_24dp" android:src="@drawable/ic_vpn_key_black_24dp"
android:tint="@color/colorDrawableTintGrey" android:tint="@color/colorDrawableTintGrey"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/text_username_or_email" app:layout_constraintBottom_toBottomOf="@+id/text_username_or_email"
app:layout_constraintEnd_toEndOf="@+id/text_username_or_email" app:layout_constraintEnd_toEndOf="@+id/text_username_or_email"
app:layout_constraintTop_toTopOf="@+id/text_username_or_email" /> app:layout_constraintTop_toTopOf="@+id/text_username_or_email" />
......
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:id="@+id/menu_section_1"
android:checkableBehavior="single">
<item
android:id="@+id/action_chat_rooms"
android:checked="true"
android:icon="@drawable/ic_chat_bubble_black_24dp"
android:title="@string/title_chats" />
<item
android:id="@+id/action_channel"
android:icon="@drawable/ic_create_black_24dp"
android:title="@string/action_create_channel" />
</group>
<group
android:id="@+id/menu_section_2"
android:checkableBehavior="single">
<item
android:id="@+id/action_profile"
android:icon="@drawable/ic_person_black_24dp"
android:title="@string/title_profile" />
<item
android:id="@+id/action_settings"
android:icon="@drawable/ic_settings_black_24dp"
android:title="@string/title_settings" />
</group>
<group
android:id="@+id/menu_section_3"
android:checkableBehavior="single">
<item
android:id="@+id/action_logout"
android:icon="@drawable/ic_exit_to_app_black_24dp"
android:title="@string/action_logout" />
</group>
</menu>
\ No newline at end of file
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
<string name="title_settings">Einstellungen</string> <string name="title_settings">Einstellungen</string>
<string name="title_preferences">Preferences</string> <!-- TODO Add translation --> <string name="title_preferences">Preferences</string> <!-- TODO Add translation -->
<string name="title_change_password">Ändere Passwort</string> <string name="title_change_password">Ändere Passwort</string>
<string name="title_admin_panel">Admin panel</string> <!-- TODO Add translation -->
<string name="title_password">Ändere Passwort</string>
<string name="title_update_profile">Update Profil</string> <string name="title_update_profile">Update Profil</string>
<string name="title_about">Über</string> <string name="title_about">Über</string>
<string name="title_create_channel">Erstelle Raum</string> <string name="title_create_channel">Erstelle Raum</string>
...@@ -83,7 +85,7 @@ ...@@ -83,7 +85,7 @@
<string name="msg_content_description_log_in_using_meteor">Login mit Meteor</string> <string name="msg_content_description_log_in_using_meteor">Login mit Meteor</string>
<string name="msg_content_description_log_in_using_twitter">Login mit Twitter</string> <string name="msg_content_description_log_in_using_twitter">Login mit Twitter</string>
<string name="msg_content_description_log_in_using_gitlab">Login mit Gitlab</string> <string name="msg_content_description_log_in_using_gitlab">Login mit Gitlab</string>
<string name="msg_content_description_log_in_using_wordprees">Login using WordPress</string> <!-- TODO Translate--> <string name="msg_content_description_log_in_using_wordpress">Login mit WordPress</string>
<string name="msg_content_description_send_message">Sende Nachricht</string> <string name="msg_content_description_send_message">Sende Nachricht</string>
<string name="msg_content_description_show_attachment_options">Zeige Anhang Optionen</string> <string name="msg_content_description_show_attachment_options">Zeige Anhang Optionen</string>
<string name="msg_you">Du</string> <string name="msg_you">Du</string>
...@@ -100,8 +102,6 @@ ...@@ -100,8 +102,6 @@
<string name="msg_preview_photo">Bild</string> <string name="msg_preview_photo">Bild</string>
<string name="msg_preview_file">Datei</string> <string name="msg_preview_file">Datei</string>
<string name="msg_no_messages_yet">Noch keine Nachrichten</string> <string name="msg_no_messages_yet">Noch keine Nachrichten</string>
<string name="msg_version">Version %1$s</string>
<string name="msg_build">Build %1$d</string>
<string name="msg_ok">OK</string> <string name="msg_ok">OK</string>
<string name="msg_update_app_version_in_order_to_continue">Server Version veraltet. Bitte kontaktieren Sie ihren Server Administrator.</string> <string name="msg_update_app_version_in_order_to_continue">Server Version veraltet. Bitte kontaktieren Sie ihren Server Administrator.</string>
<string name="msg_ver_not_recommended"> <string name="msg_ver_not_recommended">
...@@ -267,6 +267,7 @@ ...@@ -267,6 +267,7 @@
<string name="dialog_sort_by_activity">Aktivität</string> <string name="dialog_sort_by_activity">Aktivität</string>
<string name="dialog_group_by_type">Räume nach Typ</string> <string name="dialog_group_by_type">Räume nach Typ</string>
<string name="dialog_group_favourites">Räume nach Favoriten</string> <string name="dialog_group_favourites">Räume nach Favoriten</string>
<string name="dialog_button_done">Done</string><!-- TODO Add translation -->
<string name="chatroom_header">Kopf</string> <string name="chatroom_header">Kopf</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
<string name="title_settings">Configuraciones</string> <string name="title_settings">Configuraciones</string>
<string name="title_preferences">Preferences</string> <!-- TODO Add translation --> <string name="title_preferences">Preferences</string> <!-- TODO Add translation -->
<string name="title_change_password">Cambia la contraseña</string> <string name="title_change_password">Cambia la contraseña</string>
<string name="title_admin_panel">Admin panel</string> <!-- TODO Add translation -->
<string name="title_password">Cambia la contraseña</string>
<string name="title_update_profile">Actualización del perfil</string> <string name="title_update_profile">Actualización del perfil</string>
<string name="title_about">Acerca de</string> <string name="title_about">Acerca de</string>
<string name="title_create_channel">Crear canal</string> <string name="title_create_channel">Crear canal</string>
...@@ -82,7 +84,7 @@ ...@@ -82,7 +84,7 @@
<string name="msg_content_description_log_in_using_meteor">Inicia sesión usando Meteor</string> <string name="msg_content_description_log_in_using_meteor">Inicia sesión usando Meteor</string>
<string name="msg_content_description_log_in_using_twitter">Inicia sesión usando Twitter</string> <string name="msg_content_description_log_in_using_twitter">Inicia sesión usando Twitter</string>
<string name="msg_content_description_log_in_using_gitlab">Inicia sesión usando Gitlab</string> <string name="msg_content_description_log_in_using_gitlab">Inicia sesión usando Gitlab</string>
<string name="msg_content_description_log_in_using_wordprees">Login using WordPress</string> <!-- TODO Translate--> <string name="msg_content_description_log_in_using_wordpress">Login using WordPress</string> <!-- TODO Translate-->
<string name="msg_content_description_send_message">Enviar mensaje</string> <string name="msg_content_description_send_message">Enviar mensaje</string>
<string name="msg_content_description_show_attachment_options">Mostrar opciones de archivo adjunto</string> <string name="msg_content_description_show_attachment_options">Mostrar opciones de archivo adjunto</string>
<string name="msg_you"></string> <string name="msg_you"></string>
...@@ -97,8 +99,6 @@ ...@@ -97,8 +99,6 @@
<string name="msg_preview_photo">Foto</string> <string name="msg_preview_photo">Foto</string>
<string name="msg_preview_file">Fichero</string> <string name="msg_preview_file">Fichero</string>
<string name="msg_no_messages_yet">Aún no hay mensajes</string> <string name="msg_no_messages_yet">Aún no hay mensajes</string>
<string name="msg_version">Versión %1$s</string>
<string name="msg_build">Build %1$d</string>
<string name="msg_ok">OK</string> <string name="msg_ok">OK</string>
<string name="msg_update_app_version_in_order_to_continue">Versión del servidor actualizada. Póngase en contacto con el administrador del servidor para actualizar la versión del servidor y continuar.</string> <string name="msg_update_app_version_in_order_to_continue">Versión del servidor actualizada. Póngase en contacto con el administrador del servidor para actualizar la versión del servidor y continuar.</string>
<string name="msg_ver_not_recommended"> <string name="msg_ver_not_recommended">
...@@ -262,6 +262,7 @@ ...@@ -262,6 +262,7 @@
<string name="dialog_sort_by_activity">Actividad</string> <string name="dialog_sort_by_activity">Actividad</string>
<string name="dialog_group_by_type">Agrupar por tipo</string> <string name="dialog_group_by_type">Agrupar por tipo</string>
<string name="dialog_group_favourites">Agrupar favoritos</string> <string name="dialog_group_favourites">Agrupar favoritos</string>
<string name="dialog_button_done">Done</string><!-- TODO Add translation -->
<string name="chatroom_header">Cabezazo</string> <string name="chatroom_header">Cabezazo</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
<string name="title_settings">Paramètres</string> <string name="title_settings">Paramètres</string>
<string name="title_preferences">Preferences</string> <!-- TODO Add translation --> <string name="title_preferences">Preferences</string> <!-- TODO Add translation -->
<string name="title_change_password">Changer le mot de passe</string> <string name="title_change_password">Changer le mot de passe</string>
<string name="title_admin_panel">Admin panel</string> <!-- TODO Add translation -->
<string name="title_password">Changer le mot de passe</string>
<string name="title_update_profile">Update profile</string> <string name="title_update_profile">Update profile</string>
<string name="title_about">Sur</string> <string name="title_about">Sur</string>
// TODO: Add proper translation. // TODO: Add proper translation.
...@@ -88,7 +90,7 @@ ...@@ -88,7 +90,7 @@
<string name="msg_content_description_log_in_using_meteor">Connectez-vous en utilisant Meteor</string> <string name="msg_content_description_log_in_using_meteor">Connectez-vous en utilisant Meteor</string>
<string name="msg_content_description_log_in_using_twitter">Connectez-vous en utilisant Twitter</string> <string name="msg_content_description_log_in_using_twitter">Connectez-vous en utilisant Twitter</string>
<string name="msg_content_description_log_in_using_gitlab">Connectez-vous en utilisant Gitlab</string> <string name="msg_content_description_log_in_using_gitlab">Connectez-vous en utilisant Gitlab</string>
<string name="msg_content_description_log_in_using_wordprees">Login using WordPress</string> <!-- TODO Translate--> <string name="msg_content_description_log_in_using_wordpress">Login using WordPress</string> <!-- TODO Translate-->
<string name="msg_content_description_send_message">Envoyer message</string> <string name="msg_content_description_send_message">Envoyer message</string>
<string name="msg_content_description_show_attachment_options">Afficher les options de fichiers</string> <string name="msg_content_description_show_attachment_options">Afficher les options de fichiers</string>
<string name="msg_you">Toi</string> <string name="msg_you">Toi</string>
...@@ -103,8 +105,6 @@ ...@@ -103,8 +105,6 @@
<string name="msg_preview_photo">Photo</string> <string name="msg_preview_photo">Photo</string>
<string name="msg_preview_file">File</string> <string name="msg_preview_file">File</string>
<string name="msg_no_messages_yet">Aucun message pour le moment</string> <string name="msg_no_messages_yet">Aucun message pour le moment</string>
<string name="msg_version">Version %1$s</string>
<string name="msg_build">Build %1$d</string>
<string name="msg_ok">OK</string> <string name="msg_ok">OK</string>
// TODO: Add proper translation. // TODO: Add proper translation.
<string name="msg_update_app_version_in_order_to_continue">Out to date server version. Please contact the server admin to update the server version in order to continue.</string> <string name="msg_update_app_version_in_order_to_continue">Out to date server version. Please contact the server admin to update the server version in order to continue.</string>
...@@ -287,6 +287,7 @@ ...@@ -287,6 +287,7 @@
<string name="dialog_sort_by_activity">Activité</string> <string name="dialog_sort_by_activity">Activité</string>
<string name="dialog_group_by_type">Grouper par type</string> <string name="dialog_group_by_type">Grouper par type</string>
<string name="dialog_group_favourites">Grouper favoris</string> <string name="dialog_group_favourites">Grouper favoris</string>
<string name="dialog_button_done">Done</string><!-- TODO Add translation -->
<string name="chatroom_header">Entête</string> <string name="chatroom_header">Entête</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
<string name="title_settings">सेटिंग्स</string> <string name="title_settings">सेटिंग्स</string>
<string name="title_preferences">Preferences</string> <!-- TODO Add translation --> <string name="title_preferences">Preferences</string> <!-- TODO Add translation -->
<string name="title_change_password">पासवर्ड बदलें</string> <string name="title_change_password">पासवर्ड बदलें</string>
<string name="title_admin_panel">Admin panel</string> <!-- TODO Add translation -->
<string name="title_password">पासवर्ड बदलें</string>
<string name="title_update_profile">प्रोफ़ाइल अपडेट करें</string> <string name="title_update_profile">प्रोफ़ाइल अपडेट करें</string>
<string name="title_about">परिचय</string> <string name="title_about">परिचय</string>
<string name="title_create_channel">चैनल बनाएं</string> <string name="title_create_channel">चैनल बनाएं</string>
...@@ -83,7 +85,7 @@ ...@@ -83,7 +85,7 @@
<string name="msg_content_description_log_in_using_meteor">Meteor द्वारा लॉगिन करें</string> <string name="msg_content_description_log_in_using_meteor">Meteor द्वारा लॉगिन करें</string>
<string name="msg_content_description_log_in_using_twitter">Twitter द्वारा लॉगिन करें</string> <string name="msg_content_description_log_in_using_twitter">Twitter द्वारा लॉगिन करें</string>
<string name="msg_content_description_log_in_using_gitlab">Gitlab द्वारा लॉगिन करें</string> <string name="msg_content_description_log_in_using_gitlab">Gitlab द्वारा लॉगिन करें</string>
<string name="msg_content_description_log_in_using_wordprees">Login using WordPress</string> <!-- TODO Translate--> <string name="msg_content_description_log_in_using_wordpress">Login using WordPress</string> <!-- TODO Translate-->
<string name="msg_content_description_send_message">मेसेज भेजें</string> <string name="msg_content_description_send_message">मेसेज भेजें</string>
<string name="msg_content_description_show_attachment_options">अटैचमेंट विकल्प दिखाएं</string> <string name="msg_content_description_show_attachment_options">अटैचमेंट विकल्प दिखाएं</string>
<string name="msg_you">आप</string> <string name="msg_you">आप</string>
...@@ -98,8 +100,6 @@ ...@@ -98,8 +100,6 @@
<string name="msg_preview_file">फ़ाइल</string> <string name="msg_preview_file">फ़ाइल</string>
<string name="msg_unread_messages">अपठित संदेश</string> <string name="msg_unread_messages">अपठित संदेश</string>
<string name="msg_no_messages_yet">अभी तक कोई पोस्ट नहीं</string> <string name="msg_no_messages_yet">अभी तक कोई पोस्ट नहीं</string>
<string name="msg_version">वर्शन %1$s</string>
<string name="msg_build">बिल्ड %1$d</string>
<string name="msg_update_app_version_in_order_to_continue">पुराना सर्वर वर्शन। जारी रखने के लिए सर्वर वर्शन को अद्यतन करने के लिए कृपया सर्वर व्यवस्थापक से संपर्क करें।</string> <string name="msg_update_app_version_in_order_to_continue">पुराना सर्वर वर्शन। जारी रखने के लिए सर्वर वर्शन को अद्यतन करने के लिए कृपया सर्वर व्यवस्थापक से संपर्क करें।</string>
<string name="msg_ok">ठीक है</string> <string name="msg_ok">ठीक है</string>
<string name="msg_ver_not_recommended"> <string name="msg_ver_not_recommended">
...@@ -269,6 +269,7 @@ ...@@ -269,6 +269,7 @@
<string name="dialog_sort_by_activity">गतिविधि</string> <string name="dialog_sort_by_activity">गतिविधि</string>
<string name="dialog_group_by_type">प्रकार के आधार पर समूह</string> <string name="dialog_group_by_type">प्रकार के आधार पर समूह</string>
<string name="dialog_group_favourites">पसंदीदा समूह</string> <string name="dialog_group_favourites">पसंदीदा समूह</string>
<string name="dialog_button_done">Done</string><!-- TODO Add translation -->
<string name="chatroom_header">हैडर</string> <string name="chatroom_header">हैडर</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
<string name="title_settings">Configurações</string> <string name="title_settings">Configurações</string>
<string name="title_preferences">Preferencias</string> <string name="title_preferences">Preferencias</string>
<string name="title_change_password">Alterar senha</string> <string name="title_change_password">Alterar senha</string>
<string name="title_admin_panel">Painel administrativo</string>
<string name="title_password">Alterar senha</string>
<string name="title_update_profile">Editar perfil</string> <string name="title_update_profile">Editar perfil</string>
<string name="title_about">Sobre</string> <string name="title_about">Sobre</string>
<string name="title_create_channel">Criar chat</string> <string name="title_create_channel">Criar chat</string>
...@@ -83,7 +85,7 @@ ...@@ -83,7 +85,7 @@
<string name="msg_content_description_log_in_using_meteor">Fazer login através do Meteor</string> <string name="msg_content_description_log_in_using_meteor">Fazer login através do Meteor</string>
<string name="msg_content_description_log_in_using_twitter">Fazer login através do Twitter</string> <string name="msg_content_description_log_in_using_twitter">Fazer login através do Twitter</string>
<string name="msg_content_description_log_in_using_gitlab">Fazer login através do Gitlab</string> <string name="msg_content_description_log_in_using_gitlab">Fazer login através do Gitlab</string>
<string name="msg_content_description_log_in_using_wordprees">Fazer login através do WordPress</string> <string name="msg_content_description_log_in_using_wordpress">Fazer login através do WordPress</string>
<string name="msg_content_description_send_message">Enviar mensagem</string> <string name="msg_content_description_send_message">Enviar mensagem</string>
<string name="msg_content_description_show_attachment_options">Mostrar opções de anexo</string> <string name="msg_content_description_show_attachment_options">Mostrar opções de anexo</string>
<string name="msg_you">Você</string> <string name="msg_you">Você</string>
...@@ -98,8 +100,6 @@ ...@@ -98,8 +100,6 @@
<string name="msg_preview_photo">Foto</string> <string name="msg_preview_photo">Foto</string>
<string name="msg_preview_file">Arquivo</string> <string name="msg_preview_file">Arquivo</string>
<string name="msg_no_messages_yet">Nenhuma mensagem ainda</string> <string name="msg_no_messages_yet">Nenhuma mensagem ainda</string>
<string name="msg_version">Versão %1$s</string>
<string name="msg_build">Build %1$d</string>
<string name="msg_ok">OK</string> <string name="msg_ok">OK</string>
<string name="msg_update_app_version_in_order_to_continue">Versão do servidor desatualizada. Por favor, entre em contato com o administrador do sistema para continuar.</string> <string name="msg_update_app_version_in_order_to_continue">Versão do servidor desatualizada. Por favor, entre em contato com o administrador do sistema para continuar.</string>
<string name="msg_ver_not_recommended"> <string name="msg_ver_not_recommended">
...@@ -268,6 +268,7 @@ ...@@ -268,6 +268,7 @@
<string name="dialog_sort_by_activity">Atividade</string> <string name="dialog_sort_by_activity">Atividade</string>
<string name="dialog_group_by_type">Agrupar por tipo</string> <string name="dialog_group_by_type">Agrupar por tipo</string>
<string name="dialog_group_favourites">Grupos favoritos</string> <string name="dialog_group_favourites">Grupos favoritos</string>
<string name="dialog_button_done">Done</string><!-- TODO Add translation -->
<string name="chatroom_header">Cabeçalho</string> <string name="chatroom_header">Cabeçalho</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
......
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="menu_section_one" type="id"/>
<item name="menu_section_two" type="id"/>
<item name="menu_section_three" type="id"/>
<item name="menu_action_chats" type="id"/>
<item name="menu_action_create_channel" type="id"/>
<item name="menu_action_profile" type="id"/>
<item name="menu_action_settings" type="id"/>
<item name="menu_action_admin_panel" type="id"/>
<item name="menu_action_logout" type="id"/>
</resources>
\ No newline at end of file
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name" translatable="false">Rocket.Chat</string> <string name="app_name" translatable="false">Rocket.Chat</string>
<!-- Titles --> <!-- Titles -->
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
<string name="title_settings">Settings</string> <string name="title_settings">Settings</string>
<string name="title_preferences">Preferences</string> <string name="title_preferences">Preferences</string>
<string name="title_change_password">Change Password</string> <string name="title_change_password">Change Password</string>
<string name="title_admin_panel">Admin panel</string>
<string name="title_password">Change Password</string>
<string name="title_update_profile">Update profile</string> <string name="title_update_profile">Update profile</string>
<string name="title_about">About</string> <string name="title_about">About</string>
<string name="title_create_channel">Create Channel</string> <string name="title_create_channel">Create Channel</string>
...@@ -85,7 +87,7 @@ ...@@ -85,7 +87,7 @@
<string name="msg_content_description_log_in_using_meteor">Login using Meteor</string> <string name="msg_content_description_log_in_using_meteor">Login using Meteor</string>
<string name="msg_content_description_log_in_using_twitter">Login using Twitter</string> <string name="msg_content_description_log_in_using_twitter">Login using Twitter</string>
<string name="msg_content_description_log_in_using_gitlab">Login using Gitlab</string> <string name="msg_content_description_log_in_using_gitlab">Login using Gitlab</string>
<string name="msg_content_description_log_in_using_wordprees">Login using WordPress</string> <string name="msg_content_description_log_in_using_wordpress">Login using WordPress</string>
<string name="msg_content_description_send_message">Send message</string> <string name="msg_content_description_send_message">Send message</string>
<string name="msg_content_description_show_attachment_options">Show attachment options</string> <string name="msg_content_description_show_attachment_options">Show attachment options</string>
<string name="msg_you">You</string> <string name="msg_you">You</string>
...@@ -102,8 +104,7 @@ ...@@ -102,8 +104,7 @@
<string name="msg_preview_photo">Photo</string> <string name="msg_preview_photo">Photo</string>
<string name="msg_preview_file">File</string> <string name="msg_preview_file">File</string>
<string name="msg_no_messages_yet">No messages yet</string> <string name="msg_no_messages_yet">No messages yet</string>
<string name="msg_version">Version %1$s</string> <string name="msg_build" tools:ignore="MissingTranslation">Build %1$d - %2$s - %3$s</string>
<string name="msg_build">Build %1$d</string>
<string name="msg_ok">OK</string> <string name="msg_ok">OK</string>
<string name="msg_update_app_version_in_order_to_continue">Out to date server version. Please contact the server admin to update the server version in order to continue.</string> <string name="msg_update_app_version_in_order_to_continue">Out to date server version. Please contact the server admin to update the server version in order to continue.</string>
<string name="msg_ver_not_recommended"> <string name="msg_ver_not_recommended">
...@@ -269,6 +270,7 @@ ...@@ -269,6 +270,7 @@
<string name="dialog_sort_by_activity">Activity</string> <string name="dialog_sort_by_activity">Activity</string>
<string name="dialog_group_by_type">Group by type</string> <string name="dialog_group_by_type">Group by type</string>
<string name="dialog_group_favourites">Group favourites</string> <string name="dialog_group_favourites">Group favourites</string>
<string name="dialog_button_done">Done</string>
<string name="chatroom_header">Header</string> <string name="chatroom_header">Header</string>
<!--ChatRooms Headers--> <!--ChatRooms Headers-->
...@@ -285,4 +287,6 @@ ...@@ -285,4 +287,6 @@
<string name="notif_success_sending">Message sent to %1$s!</string> <string name="notif_success_sending">Message sent to %1$s!</string>
<string name="read_by">Read by</string> <string name="read_by">Read by</string>
<string name="message_information_title">Message information</string> <string name="message_information_title">Message information</string>
<string name="foss" tools:ignore="MissingTranslation">(FOSS)</string>
</resources> </resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="chat.rocket.android">
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission
android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
<application
android:name=".app.RocketChatApplication"
android:allowBackup="true"
android:fullBackupContent="@xml/backup_config"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true">
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
<service
android:name=".push.FirebaseTokenService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service
android:name=".push.FirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
package chat.rocket.android.helper
import android.app.Activity
import android.content.Intent
import androidx.fragment.app.FragmentActivity
import com.google.android.gms.auth.api.credentials.Credential
import com.google.android.gms.auth.api.credentials.Credentials
fun FragmentActivity.saveCredentials(id: String, password: String) {
val credentialsClient = Credentials.getClient(this)
SmartLockHelper.save(credentialsClient, this, id, password)
}
fun Activity.requestStoredCredentials(): Pair<String, String>? {
val credentialsClient = Credentials.getClient(this)
return SmartLockHelper.requestStoredCredentials(credentialsClient, this)?.let {
null
}
}
fun getCredentials(data: Intent): Pair<String, String>? {
val credentials: Credential = data.getParcelableExtra(Credential.EXTRA_KEY)
return credentials?.let { cred ->
cred.password?.let {
Pair(cred.id, it)
}
}
}
fun hasCredentialsSupport() = true
\ No newline at end of file
package chat.rocket.android.util
import chat.rocket.android.BuildConfig
import io.fabric.sdk.android.Fabric
import com.crashlytics.android.Crashlytics
import com.crashlytics.android.core.CrashlyticsCore
import android.content.Context
import chat.rocket.android.app.RocketChatApplication
import chat.rocket.android.infrastructure.installCrashlyticsWrapper
import com.crashlytics.android.answers.Answers
fun setupFabric(context: Context) {
val core = CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()
Fabric.with(
context,
Crashlytics.Builder()
.core(core) // For Crashlytics
.answers(Answers()) // For Answers
.build()
)
installCrashlyticsWrapper(
context as RocketChatApplication,
context.getCurrentServerInteractor,
context.settingsInteractor,
context.accountRepository,
context.localRepository
)
}
\ No newline at end of file
package chat.rocket.android.util
import chat.rocket.android.main.presentation.MainPresenter
import com.google.firebase.iid.FirebaseInstanceId
import com.google.firebase.messaging.FirebaseMessaging
import timber.log.Timber
suspend fun refreshFCMToken(presenter: MainPresenter) {
try {
val token = FirebaseInstanceId.getInstance().token
Timber.d("FCM token: $token")
presenter.refreshToken(token)
} catch (ex: Exception) {
Timber.d(ex, "Missing play services...")
}
}
fun invalidateFirebaseToken(token: String) {
FirebaseInstanceId.getInstance().deleteToken(token, FirebaseMessaging.INSTANCE_ID_SCOPE)
}
...@@ -10,7 +10,7 @@ buildscript { ...@@ -10,7 +10,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.3.0-alpha04' classpath 'com.android.tools.build:gradle:3.3.0-alpha05'
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.0.2' classpath 'com.google.gms:google-services:4.0.2'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment